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*56531Sbostic * @(#)in.c 7.26 (Berkeley) 10/11/92 823175Smckusick */ 97159Ssam 10*56531Sbostic #include <sys/param.h> 11*56531Sbostic #include <sys/ioctl.h> 12*56531Sbostic #include <sys/errno.h> 13*56531Sbostic #include <sys/malloc.h> 14*56531Sbostic #include <sys/socket.h> 15*56531Sbostic #include <sys/socketvar.h> 167159Ssam 17*56531Sbostic #include <net/if.h> 18*56531Sbostic #include <net/route.h> 19*56531Sbostic #include <net/af.h> 20*56531Sbostic 21*56531Sbostic #include <netinet/in_systm.h> 22*56531Sbostic #include <netinet/in.h> 23*56531Sbostic #include <netinet/in_var.h> 24*56531Sbostic 257159Ssam #ifdef INET 267159Ssam /* 2718377Skarels * Formulate an Internet address from network + host. 287159Ssam */ 297159Ssam struct in_addr 3018377Skarels in_makeaddr(net, host) 3118377Skarels u_long net, host; 327159Ssam { 3318377Skarels register struct in_ifaddr *ia; 3418377Skarels register u_long mask; 357159Ssam u_long addr; 367159Ssam 3718377Skarels if (IN_CLASSA(net)) 3818377Skarels mask = IN_CLASSA_HOST; 3918377Skarels else if (IN_CLASSB(net)) 4018377Skarels mask = IN_CLASSB_HOST; 417159Ssam else 4218377Skarels mask = IN_CLASSC_HOST; 4318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 4418377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 4518377Skarels mask = ~ia->ia_subnetmask; 4618377Skarels break; 4718377Skarels } 4818377Skarels addr = htonl(net | (host & mask)); 497159Ssam return (*(struct in_addr *)&addr); 507159Ssam } 517159Ssam 527159Ssam /* 538595Sroot * Return the network number from an internet address. 547159Ssam */ 5524805Skarels u_long 567159Ssam in_netof(in) 577159Ssam struct in_addr in; 587159Ssam { 598937Sroot register u_long i = ntohl(in.s_addr); 6018377Skarels register u_long net; 6118377Skarels register struct in_ifaddr *ia; 627159Ssam 6318377Skarels if (IN_CLASSA(i)) 6418377Skarels net = i & IN_CLASSA_NET; 6518377Skarels else if (IN_CLASSB(i)) 6618377Skarels net = i & IN_CLASSB_NET; 6731392Skarels else if (IN_CLASSC(i)) 6831392Skarels net = i & IN_CLASSC_NET; 6954716Ssklower #ifdef MULTICAST 7054716Ssklower else if (IN_CLASSD(i)) 7154716Ssklower net = i & IN_CLASSD_NET; 7254716Ssklower #endif 7318377Skarels else 7431392Skarels return (0); 7516413Skarels 7616413Skarels /* 7718377Skarels * Check whether network is a subnet; 7816413Skarels * if so, return subnet number. 7916413Skarels */ 8018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 8124805Skarels if (net == ia->ia_net) 8218377Skarels return (i & ia->ia_subnetmask); 8316413Skarels return (net); 847159Ssam } 857159Ssam 867159Ssam /* 8737471Ssklower * Compute and save network mask as sockaddr from an internet address. 8837471Ssklower */ 8937471Ssklower in_sockmaskof(in, sockmask) 9037471Ssklower struct in_addr in; 9137471Ssklower register struct sockaddr_in *sockmask; 9237471Ssklower { 9337471Ssklower register u_long net; 9437471Ssklower register u_long mask; 9537471Ssklower { 9637471Ssklower register u_long i = ntohl(in.s_addr); 9737471Ssklower 9837471Ssklower if (i == 0) 9937471Ssklower net = 0, mask = 0; 10037471Ssklower else if (IN_CLASSA(i)) 10137471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 10237471Ssklower else if (IN_CLASSB(i)) 10337471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 10437471Ssklower else if (IN_CLASSC(i)) 10537471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 10637471Ssklower else 10737471Ssklower net = i, mask = -1; 10837471Ssklower } 10937471Ssklower { 11037471Ssklower register struct in_ifaddr *ia; 11137471Ssklower /* 11237471Ssklower * Check whether network is a subnet; 11337471Ssklower * if so, return subnet number. 11437471Ssklower */ 11537471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 11637471Ssklower if (net == ia->ia_net) 11737471Ssklower mask = ia->ia_subnetmask; 11837471Ssklower } 11937471Ssklower { 12037471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 12139183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 12237471Ssklower 12337471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 12437471Ssklower sockmask->sin_len = 0; 12537471Ssklower while (--cp >= cpbase) 12637471Ssklower if (*cp) { 12737471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 12837471Ssklower break; 12937471Ssklower } 13037471Ssklower } 13137471Ssklower } 13237471Ssklower 13337471Ssklower /* 1348595Sroot * Return the host portion of an internet address. 1357159Ssam */ 13626381Skarels u_long 1377159Ssam in_lnaof(in) 1387159Ssam struct in_addr in; 1397159Ssam { 1408937Sroot register u_long i = ntohl(in.s_addr); 14118377Skarels register u_long net, host; 14218377Skarels register struct in_ifaddr *ia; 1437159Ssam 14416377Skarels if (IN_CLASSA(i)) { 14518377Skarels net = i & IN_CLASSA_NET; 14618377Skarels host = i & IN_CLASSA_HOST; 14716377Skarels } else if (IN_CLASSB(i)) { 14818377Skarels net = i & IN_CLASSB_NET; 14918377Skarels host = i & IN_CLASSB_HOST; 15031392Skarels } else if (IN_CLASSC(i)) { 15118377Skarels net = i & IN_CLASSC_NET; 15218377Skarels host = i & IN_CLASSC_HOST; 15354716Ssklower #ifdef MULTICAST 15454716Ssklower } else if (IN_CLASSD(i)) { 15554716Ssklower net = i & IN_CLASSD_NET; 15654716Ssklower host = i & IN_CLASSD_HOST; 15754716Ssklower #endif 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; 23937471Ssklower struct sockaddr_in oldaddr; 24037471Ssklower int error, hostIsNew, maskIsNew; 24137471Ssklower u_long i; 24218377Skarels 24318377Skarels /* 24418377Skarels * Find address for this interface, if it exists. 24518377Skarels */ 24618377Skarels if (ifp) 24718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 24818377Skarels if (ia->ia_ifp == ifp) 24918377Skarels break; 25018377Skarels 25118377Skarels switch (cmd) { 25218377Skarels 25337471Ssklower case SIOCAIFADDR: 25437471Ssklower case SIOCDIFADDR: 25537471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 25637471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 25737471Ssklower if (ia->ia_ifp == ifp && 25837471Ssklower ia->ia_addr.sin_addr.s_addr == 25937471Ssklower ifra->ifra_addr.sin_addr.s_addr) 26037471Ssklower break; 26137471Ssklower } 26237471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 26337471Ssklower return (EADDRNOTAVAIL); 26437471Ssklower /* FALLTHROUGH */ 26518377Skarels case SIOCSIFADDR: 26618377Skarels case SIOCSIFNETMASK: 26726456Skarels case SIOCSIFDSTADDR: 26848464Skarels if ((so->so_state & SS_PRIV) == 0) 26948464Skarels return (EPERM); 27018377Skarels 27118377Skarels if (ifp == 0) 27218377Skarels panic("in_control"); 27318377Skarels if (ia == (struct in_ifaddr *)0) { 27452028Ssklower oia = (struct in_ifaddr *) 27552028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK); 27652028Ssklower if (oia == (struct in_ifaddr *)NULL) 27718377Skarels return (ENOBUFS); 27852028Ssklower bzero((caddr_t)oia, sizeof *oia); 27918377Skarels if (ia = in_ifaddr) { 28018377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 28152915Storek continue; 28252028Ssklower ia->ia_next = oia; 28318377Skarels } else 28452028Ssklower in_ifaddr = oia; 28552028Ssklower ia = oia; 28618377Skarels if (ifa = ifp->if_addrlist) { 28718377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 28852915Storek continue; 28918377Skarels ifa->ifa_next = (struct ifaddr *) ia; 29018377Skarels } else 29118377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 29237471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 29337471Ssklower ia->ia_ifa.ifa_dstaddr 29437471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 29537471Ssklower ia->ia_ifa.ifa_netmask 29637471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 29737471Ssklower ia->ia_sockmask.sin_len = 8; 29837471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 29937471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 30037471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 30137471Ssklower } 30218377Skarels ia->ia_ifp = ifp; 30324805Skarels if (ifp != &loif) 30424805Skarels in_interfaces++; 30517271Skarels } 30618377Skarels break; 30726317Skarels 30826317Skarels case SIOCSIFBRDADDR: 30948464Skarels if ((so->so_state & SS_PRIV) == 0) 31048464Skarels return (EPERM); 31126317Skarels /* FALLTHROUGH */ 31226317Skarels 31339183Ssklower case SIOCGIFADDR: 31439183Ssklower case SIOCGIFNETMASK: 31539183Ssklower case SIOCGIFDSTADDR: 31639183Ssklower case SIOCGIFBRDADDR: 31726317Skarels if (ia == (struct in_ifaddr *)0) 31826317Skarels return (EADDRNOTAVAIL); 31926317Skarels break; 32017271Skarels } 32118377Skarels switch (cmd) { 32218377Skarels 32318377Skarels case SIOCGIFADDR: 32437471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 32518377Skarels break; 32618377Skarels 32718377Skarels case SIOCGIFBRDADDR: 32818377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32918377Skarels return (EINVAL); 33037471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 33118377Skarels break; 33218377Skarels 33318377Skarels case SIOCGIFDSTADDR: 33418377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33518377Skarels return (EINVAL); 33637471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33718377Skarels break; 33818377Skarels 33918377Skarels case SIOCGIFNETMASK: 34037471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 34118377Skarels break; 34218377Skarels 34318377Skarels case SIOCSIFDSTADDR: 34418377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 34518377Skarels return (EINVAL); 34627066Skarels oldaddr = ia->ia_dstaddr; 34737471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 34852619Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 34952619Ssklower (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 35027066Skarels ia->ia_dstaddr = oldaddr; 35118377Skarels return (error); 35227066Skarels } 35327066Skarels if (ia->ia_flags & IFA_ROUTE) { 35437471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 35537471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 35645454Ssklower ia->ia_ifa.ifa_dstaddr = 35745454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 35837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35927066Skarels } 36018377Skarels break; 36118377Skarels 36218377Skarels case SIOCSIFBRDADDR: 36318377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 36418377Skarels return (EINVAL); 36537471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 36618377Skarels break; 36718377Skarels 36818377Skarels case SIOCSIFADDR: 36934500Skarels return (in_ifinit(ifp, ia, 37037471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 37118377Skarels 37218377Skarels case SIOCSIFNETMASK: 37337471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 37437471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 37518377Skarels break; 37618377Skarels 37737471Ssklower case SIOCAIFADDR: 37844368Skarels maskIsNew = 0; 37944368Skarels hostIsNew = 1; 38044368Skarels error = 0; 38137471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 38237471Ssklower if (ifra->ifra_addr.sin_len == 0) { 38337471Ssklower ifra->ifra_addr = ia->ia_addr; 38437471Ssklower hostIsNew = 0; 38537471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 38637471Ssklower ia->ia_addr.sin_addr.s_addr) 38737471Ssklower hostIsNew = 0; 38837471Ssklower } 38937471Ssklower if (ifra->ifra_mask.sin_len) { 39037471Ssklower in_ifscrub(ifp, ia); 39137471Ssklower ia->ia_sockmask = ifra->ifra_mask; 39237471Ssklower ia->ia_subnetmask = 39344368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 39437471Ssklower maskIsNew = 1; 39537471Ssklower } 39637471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 39737471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 39837471Ssklower in_ifscrub(ifp, ia); 39937471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 40037471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 40137471Ssklower } 40237471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 40344368Skarels (hostIsNew || maskIsNew)) 40437471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 40537471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 40637471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 40737471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 40837471Ssklower return (error); 40937471Ssklower 41037471Ssklower case SIOCDIFADDR: 41137471Ssklower in_ifscrub(ifp, ia); 41237471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 41337471Ssklower ifp->if_addrlist = ifa->ifa_next; 41437471Ssklower else { 41537471Ssklower while (ifa->ifa_next && 41637471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 41737471Ssklower ifa = ifa->ifa_next; 41837471Ssklower if (ifa->ifa_next) 41944368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 42037471Ssklower else 42137471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 42237471Ssklower } 42337471Ssklower oia = ia; 42444368Skarels if (oia == (ia = in_ifaddr)) 42537471Ssklower in_ifaddr = ia->ia_next; 42644368Skarels else { 42744368Skarels while (ia->ia_next && (ia->ia_next != oia)) 42837471Ssklower ia = ia->ia_next; 42937471Ssklower if (ia->ia_next) 43044368Skarels ia->ia_next = oia->ia_next; 43137471Ssklower else 43237471Ssklower printf("Didn't unlink inifadr from list\n"); 43337471Ssklower } 43452028Ssklower IFAFREE((&oia->ia_ifa)); 43537471Ssklower break; 43637471Ssklower 43718377Skarels default: 43818377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43918377Skarels return (EOPNOTSUPP); 44018377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 44118377Skarels } 44217271Skarels return (0); 44317271Skarels } 44417271Skarels 44517271Skarels /* 44637471Ssklower * Delete any existing route for an interface. 44737471Ssklower */ 44837471Ssklower in_ifscrub(ifp, ia) 44937471Ssklower register struct ifnet *ifp; 45037471Ssklower register struct in_ifaddr *ia; 45137471Ssklower { 45237471Ssklower 45337471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 45437471Ssklower return; 45537471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 45637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 45737471Ssklower else 45837471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45937471Ssklower ia->ia_flags &= ~IFA_ROUTE; 46037471Ssklower } 46137471Ssklower 46237471Ssklower /* 46318377Skarels * Initialize an interface's internet address 46418377Skarels * and routing table entry. 4657159Ssam */ 46637471Ssklower in_ifinit(ifp, ia, sin, scrub) 4677159Ssam register struct ifnet *ifp; 46818377Skarels register struct in_ifaddr *ia; 46918377Skarels struct sockaddr_in *sin; 47052274Storek int scrub; 4717159Ssam { 47218377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 47337471Ssklower struct sockaddr_in oldaddr; 47454716Ssklower int s = splimp(), flags = RTF_UP, error, ether_output(); 47554716Ssklower void arp_rtrequest(); 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 */ 48452274Storek if (ifp->if_ioctl && 48552274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 48626317Skarels splx(s); 48727066Skarels ia->ia_addr = oldaddr; 48826317Skarels return (error); 48926317Skarels } 49050134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 49150134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 49250134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 49350134Ssklower } 49445454Ssklower splx(s); 49537471Ssklower if (scrub) { 49637471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 49737471Ssklower in_ifscrub(ifp, ia); 49837471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 49918377Skarels } 50018377Skarels if (IN_CLASSA(i)) 50118377Skarels ia->ia_netmask = IN_CLASSA_NET; 50218377Skarels else if (IN_CLASSB(i)) 50318377Skarels ia->ia_netmask = IN_CLASSB_NET; 50418377Skarels else 50518377Skarels ia->ia_netmask = IN_CLASSC_NET; 50618377Skarels ia->ia_net = i & ia->ia_netmask; 50718377Skarels /* 50818377Skarels * The subnet mask includes at least the standard network part, 50918377Skarels * but may already have been set to a larger value. 51018377Skarels */ 51118377Skarels ia->ia_subnetmask |= ia->ia_netmask; 51218377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 51337471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 51439183Ssklower { 51539183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 51639183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 51739183Ssklower while (--cp >= cpbase) 51839183Ssklower if (*cp) { 51939183Ssklower ia->ia_sockmask.sin_len = 52039183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 52139183Ssklower break; 52239183Ssklower } 52339183Ssklower } 52445454Ssklower /* 52545454Ssklower * Add route for the network. 52645454Ssklower */ 52752617Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 52818377Skarels if (ifp->if_flags & IFF_BROADCAST) { 52937471Ssklower ia->ia_broadaddr.sin_addr = 53018377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 53125195Skarels ia->ia_netbroadcast.s_addr = 53225195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 53345454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 53437471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 53545454Ssklower flags |= RTF_HOST; 53645454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 53745454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 53845454Ssklower return (0); 53945454Ssklower flags |= RTF_HOST; 54027066Skarels } 54145454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 54245454Ssklower ia->ia_flags |= IFA_ROUTE; 54354716Ssklower #ifdef MULTICAST 54454716Ssklower /* 54554716Ssklower * If the interface supports multicast, join the "all hosts" 54654716Ssklower * multicast group on that interface. 54754716Ssklower */ 54854716Ssklower if (ifp->if_flags & IFF_MULTICAST) { 54954716Ssklower struct in_addr addr; 55054716Ssklower 55154716Ssklower addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 55254716Ssklower in_addmulti(&addr, ifp); 55354716Ssklower } 55454716Ssklower #endif 55545454Ssklower return (error); 5567159Ssam } 55718377Skarels 55818377Skarels /* 55918377Skarels * Return address info for specified internet network. 56018377Skarels */ 56118377Skarels struct in_ifaddr * 56218377Skarels in_iaonnetof(net) 56318377Skarels u_long net; 56418377Skarels { 56518377Skarels register struct in_ifaddr *ia; 56618377Skarels 56718377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 56818377Skarels if (ia->ia_subnet == net) 56918377Skarels return (ia); 57018377Skarels return ((struct in_ifaddr *)0); 57118377Skarels } 57218377Skarels 57318377Skarels /* 57430523Skarels * Return 1 if the address might be a local broadcast address. 57518377Skarels */ 57618377Skarels in_broadcast(in) 57718377Skarels struct in_addr in; 57818377Skarels { 57918377Skarels register struct in_ifaddr *ia; 58030523Skarels u_long t; 58118377Skarels 58218377Skarels /* 58318377Skarels * Look through the list of addresses for a match 58418377Skarels * with a broadcast address. 58518377Skarels */ 58618377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 58730523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 58837471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 58918377Skarels return (1); 59030523Skarels /* 59130523Skarels * Check for old-style (host 0) broadcast. 59230523Skarels */ 59330523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 59430523Skarels return (1); 59530523Skarels } 59630523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 59730523Skarels return (1); 59818377Skarels return (0); 59918377Skarels } 60054716Ssklower 60154716Ssklower #ifdef MULTICAST 60254716Ssklower /* 60354716Ssklower * Add an address to the list of IP multicast addresses for a given interface. 60454716Ssklower */ 60554716Ssklower struct in_multi * 60654716Ssklower in_addmulti(ap, ifp) 60754716Ssklower register struct in_addr *ap; 60854716Ssklower register struct ifnet *ifp; 60954716Ssklower { 61054716Ssklower register struct in_multi *inm; 61154716Ssklower struct ifreq ifr; 61254716Ssklower struct in_ifaddr *ia; 61354716Ssklower int s = splnet(); 61454716Ssklower int error; 61554716Ssklower 61654716Ssklower /* 61754716Ssklower * See if address already in list. 61854716Ssklower */ 61954716Ssklower IN_LOOKUP_MULTI(*ap, ifp, inm); 62054716Ssklower if (inm != NULL) { 62154716Ssklower /* 62254716Ssklower * Found it; just increment the reference count. 62354716Ssklower */ 62454716Ssklower ++inm->inm_refcount; 62554716Ssklower } 62654716Ssklower else { 62754716Ssklower /* 62854716Ssklower * New address; allocate a new multicast record 62954716Ssklower * and link it into the interface's multicast list. 63054716Ssklower */ 63154716Ssklower inm = (struct in_multi *)malloc(sizeof(*inm), 63254716Ssklower M_IPMADDR, M_NOWAIT); 63354716Ssklower if (inm == NULL) { 63454716Ssklower splx(s); 63554716Ssklower return (NULL); 63654716Ssklower } 63754716Ssklower inm->inm_addr = *ap; 63854716Ssklower inm->inm_ifp = ifp; 63954716Ssklower inm->inm_refcount = 1; 64054716Ssklower IFP_TO_IA(ifp, ia); 64154716Ssklower if (ia == NULL) { 64254716Ssklower free(inm, M_IPMADDR); 64354716Ssklower splx(s); 64454716Ssklower return (NULL); 64554716Ssklower } 64654716Ssklower inm->inm_ia = ia; 64754716Ssklower inm->inm_next = ia->ia_multiaddrs; 64854716Ssklower ia->ia_multiaddrs = inm; 64954716Ssklower /* 65054716Ssklower * Ask the network driver to update its multicast reception 65154716Ssklower * filter appropriately for the new address. 65254716Ssklower */ 65354716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; 65454716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; 65554716Ssklower if (ifp->if_ioctl == NULL) { 65654716Ssklower free(inm, M_IPMADDR); 65754716Ssklower splx(s); 65854716Ssklower return (NULL); 65954716Ssklower } 66054716Ssklower error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr); 66154716Ssklower if (error != 0) { 66254716Ssklower free(inm, M_IPMADDR); 66354716Ssklower splx(s); 66454716Ssklower return (NULL); 66554716Ssklower } 66654716Ssklower /* 66754716Ssklower * Let IGMP know that we have joined a new IP multicast group. 66854716Ssklower */ 66954716Ssklower igmp_joingroup(inm); 67054716Ssklower } 67154716Ssklower splx(s); 67254716Ssklower return (inm); 67354716Ssklower } 67454716Ssklower 67554716Ssklower /* 67654716Ssklower * Delete a multicast address record. 67754716Ssklower */ 67854716Ssklower int 67954716Ssklower in_delmulti(inm) 68054716Ssklower register struct in_multi *inm; 68154716Ssklower { 68254716Ssklower register struct in_multi **p; 68354716Ssklower struct ifreq ifr; 68454716Ssklower int s = splnet(); 68554716Ssklower 68654716Ssklower if (--inm->inm_refcount == 0) { 68754716Ssklower /* 68854716Ssklower * No remaining claims to this record; let IGMP know that 68954716Ssklower * we are leaving the multicast group. 69054716Ssklower */ 69154716Ssklower igmp_leavegroup(inm); 69254716Ssklower /* 69354716Ssklower * Unlink from list. 69454716Ssklower */ 69554716Ssklower for (p = &inm->inm_ia->ia_multiaddrs; 69654716Ssklower *p != inm; 69754716Ssklower p = &(*p)->inm_next) 69854716Ssklower continue; 69954716Ssklower *p = (*p)->inm_next; 70054716Ssklower /* 70154716Ssklower * Notify the network driver to update its multicast reception 70254716Ssklower * filter. 70354716Ssklower */ 70454716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 70554716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = 70654716Ssklower inm->inm_addr; 70754716Ssklower (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 70854716Ssklower (caddr_t)&ifr); 70954716Ssklower free(inm, M_IPMADDR); 71054716Ssklower } 71154716Ssklower splx(s); 71254716Ssklower } 7137159Ssam #endif 71454716Ssklower #endif 715