summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2007-07-25 14:03:46 +0000
committerAlexander Motin <mav@FreeBSD.org>2007-07-25 14:03:46 +0000
commit9b0e4d54a4d1ba9b43eaafed87a2c663444b2fc2 (patch)
tree2a661dc526a199f0dd1499c873caa949758b198f
parent80ef4001e9c839600f7753c129ad6d5c96fcdddc (diff)
Notes
-rw-r--r--sys/netgraph/ng_mppc.c210
1 files changed, 124 insertions, 86 deletions
diff --git a/sys/netgraph/ng_mppc.c b/sys/netgraph/ng_mppc.c
index 55b021a6b564..0cf1e7272b9a 100644
--- a/sys/netgraph/ng_mppc.c
+++ b/sys/netgraph/ng_mppc.c
@@ -113,6 +113,8 @@ MALLOC_DEFINE(M_NETGRAPH_MPPC, "netgraph_mppc", "netgraph mppc node ");
#define MPPC_FLAG_ENCRYPTED 0x1000 /* packet is encrypted */
#define MPPC_CCOUNT_MASK 0x0fff /* sequence number mask */
+#define MPPC_CCOUNT_INC(d) ((d) = (((d) + 1) & MPPC_CCOUNT_MASK))
+
#define MPPE_UPDATE_MASK 0xff /* coherency count when we're */
#define MPPE_UPDATE_FLAG 0xff /* supposed to update key */
@@ -152,12 +154,14 @@ static ng_disconnect_t ng_mppc_disconnect;
/* Helper functions */
static int ng_mppc_compress(node_p node,
- struct mbuf *m, struct mbuf **resultp);
+ struct mbuf **datap);
static int ng_mppc_decompress(node_p node,
- struct mbuf *m, struct mbuf **resultp);
+ struct mbuf **datap);
+#ifdef NETGRAPH_MPPC_ENCRYPTION
static void ng_mppc_getkey(const u_char *h, u_char *h2, int len);
static void ng_mppc_updatekey(u_int32_t bits,
u_char *key0, u_char *key, struct rc4_state *rc4);
+#endif
static void ng_mppc_reset_req(node_p node);
/* Node type descriptor */
@@ -354,7 +358,6 @@ ng_mppc_rcvdata(hook_p hook, item_p item)
{
const node_p node = NG_HOOK_NODE(hook);
const priv_p priv = NG_NODE_PRIVATE(node);
- struct mbuf *out;
int error;
struct mbuf *m;
@@ -366,13 +369,11 @@ ng_mppc_rcvdata(hook_p hook, item_p item)
NG_FREE_ITEM(item);
return (ENXIO);
}
- if ((error = ng_mppc_compress(node, m, &out)) != 0) {
- NG_FREE_M(m);
+ if ((error = ng_mppc_compress(node, &m)) != 0) {
NG_FREE_ITEM(item);
return(error);
}
- NG_FREE_M(m);
- NG_FWD_NEW_DATA(error, item, priv->xmit.hook, out);
+ NG_FWD_NEW_DATA(error, item, priv->xmit.hook, m);
return (error);
}
@@ -383,8 +384,7 @@ ng_mppc_rcvdata(hook_p hook, item_p item)
NG_FREE_ITEM(item);
return (ENXIO);
}
- if ((error = ng_mppc_decompress(node, m, &out)) != 0) {
- NG_FREE_M(m);
+ if ((error = ng_mppc_decompress(node, &m)) != 0) {
NG_FREE_ITEM(item);
if (error == EINVAL && priv->ctrlnode != 0) {
struct ng_mesg *msg;
@@ -399,8 +399,7 @@ ng_mppc_rcvdata(hook_p hook, item_p item)
}
return (error);
}
- NG_FREE_M(m);
- NG_FWD_NEW_DATA(error, item, priv->recv.hook, out);
+ NG_FWD_NEW_DATA(error, item, priv->recv.hook, m);
return (error);
}
@@ -464,51 +463,54 @@ ng_mppc_disconnect(hook_p hook)
* The original mbuf is not free'd.
*/
static int
-ng_mppc_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
+ng_mppc_compress(node_p node, struct mbuf **datap)
{
const priv_p priv = NG_NODE_PRIVATE(node);
struct ng_mppc_dir *const d = &priv->xmit;
- u_char *inbuf, *outbuf;
- int outlen, inlen;
u_int16_t header;
+ struct mbuf *m = *datap;
/* Initialize */
- *resultp = NULL;
header = d->cc;
- if (d->flushed) {
+
+ /* Always set the flushed bit in stateless mode */
+ if (d->flushed || ((d->cfg.bits & MPPE_STATELESS) != 0)) {
header |= MPPC_FLAG_FLUSHED;
d->flushed = 0;
}
- /* Work with contiguous regions of memory */
- inlen = m->m_pkthdr.len;
- MALLOC(inbuf, u_char *, inlen, M_NETGRAPH_MPPC, M_NOWAIT);
- if (inbuf == NULL)
- return (ENOMEM);
- m_copydata(m, 0, inlen, (caddr_t)inbuf);
- if ((d->cfg.bits & MPPC_BIT) != 0)
- outlen = MPPC_MAX_BLOWUP(inlen);
- else
- outlen = MPPC_HDRLEN + inlen;
- MALLOC(outbuf, u_char *, outlen, M_NETGRAPH_MPPC, M_NOWAIT);
- if (outbuf == NULL) {
- FREE(inbuf, M_NETGRAPH_MPPC);
- return (ENOMEM);
- }
-
- /* Compress "inbuf" into "outbuf" (if compression enabled) */
+ /* Compress packet (if compression enabled) */
#ifdef NETGRAPH_MPPC_COMPRESSION
if ((d->cfg.bits & MPPC_BIT) != 0) {
u_short flags = MPPC_MANDATORY_COMPRESS_FLAGS;
+ u_char *inbuf, *outbuf;
+ int outlen, inlen;
u_char *source, *dest;
u_long sourceCnt, destCnt;
int rtn;
+ /* Work with contiguous regions of memory. */
+ inlen = m->m_pkthdr.len;
+ inbuf = malloc(inlen, M_NETGRAPH_MPPC, M_NOWAIT);
+ if (inbuf == NULL) {
+ m_freem(m);
+ return (ENOMEM);
+ }
+ m_copydata(m, 0, inlen, (caddr_t)inbuf);
+
+ outlen = MPPC_MAX_BLOWUP(inlen);
+ outbuf = malloc(outlen, M_NETGRAPH_MPPC, M_NOWAIT);
+ if (outbuf == NULL) {
+ m_freem(m);
+ free(inbuf, M_NETGRAPH_MPPC);
+ return (ENOMEM);
+ }
+
/* Prepare to compress */
source = inbuf;
sourceCnt = inlen;
- dest = outbuf + MPPC_HDRLEN;
- destCnt = outlen - MPPC_HDRLEN;
+ dest = outbuf;
+ destCnt = outlen;
if ((d->cfg.bits & MPPE_STATELESS) == 0)
flags |= MPPC_SAVE_HISTORY;
@@ -524,55 +526,67 @@ ng_mppc_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
header |= MPPC_FLAG_COMPRESSED;
if ((rtn & MPPC_RESTART_HISTORY) != 0)
header |= MPPC_FLAG_RESTART;
+
+ /* Replace m by the compresed one. */
+ m_freem(m);
+ m = m_devget((caddr_t)outbuf, outlen, 0, NULL, NULL);
}
d->flushed = (rtn & MPPC_EXPANDED) != 0
|| (flags & MPPC_SAVE_HISTORY) == 0;
- }
-#endif
- /* If we did not compress this packet, copy it to output buffer */
- if ((header & MPPC_FLAG_COMPRESSED) == 0) {
- bcopy(inbuf, outbuf + MPPC_HDRLEN, inlen);
- outlen = MPPC_HDRLEN + inlen;
- }
- FREE(inbuf, M_NETGRAPH_MPPC);
+ free(inbuf, M_NETGRAPH_MPPC);
+ free(outbuf, M_NETGRAPH_MPPC);
- /* Always set the flushed bit in stateless mode */
- if ((d->cfg.bits & MPPE_STATELESS) != 0)
- header |= MPPC_FLAG_FLUSHED;
+ /* Check m_devget() result. */
+ if (m == NULL)
+ return (ENOMEM);
+ }
+#endif
/* Now encrypt packet (if encryption enabled) */
#ifdef NETGRAPH_MPPC_ENCRYPTION
if ((d->cfg.bits & MPPE_BITS) != 0) {
+ struct mbuf *m1;
- /* Set header bits; need to reset key if we say we did */
+ /* Set header bits */
header |= MPPC_FLAG_ENCRYPTED;
- if ((header & MPPC_FLAG_FLUSHED) != 0)
- rc4_init(&d->rc4, d->key, KEYLEN(d->cfg.bits));
/* Update key if it's time */
if ((d->cfg.bits & MPPE_STATELESS) != 0
|| (d->cc & MPPE_UPDATE_MASK) == MPPE_UPDATE_FLAG) {
- ng_mppc_updatekey(d->cfg.bits,
- d->cfg.startkey, d->key, &d->rc4);
+ ng_mppc_updatekey(d->cfg.bits,
+ d->cfg.startkey, d->key, &d->rc4);
+ } else if ((header & MPPC_FLAG_FLUSHED) != 0) {
+ /* Need to reset key if we say we did
+ and ng_mppc_updatekey wasn't called to do it also. */
+ rc4_init(&d->rc4, d->key, KEYLEN(d->cfg.bits));
}
+ /* We must own the mbuf chain exclusively to modify it. */
+ m = m_unshare(m, M_DONTWAIT);
+ if (m == NULL)
+ return (ENOMEM);
+
/* Encrypt packet */
- rc4_crypt(&d->rc4, outbuf + MPPC_HDRLEN,
- outbuf + MPPC_HDRLEN, outlen - MPPC_HDRLEN);
+ m1 = m;
+ while (m1) {
+ rc4_crypt(&d->rc4, mtod(m1, u_char *),
+ mtod(m1, u_char *), m1->m_len);
+ m1 = m1->m_next;
+ }
}
#endif
- /* Update sequence number */
- d->cc++;
+ /* Update coherency count for next time (12 bit arithmetic) */
+ MPPC_CCOUNT_INC(d->cc);
/* Install header */
- *((u_int16_t *)outbuf) = htons(header);
+ M_PREPEND(m, MPPC_HDRLEN, M_DONTWAIT);
+ if (m != NULL)
+ *(mtod(m, uint16_t *)) = htons(header);
- /* Return packet in an mbuf */
- *resultp = m_devget((caddr_t)outbuf, outlen, 0, NULL, NULL);
- FREE(outbuf, M_NETGRAPH_MPPC);
- return (*resultp == NULL ? ENOBUFS : 0);
+ *datap = m;
+ return (*datap == NULL ? ENOBUFS : 0);
}
/*
@@ -580,28 +594,23 @@ ng_mppc_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
* The original mbuf is not free'd.
*/
static int
-ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
+ng_mppc_decompress(node_p node, struct mbuf **datap)
{
const priv_p priv = NG_NODE_PRIVATE(node);
struct ng_mppc_dir *const d = &priv->recv;
u_int16_t header, cc;
u_int numLost;
- u_char *buf;
- int len;
+ struct mbuf *m = *datap;
/* Pull off header */
- if (m->m_pkthdr.len < MPPC_HDRLEN)
+ if (m->m_pkthdr.len < MPPC_HDRLEN) {
+ m_freem(m);
return (EINVAL);
+ }
m_copydata(m, 0, MPPC_HDRLEN, (caddr_t)&header);
header = ntohs(header);
cc = (header & MPPC_CCOUNT_MASK);
-
- /* Copy payload into a contiguous region of memory */
- len = m->m_pkthdr.len - MPPC_HDRLEN;
- MALLOC(buf, u_char *, len, M_NETGRAPH_MPPC, M_NOWAIT);
- if (buf == NULL)
- return (ENOMEM);
- m_copydata(m, MPPC_HDRLEN, len, (caddr_t)buf);
+ m_adj(m, MPPC_HDRLEN);
/* Check for an unexpected jump in the sequence number */
numLost = ((cc - d->cc) & MPPC_CCOUNT_MASK);
@@ -635,7 +644,7 @@ ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
ng_mppc_updatekey(d->cfg.bits,
d->cfg.startkey, d->key, &d->rc4);
}
- d->cc++;
+ MPPC_CCOUNT_INC(d->cc);
}
/* Reset key (except in stateless mode, see below) */
@@ -653,6 +662,9 @@ ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
/* Decrypt packet */
if ((header & MPPC_FLAG_ENCRYPTED) != 0) {
+#ifdef NETGRAPH_MPPC_ENCRYPTION
+ struct mbuf *m1;
+#endif
/* Are we not expecting encryption? */
if ((d->cfg.bits & MPPE_BITS) == 0) {
@@ -669,8 +681,18 @@ ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
d->cfg.startkey, d->key, &d->rc4);
}
+ /* We must own the mbuf chain exclusively to modify it. */
+ m = m_unshare(m, M_DONTWAIT);
+ if (m == NULL)
+ return (ENOMEM);
+
/* Decrypt packet */
- rc4_crypt(&d->rc4, buf, buf, len);
+ m1 = m;
+ while (m1 != NULL) {
+ rc4_crypt(&d->rc4, mtod(m1, u_char *),
+ mtod(m1, u_char *), m1->m_len);
+ m1 = m1->m_next;
+ }
#endif
} else {
@@ -683,7 +705,7 @@ ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
}
/* Update coherency count for next time (12 bit arithmetic) */
- d->cc++;
+ MPPC_CCOUNT_INC(d->cc);
/* Check for unexpected compressed packet */
if ((header & MPPC_FLAG_COMPRESSED) != 0
@@ -691,7 +713,7 @@ ng_mppc_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
log(LOG_ERR, "%s: rec'd unexpectedly %s packet",
__func__, "compressed");
failed:
- FREE(buf, M_NETGRAPH_MPPC);
+ m_freem(m);
return (EINVAL);
}
@@ -702,12 +724,24 @@ failed:
u_char *decompbuf, *source, *dest;
u_long sourceCnt, destCnt;
int decomplen, rtn;
+ u_char *buf;
+ int len;
+
+ /* Copy payload into a contiguous region of memory. */
+ len = m->m_pkthdr.len;
+ buf = malloc(len, M_NETGRAPH_MPPC, M_NOWAIT);
+ if (buf == NULL) {
+ m_freem(m);
+ return (ENOMEM);
+ }
+ m_copydata(m, 0, len, (caddr_t)buf);
/* Allocate a buffer for decompressed data */
- MALLOC(decompbuf, u_char *, MPPC_DECOMP_BUFSIZE
- + MPPC_DECOMP_SAFETY, M_NETGRAPH_MPPC, M_NOWAIT);
+ decompbuf = malloc(MPPC_DECOMP_BUFSIZE + MPPC_DECOMP_SAFETY,
+ M_NETGRAPH_MPPC, M_NOWAIT);
if (decompbuf == NULL) {
- FREE(buf, M_NETGRAPH_MPPC);
+ m_freem(m);
+ free(buf, M_NETGRAPH_MPPC);
return (ENOMEM);
}
decomplen = MPPC_DECOMP_BUFSIZE;
@@ -730,21 +764,24 @@ failed:
|| (rtn & MPPC_DECOMP_OK) != MPPC_DECOMP_OK) {
log(LOG_ERR, "%s: decomp returned 0x%x",
__func__, rtn);
- FREE(decompbuf, M_NETGRAPH_MPPC);
+ free(buf, M_NETGRAPH_MPPC);
+ free(decompbuf, M_NETGRAPH_MPPC);
goto failed;
}
/* Replace compressed data with decompressed data */
- FREE(buf, M_NETGRAPH_MPPC);
- buf = decompbuf;
+ free(buf, M_NETGRAPH_MPPC);
len = decomplen - destCnt;
+
+ m_freem(m);
+ m = m_devget((caddr_t)decompbuf, len, 0, NULL, NULL);
+ free(decompbuf, M_NETGRAPH_MPPC);
}
#endif
/* Return result in an mbuf */
- *resultp = m_devget((caddr_t)buf, len, 0, NULL, NULL);
- FREE(buf, M_NETGRAPH_MPPC);
- return (*resultp == NULL ? ENOBUFS : 0);
+ *datap = m;
+ return (*datap == NULL ? ENOBUFS : 0);
}
/*
@@ -767,6 +804,7 @@ ng_mppc_reset_req(node_p node)
d->flushed = 1;
}
+#ifdef NETGRAPH_MPPC_ENCRYPTION
/*
* Generate a new encryption key
*/
@@ -781,11 +819,10 @@ ng_mppc_getkey(const u_char *h, u_char *h2, int len)
SHA1_CTX c;
int k;
- bzero(&hash, sizeof(hash));
SHA1Init(&c);
SHA1Update(&c, h, len);
for (k = 0; k < 4; k++)
- SHA1Update(&c, pad1, sizeof(pad2));
+ SHA1Update(&c, pad1, sizeof(pad1));
SHA1Update(&c, h2, len);
for (k = 0; k < 4; k++)
SHA1Update(&c, pad2, sizeof(pad2));
@@ -811,4 +848,5 @@ ng_mppc_updatekey(u_int32_t bits,
bcopy(&ng_mppe_weakenkey, key, 1);
rc4_init(rc4, key, keylen);
}
+#endif