diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-08-13 09:52:55 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-08-13 09:52:55 +0000 |
commit | 2621af2505e773753c88c2ee2ecbc598f166228c (patch) | |
tree | 862e2bae91c38687ace999cbb724588cfbae62c9 | |
parent | d05fc702c277cc4b4646d19d628003b3aef81643 (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.9 | 9 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 92 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 6 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 5 |
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_ */ |