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*54716Ssklower * @(#)in.c 7.25 (Berkeley) 07/06/92 823175Smckusick */ 97159Ssam 1017058Sbloom #include "param.h" 1118377Skarels #include "ioctl.h" 1250134Ssklower #include "errno.h" 13*54716Ssklower #include "malloc.h" 1417058Sbloom #include "socket.h" 1517058Sbloom #include "socketvar.h" 1617058Sbloom #include "in_systm.h" 1748464Skarels #include "net/if.h" 1848464Skarels #include "net/route.h" 1948464Skarels #include "net/af.h" 2018377Skarels #include "in.h" 2118377Skarels #include "in_var.h" 227159Ssam 237159Ssam #ifdef INET 247159Ssam /* 2518377Skarels * Formulate an Internet address from network + host. 267159Ssam */ 277159Ssam struct in_addr 2818377Skarels in_makeaddr(net, host) 2918377Skarels u_long net, host; 307159Ssam { 3118377Skarels register struct in_ifaddr *ia; 3218377Skarels register u_long mask; 337159Ssam u_long addr; 347159Ssam 3518377Skarels if (IN_CLASSA(net)) 3618377Skarels mask = IN_CLASSA_HOST; 3718377Skarels else if (IN_CLASSB(net)) 3818377Skarels mask = IN_CLASSB_HOST; 397159Ssam else 4018377Skarels mask = IN_CLASSC_HOST; 4118377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 4218377Skarels if ((ia->ia_netmask & net) == ia->ia_net) { 4318377Skarels mask = ~ia->ia_subnetmask; 4418377Skarels break; 4518377Skarels } 4618377Skarels addr = htonl(net | (host & mask)); 477159Ssam return (*(struct in_addr *)&addr); 487159Ssam } 497159Ssam 507159Ssam /* 518595Sroot * Return the network number from an internet address. 527159Ssam */ 5324805Skarels u_long 547159Ssam in_netof(in) 557159Ssam struct in_addr in; 567159Ssam { 578937Sroot register u_long i = ntohl(in.s_addr); 5818377Skarels register u_long net; 5918377Skarels register struct in_ifaddr *ia; 607159Ssam 6118377Skarels if (IN_CLASSA(i)) 6218377Skarels net = i & IN_CLASSA_NET; 6318377Skarels else if (IN_CLASSB(i)) 6418377Skarels net = i & IN_CLASSB_NET; 6531392Skarels else if (IN_CLASSC(i)) 6631392Skarels net = i & IN_CLASSC_NET; 67*54716Ssklower #ifdef MULTICAST 68*54716Ssklower else if (IN_CLASSD(i)) 69*54716Ssklower net = i & IN_CLASSD_NET; 70*54716Ssklower #endif 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; 151*54716Ssklower #ifdef MULTICAST 152*54716Ssklower } else if (IN_CLASSD(i)) { 153*54716Ssklower net = i & IN_CLASSD_NET; 154*54716Ssklower host = i & IN_CLASSD_HOST; 155*54716Ssklower #endif 15631392Skarels } else 15731392Skarels return (i); 1587159Ssam 15916413Skarels /* 16018377Skarels * Check whether network is a subnet; 16116413Skarels * if so, use the modified interpretation of `host'. 16216413Skarels */ 16318377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 16424805Skarels if (net == ia->ia_net) 16518377Skarels return (host &~ ia->ia_subnetmask); 16616413Skarels return (host); 16716377Skarels } 16816377Skarels 16926381Skarels #ifndef SUBNETSARELOCAL 17026381Skarels #define SUBNETSARELOCAL 1 17126381Skarels #endif 17226381Skarels int subnetsarelocal = SUBNETSARELOCAL; 17316377Skarels /* 17418377Skarels * Return 1 if an internet address is for a ``local'' host 17526381Skarels * (one to which we have a connection). If subnetsarelocal 17626381Skarels * is true, this includes other subnets of the local net. 17726381Skarels * Otherwise, it includes only the directly-connected (sub)nets. 17817271Skarels */ 17917271Skarels in_localaddr(in) 18017271Skarels struct in_addr in; 18117271Skarels { 18217271Skarels register u_long i = ntohl(in.s_addr); 18318377Skarels register struct in_ifaddr *ia; 18417271Skarels 18530697Skarels if (subnetsarelocal) { 18630697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 18730697Skarels if ((i & ia->ia_netmask) == ia->ia_net) 18830697Skarels return (1); 18930697Skarels } else { 19030697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 19130697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet) 19230697Skarels return (1); 19330697Skarels } 19418377Skarels return (0); 19518377Skarels } 19618377Skarels 19731392Skarels /* 19831392Skarels * Determine whether an IP address is in a reserved set of addresses 19931392Skarels * that may not be forwarded, or whether datagrams to that destination 20031392Skarels * may be forwarded. 20131392Skarels */ 20231392Skarels in_canforward(in) 20331392Skarels struct in_addr in; 20431392Skarels { 20531392Skarels register u_long i = ntohl(in.s_addr); 20631392Skarels register u_long net; 20731392Skarels 20831392Skarels if (IN_EXPERIMENTAL(i)) 20931392Skarels return (0); 21031392Skarels if (IN_CLASSA(i)) { 21131392Skarels net = i & IN_CLASSA_NET; 21231392Skarels if (net == 0 || net == IN_LOOPBACKNET) 21331392Skarels return (0); 21431392Skarels } 21531392Skarels return (1); 21631392Skarels } 21731392Skarels 21824805Skarels int in_interfaces; /* number of external internet interfaces */ 21924805Skarels extern struct ifnet loif; 22024805Skarels 22118377Skarels /* 22218377Skarels * Generic internet control operations (ioctl's). 22318377Skarels * Ifp is 0 if not an interface-specific ioctl. 22418377Skarels */ 22524805Skarels /* ARGSUSED */ 22618377Skarels in_control(so, cmd, data, ifp) 22718377Skarels struct socket *so; 22818377Skarels int cmd; 22918377Skarels caddr_t data; 23018377Skarels register struct ifnet *ifp; 23118377Skarels { 23218377Skarels register struct ifreq *ifr = (struct ifreq *)data; 23318377Skarels register struct in_ifaddr *ia = 0; 23437471Ssklower register struct ifaddr *ifa; 23537471Ssklower struct in_ifaddr *oia; 23637471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data; 23737471Ssklower struct sockaddr_in oldaddr; 23837471Ssklower int error, hostIsNew, maskIsNew; 23937471Ssklower u_long i; 24018377Skarels 24118377Skarels /* 24218377Skarels * Find address for this interface, if it exists. 24318377Skarels */ 24418377Skarels if (ifp) 24518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 24618377Skarels if (ia->ia_ifp == ifp) 24718377Skarels break; 24818377Skarels 24918377Skarels switch (cmd) { 25018377Skarels 25137471Ssklower case SIOCAIFADDR: 25237471Ssklower case SIOCDIFADDR: 25337471Ssklower if (ifra->ifra_addr.sin_family == AF_INET) 25437471Ssklower for (oia = ia; ia; ia = ia->ia_next) { 25537471Ssklower if (ia->ia_ifp == ifp && 25637471Ssklower ia->ia_addr.sin_addr.s_addr == 25737471Ssklower ifra->ifra_addr.sin_addr.s_addr) 25837471Ssklower break; 25937471Ssklower } 26037471Ssklower if (cmd == SIOCDIFADDR && ia == 0) 26137471Ssklower return (EADDRNOTAVAIL); 26237471Ssklower /* FALLTHROUGH */ 26318377Skarels case SIOCSIFADDR: 26418377Skarels case SIOCSIFNETMASK: 26526456Skarels case SIOCSIFDSTADDR: 26648464Skarels if ((so->so_state & SS_PRIV) == 0) 26748464Skarels return (EPERM); 26818377Skarels 26918377Skarels if (ifp == 0) 27018377Skarels panic("in_control"); 27118377Skarels if (ia == (struct in_ifaddr *)0) { 27252028Ssklower oia = (struct in_ifaddr *) 27352028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK); 27452028Ssklower if (oia == (struct in_ifaddr *)NULL) 27518377Skarels return (ENOBUFS); 27652028Ssklower bzero((caddr_t)oia, sizeof *oia); 27718377Skarels if (ia = in_ifaddr) { 27818377Skarels for ( ; ia->ia_next; ia = ia->ia_next) 27952915Storek continue; 28052028Ssklower ia->ia_next = oia; 28118377Skarels } else 28252028Ssklower in_ifaddr = oia; 28352028Ssklower ia = oia; 28418377Skarels if (ifa = ifp->if_addrlist) { 28518377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 28652915Storek continue; 28718377Skarels ifa->ifa_next = (struct ifaddr *) ia; 28818377Skarels } else 28918377Skarels ifp->if_addrlist = (struct ifaddr *) ia; 29037471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 29137471Ssklower ia->ia_ifa.ifa_dstaddr 29237471Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 29337471Ssklower ia->ia_ifa.ifa_netmask 29437471Ssklower = (struct sockaddr *)&ia->ia_sockmask; 29537471Ssklower ia->ia_sockmask.sin_len = 8; 29637471Ssklower if (ifp->if_flags & IFF_BROADCAST) { 29737471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 29837471Ssklower ia->ia_broadaddr.sin_family = AF_INET; 29937471Ssklower } 30018377Skarels ia->ia_ifp = ifp; 30124805Skarels if (ifp != &loif) 30224805Skarels in_interfaces++; 30317271Skarels } 30418377Skarels break; 30526317Skarels 30626317Skarels case SIOCSIFBRDADDR: 30748464Skarels if ((so->so_state & SS_PRIV) == 0) 30848464Skarels return (EPERM); 30926317Skarels /* FALLTHROUGH */ 31026317Skarels 31139183Ssklower case SIOCGIFADDR: 31239183Ssklower case SIOCGIFNETMASK: 31339183Ssklower case SIOCGIFDSTADDR: 31439183Ssklower case SIOCGIFBRDADDR: 31526317Skarels if (ia == (struct in_ifaddr *)0) 31626317Skarels return (EADDRNOTAVAIL); 31726317Skarels break; 31817271Skarels } 31918377Skarels switch (cmd) { 32018377Skarels 32118377Skarels case SIOCGIFADDR: 32237471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 32318377Skarels break; 32418377Skarels 32518377Skarels case SIOCGIFBRDADDR: 32618377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 32718377Skarels return (EINVAL); 32837471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 32918377Skarels break; 33018377Skarels 33118377Skarels case SIOCGIFDSTADDR: 33218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 33318377Skarels return (EINVAL); 33437471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 33518377Skarels break; 33618377Skarels 33718377Skarels case SIOCGIFNETMASK: 33837471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 33918377Skarels break; 34018377Skarels 34118377Skarels case SIOCSIFDSTADDR: 34218377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 34318377Skarels return (EINVAL); 34427066Skarels oldaddr = ia->ia_dstaddr; 34537471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 34652619Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 34752619Ssklower (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 34827066Skarels ia->ia_dstaddr = oldaddr; 34918377Skarels return (error); 35027066Skarels } 35127066Skarels if (ia->ia_flags & IFA_ROUTE) { 35237471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 35337471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 35445454Ssklower ia->ia_ifa.ifa_dstaddr = 35545454Ssklower (struct sockaddr *)&ia->ia_dstaddr; 35637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 35727066Skarels } 35818377Skarels break; 35918377Skarels 36018377Skarels case SIOCSIFBRDADDR: 36118377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0) 36218377Skarels return (EINVAL); 36337471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 36418377Skarels break; 36518377Skarels 36618377Skarels case SIOCSIFADDR: 36734500Skarels return (in_ifinit(ifp, ia, 36837471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1)); 36918377Skarels 37018377Skarels case SIOCSIFNETMASK: 37137471Ssklower i = ifra->ifra_addr.sin_addr.s_addr; 37237471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 37318377Skarels break; 37418377Skarels 37537471Ssklower case SIOCAIFADDR: 37644368Skarels maskIsNew = 0; 37744368Skarels hostIsNew = 1; 37844368Skarels error = 0; 37937471Ssklower if (ia->ia_addr.sin_family == AF_INET) { 38037471Ssklower if (ifra->ifra_addr.sin_len == 0) { 38137471Ssklower ifra->ifra_addr = ia->ia_addr; 38237471Ssklower hostIsNew = 0; 38337471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr == 38437471Ssklower ia->ia_addr.sin_addr.s_addr) 38537471Ssklower hostIsNew = 0; 38637471Ssklower } 38737471Ssklower if (ifra->ifra_mask.sin_len) { 38837471Ssklower in_ifscrub(ifp, ia); 38937471Ssklower ia->ia_sockmask = ifra->ifra_mask; 39037471Ssklower ia->ia_subnetmask = 39144368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr); 39237471Ssklower maskIsNew = 1; 39337471Ssklower } 39437471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 39537471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) { 39637471Ssklower in_ifscrub(ifp, ia); 39737471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 39837471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 39937471Ssklower } 40037471Ssklower if (ifra->ifra_addr.sin_family == AF_INET && 40144368Skarels (hostIsNew || maskIsNew)) 40237471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 40337471Ssklower if ((ifp->if_flags & IFF_BROADCAST) && 40437471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET)) 40537471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr; 40637471Ssklower return (error); 40737471Ssklower 40837471Ssklower case SIOCDIFADDR: 40937471Ssklower in_ifscrub(ifp, ia); 41037471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 41137471Ssklower ifp->if_addrlist = ifa->ifa_next; 41237471Ssklower else { 41337471Ssklower while (ifa->ifa_next && 41437471Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 41537471Ssklower ifa = ifa->ifa_next; 41637471Ssklower if (ifa->ifa_next) 41744368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 41837471Ssklower else 41937471Ssklower printf("Couldn't unlink inifaddr from ifp\n"); 42037471Ssklower } 42137471Ssklower oia = ia; 42244368Skarels if (oia == (ia = in_ifaddr)) 42337471Ssklower in_ifaddr = ia->ia_next; 42444368Skarels else { 42544368Skarels while (ia->ia_next && (ia->ia_next != oia)) 42637471Ssklower ia = ia->ia_next; 42737471Ssklower if (ia->ia_next) 42844368Skarels ia->ia_next = oia->ia_next; 42937471Ssklower else 43037471Ssklower printf("Didn't unlink inifadr from list\n"); 43137471Ssklower } 43252028Ssklower IFAFREE((&oia->ia_ifa)); 43337471Ssklower break; 43437471Ssklower 43518377Skarels default: 43618377Skarels if (ifp == 0 || ifp->if_ioctl == 0) 43718377Skarels return (EOPNOTSUPP); 43818377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data)); 43918377Skarels } 44017271Skarels return (0); 44117271Skarels } 44217271Skarels 44317271Skarels /* 44437471Ssklower * Delete any existing route for an interface. 44537471Ssklower */ 44637471Ssklower in_ifscrub(ifp, ia) 44737471Ssklower register struct ifnet *ifp; 44837471Ssklower register struct in_ifaddr *ia; 44937471Ssklower { 45037471Ssklower 45137471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 45237471Ssklower return; 45337471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 45437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 45537471Ssklower else 45637471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 45737471Ssklower ia->ia_flags &= ~IFA_ROUTE; 45837471Ssklower } 45937471Ssklower 46037471Ssklower /* 46118377Skarels * Initialize an interface's internet address 46218377Skarels * and routing table entry. 4637159Ssam */ 46437471Ssklower in_ifinit(ifp, ia, sin, scrub) 4657159Ssam register struct ifnet *ifp; 46618377Skarels register struct in_ifaddr *ia; 46718377Skarels struct sockaddr_in *sin; 46852274Storek int scrub; 4697159Ssam { 47018377Skarels register u_long i = ntohl(sin->sin_addr.s_addr); 47137471Ssklower struct sockaddr_in oldaddr; 472*54716Ssklower int s = splimp(), flags = RTF_UP, error, ether_output(); 473*54716Ssklower void arp_rtrequest(); 4747159Ssam 47527066Skarels oldaddr = ia->ia_addr; 47637471Ssklower ia->ia_addr = *sin; 47718377Skarels /* 47826317Skarels * Give the interface a chance to initialize 47926317Skarels * if this is its first address, 48026317Skarels * and to validate the address if necessary. 48126317Skarels */ 48252274Storek if (ifp->if_ioctl && 48352274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 48426317Skarels splx(s); 48527066Skarels ia->ia_addr = oldaddr; 48626317Skarels return (error); 48726317Skarels } 48850134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 48950134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 49050134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 49150134Ssklower } 49245454Ssklower splx(s); 49337471Ssklower if (scrub) { 49437471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 49537471Ssklower in_ifscrub(ifp, ia); 49637471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 49718377Skarels } 49818377Skarels if (IN_CLASSA(i)) 49918377Skarels ia->ia_netmask = IN_CLASSA_NET; 50018377Skarels else if (IN_CLASSB(i)) 50118377Skarels ia->ia_netmask = IN_CLASSB_NET; 50218377Skarels else 50318377Skarels ia->ia_netmask = IN_CLASSC_NET; 50418377Skarels ia->ia_net = i & ia->ia_netmask; 50518377Skarels /* 50618377Skarels * The subnet mask includes at least the standard network part, 50718377Skarels * but may already have been set to a larger value. 50818377Skarels */ 50918377Skarels ia->ia_subnetmask |= ia->ia_netmask; 51018377Skarels ia->ia_subnet = i & ia->ia_subnetmask; 51137471Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 51239183Ssklower { 51339183Ssklower register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 51439183Ssklower register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 51539183Ssklower while (--cp >= cpbase) 51639183Ssklower if (*cp) { 51739183Ssklower ia->ia_sockmask.sin_len = 51839183Ssklower 1 + cp - (char *) &(ia->ia_sockmask); 51939183Ssklower break; 52039183Ssklower } 52139183Ssklower } 52245454Ssklower /* 52345454Ssklower * Add route for the network. 52445454Ssklower */ 52552617Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 52618377Skarels if (ifp->if_flags & IFF_BROADCAST) { 52737471Ssklower ia->ia_broadaddr.sin_addr = 52818377Skarels in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 52925195Skarels ia->ia_netbroadcast.s_addr = 53025195Skarels htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 53145454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) { 53237471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 53345454Ssklower flags |= RTF_HOST; 53445454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) { 53545454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET) 53645454Ssklower return (0); 53745454Ssklower flags |= RTF_HOST; 53827066Skarels } 53945454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 54045454Ssklower ia->ia_flags |= IFA_ROUTE; 541*54716Ssklower #ifdef MULTICAST 542*54716Ssklower /* 543*54716Ssklower * If the interface supports multicast, join the "all hosts" 544*54716Ssklower * multicast group on that interface. 545*54716Ssklower */ 546*54716Ssklower if (ifp->if_flags & IFF_MULTICAST) { 547*54716Ssklower struct in_addr addr; 548*54716Ssklower 549*54716Ssklower addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 550*54716Ssklower in_addmulti(&addr, ifp); 551*54716Ssklower } 552*54716Ssklower #endif 55345454Ssklower return (error); 5547159Ssam } 55518377Skarels 55618377Skarels /* 55718377Skarels * Return address info for specified internet network. 55818377Skarels */ 55918377Skarels struct in_ifaddr * 56018377Skarels in_iaonnetof(net) 56118377Skarels u_long net; 56218377Skarels { 56318377Skarels register struct in_ifaddr *ia; 56418377Skarels 56518377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 56618377Skarels if (ia->ia_subnet == net) 56718377Skarels return (ia); 56818377Skarels return ((struct in_ifaddr *)0); 56918377Skarels } 57018377Skarels 57118377Skarels /* 57230523Skarels * Return 1 if the address might be a local broadcast address. 57318377Skarels */ 57418377Skarels in_broadcast(in) 57518377Skarels struct in_addr in; 57618377Skarels { 57718377Skarels register struct in_ifaddr *ia; 57830523Skarels u_long t; 57918377Skarels 58018377Skarels /* 58118377Skarels * Look through the list of addresses for a match 58218377Skarels * with a broadcast address. 58318377Skarels */ 58418377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next) 58530523Skarels if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 58637471Ssklower if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 58718377Skarels return (1); 58830523Skarels /* 58930523Skarels * Check for old-style (host 0) broadcast. 59030523Skarels */ 59130523Skarels if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 59230523Skarels return (1); 59330523Skarels } 59430523Skarels if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 59530523Skarels return (1); 59618377Skarels return (0); 59718377Skarels } 598*54716Ssklower 599*54716Ssklower #ifdef MULTICAST 600*54716Ssklower /* 601*54716Ssklower * Add an address to the list of IP multicast addresses for a given interface. 602*54716Ssklower */ 603*54716Ssklower struct in_multi * 604*54716Ssklower in_addmulti(ap, ifp) 605*54716Ssklower register struct in_addr *ap; 606*54716Ssklower register struct ifnet *ifp; 607*54716Ssklower { 608*54716Ssklower register struct in_multi *inm; 609*54716Ssklower struct ifreq ifr; 610*54716Ssklower struct in_ifaddr *ia; 611*54716Ssklower int s = splnet(); 612*54716Ssklower int error; 613*54716Ssklower 614*54716Ssklower /* 615*54716Ssklower * See if address already in list. 616*54716Ssklower */ 617*54716Ssklower IN_LOOKUP_MULTI(*ap, ifp, inm); 618*54716Ssklower if (inm != NULL) { 619*54716Ssklower /* 620*54716Ssklower * Found it; just increment the reference count. 621*54716Ssklower */ 622*54716Ssklower ++inm->inm_refcount; 623*54716Ssklower } 624*54716Ssklower else { 625*54716Ssklower /* 626*54716Ssklower * New address; allocate a new multicast record 627*54716Ssklower * and link it into the interface's multicast list. 628*54716Ssklower */ 629*54716Ssklower inm = (struct in_multi *)malloc(sizeof(*inm), 630*54716Ssklower M_IPMADDR, M_NOWAIT); 631*54716Ssklower if (inm == NULL) { 632*54716Ssklower splx(s); 633*54716Ssklower return (NULL); 634*54716Ssklower } 635*54716Ssklower inm->inm_addr = *ap; 636*54716Ssklower inm->inm_ifp = ifp; 637*54716Ssklower inm->inm_refcount = 1; 638*54716Ssklower IFP_TO_IA(ifp, ia); 639*54716Ssklower if (ia == NULL) { 640*54716Ssklower free(inm, M_IPMADDR); 641*54716Ssklower splx(s); 642*54716Ssklower return (NULL); 643*54716Ssklower } 644*54716Ssklower inm->inm_ia = ia; 645*54716Ssklower inm->inm_next = ia->ia_multiaddrs; 646*54716Ssklower ia->ia_multiaddrs = inm; 647*54716Ssklower /* 648*54716Ssklower * Ask the network driver to update its multicast reception 649*54716Ssklower * filter appropriately for the new address. 650*54716Ssklower */ 651*54716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; 652*54716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; 653*54716Ssklower if (ifp->if_ioctl == NULL) { 654*54716Ssklower free(inm, M_IPMADDR); 655*54716Ssklower splx(s); 656*54716Ssklower return (NULL); 657*54716Ssklower } 658*54716Ssklower error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr); 659*54716Ssklower if (error != 0) { 660*54716Ssklower free(inm, M_IPMADDR); 661*54716Ssklower splx(s); 662*54716Ssklower return (NULL); 663*54716Ssklower } 664*54716Ssklower /* 665*54716Ssklower * Let IGMP know that we have joined a new IP multicast group. 666*54716Ssklower */ 667*54716Ssklower igmp_joingroup(inm); 668*54716Ssklower } 669*54716Ssklower splx(s); 670*54716Ssklower return (inm); 671*54716Ssklower } 672*54716Ssklower 673*54716Ssklower /* 674*54716Ssklower * Delete a multicast address record. 675*54716Ssklower */ 676*54716Ssklower int 677*54716Ssklower in_delmulti(inm) 678*54716Ssklower register struct in_multi *inm; 679*54716Ssklower { 680*54716Ssklower register struct in_multi **p; 681*54716Ssklower struct ifreq ifr; 682*54716Ssklower int s = splnet(); 683*54716Ssklower 684*54716Ssklower if (--inm->inm_refcount == 0) { 685*54716Ssklower /* 686*54716Ssklower * No remaining claims to this record; let IGMP know that 687*54716Ssklower * we are leaving the multicast group. 688*54716Ssklower */ 689*54716Ssklower igmp_leavegroup(inm); 690*54716Ssklower /* 691*54716Ssklower * Unlink from list. 692*54716Ssklower */ 693*54716Ssklower for (p = &inm->inm_ia->ia_multiaddrs; 694*54716Ssklower *p != inm; 695*54716Ssklower p = &(*p)->inm_next) 696*54716Ssklower continue; 697*54716Ssklower *p = (*p)->inm_next; 698*54716Ssklower /* 699*54716Ssklower * Notify the network driver to update its multicast reception 700*54716Ssklower * filter. 701*54716Ssklower */ 702*54716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 703*54716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = 704*54716Ssklower inm->inm_addr; 705*54716Ssklower (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 706*54716Ssklower (caddr_t)&ifr); 707*54716Ssklower free(inm, M_IPMADDR); 708*54716Ssklower } 709*54716Ssklower splx(s); 710*54716Ssklower } 7117159Ssam #endif 712*54716Ssklower #endif 713