--- cci/sys/net/if.c 2019/07/28 12:24:19 1.1 +++ cci/sys/net/if.c 2019/07/28 12:30:12 1.1.1.2 @@ -9,9 +9,11 @@ #include "../h/kernel.h" #include "../h/ioctl.h" #include "../h/errno.h" +#include "../h/mbuf.h" #include "../net/if.h" #include "../net/af.h" +#include "../net/route.h" int ifqmaxlen = IFQ_MAXLEN; @@ -19,6 +21,13 @@ int ifqmaxlen = IFQ_MAXLEN; * Change: * . Add the check to make sure that only superuser can * assign Ethernet station address with ioctl(SIOCSETETADDR). + * . 01/15/86. Add new ioctl SIOCGETETADDR + * . 01/15/86. if_ifwithnet(), if_ifwithaddr(): Add check for whether + * an interface is up before qualifying it for further tests. + * . 01/19/86. Add new routine if_ifptop(). See description below. + * . 01/22/86. if_down(). Delete routing entry for inactive interface. + * . 01/22/86. if_ioctl(). Add new routing entry for an inactive interface + * which is being brought up. */ /* @@ -80,9 +89,15 @@ if_detach(ifp) { short s = splimp(); register struct ifnet **p = &ifnet; + register struct mbuf *m; while (*p) { if ((*p) == ifp) { + /* Deallocate output bufs */ + while (ifp->if_snd.ifq_head) { + IF_DEQUEUE(&ifp->if_snd, m) + m_freem(m); + } (*p) = (struct ifnet *)ifp->if_next; ifp->if_next = (struct ifnet *)0; break; @@ -106,7 +121,8 @@ if_ifwithaddr(addr) #define equal(a1, a2) \ (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (ifp->if_addr.sa_family != addr->sa_family) + if ((ifp->if_addr.sa_family != addr->sa_family) || + !(ifp->if_flags & IFF_UP)) continue; if (equal(&ifp->if_addr, addr)) break; @@ -133,7 +149,7 @@ if_ifwithnet(addr) return (0); netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (af != ifp->if_addr.sa_family) + if ((af != ifp->if_addr.sa_family) || !(ifp->if_flags & IFF_UP)) continue; if ((*netmatch)(addr, &ifp->if_addr)) break; @@ -174,7 +190,7 @@ if_ifwithaf(af) /* * Mark an interface down and notify protocols of * the transition. - * NOTE: must be called at splnet or eqivalent. + * NOTE: must be called at splnet or equivalent. */ if_down(ifp) register struct ifnet *ifp; @@ -182,6 +198,7 @@ if_down(ifp) ifp->if_flags &= ~IFF_UP; pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); + if_rtinit(ifp, -1); /* delete routing entry */ } /* @@ -248,8 +265,11 @@ ifioctl(cmd, data) case SIOCSIFFLAGS: case SIOCSIFDSTADDR: case SIOCSETETADDR: + case SIOCIFDETACH: if (!suser()) return (u.u_error); + case SIOCGETETADDR: + default: break; } ifr = (struct ifreq *)data; @@ -278,6 +298,13 @@ ifioctl(cmd, data) if_down(ifp); splx(s); } + /* + * if interface was inactive and being brought up now, + * We should add routing entry for it because its old entry + * was deleted when we brought it down earlier. + */ + if (!(ifp->if_flags & IFF_UP) && (ifr->ifr_flags & IFF_UP)) + if_rtinit(ifp, RTF_UP); ifp->if_flags = ifr->ifr_flags; break; @@ -322,3 +349,41 @@ ifconf(cmd, data) ifc->ifc_len -= space; return (error); } +/* + * Search for a point-to-point link connected to + * (destination or gateway) host. + */ +struct ifnet * +if_ifptop(rt) +register struct rtentry *rt; +{ + register struct ifnet *ifp; + + /* When adding a route that use POINTTOPOINT interface, we + give priority to a direct connection before looking for + a gateway. + */ + for (ifp = ifnet; ifp; ifp = ifp->if_next) { + if (ifp->if_addr.sa_family != rt->rt_dst.sa_family || + !(ifp->if_flags&IFF_UP)) + continue; + if ((ifp->if_flags & IFF_POINTOPOINT) && + (bcmp(ifp->if_dstaddr.sa_data, + rt->rt_dst.sa_data, 14) == 0 )) + break; + } + if (ifp == 0) { + for (ifp = ifnet; ifp; ifp = ifp->if_next) { + if (ifp->if_addr.sa_family != + rt->rt_dst.sa_family || + !(ifp->if_flags&IFF_UP)) + continue; + if ((ifp->if_flags & IFF_POINTOPOINT) && + (bcmp(ifp->if_dstaddr.sa_data, + rt->rt_gateway.sa_data, 14) == 0)) + break; + } + } + return(ifp); +} +