1*18377Skarels /* in.c 6.6 85/03/18 */ 27159Ssam 317058Sbloom #include "param.h" 4*18377Skarels #include "ioctl.h" 517058Sbloom #include "mbuf.h" 617058Sbloom #include "protosw.h" 717058Sbloom #include "socket.h" 817058Sbloom #include "socketvar.h" 9*18377Skarels #include "uio.h" 10*18377Skarels #include "dir.h" 11*18377Skarels #include "user.h" 1217058Sbloom #include "in_systm.h" 137166Ssam #include "../net/if.h" 147166Ssam #include "../net/route.h" 157159Ssam #include "../net/af.h" 16*18377Skarels #include "in.h" 17*18377Skarels #include "in_var.h" 187159Ssam 197159Ssam #ifdef INET 207159Ssam inet_hash(sin, hp) 217159Ssam register struct sockaddr_in *sin; 227159Ssam struct afhash *hp; 237159Ssam { 24*18377Skarels register u_long n; 258595Sroot 26*18377Skarels n = in_netof(sin->sin_addr); 27*18377Skarels if (n) 28*18377Skarels while ((n & 0xff) == 0) 29*18377Skarels n >>= 8; 30*18377Skarels hp->afh_nethash = n; 318937Sroot hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); 327159Ssam } 337159Ssam 347159Ssam inet_netmatch(sin1, sin2) 357159Ssam struct sockaddr_in *sin1, *sin2; 367159Ssam { 378595Sroot 3811566Ssam return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); 397159Ssam } 407159Ssam 417159Ssam /* 42*18377Skarels * Formulate an Internet address from network + host. 437159Ssam */ 447159Ssam struct in_addr 45*18377Skarels in_makeaddr(net, host) 46*18377Skarels u_long net, host; 477159Ssam { 48*18377Skarels register struct in_ifaddr *ia; 49*18377Skarels register u_long mask; 507159Ssam u_long addr; 517159Ssam 52*18377Skarels if (IN_CLASSA(net)) 53*18377Skarels mask = IN_CLASSA_HOST; 54*18377Skarels else if (IN_CLASSB(net)) 55*18377Skarels mask = IN_CLASSB_HOST; 567159Ssam else 57*18377Skarels mask = IN_CLASSC_HOST; 58*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 59*18377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 60*18377Skarels mask = ~ia->ia_subnetmask; 61*18377Skarels break; 62*18377Skarels } 63*18377Skarels addr = htonl(net | (host & mask)); 647159Ssam return (*(struct in_addr *)&addr); 657159Ssam } 667159Ssam 677159Ssam /* 688595Sroot * Return the network number from an internet address. 697159Ssam */ 707159Ssam in_netof(in) 717159Ssam struct in_addr in; 727159Ssam { 738937Sroot register u_long i = ntohl(in.s_addr); 74*18377Skarels register u_long net; 75*18377Skarels register struct in_ifaddr *ia; 767159Ssam 77*18377Skarels if (IN_CLASSA(i)) 78*18377Skarels net = i & IN_CLASSA_NET; 79*18377Skarels else if (IN_CLASSB(i)) 80*18377Skarels net = i & IN_CLASSB_NET; 81*18377Skarels else 82*18377Skarels net = i & IN_CLASSC_NET; 8316413Skarels 8416413Skarels /* 85*18377Skarels * Check whether network is a subnet; 8616413Skarels * if so, return subnet number. 8716413Skarels */ 88*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 89*18377Skarels if ((ia->ia_netmask & net) == ia->ia_net) 90*18377Skarels return (i & ia->ia_subnetmask); 9116413Skarels return (net); 927159Ssam } 937159Ssam 947159Ssam /* 958595Sroot * Return the host portion of an internet address. 967159Ssam */ 977159Ssam in_lnaof(in) 987159Ssam struct in_addr in; 997159Ssam { 1008937Sroot register u_long i = ntohl(in.s_addr); 101*18377Skarels register u_long net, host; 102*18377Skarels register struct in_ifaddr *ia; 1037159Ssam 10416377Skarels if (IN_CLASSA(i)) { 105*18377Skarels net = i & IN_CLASSA_NET; 106*18377Skarels host = i & IN_CLASSA_HOST; 10716377Skarels } else if (IN_CLASSB(i)) { 108*18377Skarels net = i & IN_CLASSB_NET; 109*18377Skarels host = i & IN_CLASSB_HOST; 11016377Skarels } else { 111*18377Skarels net = i & IN_CLASSC_NET; 112*18377Skarels host = i & IN_CLASSC_HOST; 11316377Skarels } 1147159Ssam 11516413Skarels /* 116*18377Skarels * Check whether network is a subnet; 11716413Skarels * if so, use the modified interpretation of `host'. 11816413Skarels */ 119*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 120*18377Skarels if ((ia->ia_netmask & net) == ia->ia_net) 121*18377Skarels return (host &~ ia->ia_subnetmask); 12216413Skarels return (host); 12316377Skarels } 12416377Skarels 12516377Skarels /* 126*18377Skarels * Return 1 if an internet address is for a ``local'' host 127*18377Skarels * (one to which we have a connection). 12817271Skarels */ 12917271Skarels in_localaddr(in) 13017271Skarels struct in_addr in; 13117271Skarels { 13217271Skarels register u_long i = ntohl(in.s_addr); 13317271Skarels register u_long net; 134*18377Skarels register struct in_ifaddr *ia; 13517271Skarels 13617271Skarels if (IN_CLASSA(i)) 137*18377Skarels net = i & IN_CLASSA_NET; 13817271Skarels else if (IN_CLASSB(i)) 139*18377Skarels net = i & IN_CLASSB_NET; 14017271Skarels else 141*18377Skarels net = i & IN_CLASSC_NET; 14217271Skarels 143*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 144*18377Skarels if ((ia->ia_netmask & net) == ia->ia_net) 145*18377Skarels return (1); 146*18377Skarels return (0); 147*18377Skarels } 148*18377Skarels 149*18377Skarels /* 150*18377Skarels * Generic internet control operations (ioctl's). 151*18377Skarels * Ifp is 0 if not an interface-specific ioctl. 152*18377Skarels */ 153*18377Skarels in_control(so, cmd, data, ifp) 154*18377Skarels struct socket *so; 155*18377Skarels int cmd; 156*18377Skarels caddr_t data; 157*18377Skarels register struct ifnet *ifp; 158*18377Skarels { 159*18377Skarels register struct ifreq *ifr = (struct ifreq *)data; 160*18377Skarels register struct in_ifaddr *ia = 0; 161*18377Skarels struct ifaddr *ifa; 162*18377Skarels struct mbuf *m; 163*18377Skarels int error; 164*18377Skarels 165*18377Skarels /* 166*18377Skarels * Find address for this interface, if it exists. 167*18377Skarels */ 168*18377Skarels if (ifp) 169*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 170*18377Skarels if (ia->ia_ifp == ifp) 171*18377Skarels break; 172*18377Skarels 173*18377Skarels switch (cmd) { 174*18377Skarels 175*18377Skarels case SIOCGIFADDR: 176*18377Skarels case SIOCGIFBRDADDR: 177*18377Skarels case SIOCGIFDSTADDR: 178*18377Skarels case SIOCGIFNETMASK: 179*18377Skarels if (ia == (struct in_ifaddr *)0) 180*18377Skarels return (EADDRNOTAVAIL); 181*18377Skarels break; 182*18377Skarels 183*18377Skarels case SIOCSIFADDR: 184*18377Skarels case SIOCSIFDSTADDR: 185*18377Skarels case SIOCSIFBRDADDR: 186*18377Skarels case SIOCSIFNETMASK: 187*18377Skarels if (!suser()) 188*18377Skarels return (u.u_error); 189*18377Skarels 190*18377Skarels if (ifp == 0) 191*18377Skarels panic("in_control"); 192*18377Skarels if (ia == (struct in_ifaddr *)0) { 193*18377Skarels m = m_getclr(M_WAIT, MT_IFADDR); 194*18377Skarels if (m == (struct mbuf *)NULL) 195*18377Skarels return (ENOBUFS); 196*18377Skarels if (ia = in_ifaddr) { 197*18377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 198*18377Skarels ; 199*18377Skarels ia->ia_next = mtod(m, struct in_ifaddr *); 200*18377Skarels } else 201*18377Skarels in_ifaddr = mtod(m, struct in_ifaddr *); 202*18377Skarels ia = mtod(m, struct in_ifaddr *); 203*18377Skarels if (ifa = ifp->if_addrlist) { 204*18377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 205*18377Skarels ; 206*18377Skarels ifa->ifa_next = (struct ifaddr *) ia; 207*18377Skarels } else 208*18377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 209*18377Skarels ia->ia_ifp = ifp; 210*18377Skarels IA_SIN(ia)->sin_family = AF_INET; 21117271Skarels } 212*18377Skarels break; 21317271Skarels } 214*18377Skarels 215*18377Skarels switch (cmd) { 216*18377Skarels 217*18377Skarels case SIOCGIFADDR: 218*18377Skarels ifr->ifr_addr = ia->ia_addr; 219*18377Skarels break; 220*18377Skarels 221*18377Skarels case SIOCGIFBRDADDR: 222*18377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 223*18377Skarels return (EINVAL); 224*18377Skarels ifr->ifr_dstaddr = ia->ia_broadaddr; 225*18377Skarels break; 226*18377Skarels 227*18377Skarels case SIOCGIFDSTADDR: 228*18377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 229*18377Skarels return (EINVAL); 230*18377Skarels ifr->ifr_dstaddr = ia->ia_dstaddr; 231*18377Skarels break; 232*18377Skarels 233*18377Skarels case SIOCGIFNETMASK: 234*18377Skarels #define satosin(sa) ((struct sockaddr_in *)(sa)) 235*18377Skarels satosin(&ifr->ifr_addr)->sin_family = AF_INET; 236*18377Skarels satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); 237*18377Skarels break; 238*18377Skarels 239*18377Skarels case SIOCSIFDSTADDR: 240*18377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 241*18377Skarels return (EINVAL); 242*18377Skarels if (ifp->if_ioctl && 243*18377Skarels (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) 244*18377Skarels return (error); 245*18377Skarels ia->ia_dstaddr = ifr->ifr_dstaddr; 246*18377Skarels break; 247*18377Skarels 248*18377Skarels case SIOCSIFBRDADDR: 249*18377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 250*18377Skarels return (EINVAL); 251*18377Skarels ia->ia_broadaddr = ifr->ifr_broadaddr; 252*18377Skarels break; 253*18377Skarels 254*18377Skarels case SIOCSIFADDR: 255*18377Skarels return (in_ifinit(ifp, ia, &ifr->ifr_addr)); 256*18377Skarels break; 257*18377Skarels 258*18377Skarels case SIOCSIFNETMASK: 259*18377Skarels ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); 260*18377Skarels break; 261*18377Skarels 262*18377Skarels default: 263*18377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 264*18377Skarels return (EOPNOTSUPP); 265*18377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 266*18377Skarels } 26717271Skarels return (0); 26817271Skarels } 26917271Skarels 27017271Skarels /* 271*18377Skarels * Initialize an interface's internet address 272*18377Skarels * and routing table entry. 2737159Ssam */ 274*18377Skarels in_ifinit(ifp, ia, sin) 2757159Ssam register struct ifnet *ifp; 276*18377Skarels register struct in_ifaddr *ia; 277*18377Skarels struct sockaddr_in *sin; 2787159Ssam { 279*18377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 280*18377Skarels struct sockaddr_in netaddr; 281*18377Skarels int s = splimp(), error; 2827159Ssam 283*18377Skarels bzero((caddr_t)&netaddr, sizeof (netaddr)); 284*18377Skarels netaddr.sin_family = AF_INET; 285*18377Skarels /* 286*18377Skarels * Delete any previous route for an old address. 287*18377Skarels */ 288*18377Skarels if (ia->ia_flags & IFA_ROUTE) { 289*18377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 290*18377Skarels netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 291*18377Skarels rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 292*18377Skarels } else 293*18377Skarels rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 294*18377Skarels ia->ia_flags &= ~IFA_ROUTE; 295*18377Skarels } 296*18377Skarels ia->ia_addr = *(struct sockaddr *)sin; 297*18377Skarels if (IN_CLASSA(i)) 298*18377Skarels ia->ia_netmask = IN_CLASSA_NET; 299*18377Skarels else if (IN_CLASSB(i)) 300*18377Skarels ia->ia_netmask = IN_CLASSB_NET; 301*18377Skarels else 302*18377Skarels ia->ia_netmask = IN_CLASSC_NET; 303*18377Skarels ia->ia_net = i & ia->ia_netmask; 304*18377Skarels /* 305*18377Skarels * The subnet mask includes at least the standard network part, 306*18377Skarels * but may already have been set to a larger value. 307*18377Skarels */ 308*18377Skarels ia->ia_subnetmask |= ia->ia_netmask; 309*18377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 310*18377Skarels if (ifp->if_flags & IFF_BROADCAST) { 311*18377Skarels ia->ia_broadaddr.sa_family = AF_INET; 312*18377Skarels ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr = 313*18377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 314*18377Skarels } 315*18377Skarels 316*18377Skarels /* 317*18377Skarels * Give the interface a chance to initialize 318*18377Skarels * if this is its first address, 319*18377Skarels * and to validate the address if necessary. 320*18377Skarels */ 321*18377Skarels if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 322*18377Skarels splx(s); 323*18377Skarels bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr)); 324*18377Skarels return (error); 325*18377Skarels } 326*18377Skarels splx(s); 327*18377Skarels /* 328*18377Skarels * Add route for the network. 329*18377Skarels */ 330*18377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 331*18377Skarels netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 332*18377Skarels rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 333*18377Skarels } else 334*18377Skarels rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, 335*18377Skarels RTF_HOST|RTF_UP); 336*18377Skarels ia->ia_flags |= IFA_ROUTE; 3377159Ssam } 338*18377Skarels 339*18377Skarels /* 340*18377Skarels * Return address info for specified internet network. 341*18377Skarels */ 342*18377Skarels struct in_ifaddr * 343*18377Skarels in_iaonnetof(net) 344*18377Skarels u_long net; 345*18377Skarels { 346*18377Skarels register struct in_ifaddr *ia; 347*18377Skarels 348*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 349*18377Skarels if (ia->ia_subnet == net) 350*18377Skarels return (ia); 351*18377Skarels return ((struct in_ifaddr *)0); 352*18377Skarels } 353*18377Skarels 354*18377Skarels /* 355*18377Skarels * Return 1 if the address is a local broadcast address. 356*18377Skarels */ 357*18377Skarels in_broadcast(in) 358*18377Skarels struct in_addr in; 359*18377Skarels { 360*18377Skarels register struct in_ifaddr *ia; 361*18377Skarels 362*18377Skarels /* 363*18377Skarels * Look through the list of addresses for a match 364*18377Skarels * with a broadcast address. 365*18377Skarels */ 366*18377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 367*18377Skarels if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr == 368*18377Skarels in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST)) 369*18377Skarels return (1); 370*18377Skarels return (0); 371*18377Skarels } 3727159Ssam #endif 373