From c124e99765d0f6dcbd313a3f51049048be62e9b6 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Mon, 29 Mar 1982 18:34:21 -0800 Subject: [PATCH] first cut (incomplete) at routing SCCS-vsn: sys/netinet/in_pcb.c 4.23 SCCS-vsn: sys/netinet/in_pcb.h 4.4 SCCS-vsn: sys/netinet/ip_input.c 1.36 SCCS-vsn: sys/netinet/ip_output.c 1.28 SCCS-vsn: sys/net/route.c 4.3 SCCS-vsn: sys/net/route.h 4.3 SCCS-vsn: sys/netinet/tcp_debug.c 4.3 SCCS-vsn: sys/netinet/tcp_input.c 1.65 SCCS-vsn: sys/netinet/tcp_output.c 4.37 SCCS-vsn: sys/netinet/tcp_subr.c 4.21 SCCS-vsn: sys/netinet/tcp_timer.c 4.19 SCCS-vsn: sys/netinet/tcp_usrreq.c 1.54 SCCS-vsn: sys/netinet/udp_usrreq.c 4.24 --- usr/src/sys/net/route.c | 101 ++++++++++++++++--------------- usr/src/sys/net/route.h | 3 +- usr/src/sys/netinet/in_pcb.c | 16 +++-- usr/src/sys/netinet/in_pcb.h | 3 +- usr/src/sys/netinet/ip_input.c | 22 +++---- usr/src/sys/netinet/ip_output.c | 26 +++++--- usr/src/sys/netinet/tcp_debug.c | 3 +- usr/src/sys/netinet/tcp_input.c | 3 +- usr/src/sys/netinet/tcp_output.c | 6 +- usr/src/sys/netinet/tcp_subr.c | 11 ++-- usr/src/sys/netinet/tcp_timer.c | 3 +- usr/src/sys/netinet/tcp_usrreq.c | 3 +- usr/src/sys/netinet/udp_usrreq.c | 4 +- 13 files changed, 112 insertions(+), 92 deletions(-) diff --git a/usr/src/sys/net/route.c b/usr/src/sys/net/route.c index 255ad54594..cf923703b7 100644 --- a/usr/src/sys/net/route.c +++ b/usr/src/sys/net/route.c @@ -1,23 +1,17 @@ -/* route.c 4.2 82/03/28 */ +/* route.c 4.3 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/proc.h" -#include "../h/file.h" -#include "../h/inode.h" -#include "../h/buf.h" #include "../h/mbuf.h" #include "../h/protosw.h" #include "../h/socket.h" -#include "../h/socketvar.h" #include "../h/ioctl.h" #include "../net/in.h" #include "../net/in_systm.h" #include "../net/if.h" #include "../net/af.h" #include "../net/route.h" +#include /* * Packet routing routines. @@ -27,7 +21,7 @@ * With much ado about nothing... * route the cars that climb halfway to the stars... */ -route(ro) +allocroute(ro) register struct route *ro; { register struct rtentry *rt, *rtmin; @@ -37,8 +31,8 @@ route(ro) struct sockaddr *dst = &ro->ro_dst; int af = dst->sa_family, doinghost; -COUNT(ROUTE); - if (ro && ro->ro_rt && ro->ro_rt->rt_ifp) /* ??? */ +COUNT(ALLOCROUTE); + if (ro->ro_rt && ro->ro_rt->rt_ifp) /* can't happen */ return; (*afswitch[af].af_hash)(dst, &h); m = routehash[h.afh_hosthash % RTHASHSIZ]; @@ -47,11 +41,11 @@ COUNT(ROUTE); again: for (; m; m = m->m_next) { rt = mtod(m, struct rtentry *); -#define equal(a1, a2) \ - (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof(struct sockaddr)) == 0) if (rt->rt_key != key) continue; if (doinghost) { +#define equal(a1, a2) \ + (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof(struct sockaddr)) == 0) if (!equal(&rt->rt_dst, dst)) continue; } else { @@ -67,7 +61,7 @@ again: ro->ro_dst = rt->rt_dst; ro->ro_rt = rt; rt->rt_refcnt++; - return; + return (rt->rt_flags & RTF_DIRECT); } if (doinghost) { doinghost = 0; @@ -76,8 +70,20 @@ again: goto again; } ro->ro_rt = 0; + return (0); } +freeroute(rt) + register struct rtentry *rt; +{ +COUNT(FREEROUTE); + if (rt == 0) + panic("freeroute"); + rt->rt_refcnt--; + /* on refcnt == 0 reclaim? notify someone? */ +} + +#ifdef notdef struct rtentry * reroute(sa) register struct sockaddr *sa; @@ -100,32 +106,12 @@ COUNT(REROUTE); } return (0); } +#endif /* - * Routing control calls allow a routing daemon - * to consistenly access the routing data base for updates. - */ -rtcontrol(req, addr) - caddr_t addr; -{ - register struct rtentry rq; - int x = splimp(), err = 0; - -COUNT(RTCONTROL); - if (suser()) - goto bad; - if (copyin(addr, (caddr_t)&rq, sizeof(struct rtentry))) { - u.u_error = EFAULT; - goto bad; - } - err = rtrequest(req, &rq); -bad: - splx(x); - return (err); -} - -/* - * Carry out a user request to modify the data base. + * Carry out a request to change the routing table. Called by + * interfaces at boot time to make their ``local routes'' known + * and for ioctl's. */ rtrequest(req, new) int req; @@ -136,12 +122,14 @@ rtrequest(req, new) register int key; struct sockaddr *sa = &new->rt_dst; struct afhash h; - int af = sa->sa_family, doinghost; + int af = sa->sa_family, doinghost, s, error = 0; +COUNT(RTREQUEST); (*afswitch[af].af_hash)(sa, &h); mprev = &routehash[h.afh_hosthash % RTHASHSIZ]; key = h.afh_hostkey; doinghost = 1; + s = splimp(); again: for (; m = *mprev; mprev = &m->m_next) { rt = mtod(m, struct rtentry *); @@ -156,6 +144,16 @@ again: if ((*afswitch[af].af_netmatch)(&rt->rt_dst, sa) == 0) continue; } + /* require full match on deletions */ + if (req == SIOCDELRT && + !equal(&rt->rt_gateway, &new->rt_gateway)) + continue; + /* don't keep multiple identical entries */ + if (req == SIOCADDRT && + equal(&rt->rt_gateway, &new->rt_gateway)) { + error = EEXIST; + goto bad; + } break; } if (m == 0 && doinghost) { @@ -165,29 +163,34 @@ again: goto again; } - if (m == 0 && req != SIOCADDRT) - return (ESRCH); + if (m == 0 && req != SIOCADDRT) { + error = ESRCH; + goto bad; + } switch (req) { case SIOCDELRT: rt->rt_flags &= ~RTF_UP; if (rt->rt_refcnt > 0) /* should we notify protocols? */ - break; - *mprev = m_free(m); + error = EBUSY; + else + *mprev = m_free(m); break; case SIOCCHGRT: rt->rt_flags = new->rt_flags; if (rt->rt_refcnt > 0) - return (EBUSY); - if (!equal(&rt->rt_gateway, &new->rt_gateway)) + error = EBUSY; + else if (!equal(&rt->rt_gateway, &new->rt_gateway)) goto newneighbor; break; case SIOCADDRT: m = m_getclr(M_DONTWAIT); - if (m == 0) - return (ENOBUFS); + if (m == 0) { + error = ENOBUFS; + break; + } m->m_off = MMINOFF; *mprev = m; rt = mtod(m, struct rtentry *); @@ -200,5 +203,7 @@ newneighbor: rt->rt_refcnt = 0; break; } - return (0); +bad: + splx(s); + return (error); } diff --git a/usr/src/sys/net/route.h b/usr/src/sys/net/route.h index 44034b3b8b..8a33008130 100644 --- a/usr/src/sys/net/route.h +++ b/usr/src/sys/net/route.h @@ -1,4 +1,4 @@ -/* route.h 4.2 82/03/28 */ +/* route.h 4.3 82/03/29 */ /* * Structure of kernel resident routing @@ -31,6 +31,7 @@ struct route { */ #define RTF_UP 0x1 /* route useable */ #define RTF_MUNGE 0x2 /* munge packet src address */ +#define RTF_DIRECT 0x4 /* destination is a neighbor */ #ifdef KERNEL /* diff --git a/usr/src/sys/netinet/in_pcb.c b/usr/src/sys/netinet/in_pcb.c index 3af118bc29..f6ed6a9327 100644 --- a/usr/src/sys/netinet/in_pcb.c +++ b/usr/src/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* in_pcb.c 4.22 82/03/28 */ +/* in_pcb.c 4.23 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -10,6 +10,7 @@ #include "../net/in.h" #include "../net/in_systm.h" #include "../net/if.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../h/protosw.h" @@ -68,9 +69,14 @@ COUNT(IN_PCBATTACH); if (sin) { if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); - if (sin->sin_addr.s_addr && - if_ifwithaddr((struct sockaddr *)sin) == 0) - return (EADDRNOTAVAIL); + if (sin->sin_addr.s_addr) { + int tport = sin->sin_port; + + sin->sin_port = 0; /* yech... */ + if (if_ifwithaddr((struct sockaddr *)sin) == 0) + return (EADDRNOTAVAIL); + sin->sin_port = tport; + } lport = sin->sin_port; if (lport) { u_short aport = lport; @@ -195,6 +201,8 @@ in_pcbdetach(inp) so->so_pcb = 0; sofree(so); + if (inp->inp_route.ro_rt) + freeroute(inp->inp_route.ro_rt); remque(inp); (void) m_free(dtom(inp)); } diff --git a/usr/src/sys/netinet/in_pcb.h b/usr/src/sys/netinet/in_pcb.h index 449d7924e3..24f8837e74 100644 --- a/usr/src/sys/netinet/in_pcb.h +++ b/usr/src/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* in_pcb.h 4.3 82/03/03 */ +/* in_pcb.h 4.4 82/03/29 */ /* * Common structure pcb for internet protocol implementation. @@ -18,6 +18,7 @@ struct inpcb { u_short inp_lport; /* local port */ struct socket *inp_socket; /* back pointer to socket */ caddr_t inp_ppcb; /* pointer to per-protocol pcb */ + struct route inp_route; /* placeholder for routing entry */ }; #define INPLOOKUP_WILDCARD 1 diff --git a/usr/src/sys/netinet/ip_input.c b/usr/src/sys/netinet/ip_input.c index fdfb7889d1..092a363433 100644 --- a/usr/src/sys/netinet/ip_input.c +++ b/usr/src/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* ip_input.c 1.35 82/03/28 */ +/* ip_input.c 1.36 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -130,7 +130,8 @@ next: ip_dooptions(ip); /* - * Fast check on the first interface in the list. + * Fast check on the first internet + * interface in the list. */ if (ifinet) { struct sockaddr_in *sin; @@ -138,6 +139,9 @@ next: sin = (struct sockaddr_in *)&ifinet->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; + if ((ifinet->if_flags & IFF_BROADCAST) && + sin->sin_addr.s_addr == ip->ip_dst.s_addr) + goto ours; } ipaddr.sin_addr = ip->ip_dst; if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0) { @@ -156,19 +160,7 @@ printf("forward: dst %x ttl %x\n", ip->ip_dst, ip->ip_ttl); goto bad; ip_stripoptions(ip, mopt); - /* - * Check the routing table in case we should - * munge the src address before it gets passed on. - */ - ipaddr.sin_addr = ip->ip_src; - rt = reroute(&ipaddr); - if (rt && (rt->rt_flags & RTF_MUNGE)) { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)&rt->rt_dst; - ip->ip_src = sin->sin_addr; - } - /* 0 here means no directed broadcast */ + /* last 0 here means no directed broadcast */ (void) ip_output(m0, mopt, 0, 0); goto next; } diff --git a/usr/src/sys/netinet/ip_output.c b/usr/src/sys/netinet/ip_output.c index ab2763abd5..2f29568a40 100644 --- a/usr/src/sys/netinet/ip_output.c +++ b/usr/src/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* ip_output.c 1.27 82/03/28 */ +/* ip_output.c 1.28 82/03/29 */ #include "../h/param.h" #include "../h/mbuf.h" @@ -20,9 +20,10 @@ ip_output(m, opt, ro, allowbroadcast) { register struct ip *ip = mtod(m, struct ip *); register struct ifnet *ifp; - int len, hlen = sizeof (struct ip), off; + int len, hlen = sizeof (struct ip), off, direct; struct sockaddr_in tempaddr; /* temp kludge */ struct route iproute; + struct sockaddr *dst; COUNT(IP_OUTPUT); if (opt) /* XXX */ @@ -37,7 +38,10 @@ COUNT(IP_OUTPUT); #ifdef notdef /* - * Find interface for this packet. + * Find interface for this packet in the routing + * table. Note each interface has placed itself + * in there at boot time, so call on route degenerates + * to if_ifonnetof(ip->ip_dst.s_net). */ if (ro == 0) { ro = &iproute; @@ -46,10 +50,12 @@ COUNT(IP_OUTPUT); if (ro->ro_rt == 0) { ro->ro_dest.sin_addr = ip->ip_dst; ro->ro_dest.sin_family = AF_INET; - route(ro); + direct = allocroute(ro); } if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) goto bad; + dst = direct ? (struct sockaddr *)&ro->ro_dest : + &ro->ro_rt->rt_gateway; #else /* interim kludge before routing fallout */ ifp = if_ifonnetof(ip->ip_dst.s_net); @@ -77,11 +83,11 @@ COUNT(IP_OUTPUT); #endif ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); - return ((*ifp->if_output)(ifp, m, #ifdef notdef - &ro->ro_rt->rt_dest)); + return ((*ifp->if_output)(ifp, m, dst)); #else - (struct sockaddr *)&tempaddr)); + return ((*ifp->if_output)(ifp, m, + (struct sockaddr *)&tempaddr)); #endif } @@ -137,11 +143,11 @@ COUNT(IP_OUTPUT); #endif mhip->ip_sum = 0; mhip->ip_sum = in_cksum(mh, hlen); - if ((*ifp->if_output)(ifp, mh, #ifdef notdef - &ro->ro_rt->rt_dest) == 0) + if ((*ifp->if_output)(ifp, mh, dst) == 0) #else - (struct sockaddr *)&tempaddr) == 0) + if ((*ifp->if_output)(ifp, mh, + (struct sockaddr *)&tempaddr) == 0) #endif goto bad; } diff --git a/usr/src/sys/netinet/tcp_debug.c b/usr/src/sys/netinet/tcp_debug.c index b9fc28b152..a2f703a9b5 100644 --- a/usr/src/sys/netinet/tcp_debug.c +++ b/usr/src/sys/netinet/tcp_debug.c @@ -1,4 +1,4 @@ -/* tcp_debug.c 4.2 82/03/13 */ +/* tcp_debug.c 4.3 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -8,6 +8,7 @@ #define PRUREQUESTS #include "../h/protosw.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/if.h" diff --git a/usr/src/sys/netinet/tcp_input.c b/usr/src/sys/netinet/tcp_input.c index a7ac2aaca6..834574ae13 100644 --- a/usr/src/sys/netinet/tcp_input.c +++ b/usr/src/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* tcp_input.c 1.64 82/03/26 */ +/* tcp_input.c 1.65 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -7,6 +7,7 @@ #include "../h/socket.h" #include "../h/socketvar.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/if.h" diff --git a/usr/src/sys/netinet/tcp_output.c b/usr/src/sys/netinet/tcp_output.c index c15696290b..9b3825a1ef 100644 --- a/usr/src/sys/netinet/tcp_output.c +++ b/usr/src/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* tcp_output.c 4.36 82/03/28 */ +/* tcp_output.c 4.37 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -7,6 +7,7 @@ #include "../h/socket.h" #include "../h/socketvar.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/ip.h" @@ -19,7 +20,6 @@ #include "../net/tcp_var.h" #include "../net/tcpip.h" #include "../net/tcp_debug.h" -#include "../net/route.h" #include "../errno.h" char *tcpstates[]; /* XXX */ @@ -309,7 +309,7 @@ noopt: */ ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len; ((struct ip *)ti)->ip_ttl = TCP_TTL; - if (ip_output(m, tp->t_ipopt, 0, 0) == 0) + if (ip_output(m, tp->t_ipopt, &tp->t_inpcb->inp_route, 0) == 0) return (0); /* diff --git a/usr/src/sys/netinet/tcp_subr.c b/usr/src/sys/netinet/tcp_subr.c index 697917f004..cd45506cd6 100644 --- a/usr/src/sys/netinet/tcp_subr.c +++ b/usr/src/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* tcp_subr.c 4.20 82/03/28 */ +/* tcp_subr.c 4.21 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -7,6 +7,7 @@ #include "../h/socketvar.h" #include "../h/protosw.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/if.h" @@ -18,7 +19,6 @@ #include "../net/tcp_timer.h" #include "../net/tcp_var.h" #include "../net/tcpip.h" -#include "../net/route.h" #include "../errno.h" /* @@ -95,10 +95,13 @@ tcp_respond(tp, ti, ack, seq, flags) { struct mbuf *m; int win = 0, tlen; + struct route *ro = 0; COUNT(TCP_RESPOND); - if (tp) + if (tp) { win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); + ro = &tp->t_inpcb->inp_route; + } if (flags == 0) { m = m_get(M_DONTWAIT); if (m == 0) @@ -142,7 +145,7 @@ COUNT(TCP_RESPOND); ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; ((struct ip *)ti)->ip_ttl = TCP_TTL; - (void) ip_output(m, (struct mbuf *)0, 0, 0); + (void) ip_output(m, (struct mbuf *)0, ro, 0); } /* diff --git a/usr/src/sys/netinet/tcp_timer.c b/usr/src/sys/netinet/tcp_timer.c index ab04a295d2..831146f1e5 100644 --- a/usr/src/sys/netinet/tcp_timer.c +++ b/usr/src/sys/netinet/tcp_timer.c @@ -1,4 +1,4 @@ -/* tcp_timer.c 4.18 82/03/24 */ +/* tcp_timer.c 4.19 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -7,6 +7,7 @@ #include "../h/socketvar.h" #include "../h/protosw.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/if.h" diff --git a/usr/src/sys/netinet/tcp_usrreq.c b/usr/src/sys/netinet/tcp_usrreq.c index 9250b1f006..fa02559c39 100644 --- a/usr/src/sys/netinet/tcp_usrreq.c +++ b/usr/src/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* tcp_usrreq.c 1.53 82/03/11 */ +/* tcp_usrreq.c 1.54 82/03/29 */ #include "../h/param.h" #include "../h/systm.h" @@ -7,6 +7,7 @@ #include "../h/socketvar.h" #include "../h/protosw.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/if.h" diff --git a/usr/src/sys/netinet/udp_usrreq.c b/usr/src/sys/netinet/udp_usrreq.c index 9a5fb9c36b..92cd487997 100644 --- a/usr/src/sys/netinet/udp_usrreq.c +++ b/usr/src/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* udp_usrreq.c 4.23 82/03/28 */ +/* udp_usrreq.c 4.24 82/03/29 */ #include "../h/param.h" #include "../h/dir.h" @@ -8,13 +8,13 @@ #include "../h/socket.h" #include "../h/socketvar.h" #include "../net/in.h" +#include "../net/route.h" #include "../net/in_pcb.h" #include "../net/in_systm.h" #include "../net/ip.h" #include "../net/ip_var.h" #include "../net/udp.h" #include "../net/udp_var.h" -#include "../net/route.h" /* * UDP protocol implementation. -- 2.20.1