From owner-p4-projects@FreeBSD.ORG Tue Aug 26 16:43:04 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id A4C1C16A4C1; Tue, 26 Aug 2003 16:43:04 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 688D016A4BF for ; Tue, 26 Aug 2003 16:43:04 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id E556343FDF for ; Tue, 26 Aug 2003 16:43:02 -0700 (PDT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h7QNh20U022737 for ; Tue, 26 Aug 2003 16:43:02 -0700 (PDT) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h7QNh2Pq022731 for perforce@freebsd.org; Tue, 26 Aug 2003 16:43:02 -0700 (PDT) Date: Tue, 26 Aug 2003 16:43:02 -0700 (PDT) Message-Id: <200308262343.h7QNh2Pq022731@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 36994 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Aug 2003 23:43:05 -0000 http://perforce.freebsd.org/chv.cgi?CH=36994 Change 36994 by sam@sam_ebb on 2003/08/26 16:42:07 o lock divert sockets a la udp, et. al. o move divsrc global to a stack variable instead of locking it's use o replace cr_canseesocket with prison_xinpcb to correct socket visibility check in sysctl o wire the sysctl buffer in the scan request a la everyone else Affected files ... .. //depot/projects/netperf/sys/netinet/ip_divert.c#2 edit Differences ... ==== //depot/projects/netperf/sys/netinet/ip_divert.c#2 (text+ko) ==== @@ -111,9 +111,6 @@ static u_long div_sendspace = DIVSNDQ; /* XXX sysctl ? */ static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */ -/* Optimization: have this preinitialized */ -static struct sockaddr_in divsrc = { sizeof(divsrc), AF_INET }; - /* * Initialize divert connection block queue. */ @@ -159,12 +156,11 @@ struct inpcb *inp; struct socket *sa; u_int16_t nport; + struct sockaddr_in divsrc; /* Sanity check */ KASSERT(port != 0, ("%s: port=0", __func__)); - divsrc.sin_port = rule; /* record matching rule */ - /* Assure header */ if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == 0) @@ -175,7 +171,10 @@ * Record receive interface address, if any. * But only for incoming packets. */ - divsrc.sin_addr.s_addr = 0; + bzero(&divsrc, sizeof(divsrc)); + divsrc.sin_len = sizeof(divsrc); + divsrc.sin_family = AF_INET; + divsrc.sin_port = rule; /* record matching rule */ if (incoming) { struct ifaddr *ifa; @@ -196,7 +195,6 @@ /* * Record the incoming interface name whenever we have one. */ - bzero(&divsrc.sin_zero, sizeof(divsrc.sin_zero)); if (m->m_pkthdr.rcvif) { /* * Hide the actual interface name in there in the @@ -224,17 +222,25 @@ /* Put packet on socket queue, if any */ sa = NULL; nport = htons((u_int16_t)port); + INP_INFO_RLOCK(&divcbinfo); LIST_FOREACH(inp, &divcb, inp_list) { - if (inp->inp_lport == nport) + INP_LOCK(inp); + /* XXX why does only one socket match? */ + if (inp->inp_lport == nport) { sa = inp->inp_socket; + if (sbappendaddr(&sa->so_rcv, + (struct sockaddr *)&divsrc, m, + (struct mbuf *)0) == 0) + sa = NULL; /* force mbuf reclaim below */ + else + sorwakeup(sa); + INP_UNLOCK(inp); + break; + } + INP_UNLOCK(inp); } - if (sa) { - if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, - m, (struct mbuf *)0) == 0) - m_freem(m); - else - sorwakeup(sa); - } else { + INP_INFO_RUNLOCK(&divcbinfo); + if (sa == NULL) { m_freem(m); ipstat.ips_noproto++; ipstat.ips_delivered--; @@ -349,28 +355,37 @@ div_attach(struct socket *so, int proto, struct thread *td) { struct inpcb *inp; - int error, s; + int error; + INP_INFO_WLOCK(&divcbinfo); inp = sotoinpcb(so); - if (inp) - panic("div_attach"); - if (td && (error = suser(td)) != 0) + if (inp != 0) { + INP_INFO_WUNLOCK(&divcbinfo); + return EINVAL; + } + if (td && (error = suser(td)) != 0) { + INP_INFO_WUNLOCK(&divcbinfo); return error; - + } error = soreserve(so, div_sendspace, div_recvspace); - if (error) + if (error) { + INP_INFO_WUNLOCK(&divcbinfo); return error; - s = splnet(); + } error = in_pcballoc(so, &divcbinfo, td); - splx(s); - if (error) + if (error) { + INP_INFO_WUNLOCK(&divcbinfo); return error; + } inp = (struct inpcb *)so->so_pcb; + INP_LOCK(inp); + INP_INFO_WUNLOCK(&divcbinfo); inp->inp_ip_p = proto; inp->inp_vflag |= INP_IPV4; inp->inp_flags |= INP_HDRINCL; /* The socket is always "connected" because we always know "where" to send the packet */ + INP_UNLOCK(inp); so->so_state |= SS_ISCONNECTED; return 0; } @@ -380,10 +395,15 @@ { struct inpcb *inp; + INP_INFO_WLOCK(&divcbinfo); inp = sotoinpcb(so); - if (inp == 0) - panic("div_detach"); + if (inp == 0) { + INP_INFO_WUNLOCK(&divcbinfo); + return EINVAL; + } + INP_LOCK(inp); in_pcbdetach(inp); + INP_INFO_WUNLOCK(&divcbinfo); return 0; } @@ -406,11 +426,14 @@ div_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; - int s; int error; - s = splnet(); + INP_INFO_WLOCK(&divcbinfo); inp = sotoinpcb(so); + if (inp == 0) { + INP_INFO_WUNLOCK(&divcbinfo); + return EINVAL; + } /* in_pcbbind assumes that nam is a sockaddr_in * and in_pcbbind requires a valid address. Since divert * sockets don't we need to make sure the address is @@ -422,9 +445,11 @@ error = EAFNOSUPPORT; else { ((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY; + INP_LOCK(inp); error = in_pcbbind(inp, nam, td); + INP_UNLOCK(inp); } - splx(s); + INP_INFO_WUNLOCK(&divcbinfo); return error; } @@ -454,7 +479,7 @@ static int div_pcblist(SYSCTL_HANDLER_ARGS) { - int error, i, n, s; + int error, i, n; struct inpcb *inp, **inp_list; inp_gen_t gencnt; struct xinpgen xig; @@ -476,10 +501,12 @@ /* * OK, now we're committed to doing something. */ - s = splnet(); + INP_INFO_RLOCK(&divcbinfo); gencnt = divcbinfo.ipi_gencnt; n = divcbinfo.ipi_count; - splx(s); + INP_INFO_RUNLOCK(&divcbinfo); + + sysctl_wire_old_buffer(req, 2 * sizeof(xig) + n*sizeof(struct xinpcb)); xig.xig_len = sizeof xig; xig.xig_count = n; @@ -493,13 +520,16 @@ if (inp_list == 0) return ENOMEM; - s = splnet(); + INP_INFO_RLOCK(&divcbinfo); for (inp = LIST_FIRST(divcbinfo.listhead), i = 0; inp && i < n; inp = LIST_NEXT(inp, inp_list)) { - if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->td, inp)) + INP_LOCK(inp); + if (inp->inp_gencnt <= gencnt && + cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) inp_list[i++] = inp; + INP_UNLOCK(inp); } - splx(s); + INP_INFO_RUNLOCK(&divcbinfo); n = i; error = 0; @@ -523,11 +553,11 @@ * while we were processing this request, and it * might be necessary to retry. */ - s = splnet(); + INP_INFO_RLOCK(&divcbinfo); xig.xig_gen = divcbinfo.ipi_gencnt; xig.xig_sogen = so_gencnt; xig.xig_count = divcbinfo.ipi_count; - splx(s); + INP_INFO_RUNLOCK(&divcbinfo); error = SYSCTL_OUT(req, &xig, sizeof xig); } free(inp_list, M_TEMP);