summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2013-08-13 09:52:55 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2013-08-13 09:52:55 +0000
commit2621af2505e773753c88c2ee2ecbc598f166228c (patch)
tree862e2bae91c38687ace999cbb724588cfbae62c9
parentd05fc702c277cc4b4646d19d628003b3aef81643 (diff)
When net.inet.ip.sourceroute is enable, store the source route
of incoming IPv4 packets with the SSRR or LSRR header option in a m_tag rather than in a single static entry. Use a new m_tag type, PACKET_TAG_SRCROUTE, for this and bump PACKET_TAG_MAXSIZE accordingly. Adapted from FreeBSD r135274 with inputs from bluhm@. ok bluhm@, mikeb@
-rw-r--r--share/man/man9/mbuf_tags.99
-rw-r--r--sys/netinet/ip_icmp.c4
-rw-r--r--sys/netinet/ip_input.c92
-rw-r--r--sys/netinet/ip_var.h4
-rw-r--r--sys/netinet/tcp_input.c6
-rw-r--r--sys/sys/mbuf.h5
6 files changed, 72 insertions, 48 deletions
diff --git a/share/man/man9/mbuf_tags.9 b/share/man/man9/mbuf_tags.9
index 9db0f98148f..cd0204c767d 100644
--- a/share/man/man9/mbuf_tags.9
+++ b/share/man/man9/mbuf_tags.9
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mbuf_tags.9,v 1.31 2013/07/17 20:21:54 schwarze Exp $
+.\" $OpenBSD: mbuf_tags.9,v 1.32 2013/08/13 09:52:53 mpi Exp $
.\"
.\" The author of this man page is Angelos D. Keromytis (angelos@cis.upenn.edu)
.\"
@@ -15,7 +15,7 @@
.\" MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
.\" PURPOSE.
.\"
-.Dd $Mdocdate: July 17 2013 $
+.Dd $Mdocdate: August 13 2013 $
.Dt MBUF_TAGS 9
.Os
.Sh NAME
@@ -184,6 +184,11 @@ Used by
to reassemble IPv6 fragments.
The tag contains a
.Va struct pf_fragment_tag .
+.It PACKET_TAG_SRCROUTE
+Used by the IPv4 stack to keep track of the source route of an incoming
+IP packet, in case a protocol wants to respond over the same route.
+The tag contains a
+.Va struct ip_srcrt .
.El
.Pp
.Fn m_tag_find
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index 91d8213b45e..4d427e201b5 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_icmp.c,v 1.104 2013/08/08 14:59:22 mpi Exp $ */
+/* $OpenBSD: ip_icmp.c,v 1.105 2013/08/13 09:52:53 mpi Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@@ -745,7 +745,7 @@ icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
* add on any record-route or timestamp options.
*/
cp = (u_char *) (ip + 1);
- if (op && (opts = ip_srcroute()) == 0 &&
+ if (op && (opts = ip_srcroute(m)) == NULL &&
(opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
opts->m_len = sizeof(struct in_addr);
mtod(opts, struct in_addr *)->s_addr = 0;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index da49a5ba33e..1b219001779 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.215 2013/07/31 15:41:51 mikeb Exp $ */
+/* $OpenBSD: ip_input.c,v 1.216 2013/08/13 09:52:53 mpi Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -143,21 +143,21 @@ inet_ntoa(ina)
}
/*
- * We need to save the IP options in case a protocol wants to respond
+ * Used to save the IP options in case a protocol wants to respond
* to an incoming packet over the same route if the packet got here
* using IP source routing. This allows connection establishment and
* maintenance when the remote end is on a network that is not known
* to us.
*/
-int ip_nhops = 0;
-static struct ip_srcrt {
- struct in_addr dst; /* final destination */
- char nop; /* one NOP to align */
- char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
- struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
-} ip_srcrt;
+struct ip_srcrt {
+ int isr_nhops; /* number of hops */
+ struct in_addr isr_dst; /* final destination */
+ char isr_nop; /* one NOP to align */
+ char isr_hdr[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN & OFFSET */
+ struct in_addr isr_routes[MAX_IPOPTLEN/sizeof(struct in_addr)];
+};
-void save_rte(u_char *, struct in_addr);
+void save_rte(struct mbuf *, u_char *, struct in_addr);
/*
* IP initialization: fill in IP protocol switch table.
@@ -363,7 +363,6 @@ ipv4_input(struct mbuf *m)
* error was detected (causing an icmp message
* to be sent and the original packet to be freed).
*/
- ip_nhops = 0; /* for source routed packets */
if (hlen > sizeof (struct ip) && ip_dooptions(m)) {
return;
}
@@ -1097,7 +1096,7 @@ ip_dooptions(struct mbuf *m)
/*
* End of source route. Should be for us.
*/
- save_rte(cp, ip->ip_src);
+ save_rte(m, cp, ip->ip_src);
break;
}
@@ -1266,20 +1265,29 @@ ip_rtaddr(struct in_addr dst, u_int rtableid)
* to be picked up later by ip_srcroute if the receiver is interested.
*/
void
-save_rte(u_char *option, struct in_addr dst)
+save_rte(struct mbuf *m, u_char *option, struct in_addr dst)
{
+ struct ip_srcrt *isr;
+ struct m_tag *mtag;
unsigned olen;
olen = option[IPOPT_OLEN];
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf("save_rte: olen %d\n", olen);
-#endif /* 0 */
- if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
+ printf("%s: olen %d\n", __func__, olen);
+#endif
+ if (olen > sizeof(isr->isr_hdr) + sizeof(isr->isr_routes))
return;
- bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
- ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
- ip_srcrt.dst = dst;
+
+ mtag = m_tag_get(PACKET_TAG_SRCROUTE, sizeof(*isr), M_NOWAIT);
+ if (mtag == NULL)
+ return;
+ isr = (struct ip_srcrt *)(mtag + 1);
+
+ bcopy(option, isr->isr_hdr, olen);
+ isr->isr_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
+ isr->isr_dst = dst;
+ m_tag_prepend(m, mtag);
}
/*
@@ -1288,31 +1296,41 @@ save_rte(u_char *option, struct in_addr dst)
* The first hop is placed before the options, will be removed later.
*/
struct mbuf *
-ip_srcroute(void)
+ip_srcroute(struct mbuf *m0)
{
struct in_addr *p, *q;
struct mbuf *m;
+ struct ip_srcrt *isr;
+ struct m_tag *mtag;
- if (ip_nhops == 0)
- return ((struct mbuf *)0);
+ if (!ip_dosourceroute)
+ return (NULL);
+
+ mtag = m_tag_find(m0, PACKET_TAG_SRCROUTE, NULL);
+ if (mtag == NULL)
+ return (NULL);
+ isr = (struct ip_srcrt *)(mtag + 1);
+
+ if (isr->isr_nhops == 0)
+ return (NULL);
m = m_get(M_DONTWAIT, MT_SOOPTS);
- if (m == 0)
- return ((struct mbuf *)0);
+ if (m == NULL)
+ return (NULL);
-#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
+#define OPTSIZ (sizeof(isr->isr_nop) + sizeof(isr->isr_hdr))
- /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
- m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
- OPTSIZ;
+ /* length is (nhops+1)*sizeof(addr) + sizeof(nop + header) */
+ m->m_len = (isr->isr_nhops + 1) * sizeof(struct in_addr) + OPTSIZ;
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
+ printf("%s: nhops %d mlen %d", __func__, isr->isr_nhops,
+ m->m_len);
#endif
/*
* First save first hop for return route
*/
- p = &ip_srcrt.route[ip_nhops - 1];
+ p = &(isr->isr_routes[isr->isr_nhops - 1]);
*(mtod(m, struct in_addr *)) = *p--;
#ifdef DIAGNOSTIC
if (ipprintfs)
@@ -1322,10 +1340,9 @@ ip_srcroute(void)
/*
* Copy option fields and padding (nop) to mbuf.
*/
- ip_srcrt.nop = IPOPT_NOP;
- ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
- bcopy((caddr_t)&ip_srcrt.nop,
- mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
+ isr->isr_nop = IPOPT_NOP;
+ isr->isr_hdr[IPOPT_OFFSET] = IPOPT_MINOFF;
+ bcopy(&isr->isr_nop, mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
q = (struct in_addr *)(mtod(m, caddr_t) +
sizeof(struct in_addr) + OPTSIZ);
#undef OPTSIZ
@@ -1333,7 +1350,7 @@ ip_srcroute(void)
* Record return path as an IP source route,
* reversing the path (pointers are now aligned).
*/
- while (p >= ip_srcrt.route) {
+ while (p >= isr->isr_routes) {
#ifdef DIAGNOSTIC
if (ipprintfs)
printf(" %x", ntohl(q->s_addr));
@@ -1343,11 +1360,12 @@ ip_srcroute(void)
/*
* Last hop goes to final destination.
*/
- *q = ip_srcrt.dst;
+ *q = isr->isr_dst;
#ifdef DIAGNOSTIC
if (ipprintfs)
printf(" %x\n", ntohl(q->s_addr));
#endif
+ m_tag_delete(m0, (struct m_tag *)isr);
return (m);
}
@@ -1706,7 +1724,7 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
}
/* ip_srcroute doesn't do what we want here, need to fix */
if (inp->inp_flags & INP_RECVRETOPTS) {
- *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
+ *mp = sbcreatecontrol((caddr_t) ip_srcroute(m),
sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
if (*mp)
mp = &(*mp)->m_next;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 9103b99d3bf..c111109cfd8 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.45 2013/04/10 08:50:59 mpi Exp $ */
+/* $OpenBSD: ip_var.h,v 1.46 2013/08/13 09:52:53 mpi Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -196,7 +196,7 @@ u_int16_t
int ip_setmoptions(int, struct ip_moptions **, struct mbuf *, u_int);
void ip_slowtimo(void);
struct mbuf *
- ip_srcroute(void);
+ ip_srcroute(struct mbuf *);
void ip_stripoptions(struct mbuf *, struct mbuf *);
int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 734ae46c916..5dd996f336d 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.266 2013/07/31 15:41:52 mikeb Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.267 2013/08/13 09:52:53 mpi Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -3769,7 +3769,7 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
case AF_INET:
inp->inp_laddr = ((struct sockaddr_in *)dst)->sin_addr;
- inp->inp_options = ip_srcroute();
+ inp->inp_options = ip_srcroute(m);
if (inp->inp_options == NULL) {
inp->inp_options = sc->sc_ipopts;
sc->sc_ipopts = NULL;
@@ -4043,7 +4043,7 @@ syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
/*
* Remember the IP options, if any.
*/
- ipopts = ip_srcroute();
+ ipopts = ip_srcroute(m);
break;
#endif
default:
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index d885c7fb88c..c6eaba98c13 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.165 2013/07/06 02:44:23 brad Exp $ */
+/* $OpenBSD: mbuf.h,v 1.166 2013/08/13 09:52:54 mpi Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -454,6 +454,7 @@ struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
#define PACKET_TAG_PF_DIVERT 0x0200 /* pf(4) diverted packet */
#define PACKET_TAG_PIPEX 0x0400 /* pipex session cache */
#define PACKET_TAG_PF_REASSEMBLED 0x0800 /* pf reassembled ipv6 packet */
+#define PACKET_TAG_SRCROUTE 0x1000 /* IPv4 source routing options */
/*
* Maximum tag payload length (that is excluding the m_tag structure).
@@ -461,7 +462,7 @@ struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
* length for an existing packet tag type or when adding a new one that
* has payload larger than the value below.
*/
-#define PACKET_TAG_MAXSIZE 40
+#define PACKET_TAG_MAXSIZE 52
#endif /* _KERNEL */
#endif /* _SYS_MBUF_H_ */