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*44368Skarels * @(#)in.c 7.14 (Berkeley) 06/28/90 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 "user.h" 2717058Sbloom #include "in_systm.h" 287166Ssam #include "../net/if.h" 297166Ssam #include "../net/route.h" 307159Ssam #include "../net/af.h" 3118377Skarels #include "in.h" 3218377Skarels #include "in_var.h" 337159Ssam 347159Ssam #ifdef INET 357159Ssam /* 3618377Skarels * Formulate an Internet address from network + host. 377159Ssam */ 387159Ssam struct in_addr 3918377Skarels in_makeaddr(net, host) 4018377Skarels u_long net, host; 417159Ssam { 4218377Skarels register struct in_ifaddr *ia; 4318377Skarels register u_long mask; 447159Ssam u_long addr; 457159Ssam 4618377Skarels if (IN_CLASSA(net)) 4718377Skarels mask = IN_CLASSA_HOST; 4818377Skarels else if (IN_CLASSB(net)) 4918377Skarels mask = IN_CLASSB_HOST; 507159Ssam else 5118377Skarels mask = IN_CLASSC_HOST; 5218377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 5318377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 5418377Skarels mask = ~ia->ia_subnetmask; 5518377Skarels break; 5618377Skarels } 5718377Skarels addr = htonl(net | (host & mask)); 587159Ssam return (*(struct in_addr *)&addr); 597159Ssam } 607159Ssam 617159Ssam /* 628595Sroot * Return the network number from an internet address. 637159Ssam */ 6424805Skarels u_long 657159Ssam in_netof(in) 667159Ssam struct in_addr in; 677159Ssam { 688937Sroot register u_long i = ntohl(in.s_addr); 6918377Skarels register u_long net; 7018377Skarels register struct in_ifaddr *ia; 717159Ssam 7218377Skarels if (IN_CLASSA(i)) 7318377Skarels net = i & IN_CLASSA_NET; 7418377Skarels else if (IN_CLASSB(i)) 7518377Skarels net = i & IN_CLASSB_NET; 7631392Skarels else if (IN_CLASSC(i)) 7731392Skarels net = i & IN_CLASSC_NET; 7818377Skarels else 7931392Skarels return (0); 8016413Skarels 8116413Skarels /* 8218377Skarels * Check whether network is a subnet; 8316413Skarels * if so, return subnet number. 8416413Skarels */ 8518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 8624805Skarels if (net == ia->ia_net) 8718377Skarels return (i & ia->ia_subnetmask); 8816413Skarels return (net); 897159Ssam } 907159Ssam 917159Ssam /* 9237471Ssklower * Compute and save network mask as sockaddr from an internet address. 9337471Ssklower */ 9437471Ssklower in_sockmaskof(in, sockmask) 9537471Ssklower struct in_addr in; 9637471Ssklower register struct sockaddr_in *sockmask; 9737471Ssklower { 9837471Ssklower register u_long net; 9937471Ssklower register u_long mask; 10037471Ssklower { 10137471Ssklower register u_long i = ntohl(in.s_addr); 10237471Ssklower 10337471Ssklower if (i == 0) 10437471Ssklower net = 0, mask = 0; 10537471Ssklower else if (IN_CLASSA(i)) 10637471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 10737471Ssklower else if (IN_CLASSB(i)) 10837471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 10937471Ssklower else if (IN_CLASSC(i)) 11037471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 11137471Ssklower else 11237471Ssklower net = i, mask = -1; 11337471Ssklower } 11437471Ssklower { 11537471Ssklower register struct in_ifaddr *ia; 11637471Ssklower /* 11737471Ssklower * Check whether network is a subnet; 11837471Ssklower * if so, return subnet number. 11937471Ssklower */ 12037471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 12137471Ssklower if (net == ia->ia_net) 12237471Ssklower mask = ia->ia_subnetmask; 12337471Ssklower } 12437471Ssklower { 12537471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 12639183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 12737471Ssklower 12837471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 12937471Ssklower sockmask->sin_len = 0; 13037471Ssklower while (--cp >= cpbase) 13137471Ssklower if (*cp) { 13237471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 13337471Ssklower break; 13437471Ssklower } 13537471Ssklower } 13637471Ssklower } 13737471Ssklower 13837471Ssklower /* 1398595Sroot * Return the host portion of an internet address. 1407159Ssam */ 14126381Skarels u_long 1427159Ssam in_lnaof(in) 1437159Ssam struct in_addr in; 1447159Ssam { 1458937Sroot register u_long i = ntohl(in.s_addr); 14618377Skarels register u_long net, host; 14718377Skarels register struct in_ifaddr *ia; 1487159Ssam 14916377Skarels if (IN_CLASSA(i)) { 15018377Skarels net = i & IN_CLASSA_NET; 15118377Skarels host = i & IN_CLASSA_HOST; 15216377Skarels } else if (IN_CLASSB(i)) { 15318377Skarels net = i & IN_CLASSB_NET; 15418377Skarels host = i & IN_CLASSB_HOST; 15531392Skarels } else if (IN_CLASSC(i)) { 15618377Skarels net = i & IN_CLASSC_NET; 15718377Skarels host = i & IN_CLASSC_HOST; 15831392Skarels } else 15931392Skarels return (i); 1607159Ssam 16116413Skarels /* 16218377Skarels * Check whether network is a subnet; 16316413Skarels * if so, use the modified interpretation of `host'. 16416413Skarels */ 16518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 16624805Skarels if (net == ia->ia_net) 16718377Skarels return (host &~ ia->ia_subnetmask); 16816413Skarels return (host); 16916377Skarels } 17016377Skarels 17126381Skarels #ifndef SUBNETSARELOCAL 17226381Skarels #define SUBNETSARELOCAL 1 17326381Skarels #endif 17426381Skarels int subnetsarelocal = SUBNETSARELOCAL; 17516377Skarels /* 17618377Skarels * Return 1 if an internet address is for a ``local'' host 17726381Skarels * (one to which we have a connection). If subnetsarelocal 17826381Skarels * is true, this includes other subnets of the local net. 17926381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 18017271Skarels */ 18117271Skarels in_localaddr(in) 18217271Skarels struct in_addr in; 18317271Skarels { 18417271Skarels register u_long i = ntohl(in.s_addr); 18518377Skarels register struct in_ifaddr *ia; 18617271Skarels 18730697Skarels if (subnetsarelocal) { 18830697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18930697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 19030697Skarels return (1); 19130697Skarels } else { 19230697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 19330697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 19430697Skarels return (1); 19530697Skarels } 19618377Skarels return (0); 19718377Skarels } 19818377Skarels 19931392Skarels /* 20031392Skarels * Determine whether an IP address is in a reserved set of addresses 20131392Skarels * that may not be forwarded, or whether datagrams to that destination 20231392Skarels * may be forwarded. 20331392Skarels */ 20431392Skarels in_canforward(in) 20531392Skarels struct in_addr in; 20631392Skarels { 20731392Skarels register u_long i = ntohl(in.s_addr); 20831392Skarels register u_long net; 20931392Skarels 21031392Skarels if (IN_EXPERIMENTAL(i)) 21131392Skarels return (0); 21231392Skarels if (IN_CLASSA(i)) { 21331392Skarels net = i & IN_CLASSA_NET; 21431392Skarels if (net == 0 || net == IN_LOOPBACKNET) 21531392Skarels return (0); 21631392Skarels } 21731392Skarels return (1); 21831392Skarels } 21931392Skarels 22024805Skarels int in_interfaces; /* number of external internet interfaces */ 22124805Skarels extern struct ifnet loif; 22224805Skarels 22318377Skarels /* 22418377Skarels * Generic internet control operations (ioctl's). 22518377Skarels * Ifp is 0 if not an interface-specific ioctl. 22618377Skarels */ 22724805Skarels /* ARGSUSED */ 22818377Skarels in_control(so, cmd, data, ifp) 22918377Skarels struct socket *so; 23018377Skarels int cmd; 23118377Skarels caddr_t data; 23218377Skarels register struct ifnet *ifp; 23318377Skarels { 23418377Skarels register struct ifreq *ifr = (struct ifreq *)data; 23518377Skarels register struct in_ifaddr *ia = 0; 23637471Ssklower register struct ifaddr *ifa; 23737471Ssklower struct in_ifaddr *oia; 23837471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 23918377Skarels struct mbuf *m; 24037471Ssklower struct sockaddr_in oldaddr; 24137471Ssklower int error, hostIsNew, maskIsNew; 24237471Ssklower u_long i; 24318377Skarels 24418377Skarels /* 24518377Skarels * Find address for this interface, if it exists. 24618377Skarels */ 24718377Skarels if (ifp) 24818377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 24918377Skarels if (ia->ia_ifp == ifp) 25018377Skarels break; 25118377Skarels 25218377Skarels switch (cmd) { 25318377Skarels 25437471Ssklower case SIOCAIFADDR: 25537471Ssklower case SIOCDIFADDR: 25637471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 25737471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 25837471Ssklower if (ia->ia_ifp == ifp && 25937471Ssklower ia->ia_addr.sin_addr.s_addr == 26037471Ssklower ifra->ifra_addr.sin_addr.s_addr) 26137471Ssklower break; 26237471Ssklower } 26337471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 26437471Ssklower return (EADDRNOTAVAIL); 26537471Ssklower /* FALLTHROUGH */ 26618377Skarels case SIOCSIFADDR: 26718377Skarels case SIOCSIFNETMASK: 26826456Skarels case SIOCSIFDSTADDR: 26937548Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 27037548Smckusick return (error); 27118377Skarels 27218377Skarels if (ifp == 0) 27318377Skarels panic("in_control"); 27418377Skarels if (ia == (struct in_ifaddr *)0) { 27518377Skarels m = m_getclr(M_WAIT, MT_IFADDR); 27618377Skarels if (m == (struct mbuf *)NULL) 27718377Skarels return (ENOBUFS); 27818377Skarels if (ia = in_ifaddr) { 27918377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 28018377Skarels ; 28118377Skarels ia->ia_next = mtod(m, struct in_ifaddr *); 28218377Skarels } else 28318377Skarels in_ifaddr = mtod(m, struct in_ifaddr *); 28418377Skarels ia = mtod(m, struct in_ifaddr *); 28518377Skarels if (ifa = ifp->if_addrlist) { 28618377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 28718377Skarels ; 28818377Skarels ifa->ifa_next = (struct ifaddr *) ia; 28918377Skarels } else 29018377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 29137471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 29237471Ssklower ia->ia_ifa.ifa_dstaddr 29337471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 29437471Ssklower ia->ia_ifa.ifa_netmask 29537471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 29637471Ssklower ia->ia_sockmask.sin_len = 8; 29737471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 29837471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 29937471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 30037471Ssklower } 30118377Skarels ia->ia_ifp = ifp; 30224805Skarels if (ifp != &loif) 30324805Skarels in_interfaces++; 30417271Skarels } 30518377Skarels break; 30626317Skarels 30726317Skarels case SIOCSIFBRDADDR: 30837548Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 30937548Smckusick return (error); 31026317Skarels /* FALLTHROUGH */ 31126317Skarels 31239183Ssklower case SIOCGIFADDR: 31339183Ssklower case SIOCGIFNETMASK: 31439183Ssklower case SIOCGIFDSTADDR: 31539183Ssklower case SIOCGIFBRDADDR: 31626317Skarels if (ia == (struct in_ifaddr *)0) 31726317Skarels return (EADDRNOTAVAIL); 31826317Skarels break; 31939183Ssklower 32039183Ssklower default: 32139183Ssklower return (EOPNOTSUPP); 32239183Ssklower break; 32317271Skarels } 32418377Skarels switch (cmd) { 32518377Skarels 32618377Skarels case SIOCGIFADDR: 32737471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 32818377Skarels break; 32918377Skarels 33018377Skarels case SIOCGIFBRDADDR: 33118377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 33218377Skarels return (EINVAL); 33337471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 33418377Skarels break; 33518377Skarels 33618377Skarels case SIOCGIFDSTADDR: 33718377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33818377Skarels return (EINVAL); 33937471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 34018377Skarels break; 34118377Skarels 34218377Skarels case SIOCGIFNETMASK: 34337471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 34418377Skarels break; 34518377Skarels 34618377Skarels case SIOCSIFDSTADDR: 34718377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 34818377Skarels return (EINVAL); 34927066Skarels oldaddr = ia->ia_dstaddr; 35037471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 35118377Skarels if (ifp->if_ioctl && 35227066Skarels (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 35327066Skarels ia->ia_dstaddr = oldaddr; 35418377Skarels return (error); 35527066Skarels } 35627066Skarels if (ia->ia_flags & IFA_ROUTE) { 35737471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 35837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 35937471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr; 36037471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 36127066Skarels } 36218377Skarels break; 36318377Skarels 36418377Skarels case SIOCSIFBRDADDR: 36518377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 36618377Skarels return (EINVAL); 36737471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 36818377Skarels break; 36918377Skarels 37018377Skarels case SIOCSIFADDR: 37134500Skarels return (in_ifinit(ifp, ia, 37237471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 37318377Skarels 37418377Skarels case SIOCSIFNETMASK: 37537471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 37637471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 37718377Skarels break; 37818377Skarels 37937471Ssklower case SIOCAIFADDR: 380*44368Skarels maskIsNew = 0; 381*44368Skarels hostIsNew = 1; 382*44368Skarels error = 0; 38337471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 38437471Ssklower if (ifra->ifra_addr.sin_len == 0) { 38537471Ssklower ifra->ifra_addr = ia->ia_addr; 38637471Ssklower hostIsNew = 0; 38737471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 38837471Ssklower ia->ia_addr.sin_addr.s_addr) 38937471Ssklower hostIsNew = 0; 39037471Ssklower } 39137471Ssklower if (ifra->ifra_mask.sin_len) { 39237471Ssklower in_ifscrub(ifp, ia); 39337471Ssklower ia->ia_sockmask = ifra->ifra_mask; 39437471Ssklower ia->ia_subnetmask = 395*44368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 39637471Ssklower maskIsNew = 1; 39737471Ssklower } 39837471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 39937471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 40037471Ssklower in_ifscrub(ifp, ia); 40137471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 40237471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 40337471Ssklower } 40437471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 405*44368Skarels (hostIsNew || maskIsNew)) 40637471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 40737471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 40837471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 40937471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 41037471Ssklower return (error); 41137471Ssklower 41237471Ssklower case SIOCDIFADDR: 41337471Ssklower in_ifscrub(ifp, ia); 41437471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 41537471Ssklower ifp->if_addrlist = ifa->ifa_next; 41637471Ssklower else { 41737471Ssklower while (ifa->ifa_next && 41837471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 41937471Ssklower ifa = ifa->ifa_next; 42037471Ssklower if (ifa->ifa_next) 421*44368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 42237471Ssklower else 42337471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 42437471Ssklower } 42537471Ssklower oia = ia; 426*44368Skarels if (oia == (ia = in_ifaddr)) 42737471Ssklower in_ifaddr = ia->ia_next; 428*44368Skarels else { 429*44368Skarels while (ia->ia_next && (ia->ia_next != oia)) 43037471Ssklower ia = ia->ia_next; 43137471Ssklower if (ia->ia_next) 432*44368Skarels ia->ia_next = oia->ia_next; 43337471Ssklower else 43437471Ssklower printf("Didn't unlink inifadr from list\n"); 43537471Ssklower } 43637471Ssklower (void) m_free(dtom(oia)); 43737471Ssklower break; 43837471Ssklower 43918377Skarels default: 44018377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 44118377Skarels return (EOPNOTSUPP); 44218377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 44318377Skarels } 44417271Skarels return (0); 44517271Skarels } 44617271Skarels 44717271Skarels /* 44837471Ssklower * Delete any existing route for an interface. 44937471Ssklower */ 45037471Ssklower in_ifscrub(ifp, ia) 45137471Ssklower register struct ifnet *ifp; 45237471Ssklower register struct in_ifaddr *ia; 45337471Ssklower { 45437471Ssklower 45537471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 45637471Ssklower return; 45737471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 45837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 45937471Ssklower else 46037471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 46137471Ssklower ia->ia_flags &= ~IFA_ROUTE; 46237471Ssklower } 46337471Ssklower 46437471Ssklower /* 46518377Skarels * Initialize an interface's internet address 46618377Skarels * and routing table entry. 4677159Ssam */ 46837471Ssklower in_ifinit(ifp, ia, sin, scrub) 4697159Ssam register struct ifnet *ifp; 47018377Skarels register struct in_ifaddr *ia; 47118377Skarels struct sockaddr_in *sin; 4727159Ssam { 47318377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 47437471Ssklower struct sockaddr_in oldaddr; 47518377Skarels int s = splimp(), error; 4767159Ssam 47727066Skarels oldaddr = ia->ia_addr; 47837471Ssklower ia->ia_addr = *sin; 47918377Skarels /* 48026317Skarels * Give the interface a chance to initialize 48126317Skarels * if this is its first address, 48226317Skarels * and to validate the address if necessary. 48326317Skarels */ 48426317Skarels if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 48526317Skarels splx(s); 48627066Skarels ia->ia_addr = oldaddr; 48726317Skarels return (error); 48826317Skarels } 48937471Ssklower if (scrub) { 49037471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 49137471Ssklower in_ifscrub(ifp, ia); 49237471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 49318377Skarels } 49418377Skarels if (IN_CLASSA(i)) 49518377Skarels ia->ia_netmask = IN_CLASSA_NET; 49618377Skarels else if (IN_CLASSB(i)) 49718377Skarels ia->ia_netmask = IN_CLASSB_NET; 49818377Skarels else 49918377Skarels ia->ia_netmask = IN_CLASSC_NET; 50018377Skarels ia->ia_net = i & ia->ia_netmask; 50118377Skarels /* 50218377Skarels * The subnet mask includes at least the standard network part, 50318377Skarels * but may already have been set to a larger value. 50418377Skarels */ 50518377Skarels ia->ia_subnetmask |= ia->ia_netmask; 50618377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 50737471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 50839183Ssklower { 50939183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 51039183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 51139183Ssklower while (--cp >= cpbase) 51239183Ssklower if (*cp) { 51339183Ssklower ia->ia_sockmask.sin_len = 51439183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 51539183Ssklower break; 51639183Ssklower } 51739183Ssklower } 51818377Skarels if (ifp->if_flags & IFF_BROADCAST) { 51937471Ssklower ia->ia_broadaddr.sin_addr = 52018377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 52125195Skarels ia->ia_netbroadcast.s_addr = 52225195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 52318377Skarels } 52418377Skarels /* 52518377Skarels * Add route for the network. 52618377Skarels */ 52737471Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 52837471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 52937471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 53037471Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 53137471Ssklower ia->ia_dstaddr.sin_family == AF_INET) 53237471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 53327066Skarels else { 53437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 53527066Skarels } 53618377Skarels ia->ia_flags |= IFA_ROUTE; 53730523Skarels splx(s); 53818642Skarels return (0); 5397159Ssam } 54018377Skarels 54118377Skarels /* 54218377Skarels * Return address info for specified internet network. 54318377Skarels */ 54418377Skarels struct in_ifaddr * 54518377Skarels in_iaonnetof(net) 54618377Skarels u_long net; 54718377Skarels { 54818377Skarels register struct in_ifaddr *ia; 54918377Skarels 55018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 55118377Skarels if (ia->ia_subnet == net) 55218377Skarels return (ia); 55318377Skarels return ((struct in_ifaddr *)0); 55418377Skarels } 55518377Skarels 55618377Skarels /* 55730523Skarels * Return 1 if the address might be a local broadcast address. 55818377Skarels */ 55918377Skarels in_broadcast(in) 56018377Skarels struct in_addr in; 56118377Skarels { 56218377Skarels register struct in_ifaddr *ia; 56330523Skarels u_long t; 56418377Skarels 56518377Skarels /* 56618377Skarels * Look through the list of addresses for a match 56718377Skarels * with a broadcast address. 56818377Skarels */ 56918377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 57030523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 57137471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 57218377Skarels return (1); 57330523Skarels /* 57430523Skarels * Check for old-style (host 0) broadcast. 57530523Skarels */ 57630523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 57730523Skarels return (1); 57830523Skarels } 57930523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 58030523Skarels return (1); 58118377Skarels return (0); 58218377Skarels } 5837159Ssam #endif 584