summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-07-18 10:47:07 +0000
committerrwatson <rwatson@FreeBSD.org>2008-07-18 10:47:07 +0000
commit4efb6d2a37b496ded581b12ed193e4ebe091076a (patch)
tree5cc7a11f44218d9193298934b3d1154f637e70df /sys/netinet
parent6dfc39c2b65e071af0416aab8ac653dede74f1b4 (diff)
downloadFreeBSD-src-4efb6d2a37b496ded581b12ed193e4ebe091076a.zip
FreeBSD-src-4efb6d2a37b496ded581b12ed193e4ebe091076a.tar.gz
Eliminate use of the global ripsrc which was being used to pass address
information from rip_input() to rip_append(). Instead, pass the source address for an IP datagram to rip_append() using a stack-allocated sockaddr_in, similar to udp_input() and udp_append(). Prior to the move to rwlocks for inpcbinfo, this was not a problem, as use of the global was synchronized using the ripcbinfo mutex, but with read-locking there is the potential for a race during concurrent receive. This problem is not present in the IPv6 raw IP socket code, which already used a stack variable for the address. Spotted by: mav MFC after: 1 week (before inpcbinfo rwlock changes)
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/raw_ip.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 902fc5d..ea81cdc 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -153,10 +153,9 @@ rip_init(void)
EVENTHANDLER_PRI_ANY);
}
-static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
-
static int
-rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n)
+rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
+ struct sockaddr_in *ripsrc)
{
int policyfail = 0;
@@ -185,7 +184,7 @@ rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n)
ip_savecontrol(last, &opts, ip, n);
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv,
- (struct sockaddr *)&ripsrc, n, opts) == 0) {
+ (struct sockaddr *)ripsrc, n, opts) == 0) {
/* should notify about lost packet */
m_freem(n);
if (opts)
@@ -208,10 +207,14 @@ rip_input(struct mbuf *m, int off)
struct ip *ip = mtod(m, struct ip *);
int proto = ip->ip_p;
struct inpcb *inp, *last;
+ struct sockaddr_in ripsrc;
- INP_INFO_RLOCK(&ripcbinfo);
+ bzero(&ripsrc, sizeof(ripsrc));
+ ripsrc.sin_len = sizeof(ripsrc);
+ ripsrc.sin_family = AF_INET;
ripsrc.sin_addr = ip->ip_src;
last = NULL;
+ INP_INFO_RLOCK(&ripcbinfo);
LIST_FOREACH(inp, &ripcb, inp_list) {
INP_RLOCK(inp);
if (inp->inp_ip_p && inp->inp_ip_p != proto) {
@@ -238,14 +241,14 @@ rip_input(struct mbuf *m, int off)
n = m_copy(m, 0, (int)M_COPYALL);
if (n != NULL)
- (void) rip_append(last, ip, n);
+ (void) rip_append(last, ip, n, &ripsrc);
/* XXX count dropped packet */
INP_RUNLOCK(last);
}
last = inp;
}
if (last != NULL) {
- if (rip_append(last, ip, m) != 0)
+ if (rip_append(last, ip, m, &ripsrc) != 0)
ipstat.ips_delivered--;
INP_RUNLOCK(last);
} else {
OpenPOWER on IntegriCloud