123175Smckusick /* 229136Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 332787Sbostic * All rights reserved. 423175Smckusick * 5*44472Sbostic * %sccs.include.redist.c% 632787Sbostic * 7*44472Sbostic * @(#)in.c 7.15 (Berkeley) 06/28/90 823175Smckusick */ 97159Ssam 1017058Sbloom #include "param.h" 1118377Skarels #include "ioctl.h" 1217058Sbloom #include "mbuf.h" 1317058Sbloom #include "protosw.h" 1417058Sbloom #include "socket.h" 1517058Sbloom #include "socketvar.h" 1618377Skarels #include "user.h" 1717058Sbloom #include "in_systm.h" 187166Ssam #include "../net/if.h" 197166Ssam #include "../net/route.h" 207159Ssam #include "../net/af.h" 2118377Skarels #include "in.h" 2218377Skarels #include "in_var.h" 237159Ssam 247159Ssam #ifdef INET 257159Ssam /* 2618377Skarels * Formulate an Internet address from network + host. 277159Ssam */ 287159Ssam struct in_addr 2918377Skarels in_makeaddr(net, host) 3018377Skarels u_long net, host; 317159Ssam { 3218377Skarels register struct in_ifaddr *ia; 3318377Skarels register u_long mask; 347159Ssam u_long addr; 357159Ssam 3618377Skarels if (IN_CLASSA(net)) 3718377Skarels mask = IN_CLASSA_HOST; 3818377Skarels else if (IN_CLASSB(net)) 3918377Skarels mask = IN_CLASSB_HOST; 407159Ssam else 4118377Skarels mask = IN_CLASSC_HOST; 4218377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 4318377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 4418377Skarels mask = ~ia->ia_subnetmask; 4518377Skarels break; 4618377Skarels } 4718377Skarels addr = htonl(net | (host & mask)); 487159Ssam return (*(struct in_addr *)&addr); 497159Ssam } 507159Ssam 517159Ssam /* 528595Sroot * Return the network number from an internet address. 537159Ssam */ 5424805Skarels u_long 557159Ssam in_netof(in) 567159Ssam struct in_addr in; 577159Ssam { 588937Sroot register u_long i = ntohl(in.s_addr); 5918377Skarels register u_long net; 6018377Skarels register struct in_ifaddr *ia; 617159Ssam 6218377Skarels if (IN_CLASSA(i)) 6318377Skarels net = i & IN_CLASSA_NET; 6418377Skarels else if (IN_CLASSB(i)) 6518377Skarels net = i & IN_CLASSB_NET; 6631392Skarels else if (IN_CLASSC(i)) 6731392Skarels net = i & IN_CLASSC_NET; 6818377Skarels else 6931392Skarels return (0); 7016413Skarels 7116413Skarels /* 7218377Skarels * Check whether network is a subnet; 7316413Skarels * if so, return subnet number. 7416413Skarels */ 7518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 7624805Skarels if (net == ia->ia_net) 7718377Skarels return (i & ia->ia_subnetmask); 7816413Skarels return (net); 797159Ssam } 807159Ssam 817159Ssam /* 8237471Ssklower * Compute and save network mask as sockaddr from an internet address. 8337471Ssklower */ 8437471Ssklower in_sockmaskof(in, sockmask) 8537471Ssklower struct in_addr in; 8637471Ssklower register struct sockaddr_in *sockmask; 8737471Ssklower { 8837471Ssklower register u_long net; 8937471Ssklower register u_long mask; 9037471Ssklower { 9137471Ssklower register u_long i = ntohl(in.s_addr); 9237471Ssklower 9337471Ssklower if (i == 0) 9437471Ssklower net = 0, mask = 0; 9537471Ssklower else if (IN_CLASSA(i)) 9637471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 9737471Ssklower else if (IN_CLASSB(i)) 9837471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 9937471Ssklower else if (IN_CLASSC(i)) 10037471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 10137471Ssklower else 10237471Ssklower net = i, mask = -1; 10337471Ssklower } 10437471Ssklower { 10537471Ssklower register struct in_ifaddr *ia; 10637471Ssklower /* 10737471Ssklower * Check whether network is a subnet; 10837471Ssklower * if so, return subnet number. 10937471Ssklower */ 11037471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 11137471Ssklower if (net == ia->ia_net) 11237471Ssklower mask = ia->ia_subnetmask; 11337471Ssklower } 11437471Ssklower { 11537471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 11639183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 11737471Ssklower 11837471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 11937471Ssklower sockmask->sin_len = 0; 12037471Ssklower while (--cp >= cpbase) 12137471Ssklower if (*cp) { 12237471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 12337471Ssklower break; 12437471Ssklower } 12537471Ssklower } 12637471Ssklower } 12737471Ssklower 12837471Ssklower /* 1298595Sroot * Return the host portion of an internet address. 1307159Ssam */ 13126381Skarels u_long 1327159Ssam in_lnaof(in) 1337159Ssam struct in_addr in; 1347159Ssam { 1358937Sroot register u_long i = ntohl(in.s_addr); 13618377Skarels register u_long net, host; 13718377Skarels register struct in_ifaddr *ia; 1387159Ssam 13916377Skarels if (IN_CLASSA(i)) { 14018377Skarels net = i & IN_CLASSA_NET; 14118377Skarels host = i & IN_CLASSA_HOST; 14216377Skarels } else if (IN_CLASSB(i)) { 14318377Skarels net = i & IN_CLASSB_NET; 14418377Skarels host = i & IN_CLASSB_HOST; 14531392Skarels } else if (IN_CLASSC(i)) { 14618377Skarels net = i & IN_CLASSC_NET; 14718377Skarels host = i & IN_CLASSC_HOST; 14831392Skarels } else 14931392Skarels return (i); 1507159Ssam 15116413Skarels /* 15218377Skarels * Check whether network is a subnet; 15316413Skarels * if so, use the modified interpretation of `host'. 15416413Skarels */ 15518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 15624805Skarels if (net == ia->ia_net) 15718377Skarels return (host &~ ia->ia_subnetmask); 15816413Skarels return (host); 15916377Skarels } 16016377Skarels 16126381Skarels #ifndef SUBNETSARELOCAL 16226381Skarels #define SUBNETSARELOCAL 1 16326381Skarels #endif 16426381Skarels int subnetsarelocal = SUBNETSARELOCAL; 16516377Skarels /* 16618377Skarels * Return 1 if an internet address is for a ``local'' host 16726381Skarels * (one to which we have a connection). If subnetsarelocal 16826381Skarels * is true, this includes other subnets of the local net. 16926381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 17017271Skarels */ 17117271Skarels in_localaddr(in) 17217271Skarels struct in_addr in; 17317271Skarels { 17417271Skarels register u_long i = ntohl(in.s_addr); 17518377Skarels register struct in_ifaddr *ia; 17617271Skarels 17730697Skarels if (subnetsarelocal) { 17830697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 17930697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 18030697Skarels return (1); 18130697Skarels } else { 18230697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18330697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 18430697Skarels return (1); 18530697Skarels } 18618377Skarels return (0); 18718377Skarels } 18818377Skarels 18931392Skarels /* 19031392Skarels * Determine whether an IP address is in a reserved set of addresses 19131392Skarels * that may not be forwarded, or whether datagrams to that destination 19231392Skarels * may be forwarded. 19331392Skarels */ 19431392Skarels in_canforward(in) 19531392Skarels struct in_addr in; 19631392Skarels { 19731392Skarels register u_long i = ntohl(in.s_addr); 19831392Skarels register u_long net; 19931392Skarels 20031392Skarels if (IN_EXPERIMENTAL(i)) 20131392Skarels return (0); 20231392Skarels if (IN_CLASSA(i)) { 20331392Skarels net = i & IN_CLASSA_NET; 20431392Skarels if (net == 0 || net == IN_LOOPBACKNET) 20531392Skarels return (0); 20631392Skarels } 20731392Skarels return (1); 20831392Skarels } 20931392Skarels 21024805Skarels int in_interfaces; /* number of external internet interfaces */ 21124805Skarels extern struct ifnet loif; 21224805Skarels 21318377Skarels /* 21418377Skarels * Generic internet control operations (ioctl's). 21518377Skarels * Ifp is 0 if not an interface-specific ioctl. 21618377Skarels */ 21724805Skarels /* ARGSUSED */ 21818377Skarels in_control(so, cmd, data, ifp) 21918377Skarels struct socket *so; 22018377Skarels int cmd; 22118377Skarels caddr_t data; 22218377Skarels register struct ifnet *ifp; 22318377Skarels { 22418377Skarels register struct ifreq *ifr = (struct ifreq *)data; 22518377Skarels register struct in_ifaddr *ia = 0; 22637471Ssklower register struct ifaddr *ifa; 22737471Ssklower struct in_ifaddr *oia; 22837471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 22918377Skarels struct mbuf *m; 23037471Ssklower struct sockaddr_in oldaddr; 23137471Ssklower int error, hostIsNew, maskIsNew; 23237471Ssklower u_long i; 23318377Skarels 23418377Skarels /* 23518377Skarels * Find address for this interface, if it exists. 23618377Skarels */ 23718377Skarels if (ifp) 23818377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 23918377Skarels if (ia->ia_ifp == ifp) 24018377Skarels break; 24118377Skarels 24218377Skarels switch (cmd) { 24318377Skarels 24437471Ssklower case SIOCAIFADDR: 24537471Ssklower case SIOCDIFADDR: 24637471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 24737471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 24837471Ssklower if (ia->ia_ifp == ifp && 24937471Ssklower ia->ia_addr.sin_addr.s_addr == 25037471Ssklower ifra->ifra_addr.sin_addr.s_addr) 25137471Ssklower break; 25237471Ssklower } 25337471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 25437471Ssklower return (EADDRNOTAVAIL); 25537471Ssklower /* FALLTHROUGH */ 25618377Skarels case SIOCSIFADDR: 25718377Skarels case SIOCSIFNETMASK: 25826456Skarels case SIOCSIFDSTADDR: 25937548Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 26037548Smckusick return (error); 26118377Skarels 26218377Skarels if (ifp == 0) 26318377Skarels panic("in_control"); 26418377Skarels if (ia == (struct in_ifaddr *)0) { 26518377Skarels m = m_getclr(M_WAIT, MT_IFADDR); 26618377Skarels if (m == (struct mbuf *)NULL) 26718377Skarels return (ENOBUFS); 26818377Skarels if (ia = in_ifaddr) { 26918377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 27018377Skarels ; 27118377Skarels ia->ia_next = mtod(m, struct in_ifaddr *); 27218377Skarels } else 27318377Skarels in_ifaddr = mtod(m, struct in_ifaddr *); 27418377Skarels ia = mtod(m, struct in_ifaddr *); 27518377Skarels if (ifa = ifp->if_addrlist) { 27618377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 27718377Skarels ; 27818377Skarels ifa->ifa_next = (struct ifaddr *) ia; 27918377Skarels } else 28018377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 28137471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 28237471Ssklower ia->ia_ifa.ifa_dstaddr 28337471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 28437471Ssklower ia->ia_ifa.ifa_netmask 28537471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 28637471Ssklower ia->ia_sockmask.sin_len = 8; 28737471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 28837471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 28937471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 29037471Ssklower } 29118377Skarels ia->ia_ifp = ifp; 29224805Skarels if (ifp != &loif) 29324805Skarels in_interfaces++; 29417271Skarels } 29518377Skarels break; 29626317Skarels 29726317Skarels case SIOCSIFBRDADDR: 29837548Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 29937548Smckusick return (error); 30026317Skarels /* FALLTHROUGH */ 30126317Skarels 30239183Ssklower case SIOCGIFADDR: 30339183Ssklower case SIOCGIFNETMASK: 30439183Ssklower case SIOCGIFDSTADDR: 30539183Ssklower case SIOCGIFBRDADDR: 30626317Skarels if (ia == (struct in_ifaddr *)0) 30726317Skarels return (EADDRNOTAVAIL); 30826317Skarels break; 30939183Ssklower 31039183Ssklower default: 31139183Ssklower return (EOPNOTSUPP); 31239183Ssklower break; 31317271Skarels } 31418377Skarels switch (cmd) { 31518377Skarels 31618377Skarels case SIOCGIFADDR: 31737471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 31818377Skarels break; 31918377Skarels 32018377Skarels case SIOCGIFBRDADDR: 32118377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32218377Skarels return (EINVAL); 32337471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32418377Skarels break; 32518377Skarels 32618377Skarels case SIOCGIFDSTADDR: 32718377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 32818377Skarels return (EINVAL); 32937471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33018377Skarels break; 33118377Skarels 33218377Skarels case SIOCGIFNETMASK: 33337471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33418377Skarels break; 33518377Skarels 33618377Skarels case SIOCSIFDSTADDR: 33718377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33818377Skarels return (EINVAL); 33927066Skarels oldaddr = ia->ia_dstaddr; 34037471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 34118377Skarels if (ifp->if_ioctl && 34227066Skarels (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 34327066Skarels ia->ia_dstaddr = oldaddr; 34418377Skarels return (error); 34527066Skarels } 34627066Skarels if (ia->ia_flags & IFA_ROUTE) { 34737471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 34837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 34937471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr; 35037471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35127066Skarels } 35218377Skarels break; 35318377Skarels 35418377Skarels case SIOCSIFBRDADDR: 35518377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 35618377Skarels return (EINVAL); 35737471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 35818377Skarels break; 35918377Skarels 36018377Skarels case SIOCSIFADDR: 36134500Skarels return (in_ifinit(ifp, ia, 36237471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36318377Skarels 36418377Skarels case SIOCSIFNETMASK: 36537471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 36637471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 36718377Skarels break; 36818377Skarels 36937471Ssklower case SIOCAIFADDR: 37044368Skarels maskIsNew = 0; 37144368Skarels hostIsNew = 1; 37244368Skarels error = 0; 37337471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 37437471Ssklower if (ifra->ifra_addr.sin_len == 0) { 37537471Ssklower ifra->ifra_addr = ia->ia_addr; 37637471Ssklower hostIsNew = 0; 37737471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 37837471Ssklower ia->ia_addr.sin_addr.s_addr) 37937471Ssklower hostIsNew = 0; 38037471Ssklower } 38137471Ssklower if (ifra->ifra_mask.sin_len) { 38237471Ssklower in_ifscrub(ifp, ia); 38337471Ssklower ia->ia_sockmask = ifra->ifra_mask; 38437471Ssklower ia->ia_subnetmask = 38544368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 38637471Ssklower maskIsNew = 1; 38737471Ssklower } 38837471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 38937471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 39037471Ssklower in_ifscrub(ifp, ia); 39137471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 39237471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 39337471Ssklower } 39437471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 39544368Skarels (hostIsNew || maskIsNew)) 39637471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 39737471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 39837471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 39937471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 40037471Ssklower return (error); 40137471Ssklower 40237471Ssklower case SIOCDIFADDR: 40337471Ssklower in_ifscrub(ifp, ia); 40437471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 40537471Ssklower ifp->if_addrlist = ifa->ifa_next; 40637471Ssklower else { 40737471Ssklower while (ifa->ifa_next && 40837471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 40937471Ssklower ifa = ifa->ifa_next; 41037471Ssklower if (ifa->ifa_next) 41144368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 41237471Ssklower else 41337471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 41437471Ssklower } 41537471Ssklower oia = ia; 41644368Skarels if (oia == (ia = in_ifaddr)) 41737471Ssklower in_ifaddr = ia->ia_next; 41844368Skarels else { 41944368Skarels while (ia->ia_next && (ia->ia_next != oia)) 42037471Ssklower ia = ia->ia_next; 42137471Ssklower if (ia->ia_next) 42244368Skarels ia->ia_next = oia->ia_next; 42337471Ssklower else 42437471Ssklower printf("Didn't unlink inifadr from list\n"); 42537471Ssklower } 42637471Ssklower (void) m_free(dtom(oia)); 42737471Ssklower break; 42837471Ssklower 42918377Skarels default: 43018377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43118377Skarels return (EOPNOTSUPP); 43218377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43318377Skarels } 43417271Skarels return (0); 43517271Skarels } 43617271Skarels 43717271Skarels /* 43837471Ssklower * Delete any existing route for an interface. 43937471Ssklower */ 44037471Ssklower in_ifscrub(ifp, ia) 44137471Ssklower register struct ifnet *ifp; 44237471Ssklower register struct in_ifaddr *ia; 44337471Ssklower { 44437471Ssklower 44537471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 44637471Ssklower return; 44737471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 44837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 44937471Ssklower else 45037471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45137471Ssklower ia->ia_flags &= ~IFA_ROUTE; 45237471Ssklower } 45337471Ssklower 45437471Ssklower /* 45518377Skarels * Initialize an interface's internet address 45618377Skarels * and routing table entry. 4577159Ssam */ 45837471Ssklower in_ifinit(ifp, ia, sin, scrub) 4597159Ssam register struct ifnet *ifp; 46018377Skarels register struct in_ifaddr *ia; 46118377Skarels struct sockaddr_in *sin; 4627159Ssam { 46318377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 46437471Ssklower struct sockaddr_in oldaddr; 46518377Skarels int s = splimp(), error; 4667159Ssam 46727066Skarels oldaddr = ia->ia_addr; 46837471Ssklower ia->ia_addr = *sin; 46918377Skarels /* 47026317Skarels * Give the interface a chance to initialize 47126317Skarels * if this is its first address, 47226317Skarels * and to validate the address if necessary. 47326317Skarels */ 47426317Skarels if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 47526317Skarels splx(s); 47627066Skarels ia->ia_addr = oldaddr; 47726317Skarels return (error); 47826317Skarels } 47937471Ssklower if (scrub) { 48037471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 48137471Ssklower in_ifscrub(ifp, ia); 48237471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 48318377Skarels } 48418377Skarels if (IN_CLASSA(i)) 48518377Skarels ia->ia_netmask = IN_CLASSA_NET; 48618377Skarels else if (IN_CLASSB(i)) 48718377Skarels ia->ia_netmask = IN_CLASSB_NET; 48818377Skarels else 48918377Skarels ia->ia_netmask = IN_CLASSC_NET; 49018377Skarels ia->ia_net = i & ia->ia_netmask; 49118377Skarels /* 49218377Skarels * The subnet mask includes at least the standard network part, 49318377Skarels * but may already have been set to a larger value. 49418377Skarels */ 49518377Skarels ia->ia_subnetmask |= ia->ia_netmask; 49618377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 49737471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 49839183Ssklower { 49939183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 50039183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 50139183Ssklower while (--cp >= cpbase) 50239183Ssklower if (*cp) { 50339183Ssklower ia->ia_sockmask.sin_len = 50439183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 50539183Ssklower break; 50639183Ssklower } 50739183Ssklower } 50818377Skarels if (ifp->if_flags & IFF_BROADCAST) { 50937471Ssklower ia->ia_broadaddr.sin_addr = 51018377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 51125195Skarels ia->ia_netbroadcast.s_addr = 51225195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 51318377Skarels } 51418377Skarels /* 51518377Skarels * Add route for the network. 51618377Skarels */ 51737471Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 51837471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 51937471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 52037471Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 52137471Ssklower ia->ia_dstaddr.sin_family == AF_INET) 52237471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 52327066Skarels else { 52437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 52527066Skarels } 52618377Skarels ia->ia_flags |= IFA_ROUTE; 52730523Skarels splx(s); 52818642Skarels return (0); 5297159Ssam } 53018377Skarels 53118377Skarels /* 53218377Skarels * Return address info for specified internet network. 53318377Skarels */ 53418377Skarels struct in_ifaddr * 53518377Skarels in_iaonnetof(net) 53618377Skarels u_long net; 53718377Skarels { 53818377Skarels register struct in_ifaddr *ia; 53918377Skarels 54018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 54118377Skarels if (ia->ia_subnet == net) 54218377Skarels return (ia); 54318377Skarels return ((struct in_ifaddr *)0); 54418377Skarels } 54518377Skarels 54618377Skarels /* 54730523Skarels * Return 1 if the address might be a local broadcast address. 54818377Skarels */ 54918377Skarels in_broadcast(in) 55018377Skarels struct in_addr in; 55118377Skarels { 55218377Skarels register struct in_ifaddr *ia; 55330523Skarels u_long t; 55418377Skarels 55518377Skarels /* 55618377Skarels * Look through the list of addresses for a match 55718377Skarels * with a broadcast address. 55818377Skarels */ 55918377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 56030523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 56137471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 56218377Skarels return (1); 56330523Skarels /* 56430523Skarels * Check for old-style (host 0) broadcast. 56530523Skarels */ 56630523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 56730523Skarels return (1); 56830523Skarels } 56930523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 57030523Skarels return (1); 57118377Skarels return (0); 57218377Skarels } 5737159Ssam #endif 574