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*57938Ssklower * @(#)in.c 7.29 (Berkeley) 02/11/93 823175Smckusick */ 97159Ssam 1056531Sbostic #include <sys/param.h> 1156531Sbostic #include <sys/ioctl.h> 1256531Sbostic #include <sys/errno.h> 1356531Sbostic #include <sys/malloc.h> 1456531Sbostic #include <sys/socket.h> 1556531Sbostic #include <sys/socketvar.h> 167159Ssam 1756531Sbostic #include <net/if.h> 1856531Sbostic #include <net/route.h> 1956531Sbostic #include <net/af.h> 2056531Sbostic 2156531Sbostic #include <netinet/in_systm.h> 2256531Sbostic #include <netinet/in.h> 2356531Sbostic #include <netinet/in_var.h> 2456531Sbostic 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 else if (IN_CLASSD(i)) 7054716Ssklower net = i & IN_CLASSD_NET; 7118377Skarels else 7231392Skarels return (0); 7316413Skarels 7416413Skarels /* 7518377Skarels * Check whether network is a subnet; 7616413Skarels * if so, return subnet number. 7716413Skarels */ 7818377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 7924805Skarels if (net == ia->ia_net) 8018377Skarels return (i & ia->ia_subnetmask); 8116413Skarels return (net); 827159Ssam } 837159Ssam 847159Ssam /* 8537471Ssklower * Compute and save network mask as sockaddr from an internet address. 8637471Ssklower */ 8737471Ssklower in_sockmaskof(in, sockmask) 8837471Ssklower struct in_addr in; 8937471Ssklower register struct sockaddr_in *sockmask; 9037471Ssklower { 9137471Ssklower register u_long net; 9237471Ssklower register u_long mask; 9337471Ssklower { 9437471Ssklower register u_long i = ntohl(in.s_addr); 9537471Ssklower 9637471Ssklower if (i == 0) 9737471Ssklower net = 0, mask = 0; 9837471Ssklower else if (IN_CLASSA(i)) 9937471Ssklower net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 10037471Ssklower else if (IN_CLASSB(i)) 10137471Ssklower net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 10237471Ssklower else if (IN_CLASSC(i)) 10337471Ssklower net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 10437471Ssklower else 10537471Ssklower net = i, mask = -1; 10637471Ssklower } 10737471Ssklower { 10837471Ssklower register struct in_ifaddr *ia; 10937471Ssklower /* 11037471Ssklower * Check whether network is a subnet; 11137471Ssklower * if so, return subnet number. 11237471Ssklower */ 11337471Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 11437471Ssklower if (net == ia->ia_net) 11537471Ssklower mask = ia->ia_subnetmask; 11637471Ssklower } 11737471Ssklower { 11837471Ssklower register char *cpbase = (char *)&(sockmask->sin_addr); 11939183Ssklower register char *cp = (char *)(1 + &(sockmask->sin_addr)); 12037471Ssklower 12137471Ssklower sockmask->sin_addr.s_addr = htonl(mask); 12237471Ssklower sockmask->sin_len = 0; 12337471Ssklower while (--cp >= cpbase) 12437471Ssklower if (*cp) { 12537471Ssklower sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 12637471Ssklower break; 12737471Ssklower } 12837471Ssklower } 12937471Ssklower } 13037471Ssklower 13137471Ssklower /* 1328595Sroot * Return the host portion of an internet address. 1337159Ssam */ 13426381Skarels u_long 1357159Ssam in_lnaof(in) 1367159Ssam struct in_addr in; 1377159Ssam { 1388937Sroot register u_long i = ntohl(in.s_addr); 13918377Skarels register u_long net, host; 14018377Skarels register struct in_ifaddr *ia; 1417159Ssam 14216377Skarels if (IN_CLASSA(i)) { 14318377Skarels net = i & IN_CLASSA_NET; 14418377Skarels host = i & IN_CLASSA_HOST; 14516377Skarels } else if (IN_CLASSB(i)) { 14618377Skarels net = i & IN_CLASSB_NET; 14718377Skarels host = i & IN_CLASSB_HOST; 14831392Skarels } else if (IN_CLASSC(i)) { 14918377Skarels net = i & IN_CLASSC_NET; 15018377Skarels host = i & IN_CLASSC_HOST; 15154716Ssklower } else if (IN_CLASSD(i)) { 15254716Ssklower net = i & IN_CLASSD_NET; 15354716Ssklower host = i & IN_CLASSD_HOST; 15431392Skarels } else 15531392Skarels return (i); 1567159Ssam 15716413Skarels /* 15818377Skarels * Check whether network is a subnet; 15916413Skarels * if so, use the modified interpretation of `host'. 16016413Skarels */ 16118377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 16224805Skarels if (net == ia->ia_net) 16318377Skarels return (host &~ ia->ia_subnetmask); 16416413Skarels return (host); 16516377Skarels } 16616377Skarels 16726381Skarels #ifndef SUBNETSARELOCAL 16826381Skarels #define SUBNETSARELOCAL 1 16926381Skarels #endif 17026381Skarels int subnetsarelocal = SUBNETSARELOCAL; 17116377Skarels /* 17218377Skarels * Return 1 if an internet address is for a ``local'' host 17326381Skarels * (one to which we have a connection). If subnetsarelocal 17426381Skarels * is true, this includes other subnets of the local net. 17526381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 17617271Skarels */ 17717271Skarels in_localaddr(in) 17817271Skarels struct in_addr in; 17917271Skarels { 18017271Skarels register u_long i = ntohl(in.s_addr); 18118377Skarels register struct in_ifaddr *ia; 18217271Skarels 18330697Skarels if (subnetsarelocal) { 18430697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18530697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 18630697Skarels return (1); 18730697Skarels } else { 18830697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18930697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 19030697Skarels return (1); 19130697Skarels } 19218377Skarels return (0); 19318377Skarels } 19418377Skarels 19531392Skarels /* 19631392Skarels * Determine whether an IP address is in a reserved set of addresses 19731392Skarels * that may not be forwarded, or whether datagrams to that destination 19831392Skarels * may be forwarded. 19931392Skarels */ 20031392Skarels in_canforward(in) 20131392Skarels struct in_addr in; 20231392Skarels { 20331392Skarels register u_long i = ntohl(in.s_addr); 20431392Skarels register u_long net; 20531392Skarels 20631392Skarels if (IN_EXPERIMENTAL(i)) 20731392Skarels return (0); 20831392Skarels if (IN_CLASSA(i)) { 20931392Skarels net = i & IN_CLASSA_NET; 210*57938Ssklower if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 21131392Skarels return (0); 21231392Skarels } 21331392Skarels return (1); 21431392Skarels } 21531392Skarels 21624805Skarels int in_interfaces; /* number of external internet interfaces */ 21724805Skarels extern struct ifnet loif; 21824805Skarels 21918377Skarels /* 22018377Skarels * Generic internet control operations (ioctl's). 22118377Skarels * Ifp is 0 if not an interface-specific ioctl. 22218377Skarels */ 22324805Skarels /* ARGSUSED */ 22418377Skarels in_control(so, cmd, data, ifp) 22518377Skarels struct socket *so; 22618377Skarels int cmd; 22718377Skarels caddr_t data; 22818377Skarels register struct ifnet *ifp; 22918377Skarels { 23018377Skarels register struct ifreq *ifr = (struct ifreq *)data; 23118377Skarels register struct in_ifaddr *ia = 0; 23237471Ssklower register struct ifaddr *ifa; 23337471Ssklower struct in_ifaddr *oia; 23437471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 23537471Ssklower struct sockaddr_in oldaddr; 23637471Ssklower int error, hostIsNew, maskIsNew; 23737471Ssklower u_long i; 23818377Skarels 23918377Skarels /* 24018377Skarels * Find address for this interface, if it exists. 24118377Skarels */ 24218377Skarels if (ifp) 24318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 24418377Skarels if (ia->ia_ifp == ifp) 24518377Skarels break; 24618377Skarels 24718377Skarels switch (cmd) { 24818377Skarels 24937471Ssklower case SIOCAIFADDR: 25037471Ssklower case SIOCDIFADDR: 25137471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 25237471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 25337471Ssklower if (ia->ia_ifp == ifp && 25437471Ssklower ia->ia_addr.sin_addr.s_addr == 25537471Ssklower ifra->ifra_addr.sin_addr.s_addr) 25637471Ssklower break; 25737471Ssklower } 25837471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 25937471Ssklower return (EADDRNOTAVAIL); 26037471Ssklower /* FALLTHROUGH */ 26118377Skarels case SIOCSIFADDR: 26218377Skarels case SIOCSIFNETMASK: 26326456Skarels case SIOCSIFDSTADDR: 26448464Skarels if ((so->so_state & SS_PRIV) == 0) 26548464Skarels return (EPERM); 26618377Skarels 26718377Skarels if (ifp == 0) 26818377Skarels panic("in_control"); 26918377Skarels if (ia == (struct in_ifaddr *)0) { 27052028Ssklower oia = (struct in_ifaddr *) 27152028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK); 27252028Ssklower if (oia == (struct in_ifaddr *)NULL) 27318377Skarels return (ENOBUFS); 27452028Ssklower bzero((caddr_t)oia, sizeof *oia); 27518377Skarels if (ia = in_ifaddr) { 27618377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 27752915Storek continue; 27852028Ssklower ia->ia_next = oia; 27918377Skarels } else 28052028Ssklower in_ifaddr = oia; 28152028Ssklower ia = oia; 28218377Skarels if (ifa = ifp->if_addrlist) { 28318377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 28452915Storek continue; 28518377Skarels ifa->ifa_next = (struct ifaddr *) ia; 28618377Skarels } else 28718377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 28837471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 28937471Ssklower ia->ia_ifa.ifa_dstaddr 29037471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 29137471Ssklower ia->ia_ifa.ifa_netmask 29237471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 29337471Ssklower ia->ia_sockmask.sin_len = 8; 29437471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 29537471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 29637471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 29737471Ssklower } 29818377Skarels ia->ia_ifp = ifp; 29924805Skarels if (ifp != &loif) 30024805Skarels in_interfaces++; 30117271Skarels } 30218377Skarels break; 30326317Skarels 30426317Skarels case SIOCSIFBRDADDR: 30548464Skarels if ((so->so_state & SS_PRIV) == 0) 30648464Skarels return (EPERM); 30726317Skarels /* FALLTHROUGH */ 30826317Skarels 30939183Ssklower case SIOCGIFADDR: 31039183Ssklower case SIOCGIFNETMASK: 31139183Ssklower case SIOCGIFDSTADDR: 31239183Ssklower case SIOCGIFBRDADDR: 31326317Skarels if (ia == (struct in_ifaddr *)0) 31426317Skarels return (EADDRNOTAVAIL); 31526317Skarels break; 31617271Skarels } 31718377Skarels switch (cmd) { 31818377Skarels 31918377Skarels case SIOCGIFADDR: 32037471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 32118377Skarels break; 32218377Skarels 32318377Skarels case SIOCGIFBRDADDR: 32418377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32518377Skarels return (EINVAL); 32637471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32718377Skarels break; 32818377Skarels 32918377Skarels case SIOCGIFDSTADDR: 33018377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33118377Skarels return (EINVAL); 33237471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33318377Skarels break; 33418377Skarels 33518377Skarels case SIOCGIFNETMASK: 33637471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33718377Skarels break; 33818377Skarels 33918377Skarels case SIOCSIFDSTADDR: 34018377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 34118377Skarels return (EINVAL); 34227066Skarels oldaddr = ia->ia_dstaddr; 34337471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 34452619Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 34552619Ssklower (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 34627066Skarels ia->ia_dstaddr = oldaddr; 34718377Skarels return (error); 34827066Skarels } 34927066Skarels if (ia->ia_flags & IFA_ROUTE) { 35037471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 35137471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 35245454Ssklower ia->ia_ifa.ifa_dstaddr = 35345454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 35437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35527066Skarels } 35618377Skarels break; 35718377Skarels 35818377Skarels case SIOCSIFBRDADDR: 35918377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 36018377Skarels return (EINVAL); 36137471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 36218377Skarels break; 36318377Skarels 36418377Skarels case SIOCSIFADDR: 36534500Skarels return (in_ifinit(ifp, ia, 36637471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36718377Skarels 36818377Skarels case SIOCSIFNETMASK: 36937471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 37037471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 37118377Skarels break; 37218377Skarels 37337471Ssklower case SIOCAIFADDR: 37444368Skarels maskIsNew = 0; 37544368Skarels hostIsNew = 1; 37644368Skarels error = 0; 37737471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 37837471Ssklower if (ifra->ifra_addr.sin_len == 0) { 37937471Ssklower ifra->ifra_addr = ia->ia_addr; 38037471Ssklower hostIsNew = 0; 38137471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 38237471Ssklower ia->ia_addr.sin_addr.s_addr) 38337471Ssklower hostIsNew = 0; 38437471Ssklower } 38537471Ssklower if (ifra->ifra_mask.sin_len) { 38637471Ssklower in_ifscrub(ifp, ia); 38737471Ssklower ia->ia_sockmask = ifra->ifra_mask; 38837471Ssklower ia->ia_subnetmask = 38944368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 39037471Ssklower maskIsNew = 1; 39137471Ssklower } 39237471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 39337471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 39437471Ssklower in_ifscrub(ifp, ia); 39537471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 39637471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 39737471Ssklower } 39837471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 39944368Skarels (hostIsNew || maskIsNew)) 40037471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 40137471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 40237471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 40337471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 40437471Ssklower return (error); 40537471Ssklower 40637471Ssklower case SIOCDIFADDR: 40737471Ssklower in_ifscrub(ifp, ia); 40837471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 40937471Ssklower ifp->if_addrlist = ifa->ifa_next; 41037471Ssklower else { 41137471Ssklower while (ifa->ifa_next && 41237471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 41337471Ssklower ifa = ifa->ifa_next; 41437471Ssklower if (ifa->ifa_next) 41544368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 41637471Ssklower else 41737471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 41837471Ssklower } 41937471Ssklower oia = ia; 42044368Skarels if (oia == (ia = in_ifaddr)) 42137471Ssklower in_ifaddr = ia->ia_next; 42244368Skarels else { 42344368Skarels while (ia->ia_next && (ia->ia_next != oia)) 42437471Ssklower ia = ia->ia_next; 42537471Ssklower if (ia->ia_next) 42644368Skarels ia->ia_next = oia->ia_next; 42737471Ssklower else 42837471Ssklower printf("Didn't unlink inifadr from list\n"); 42937471Ssklower } 43052028Ssklower IFAFREE((&oia->ia_ifa)); 43137471Ssklower break; 43237471Ssklower 43318377Skarels default: 43418377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43518377Skarels return (EOPNOTSUPP); 43618377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43718377Skarels } 43817271Skarels return (0); 43917271Skarels } 44017271Skarels 44117271Skarels /* 44237471Ssklower * Delete any existing route for an interface. 44337471Ssklower */ 44437471Ssklower in_ifscrub(ifp, ia) 44537471Ssklower register struct ifnet *ifp; 44637471Ssklower register struct in_ifaddr *ia; 44737471Ssklower { 44837471Ssklower 44937471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 45037471Ssklower return; 45137471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 45237471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 45337471Ssklower else 45437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45537471Ssklower ia->ia_flags &= ~IFA_ROUTE; 45637471Ssklower } 45737471Ssklower 45837471Ssklower /* 45918377Skarels * Initialize an interface's internet address 46018377Skarels * and routing table entry. 4617159Ssam */ 46237471Ssklower in_ifinit(ifp, ia, sin, scrub) 4637159Ssam register struct ifnet *ifp; 46418377Skarels register struct in_ifaddr *ia; 46518377Skarels struct sockaddr_in *sin; 46652274Storek int scrub; 4677159Ssam { 46818377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 46937471Ssklower struct sockaddr_in oldaddr; 47054716Ssklower int s = splimp(), flags = RTF_UP, error, ether_output(); 47154716Ssklower void arp_rtrequest(); 4727159Ssam 47327066Skarels oldaddr = ia->ia_addr; 47437471Ssklower ia->ia_addr = *sin; 47518377Skarels /* 47626317Skarels * Give the interface a chance to initialize 47726317Skarels * if this is its first address, 47826317Skarels * and to validate the address if necessary. 47926317Skarels */ 48052274Storek if (ifp->if_ioctl && 48152274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 48226317Skarels splx(s); 48327066Skarels ia->ia_addr = oldaddr; 48426317Skarels return (error); 48526317Skarels } 48650134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 48750134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 48850134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 48950134Ssklower } 49045454Ssklower splx(s); 49137471Ssklower if (scrub) { 49237471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 49337471Ssklower in_ifscrub(ifp, ia); 49437471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 49518377Skarels } 49618377Skarels if (IN_CLASSA(i)) 49718377Skarels ia->ia_netmask = IN_CLASSA_NET; 49818377Skarels else if (IN_CLASSB(i)) 49918377Skarels ia->ia_netmask = IN_CLASSB_NET; 50018377Skarels else 50118377Skarels ia->ia_netmask = IN_CLASSC_NET; 50218377Skarels ia->ia_net = i & ia->ia_netmask; 50318377Skarels /* 50418377Skarels * The subnet mask includes at least the standard network part, 50518377Skarels * but may already have been set to a larger value. 50618377Skarels */ 50718377Skarels ia->ia_subnetmask |= ia->ia_netmask; 50818377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 50937471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 51039183Ssklower { 51139183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 51239183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 51339183Ssklower while (--cp >= cpbase) 51439183Ssklower if (*cp) { 51539183Ssklower ia->ia_sockmask.sin_len = 51639183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 51739183Ssklower break; 51839183Ssklower } 51939183Ssklower } 52045454Ssklower /* 52145454Ssklower * Add route for the network. 52245454Ssklower */ 52352617Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 52418377Skarels if (ifp->if_flags & IFF_BROADCAST) { 52537471Ssklower ia->ia_broadaddr.sin_addr = 52618377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 52725195Skarels ia->ia_netbroadcast.s_addr = 52825195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 52945454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 53037471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 53145454Ssklower flags |= RTF_HOST; 53245454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 53345454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 53445454Ssklower return (0); 53545454Ssklower flags |= RTF_HOST; 53627066Skarels } 53745454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 53845454Ssklower ia->ia_flags |= IFA_ROUTE; 53954716Ssklower /* 54054716Ssklower * If the interface supports multicast, join the "all hosts" 54154716Ssklower * multicast group on that interface. 54254716Ssklower */ 54354716Ssklower if (ifp->if_flags & IFF_MULTICAST) { 54454716Ssklower struct in_addr addr; 54554716Ssklower 54654716Ssklower addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 54754716Ssklower in_addmulti(&addr, ifp); 54854716Ssklower } 54945454Ssklower return (error); 5507159Ssam } 55118377Skarels 55218377Skarels /* 55318377Skarels * Return address info for specified internet network. 55418377Skarels */ 55518377Skarels struct in_ifaddr * 55618377Skarels in_iaonnetof(net) 55718377Skarels u_long net; 55818377Skarels { 55918377Skarels register struct in_ifaddr *ia; 56018377Skarels 56118377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 56218377Skarels if (ia->ia_subnet == net) 56318377Skarels return (ia); 56418377Skarels return ((struct in_ifaddr *)0); 56518377Skarels } 56618377Skarels 56718377Skarels /* 56830523Skarels * Return 1 if the address might be a local broadcast address. 56918377Skarels */ 57018377Skarels in_broadcast(in) 57118377Skarels struct in_addr in; 57218377Skarels { 57318377Skarels register struct in_ifaddr *ia; 57430523Skarels u_long t; 57518377Skarels 57618377Skarels /* 57718377Skarels * Look through the list of addresses for a match 57818377Skarels * with a broadcast address. 57918377Skarels */ 58018377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 58130523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 58237471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 58318377Skarels return (1); 58430523Skarels /* 58530523Skarels * Check for old-style (host 0) broadcast. 58630523Skarels */ 58730523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 58830523Skarels return (1); 58930523Skarels } 59030523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 59130523Skarels return (1); 59218377Skarels return (0); 59318377Skarels } 59454716Ssklower 59554716Ssklower /* 59654716Ssklower * Add an address to the list of IP multicast addresses for a given interface. 59754716Ssklower */ 59854716Ssklower struct in_multi * 59954716Ssklower in_addmulti(ap, ifp) 60054716Ssklower register struct in_addr *ap; 60154716Ssklower register struct ifnet *ifp; 60254716Ssklower { 60354716Ssklower register struct in_multi *inm; 60454716Ssklower struct ifreq ifr; 60554716Ssklower struct in_ifaddr *ia; 60654716Ssklower int s = splnet(); 60757872Sandrew int error; 60854716Ssklower 60954716Ssklower /* 61054716Ssklower * See if address already in list. 61154716Ssklower */ 61254716Ssklower IN_LOOKUP_MULTI(*ap, ifp, inm); 61354716Ssklower if (inm != NULL) { 61454716Ssklower /* 61554716Ssklower * Found it; just increment the reference count. 61654716Ssklower */ 61754716Ssklower ++inm->inm_refcount; 61854716Ssklower } 61954716Ssklower else { 62054716Ssklower /* 62154716Ssklower * New address; allocate a new multicast record 62254716Ssklower * and link it into the interface's multicast list. 62354716Ssklower */ 62454716Ssklower inm = (struct in_multi *)malloc(sizeof(*inm), 62554716Ssklower M_IPMADDR, M_NOWAIT); 62654716Ssklower if (inm == NULL) { 62754716Ssklower splx(s); 62854716Ssklower return (NULL); 62954716Ssklower } 63054716Ssklower inm->inm_addr = *ap; 63154716Ssklower inm->inm_ifp = ifp; 63254716Ssklower inm->inm_refcount = 1; 63354716Ssklower IFP_TO_IA(ifp, ia); 63454716Ssklower if (ia == NULL) { 63554716Ssklower free(inm, M_IPMADDR); 63654716Ssklower splx(s); 63754716Ssklower return (NULL); 63854716Ssklower } 63954716Ssklower inm->inm_ia = ia; 64054716Ssklower /* 64154716Ssklower * Ask the network driver to update its multicast reception 64254716Ssklower * filter appropriately for the new address. 64354716Ssklower */ 64454716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; 64554716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; 64654716Ssklower if (ifp->if_ioctl == NULL) { 64754716Ssklower free(inm, M_IPMADDR); 64854716Ssklower splx(s); 64954716Ssklower return (NULL); 65054716Ssklower } 65154716Ssklower error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr); 65254716Ssklower if (error != 0) { 65354716Ssklower free(inm, M_IPMADDR); 65454716Ssklower splx(s); 65554716Ssklower return (NULL); 65654716Ssklower } 65757872Sandrew inm->inm_next = ia->ia_multiaddrs; 65857872Sandrew ia->ia_multiaddrs = inm; 65954716Ssklower /* 66054716Ssklower * Let IGMP know that we have joined a new IP multicast group. 66154716Ssklower */ 66254716Ssklower igmp_joingroup(inm); 66354716Ssklower } 66454716Ssklower splx(s); 66554716Ssklower return (inm); 66654716Ssklower } 66754716Ssklower 66854716Ssklower /* 66954716Ssklower * Delete a multicast address record. 67054716Ssklower */ 67154716Ssklower int 67254716Ssklower in_delmulti(inm) 67354716Ssklower register struct in_multi *inm; 67454716Ssklower { 67554716Ssklower register struct in_multi **p; 67654716Ssklower struct ifreq ifr; 67754716Ssklower int s = splnet(); 67854716Ssklower 67954716Ssklower if (--inm->inm_refcount == 0) { 68054716Ssklower /* 68154716Ssklower * No remaining claims to this record; let IGMP know that 68254716Ssklower * we are leaving the multicast group. 68354716Ssklower */ 68454716Ssklower igmp_leavegroup(inm); 68554716Ssklower /* 68654716Ssklower * Unlink from list. 68754716Ssklower */ 68854716Ssklower for (p = &inm->inm_ia->ia_multiaddrs; 68954716Ssklower *p != inm; 69054716Ssklower p = &(*p)->inm_next) 69154716Ssklower continue; 69254716Ssklower *p = (*p)->inm_next; 69354716Ssklower /* 69454716Ssklower * Notify the network driver to update its multicast reception 69554716Ssklower * filter. 69654716Ssklower */ 69754716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 69854716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = 69954716Ssklower inm->inm_addr; 70054716Ssklower (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 70154716Ssklower (caddr_t)&ifr); 70254716Ssklower free(inm, M_IPMADDR); 70354716Ssklower } 70454716Ssklower splx(s); 70554716Ssklower } 7067159Ssam #endif 707