X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/79e0ea5deab8f2a2db706a3a448d2363de65865c..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/sys/net/rtsock.c diff --git a/usr/src/sys/net/rtsock.c b/usr/src/sys/net/rtsock.c index 8bf58cd527..a64719bf8b 100644 --- a/usr/src/sys/net/rtsock.c +++ b/usr/src/sys/net/rtsock.c @@ -1,31 +1,45 @@ /* - * Copyright (c) 1988 Regents of the University of California. + * Copyright (c) 1988, 1991 Regents of the University of California. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * @(#)rtsock.c 7.8 (Berkeley) %G% + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rtsock.c 7.18 (Berkeley) 6/27/91 */ #include "param.h" #include "mbuf.h" -#include "user.h" #include "proc.h" #include "socket.h" #include "socketvar.h" #include "domain.h" #include "protosw.h" -#include "errno.h" #include "af.h" #include "if.h" @@ -34,8 +48,8 @@ #include "machine/mtpr.h" -struct sockaddr route_dst = { 0, PF_ROUTE, }; -struct sockaddr route_src = { 0, PF_ROUTE, }; +struct sockaddr route_dst = { 2, PF_ROUTE, }; +struct sockaddr route_src = { 2, PF_ROUTE, }; struct sockproto route_proto = { PF_ROUTE, }; /*ARGSUSED*/ @@ -46,6 +60,7 @@ route_usrreq(so, req, m, nam, control) { register int error = 0; register struct rawcb *rp = sotorawcb(so); + int s; if (req == PRU_ATTACH) { MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); if (so->so_pcb = (caddr_t)rp) @@ -62,12 +77,14 @@ route_usrreq(so, req, m, nam, control) route_cb.iso_count--; route_cb.any_count--; } + s = splnet(); error = raw_usrreq(so, req, m, nam, control); rp = sotorawcb(so); if (req == PRU_ATTACH && rp) { int af = rp->rcb_proto.sp_protocol; if (error) { free((caddr_t)rp, M_PCB); + splx(s); return (error); } if (af == AF_INET) @@ -79,10 +96,14 @@ route_usrreq(so, req, m, nam, control) rp->rcb_faddr = &route_src; route_cb.any_count++; soisconnected(so); + so->so_options |= SO_USELOOPBACK; } + splx(s); return (error); } -#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) /*ARGSUSED*/ route_output(m, so) @@ -93,8 +114,12 @@ route_output(m, so) register struct rtentry *rt = 0; struct rtentry *saved_nrt = 0; struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *genmask = 0; + struct sockaddr *ifpaddr = 0, *ifaaddr = 0; caddr_t cp, lim; int len, error = 0; + struct ifnet *ifp = 0; + struct ifaddr *ifa = 0; + struct ifaddr *ifaof_ifpforaddr(), *ifa_ifwithroute(); #define senderr(e) { error = e; goto flush;} if (m == 0 || m->m_len < sizeof(long)) @@ -104,8 +129,8 @@ route_output(m, so) if ((m->m_flags & M_PKTHDR) == 0) panic("route_output"); len = m->m_pkthdr.len; - rtm = mtod(m, struct rt_msghdr *); - if (len < rtm->rtm_msglen) + if (len < sizeof(*rtm) || + len != mtod(m, struct rt_msghdr *)->rtm_msglen) senderr(EINVAL); R_Malloc(rtm, struct rt_msghdr *, len); if (rtm == 0) @@ -113,28 +138,38 @@ route_output(m, so) m_copydata(m, 0, len, (caddr_t)rtm); if (rtm->rtm_version != RTM_VERSION) senderr(EPROTONOSUPPORT); - rtm->rtm_pid = u.u_procp->p_pid; + rtm->rtm_pid = curproc->p_pid; lim = len + (caddr_t) rtm; cp = (caddr_t) (rtm + 1); if (rtm->rtm_addrs & RTA_DST) { dst = (struct sockaddr *)cp; - cp += ROUNDUP(dst->sa_len); + ADVANCE(cp, dst); } else senderr(EINVAL); if ((rtm->rtm_addrs & RTA_GATEWAY) && cp < lim) { gate = (struct sockaddr *)cp; - cp += ROUNDUP(gate->sa_len); + ADVANCE(cp, gate); } if ((rtm->rtm_addrs & RTA_NETMASK) && cp < lim) { netmask = (struct sockaddr *)cp; - if (*cp) - cp += ROUNDUP(netmask->sa_len); - else - cp += sizeof(long); - + ADVANCE(cp, netmask); } if ((rtm->rtm_addrs & RTA_GENMASK) && cp < lim) { + struct radix_node *t, *rn_addmask(); genmask = (struct sockaddr *)cp; + ADVANCE(cp, genmask); + t = rn_addmask(genmask, 1, 2); + if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) + genmask = (struct sockaddr *)(t->rn_key); + else + senderr(ENOBUFS); + } + if ((rtm->rtm_addrs & RTA_IFP) && cp < lim) { + ifpaddr = (struct sockaddr *)cp; + ADVANCE(cp, ifpaddr); + } + if ((rtm->rtm_addrs & RTA_IFA) && cp < lim) { + ifaaddr = (struct sockaddr *)cp; } switch (rtm->rtm_type) { case RTM_ADD: @@ -146,6 +181,7 @@ route_output(m, so) rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &saved_nrt->rt_rmx); saved_nrt->rt_refcnt--; + saved_nrt->rt_genmask = genmask; } break; @@ -160,20 +196,51 @@ route_output(m, so) rt = rtalloc1(dst, 0); if (rt == 0) senderr(ESRCH); + if (rtm->rtm_type != RTM_GET) { + if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0) + senderr(ESRCH); + if (rt->rt_nodes->rn_dupedkey && + (netmask == 0 || + Bcmp(netmask, rt_mask(rt), netmask->sa_len))) + senderr(ETOOMANYREFS); + } switch(rtm->rtm_type) { - struct sockaddr *outmask; case RTM_GET: - netmask = rt_mask(rt); - len = sizeof(*rtm) + ROUNDUP(rt_key(rt)->sa_len); - rtm->rtm_addrs = RTA_DST; - if (rt->rt_gateway) { - len += ROUNDUP(rt->rt_gateway->sa_len); + dst = rt_key(rt); len = sizeof(*rtm); + ADVANCE(len, dst); + rtm->rtm_addrs |= RTA_DST; + if (gate = rt->rt_gateway) { + ADVANCE(len, gate); rtm->rtm_addrs |= RTA_GATEWAY; - } - if (netmask) { - len += netmask->sa_len; + } else + rtm->rtm_addrs &= ~RTA_GATEWAY; + if (netmask = rt_mask(rt)) { + ADVANCE(len, netmask); rtm->rtm_addrs |= RTA_NETMASK; + } else + rtm->rtm_addrs &= ~RTA_NETMASK; + if (genmask = rt->rt_genmask) { + ADVANCE(len, genmask); + rtm->rtm_addrs |= RTA_GENMASK; + } else + rtm->rtm_addrs &= ~RTA_GENMASK; + if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { + if (rt->rt_ifp == 0) + goto badif; + for (ifa = rt->rt_ifp->if_addrlist; + ifa && ifa->ifa_addr->sa_family != AF_LINK; + ifa = ifa->ifa_next){} + if (ifa && rt->rt_ifa) { + ifpaddr = ifa->ifa_addr; + ADVANCE(len, ifpaddr); + ifaaddr = rt->rt_ifa->ifa_addr; + ADVANCE(len, ifaaddr); + rtm->rtm_addrs |= RTA_IFP | RTA_IFA; + } else { + badif: ifpaddr = 0; + rtm->rtm_addrs &= ~(RTA_IFP | RTA_IFA); + } } if (len > rtm->rtm_msglen) { struct rt_msghdr *new_rtm; @@ -182,32 +249,66 @@ route_output(m, so) senderr(ENOBUFS); Bcopy(rtm, new_rtm, rtm->rtm_msglen); Free(rtm); rtm = new_rtm; - gate = (struct sockaddr *) - (ROUNDUP(rt->rt_gateway->sa_len) - + (char *)dst); - Bcopy(&rt->rt_gateway, gate, - rt->rt_gateway->sa_len); - rtm->rtm_flags = rt->rt_flags; - if (netmask) { - outmask = (struct sockaddr *) - (ROUNDUP(netmask->sa_len)+(char *)gate); - Bcopy(netmask, outmask, netmask->sa_len); - } + } + rtm->rtm_msglen = len; + rtm->rtm_flags = rt->rt_flags; + rtm->rtm_rmx = rt->rt_rmx; + cp = (caddr_t) (1 + rtm); + len = ROUNDUP(dst->sa_len); + Bcopy(dst, cp, len); cp += len; + if (gate) { + len = ROUNDUP(gate->sa_len); + Bcopy(gate, cp, len); cp += len; + } + if (netmask) { + len = ROUNDUP(netmask->sa_len); + Bcopy(netmask, cp, len); cp += len; + } + if (genmask) { + len = ROUNDUP(genmask->sa_len); + Bcopy(genmask, cp, len); cp += len; + } + if (ifpaddr) { + len = ROUNDUP(ifpaddr->sa_len); + Bcopy(ifpaddr, cp, len); cp += len; + len = ROUNDUP(ifaaddr->sa_len); + Bcopy(ifaaddr, cp, len); cp += len; } break; case RTM_CHANGE: - if (gate == 0) - senderr(EINVAL); - if (gate->sa_len > (len = rt->rt_gateway->sa_len)) + if (gate && + (gate->sa_len > (len = rt->rt_gateway->sa_len))) senderr(EDQUOT); + /* new gateway could require new ifaddr, ifp; + flags may also be different; ifp may be specified + by ll sockaddr when protocol address is ambiguous */ + if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && + (ifp = ifa->ifa_ifp)) + ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, + ifp); + else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || + (ifa = ifa_ifwithroute(rt->rt_flags, + rt_key(rt), gate))) + ifp = ifa->ifa_ifp; + if (ifa) { + register struct ifaddr *oifa = rt->rt_ifa; + if (oifa != ifa) { + if (oifa && oifa->ifa_rtrequest) + oifa->ifa_rtrequest(RTM_DELETE, + rt, gate); + rt->rt_ifa = ifa; + rt->rt_ifp = ifp; + } + } + if (gate) + Bcopy(gate, rt->rt_gateway, len); + rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, + &rt->rt_rmx); if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) - rt->rt_ifa->ifa_rtrequest(RTM_CHANGE, rt, gate); - Bcopy(gate, rt->rt_gateway, len); - rt->rt_gateway->sa_len = len; - - rt_setmetrics(rtm->rtm_inits, - &rtm->rtm_rmx, &rt->rt_rmx); + rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); + if (genmask) + rt->rt_genmask = genmask; /* * Fall into */ @@ -233,16 +334,37 @@ flush: cleanup: if (rt) rtfree(rt); - if (cp = (caddr_t)rtm) { - m_copyback(m, 0, len, cp); + { + register struct rawcb *rp = 0; + /* + * Check to see if we don't want our own messages. + */ + if ((so->so_options & SO_USELOOPBACK) == 0) { + if (route_cb.any_count <= 1) { + if (rtm) + Free(rtm); + m_freem(m); + return (error); + } + /* There is another listener, so construct message */ + rp = sotorawcb(so); + } + if (rtm) { + m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); Free(rtm); } - route_proto.sp_protocol = dst->sa_family; + if (rp) + rp->rcb_proto.sp_family = 0; /* Avoid us */ + if (dst) + route_proto.sp_protocol = dst->sa_family; raw_input(m, &route_proto, &route_src, &route_dst); + if (rp) + rp->rcb_proto.sp_family = PF_ROUTE; + } return (error); } -static rt_setmetrics(which, in, out) +rt_setmetrics(which, in, out) u_long which; register struct rt_metrics *in, *out; { @@ -254,6 +376,7 @@ static rt_setmetrics(which, in, out) metric(RTV_RTTVAR, rmx_rttvar); metric(RTV_HOPCOUNT, rmx_hopcount); metric(RTV_MTU, rmx_mtu); + metric(RTV_EXPIRE, rmx_expire); #undef metric } @@ -275,7 +398,7 @@ m_copyback(m0, off, len, cp) if (m0 == 0) return; - while (off >= (mlen = m->m_len)) { + while (off > (mlen = m->m_len)) { off -= mlen; totlen += mlen; if (m->m_next == 0) { @@ -338,7 +461,7 @@ struct sockaddr *gate, *mask, *src; rtm->rtm_type = type; rtm->rtm_addrs = RTA_DST; if (type == RTM_OLDADD || type == RTM_OLDDEL) { - rtm->rtm_pid = u.u_procp->p_pid; + rtm->rtm_pid = curproc->p_pid; } m_copyback(m, sizeof (*rtm), dlen, (caddr_t)dst); if (gate) { @@ -348,10 +471,7 @@ struct sockaddr *gate, *mask, *src; rtm->rtm_addrs |= RTA_GATEWAY; } if (mask) { - if (mask->sa_len) - dlen = ROUNDUP(mask->sa_len); - else - dlen = sizeof(long); + dlen = ROUNDUP(mask->sa_len); m_copyback(m, len , dlen, (caddr_t)mask); len += dlen; rtm->rtm_addrs |= RTA_NETMASK; @@ -393,10 +513,12 @@ rt_dumpentry(rn, w) register struct sockaddr *sa; int n, error; - for (; rn && !(rn->rn_flags & RNF_ROOT); rn = rn->rn_dupedkey) { + for (; rn; rn = rn->rn_dupedkey) { int count = 0, size = sizeof(w->w_rtm); register struct rtentry *rt = (struct rtentry *)rn; + if (rn->rn_flags & RNF_ROOT) + continue; if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg)) continue; #define next(a, l) {size += (l); w->w_rtm.rtm_addrs |= (a); } @@ -406,8 +528,7 @@ rt_dumpentry(rn, w) if (sa = rt->rt_gateway) next(RTA_GATEWAY, ROUNDUP(sa->sa_len)); if (sa = rt_mask(rt)) - next(RTA_NETMASK, - sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); + next(RTA_NETMASK, ROUNDUP(sa->sa_len)); if (sa = rt->rt_genmask) next(RTA_GENMASK, ROUNDUP(sa->sa_len)); w->w_needed += size; @@ -427,7 +548,7 @@ rt_dumpentry(rn, w) if (sa = rt->rt_gateway) next(ROUNDUP(sa->sa_len)); if (sa = rt_mask(rt)) - next(sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); + next(ROUNDUP(sa->sa_len)); if (sa = rt->rt_genmask) next(ROUNDUP(sa->sa_len)); #undef next @@ -444,7 +565,7 @@ rt_dumpentry(rn, w) if (sa = rt->rt_gateway) next(sa, ROUNDUP(sa->sa_len)); if (sa = rt_mask(rt)) - next(sa, sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); + next(sa, ROUNDUP(sa->sa_len)); if (sa = rt->rt_genmask) next(sa, ROUNDUP(sa->sa_len)); } @@ -519,7 +640,6 @@ rt_walk(rn, f, w) * Definitions of protocols supported in the ROUTE domain. */ -int route_output(); int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); extern struct domain routedomain; /* or at least forward */ @@ -528,11 +648,6 @@ struct protosw routesw[] = { raw_input, route_output, raw_ctlinput, 0, route_usrreq, raw_init, 0, 0, 0, -}, -{ 0, 0, 0, 0, - raw_input, 0, raw_ctlinput, 0, - raw_usrreq, - raw_init, 0, 0, 0, } };