diff options
author | mav <mav@FreeBSD.org> | 2009-01-18 19:25:36 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2009-01-18 19:25:36 +0000 |
commit | 74ed22786b2388740d2f5bc730136ec510dcfac2 (patch) | |
tree | e258ed6671707a1c996eb707ec8d75e37a8f676d /sys/netgraph/ng_pred1.c | |
parent | 963ae12224cd98dd95013e6649729f830eb6aa90 (diff) | |
download | FreeBSD-src-74ed22786b2388740d2f5bc730136ec510dcfac2.zip FreeBSD-src-74ed22786b2388740d2f5bc730136ec510dcfac2.tar.gz |
Use m_unshare()+m_copyback() instead of m_freem()+m_devget() to keep
original mbuf chain headers. It can be less efficient in some cases, but it
looks better then mess of copying headers into the nonempty chain.
Diffstat (limited to 'sys/netgraph/ng_pred1.c')
-rw-r--r-- | sys/netgraph/ng_pred1.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/sys/netgraph/ng_pred1.c b/sys/netgraph/ng_pred1.c index 981448e..5f01e88 100644 --- a/sys/netgraph/ng_pred1.c +++ b/sys/netgraph/ng_pred1.c @@ -400,11 +400,16 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp) return (ENOMEM); } + /* We must own the mbuf chain exclusively to modify it. */ + m = m_unshare(m, M_DONTWAIT); + if (m == NULL) { + priv->stats.Errors++; + return (ENOMEM); + } + /* Work with contiguous regions of memory. */ m_copydata(m, 0, inlen, (caddr_t)(priv->inbuf + 2)); - NG_FREE_M(m); - lenn = htons(inlen & 0x7FFF); /* Compute FCS. */ @@ -437,12 +442,14 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp) outlen += 2; /* Return packet in an mbuf. */ - *resultp = m_devget((caddr_t)out, outlen, 0, NULL, NULL); - if (*resultp == NULL) { - priv->stats.Errors++; - return (ENOMEM); - }; - + m_copyback(m, 0, outlen, (caddr_t)out); + if (m->m_pkthdr.len < outlen) { + m_freem(m); + priv->stats.Errors++; + return (ENOMEM); + } else if (outlen < m->m_pkthdr.len) + m_adj(m, outlen - m->m_pkthdr.len); + *resultp = m; priv->stats.OutOctets += outlen; return (0); @@ -471,6 +478,13 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp) return (ENOMEM); } + /* We must own the mbuf chain exclusively to modify it. */ + m = m_unshare(m, M_DONTWAIT); + if (m == NULL) { + priv->stats.Errors++; + return (ENOMEM); + } + /* Work with contiguous regions of memory. */ m_copydata(m, 0, inlen, (caddr_t)priv->inbuf); @@ -485,13 +499,12 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp) /* Is data compressed or not really? */ if (cf) { - NG_FREE_M(m); - priv->stats.FramesComp++; len1 = Pred1Decompress(node, priv->inbuf + 2, priv->outbuf, inlen - 4, PRED1_BUF_SIZE); if (len != len1) { /* Error is detected. Send reset request */ + m_freem(m); priv->stats.Errors++; log(LOG_NOTICE, "ng_pred1: Comp length error (%d) " "--> len (%d)\n", len, len1); @@ -510,17 +523,21 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp) fcs = Crc16(fcs, priv->inbuf + inlen - 2, 2); if (fcs != PPP_GOODFCS) { + m_freem(m); priv->stats.Errors++; log(LOG_NOTICE, "ng_pred1: Pred1: Bad CRC-16\n"); return (EIO); } /* Return packet in an mbuf. */ - *resultp = m_devget((caddr_t)priv->outbuf, len, 0, NULL, NULL); - if (*resultp == NULL) { + m_copyback(m, 0, len, (caddr_t)priv->outbuf); + if (m->m_pkthdr.len < len) { + m_freem(m); priv->stats.Errors++; return (ENOMEM); - }; + } else if (len < m->m_pkthdr.len) + m_adj(m, len - m->m_pkthdr.len); + *resultp = m; } else { priv->stats.FramesUncomp++; |