Path: seismo!hao!hplabs!ucbvax!decvax!genrad!panda!talcott!ut-sally!jsq (John Quarterman) From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: 4.3BSD IP subnet ARP hack Message-ID: <1651@panda.UUCP> Date: 12 Apr 86 13:43:22 GMT Sender: jpn@panda.UUCP Lines: 425 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 64 Submitted by: talcott!ut-sally!jsq (John Quarterman) : This is a shar archive. Extract with sh, not csh. echo x - README sed -e 's/^X//' > README << '!RoNnIe!RaYgUn!' XThese are the mods necessary to 4.3BSD to add a subnet ARP hack. XThey allow a subnet gateway machine to act as a bridge so that only Xit need know of the existence of subnets. This is quite useful if Xmany machines on the local network do not have RFC950 subnet code Xand you do not have sources for them. X XTo turn on the subarp code, you need to do "ifconfig xxn subarp". X X/sys/netinet/if_ether.c: subnet ARP hack X/sys/net/if.h: IFF_SUBARP X/sys/net/route.c: splimp instead of splnet in rtalloc X/sys/netinet/in.c: in_mainnetof X/sys/netinet/in.h: in_mainnetof X/usr/src/etc/ifconfig/ifconfig.c: IFF_SUBARP (subarp, -subarp) X/usr/man/man8/ifconfig.8c: subarp, -subarp X !RoNnIe!RaYgUn! echo x - Install sed -e 's/^X//' > Install << '!RoNnIe!RaYgUn!' Xcp if_ether.c.diff /sys/netinet/if_ether.c.diff Xcp in.c.diff /sys/netinet/in.c.diff Xcp in.h.diff /sys/netinet/in.h.diff Xcp if.h.diff /sys/net/if.h.diff Xcp route.c.diff /sys/net/route.c.diff Xcp ifconfig.c.diff /usr/src/etc/ifconfig/ifconfig.c.diff Xcp ifconfig.8c.diff /usr/man/man8/ifconfig.8c.diff X Xcd /sys/netinet Xsccs edit if_ether.c Xpatch if_ether.c.diff Xecho 'subarp' | sccs delget if_ether.c X Xcd /sys/netinet Xsccs edit in.c Xpatch in.c.diff Xecho 'subarp' | sccs delget in.c X Xcd /sys/netinet Xsccs edit in.h Xpatch in.h.diff Xecho 'subarp' | sccs delget in.h X Xcd /sys/net Xsccs edit if.h Xpatch if.h.diff Xecho 'subarp' | sccs delget if.h X Xcd /sys/net Xsccs edit route.c Xpatch route.c.diff Xecho 'subarp' | sccs delget route.c X Xcd /usr/src/etc/ifconfig Xsccs edit ifconfig.c Xpatch ifconfig.c.diff Xecho 'subarp' | sccs delget ifconfig.c X Xcd /usr/man/man8 Xsccs edit ifconfig.8c Xpatch ifconfig.8c.diff Xecho 'subarp' | sccs delget ifconfig.8c !RoNnIe!RaYgUn! echo x - if_ether.c.diff sed -e 's/^X//' > if_ether.c.diff << '!RoNnIe!RaYgUn!' X*** if_ether.c.orig Sun Apr 6 14:42:51 1986 X--- if_ether.c Sun Apr 6 14:42:53 1986 X*************** X*** 21,27 **** X--- 21,29 ---- X #include "syslog.h" X X #include "../net/if.h" X+ #include "../net/route.h" X #include "in.h" X+ #include "in_var.h" X #include "in_systm.h" X #include "ip.h" X #include "if_ether.h" X*************** X*** 343,348 **** X--- 345,364 ---- X sizeof(ea->arp_sha)); X bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, X sizeof(ea->arp_sha)); X+ } else X+ /* X+ * Subnet ARP hack (subarp). This allows a site to run the subnet X+ * kernel only on the gateway machines by allowing the gateway X+ * to reply to ARP requests for a target machine on a locally X+ * attached subnet or reachable via a route from this gateway. X+ */ X+ if (ac->ac_if.if_flags & IFF_SUBARP X+ && in_netof(isaddr) != in_netof(itaddr) X+ && if_subarp(isaddr, itaddr, &(ac->ac_if))) { X+ bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, X+ sizeof(ea->arp_sha)); X+ bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, X+ sizeof(ea->arp_sha)); X } else { X ARPTAB_LOOK(at, itaddr.s_addr); X if (at == NULL || (at->at_flags & ATF_PUBL) == 0) X*************** X*** 352,358 **** X bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha, X sizeof(ea->arp_sha)); X } X- X bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, X sizeof(ea->arp_spa)); X bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, X--- 368,373 ---- X*************** X*** 528,531 **** X--- 543,619 ---- X } X *--cp = 0; X return (etherbuf); X+ } X+ X+ /* X+ * Determine if interface of target address has ARP subnet routing enabled. X+ */ X+ int if_subarplog = 1; X+ #define sublog if (if_subarplog) log X+ if_subarp(isaddr, itaddr, sifp) X+ struct in_addr isaddr, itaddr; X+ register struct ifnet *sifp; X+ { X+ register u_long net; X+ register struct in_ifaddr *ia; X+ struct route ro; X+ register struct sockaddr_in *sin; X+ register struct ifaddr *taddr; X+ register struct ifnet *tifp; X+ X+ net = in_mainnetof(itaddr); X+ if (net != in_mainnetof(isaddr)) /* sanity check */ X+ return(0); X+ for (ia = in_ifaddr; ia; ia = ia->ia_next) X+ if (net == ia->ia_net) X+ break; X+ if (ia) { /* don't respond to requests for IP broadcast addresses */ X+ register u_long m, l; X+ X+ m = ~ia->ia_subnetmask; X+ l = ntohl(itaddr.s_addr) & m; X+ if (l == (INADDR_BROADCAST & m) || l == (INADDR_ANY & m)) X+ return(0); X+ m = ~ia->ia_netmask; X+ l = ntohl(itaddr.s_addr) & m; X+ if (l == (INADDR_BROADCAST & m) || l == (INADDR_ANY & m)) X+ return(0); X+ } X+ sin = (struct sockaddr_in *)&(ro.ro_dst); X+ sin->sin_family = AF_INET; X+ sin->sin_addr = itaddr; X+ tifp = (struct ifnet *)0; X+ if ((taddr = ifa_ifwithnet((struct sockaddr *)sin)) != NULL) X+ tifp = taddr->ifa_ifp; /* is subnet of an interface */ X+ else { /* look in routing table for non-local target */ X+ extern struct rtentry nowildcard; X+ X+ ro.ro_rt = &nowildcard; X+ (void) rtalloc(&ro); X+ if (ro.ro_rt != (struct rtentry *)0) { X+ tifp = ro.ro_rt->rt_ifp; X+ RTFREE(ro.ro_rt); X+ } X+ } X+ if (tifp == (struct ifnet *)0) { X+ if ((sifp->if_flags & IFF_DEBUG) != 0) X+ sublog(LOG_DEBUG, "subarp %s%d:%x to ?:%x - no route\n", X+ sifp->if_name, sifp->if_unit, X+ ntohl(isaddr.s_addr), ntohl(itaddr.s_addr)); X+ return(0); X+ } X+ if ((tifp->if_flags & IFF_SUBARP) == 0) X+ return(0); X+ /* Sanity check: ignore request if from same interface as target. */ X+ if (sifp->if_addrlist->ifa_ifp == tifp) { X+ if ((sifp->if_flags & IFF_DEBUG) != 0) X+ sublog(LOG_DEBUG,"subarp %s%d:%x to %s%d:%x - same interface\n", X+ sifp->if_name, sifp->if_unit, ntohl(isaddr.s_addr), X+ tifp->if_name, tifp->if_unit, ntohl(itaddr.s_addr)); X+ return(0); X+ } X+ sublog(LOG_INFO, "subarp %s%d:%x to %s%d:%x\n", X+ sifp->if_name, sifp->if_unit, ntohl(isaddr.s_addr), X+ tifp->if_name, tifp->if_unit, ntohl(itaddr.s_addr)); X+ return(1); X } !RoNnIe!RaYgUn! echo x - in.c.diff sed -e 's/^X//' > in.c.diff << '!RoNnIe!RaYgUn!' X*** in.c.orig Sun Apr 6 14:43:01 1986 X--- in.c Sun Apr 6 14:43:03 1986 X*************** X*** 74,79 **** X--- 74,98 ---- X * Return the network number from an internet address. X */ X u_long X+ in_mainnetof(in) X+ struct in_addr in; X+ { X+ register u_long i = ntohl(in.s_addr); X+ register u_long net; X+ X+ if (IN_CLASSA(i)) X+ net = i & IN_CLASSA_NET; X+ else if (IN_CLASSB(i)) X+ net = i & IN_CLASSB_NET; X+ else X+ net = i & IN_CLASSC_NET; X+ return (net); X+ } X+ X+ /* X+ * Return the network number from an internet address. X+ */ X+ u_long X in_netof(in) X struct in_addr in; X { !RoNnIe!RaYgUn! echo x - in.h.diff sed -e 's/^X//' > in.h.diff << '!RoNnIe!RaYgUn!' X*** in.h.orig Sun Apr 6 14:43:09 1986 X--- in.h Sun Apr 6 14:43:11 1986 X*************** X*** 104,108 **** X extern struct domain inetdomain; X extern struct protosw inetsw[]; X struct in_addr in_makeaddr(); X! u_long in_netof(), in_lnaof(); X #endif X--- 104,108 ---- X extern struct domain inetdomain; X extern struct protosw inetsw[]; X struct in_addr in_makeaddr(); X! u_long in_netof(), in_lnaof(), in_mainnetof(); X #endif !RoNnIe!RaYgUn! echo x - if.h.diff sed -e 's/^X//' > if.h.diff << '!RoNnIe!RaYgUn!' X*** if.h.orig Mon Mar 24 15:24:20 1986 X--- if.h Mon Mar 24 15:24:22 1986 X*************** X*** 75,80 **** X--- 75,81 ---- X #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ X #define IFF_RUNNING 0x40 /* resources allocated */ X #define IFF_NOARP 0x80 /* no address resolution protocol */ X+ #define IFF_SUBARP 0x200 /* ARP subnet gateway hack */ X /* flags set internally only: */ X #define IFF_CANTCHANGE (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING) X !RoNnIe!RaYgUn! echo x - route.c.diff sed -e 's/^X//' > route.c.diff << '!RoNnIe!RaYgUn!' X*** route.c.orig Sun Apr 6 14:43:23 1986 X--- route.c Sun Apr 6 14:43:25 1986 X*************** X*** 22,27 **** X--- 22,28 ---- X X int rttrash; /* routes not in table but not freed */ X struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ X+ struct rtentry nowildcard; /* indicates rtalloc shouldn't use wildcard */ X int rthashsize = RTHASHSIZ; /* for netstat, etc. */ X X /* X*************** X*** 34,44 **** X register struct mbuf *m; X register u_long hash; X struct sockaddr *dst = &ro->ro_dst; X! int (*match)(), doinghost, s; X struct afhash h; X u_int af = dst->sa_family; X struct mbuf **table; X X if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) X return; /* XXX */ X if (af >= AF_MAX) X--- 35,50 ---- X register struct mbuf *m; X register u_long hash; X struct sockaddr *dst = &ro->ro_dst; X! int (*match)(), doinghost, s, nowild; X struct afhash h; X u_int af = dst->sa_family; X struct mbuf **table; X X+ nowild = 0; X+ if (ro->ro_rt == &nowildcard) { X+ ro->ro_rt = NULL; X+ nowild++; X+ } X if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) X return; /* XXX */ X if (af >= AF_MAX) X*************** X*** 46,52 **** X (*afswitch[af].af_hash)(dst, &h); X match = afswitch[af].af_netmatch; X hash = h.afh_hosthash, table = rthost, doinghost = 1; X! s = splnet(); X again: X for (m = table[RTHASHMOD(hash)]; m; m = m->m_next) { X rt = mtod(m, struct rtentry *); X--- 52,58 ---- X (*afswitch[af].af_hash)(dst, &h); X match = afswitch[af].af_netmatch; X hash = h.afh_hosthash, table = rthost, doinghost = 1; X! s = splimp(); /* splnet not high enough: also called from interrupt. */ X again: X for (m = table[RTHASHMOD(hash)]; m; m = m->m_next) { X rt = mtod(m, struct rtentry *); X*************** X*** 79,85 **** X /* X * Check for wildcard gateway, by convention network 0. X */ X! if (dst != &wildcard) { X dst = &wildcard, hash = 0; X goto again; X } X--- 85,91 ---- X /* X * Check for wildcard gateway, by convention network 0. X */ X! if (!nowild && dst != &wildcard) { X dst = &wildcard, hash = 0; X goto again; X } !RoNnIe!RaYgUn! echo x - ifconfig.c.diff sed -e 's/^X//' > ifconfig.c.diff << '!RoNnIe!RaYgUn!' X*** ifconfig.c.orig Sun Apr 6 14:43:30 1986 X--- ifconfig.c Sun Apr 6 14:43:32 1986 X*************** X*** 62,67 **** X--- 62,69 ---- X { "-trailers", IFF_NOTRAILERS, setifflags }, X { "arp", -IFF_NOARP, setifflags }, X { "-arp", IFF_NOARP, setifflags }, X+ { "subarp", IFF_SUBARP, setifflags }, X+ { "-subarp", -IFF_SUBARP, setifflags }, X { "debug", IFF_DEBUG, setifflags }, X { "-debug", -IFF_DEBUG, setifflags }, X #ifdef notdef X*************** X*** 106,117 **** X { X int af = AF_INET; X if (argc < 2) { X! fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s", X "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", X "[ netmask mask ] ]\n", X "\t[ metric n ]\n", X "\t[ trailers | -trailers ]\n", X! "\t[ arp | -arp ]\n"); X exit(1); X } X argc--, argv++; X--- 108,119 ---- X { X int af = AF_INET; X if (argc < 2) { X! fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s", X "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", X "[ netmask mask ] ]\n", X "\t[ metric n ]\n", X "\t[ trailers | -trailers ]\n", X! "\t[ arp | -arp ]\t[ subarp | -subarp ]\n"); X exit(1); X } X argc--, argv++; X*************** X*** 287,292 **** X--- 289,295 ---- X X #define IFFBITS \ X "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ X+ \12SUBARP\ X " X X /* !RoNnIe!RaYgUn! echo x - ifconfig.8c.diff sed -e 's/^X//' > ifconfig.8c.diff << '!RoNnIe!RaYgUn!' X*** ifconfig.8c.orig Sun Apr 6 14:43:39 1986 X--- ifconfig.8c Sun Apr 6 14:43:41 1986 X*************** X*** 101,106 **** X--- 101,119 ---- X .B \-arp X Disable the use of the Address Resolution Protocol. X .TP 15 X+ .B subarp X+ Enable an interface on a subnet gateway to respond to ARP requests X+ for hosts reachable via this subnet. X+ Only useful on hardware which supports ARP. X+ This allows a gateway between two subnets to respond to ARP requests X+ received on an enabled interface to respond for hosts on another X+ enabled interface and route packets thru the gateway. X+ This allows a network configuration where only the gateway hosts need to X+ be aware of the existence of subnets. X+ .TP 15 X+ .B \-subarp X+ Disable the ARP subnet code. X+ .TP 15 X .BI metric " n" X Set the routing metric of the interface to X .IR n , !RoNnIe!RaYgUn! exit