123175Smckusick /* 248464Skarels * Copyright (c) 1982, 1986, 1991 Regents of the University of California. 332787Sbostic * All rights reserved. 423175Smckusick * 544472Sbostic * %sccs.include.redist.c% 632787Sbostic * 7*52274Storek * @(#)in.c 7.20 (Berkeley) 01/30/92 823175Smckusick */ 97159Ssam 1017058Sbloom #include "param.h" 1118377Skarels #include "ioctl.h" 1250134Ssklower #include "errno.h" 1317058Sbloom #include "mbuf.h" 1417058Sbloom #include "socket.h" 1517058Sbloom #include "socketvar.h" 1617058Sbloom #include "in_systm.h" 1748464Skarels #include "net/if.h" 1848464Skarels #include "net/route.h" 1948464Skarels #include "net/af.h" 2018377Skarels #include "in.h" 2118377Skarels #include "in_var.h" 227159Ssam 237159Ssam #ifdef INET 247159Ssam /* 2518377Skarels * Formulate an Internet address from network + host. 267159Ssam */ 277159Ssam struct in_addr 2818377Skarels in_makeaddr(net, host) 2918377Skarels u_long net, host; 307159Ssam { 3118377Skarels register struct in_ifaddr *ia; 3218377Skarels register u_long mask; 337159Ssam u_long addr; 347159Ssam 3518377Skarels if (IN_CLASSA(net)) 3618377Skarels mask = IN_CLASSA_HOST; 3718377Skarels else if (IN_CLASSB(net)) 3818377Skarels mask = IN_CLASSB_HOST; 397159Ssam else 4018377Skarels mask = IN_CLASSC_HOST; 4118377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 4218377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 4318377Skarels mask = ~ia->ia_subnetmask; 4418377Skarels break; 4518377Skarels } 4618377Skarels addr = htonl(net | (host & mask)); 477159Ssam return (*(struct in_addr *)&addr); 487159Ssam } 497159Ssam 507159Ssam /* 518595Sroot * Return the network number from an internet address. 527159Ssam */ 5324805Skarels u_long 547159Ssam in_netof(in) 557159Ssam struct in_addr in; 567159Ssam { 578937Sroot register u_long i = ntohl(in.s_addr); 5818377Skarels register u_long net; 5918377Skarels register struct in_ifaddr *ia; 607159Ssam 6118377Skarels if (IN_CLASSA(i)) 6218377Skarels net = i & IN_CLASSA_NET; 6318377Skarels else if (IN_CLASSB(i)) 6418377Skarels net = i & IN_CLASSB_NET; 6531392Skarels else if (IN_CLASSC(i)) 6631392Skarels net = i & IN_CLASSC_NET; 6718377Skarels else 6831392Skarels return (0); 6916413Skarels 7016413Skarels /* 7118377Skarels * Check whether network is a subnet; 7216413Skarels * if so, return subnet number. 7316413Skarels */ 7418377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 7524805Skarels if (net == ia->ia_net) 7618377Skarels return (i & ia->ia_subnetmask); 7716413Skarels return (net); 787159Ssam } 797159Ssam 807159Ssam /* 8137471Ssklower * Compute and save network mask as sockaddr from an internet address. 8237471Ssklower */ 8337471Ssklower in_sockmaskof(in, sockmask) 8437471Ssklower struct in_addr in; 8537471Ssklower register struct sockaddr_in *sockmask; 8637471Ssklower { 8737471Ssklower register u_long net; 8837471Ssklower register u_long mask; 8937471Ssklower { 9037471Ssklower register u_long i = ntohl(in.s_addr); 9137471Ssklower 9237471Ssklower if (i == 0) 9337471Ssklower net = 0, mask = 0; 9437471Ssklower else if (IN_CLASSA(i)) 9537471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 9637471Ssklower else if (IN_CLASSB(i)) 9737471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 9837471Ssklower else if (IN_CLASSC(i)) 9937471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 10037471Ssklower else 10137471Ssklower net = i, mask = -1; 10237471Ssklower } 10337471Ssklower { 10437471Ssklower register struct in_ifaddr *ia; 10537471Ssklower /* 10637471Ssklower * Check whether network is a subnet; 10737471Ssklower * if so, return subnet number. 10837471Ssklower */ 10937471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 11037471Ssklower if (net == ia->ia_net) 11137471Ssklower mask = ia->ia_subnetmask; 11237471Ssklower } 11337471Ssklower { 11437471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 11539183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 11637471Ssklower 11737471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 11837471Ssklower sockmask->sin_len = 0; 11937471Ssklower while (--cp >= cpbase) 12037471Ssklower if (*cp) { 12137471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 12237471Ssklower break; 12337471Ssklower } 12437471Ssklower } 12537471Ssklower } 12637471Ssklower 12737471Ssklower /* 1288595Sroot * Return the host portion of an internet address. 1297159Ssam */ 13026381Skarels u_long 1317159Ssam in_lnaof(in) 1327159Ssam struct in_addr in; 1337159Ssam { 1348937Sroot register u_long i = ntohl(in.s_addr); 13518377Skarels register u_long net, host; 13618377Skarels register struct in_ifaddr *ia; 1377159Ssam 13816377Skarels if (IN_CLASSA(i)) { 13918377Skarels net = i & IN_CLASSA_NET; 14018377Skarels host = i & IN_CLASSA_HOST; 14116377Skarels } else if (IN_CLASSB(i)) { 14218377Skarels net = i & IN_CLASSB_NET; 14318377Skarels host = i & IN_CLASSB_HOST; 14431392Skarels } else if (IN_CLASSC(i)) { 14518377Skarels net = i & IN_CLASSC_NET; 14618377Skarels host = i & IN_CLASSC_HOST; 14731392Skarels } else 14831392Skarels return (i); 1497159Ssam 15016413Skarels /* 15118377Skarels * Check whether network is a subnet; 15216413Skarels * if so, use the modified interpretation of `host'. 15316413Skarels */ 15418377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 15524805Skarels if (net == ia->ia_net) 15618377Skarels return (host &~ ia->ia_subnetmask); 15716413Skarels return (host); 15816377Skarels } 15916377Skarels 16026381Skarels #ifndef SUBNETSARELOCAL 16126381Skarels #define SUBNETSARELOCAL 1 16226381Skarels #endif 16326381Skarels int subnetsarelocal = SUBNETSARELOCAL; 16416377Skarels /* 16518377Skarels * Return 1 if an internet address is for a ``local'' host 16626381Skarels * (one to which we have a connection). If subnetsarelocal 16726381Skarels * is true, this includes other subnets of the local net. 16826381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 16917271Skarels */ 17017271Skarels in_localaddr(in) 17117271Skarels struct in_addr in; 17217271Skarels { 17317271Skarels register u_long i = ntohl(in.s_addr); 17418377Skarels register struct in_ifaddr *ia; 17517271Skarels 17630697Skarels if (subnetsarelocal) { 17730697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 17830697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 17930697Skarels return (1); 18030697Skarels } else { 18130697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18230697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 18330697Skarels return (1); 18430697Skarels } 18518377Skarels return (0); 18618377Skarels } 18718377Skarels 18831392Skarels /* 18931392Skarels * Determine whether an IP address is in a reserved set of addresses 19031392Skarels * that may not be forwarded, or whether datagrams to that destination 19131392Skarels * may be forwarded. 19231392Skarels */ 19331392Skarels in_canforward(in) 19431392Skarels struct in_addr in; 19531392Skarels { 19631392Skarels register u_long i = ntohl(in.s_addr); 19731392Skarels register u_long net; 19831392Skarels 19931392Skarels if (IN_EXPERIMENTAL(i)) 20031392Skarels return (0); 20131392Skarels if (IN_CLASSA(i)) { 20231392Skarels net = i & IN_CLASSA_NET; 20331392Skarels if (net == 0 || net == IN_LOOPBACKNET) 20431392Skarels return (0); 20531392Skarels } 20631392Skarels return (1); 20731392Skarels } 20831392Skarels 20924805Skarels int in_interfaces; /* number of external internet interfaces */ 21024805Skarels extern struct ifnet loif; 21124805Skarels 21218377Skarels /* 21318377Skarels * Generic internet control operations (ioctl's). 21418377Skarels * Ifp is 0 if not an interface-specific ioctl. 21518377Skarels */ 21624805Skarels /* ARGSUSED */ 21718377Skarels in_control(so, cmd, data, ifp) 21818377Skarels struct socket *so; 21918377Skarels int cmd; 22018377Skarels caddr_t data; 22118377Skarels register struct ifnet *ifp; 22218377Skarels { 22318377Skarels register struct ifreq *ifr = (struct ifreq *)data; 22418377Skarels register struct in_ifaddr *ia = 0; 22537471Ssklower register struct ifaddr *ifa; 22637471Ssklower struct in_ifaddr *oia; 22737471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 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: 25748464Skarels if ((so->so_state & SS_PRIV) == 0) 25848464Skarels return (EPERM); 25918377Skarels 26018377Skarels if (ifp == 0) 26118377Skarels panic("in_control"); 26218377Skarels if (ia == (struct in_ifaddr *)0) { 26352028Ssklower oia = (struct in_ifaddr *) 26452028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK); 26552028Ssklower if (oia == (struct in_ifaddr *)NULL) 26618377Skarels return (ENOBUFS); 26752028Ssklower bzero((caddr_t)oia, sizeof *oia); 26818377Skarels if (ia = in_ifaddr) { 26918377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 27018377Skarels ; 27152028Ssklower ia->ia_next = oia; 27218377Skarels } else 27352028Ssklower in_ifaddr = oia; 27452028Ssklower ia = oia; 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: 29848464Skarels if ((so->so_state & SS_PRIV) == 0) 29948464Skarels return (EPERM); 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); 34945454Ssklower ia->ia_ifa.ifa_dstaddr = 35045454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 35137471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35227066Skarels } 35318377Skarels break; 35418377Skarels 35518377Skarels case SIOCSIFBRDADDR: 35618377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 35718377Skarels return (EINVAL); 35837471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 35918377Skarels break; 36018377Skarels 36118377Skarels case SIOCSIFADDR: 36234500Skarels return (in_ifinit(ifp, ia, 36337471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36418377Skarels 36518377Skarels case SIOCSIFNETMASK: 36637471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 36737471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 36818377Skarels break; 36918377Skarels 37037471Ssklower case SIOCAIFADDR: 37144368Skarels maskIsNew = 0; 37244368Skarels hostIsNew = 1; 37344368Skarels error = 0; 37437471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 37537471Ssklower if (ifra->ifra_addr.sin_len == 0) { 37637471Ssklower ifra->ifra_addr = ia->ia_addr; 37737471Ssklower hostIsNew = 0; 37837471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 37937471Ssklower ia->ia_addr.sin_addr.s_addr) 38037471Ssklower hostIsNew = 0; 38137471Ssklower } 38237471Ssklower if (ifra->ifra_mask.sin_len) { 38337471Ssklower in_ifscrub(ifp, ia); 38437471Ssklower ia->ia_sockmask = ifra->ifra_mask; 38537471Ssklower ia->ia_subnetmask = 38644368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 38737471Ssklower maskIsNew = 1; 38837471Ssklower } 38937471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 39037471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 39137471Ssklower in_ifscrub(ifp, ia); 39237471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 39337471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 39437471Ssklower } 39537471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 39644368Skarels (hostIsNew || maskIsNew)) 39737471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 39837471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 39937471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 40037471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 40137471Ssklower return (error); 40237471Ssklower 40337471Ssklower case SIOCDIFADDR: 40437471Ssklower in_ifscrub(ifp, ia); 40537471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 40637471Ssklower ifp->if_addrlist = ifa->ifa_next; 40737471Ssklower else { 40837471Ssklower while (ifa->ifa_next && 40937471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 41037471Ssklower ifa = ifa->ifa_next; 41137471Ssklower if (ifa->ifa_next) 41244368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 41337471Ssklower else 41437471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 41537471Ssklower } 41637471Ssklower oia = ia; 41744368Skarels if (oia == (ia = in_ifaddr)) 41837471Ssklower in_ifaddr = ia->ia_next; 41944368Skarels else { 42044368Skarels while (ia->ia_next && (ia->ia_next != oia)) 42137471Ssklower ia = ia->ia_next; 42237471Ssklower if (ia->ia_next) 42344368Skarels ia->ia_next = oia->ia_next; 42437471Ssklower else 42537471Ssklower printf("Didn't unlink inifadr from list\n"); 42637471Ssklower } 42752028Ssklower IFAFREE((&oia->ia_ifa)); 42837471Ssklower break; 42937471Ssklower 43018377Skarels default: 43118377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43218377Skarels return (EOPNOTSUPP); 43318377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43418377Skarels } 43517271Skarels return (0); 43617271Skarels } 43717271Skarels 43817271Skarels /* 43937471Ssklower * Delete any existing route for an interface. 44037471Ssklower */ 44137471Ssklower in_ifscrub(ifp, ia) 44237471Ssklower register struct ifnet *ifp; 44337471Ssklower register struct in_ifaddr *ia; 44437471Ssklower { 44537471Ssklower 44637471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 44737471Ssklower return; 44837471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 44937471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 45037471Ssklower else 45137471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45237471Ssklower ia->ia_flags &= ~IFA_ROUTE; 45337471Ssklower } 45437471Ssklower 45537471Ssklower /* 45618377Skarels * Initialize an interface's internet address 45718377Skarels * and routing table entry. 4587159Ssam */ 45937471Ssklower in_ifinit(ifp, ia, sin, scrub) 4607159Ssam register struct ifnet *ifp; 46118377Skarels register struct in_ifaddr *ia; 46218377Skarels struct sockaddr_in *sin; 463*52274Storek int scrub; 4647159Ssam { 46518377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 46637471Ssklower struct sockaddr_in oldaddr; 46745454Ssklower int s = splimp(), error, flags = RTF_UP; 46850134Ssklower int ether_output(), arp_rtrequest(); 4697159Ssam 47027066Skarels oldaddr = ia->ia_addr; 47137471Ssklower ia->ia_addr = *sin; 47218377Skarels /* 47326317Skarels * Give the interface a chance to initialize 47426317Skarels * if this is its first address, 47526317Skarels * and to validate the address if necessary. 47626317Skarels */ 477*52274Storek if (ifp->if_ioctl && 478*52274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 47926317Skarels splx(s); 48027066Skarels ia->ia_addr = oldaddr; 48126317Skarels return (error); 48226317Skarels } 48350134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 48450134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 48550134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 48650134Ssklower } 48745454Ssklower splx(s); 48837471Ssklower if (scrub) { 48937471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 49037471Ssklower in_ifscrub(ifp, ia); 49137471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 49218377Skarels } 49318377Skarels if (IN_CLASSA(i)) 49418377Skarels ia->ia_netmask = IN_CLASSA_NET; 49518377Skarels else if (IN_CLASSB(i)) 49618377Skarels ia->ia_netmask = IN_CLASSB_NET; 49718377Skarels else 49818377Skarels ia->ia_netmask = IN_CLASSC_NET; 49918377Skarels ia->ia_net = i & ia->ia_netmask; 50018377Skarels /* 50118377Skarels * The subnet mask includes at least the standard network part, 50218377Skarels * but may already have been set to a larger value. 50318377Skarels */ 50418377Skarels ia->ia_subnetmask |= ia->ia_netmask; 50518377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 50637471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 50739183Ssklower { 50839183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 50939183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 51039183Ssklower while (--cp >= cpbase) 51139183Ssklower if (*cp) { 51239183Ssklower ia->ia_sockmask.sin_len = 51339183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 51439183Ssklower break; 51539183Ssklower } 51639183Ssklower } 51745454Ssklower /* 51845454Ssklower * Add route for the network. 51945454Ssklower */ 52018377Skarels if (ifp->if_flags & IFF_BROADCAST) { 52137471Ssklower ia->ia_broadaddr.sin_addr = 52218377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 52325195Skarels ia->ia_netbroadcast.s_addr = 52425195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 52545454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 52637471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 52745454Ssklower flags |= RTF_HOST; 52845454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 52945454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 53045454Ssklower return (0); 53145454Ssklower flags |= RTF_HOST; 53227066Skarels } 53345454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 53445454Ssklower ia->ia_flags |= IFA_ROUTE; 53545454Ssklower return (error); 5367159Ssam } 53718377Skarels 53818377Skarels /* 53918377Skarels * Return address info for specified internet network. 54018377Skarels */ 54118377Skarels struct in_ifaddr * 54218377Skarels in_iaonnetof(net) 54318377Skarels u_long net; 54418377Skarels { 54518377Skarels register struct in_ifaddr *ia; 54618377Skarels 54718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 54818377Skarels if (ia->ia_subnet == net) 54918377Skarels return (ia); 55018377Skarels return ((struct in_ifaddr *)0); 55118377Skarels } 55218377Skarels 55318377Skarels /* 55430523Skarels * Return 1 if the address might be a local broadcast address. 55518377Skarels */ 55618377Skarels in_broadcast(in) 55718377Skarels struct in_addr in; 55818377Skarels { 55918377Skarels register struct in_ifaddr *ia; 56030523Skarels u_long t; 56118377Skarels 56218377Skarels /* 56318377Skarels * Look through the list of addresses for a match 56418377Skarels * with a broadcast address. 56518377Skarels */ 56618377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 56730523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 56837471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 56918377Skarels return (1); 57030523Skarels /* 57130523Skarels * Check for old-style (host 0) broadcast. 57230523Skarels */ 57330523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 57430523Skarels return (1); 57530523Skarels } 57630523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 57730523Skarels return (1); 57818377Skarels return (0); 57918377Skarels } 5807159Ssam #endif 581