1*17271Skarels /* in.c 6.5 84/10/19 */ 27159Ssam 317058Sbloom #include "param.h" 417058Sbloom #include "mbuf.h" 517058Sbloom #include "protosw.h" 617058Sbloom #include "socket.h" 717058Sbloom #include "socketvar.h" 817058Sbloom #include "in.h" 917058Sbloom #include "in_systm.h" 107166Ssam #include "../net/if.h" 117166Ssam #include "../net/route.h" 127159Ssam #include "../net/af.h" 137159Ssam 147159Ssam #ifdef INET 157159Ssam inet_hash(sin, hp) 167159Ssam register struct sockaddr_in *sin; 177159Ssam struct afhash *hp; 187159Ssam { 198595Sroot 207159Ssam hp->afh_nethash = in_netof(sin->sin_addr); 218937Sroot hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); 227159Ssam } 237159Ssam 247159Ssam inet_netmatch(sin1, sin2) 257159Ssam struct sockaddr_in *sin1, *sin2; 267159Ssam { 278595Sroot 2811566Ssam return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); 297159Ssam } 307159Ssam 317159Ssam /* 327159Ssam * Formulate an Internet address from network + host. Used in 337159Ssam * building addresses stored in the ifnet structure. 347159Ssam */ 357159Ssam struct in_addr 367159Ssam if_makeaddr(net, host) 377159Ssam int net, host; 387159Ssam { 397159Ssam u_long addr; 407159Ssam 4116377Skarels if (net < IN_CLASSA_MAX) 428694Sroot addr = (net << IN_CLASSA_NSHIFT) | host; 4316377Skarels else if (net < IN_CLASSB_MAX) 448694Sroot addr = (net << IN_CLASSB_NSHIFT) | host; 457159Ssam else 468694Sroot addr = (net << IN_CLASSC_NSHIFT) | host; 477159Ssam addr = htonl(addr); 487159Ssam return (*(struct in_addr *)&addr); 497159Ssam } 507159Ssam 517159Ssam /* 528595Sroot * Return the network number from an internet address. 537159Ssam */ 547159Ssam in_netof(in) 557159Ssam struct in_addr in; 567159Ssam { 578937Sroot register u_long i = ntohl(in.s_addr); 5816413Skarels register u_long net, subnet; 5916413Skarels register struct ifnet *ifp; 607159Ssam 6116377Skarels if (IN_CLASSA(i)) { 6216413Skarels net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT; 6316413Skarels if (IN_SUBNETA(i)) { 6416413Skarels subnet = (i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT; 6516413Skarels /* Fall through and check whether a subnet */ 6616413Skarels } else 6716377Skarels return (net); 6816377Skarels } else if (IN_CLASSB(i)) { 6916413Skarels net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT; 7016413Skarels if (IN_SUBNETB(i)) { 7116413Skarels subnet = (i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT; 7216413Skarels /* Fall through and check whether a subnet */ 7316413Skarels } else 7416377Skarels return (net); 7516377Skarels } else { 7616413Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 7716377Skarels } 7816413Skarels 7916413Skarels /* 8016413Skarels * Check whether network is a subnet of a `local' network; 8116413Skarels * if so, return subnet number. 8216413Skarels */ 8316413Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) { 8416413Skarels if (ifp->if_addr.sa_family != AF_INET) 8516413Skarels continue; 8616413Skarels if (ifp->if_flags & IFF_LOCAL) { 8716413Skarels if (ifp->if_net == net) 8816413Skarels return (subnet); 8916413Skarels if ((ifp->if_net >> SUBNETSHIFT) == net) 9016413Skarels return (subnet); 9116413Skarels /* 9216413Skarels * Hack for use in setting if_net initially. 9316413Skarels */ 9416413Skarels if (ifp->if_net == 0) { 9516413Skarels register struct sockaddr_in *sin; 9616413Skarels sin = (struct sockaddr_in *) &ifp->if_addr; 9716413Skarels if (sin->sin_addr.s_addr == in.s_addr) 9816413Skarels return (subnet); 9916413Skarels } 10016413Skarels } 10116413Skarels } 10216413Skarels return (net); 1037159Ssam } 1047159Ssam 1057159Ssam /* 1068595Sroot * Return the host portion of an internet address. 1077159Ssam */ 1087159Ssam in_lnaof(in) 1097159Ssam struct in_addr in; 1107159Ssam { 1118937Sroot register u_long i = ntohl(in.s_addr); 11216413Skarels register u_long net, host, subhost; 11316413Skarels register struct ifnet *ifp; 1147159Ssam 11516377Skarels if (IN_CLASSA(i)) { 11616413Skarels if (IN_SUBNETA(i)) { 11716413Skarels net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT; 11816413Skarels host = i & IN_CLASSA_HOST; 11916413Skarels subhost = i & IN_CLASSA_SUBHOST; 12016413Skarels /* Fall through and check whether a subnet */ 12116413Skarels } else 12216413Skarels return (i & IN_CLASSA_HOST); 12316377Skarels } else if (IN_CLASSB(i)) { 12416413Skarels if (IN_SUBNETB(i)) { 12516413Skarels net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT; 12616413Skarels host = i & IN_CLASSB_HOST; 12716413Skarels subhost = i & IN_CLASSB_SUBHOST; 12816413Skarels /* Fall through and check whether a subnet */ 12916413Skarels } else 13016413Skarels return (i & IN_CLASSB_HOST); 13116377Skarels } else { 13216413Skarels return (i & IN_CLASSC_HOST); 13316377Skarels } 1347159Ssam 13516413Skarels /* 13616413Skarels * Check whether network is a subnet of a `local' network; 13716413Skarels * if so, use the modified interpretation of `host'. 13816413Skarels */ 13916377Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) { 14016377Skarels if (ifp->if_addr.sa_family != AF_INET) 14116377Skarels continue; 14216377Skarels if (ifp->if_flags & IFF_LOCAL) { 14316377Skarels if (ifp->if_net == net) 14416413Skarels return (subhost); 14516377Skarels if ((ifp->if_net >> SUBNETSHIFT) == net) 14616413Skarels return (subhost); 14716377Skarels } 14816377Skarels } 14916413Skarels return (host); 15016377Skarels } 15116377Skarels 15216377Skarels /* 153*17271Skarels * Return 1 if an internet address is for a ``local'' host. 154*17271Skarels */ 155*17271Skarels in_localaddr(in) 156*17271Skarels struct in_addr in; 157*17271Skarels { 158*17271Skarels register u_long i = ntohl(in.s_addr); 159*17271Skarels register u_long net; 160*17271Skarels register struct ifnet *ifp; 161*17271Skarels 162*17271Skarels if (IN_CLASSA(i)) 163*17271Skarels net = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT; 164*17271Skarels else if (IN_CLASSB(i)) 165*17271Skarels net = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT; 166*17271Skarels else 167*17271Skarels net = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT; 168*17271Skarels 169*17271Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) { 170*17271Skarels if (ifp->if_addr.sa_family != AF_INET) 171*17271Skarels continue; 172*17271Skarels if (ifp->if_flags & IFF_LOCAL) { 173*17271Skarels if (ifp->if_net == net) 174*17271Skarels return (1); 175*17271Skarels if ((ifp->if_net >> SUBNETSHIFT) == net) 176*17271Skarels return (1); 177*17271Skarels } 178*17271Skarels } 179*17271Skarels return (0); 180*17271Skarels } 181*17271Skarels 182*17271Skarels /* 1837159Ssam * Initialize an interface's routing 1847159Ssam * table entry according to the network. 1857159Ssam * INTERNET SPECIFIC. 1867159Ssam */ 1877159Ssam if_rtinit(ifp, flags) 1887159Ssam register struct ifnet *ifp; 1897159Ssam int flags; 1907159Ssam { 1917159Ssam struct sockaddr_in sin; 1927159Ssam 1937159Ssam if (ifp->if_flags & IFF_ROUTE) 1947159Ssam return; 1957159Ssam bzero((caddr_t)&sin, sizeof (sin)); 1967159Ssam sin.sin_family = AF_INET; 19711566Ssam sin.sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); 1988637Sroot rtinit((struct sockaddr *)&sin, &ifp->if_addr, flags); 1997159Ssam } 2007159Ssam #endif 201