Module Name: src
Committed By: yamaguchi
Date: Wed Nov 25 09:16:20 UTC 2020
Modified Files:
src/sys/net: if_spppsubr.c
Log Message:
Refactoring functions for RCR and RCN
To generate a diff of this commit:
cvs rdiff -u -r1.192 -r1.193 src/sys/net/if_spppsubr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if_spppsubr.c
diff -u src/sys/net/if_spppsubr.c:1.192 src/sys/net/if_spppsubr.c:1.193
--- src/sys/net/if_spppsubr.c:1.192 Wed Nov 25 09:12:50 2020
+++ src/sys/net/if_spppsubr.c Wed Nov 25 09:16:20 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_spppsubr.c,v 1.192 2020/11/25 09:12:50 yamaguchi Exp $ */
+/* $NetBSD: if_spppsubr.c,v 1.193 2020/11/25 09:16:20 yamaguchi Exp $ */
/*
* Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.192 2020/11/25 09:12:50 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.193 2020/11/25 09:16:20 yamaguchi Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -2294,21 +2294,30 @@ sppp_lcp_TO(void *cookie)
* transition decision in the state automaton.)
*/
static int
-sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
+sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int origlen)
{
STDDCL;
- u_char *buf, *r, *p, l, blen;
- int origlen, rlen;
+ u_char *buf, *r, *p, l, blen, type;
+ int len, rlen;
uint32_t nmagic;
u_short authproto;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- origlen = len;
- buf = r = malloc (blen = len, M_TEMP, M_NOWAIT);
- if (! buf)
- return (0);
+ if (origlen < sizeof(*h))
+ return 0;
+
+ origlen -= sizeof(*h);
+ type = 0;
+
+ if (origlen <= 0)
+ return 0;
+ else
+ blen = origlen;
+
+ buf = kmem_intr_alloc(blen, KM_NOSLEEP);
+ if (buf == NULL)
+ return 0;
if (debug)
log(LOG_DEBUG, "%s: lcp parse opts:",
@@ -2316,7 +2325,13 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
/* pass 1: check for things that need to be rejected */
p = (void *)(h + 1);
- for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ r = buf;
+ rlen = 0;
+ for (len = origlen; len > 1; len-= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
/* Sanity check option length */
if (l > len) {
/*
@@ -2326,11 +2341,12 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
addlog("%s: received malicious LCP option 0x%02x, "
"length 0x%02x, (len: 0x%02x) dropping.\n", ifp->if_xname,
p[0], l, len);
- goto drop;
+ rlen = -1;
+ goto end;
}
if (debug)
addlog(" %s", sppp_lcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case LCP_OPT_MAGIC:
/* Magic number. */
/* fall through, both are same length */
@@ -2418,12 +2434,13 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
r += l;
rlen += l;
}
- if (rlen) {
- if (debug)
- addlog(" send conf-rej\n");
- sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
+
+ if (rlen > 0) {
+ type = CONF_REJ;
goto end;
- } else if (debug)
+ }
+
+ if (debug)
addlog("\n");
/*
@@ -2435,11 +2452,16 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
ifp->if_xname);
p = (void *)(h + 1);
- len = origlen;
- for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ r = buf;
+ rlen = 0;
+ for (len = origlen; len > 0; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
if (debug)
addlog(" %s", sppp_lcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case LCP_OPT_MAGIC:
/* Magic number -- extract. */
nmagic = (uint32_t)p[2] << 24 |
@@ -2560,34 +2582,41 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
r += l;
rlen += l;
}
- if (rlen) {
+
+ if (rlen > 0) {
if (++sp->scp[IDX_LCP].fail_counter >= sp->lcp.max_failure) {
if (debug)
- addlog(" max_failure (%d) exceeded, "
- "send conf-rej\n",
- sp->lcp.max_failure);
- sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
+ addlog(" max_failure (%d) exceeded, ",
+ sp->lcp.max_failure);
+ type = CONF_REJ;
} else {
- if (debug)
- addlog(" send conf-nak\n");
- sppp_cp_send(sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf);
+ type = CONF_NAK;
}
- goto end;
} else {
- if (debug)
- addlog(" send conf-ack\n");
+ type = CONF_ACK;
+ rlen = origlen;
+ memcpy(r, h + 1, rlen);
sp->scp[IDX_LCP].fail_counter = 0;
sp->pp_loopcnt = 0;
- sppp_cp_send(sp, PPP_LCP, CONF_ACK, h->ident, origlen, h + 1);
}
- end:
- free(buf, M_TEMP);
- return (rlen == 0);
+end:
+ if (rlen > 0) {
+ if (debug)
+ addlog("send %s", sppp_cp_type_name(type));
+ sppp_cp_send(sp, PPP_LCP, type, h->ident, rlen, buf);
+ }
+
+ if (debug)
+ addlog("\n");
+
+ kmem_free(buf, blen);
- drop:
- free(buf, M_TEMP);
- return -1;
+ if (rlen > 0)
+ return -1;
+ if (type != CONF_ACK)
+ return 0;
+ return 1;
}
/*
@@ -2598,15 +2627,15 @@ static void
sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
{
STDDCL;
- u_char *buf, *p, l;
+ u_char *p, l;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- buf = malloc (len, M_TEMP, M_NOWAIT);
- if (!buf)
+ if (len <= sizeof(*h))
return;
+ len -= sizeof(*h);
+
if (debug)
log(LOG_DEBUG, "%s: lcp rej opts:",
ifp->if_xname);
@@ -2621,11 +2650,11 @@ sppp_lcp_RCN_rej(struct sppp *sp, struct
*/
addlog("%s: received malicious LCP option, "
"dropping.\n", ifp->if_xname);
- goto drop;
+ goto end;
}
if (debug)
addlog(" %s", sppp_lcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case LCP_OPT_MAGIC:
/* Magic number -- can't use it, use 0 */
sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC);
@@ -2668,8 +2697,7 @@ sppp_lcp_RCN_rej(struct sppp *sp, struct
}
if (debug)
addlog("\n");
-drop:
- free(buf, M_TEMP);
+end:
return;
}
@@ -2681,15 +2709,14 @@ static void
sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
{
STDDCL;
- u_char *buf, *p, l, blen;
+ u_char *p, l;
uint32_t magic;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- buf = malloc (blen = len, M_TEMP, M_NOWAIT);
- if (!buf)
+ if (len <= sizeof(*h))
return;
+ len -= sizeof(*h);
if (debug)
log(LOG_DEBUG, "%s: lcp nak opts:",
@@ -2705,11 +2732,11 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
*/
addlog("%s: received malicious LCP option, "
"dropping.\n", ifp->if_xname);
- goto drop;
+ goto end;
}
if (debug)
addlog(" %s", sppp_lcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case LCP_OPT_MAGIC:
/* Magic number -- renegotiate */
if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
@@ -2761,8 +2788,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
}
if (debug)
addlog("\n");
-drop:
- free(buf, M_TEMP);
+end:
return;
}
@@ -3092,42 +3118,54 @@ sppp_ipcp_TO(void *cookie)
* transition decision in the state automaton.)
*/
static int
-sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
+sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int origlen)
{
- u_char *buf, *r, *p, l, blen;
+ u_char *buf, *r, *p, l, blen, type;
struct ifnet *ifp = &sp->pp_if;
- int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
+ int rlen, len, debug = ifp->if_flags & IFF_DEBUG;
uint32_t hisaddr, desiredaddr;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- origlen = len;
+ if (origlen < sizeof(*h))
+ return 0;
+
+ origlen -= sizeof(*h);
+ type = 0;
+
/*
* Make sure to allocate a buf that can at least hold a
* conf-nak with an `address' option. We might need it below.
*/
- blen = len < 6 ? 6 : len;
- buf = r = malloc (blen, M_TEMP, M_NOWAIT);
- if (! buf)
- return (0);
+ blen = MAX(6, origlen);
+
+ buf = kmem_intr_alloc(blen, KM_NOSLEEP);
+ if (buf == NULL)
+ return 0;
/* pass 1: see if we can recognize them */
if (debug)
log(LOG_DEBUG, "%s: ipcp parse opts:",
ifp->if_xname);
p = (void *)(h + 1);
- for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ r = buf;
+ rlen = 0;
+ for (len = origlen; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
/* Sanity check option length */
if (l > len) {
/* XXX should we just RXJ? */
addlog("%s: malicious IPCP option received, dropping\n",
ifp->if_xname);
- goto drop;
+ rlen = -1;
+ goto end;
}
if (debug)
addlog(" %s", sppp_ipcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
#ifdef notyet
case IPCP_OPT_COMPRESSION:
if (len >= 6 && l >= 6) {
@@ -3162,12 +3200,13 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
r += l;
rlen += l;
}
- if (rlen) {
- if (debug)
- addlog(" send conf-rej\n");
- sppp_cp_send(sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf);
+
+ if (rlen > 0) {
+ type = CONF_REJ;
goto end;
- } else if (debug)
+ }
+
+ if (debug)
addlog("\n");
/* pass 2: parse option values */
@@ -3183,11 +3222,16 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
log(LOG_DEBUG, "%s: ipcp parse opt values: ",
ifp->if_xname);
p = (void *)(h + 1);
- len = origlen;
- for (rlen=0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ r = buf;
+ rlen = 0;
+ for (len = origlen; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
if (debug)
addlog(" %s", sppp_ipcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
#ifdef notyet
case IPCP_OPT_COMPRESSION:
continue;
@@ -3243,26 +3287,34 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
rlen += l;
}
- /*
- * If we are about to conf-ack the request, but haven't seen
- * his address so far, gonna conf-nak it instead, with the
- * `address' option present and our idea of his address being
- * filled in there, to request negotiation of both addresses.
- *
- * XXX This can result in an endless req - nak loop if peer
- * doesn't want to send us his address. Q: What should we do
- * about it? XXX A: implement the max-failure counter.
- */
- if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) {
- buf[0] = IPCP_OPT_ADDRESS;
- buf[1] = 6;
- buf[2] = hisaddr >> 24;
- buf[3] = hisaddr >> 16;
- buf[4] = hisaddr >> 8;
- buf[5] = hisaddr;
- rlen = 6;
- if (debug)
- addlog(" still need hisaddr");
+ if (rlen > 0) {
+ type = CONF_NAK;
+ } else {
+ type = CONF_ACK;
+ rlen = origlen;
+ memcpy(r, h + 1, rlen);
+
+ if ((sp->ipcp.flags & IPCP_HISADDR_SEEN) == 0) {
+ /*
+ * If we are about to conf-ack the request, but haven't seen
+ * his address so far, gonna conf-nak it instead, with the
+ * `address' option present and our idea of his address being
+ * filled in there, to request negotiation of both addresses.
+ *
+ * XXX This can result in an endless req - nak loop if peer
+ * doesn't want to send us his address. Q: What should we do
+ * about it? XXX A: implement the max-failure counter.
+ */
+ buf[0] = IPCP_OPT_ADDRESS;
+ buf[1] = 6;
+ buf[2] = hisaddr >> 24;
+ buf[3] = hisaddr >> 16;
+ buf[4] = hisaddr >> 8;
+ buf[5] = hisaddr;
+ rlen = 6;
+ if (debug)
+ addlog(" still need hisaddr");
+ }
}
if (rlen) {
@@ -3275,13 +3327,20 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
sppp_cp_send(sp, PPP_IPCP, CONF_ACK, h->ident, origlen, h + 1);
}
- end:
- free(buf, M_TEMP);
- return (rlen == 0);
-
- drop:
- free(buf, M_TEMP);
- return -1;
+end:
+ if (rlen > 0) {
+ if (debug)
+ addlog(" send %s\n", sppp_cp_type_name(type));
+ sppp_cp_send(sp, PPP_IPCP, type, h->ident, rlen, buf);
+ }
+
+ kmem_free(buf, blen);
+
+ if (rlen < 0)
+ return -1;
+ if (type != CONF_ACK)
+ return 0;
+ return 1;
}
/*
@@ -3291,33 +3350,37 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
static void
sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
{
- u_char *buf, *p, l, blen;
+ u_char *p, l;
struct ifnet *ifp = &sp->pp_if;
int debug = ifp->if_flags & IFF_DEBUG;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- buf = malloc (blen = len, M_TEMP, M_NOWAIT);
- if (!buf)
+ if (len <= sizeof(*h))
return;
+ len -= sizeof(*h);
+
if (debug)
log(LOG_DEBUG, "%s: ipcp rej opts:",
ifp->if_xname);
p = (void *)(h + 1);
- for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
/* Sanity check option length */
if (l > len) {
/* XXX should we just RXJ? */
addlog("%s: malicious IPCP option received, dropping\n",
ifp->if_xname);
- goto drop;
+ goto end;
}
if (debug)
addlog(" %s", sppp_ipcp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case IPCP_OPT_ADDRESS:
/*
* Peer doesn't grok address option. This is
@@ -3334,8 +3397,7 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struc
}
if (debug)
addlog("\n");
-drop:
- free(buf, M_TEMP);
+end:
return;
}
@@ -3353,14 +3415,18 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struc
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
+ len -= sizeof(*h);
if (debug)
log(LOG_DEBUG, "%s: ipcp nak opts:",
ifp->if_xname);
p = (void *)(h + 1);
- for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
/* Sanity check option length */
if (l > len) {
/* XXX should we just RXJ? */
@@ -3619,11 +3685,11 @@ sppp_ipv6cp_TO(void *cookie)
* transition decision in the state automaton.)
*/
static int
-sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len)
+sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int origlen)
{
u_char *buf, *r, *p, l, blen;
struct ifnet *ifp = &sp->pp_if;
- int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
+ int rlen, len, debug = ifp->if_flags & IFF_DEBUG;
struct in6_addr myaddr, desiredaddr, suggestaddr;
int ifidcount;
int type;
@@ -3632,34 +3698,46 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- origlen = len;
+ if (origlen <= 0)
+ return 0;
+
+ origlen -= sizeof(*h);
+ type = 0;
+
/*
* Make sure to allocate a buf that can at least hold a
* conf-nak with an `address' option. We might need it below.
*/
- blen = len < 6 ? 6 : len;
- buf = r = malloc (blen, M_TEMP, M_NOWAIT);
- if (! buf)
- return (0);
+ blen = MAX(6, origlen);
+
+ buf = kmem_intr_alloc(blen, KM_NOSLEEP);
+ if (buf == NULL)
+ return 0;
/* pass 1: see if we can recognize them */
if (debug)
log(LOG_DEBUG, "%s: ipv6cp parse opts:",
ifp->if_xname);
p = (void *)(h + 1);
+ r = buf;
+ rlen = 0;
ifidcount = 0;
- for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (len = origlen; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
/* Sanity check option length */
if (l > len) {
/* XXX just RXJ? */
addlog("%s: received malicious IPCPv6 option, "
"dropping\n", ifp->if_xname);
- goto drop;
+ rlen = -1;
+ goto end;
}
if (debug)
addlog(" %s", sppp_ipv6cp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case IPV6CP_OPT_IFID:
if (len >= 10 && l == 10 && ifidcount == 0) {
/* correctly formed address option */
@@ -3695,12 +3773,13 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct
r += l;
rlen += l;
}
- if (rlen) {
- if (debug)
- addlog(" send conf-rej\n");
- sppp_cp_send(sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf);
+
+ if (rlen > 0) {
+ type = CONF_REJ;
goto end;
- } else if (debug)
+ }
+
+ if (debug)
addlog("\n");
/* pass 2: parse option values */
@@ -3709,12 +3788,17 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct
log(LOG_DEBUG, "%s: ipv6cp parse opt values: ",
ifp->if_xname);
p = (void *)(h + 1);
- len = origlen;
+ r = buf;
+ rlen = 0;
type = CONF_ACK;
- for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (len = origlen; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
if (debug)
addlog(" %s", sppp_ipv6cp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
#ifdef notyet
case IPV6CP_OPT_COMPRESSION:
continue;
@@ -3772,30 +3856,41 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct
rlen += l;
}
- if (rlen == 0 && type == CONF_ACK) {
- if (debug)
- addlog(" send %s\n", sppp_cp_type_name(type));
- sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, origlen, h + 1);
- } else {
+ if (rlen > 0) {
+ if (type != CONF_ACK) {
+ if (debug) {
+ addlog(" send %s suggest %s\n",
+ sppp_cp_type_name(type),
+ IN6_PRINT(ip6buf, &suggestaddr));
+ }
+ }
#ifdef notdef
if (type == CONF_ACK)
panic("IPv6CP RCR: CONF_ACK with non-zero rlen");
#endif
-
- if (debug) {
- addlog(" send %s suggest %s\n",
- sppp_cp_type_name(type), IN6_PRINT(ip6buf, &suggestaddr));
+ } else {
+ if (type == CONF_ACK) {
+ rlen = origlen;
+ memcpy(r, h + 1, rlen);
}
+ }
+end:
+ if (rlen > 0) {
+ if (debug)
+ addlog("send %s", sppp_cp_type_name(type));
sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, rlen, buf);
}
- end:
- free(buf, M_TEMP);
- return (rlen == 0);
-
- drop:
- free(buf, M_TEMP);
- return -1;
+ if (debug)
+ addlog("\n");
+
+ kmem_free(buf, blen);
+
+ if (rlen < 0)
+ return -1;
+ if (type != CONF_ACK)
+ return 0;
+ return 0;
}
/*
@@ -3805,32 +3900,36 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct
static void
sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
{
- u_char *buf, *p, l, blen;
+ u_char *p, l;
struct ifnet *ifp = &sp->pp_if;
int debug = ifp->if_flags & IFF_DEBUG;
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- buf = malloc (blen = len, M_TEMP, M_NOWAIT);
- if (!buf)
+ if (len <= sizeof(*h))
return;
+ len -= sizeof(*h);
+
if (debug)
log(LOG_DEBUG, "%s: ipv6cp rej opts:",
ifp->if_xname);
p = (void *)(h + 1);
- for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
if (l > len) {
/* XXX just RXJ? */
addlog("%s: received malicious IPCPv6 option, "
"dropping\n", ifp->if_xname);
- goto drop;
+ goto end;
}
if (debug)
addlog(" %s", sppp_ipv6cp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case IPV6CP_OPT_IFID:
/*
* Peer doesn't grok address option. This is
@@ -3847,8 +3946,7 @@ sppp_ipv6cp_RCN_rej(struct sppp *sp, str
}
if (debug)
addlog("\n");
-drop:
- free(buf, M_TEMP);
+end:
return;
}
@@ -3859,7 +3957,7 @@ drop:
static void
sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
{
- u_char *buf, *p, l, blen;
+ u_char *p, l;
struct ifnet *ifp = &sp->pp_if;
int debug = ifp->if_flags & IFF_DEBUG;
struct in6_addr suggestaddr;
@@ -3867,26 +3965,30 @@ sppp_ipv6cp_RCN_nak(struct sppp *sp, str
KASSERT(SPPP_WLOCKED(sp));
- len -= 4;
- buf = malloc (blen = len, M_TEMP, M_NOWAIT);
- if (!buf)
+ if (len <= sizeof(*h))
return;
+ len -= sizeof(*h);
+
if (debug)
log(LOG_DEBUG, "%s: ipv6cp nak opts:",
ifp->if_xname);
p = (void *)(h + 1);
- for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+ for (; len > 1; len -= l, p += l) {
+ l = p[1];
+ if (l == 0)
+ break;
+
if (l > len) {
/* XXX just RXJ? */
addlog("%s: received malicious IPCPv6 option, "
"dropping\n", ifp->if_xname);
- goto drop;
+ goto end;
}
if (debug)
addlog(" %s", sppp_ipv6cp_opt_name(*p));
- switch (*p) {
+ switch (p[0]) {
case IPV6CP_OPT_IFID:
/*
* Peer doesn't like our local ifid. See
@@ -3954,8 +4056,7 @@ sppp_ipv6cp_RCN_nak(struct sppp *sp, str
}
if (debug)
addlog("\n");
-drop:
- free(buf, M_TEMP);
+end:
return;
}