diff options
-rw-r--r-- | sys/kern/uipc_mbuf.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_esp_new.c | 37 | ||||
-rw-r--r-- | sys/netinet/ip_esp_old.c | 37 |
3 files changed, 71 insertions, 7 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index dcfd71964de..f83ccb3ef41 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.9 1999/02/26 04:49:07 art Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.10 1999/05/12 21:11:40 ho Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -364,8 +364,6 @@ nospace: /* * m_copym2() is like m_copym(), except it COPIES cluster mbufs, instead * of merely bumping the reference count. - * - * The hope is to obsolete this function someday. */ struct mbuf * m_copym2(m, off0, len, wait) diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c index 67f87eb5b9e..cb345c5bfce 100644 --- a/sys/netinet/ip_esp_new.c +++ b/sys/netinet/ip_esp_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_new.c,v 1.40 1999/03/24 17:00:45 niklas Exp $ */ +/* $OpenBSD: ip_esp_new.c,v 1.41 1999/05/12 21:11:42 ho Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -781,7 +781,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct ip *ip, ipo; int i, ilen, ohlen, nh, rlen, plen, padding, rest; struct esp_new espo; - struct mbuf *mi, *mo; + struct mbuf *mi, *mo = (struct mbuf *)NULL; u_char *pad, *idat, *odat, *ivp; u_char iv[ESP_MAX_IVS], blk[ESP_MAX_BLKS], auth[AH_ALEN_MAX], opts[40]; union { @@ -800,6 +800,39 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, espstat.esps_output++; + /* + * Loop through mbuf chain; if we find an M_EXT mbuf with + * more than one reference, replace the rest of the chain. + */ + mi = m; + while (mi != NULL && + (!(mi->m_flags & M_EXT) || + mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)) + { + mo = mi; + mi = mi->m_next; + } + + if (mi != NULL) + { + /* Replace the rest of the mbuf chain. */ + struct mbuf *n = m_copym2 (mi, 0, M_COPYALL, M_DONTWAIT); + + if (n == NULL) + { + espstat.esps_hdrops++; + m_freem(m); + return ENOBUFS; + } + + if (mo != NULL) + mo->m_next = n; + else + m = n; + + m_freem(mi); + } + m = m_pullup(m, sizeof (struct ip)); /* Get IP header in one mbuf */ if (m == NULL) { diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c index 92639fe002a..2d33b230eef 100644 --- a/sys/netinet/ip_esp_old.c +++ b/sys/netinet/ip_esp_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_old.c,v 1.31 1999/03/24 17:00:46 niklas Exp $ */ +/* $OpenBSD: ip_esp_old.c,v 1.32 1999/05/12 21:11:42 ho Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -505,7 +505,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct ip *ip, ipo; int i, ilen, ohlen, nh, rlen, plen, padding, rest; u_int32_t spi; - struct mbuf *mi, *mo; + struct mbuf *mi, *mo = (struct mbuf *)NULL; u_char *pad, *idat, *odat, *ivp; u_char iv[ESP_3DES_IVS], blk[ESP_3DES_IVS], opts[40]; int iphlen, blks; @@ -514,6 +514,39 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, espstat.esps_output++; + /* + * Loop through mbuf chain; if we find an M_EXT mbuf with + * more than one reference, replace the rest of the chain. + */ + mi = m; + while (mi != NULL && + (!(mi->m_flags & M_EXT) || + mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)) + { + mo = mi; + mi = mi->m_next; + } + + if (mi != NULL) + { + /* Replace the rest of the mbuf chain. */ + struct mbuf *n = m_copym2 (mi, 0, M_COPYALL, M_DONTWAIT); + + if (n == NULL) + { + espstat.esps_hdrops++; + m_freem(m); + return ENOBUFS; + } + + if (mo != NULL) + mo->m_next = n; + else + m = n; + + m_freem(mi); + } + m = m_pullup(m, sizeof(struct ip)); if (m == NULL) { |