123175Smckusick /* 229136Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 332787Sbostic * All rights reserved. 423175Smckusick * 532787Sbostic * Redistribution and use in source and binary forms are permitted 634854Sbostic * provided that the above copyright notice and this paragraph are 734854Sbostic * duplicated in all such forms and that any documentation, 834854Sbostic * advertising materials, and other materials related to such 934854Sbostic * distribution and use acknowledge that the software was developed 1034854Sbostic * by the University of California, Berkeley. The name of the 1134854Sbostic * University may not be used to endorse or promote products derived 1234854Sbostic * from this software without specific prior written permission. 1334854Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434854Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534854Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1632787Sbostic * 17*37471Ssklower * @(#)in.c 7.10 (Berkeley) 04/22/89 1823175Smckusick */ 197159Ssam 2017058Sbloom #include "param.h" 2118377Skarels #include "ioctl.h" 2217058Sbloom #include "mbuf.h" 2317058Sbloom #include "protosw.h" 2417058Sbloom #include "socket.h" 2517058Sbloom #include "socketvar.h" 2618377Skarels #include "uio.h" 2718377Skarels #include "dir.h" 2818377Skarels #include "user.h" 2917058Sbloom #include "in_systm.h" 307166Ssam #include "../net/if.h" 317166Ssam #include "../net/route.h" 327159Ssam #include "../net/af.h" 3318377Skarels #include "in.h" 3418377Skarels #include "in_var.h" 357159Ssam 367159Ssam #ifdef INET 377159Ssam /* 3818377Skarels * Formulate an Internet address from network + host. 397159Ssam */ 407159Ssam struct in_addr 4118377Skarels in_makeaddr(net, host) 4218377Skarels u_long net, host; 437159Ssam { 4418377Skarels register struct in_ifaddr *ia; 4518377Skarels register u_long mask; 467159Ssam u_long addr; 477159Ssam 4818377Skarels if (IN_CLASSA(net)) 4918377Skarels mask = IN_CLASSA_HOST; 5018377Skarels else if (IN_CLASSB(net)) 5118377Skarels mask = IN_CLASSB_HOST; 527159Ssam else 5318377Skarels mask = IN_CLASSC_HOST; 5418377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 5518377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 5618377Skarels mask = ~ia->ia_subnetmask; 5718377Skarels break; 5818377Skarels } 5918377Skarels addr = htonl(net | (host & mask)); 607159Ssam return (*(struct in_addr *)&addr); 617159Ssam } 627159Ssam 637159Ssam /* 648595Sroot * Return the network number from an internet address. 657159Ssam */ 6624805Skarels u_long 677159Ssam in_netof(in) 687159Ssam struct in_addr in; 697159Ssam { 708937Sroot register u_long i = ntohl(in.s_addr); 7118377Skarels register u_long net; 7218377Skarels register struct in_ifaddr *ia; 737159Ssam 7418377Skarels if (IN_CLASSA(i)) 7518377Skarels net = i & IN_CLASSA_NET; 7618377Skarels else if (IN_CLASSB(i)) 7718377Skarels net = i & IN_CLASSB_NET; 7831392Skarels else if (IN_CLASSC(i)) 7931392Skarels net = i & IN_CLASSC_NET; 8018377Skarels else 8131392Skarels return (0); 8216413Skarels 8316413Skarels /* 8418377Skarels * Check whether network is a subnet; 8516413Skarels * if so, return subnet number. 8616413Skarels */ 8718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 8824805Skarels if (net == ia->ia_net) 8918377Skarels return (i & ia->ia_subnetmask); 9016413Skarels return (net); 917159Ssam } 927159Ssam 937159Ssam /* 94*37471Ssklower * Compute and save network mask as sockaddr from an internet address. 95*37471Ssklower */ 96*37471Ssklower in_sockmaskof(in, sockmask) 97*37471Ssklower struct in_addr in; 98*37471Ssklower register struct sockaddr_in *sockmask; 99*37471Ssklower { 100*37471Ssklower register u_long net; 101*37471Ssklower register u_long mask; 102*37471Ssklower { 103*37471Ssklower register u_long i = ntohl(in.s_addr); 104*37471Ssklower 105*37471Ssklower if (i == 0) 106*37471Ssklower net = 0, mask = 0; 107*37471Ssklower else if (IN_CLASSA(i)) 108*37471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 109*37471Ssklower else if (IN_CLASSB(i)) 110*37471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 111*37471Ssklower else if (IN_CLASSC(i)) 112*37471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 113*37471Ssklower else 114*37471Ssklower net = i, mask = -1; 115*37471Ssklower } 116*37471Ssklower { 117*37471Ssklower register struct in_ifaddr *ia; 118*37471Ssklower /* 119*37471Ssklower * Check whether network is a subnet; 120*37471Ssklower * if so, return subnet number. 121*37471Ssklower */ 122*37471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 123*37471Ssklower if (net == ia->ia_net) 124*37471Ssklower mask = ia->ia_subnetmask; 125*37471Ssklower } 126*37471Ssklower { 127*37471Ssklower register char *cp = (char *)&(sockmask->sin_port); 128*37471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 129*37471Ssklower 130*37471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 131*37471Ssklower sockmask->sin_len = 0; 132*37471Ssklower while (--cp >= cpbase) 133*37471Ssklower if (*cp) { 134*37471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 135*37471Ssklower break; 136*37471Ssklower } 137*37471Ssklower } 138*37471Ssklower } 139*37471Ssklower 140*37471Ssklower /* 1418595Sroot * Return the host portion of an internet address. 1427159Ssam */ 14326381Skarels u_long 1447159Ssam in_lnaof(in) 1457159Ssam struct in_addr in; 1467159Ssam { 1478937Sroot register u_long i = ntohl(in.s_addr); 14818377Skarels register u_long net, host; 14918377Skarels register struct in_ifaddr *ia; 1507159Ssam 15116377Skarels if (IN_CLASSA(i)) { 15218377Skarels net = i & IN_CLASSA_NET; 15318377Skarels host = i & IN_CLASSA_HOST; 15416377Skarels } else if (IN_CLASSB(i)) { 15518377Skarels net = i & IN_CLASSB_NET; 15618377Skarels host = i & IN_CLASSB_HOST; 15731392Skarels } else if (IN_CLASSC(i)) { 15818377Skarels net = i & IN_CLASSC_NET; 15918377Skarels host = i & IN_CLASSC_HOST; 16031392Skarels } else 16131392Skarels return (i); 1627159Ssam 16316413Skarels /* 16418377Skarels * Check whether network is a subnet; 16516413Skarels * if so, use the modified interpretation of `host'. 16616413Skarels */ 16718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 16824805Skarels if (net == ia->ia_net) 16918377Skarels return (host &~ ia->ia_subnetmask); 17016413Skarels return (host); 17116377Skarels } 17216377Skarels 17326381Skarels #ifndef SUBNETSARELOCAL 17426381Skarels #define SUBNETSARELOCAL 1 17526381Skarels #endif 17626381Skarels int subnetsarelocal = SUBNETSARELOCAL; 17716377Skarels /* 17818377Skarels * Return 1 if an internet address is for a ``local'' host 17926381Skarels * (one to which we have a connection). If subnetsarelocal 18026381Skarels * is true, this includes other subnets of the local net. 18126381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 18217271Skarels */ 18317271Skarels in_localaddr(in) 18417271Skarels struct in_addr in; 18517271Skarels { 18617271Skarels register u_long i = ntohl(in.s_addr); 18718377Skarels register struct in_ifaddr *ia; 18817271Skarels 18930697Skarels if (subnetsarelocal) { 19030697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 19130697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 19230697Skarels return (1); 19330697Skarels } else { 19430697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 19530697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 19630697Skarels return (1); 19730697Skarels } 19818377Skarels return (0); 19918377Skarels } 20018377Skarels 20131392Skarels /* 20231392Skarels * Determine whether an IP address is in a reserved set of addresses 20331392Skarels * that may not be forwarded, or whether datagrams to that destination 20431392Skarels * may be forwarded. 20531392Skarels */ 20631392Skarels in_canforward(in) 20731392Skarels struct in_addr in; 20831392Skarels { 20931392Skarels register u_long i = ntohl(in.s_addr); 21031392Skarels register u_long net; 21131392Skarels 21231392Skarels if (IN_EXPERIMENTAL(i)) 21331392Skarels return (0); 21431392Skarels if (IN_CLASSA(i)) { 21531392Skarels net = i & IN_CLASSA_NET; 21631392Skarels if (net == 0 || net == IN_LOOPBACKNET) 21731392Skarels return (0); 21831392Skarels } 21931392Skarels return (1); 22031392Skarels } 22131392Skarels 22224805Skarels int in_interfaces; /* number of external internet interfaces */ 22324805Skarels extern struct ifnet loif; 22424805Skarels 22518377Skarels /* 22618377Skarels * Generic internet control operations (ioctl's). 22718377Skarels * Ifp is 0 if not an interface-specific ioctl. 22818377Skarels */ 22924805Skarels /* ARGSUSED */ 23018377Skarels in_control(so, cmd, data, ifp) 23118377Skarels struct socket *so; 23218377Skarels int cmd; 23318377Skarels caddr_t data; 23418377Skarels register struct ifnet *ifp; 23518377Skarels { 23618377Skarels register struct ifreq *ifr = (struct ifreq *)data; 23718377Skarels register struct in_ifaddr *ia = 0; 238*37471Ssklower register struct ifaddr *ifa; 239*37471Ssklower struct in_ifaddr *oia; 240*37471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 24118377Skarels struct mbuf *m; 242*37471Ssklower struct sockaddr_in oldaddr; 243*37471Ssklower int error, hostIsNew, maskIsNew; 244*37471Ssklower u_long i; 24518377Skarels 24618377Skarels /* 24718377Skarels * Find address for this interface, if it exists. 24818377Skarels */ 24918377Skarels if (ifp) 25018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 25118377Skarels if (ia->ia_ifp == ifp) 25218377Skarels break; 25318377Skarels 25418377Skarels switch (cmd) { 25518377Skarels 256*37471Ssklower case SIOCAIFADDR: 257*37471Ssklower case SIOCDIFADDR: 258*37471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 259*37471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 260*37471Ssklower if (ia->ia_ifp == ifp && 261*37471Ssklower ia->ia_addr.sin_addr.s_addr == 262*37471Ssklower ifra->ifra_addr.sin_addr.s_addr) 263*37471Ssklower break; 264*37471Ssklower } 265*37471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 266*37471Ssklower return (EADDRNOTAVAIL); 267*37471Ssklower /* FALLTHROUGH */ 26818377Skarels case SIOCSIFADDR: 26918377Skarels case SIOCSIFNETMASK: 27026456Skarels case SIOCSIFDSTADDR: 27118377Skarels if (!suser()) 27218377Skarels return (u.u_error); 27318377Skarels 27418377Skarels if (ifp == 0) 27518377Skarels panic("in_control"); 27618377Skarels if (ia == (struct in_ifaddr *)0) { 27718377Skarels m = m_getclr(M_WAIT, MT_IFADDR); 27818377Skarels if (m == (struct mbuf *)NULL) 27918377Skarels return (ENOBUFS); 28018377Skarels if (ia = in_ifaddr) { 28118377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 28218377Skarels ; 28318377Skarels ia->ia_next = mtod(m, struct in_ifaddr *); 28418377Skarels } else 28518377Skarels in_ifaddr = mtod(m, struct in_ifaddr *); 28618377Skarels ia = mtod(m, struct in_ifaddr *); 28718377Skarels if (ifa = ifp->if_addrlist) { 28818377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 28918377Skarels ; 29018377Skarels ifa->ifa_next = (struct ifaddr *) ia; 29118377Skarels } else 29218377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 293*37471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 294*37471Ssklower ia->ia_ifa.ifa_dstaddr 295*37471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 296*37471Ssklower ia->ia_ifa.ifa_netmask 297*37471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 298*37471Ssklower ia->ia_sockmask.sin_len = 8; 299*37471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 300*37471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 301*37471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 302*37471Ssklower } 30318377Skarels ia->ia_ifp = ifp; 30424805Skarels if (ifp != &loif) 30524805Skarels in_interfaces++; 30617271Skarels } 30718377Skarels break; 30826317Skarels 30926317Skarels case SIOCSIFBRDADDR: 31026317Skarels if (!suser()) 31126317Skarels return (u.u_error); 31226317Skarels /* FALLTHROUGH */ 31326317Skarels 31426317Skarels default: 31526317Skarels if (ia == (struct in_ifaddr *)0) 31626317Skarels return (EADDRNOTAVAIL); 31726317Skarels break; 31817271Skarels } 31918377Skarels switch (cmd) { 32018377Skarels 32118377Skarels case SIOCGIFADDR: 322*37471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 32318377Skarels break; 32418377Skarels 32518377Skarels case SIOCGIFBRDADDR: 32618377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32718377Skarels return (EINVAL); 328*37471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32918377Skarels break; 33018377Skarels 33118377Skarels case SIOCGIFDSTADDR: 33218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33318377Skarels return (EINVAL); 334*37471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33518377Skarels break; 33618377Skarels 33718377Skarels case SIOCGIFNETMASK: 338*37471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33918377Skarels break; 34018377Skarels 34118377Skarels case SIOCSIFDSTADDR: 34218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 34318377Skarels return (EINVAL); 34427066Skarels oldaddr = ia->ia_dstaddr; 345*37471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 34618377Skarels if (ifp->if_ioctl && 34727066Skarels (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 34827066Skarels ia->ia_dstaddr = oldaddr; 34918377Skarels return (error); 35027066Skarels } 35127066Skarels if (ia->ia_flags & IFA_ROUTE) { 352*37471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 353*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 354*37471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr; 355*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35627066Skarels } 35718377Skarels break; 35818377Skarels 35918377Skarels case SIOCSIFBRDADDR: 36018377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 36118377Skarels return (EINVAL); 362*37471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 36318377Skarels break; 36418377Skarels 36518377Skarels case SIOCSIFADDR: 36634500Skarels return (in_ifinit(ifp, ia, 367*37471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36818377Skarels 36918377Skarels case SIOCSIFNETMASK: 370*37471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 371*37471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 37218377Skarels break; 37318377Skarels 374*37471Ssklower case SIOCAIFADDR: 375*37471Ssklower maskIsNew = 0; hostIsNew = 1; error = u.u_error; 376*37471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 377*37471Ssklower if (ifra->ifra_addr.sin_len == 0) { 378*37471Ssklower ifra->ifra_addr = ia->ia_addr; 379*37471Ssklower hostIsNew = 0; 380*37471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 381*37471Ssklower ia->ia_addr.sin_addr.s_addr) 382*37471Ssklower hostIsNew = 0; 383*37471Ssklower } 384*37471Ssklower if (ifra->ifra_mask.sin_len) { 385*37471Ssklower in_ifscrub(ifp, ia); 386*37471Ssklower ia->ia_sockmask = ifra->ifra_mask; 387*37471Ssklower ia->ia_subnetmask = 388*37471Ssklower ntohl(ia->ia_sockmask.sin_addr.s_addr); 389*37471Ssklower maskIsNew = 1; 390*37471Ssklower } 391*37471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 392*37471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 393*37471Ssklower in_ifscrub(ifp, ia); 394*37471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 395*37471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 396*37471Ssklower } 397*37471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 398*37471Ssklower (hostIsNew || maskIsNew)) 399*37471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 400*37471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 401*37471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 402*37471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 403*37471Ssklower return (error); 404*37471Ssklower 405*37471Ssklower case SIOCDIFADDR: 406*37471Ssklower in_ifscrub(ifp, ia); 407*37471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 408*37471Ssklower ifp->if_addrlist = ifa->ifa_next; 409*37471Ssklower else { 410*37471Ssklower while (ifa->ifa_next && 411*37471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 412*37471Ssklower ifa = ifa->ifa_next; 413*37471Ssklower if (ifa->ifa_next) 414*37471Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 415*37471Ssklower else 416*37471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 417*37471Ssklower } 418*37471Ssklower oia = ia; 419*37471Ssklower if (oia == (ia = in_ifaddr)) { 420*37471Ssklower in_ifaddr = ia->ia_next; 421*37471Ssklower } else { 422*37471Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 423*37471Ssklower ia = ia->ia_next; 424*37471Ssklower } 425*37471Ssklower if (ia->ia_next) 426*37471Ssklower ia->ia_next = oia->ia_next; 427*37471Ssklower else 428*37471Ssklower printf("Didn't unlink inifadr from list\n"); 429*37471Ssklower } 430*37471Ssklower (void) m_free(dtom(oia)); 431*37471Ssklower break; 432*37471Ssklower 43318377Skarels default: 43418377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43518377Skarels return (EOPNOTSUPP); 43618377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43718377Skarels } 43817271Skarels return (0); 43917271Skarels } 44017271Skarels 44117271Skarels /* 442*37471Ssklower * Delete any existing route for an interface. 443*37471Ssklower */ 444*37471Ssklower in_ifscrub(ifp, ia) 445*37471Ssklower register struct ifnet *ifp; 446*37471Ssklower register struct in_ifaddr *ia; 447*37471Ssklower { 448*37471Ssklower 449*37471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 450*37471Ssklower return; 451*37471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 452*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 453*37471Ssklower else 454*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 455*37471Ssklower ia->ia_flags &= ~IFA_ROUTE; 456*37471Ssklower } 457*37471Ssklower 458*37471Ssklower /* 45918377Skarels * Initialize an interface's internet address 46018377Skarels * and routing table entry. 4617159Ssam */ 462*37471Ssklower in_ifinit(ifp, ia, sin, scrub) 4637159Ssam register struct ifnet *ifp; 46418377Skarels register struct in_ifaddr *ia; 46518377Skarels struct sockaddr_in *sin; 4667159Ssam { 46718377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 468*37471Ssklower struct sockaddr_in oldaddr; 46918377Skarels int s = splimp(), error; 4707159Ssam 47127066Skarels oldaddr = ia->ia_addr; 472*37471Ssklower ia->ia_addr = *sin; 47318377Skarels /* 47426317Skarels * Give the interface a chance to initialize 47526317Skarels * if this is its first address, 47626317Skarels * and to validate the address if necessary. 47726317Skarels */ 47826317Skarels if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 47926317Skarels splx(s); 48027066Skarels ia->ia_addr = oldaddr; 48126317Skarels return (error); 48226317Skarels } 483*37471Ssklower if (scrub) { 484*37471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 485*37471Ssklower in_ifscrub(ifp, ia); 486*37471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 48718377Skarels } 48818377Skarels if (IN_CLASSA(i)) 48918377Skarels ia->ia_netmask = IN_CLASSA_NET; 49018377Skarels else if (IN_CLASSB(i)) 49118377Skarels ia->ia_netmask = IN_CLASSB_NET; 49218377Skarels else 49318377Skarels ia->ia_netmask = IN_CLASSC_NET; 49418377Skarels ia->ia_net = i & ia->ia_netmask; 49518377Skarels /* 49618377Skarels * The subnet mask includes at least the standard network part, 49718377Skarels * but may already have been set to a larger value. 49818377Skarels */ 49918377Skarels ia->ia_subnetmask |= ia->ia_netmask; 50018377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 501*37471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 50218377Skarels if (ifp->if_flags & IFF_BROADCAST) { 503*37471Ssklower ia->ia_broadaddr.sin_addr = 50418377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 50525195Skarels ia->ia_netbroadcast.s_addr = 50625195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 50718377Skarels } 50818377Skarels /* 50918377Skarels * Add route for the network. 51018377Skarels */ 511*37471Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 512*37471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 513*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 514*37471Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 515*37471Ssklower ia->ia_dstaddr.sin_family == AF_INET) 516*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 51727066Skarels else { 518*37471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 51927066Skarels } 52018377Skarels ia->ia_flags |= IFA_ROUTE; 52130523Skarels splx(s); 52218642Skarels return (0); 5237159Ssam } 52418377Skarels 52518377Skarels /* 52618377Skarels * Return address info for specified internet network. 52718377Skarels */ 52818377Skarels struct in_ifaddr * 52918377Skarels in_iaonnetof(net) 53018377Skarels u_long net; 53118377Skarels { 53218377Skarels register struct in_ifaddr *ia; 53318377Skarels 53418377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 53518377Skarels if (ia->ia_subnet == net) 53618377Skarels return (ia); 53718377Skarels return ((struct in_ifaddr *)0); 53818377Skarels } 53918377Skarels 54018377Skarels /* 54130523Skarels * Return 1 if the address might be a local broadcast address. 54218377Skarels */ 54318377Skarels in_broadcast(in) 54418377Skarels struct in_addr in; 54518377Skarels { 54618377Skarels register struct in_ifaddr *ia; 54730523Skarels u_long t; 54818377Skarels 54918377Skarels /* 55018377Skarels * Look through the list of addresses for a match 55118377Skarels * with a broadcast address. 55218377Skarels */ 55318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 55430523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 555*37471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 55618377Skarels return (1); 55730523Skarels /* 55830523Skarels * Check for old-style (host 0) broadcast. 55930523Skarels */ 56030523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 56130523Skarels return (1); 56230523Skarels } 56330523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 56430523Skarels return (1); 56518377Skarels return (0); 56618377Skarels } 5677159Ssam #endif 568