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*58998Ssklower * @(#)in.c 7.31 (Berkeley) 04/07/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 13126381Skarels #ifndef SUBNETSARELOCAL 13226381Skarels #define SUBNETSARELOCAL 1 13326381Skarels #endif 13426381Skarels int subnetsarelocal = SUBNETSARELOCAL; 13516377Skarels /* 13618377Skarels * Return 1 if an internet address is for a ``local'' host 13726381Skarels * (one to which we have a connection). If subnetsarelocal 13826381Skarels * is true, this includes other subnets of the local net. 13926381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 14017271Skarels */ 14117271Skarels in_localaddr(in) 14217271Skarels struct in_addr in; 14317271Skarels { 14417271Skarels register u_long i = ntohl(in.s_addr); 14518377Skarels register struct in_ifaddr *ia; 14617271Skarels 14730697Skarels if (subnetsarelocal) { 14830697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 14930697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 15030697Skarels return (1); 15130697Skarels } else { 15230697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 15330697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 15430697Skarels return (1); 15530697Skarels } 15618377Skarels return (0); 15718377Skarels } 15818377Skarels 15931392Skarels /* 16031392Skarels * Determine whether an IP address is in a reserved set of addresses 16131392Skarels * that may not be forwarded, or whether datagrams to that destination 16231392Skarels * may be forwarded. 16331392Skarels */ 16431392Skarels in_canforward(in) 16531392Skarels struct in_addr in; 16631392Skarels { 16731392Skarels register u_long i = ntohl(in.s_addr); 16831392Skarels register u_long net; 16931392Skarels 170*58998Ssklower if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) 17131392Skarels return (0); 17231392Skarels if (IN_CLASSA(i)) { 17331392Skarels net = i & IN_CLASSA_NET; 17457938Ssklower if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 17531392Skarels return (0); 17631392Skarels } 17731392Skarels return (1); 17831392Skarels } 17931392Skarels 180*58998Ssklower /* 181*58998Ssklower * Trim a mask in a sockaddr 182*58998Ssklower */ 183*58998Ssklower void 184*58998Ssklower in_socktrim(ap) 185*58998Ssklower struct sockaddr_in *ap; 186*58998Ssklower { 187*58998Ssklower register char *cplim = (char *) &ap->sin_addr; 188*58998Ssklower register char *cp = (char *) (&ap->sin_addr + 1); 189*58998Ssklower 190*58998Ssklower ap->sin_len = 0; 191*58998Ssklower while (--cp > cplim) 192*58998Ssklower if (*cp) { 193*58998Ssklower (ap)->sin_len = cp - (char *) (ap) + 1; 194*58998Ssklower break; 195*58998Ssklower } 196*58998Ssklower } 197*58998Ssklower 19824805Skarels int in_interfaces; /* number of external internet interfaces */ 19924805Skarels extern struct ifnet loif; 20024805Skarels 20118377Skarels /* 20218377Skarels * Generic internet control operations (ioctl's). 20318377Skarels * Ifp is 0 if not an interface-specific ioctl. 20418377Skarels */ 20524805Skarels /* ARGSUSED */ 20618377Skarels in_control(so, cmd, data, ifp) 20718377Skarels struct socket *so; 20818377Skarels int cmd; 20918377Skarels caddr_t data; 21018377Skarels register struct ifnet *ifp; 21118377Skarels { 21218377Skarels register struct ifreq *ifr = (struct ifreq *)data; 21318377Skarels register struct in_ifaddr *ia = 0; 21437471Ssklower register struct ifaddr *ifa; 21537471Ssklower struct in_ifaddr *oia; 21637471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 21737471Ssklower struct sockaddr_in oldaddr; 21837471Ssklower int error, hostIsNew, maskIsNew; 21937471Ssklower u_long i; 22018377Skarels 22118377Skarels /* 22218377Skarels * Find address for this interface, if it exists. 22318377Skarels */ 22418377Skarels if (ifp) 22518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 22618377Skarels if (ia->ia_ifp == ifp) 22718377Skarels break; 22818377Skarels 22918377Skarels switch (cmd) { 23018377Skarels 23137471Ssklower case SIOCAIFADDR: 23237471Ssklower case SIOCDIFADDR: 23337471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 23437471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 23537471Ssklower if (ia->ia_ifp == ifp && 23637471Ssklower ia->ia_addr.sin_addr.s_addr == 23737471Ssklower ifra->ifra_addr.sin_addr.s_addr) 23837471Ssklower break; 23937471Ssklower } 24037471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 24137471Ssklower return (EADDRNOTAVAIL); 24237471Ssklower /* FALLTHROUGH */ 24318377Skarels case SIOCSIFADDR: 24418377Skarels case SIOCSIFNETMASK: 24526456Skarels case SIOCSIFDSTADDR: 24648464Skarels if ((so->so_state & SS_PRIV) == 0) 24748464Skarels return (EPERM); 24818377Skarels 24918377Skarels if (ifp == 0) 25018377Skarels panic("in_control"); 25118377Skarels if (ia == (struct in_ifaddr *)0) { 25252028Ssklower oia = (struct in_ifaddr *) 25352028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK); 25452028Ssklower if (oia == (struct in_ifaddr *)NULL) 25518377Skarels return (ENOBUFS); 25652028Ssklower bzero((caddr_t)oia, sizeof *oia); 25718377Skarels if (ia = in_ifaddr) { 25818377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 25952915Storek continue; 26052028Ssklower ia->ia_next = oia; 26118377Skarels } else 26252028Ssklower in_ifaddr = oia; 26352028Ssklower ia = oia; 26418377Skarels if (ifa = ifp->if_addrlist) { 26518377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 26652915Storek continue; 26718377Skarels ifa->ifa_next = (struct ifaddr *) ia; 26818377Skarels } else 26918377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 27037471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 27137471Ssklower ia->ia_ifa.ifa_dstaddr 27237471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 27337471Ssklower ia->ia_ifa.ifa_netmask 27437471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 27537471Ssklower ia->ia_sockmask.sin_len = 8; 27637471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 27737471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 27837471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 27937471Ssklower } 28018377Skarels ia->ia_ifp = ifp; 28124805Skarels if (ifp != &loif) 28224805Skarels in_interfaces++; 28317271Skarels } 28418377Skarels break; 28526317Skarels 28626317Skarels case SIOCSIFBRDADDR: 28748464Skarels if ((so->so_state & SS_PRIV) == 0) 28848464Skarels return (EPERM); 28926317Skarels /* FALLTHROUGH */ 29026317Skarels 29139183Ssklower case SIOCGIFADDR: 29239183Ssklower case SIOCGIFNETMASK: 29339183Ssklower case SIOCGIFDSTADDR: 29439183Ssklower case SIOCGIFBRDADDR: 29526317Skarels if (ia == (struct in_ifaddr *)0) 29626317Skarels return (EADDRNOTAVAIL); 29726317Skarels break; 29817271Skarels } 29918377Skarels switch (cmd) { 30018377Skarels 30118377Skarels case SIOCGIFADDR: 30237471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 30318377Skarels break; 30418377Skarels 30518377Skarels case SIOCGIFBRDADDR: 30618377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 30718377Skarels return (EINVAL); 30837471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 30918377Skarels break; 31018377Skarels 31118377Skarels case SIOCGIFDSTADDR: 31218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 31318377Skarels return (EINVAL); 31437471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 31518377Skarels break; 31618377Skarels 31718377Skarels case SIOCGIFNETMASK: 31837471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 31918377Skarels break; 32018377Skarels 32118377Skarels case SIOCSIFDSTADDR: 32218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 32318377Skarels return (EINVAL); 32427066Skarels oldaddr = ia->ia_dstaddr; 32537471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 32652619Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 32752619Ssklower (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 32827066Skarels ia->ia_dstaddr = oldaddr; 32918377Skarels return (error); 33027066Skarels } 33127066Skarels if (ia->ia_flags & IFA_ROUTE) { 33237471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 33337471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 33445454Ssklower ia->ia_ifa.ifa_dstaddr = 33545454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 33637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 33727066Skarels } 33818377Skarels break; 33918377Skarels 34018377Skarels case SIOCSIFBRDADDR: 34118377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 34218377Skarels return (EINVAL); 34337471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 34418377Skarels break; 34518377Skarels 34618377Skarels case SIOCSIFADDR: 34734500Skarels return (in_ifinit(ifp, ia, 34837471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 34918377Skarels 35018377Skarels case SIOCSIFNETMASK: 35137471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 35237471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 35318377Skarels break; 35418377Skarels 35537471Ssklower case SIOCAIFADDR: 35644368Skarels maskIsNew = 0; 35744368Skarels hostIsNew = 1; 35844368Skarels error = 0; 35937471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 36037471Ssklower if (ifra->ifra_addr.sin_len == 0) { 36137471Ssklower ifra->ifra_addr = ia->ia_addr; 36237471Ssklower hostIsNew = 0; 36337471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 36437471Ssklower ia->ia_addr.sin_addr.s_addr) 36537471Ssklower hostIsNew = 0; 36637471Ssklower } 36737471Ssklower if (ifra->ifra_mask.sin_len) { 36837471Ssklower in_ifscrub(ifp, ia); 36937471Ssklower ia->ia_sockmask = ifra->ifra_mask; 37037471Ssklower ia->ia_subnetmask = 37144368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 37237471Ssklower maskIsNew = 1; 37337471Ssklower } 37437471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 37537471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 37637471Ssklower in_ifscrub(ifp, ia); 37737471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 37837471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 37937471Ssklower } 38037471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 38144368Skarels (hostIsNew || maskIsNew)) 38237471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 38337471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 38437471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 38537471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 38637471Ssklower return (error); 38737471Ssklower 38837471Ssklower case SIOCDIFADDR: 38937471Ssklower in_ifscrub(ifp, ia); 39037471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 39137471Ssklower ifp->if_addrlist = ifa->ifa_next; 39237471Ssklower else { 39337471Ssklower while (ifa->ifa_next && 39437471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 39537471Ssklower ifa = ifa->ifa_next; 39637471Ssklower if (ifa->ifa_next) 39744368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 39837471Ssklower else 39937471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 40037471Ssklower } 40137471Ssklower oia = ia; 40244368Skarels if (oia == (ia = in_ifaddr)) 40337471Ssklower in_ifaddr = ia->ia_next; 40444368Skarels else { 40544368Skarels while (ia->ia_next && (ia->ia_next != oia)) 40637471Ssklower ia = ia->ia_next; 40737471Ssklower if (ia->ia_next) 40844368Skarels ia->ia_next = oia->ia_next; 40937471Ssklower else 41037471Ssklower printf("Didn't unlink inifadr from list\n"); 41137471Ssklower } 41252028Ssklower IFAFREE((&oia->ia_ifa)); 41337471Ssklower break; 41437471Ssklower 41518377Skarels default: 41618377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 41718377Skarels return (EOPNOTSUPP); 41818377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 41918377Skarels } 42017271Skarels return (0); 42117271Skarels } 42217271Skarels 42317271Skarels /* 42437471Ssklower * Delete any existing route for an interface. 42537471Ssklower */ 42637471Ssklower in_ifscrub(ifp, ia) 42737471Ssklower register struct ifnet *ifp; 42837471Ssklower register struct in_ifaddr *ia; 42937471Ssklower { 43037471Ssklower 43137471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 43237471Ssklower return; 43337471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 43437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 43537471Ssklower else 43637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 43737471Ssklower ia->ia_flags &= ~IFA_ROUTE; 43837471Ssklower } 43937471Ssklower 44037471Ssklower /* 44118377Skarels * Initialize an interface's internet address 44218377Skarels * and routing table entry. 4437159Ssam */ 44437471Ssklower in_ifinit(ifp, ia, sin, scrub) 4457159Ssam register struct ifnet *ifp; 44618377Skarels register struct in_ifaddr *ia; 44718377Skarels struct sockaddr_in *sin; 44852274Storek int scrub; 4497159Ssam { 45018377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 45137471Ssklower struct sockaddr_in oldaddr; 45254716Ssklower int s = splimp(), flags = RTF_UP, error, ether_output(); 45354716Ssklower void arp_rtrequest(); 4547159Ssam 45527066Skarels oldaddr = ia->ia_addr; 45637471Ssklower ia->ia_addr = *sin; 45718377Skarels /* 45826317Skarels * Give the interface a chance to initialize 45926317Skarels * if this is its first address, 46026317Skarels * and to validate the address if necessary. 46126317Skarels */ 46252274Storek if (ifp->if_ioctl && 46352274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 46426317Skarels splx(s); 46527066Skarels ia->ia_addr = oldaddr; 46626317Skarels return (error); 46726317Skarels } 46850134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 46950134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 47050134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 47150134Ssklower } 47245454Ssklower splx(s); 47337471Ssklower if (scrub) { 47437471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 47537471Ssklower in_ifscrub(ifp, ia); 47637471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 47718377Skarels } 47818377Skarels if (IN_CLASSA(i)) 47918377Skarels ia->ia_netmask = IN_CLASSA_NET; 48018377Skarels else if (IN_CLASSB(i)) 48118377Skarels ia->ia_netmask = IN_CLASSB_NET; 48218377Skarels else 48318377Skarels ia->ia_netmask = IN_CLASSC_NET; 48418377Skarels ia->ia_net = i & ia->ia_netmask; 48518377Skarels /* 48618377Skarels * The subnet mask includes at least the standard network part, 48718377Skarels * but may already have been set to a larger value. 48818377Skarels */ 48918377Skarels ia->ia_subnetmask |= ia->ia_netmask; 49018377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 49137471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 492*58998Ssklower in_socktrim(&ia->ia_sockmask); 49345454Ssklower /* 49445454Ssklower * Add route for the network. 49545454Ssklower */ 49652617Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 49718377Skarels if (ifp->if_flags & IFF_BROADCAST) { 498*58998Ssklower ia->ia_broadaddr.sin_addr.s_addr = 499*58998Ssklower htonl(ia->ia_subnet | ~ia->ia_subnetmask); 50025195Skarels ia->ia_netbroadcast.s_addr = 501*58998Ssklower htonl(ia->ia_net | ~ ia->ia_netmask); 50245454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 50337471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 50445454Ssklower flags |= RTF_HOST; 50545454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 50645454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 50745454Ssklower return (0); 50845454Ssklower flags |= RTF_HOST; 50927066Skarels } 51045454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 51145454Ssklower ia->ia_flags |= IFA_ROUTE; 51254716Ssklower /* 51354716Ssklower * If the interface supports multicast, join the "all hosts" 51454716Ssklower * multicast group on that interface. 51554716Ssklower */ 51654716Ssklower if (ifp->if_flags & IFF_MULTICAST) { 51754716Ssklower struct in_addr addr; 51854716Ssklower 51954716Ssklower addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 52054716Ssklower in_addmulti(&addr, ifp); 52154716Ssklower } 52245454Ssklower return (error); 5237159Ssam } 52418377Skarels 52518377Skarels 52618377Skarels /* 52730523Skarels * Return 1 if the address might be a local broadcast address. 52818377Skarels */ 529*58998Ssklower in_broadcast(in, ifp) 53018377Skarels struct in_addr in; 531*58998Ssklower struct ifnet *ifp; 53218377Skarels { 533*58998Ssklower register struct ifaddr *ifa; 53430523Skarels u_long t; 53518377Skarels 536*58998Ssklower if (in.s_addr == INADDR_BROADCAST || 537*58998Ssklower in.s_addr == INADDR_ANY) 538*58998Ssklower return 1; 539*58998Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 540*58998Ssklower return 0; 541*58998Ssklower t = ntohl(in.s_addr); 54218377Skarels /* 54318377Skarels * Look through the list of addresses for a match 54418377Skarels * with a broadcast address. 54518377Skarels */ 546*58998Ssklower #define ia ((struct in_ifaddr *)ifa) 547*58998Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 548*58998Ssklower if (ifa->ifa_addr->sa_family == AF_INET && 549*58998Ssklower (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || 550*58998Ssklower in.s_addr == ia->ia_netbroadcast.s_addr || 551*58998Ssklower /* 552*58998Ssklower * Check for old-style (host 0) broadcast. 553*58998Ssklower */ 554*58998Ssklower t == ia->ia_subnet || t == ia->ia_net)) 555*58998Ssklower return 1; 556*58998Ssklower return 0; 557*58998Ssklower #undef ia 55818377Skarels } 55954716Ssklower /* 56054716Ssklower * Add an address to the list of IP multicast addresses for a given interface. 56154716Ssklower */ 56254716Ssklower struct in_multi * 56354716Ssklower in_addmulti(ap, ifp) 56454716Ssklower register struct in_addr *ap; 56554716Ssklower register struct ifnet *ifp; 56654716Ssklower { 56754716Ssklower register struct in_multi *inm; 56854716Ssklower struct ifreq ifr; 56954716Ssklower struct in_ifaddr *ia; 57054716Ssklower int s = splnet(); 57154716Ssklower 57254716Ssklower /* 57354716Ssklower * See if address already in list. 57454716Ssklower */ 57554716Ssklower IN_LOOKUP_MULTI(*ap, ifp, inm); 57654716Ssklower if (inm != NULL) { 57754716Ssklower /* 57854716Ssklower * Found it; just increment the reference count. 57954716Ssklower */ 58054716Ssklower ++inm->inm_refcount; 58154716Ssklower } 58254716Ssklower else { 58354716Ssklower /* 58454716Ssklower * New address; allocate a new multicast record 58554716Ssklower * and link it into the interface's multicast list. 58654716Ssklower */ 58754716Ssklower inm = (struct in_multi *)malloc(sizeof(*inm), 58854716Ssklower M_IPMADDR, M_NOWAIT); 58954716Ssklower if (inm == NULL) { 59054716Ssklower splx(s); 59154716Ssklower return (NULL); 59254716Ssklower } 59354716Ssklower inm->inm_addr = *ap; 59454716Ssklower inm->inm_ifp = ifp; 59554716Ssklower inm->inm_refcount = 1; 59654716Ssklower IFP_TO_IA(ifp, ia); 59754716Ssklower if (ia == NULL) { 59854716Ssklower free(inm, M_IPMADDR); 59954716Ssklower splx(s); 60054716Ssklower return (NULL); 60154716Ssklower } 60254716Ssklower inm->inm_ia = ia; 60358413Ssklower inm->inm_next = ia->ia_multiaddrs; 60458413Ssklower ia->ia_multiaddrs = inm; 60554716Ssklower /* 60654716Ssklower * Ask the network driver to update its multicast reception 60754716Ssklower * filter appropriately for the new address. 60854716Ssklower */ 60954716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; 61054716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; 61158413Ssklower if ((ifp->if_ioctl == NULL) || 61258413Ssklower (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { 61358413Ssklower ia->ia_multiaddrs = inm->inm_next; 61454716Ssklower free(inm, M_IPMADDR); 61554716Ssklower splx(s); 61654716Ssklower return (NULL); 61754716Ssklower } 61854716Ssklower /* 61954716Ssklower * Let IGMP know that we have joined a new IP multicast group. 62054716Ssklower */ 62154716Ssklower igmp_joingroup(inm); 62254716Ssklower } 62354716Ssklower splx(s); 62454716Ssklower return (inm); 62554716Ssklower } 62654716Ssklower 62754716Ssklower /* 62854716Ssklower * Delete a multicast address record. 62954716Ssklower */ 63054716Ssklower int 63154716Ssklower in_delmulti(inm) 63254716Ssklower register struct in_multi *inm; 63354716Ssklower { 63454716Ssklower register struct in_multi **p; 63554716Ssklower struct ifreq ifr; 63654716Ssklower int s = splnet(); 63754716Ssklower 63854716Ssklower if (--inm->inm_refcount == 0) { 63954716Ssklower /* 64054716Ssklower * No remaining claims to this record; let IGMP know that 64154716Ssklower * we are leaving the multicast group. 64254716Ssklower */ 64354716Ssklower igmp_leavegroup(inm); 64454716Ssklower /* 64554716Ssklower * Unlink from list. 64654716Ssklower */ 64754716Ssklower for (p = &inm->inm_ia->ia_multiaddrs; 64854716Ssklower *p != inm; 64954716Ssklower p = &(*p)->inm_next) 65054716Ssklower continue; 65154716Ssklower *p = (*p)->inm_next; 65254716Ssklower /* 65354716Ssklower * Notify the network driver to update its multicast reception 65454716Ssklower * filter. 65554716Ssklower */ 65654716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 65754716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = 65854716Ssklower inm->inm_addr; 65954716Ssklower (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 66054716Ssklower (caddr_t)&ifr); 66154716Ssklower free(inm, M_IPMADDR); 66254716Ssklower } 66354716Ssklower splx(s); 66454716Ssklower } 6657159Ssam #endif 666