summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_mbuf.c4
-rw-r--r--sys/netinet/ip_esp_new.c37
-rw-r--r--sys/netinet/ip_esp_old.c37
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)
{