Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Don't use a single global variable to store source route...
details: https://anonhg.NetBSD.org/src/rev/af31e6a98e1d
branches: trunk
changeset: 352423:af31e6a98e1d
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Fri Mar 31 06:49:44 2017 +0000
description:
Don't use a single global variable to store source route information for multiple incoming packets
It's not MP-safe. So use a m_tag to store the information instead.
Pointed out by knakahara@
The fix is from OpenBSD (originally fixed in FreeBSD)
diffstat:
sys/netinet/ip_icmp.c | 6 +-
sys/netinet/ip_input.c | 82 ++++++++++++++++++++++++++++--------------------
sys/netinet/ip_var.h | 4 +-
sys/netinet/tcp_input.c | 8 ++--
sys/sys/mbuf.h | 3 +-
5 files changed, 59 insertions(+), 44 deletions(-)
diffs (273 lines):
diff -r 1cedbabcb046 -r af31e6a98e1d sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_icmp.c Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_icmp.c,v 1.160 2017/03/06 07:31:15 ozaki-r Exp $ */
+/* $NetBSD: ip_icmp.c,v 1.161 2017/03/31 06:49:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -94,7 +94,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.160 2017/03/06 07:31:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.161 2017/03/31 06:49:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -888,7 +888,7 @@
* add on any record-route or timestamp options.
*/
cp = (u_char *) (ip + 1);
- if ((opts = ip_srcroute()) == NULL &&
+ if ((opts = ip_srcroute(m)) == NULL &&
(opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
MCLAIM(opts, m->m_owner);
opts->m_len = sizeof(struct in_addr);
diff -r 1cedbabcb046 -r af31e6a98e1d sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_input.c Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.353 2017/03/31 06:42:19 ozaki-r Exp $ */
+/* $NetBSD: ip_input.c,v 1.354 2017/03/31 06:49:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.353 2017/03/31 06:42:19 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.354 2017/03/31 06:49:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -253,25 +253,23 @@
#endif /* INET_CSUM_COUNTERS */
/*
- * 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.
*/
-
-static 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)];
+};
static int ip_drainwanted;
-static void save_rte(u_char *, struct in_addr);
+static void save_rte(struct mbuf *, u_char *, struct in_addr);
#ifdef MBUFTRACE
struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx");
@@ -664,7 +662,6 @@
* 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)) {
m = NULL;
goto out;
@@ -987,7 +984,7 @@
/*
* End of source route. Should be for us.
*/
- save_rte(cp, ip->ip_src);
+ save_rte(m, cp, ip->ip_src);
break;
}
/*
@@ -1226,16 +1223,25 @@
* up later by ip_srcroute if the receiver is interested.
*/
static 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];
- if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
+ if (olen > sizeof(isr->isr_hdr) + sizeof(isr->isr_routes))
+ return;
+
+ mtag = m_tag_get(PACKET_TAG_SRCROUTE, sizeof(*isr), M_NOWAIT);
+ if (mtag == NULL)
return;
- memcpy((void *)ip_srcrt.srcopt, (void *)option, olen);
- ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
- ip_srcrt.dst = dst;
+ isr = (struct ip_srcrt *)(mtag + 1);
+
+ memcpy(isr->isr_hdr, option, olen);
+ isr->isr_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
+ isr->isr_dst = dst;
+ m_tag_prepend(m, mtag);
}
/*
@@ -1244,36 +1250,43 @@
* 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)
+ 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)
+ if (m == NULL)
return NULL;
MCLAIM(m, &inetdomain.dom_mowner);
-#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;
/*
* 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--;
/*
* Copy option fields and padding (nop) to mbuf.
*/
- ip_srcrt.nop = IPOPT_NOP;
- ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
- memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop,
+ isr->isr_nop = IPOPT_NOP;
+ isr->isr_hdr[IPOPT_OFFSET] = IPOPT_MINOFF;
+ memmove(mtod(m, char *) + sizeof(struct in_addr), &isr->isr_nop,
OPTSIZ);
q = (struct in_addr *)(mtod(m, char *) +
sizeof(struct in_addr) + OPTSIZ);
@@ -1282,14 +1295,15 @@
* 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) {
*q++ = *p--;
}
/*
* Last hop goes to final destination.
*/
- *q = ip_srcrt.dst;
- return (m);
+ *q = isr->isr_dst;
+ m_tag_delete(m0, mtag);
+ return m;
}
const int inetctlerrmap[PRC_NCMDS] = {
diff -r 1cedbabcb046 -r af31e6a98e1d sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_var.h Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_var.h,v 1.118 2017/03/03 07:13:06 ozaki-r Exp $ */
+/* $NetBSD: ip_var.h,v 1.119 2017/03/31 06:49:44 ozaki-r Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -226,7 +226,7 @@
void ip_slowtimo(void);
void ip_fasttimo(void);
struct mbuf *
- ip_srcroute(void);
+ ip_srcroute(struct mbuf *);
int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
void ip_statinc(u_int);
void * rip_ctlinput(int, const struct sockaddr *, void *);
diff -r 1cedbabcb046 -r af31e6a98e1d sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/tcp_input.c Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tcp_input.c,v 1.355 2017/03/03 07:13:06 ozaki-r Exp $ */
+/* $NetBSD: tcp_input.c,v 1.356 2017/03/31 06:49:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -148,7 +148,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.355 2017/03/03 07:13:06 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.356 2017/03/31 06:49:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -4004,7 +4004,7 @@
if (inp) {
inp->inp_laddr = ((struct sockaddr_in *)dst)->sin_addr;
inp->inp_lport = ((struct sockaddr_in *)dst)->sin_port;
- inp->inp_options = ip_srcroute();
+ inp->inp_options = ip_srcroute(m);
in_pcbstate(inp, INP_BOUND);
if (inp->inp_options == NULL) {
inp->inp_options = sc->sc_ipopts;
@@ -4341,7 +4341,7 @@
/*
* Remember the IP options, if any.
*/
- ipopts = ip_srcroute();
+ ipopts = ip_srcroute(m);
break;
#endif
default:
diff -r 1cedbabcb046 -r af31e6a98e1d sys/sys/mbuf.h
--- a/sys/sys/mbuf.h Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/sys/mbuf.h Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mbuf.h,v 1.168 2017/02/07 02:36:48 ozaki-r Exp $ */
+/* $NetBSD: mbuf.h,v 1.169 2017/03/31 06:49:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
@@ -922,6 +922,7 @@
*/
#define PACKET_TAG_MPLS 29 /* Indicate it's for MPLS */
+#define PACKET_TAG_SRCROUTE 30 /* IPv4 source routing */
/*
* Return the number of bytes in the mbuf chain, m.
Home |
Main Index |
Thread Index |
Old Index