Subject: None
To: None <burgess@neonramp.com, tech-net@netbsd.org>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 02/02/2001 10:49:31
the following patch is equivalent to
http://mail-index.netbsd.org/current-users/2001/01/23/0005.html,
but for NetBSD 1.5.1_ALPHA (the latest code on netbsd-1-5 branch).
it should apply much cleaner against 1.5.
it should change:
- ipf to only look at wire-format packet. ipf will not touch
ipsec-decapsulated packet on inbound, nor packet before encapsulation
on outbound.
see
http://www.netbsd.org/Documentation/network/ipsec/#ipf-interaction
for more details.
itojun
Index: sys/mbuf.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/mbuf.h,v
retrieving revision 1.49.4.2
diff -u -r1.49.4.2 mbuf.h
--- sys/mbuf.h 2000/08/30 06:23:08 1.49.4.2
+++ sys/mbuf.h 2001/02/02 01:47:22
@@ -92,11 +92,6 @@
#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */
-/*
- * NOTE: MINCLSIZE is changed to MHLEN + 1, to avoid allocating chained
- * non-external mbufs in the driver. This has no impact on performance
- * seen from the packet statistics, and avoid header pullups in network code.
- */
#define MINCLSIZE (MHLEN+MLEN+1) /* smallest amount to put in cluster */
#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */
@@ -395,10 +390,18 @@
* MFREE(struct mbuf *m, struct mbuf *n)
* Free a single mbuf and associated external storage.
* Place the successor, if any, in n.
+ *
+ * we do need to check non-first mbuf for m_aux, since some of existing
+ * code does not call M_PREPEND properly.
+ * (example: call to bpf_mtap from drivers)
*/
#define MFREE(m, n) \
MBUFLOCK( \
mbstat.m_mtypes[(m)->m_type]--; \
+ if (((m)->m_flags & M_PKTHDR) != 0 && (m)->m_pkthdr.aux) { \
+ m_freem((m)->m_pkthdr.aux); \
+ (m)->m_pkthdr.aux = NULL; \
+ } \
if ((m)->m_flags & M_EXT) { \
_MEXTREMOVE((m)); \
} \
Index: kern/uipc_mbuf.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/uipc_mbuf.c,v
retrieving revision 1.45.4.1
diff -u -r1.45.4.1 uipc_mbuf.c
--- kern/uipc_mbuf.c 2000/08/19 07:55:31 1.45.4.1
+++ kern/uipc_mbuf.c 2001/02/02 01:47:24
@@ -350,10 +350,6 @@
if (m == NULL)
return;
- if ((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.aux) {
- m_freem(m->m_pkthdr.aux);
- m->m_pkthdr.aux = NULL;
- }
do {
MFREE(m, n);
m = n;
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_icmp.c,v
retrieving revision 1.47.2.3
diff -u -r1.47.2.3 ip_icmp.c
--- netinet/ip_icmp.c 2000/08/16 01:22:22 1.47.2.3
+++ netinet/ip_icmp.c 2001/02/02 01:47:26
@@ -808,7 +808,7 @@
#endif
#ifdef IPSEC
/* Don't lookup socket */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
(void) ip_output(m, opts, NULL, 0, NULL);
}
Index: netinet/ip_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_input.c,v
retrieving revision 1.114.4.3
diff -u -r1.114.4.3 ip_input.c
--- netinet/ip_input.c 2000/10/17 00:59:49 1.114.4.3
+++ netinet/ip_input.c 2001/02/02 01:47:29
@@ -459,6 +459,14 @@
#endif
#ifdef PFIL_HOOKS
+#ifdef IPSEC
+ /*
+ * let ipfilter look at packet on the wire,
+ * not the decapsulated packet.
+ */
+ if (ipsec_gethist(m, NULL))
+ goto nofilt;
+#endif
/*
* Run through list of hooks for input packets. If there are any
* filters which require that additional packets in the flow are
@@ -479,6 +487,9 @@
return;
ip = mtod(m, struct ip *);
}
+#ifdef IPSEC
+nofilt:;
+#endif
#endif /* PFIL_HOOKS */
/*
@@ -1439,7 +1450,7 @@
#ifdef IPSEC
/* Don't lookup socket in forwading case */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0);
Index: netinet/ip_mroute.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_mroute.c,v
retrieving revision 1.50
diff -u -r1.50 ip_mroute.c
--- netinet/ip_mroute.c 2000/04/19 06:30:55 1.50
+++ netinet/ip_mroute.c 2001/02/02 01:47:32
@@ -1690,7 +1690,7 @@
/* If tunnel options */
#ifdef IPSEC
/* Don't lookup socket in forwading case */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
ip_output(m, (struct mbuf *)0, &vifp->v_route,
IP_FORWARDING, (struct ip_moptions *)0);
@@ -1707,7 +1707,7 @@
#ifdef IPSEC
/* Don't lookup socket in forwading case */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
error = ip_output(m, (struct mbuf *)0, (struct route *)0,
IP_FORWARDING|IP_MULTICASTOPTS, &imo);
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_output.c,v
retrieving revision 1.74
diff -u -r1.74 ip_output.c
--- netinet/ip_output.c 2000/05/10 03:31:30 1.74
+++ netinet/ip_output.c 2001/02/02 01:47:35
@@ -204,7 +204,7 @@
#ifdef IPSEC
so = ipsec_getsocket(m);
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif /*IPSEC*/
#ifdef DIAGNOSTIC
@@ -417,26 +417,6 @@
m->m_flags &= ~M_BCAST;
sendit:
-#ifdef PFIL_HOOKS
- /*
- * Run through list of hooks for output packets.
- */
- m1 = m;
- pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
- for (; pfh; pfh = pfh->pfil_link.tqe_next)
- if (pfh->pfil_func) {
- rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
- if (rv) {
- error = EHOSTUNREACH;
- goto done;
- }
- m = m1;
- if (m == NULL)
- goto done;
- ip = mtod(m, struct ip *);
- }
-#endif /* PFIL_HOOKS */
-
#ifdef IPSEC
/* get SP for this packet */
if (so == NULL)
@@ -556,6 +536,26 @@
skip_ipsec:
#endif /*IPSEC*/
+#ifdef PFIL_HOOKS
+ /*
+ * Run through list of hooks for output packets.
+ */
+ m1 = m;
+ pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ for (; pfh; pfh = pfh->pfil_link.tqe_next)
+ if (pfh->pfil_func) {
+ rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
+ if (rv) {
+ error = EHOSTUNREACH;
+ goto done;
+ }
+ m = m1;
+ if (m == NULL)
+ goto done;
+ ip = mtod(m, struct ip *);
+ }
+#endif /* PFIL_HOOKS */
+
/*
* If small enough for mtu of path, can just send directly.
*/
@@ -577,6 +577,10 @@
HTONS(ip->ip_off);
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
+#endif
error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
goto done;
}
@@ -700,6 +704,10 @@
ia->ia_ifa.ifa_data.ifad_outbytes +=
ntohs(ip->ip_len);
}
+#endif
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
#endif
error = (*ifp->if_output)(ifp, m, sintosa(dst),
ro->ro_rt);
Index: netinet/raw_ip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/raw_ip.c,v
retrieving revision 1.53
diff -u -r1.53 raw_ip.c
--- netinet/raw_ip.c 2000/03/30 13:25:04 1.53
+++ netinet/raw_ip.c 2001/02/02 01:47:36
@@ -279,7 +279,10 @@
ipstat.ips_rawout++;
}
#ifdef IPSEC
- ipsec_setsocket(m, inp->inp_socket);
+ if (ipsec_setsocket(m, inp->inp_socket) != 0) {
+ m_freem(m);
+ return ENOBUFS;
+ }
#endif /*IPSEC*/
return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, &inp->inp_errormtu));
}
Index: netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp_input.c,v
retrieving revision 1.108.4.7
diff -u -r1.108.4.7 tcp_input.c
--- netinet/tcp_input.c 2000/08/16 01:22:22 1.108.4.7
+++ netinet/tcp_input.c 2001/02/02 01:47:42
@@ -3409,7 +3409,10 @@
else
so = NULL;
/* use IPsec policy on listening socket, on SYN ACK */
- ipsec_setsocket(m, so);
+ if (ipsec_setsocket(m, so) != 0) {
+ m_freem(m);
+ return ENOBUFS;
+ }
}
#endif
m->m_pkthdr.rcvif = NULL;
Index: netinet/tcp_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp_output.c,v
retrieving revision 1.56.4.3
diff -u -r1.56.4.3 tcp_output.c
--- netinet/tcp_output.c 2000/11/10 00:12:43 1.56.4.3
+++ netinet/tcp_output.c 2001/02/02 01:47:44
@@ -1024,7 +1024,11 @@
}
}
#ifdef IPSEC
- ipsec_setsocket(m, so);
+ if (ipsec_setsocket(m, so) != 0) {
+ m_freem(m);
+ error = ENOBUFS;
+ goto out;
+ }
#endif /*IPSEC*/
switch (af) {
Index: netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp_subr.c,v
retrieving revision 1.91.4.3
diff -u -r1.91.4.3 tcp_subr.c
--- netinet/tcp_subr.c 2000/10/17 00:48:30 1.91.4.3
+++ netinet/tcp_subr.c 2001/02/02 01:47:47
@@ -618,7 +618,7 @@
}
#ifdef IPSEC
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif /*IPSEC*/
/*
@@ -632,7 +632,10 @@
if (tp != NULL && tp->t_inpcb != NULL) {
ro = &tp->t_inpcb->inp_route;
#ifdef IPSEC
- ipsec_setsocket(m, tp->t_inpcb->inp_socket);
+ if (ipsec_setsocket(m, tp->t_inpcb->inp_socket) != 0) {
+ m_freem(m);
+ return ENOBUFS;
+ }
#endif
#ifdef DIAGNOSTIC
if (family != AF_INET)
@@ -648,7 +651,10 @@
else if (tp != NULL && tp->t_in6pcb != NULL) {
ro = (struct route *)&tp->t_in6pcb->in6p_route;
#ifdef IPSEC
- ipsec_setsocket(m, tp->t_in6pcb->in6p_socket);
+ if (ipsec_setsocket(m, tp->t_in6pcb->in6p_socket) != 0) {
+ m_freem(m);
+ return ENOBUFS;
+ }
#endif
#ifdef DIAGNOSTIC
if (family == AF_INET) {
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/udp_usrreq.c,v
retrieving revision 1.66.4.3
diff -u -r1.66.4.3 udp_usrreq.c
--- netinet/udp_usrreq.c 2000/12/15 03:29:16 1.66.4.3
+++ netinet/udp_usrreq.c 2001/02/02 01:47:50
@@ -1254,7 +1254,10 @@
udpstat.udps_opackets++;
#ifdef IPSEC
- ipsec_setsocket(m, inp->inp_socket);
+ if (ipsec_setsocket(m, inp->inp_socket) != 0) {
+ error = ENOBUFS;
+ goto release;
+ }
#endif /*IPSEC*/
return (ip_output(m, inp->inp_options, &inp->inp_route,
Index: netinet6/ah_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ah_input.c,v
retrieving revision 1.15.2.4
diff -u -r1.15.2.4 ah_input.c
--- netinet6/ah_input.c 2000/10/02 23:41:31 1.15.2.4
+++ netinet6/ah_input.c 2001/02/02 01:47:51
@@ -382,7 +382,7 @@
}
/* was it transmitted over the IPsec tunnel SA? */
- if (ipsec4_tunnel_validate(ip, nxt, sav) && nxt == IPPROTO_IPV4) {
+ if (ipsec4_tunnel_validate(ip, nxt, sav)) {
/*
* strip off all the headers that precedes AH.
* IP xx AH IP' payload -> IP' payload
@@ -454,6 +454,11 @@
#endif
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
+ ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
+ ipsecstat.in_nomem++;
+ goto fail;
+ }
s = splimp();
if (IF_QFULL(&ipintrq)) {
@@ -536,6 +541,10 @@
/* forget about IP hdr checksum, the check has already been passed */
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
+ ipsecstat.in_nomem++;
+ goto fail;
+ }
if (nxt != IPPROTO_DONE)
(*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
@@ -797,7 +806,7 @@
}
/* was it transmitted over the IPsec tunnel SA? */
- if (ipsec6_tunnel_validate(ip6, nxt, sav) && nxt == IPPROTO_IPV6) {
+ if (ipsec6_tunnel_validate(ip6, nxt, sav)) {
/*
* strip off all the headers that precedes AH.
* IP6 xx AH IP6' payload -> IP6' payload
@@ -859,6 +868,11 @@
#endif
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
+ ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
+ ipsec6stat.in_nomem++;
+ goto fail;
+ }
s = splimp();
if (IF_QFULL(&ip6intrq)) {
@@ -937,6 +951,10 @@
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
+ ipsec6stat.in_nomem++;
+ goto fail;
+ }
}
*offp = off;
Index: netinet6/esp_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/esp_input.c,v
retrieving revision 1.1.1.1.2.5
diff -u -r1.1.1.1.2.5 esp_input.c
--- netinet6/esp_input.c 2000/10/02 23:41:32 1.1.1.1.2.5
+++ netinet6/esp_input.c 2001/02/02 01:47:53
@@ -380,6 +380,11 @@
#endif
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
+ ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
+ ipsecstat.in_nomem++;
+ goto bad;
+ }
s = splimp();
if (IF_QFULL(&ipintrq)) {
@@ -417,6 +422,10 @@
ip->ip_p = nxt;
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
+ ipsecstat.in_nomem++;
+ goto bad;
+ }
if (nxt != IPPROTO_DONE)
(*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
@@ -736,6 +745,11 @@
#endif
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
+ ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
+ ipsec6stat.in_nomem++;
+ goto bad;
+ }
s = splimp();
if (IF_QFULL(&ip6intrq)) {
@@ -839,6 +853,10 @@
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
+ ipsec6stat.in_nomem++;
+ goto bad;
+ }
}
*offp = off;
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/icmp6.c,v
retrieving revision 1.33.2.6
diff -u -r1.33.2.6 icmp6.c
--- netinet6/icmp6.c 2001/01/26 01:18:25 1.33.2.6
+++ netinet6/icmp6.c 2001/02/02 01:47:57
@@ -1862,7 +1862,7 @@
m->m_flags &= ~(M_BCAST|M_MCAST);
#ifdef IPSEC
/* Don't lookup socket */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif /*IPSEC*/
#ifdef COMPAT_RFC1885
@@ -2377,7 +2377,7 @@
/* send the packet to outside... */
#ifdef IPSEC
/* Don't lookup socket */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif /*IPSEC*/
ip6_output(m, NULL, NULL, 0, NULL, &outif);
if (outif) {
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_output.c,v
retrieving revision 1.23
diff -u -r1.23 ip6_output.c
--- netinet6/ip6_output.c 2000/06/20 02:24:42 1.23
+++ netinet6/ip6_output.c 2001/02/02 01:48:01
@@ -170,7 +170,7 @@
/* for AH processing. stupid to have "socket" variable in IP layer... */
so = ipsec_getsocket(m);
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
ip6 = mtod(m, struct ip6_hdr *);
#endif /* IPSEC */
@@ -874,6 +874,10 @@
}
}
#endif
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
+#endif
#ifdef OLDIP6OUTPUT
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
@@ -1005,6 +1009,10 @@
m->m_pkthdr.len;
}
}
+#endif
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
#endif
#ifdef OLDIP6OUTPUT
error = (*ifp->if_output)(ifp, m,
Index: netinet6/ipcomp_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ipcomp_input.c,v
retrieving revision 1.10.4.2
diff -u -r1.10.4.2 ipcomp_input.c
--- netinet6/ipcomp_input.c 2000/10/02 23:41:32 1.10.4.2
+++ netinet6/ipcomp_input.c 2001/02/02 01:48:02
@@ -1,5 +1,5 @@
/* $NetBSD: ipcomp_input.c,v 1.10.4.2 2000/10/02 23:41:32 itojun Exp $ */
-/* $KAME: ipcomp_input.c,v 1.19 2000/10/01 12:37:20 itojun Exp $ */
+/* $KAME: ipcomp_input.c,v 1.22 2001/01/23 08:59:37 itojun Exp $ */
/*
* Copyright (C) 1999 WIDE Project.
@@ -209,6 +209,10 @@
if (sav) {
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
+ ipsecstat.in_nomem++;
+ goto fail;
+ }
key_freesav(sav);
sav = NULL;
}
@@ -320,6 +324,10 @@
if (sav) {
key_sa_recordxfer(sav, m);
+ if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
+ ipsec6stat.in_nomem++;
+ goto fail;
+ }
key_freesav(sav);
sav = NULL;
}
Index: netinet6/ipsec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ipsec.c,v
retrieving revision 1.23.2.3
diff -u -r1.23.2.3 ipsec.c
--- netinet6/ipsec.c 2000/11/10 01:15:26 1.23.2.3
+++ netinet6/ipsec.c 2001/02/02 01:48:07
@@ -1,5 +1,5 @@
/* $NetBSD: ipsec.c,v 1.23.2.3 2000/11/10 01:15:26 tv Exp $ */
-/* $KAME: ipsec.c,v 1.83 2000/11/09 17:45:30 itojun Exp $ */
+/* $KAME: ipsec.c,v 1.87 2001/01/23 08:59:38 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -152,6 +152,9 @@
#ifdef INET6
static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *));
#endif
+static struct mbuf *ipsec_addaux __P((struct mbuf *));
+static struct mbuf *ipsec_findaux __P((struct mbuf *));
+static void ipsec_optaux __P((struct mbuf *, struct mbuf *));
/*
* For OUTBOUND packet having a socket. Searching SPD for packet,
@@ -3258,27 +3261,78 @@
return(NULL);
}
+static struct mbuf *
+ipsec_addaux(m)
+ struct mbuf *m;
+{
+ struct mbuf *n;
+
+ n = m_aux_find(m, AF_INET, IPPROTO_ESP);
+ if (!n)
+ n = m_aux_add(m, AF_INET, IPPROTO_ESP);
+ if (!n)
+ return n; /* ENOBUFS */
+ n->m_len = sizeof(struct socket *);
+ bzero(mtod(n, void *), n->m_len);
+ return n;
+}
+
+static struct mbuf *
+ipsec_findaux(m)
+ struct mbuf *m;
+{
+ struct mbuf *n;
+
+ n = m_aux_find(m, AF_INET, IPPROTO_ESP);
+#ifdef DIAGNOSTIC
+ if (n && n->m_len < sizeof(struct socket *))
+ panic("invalid ipsec m_aux");
+#endif
+ return n;
+}
+
void
+ipsec_delaux(m)
+ struct mbuf *m;
+{
+ struct mbuf *n;
+
+ n = m_aux_find(m, AF_INET, IPPROTO_ESP);
+ if (n)
+ m_aux_delete(m, n);
+}
+
+/* if the aux buffer is unnecessary, nuke it. */
+static void
+ipsec_optaux(m, n)
+ struct mbuf *m;
+ struct mbuf *n;
+{
+
+ if (!n)
+ return;
+ if (n->m_len == sizeof(struct socket *) && !*mtod(n, struct socket **))
+ ipsec_delaux(m);
+}
+
+int
ipsec_setsocket(m, so)
struct mbuf *m;
struct socket *so;
{
struct mbuf *n;
- n = m_aux_find(m, AF_INET, IPPROTO_ESP);
- if (so && !n)
- n = m_aux_add(m, AF_INET, IPPROTO_ESP);
- if (n) {
- if (so) {
- *mtod(n, struct socket **) = so;
- /*
- * XXX think again about it when we put decryption
- * histrory into aux mbuf
- */
- n->m_len = sizeof(struct socket *);
- } else
- m_aux_delete(m, n);
- }
+ /* if so == NULL, don't insist on getting the aux mbuf */
+ if (so) {
+ n = ipsec_addaux(m);
+ if (!n)
+ return ENOBUFS;
+ } else
+ n = ipsec_findaux(m);
+ if (n && n->m_len >= sizeof(struct socket *))
+ *mtod(n, struct socket **) = so;
+ ipsec_optaux(m, n);
+ return 0;
}
struct socket *
@@ -3287,11 +3341,68 @@
{
struct mbuf *n;
- n = m_aux_find(m, AF_INET, IPPROTO_ESP);
+ n = ipsec_findaux(m);
if (n && n->m_len >= sizeof(struct socket *))
return *mtod(n, struct socket **);
else
return NULL;
+}
+
+int
+ipsec_addhist(m, proto, spi)
+ struct mbuf *m;
+ int proto;
+ u_int32_t spi;
+{
+ struct mbuf *n;
+ struct ipsec_history *p;
+
+ n = ipsec_addaux(m);
+ if (!n)
+ return ENOBUFS;
+ if (M_TRAILINGSPACE(n) < sizeof(*p))
+ return ENOSPC; /*XXX*/
+ p = (struct ipsec_history *)(mtod(n, caddr_t) + n->m_len);
+ n->m_len += sizeof(*p);
+ bzero(p, sizeof(*p));
+ p->ih_proto = proto;
+ p->ih_spi = spi;
+ return 0;
+}
+
+struct ipsec_history *
+ipsec_gethist(m, lenp)
+ struct mbuf *m;
+ int *lenp;
+{
+ struct mbuf *n;
+ int l;
+
+ n = ipsec_findaux(m);
+ if (!n)
+ return NULL;
+ l = n->m_len;
+ if (sizeof(struct socket *) > l)
+ return NULL;
+ if ((l - sizeof(struct socket *)) % sizeof(struct ipsec_history))
+ return NULL;
+ /* XXX does it make more sense to divide by sizeof(ipsec_history)? */
+ if (lenp)
+ *lenp = l - sizeof(struct socket *);
+ return (struct ipsec_history *)
+ (mtod(n, caddr_t) + sizeof(struct socket *));
+}
+
+void
+ipsec_clearhist(m)
+ struct mbuf *m;
+{
+ struct mbuf *n;
+
+ n = ipsec_findaux(m);
+ if ((n) && n->m_len > sizeof(struct socket *))
+ n->m_len = sizeof(struct socket *);
+ ipsec_optaux(m, n);
}
/*
Index: netinet6/ipsec.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ipsec.h,v
retrieving revision 1.14.2.2
diff -u -r1.14.2.2 ipsec.h
--- netinet6/ipsec.h 2000/09/29 06:42:43 1.14.2.2
+++ netinet6/ipsec.h 2001/02/02 01:48:08
@@ -261,6 +261,11 @@
struct sockaddr *dst;
};
+struct ipsec_history {
+ int ih_proto;
+ u_int32_t ih_spi;
+};
+
extern int ipsec_debug;
#ifdef INET
@@ -370,8 +375,12 @@
struct secasvar *));
#endif
extern struct mbuf *ipsec_copypkt __P((struct mbuf *));
-extern void ipsec_setsocket __P((struct mbuf *, struct socket *));
+extern void ipsec_delaux __P((struct mbuf *));
+extern int ipsec_setsocket __P((struct mbuf *, struct socket *));
extern struct socket *ipsec_getsocket __P((struct mbuf *));
+extern int ipsec_addhist __P((struct mbuf *, int, u_int32_t));
+extern struct ipsec_history *ipsec_gethist __P((struct mbuf *, int *));
+extern void ipsec_clearhist __P((struct mbuf *));
extern int ipsec_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
extern int ipsec6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.22
diff -u -r1.22 nd6_nbr.c
--- netinet6/nd6_nbr.c 2000/05/19 01:40:19 1.22
+++ netinet6/nd6_nbr.c 2001/02/02 01:48:11
@@ -1,5 +1,5 @@
/* $NetBSD: nd6_nbr.c,v 1.22 2000/05/19 01:40:19 itojun Exp $ */
-/* $KAME: nd6_nbr.c,v 1.36 2000/05/17 12:35:59 jinmei Exp $ */
+/* $KAME: nd6_nbr.c,v 1.51 2001/01/20 17:27:00 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -493,7 +493,7 @@
#ifdef IPSEC
/* Don't lookup socket */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif);
if (outif) {
@@ -913,7 +913,7 @@
#ifdef IPSEC
/* Don't lookup socket */
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
ip6_output(m, NULL, NULL, 0, &im6o, &outif);
if (outif) {
Index: netinet6/raw_ip6.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/raw_ip6.c,v
retrieving revision 1.23
diff -u -r1.23 raw_ip6.c
--- netinet6/raw_ip6.c 2000/05/29 00:03:18 1.23
+++ netinet6/raw_ip6.c 2001/02/02 01:48:12
@@ -458,6 +458,13 @@
*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
}
+#ifdef IPSEC
+ if (ipsec_setsocket(m, so) != 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+#endif /*IPSEC*/
+
error = ip6_output(m, optp, &in6p->in6p_route, 0, in6p->in6p_moptions,
&oifp);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
Index: netinet6/udp6_usrreq.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.30.2.2
diff -u -r1.30.2.2 udp6_usrreq.c
--- netinet6/udp6_usrreq.c 2000/11/10 00:13:30 1.30.2.2
+++ netinet6/udp6_usrreq.c 2001/02/02 01:48:14
@@ -733,7 +733,10 @@
udp6stat.udp6s_opackets++;
#ifdef IPSEC
- ipsec_setsocket(m, in6p->in6p_socket);
+ if (ipsec_setsocket(m, in6p->in6p_socket) != 0) {
+ error = ENOBUFS;
+ goto release;
+ }
#endif /*IPSEC*/
error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
0, in6p->in6p_moptions, NULL);
@@ -761,7 +764,7 @@
udpstat.udps_opackets++;
#ifdef IPSEC
- ipsec_setsocket(m, NULL); /*XXX*/
+ (void)ipsec_setsocket(m, NULL); /*XXX*/
#endif /*IPSEC*/
error = ip_output(m, NULL, &in6p->in6p_route, 0 /*XXX*/);
break;