123175Smckusick /*
263218Sbostic * Copyright (c) 1982, 1986, 1991, 1993
363218Sbostic * The Regents of the University of California. All rights reserved.
423175Smckusick *
544472Sbostic * %sccs.include.redist.c%
632787Sbostic *
7*68170Scgd * @(#)in.c 8.4 (Berkeley) 01/09/95
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
2056531Sbostic #include <netinet/in_systm.h>
2156531Sbostic #include <netinet/in.h>
2256531Sbostic #include <netinet/in_var.h>
2361335Sbostic #include <netinet/if_ether.h>
2456531Sbostic
257159Ssam #ifdef INET
267159Ssam /*
278595Sroot * Return the network number from an internet address.
287159Ssam */
2924805Skarels u_long
in_netof(in)307159Ssam in_netof(in)
317159Ssam struct in_addr in;
327159Ssam {
338937Sroot register u_long i = ntohl(in.s_addr);
3418377Skarels register u_long net;
3518377Skarels register struct in_ifaddr *ia;
367159Ssam
3718377Skarels if (IN_CLASSA(i))
3818377Skarels net = i & IN_CLASSA_NET;
3918377Skarels else if (IN_CLASSB(i))
4018377Skarels net = i & IN_CLASSB_NET;
4131392Skarels else if (IN_CLASSC(i))
4231392Skarels net = i & IN_CLASSC_NET;
4354716Ssklower else if (IN_CLASSD(i))
4454716Ssklower net = i & IN_CLASSD_NET;
4518377Skarels else
4631392Skarels return (0);
4716413Skarels
4816413Skarels /*
4918377Skarels * Check whether network is a subnet;
5016413Skarels * if so, return subnet number.
5116413Skarels */
5218377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next)
5324805Skarels if (net == ia->ia_net)
5418377Skarels return (i & ia->ia_subnetmask);
5516413Skarels return (net);
567159Ssam }
577159Ssam
5826381Skarels #ifndef SUBNETSARELOCAL
5926381Skarels #define SUBNETSARELOCAL 1
6026381Skarels #endif
6126381Skarels int subnetsarelocal = SUBNETSARELOCAL;
6216377Skarels /*
6318377Skarels * Return 1 if an internet address is for a ``local'' host
6426381Skarels * (one to which we have a connection). If subnetsarelocal
6526381Skarels * is true, this includes other subnets of the local net.
6626381Skarels * Otherwise, it includes only the directly-connected (sub)nets.
6717271Skarels */
6817271Skarels in_localaddr(in)
6917271Skarels struct in_addr in;
7017271Skarels {
7117271Skarels register u_long i = ntohl(in.s_addr);
7218377Skarels register struct in_ifaddr *ia;
7317271Skarels
7430697Skarels if (subnetsarelocal) {
7530697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next)
7630697Skarels if ((i & ia->ia_netmask) == ia->ia_net)
7730697Skarels return (1);
7830697Skarels } else {
7930697Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next)
8030697Skarels if ((i & ia->ia_subnetmask) == ia->ia_subnet)
8130697Skarels return (1);
8230697Skarels }
8318377Skarels return (0);
8418377Skarels }
8518377Skarels
8631392Skarels /*
8731392Skarels * Determine whether an IP address is in a reserved set of addresses
8831392Skarels * that may not be forwarded, or whether datagrams to that destination
8931392Skarels * may be forwarded.
9031392Skarels */
9131392Skarels in_canforward(in)
9231392Skarels struct in_addr in;
9331392Skarels {
9431392Skarels register u_long i = ntohl(in.s_addr);
9531392Skarels register u_long net;
9631392Skarels
9758998Ssklower if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
9831392Skarels return (0);
9931392Skarels if (IN_CLASSA(i)) {
10031392Skarels net = i & IN_CLASSA_NET;
10157938Ssklower if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
10231392Skarels return (0);
10331392Skarels }
10431392Skarels return (1);
10531392Skarels }
10631392Skarels
10758998Ssklower /*
10858998Ssklower * Trim a mask in a sockaddr
10958998Ssklower */
11058998Ssklower void
in_socktrim(ap)11158998Ssklower in_socktrim(ap)
11258998Ssklower struct sockaddr_in *ap;
11358998Ssklower {
11458998Ssklower register char *cplim = (char *) &ap->sin_addr;
11558998Ssklower register char *cp = (char *) (&ap->sin_addr + 1);
11658998Ssklower
11758998Ssklower ap->sin_len = 0;
11867890Ssklower while (--cp >= cplim)
11958998Ssklower if (*cp) {
12058998Ssklower (ap)->sin_len = cp - (char *) (ap) + 1;
12158998Ssklower break;
12258998Ssklower }
12358998Ssklower }
12458998Ssklower
12524805Skarels int in_interfaces; /* number of external internet interfaces */
12624805Skarels extern struct ifnet loif;
12724805Skarels
12818377Skarels /*
12918377Skarels * Generic internet control operations (ioctl's).
13018377Skarels * Ifp is 0 if not an interface-specific ioctl.
13118377Skarels */
13224805Skarels /* ARGSUSED */
13318377Skarels in_control(so, cmd, data, ifp)
13418377Skarels struct socket *so;
135*68170Scgd u_long cmd;
13618377Skarels caddr_t data;
13718377Skarels register struct ifnet *ifp;
13818377Skarels {
13918377Skarels register struct ifreq *ifr = (struct ifreq *)data;
14018377Skarels register struct in_ifaddr *ia = 0;
14137471Ssklower register struct ifaddr *ifa;
14237471Ssklower struct in_ifaddr *oia;
14337471Ssklower struct in_aliasreq *ifra = (struct in_aliasreq *)data;
14437471Ssklower struct sockaddr_in oldaddr;
14537471Ssklower int error, hostIsNew, maskIsNew;
14637471Ssklower u_long i;
14718377Skarels
14818377Skarels /*
14918377Skarels * Find address for this interface, if it exists.
15018377Skarels */
15118377Skarels if (ifp)
15218377Skarels for (ia = in_ifaddr; ia; ia = ia->ia_next)
15318377Skarels if (ia->ia_ifp == ifp)
15418377Skarels break;
15518377Skarels
15618377Skarels switch (cmd) {
15718377Skarels
15837471Ssklower case SIOCAIFADDR:
15937471Ssklower case SIOCDIFADDR:
16037471Ssklower if (ifra->ifra_addr.sin_family == AF_INET)
16137471Ssklower for (oia = ia; ia; ia = ia->ia_next) {
16237471Ssklower if (ia->ia_ifp == ifp &&
16337471Ssklower ia->ia_addr.sin_addr.s_addr ==
16437471Ssklower ifra->ifra_addr.sin_addr.s_addr)
16537471Ssklower break;
16637471Ssklower }
16737471Ssklower if (cmd == SIOCDIFADDR && ia == 0)
16837471Ssklower return (EADDRNOTAVAIL);
16937471Ssklower /* FALLTHROUGH */
17018377Skarels case SIOCSIFADDR:
17118377Skarels case SIOCSIFNETMASK:
17226456Skarels case SIOCSIFDSTADDR:
17348464Skarels if ((so->so_state & SS_PRIV) == 0)
17448464Skarels return (EPERM);
17518377Skarels
17618377Skarels if (ifp == 0)
17718377Skarels panic("in_control");
17818377Skarels if (ia == (struct in_ifaddr *)0) {
17952028Ssklower oia = (struct in_ifaddr *)
18052028Ssklower malloc(sizeof *oia, M_IFADDR, M_WAITOK);
18152028Ssklower if (oia == (struct in_ifaddr *)NULL)
18218377Skarels return (ENOBUFS);
18352028Ssklower bzero((caddr_t)oia, sizeof *oia);
18418377Skarels if (ia = in_ifaddr) {
18518377Skarels for ( ; ia->ia_next; ia = ia->ia_next)
18652915Storek continue;
18752028Ssklower ia->ia_next = oia;
18818377Skarels } else
18952028Ssklower in_ifaddr = oia;
19052028Ssklower ia = oia;
19118377Skarels if (ifa = ifp->if_addrlist) {
19218377Skarels for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
19352915Storek continue;
19418377Skarels ifa->ifa_next = (struct ifaddr *) ia;
19518377Skarels } else
19618377Skarels ifp->if_addrlist = (struct ifaddr *) ia;
19737471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
19837471Ssklower ia->ia_ifa.ifa_dstaddr
19937471Ssklower = (struct sockaddr *)&ia->ia_dstaddr;
20037471Ssklower ia->ia_ifa.ifa_netmask
20137471Ssklower = (struct sockaddr *)&ia->ia_sockmask;
20237471Ssklower ia->ia_sockmask.sin_len = 8;
20337471Ssklower if (ifp->if_flags & IFF_BROADCAST) {
20437471Ssklower ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
20537471Ssklower ia->ia_broadaddr.sin_family = AF_INET;
20637471Ssklower }
20718377Skarels ia->ia_ifp = ifp;
20824805Skarels if (ifp != &loif)
20924805Skarels in_interfaces++;
21017271Skarels }
21118377Skarels break;
21226317Skarels
21326317Skarels case SIOCSIFBRDADDR:
21448464Skarels if ((so->so_state & SS_PRIV) == 0)
21548464Skarels return (EPERM);
21626317Skarels /* FALLTHROUGH */
21726317Skarels
21839183Ssklower case SIOCGIFADDR:
21939183Ssklower case SIOCGIFNETMASK:
22039183Ssklower case SIOCGIFDSTADDR:
22139183Ssklower case SIOCGIFBRDADDR:
22226317Skarels if (ia == (struct in_ifaddr *)0)
22326317Skarels return (EADDRNOTAVAIL);
22426317Skarels break;
22517271Skarels }
22618377Skarels switch (cmd) {
22718377Skarels
22818377Skarels case SIOCGIFADDR:
22937471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
23018377Skarels break;
23118377Skarels
23218377Skarels case SIOCGIFBRDADDR:
23318377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0)
23418377Skarels return (EINVAL);
23537471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
23618377Skarels break;
23718377Skarels
23818377Skarels case SIOCGIFDSTADDR:
23918377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
24018377Skarels return (EINVAL);
24137471Ssklower *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
24218377Skarels break;
24318377Skarels
24418377Skarels case SIOCGIFNETMASK:
24537471Ssklower *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
24618377Skarels break;
24718377Skarels
24818377Skarels case SIOCSIFDSTADDR:
24918377Skarels if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
25018377Skarels return (EINVAL);
25127066Skarels oldaddr = ia->ia_dstaddr;
25237471Ssklower ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
25352619Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
25452619Ssklower (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
25527066Skarels ia->ia_dstaddr = oldaddr;
25618377Skarels return (error);
25727066Skarels }
25827066Skarels if (ia->ia_flags & IFA_ROUTE) {
25937471Ssklower ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
26037471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
26145454Ssklower ia->ia_ifa.ifa_dstaddr =
26245454Ssklower (struct sockaddr *)&ia->ia_dstaddr;
26337471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
26427066Skarels }
26518377Skarels break;
26618377Skarels
26718377Skarels case SIOCSIFBRDADDR:
26818377Skarels if ((ifp->if_flags & IFF_BROADCAST) == 0)
26918377Skarels return (EINVAL);
27037471Ssklower ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
27118377Skarels break;
27218377Skarels
27318377Skarels case SIOCSIFADDR:
27434500Skarels return (in_ifinit(ifp, ia,
27537471Ssklower (struct sockaddr_in *) &ifr->ifr_addr, 1));
27618377Skarels
27718377Skarels case SIOCSIFNETMASK:
27837471Ssklower i = ifra->ifra_addr.sin_addr.s_addr;
27937471Ssklower ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
28018377Skarels break;
28118377Skarels
28237471Ssklower case SIOCAIFADDR:
28344368Skarels maskIsNew = 0;
28444368Skarels hostIsNew = 1;
28544368Skarels error = 0;
28637471Ssklower if (ia->ia_addr.sin_family == AF_INET) {
28737471Ssklower if (ifra->ifra_addr.sin_len == 0) {
28837471Ssklower ifra->ifra_addr = ia->ia_addr;
28937471Ssklower hostIsNew = 0;
29037471Ssklower } else if (ifra->ifra_addr.sin_addr.s_addr ==
29137471Ssklower ia->ia_addr.sin_addr.s_addr)
29237471Ssklower hostIsNew = 0;
29337471Ssklower }
29437471Ssklower if (ifra->ifra_mask.sin_len) {
29537471Ssklower in_ifscrub(ifp, ia);
29637471Ssklower ia->ia_sockmask = ifra->ifra_mask;
29737471Ssklower ia->ia_subnetmask =
29844368Skarels ntohl(ia->ia_sockmask.sin_addr.s_addr);
29937471Ssklower maskIsNew = 1;
30037471Ssklower }
30137471Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) &&
30237471Ssklower (ifra->ifra_dstaddr.sin_family == AF_INET)) {
30337471Ssklower in_ifscrub(ifp, ia);
30437471Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr;
30537471Ssklower maskIsNew = 1; /* We lie; but the effect's the same */
30637471Ssklower }
30737471Ssklower if (ifra->ifra_addr.sin_family == AF_INET &&
30844368Skarels (hostIsNew || maskIsNew))
30937471Ssklower error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
31037471Ssklower if ((ifp->if_flags & IFF_BROADCAST) &&
31137471Ssklower (ifra->ifra_broadaddr.sin_family == AF_INET))
31237471Ssklower ia->ia_broadaddr = ifra->ifra_broadaddr;
31337471Ssklower return (error);
31437471Ssklower
31537471Ssklower case SIOCDIFADDR:
31637471Ssklower in_ifscrub(ifp, ia);
31737471Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
31837471Ssklower ifp->if_addrlist = ifa->ifa_next;
31937471Ssklower else {
32037471Ssklower while (ifa->ifa_next &&
32137471Ssklower (ifa->ifa_next != (struct ifaddr *)ia))
32237471Ssklower ifa = ifa->ifa_next;
32337471Ssklower if (ifa->ifa_next)
32444368Skarels ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
32537471Ssklower else
32637471Ssklower printf("Couldn't unlink inifaddr from ifp\n");
32737471Ssklower }
32837471Ssklower oia = ia;
32944368Skarels if (oia == (ia = in_ifaddr))
33037471Ssklower in_ifaddr = ia->ia_next;
33144368Skarels else {
33244368Skarels while (ia->ia_next && (ia->ia_next != oia))
33337471Ssklower ia = ia->ia_next;
33437471Ssklower if (ia->ia_next)
33544368Skarels ia->ia_next = oia->ia_next;
33637471Ssklower else
33737471Ssklower printf("Didn't unlink inifadr from list\n");
33837471Ssklower }
33952028Ssklower IFAFREE((&oia->ia_ifa));
34037471Ssklower break;
34137471Ssklower
34218377Skarels default:
34318377Skarels if (ifp == 0 || ifp->if_ioctl == 0)
34418377Skarels return (EOPNOTSUPP);
34518377Skarels return ((*ifp->if_ioctl)(ifp, cmd, data));
34618377Skarels }
34717271Skarels return (0);
34817271Skarels }
34917271Skarels
35017271Skarels /*
35137471Ssklower * Delete any existing route for an interface.
35237471Ssklower */
35361335Sbostic void
in_ifscrub(ifp,ia)35437471Ssklower in_ifscrub(ifp, ia)
35537471Ssklower register struct ifnet *ifp;
35637471Ssklower register struct in_ifaddr *ia;
35737471Ssklower {
35837471Ssklower
35937471Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0)
36037471Ssklower return;
36137471Ssklower if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
36237471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
36337471Ssklower else
36437471Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
36537471Ssklower ia->ia_flags &= ~IFA_ROUTE;
36637471Ssklower }
36737471Ssklower
36837471Ssklower /*
36918377Skarels * Initialize an interface's internet address
37018377Skarels * and routing table entry.
3717159Ssam */
in_ifinit(ifp,ia,sin,scrub)37237471Ssklower in_ifinit(ifp, ia, sin, scrub)
3737159Ssam register struct ifnet *ifp;
37418377Skarels register struct in_ifaddr *ia;
37518377Skarels struct sockaddr_in *sin;
37652274Storek int scrub;
3777159Ssam {
37818377Skarels register u_long i = ntohl(sin->sin_addr.s_addr);
37937471Ssklower struct sockaddr_in oldaddr;
38054716Ssklower int s = splimp(), flags = RTF_UP, error, ether_output();
3817159Ssam
38227066Skarels oldaddr = ia->ia_addr;
38337471Ssklower ia->ia_addr = *sin;
38418377Skarels /*
38526317Skarels * Give the interface a chance to initialize
38626317Skarels * if this is its first address,
38726317Skarels * and to validate the address if necessary.
38826317Skarels */
38952274Storek if (ifp->if_ioctl &&
39052274Storek (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
39126317Skarels splx(s);
39227066Skarels ia->ia_addr = oldaddr;
39326317Skarels return (error);
39426317Skarels }
39550134Ssklower if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
39650134Ssklower ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
39750134Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING;
39850134Ssklower }
39945454Ssklower splx(s);
40037471Ssklower if (scrub) {
40137471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
40237471Ssklower in_ifscrub(ifp, ia);
40337471Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
40418377Skarels }
40518377Skarels if (IN_CLASSA(i))
40618377Skarels ia->ia_netmask = IN_CLASSA_NET;
40718377Skarels else if (IN_CLASSB(i))
40818377Skarels ia->ia_netmask = IN_CLASSB_NET;
40918377Skarels else
41018377Skarels ia->ia_netmask = IN_CLASSC_NET;
41118377Skarels /*
41262865Ssklower * The subnet mask usually includes at least the standard network part,
41362865Ssklower * but may may be smaller in the case of supernetting.
41462865Ssklower * If it is set, we believe it.
41518377Skarels */
41662865Ssklower if (ia->ia_subnetmask == 0) {
41762865Ssklower ia->ia_subnetmask = ia->ia_netmask;
41862865Ssklower ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
41962865Ssklower } else
42062865Ssklower ia->ia_netmask &= ia->ia_subnetmask;
42162865Ssklower ia->ia_net = i & ia->ia_netmask;
42218377Skarels ia->ia_subnet = i & ia->ia_subnetmask;
42358998Ssklower in_socktrim(&ia->ia_sockmask);
42445454Ssklower /*
42545454Ssklower * Add route for the network.
42645454Ssklower */
42752617Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric;
42818377Skarels if (ifp->if_flags & IFF_BROADCAST) {
42958998Ssklower ia->ia_broadaddr.sin_addr.s_addr =
43058998Ssklower htonl(ia->ia_subnet | ~ia->ia_subnetmask);
43125195Skarels ia->ia_netbroadcast.s_addr =
43258998Ssklower htonl(ia->ia_net | ~ ia->ia_netmask);
43345454Ssklower } else if (ifp->if_flags & IFF_LOOPBACK) {
43437471Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
43545454Ssklower flags |= RTF_HOST;
43645454Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT) {
43745454Ssklower if (ia->ia_dstaddr.sin_family != AF_INET)
43845454Ssklower return (0);
43945454Ssklower flags |= RTF_HOST;
44027066Skarels }
44145454Ssklower if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
44245454Ssklower ia->ia_flags |= IFA_ROUTE;
44354716Ssklower /*
44454716Ssklower * If the interface supports multicast, join the "all hosts"
44554716Ssklower * multicast group on that interface.
44654716Ssklower */
44754716Ssklower if (ifp->if_flags & IFF_MULTICAST) {
44854716Ssklower struct in_addr addr;
44954716Ssklower
45054716Ssklower addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
45154716Ssklower in_addmulti(&addr, ifp);
45254716Ssklower }
45345454Ssklower return (error);
4547159Ssam }
45518377Skarels
45618377Skarels
45718377Skarels /*
45830523Skarels * Return 1 if the address might be a local broadcast address.
45918377Skarels */
46058998Ssklower in_broadcast(in, ifp)
46118377Skarels struct in_addr in;
46258998Ssklower struct ifnet *ifp;
46318377Skarels {
46458998Ssklower register struct ifaddr *ifa;
46530523Skarels u_long t;
46618377Skarels
46758998Ssklower if (in.s_addr == INADDR_BROADCAST ||
46858998Ssklower in.s_addr == INADDR_ANY)
46958998Ssklower return 1;
47058998Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0)
47158998Ssklower return 0;
47258998Ssklower t = ntohl(in.s_addr);
47318377Skarels /*
47418377Skarels * Look through the list of addresses for a match
47518377Skarels * with a broadcast address.
47618377Skarels */
47758998Ssklower #define ia ((struct in_ifaddr *)ifa)
47858998Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
47958998Ssklower if (ifa->ifa_addr->sa_family == AF_INET &&
48058998Ssklower (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
48158998Ssklower in.s_addr == ia->ia_netbroadcast.s_addr ||
48258998Ssklower /*
48358998Ssklower * Check for old-style (host 0) broadcast.
48458998Ssklower */
48558998Ssklower t == ia->ia_subnet || t == ia->ia_net))
48658998Ssklower return 1;
48761335Sbostic return (0);
48858998Ssklower #undef ia
48918377Skarels }
49054716Ssklower /*
49154716Ssklower * Add an address to the list of IP multicast addresses for a given interface.
49254716Ssklower */
49354716Ssklower struct in_multi *
in_addmulti(ap,ifp)49454716Ssklower in_addmulti(ap, ifp)
49554716Ssklower register struct in_addr *ap;
49654716Ssklower register struct ifnet *ifp;
49754716Ssklower {
49854716Ssklower register struct in_multi *inm;
49954716Ssklower struct ifreq ifr;
50054716Ssklower struct in_ifaddr *ia;
50154716Ssklower int s = splnet();
50254716Ssklower
50354716Ssklower /*
50454716Ssklower * See if address already in list.
50554716Ssklower */
50654716Ssklower IN_LOOKUP_MULTI(*ap, ifp, inm);
50754716Ssklower if (inm != NULL) {
50854716Ssklower /*
50954716Ssklower * Found it; just increment the reference count.
51054716Ssklower */
51154716Ssklower ++inm->inm_refcount;
51254716Ssklower }
51354716Ssklower else {
51454716Ssklower /*
51554716Ssklower * New address; allocate a new multicast record
51654716Ssklower * and link it into the interface's multicast list.
51754716Ssklower */
51854716Ssklower inm = (struct in_multi *)malloc(sizeof(*inm),
51954716Ssklower M_IPMADDR, M_NOWAIT);
52054716Ssklower if (inm == NULL) {
52154716Ssklower splx(s);
52254716Ssklower return (NULL);
52354716Ssklower }
52454716Ssklower inm->inm_addr = *ap;
52554716Ssklower inm->inm_ifp = ifp;
52654716Ssklower inm->inm_refcount = 1;
52754716Ssklower IFP_TO_IA(ifp, ia);
52854716Ssklower if (ia == NULL) {
52954716Ssklower free(inm, M_IPMADDR);
53054716Ssklower splx(s);
53154716Ssklower return (NULL);
53254716Ssklower }
53354716Ssklower inm->inm_ia = ia;
53458413Ssklower inm->inm_next = ia->ia_multiaddrs;
53558413Ssklower ia->ia_multiaddrs = inm;
53654716Ssklower /*
53754716Ssklower * Ask the network driver to update its multicast reception
53854716Ssklower * filter appropriately for the new address.
53954716Ssklower */
54054716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
54154716Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
54258413Ssklower if ((ifp->if_ioctl == NULL) ||
54358413Ssklower (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
54458413Ssklower ia->ia_multiaddrs = inm->inm_next;
54554716Ssklower free(inm, M_IPMADDR);
54654716Ssklower splx(s);
54754716Ssklower return (NULL);
54854716Ssklower }
54954716Ssklower /*
55054716Ssklower * Let IGMP know that we have joined a new IP multicast group.
55154716Ssklower */
55254716Ssklower igmp_joingroup(inm);
55354716Ssklower }
55454716Ssklower splx(s);
55554716Ssklower return (inm);
55654716Ssklower }
55754716Ssklower
55854716Ssklower /*
55954716Ssklower * Delete a multicast address record.
56054716Ssklower */
56154716Ssklower int
in_delmulti(inm)56254716Ssklower in_delmulti(inm)
56354716Ssklower register struct in_multi *inm;
56454716Ssklower {
56554716Ssklower register struct in_multi **p;
56654716Ssklower struct ifreq ifr;
56754716Ssklower int s = splnet();
56854716Ssklower
56954716Ssklower if (--inm->inm_refcount == 0) {
57054716Ssklower /*
57154716Ssklower * No remaining claims to this record; let IGMP know that
57254716Ssklower * we are leaving the multicast group.
57354716Ssklower */
57454716Ssklower igmp_leavegroup(inm);
57554716Ssklower /*
57654716Ssklower * Unlink from list.
57754716Ssklower */
57854716Ssklower for (p = &inm->inm_ia->ia_multiaddrs;
57954716Ssklower *p != inm;
58054716Ssklower p = &(*p)->inm_next)
58154716Ssklower continue;
58254716Ssklower *p = (*p)->inm_next;
58354716Ssklower /*
58454716Ssklower * Notify the network driver to update its multicast reception
58554716Ssklower * filter.
58654716Ssklower */
58754716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
58854716Ssklower ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
58954716Ssklower inm->inm_addr;
59054716Ssklower (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
59154716Ssklower (caddr_t)&ifr);
59254716Ssklower free(inm, M_IPMADDR);
59354716Ssklower }
59454716Ssklower splx(s);
59554716Ssklower }
5967159Ssam #endif
597