123175Smckusick /* 2*48464Skarels * Copyright (c) 1982, 1986, 1991 Regents of the University of California. 332787Sbostic * All rights reserved. 423175Smckusick * 544472Sbostic * %sccs.include.redist.c% 632787Sbostic * 7*48464Skarels * @(#)in.c 7.17 (Berkeley) 04/20/91 823175Smckusick */ 97159Ssam 1017058Sbloom #include "param.h" 1118377Skarels #include "ioctl.h" 1217058Sbloom #include "mbuf.h" 1317058Sbloom #include "socket.h" 1417058Sbloom #include "socketvar.h" 1517058Sbloom #include "in_systm.h" 16*48464Skarels #include "net/if.h" 17*48464Skarels #include "net/route.h" 18*48464Skarels #include "net/af.h" 1918377Skarels #include "in.h" 2018377Skarels #include "in_var.h" 217159Ssam 227159Ssam #ifdef INET 237159Ssam /* 2418377Skarels * Formulate an Internet address from network + host. 257159Ssam */ 267159Ssam struct in_addr 2718377Skarels in_makeaddr(net, host) 2818377Skarels u_long net, host; 297159Ssam { 3018377Skarels register struct in_ifaddr *ia; 3118377Skarels register u_long mask; 327159Ssam u_long addr; 337159Ssam 3418377Skarels if (IN_CLASSA(net)) 3518377Skarels mask = IN_CLASSA_HOST; 3618377Skarels else if (IN_CLASSB(net)) 3718377Skarels mask = IN_CLASSB_HOST; 387159Ssam else 3918377Skarels mask = IN_CLASSC_HOST; 4018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 4118377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 4218377Skarels mask = ~ia->ia_subnetmask; 4318377Skarels break; 4418377Skarels } 4518377Skarels addr = htonl(net | (host & mask)); 467159Ssam return (*(struct in_addr *)&addr); 477159Ssam } 487159Ssam 497159Ssam /* 508595Sroot * Return the network number from an internet address. 517159Ssam */ 5224805Skarels u_long 537159Ssam in_netof(in) 547159Ssam struct in_addr in; 557159Ssam { 568937Sroot register u_long i = ntohl(in.s_addr); 5718377Skarels register u_long net; 5818377Skarels register struct in_ifaddr *ia; 597159Ssam 6018377Skarels if (IN_CLASSA(i)) 6118377Skarels net = i & IN_CLASSA_NET; 6218377Skarels else if (IN_CLASSB(i)) 6318377Skarels net = i & IN_CLASSB_NET; 6431392Skarels else if (IN_CLASSC(i)) 6531392Skarels net = i & IN_CLASSC_NET; 6618377Skarels else 6731392Skarels return (0); 6816413Skarels 6916413Skarels /* 7018377Skarels * Check whether network is a subnet; 7116413Skarels * if so, return subnet number. 7216413Skarels */ 7318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 7424805Skarels if (net == ia->ia_net) 7518377Skarels return (i & ia->ia_subnetmask); 7616413Skarels return (net); 777159Ssam } 787159Ssam 797159Ssam /* 8037471Ssklower * Compute and save network mask as sockaddr from an internet address. 8137471Ssklower */ 8237471Ssklower in_sockmaskof(in, sockmask) 8337471Ssklower struct in_addr in; 8437471Ssklower register struct sockaddr_in *sockmask; 8537471Ssklower { 8637471Ssklower register u_long net; 8737471Ssklower register u_long mask; 8837471Ssklower { 8937471Ssklower register u_long i = ntohl(in.s_addr); 9037471Ssklower 9137471Ssklower if (i == 0) 9237471Ssklower net = 0, mask = 0; 9337471Ssklower else if (IN_CLASSA(i)) 9437471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 9537471Ssklower else if (IN_CLASSB(i)) 9637471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 9737471Ssklower else if (IN_CLASSC(i)) 9837471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 9937471Ssklower else 10037471Ssklower net = i, mask = -1; 10137471Ssklower } 10237471Ssklower { 10337471Ssklower register struct in_ifaddr *ia; 10437471Ssklower /* 10537471Ssklower * Check whether network is a subnet; 10637471Ssklower * if so, return subnet number. 10737471Ssklower */ 10837471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 10937471Ssklower if (net == ia->ia_net) 11037471Ssklower mask = ia->ia_subnetmask; 11137471Ssklower } 11237471Ssklower { 11337471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 11439183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 11537471Ssklower 11637471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 11737471Ssklower sockmask->sin_len = 0; 11837471Ssklower while (--cp >= cpbase) 11937471Ssklower if (*cp) { 12037471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 12137471Ssklower break; 12237471Ssklower } 12337471Ssklower } 12437471Ssklower } 12537471Ssklower 12637471Ssklower /* 1278595Sroot * Return the host portion of an internet address. 1287159Ssam */ 12926381Skarels u_long 1307159Ssam in_lnaof(in) 1317159Ssam struct in_addr in; 1327159Ssam { 1338937Sroot register u_long i = ntohl(in.s_addr); 13418377Skarels register u_long net, host; 13518377Skarels register struct in_ifaddr *ia; 1367159Ssam 13716377Skarels if (IN_CLASSA(i)) { 13818377Skarels net = i & IN_CLASSA_NET; 13918377Skarels host = i & IN_CLASSA_HOST; 14016377Skarels } else if (IN_CLASSB(i)) { 14118377Skarels net = i & IN_CLASSB_NET; 14218377Skarels host = i & IN_CLASSB_HOST; 14331392Skarels } else if (IN_CLASSC(i)) { 14418377Skarels net = i & IN_CLASSC_NET; 14518377Skarels host = i & IN_CLASSC_HOST; 14631392Skarels } else 14731392Skarels return (i); 1487159Ssam 14916413Skarels /* 15018377Skarels * Check whether network is a subnet; 15116413Skarels * if so, use the modified interpretation of `host'. 15216413Skarels */ 15318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 15424805Skarels if (net == ia->ia_net) 15518377Skarels return (host &~ ia->ia_subnetmask); 15616413Skarels return (host); 15716377Skarels } 15816377Skarels 15926381Skarels #ifndef SUBNETSARELOCAL 16026381Skarels #define SUBNETSARELOCAL 1 16126381Skarels #endif 16226381Skarels int subnetsarelocal = SUBNETSARELOCAL; 16316377Skarels /* 16418377Skarels * Return 1 if an internet address is for a ``local'' host 16526381Skarels * (one to which we have a connection). If subnetsarelocal 16626381Skarels * is true, this includes other subnets of the local net. 16726381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 16817271Skarels */ 16917271Skarels in_localaddr(in) 17017271Skarels struct in_addr in; 17117271Skarels { 17217271Skarels register u_long i = ntohl(in.s_addr); 17318377Skarels register struct in_ifaddr *ia; 17417271Skarels 17530697Skarels if (subnetsarelocal) { 17630697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 17730697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 17830697Skarels return (1); 17930697Skarels } else { 18030697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18130697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 18230697Skarels return (1); 18330697Skarels } 18418377Skarels return (0); 18518377Skarels } 18618377Skarels 18731392Skarels /* 18831392Skarels * Determine whether an IP address is in a reserved set of addresses 18931392Skarels * that may not be forwarded, or whether datagrams to that destination 19031392Skarels * may be forwarded. 19131392Skarels */ 19231392Skarels in_canforward(in) 19331392Skarels struct in_addr in; 19431392Skarels { 19531392Skarels register u_long i = ntohl(in.s_addr); 19631392Skarels register u_long net; 19731392Skarels 19831392Skarels if (IN_EXPERIMENTAL(i)) 19931392Skarels return (0); 20031392Skarels if (IN_CLASSA(i)) { 20131392Skarels net = i & IN_CLASSA_NET; 20231392Skarels if (net == 0 || net == IN_LOOPBACKNET) 20331392Skarels return (0); 20431392Skarels } 20531392Skarels return (1); 20631392Skarels } 20731392Skarels 20824805Skarels int in_interfaces; /* number of external internet interfaces */ 20924805Skarels extern struct ifnet loif; 21024805Skarels 21118377Skarels /* 21218377Skarels * Generic internet control operations (ioctl's). 21318377Skarels * Ifp is 0 if not an interface-specific ioctl. 21418377Skarels */ 21524805Skarels /* ARGSUSED */ 21618377Skarels in_control(so, cmd, data, ifp) 21718377Skarels struct socket *so; 21818377Skarels int cmd; 21918377Skarels caddr_t data; 22018377Skarels register struct ifnet *ifp; 22118377Skarels { 22218377Skarels register struct ifreq *ifr = (struct ifreq *)data; 22318377Skarels register struct in_ifaddr *ia = 0; 22437471Ssklower register struct ifaddr *ifa; 22537471Ssklower struct in_ifaddr *oia; 22637471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 22718377Skarels struct mbuf *m; 22837471Ssklower struct sockaddr_in oldaddr; 22937471Ssklower int error, hostIsNew, maskIsNew; 23037471Ssklower u_long i; 23118377Skarels 23218377Skarels /* 23318377Skarels * Find address for this interface, if it exists. 23418377Skarels */ 23518377Skarels if (ifp) 23618377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 23718377Skarels if (ia->ia_ifp == ifp) 23818377Skarels break; 23918377Skarels 24018377Skarels switch (cmd) { 24118377Skarels 24237471Ssklower case SIOCAIFADDR: 24337471Ssklower case SIOCDIFADDR: 24437471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 24537471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 24637471Ssklower if (ia->ia_ifp == ifp && 24737471Ssklower ia->ia_addr.sin_addr.s_addr == 24837471Ssklower ifra->ifra_addr.sin_addr.s_addr) 24937471Ssklower break; 25037471Ssklower } 25137471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 25237471Ssklower return (EADDRNOTAVAIL); 25337471Ssklower /* FALLTHROUGH */ 25418377Skarels case SIOCSIFADDR: 25518377Skarels case SIOCSIFNETMASK: 25626456Skarels case SIOCSIFDSTADDR: 257*48464Skarels if ((so->so_state & SS_PRIV) == 0) 258*48464Skarels return (EPERM); 25918377Skarels 26018377Skarels if (ifp == 0) 26118377Skarels panic("in_control"); 26218377Skarels if (ia == (struct in_ifaddr *)0) { 26318377Skarels m = m_getclr(M_WAIT, MT_IFADDR); 26418377Skarels if (m == (struct mbuf *)NULL) 26518377Skarels return (ENOBUFS); 26618377Skarels if (ia = in_ifaddr) { 26718377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 26818377Skarels ; 26918377Skarels ia->ia_next = mtod(m, struct in_ifaddr *); 27018377Skarels } else 27118377Skarels in_ifaddr = mtod(m, struct in_ifaddr *); 27218377Skarels ia = mtod(m, struct in_ifaddr *); 27318377Skarels if (ifa = ifp->if_addrlist) { 27418377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 27518377Skarels ; 27618377Skarels ifa->ifa_next = (struct ifaddr *) ia; 27718377Skarels } else 27818377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 27937471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 28037471Ssklower ia->ia_ifa.ifa_dstaddr 28137471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 28237471Ssklower ia->ia_ifa.ifa_netmask 28337471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 28437471Ssklower ia->ia_sockmask.sin_len = 8; 28537471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 28637471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 28737471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 28837471Ssklower } 28918377Skarels ia->ia_ifp = ifp; 29024805Skarels if (ifp != &loif) 29124805Skarels in_interfaces++; 29217271Skarels } 29318377Skarels break; 29426317Skarels 29526317Skarels case SIOCSIFBRDADDR: 296*48464Skarels if ((so->so_state & SS_PRIV) == 0) 297*48464Skarels return (EPERM); 29826317Skarels /* FALLTHROUGH */ 29926317Skarels 30039183Ssklower case SIOCGIFADDR: 30139183Ssklower case SIOCGIFNETMASK: 30239183Ssklower case SIOCGIFDSTADDR: 30339183Ssklower case SIOCGIFBRDADDR: 30426317Skarels if (ia == (struct in_ifaddr *)0) 30526317Skarels return (EADDRNOTAVAIL); 30626317Skarels break; 30739183Ssklower 30839183Ssklower default: 30939183Ssklower return (EOPNOTSUPP); 31039183Ssklower break; 31117271Skarels } 31218377Skarels switch (cmd) { 31318377Skarels 31418377Skarels case SIOCGIFADDR: 31537471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 31618377Skarels break; 31718377Skarels 31818377Skarels case SIOCGIFBRDADDR: 31918377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32018377Skarels return (EINVAL); 32137471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32218377Skarels break; 32318377Skarels 32418377Skarels case SIOCGIFDSTADDR: 32518377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 32618377Skarels return (EINVAL); 32737471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 32818377Skarels break; 32918377Skarels 33018377Skarels case SIOCGIFNETMASK: 33137471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33218377Skarels break; 33318377Skarels 33418377Skarels case SIOCSIFDSTADDR: 33518377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33618377Skarels return (EINVAL); 33727066Skarels oldaddr = ia->ia_dstaddr; 33837471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 33918377Skarels if (ifp->if_ioctl && 34027066Skarels (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 34127066Skarels ia->ia_dstaddr = oldaddr; 34218377Skarels return (error); 34327066Skarels } 34427066Skarels if (ia->ia_flags & IFA_ROUTE) { 34537471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 34637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 34745454Ssklower ia->ia_ifa.ifa_dstaddr = 34845454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 34937471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35027066Skarels } 35118377Skarels break; 35218377Skarels 35318377Skarels case SIOCSIFBRDADDR: 35418377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 35518377Skarels return (EINVAL); 35637471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 35718377Skarels break; 35818377Skarels 35918377Skarels case SIOCSIFADDR: 36034500Skarels return (in_ifinit(ifp, ia, 36137471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36218377Skarels 36318377Skarels case SIOCSIFNETMASK: 36437471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 36537471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 36618377Skarels break; 36718377Skarels 36837471Ssklower case SIOCAIFADDR: 36944368Skarels maskIsNew = 0; 37044368Skarels hostIsNew = 1; 37144368Skarels error = 0; 37237471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 37337471Ssklower if (ifra->ifra_addr.sin_len == 0) { 37437471Ssklower ifra->ifra_addr = ia->ia_addr; 37537471Ssklower hostIsNew = 0; 37637471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 37737471Ssklower ia->ia_addr.sin_addr.s_addr) 37837471Ssklower hostIsNew = 0; 37937471Ssklower } 38037471Ssklower if (ifra->ifra_mask.sin_len) { 38137471Ssklower in_ifscrub(ifp, ia); 38237471Ssklower ia->ia_sockmask = ifra->ifra_mask; 38337471Ssklower ia->ia_subnetmask = 38444368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 38537471Ssklower maskIsNew = 1; 38637471Ssklower } 38737471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 38837471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 38937471Ssklower in_ifscrub(ifp, ia); 39037471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 39137471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 39237471Ssklower } 39337471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 39444368Skarels (hostIsNew || maskIsNew)) 39537471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 39637471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 39737471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 39837471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 39937471Ssklower return (error); 40037471Ssklower 40137471Ssklower case SIOCDIFADDR: 40237471Ssklower in_ifscrub(ifp, ia); 40337471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 40437471Ssklower ifp->if_addrlist = ifa->ifa_next; 40537471Ssklower else { 40637471Ssklower while (ifa->ifa_next && 40737471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 40837471Ssklower ifa = ifa->ifa_next; 40937471Ssklower if (ifa->ifa_next) 41044368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 41137471Ssklower else 41237471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 41337471Ssklower } 41437471Ssklower oia = ia; 41544368Skarels if (oia == (ia = in_ifaddr)) 41637471Ssklower in_ifaddr = ia->ia_next; 41744368Skarels else { 41844368Skarels while (ia->ia_next && (ia->ia_next != oia)) 41937471Ssklower ia = ia->ia_next; 42037471Ssklower if (ia->ia_next) 42144368Skarels ia->ia_next = oia->ia_next; 42237471Ssklower else 42337471Ssklower printf("Didn't unlink inifadr from list\n"); 42437471Ssklower } 42537471Ssklower (void) m_free(dtom(oia)); 42637471Ssklower break; 42737471Ssklower 42818377Skarels default: 42918377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43018377Skarels return (EOPNOTSUPP); 43118377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43218377Skarels } 43317271Skarels return (0); 43417271Skarels } 43517271Skarels 43617271Skarels /* 43737471Ssklower * Delete any existing route for an interface. 43837471Ssklower */ 43937471Ssklower in_ifscrub(ifp, ia) 44037471Ssklower register struct ifnet *ifp; 44137471Ssklower register struct in_ifaddr *ia; 44237471Ssklower { 44337471Ssklower 44437471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 44537471Ssklower return; 44637471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 44737471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 44837471Ssklower else 44937471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45037471Ssklower ia->ia_flags &= ~IFA_ROUTE; 45137471Ssklower } 45237471Ssklower 45337471Ssklower /* 45418377Skarels * Initialize an interface's internet address 45518377Skarels * and routing table entry. 4567159Ssam */ 45737471Ssklower in_ifinit(ifp, ia, sin, scrub) 4587159Ssam register struct ifnet *ifp; 45918377Skarels register struct in_ifaddr *ia; 46018377Skarels struct sockaddr_in *sin; 4617159Ssam { 46218377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 46337471Ssklower struct sockaddr_in oldaddr; 46445454Ssklower int s = splimp(), error, flags = RTF_UP; 4657159Ssam 46627066Skarels oldaddr = ia->ia_addr; 46737471Ssklower ia->ia_addr = *sin; 46818377Skarels /* 46926317Skarels * Give the interface a chance to initialize 47026317Skarels * if this is its first address, 47126317Skarels * and to validate the address if necessary. 47226317Skarels */ 47326317Skarels if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 47426317Skarels splx(s); 47527066Skarels ia->ia_addr = oldaddr; 47626317Skarels return (error); 47726317Skarels } 47845454Ssklower splx(s); 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 } 50845454Ssklower /* 50945454Ssklower * Add route for the network. 51045454Ssklower */ 51118377Skarels if (ifp->if_flags & IFF_BROADCAST) { 51237471Ssklower ia->ia_broadaddr.sin_addr = 51318377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 51425195Skarels ia->ia_netbroadcast.s_addr = 51525195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 51645454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 51737471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 51845454Ssklower flags |= RTF_HOST; 51945454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 52045454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 52145454Ssklower return (0); 52245454Ssklower flags |= RTF_HOST; 52327066Skarels } 52445454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 52545454Ssklower ia->ia_flags |= IFA_ROUTE; 52645454Ssklower return (error); 5277159Ssam } 52818377Skarels 52918377Skarels /* 53018377Skarels * Return address info for specified internet network. 53118377Skarels */ 53218377Skarels struct in_ifaddr * 53318377Skarels in_iaonnetof(net) 53418377Skarels u_long net; 53518377Skarels { 53618377Skarels register struct in_ifaddr *ia; 53718377Skarels 53818377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 53918377Skarels if (ia->ia_subnet == net) 54018377Skarels return (ia); 54118377Skarels return ((struct in_ifaddr *)0); 54218377Skarels } 54318377Skarels 54418377Skarels /* 54530523Skarels * Return 1 if the address might be a local broadcast address. 54618377Skarels */ 54718377Skarels in_broadcast(in) 54818377Skarels struct in_addr in; 54918377Skarels { 55018377Skarels register struct in_ifaddr *ia; 55130523Skarels u_long t; 55218377Skarels 55318377Skarels /* 55418377Skarels * Look through the list of addresses for a match 55518377Skarels * with a broadcast address. 55618377Skarels */ 55718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 55830523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 55937471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 56018377Skarels return (1); 56130523Skarels /* 56230523Skarels * Check for old-style (host 0) broadcast. 56330523Skarels */ 56430523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 56530523Skarels return (1); 56630523Skarels } 56730523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 56830523Skarels return (1); 56918377Skarels return (0); 57018377Skarels } 5717159Ssam #endif 572