4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sys / netinet / in.c
CommitLineData
8ae0e4b4 1/*
e7a3707f
KB
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
8ae0e4b4 4 *
dbf0c423 5 * %sccs.include.redist.c%
2b6b6284 6 *
e7a3707f 7 * @(#)in.c 8.1 (Berkeley) %G%
8ae0e4b4 8 */
8473bbab 9
5548a02f
KB
10#include <sys/param.h>
11#include <sys/ioctl.h>
12#include <sys/errno.h>
13#include <sys/malloc.h>
14#include <sys/socket.h>
15#include <sys/socketvar.h>
16
17#include <net/if.h>
18#include <net/route.h>
19#include <net/af.h>
20
21#include <netinet/in_systm.h>
22#include <netinet/in.h>
23#include <netinet/in_var.h>
c46785cb 24#include <netinet/if_ether.h>
8473bbab
SL
25
26#ifdef INET
8473bbab 27/*
a8d3bf7f 28 * Return the network number from an internet address.
8473bbab 29 */
2dd77a90 30u_long
8473bbab
SL
31in_netof(in)
32 struct in_addr in;
33{
2c48b3f8 34 register u_long i = ntohl(in.s_addr);
65b95551
MK
35 register u_long net;
36 register struct in_ifaddr *ia;
8473bbab 37
65b95551
MK
38 if (IN_CLASSA(i))
39 net = i & IN_CLASSA_NET;
40 else if (IN_CLASSB(i))
41 net = i & IN_CLASSB_NET;
b4f9e9c7 42 else if (IN_CLASSC(i))
65b95551 43 net = i & IN_CLASSC_NET;
d6fa15c2
KS
44 else if (IN_CLASSD(i))
45 net = i & IN_CLASSD_NET;
b4f9e9c7
MK
46 else
47 return (0);
083b2954
MK
48
49 /*
65b95551 50 * Check whether network is a subnet;
083b2954
MK
51 * if so, return subnet number.
52 */
65b95551 53 for (ia = in_ifaddr; ia; ia = ia->ia_next)
2dd77a90 54 if (net == ia->ia_net)
65b95551 55 return (i & ia->ia_subnetmask);
083b2954 56 return (net);
8473bbab
SL
57}
58
8011f5df
MK
59#ifndef SUBNETSARELOCAL
60#define SUBNETSARELOCAL 1
61#endif
62int subnetsarelocal = SUBNETSARELOCAL;
99578149 63/*
65b95551 64 * Return 1 if an internet address is for a ``local'' host
8011f5df
MK
65 * (one to which we have a connection). If subnetsarelocal
66 * is true, this includes other subnets of the local net.
67 * Otherwise, it includes only the directly-connected (sub)nets.
99578149
MK
68 */
69in_localaddr(in)
70 struct in_addr in;
71{
72 register u_long i = ntohl(in.s_addr);
65b95551 73 register struct in_ifaddr *ia;
99578149 74
16cae8d5
MK
75 if (subnetsarelocal) {
76 for (ia = in_ifaddr; ia; ia = ia->ia_next)
77 if ((i & ia->ia_netmask) == ia->ia_net)
78 return (1);
79 } else {
80 for (ia = in_ifaddr; ia; ia = ia->ia_next)
81 if ((i & ia->ia_subnetmask) == ia->ia_subnet)
82 return (1);
83 }
65b95551
MK
84 return (0);
85}
86
b4f9e9c7
MK
87/*
88 * Determine whether an IP address is in a reserved set of addresses
89 * that may not be forwarded, or whether datagrams to that destination
90 * may be forwarded.
91 */
92in_canforward(in)
93 struct in_addr in;
94{
95 register u_long i = ntohl(in.s_addr);
96 register u_long net;
97
09ed489e 98 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
b4f9e9c7
MK
99 return (0);
100 if (IN_CLASSA(i)) {
101 net = i & IN_CLASSA_NET;
9a306efe 102 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
b4f9e9c7
MK
103 return (0);
104 }
105 return (1);
106}
107
09ed489e
KS
108/*
109 * Trim a mask in a sockaddr
110 */
111void
112in_socktrim(ap)
113struct sockaddr_in *ap;
114{
115 register char *cplim = (char *) &ap->sin_addr;
116 register char *cp = (char *) (&ap->sin_addr + 1);
117
118 ap->sin_len = 0;
119 while (--cp > cplim)
120 if (*cp) {
121 (ap)->sin_len = cp - (char *) (ap) + 1;
122 break;
123 }
124}
125
2dd77a90
MK
126int in_interfaces; /* number of external internet interfaces */
127extern struct ifnet loif;
128
65b95551
MK
129/*
130 * Generic internet control operations (ioctl's).
131 * Ifp is 0 if not an interface-specific ioctl.
132 */
2dd77a90 133/* ARGSUSED */
65b95551
MK
134in_control(so, cmd, data, ifp)
135 struct socket *so;
136 int cmd;
137 caddr_t data;
138 register struct ifnet *ifp;
139{
140 register struct ifreq *ifr = (struct ifreq *)data;
141 register struct in_ifaddr *ia = 0;
b4dc7708
KS
142 register struct ifaddr *ifa;
143 struct in_ifaddr *oia;
144 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
b4dc7708
KS
145 struct sockaddr_in oldaddr;
146 int error, hostIsNew, maskIsNew;
147 u_long i;
65b95551
MK
148
149 /*
150 * Find address for this interface, if it exists.
151 */
152 if (ifp)
153 for (ia = in_ifaddr; ia; ia = ia->ia_next)
154 if (ia->ia_ifp == ifp)
155 break;
156
157 switch (cmd) {
158
b4dc7708
KS
159 case SIOCAIFADDR:
160 case SIOCDIFADDR:
161 if (ifra->ifra_addr.sin_family == AF_INET)
162 for (oia = ia; ia; ia = ia->ia_next) {
163 if (ia->ia_ifp == ifp &&
164 ia->ia_addr.sin_addr.s_addr ==
165 ifra->ifra_addr.sin_addr.s_addr)
166 break;
167 }
168 if (cmd == SIOCDIFADDR && ia == 0)
169 return (EADDRNOTAVAIL);
170 /* FALLTHROUGH */
65b95551 171 case SIOCSIFADDR:
65b95551 172 case SIOCSIFNETMASK:
0977715b 173 case SIOCSIFDSTADDR:
6aa944c6
MK
174 if ((so->so_state & SS_PRIV) == 0)
175 return (EPERM);
65b95551
MK
176
177 if (ifp == 0)
178 panic("in_control");
179 if (ia == (struct in_ifaddr *)0) {
b965365f
KS
180 oia = (struct in_ifaddr *)
181 malloc(sizeof *oia, M_IFADDR, M_WAITOK);
182 if (oia == (struct in_ifaddr *)NULL)
65b95551 183 return (ENOBUFS);
b965365f 184 bzero((caddr_t)oia, sizeof *oia);
65b95551
MK
185 if (ia = in_ifaddr) {
186 for ( ; ia->ia_next; ia = ia->ia_next)
a6e3920d 187 continue;
b965365f 188 ia->ia_next = oia;
65b95551 189 } else
b965365f
KS
190 in_ifaddr = oia;
191 ia = oia;
65b95551
MK
192 if (ifa = ifp->if_addrlist) {
193 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
a6e3920d 194 continue;
65b95551
MK
195 ifa->ifa_next = (struct ifaddr *) ia;
196 } else
197 ifp->if_addrlist = (struct ifaddr *) ia;
b4dc7708
KS
198 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
199 ia->ia_ifa.ifa_dstaddr
200 = (struct sockaddr *)&ia->ia_dstaddr;
201 ia->ia_ifa.ifa_netmask
202 = (struct sockaddr *)&ia->ia_sockmask;
203 ia->ia_sockmask.sin_len = 8;
204 if (ifp->if_flags & IFF_BROADCAST) {
205 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
206 ia->ia_broadaddr.sin_family = AF_INET;
207 }
65b95551 208 ia->ia_ifp = ifp;
2dd77a90
MK
209 if (ifp != &loif)
210 in_interfaces++;
99578149 211 }
65b95551 212 break;
b9ce6c7a
MK
213
214 case SIOCSIFBRDADDR:
6aa944c6
MK
215 if ((so->so_state & SS_PRIV) == 0)
216 return (EPERM);
b9ce6c7a
MK
217 /* FALLTHROUGH */
218
a48489e5
KS
219 case SIOCGIFADDR:
220 case SIOCGIFNETMASK:
221 case SIOCGIFDSTADDR:
222 case SIOCGIFBRDADDR:
b9ce6c7a
MK
223 if (ia == (struct in_ifaddr *)0)
224 return (EADDRNOTAVAIL);
225 break;
65b95551 226 }
65b95551
MK
227 switch (cmd) {
228
229 case SIOCGIFADDR:
b4dc7708 230 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
65b95551
MK
231 break;
232
233 case SIOCGIFBRDADDR:
234 if ((ifp->if_flags & IFF_BROADCAST) == 0)
235 return (EINVAL);
b4dc7708 236 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
65b95551
MK
237 break;
238
239 case SIOCGIFDSTADDR:
240 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
241 return (EINVAL);
b4dc7708 242 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
65b95551
MK
243 break;
244
245 case SIOCGIFNETMASK:
b4dc7708 246 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
65b95551
MK
247 break;
248
249 case SIOCSIFDSTADDR:
250 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
251 return (EINVAL);
2c83bd95 252 oldaddr = ia->ia_dstaddr;
b4dc7708 253 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
4138c016
KS
254 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
255 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
2c83bd95 256 ia->ia_dstaddr = oldaddr;
65b95551 257 return (error);
2c83bd95
MK
258 }
259 if (ia->ia_flags & IFA_ROUTE) {
b4dc7708
KS
260 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
261 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
7189a987
KS
262 ia->ia_ifa.ifa_dstaddr =
263 (struct sockaddr *)&ia->ia_dstaddr;
b4dc7708 264 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
2c83bd95 265 }
65b95551
MK
266 break;
267
268 case SIOCSIFBRDADDR:
269 if ((ifp->if_flags & IFF_BROADCAST) == 0)
270 return (EINVAL);
b4dc7708 271 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
65b95551
MK
272 break;
273
274 case SIOCSIFADDR:
9340d736 275 return (in_ifinit(ifp, ia,
b4dc7708 276 (struct sockaddr_in *) &ifr->ifr_addr, 1));
65b95551
MK
277
278 case SIOCSIFNETMASK:
b4dc7708
KS
279 i = ifra->ifra_addr.sin_addr.s_addr;
280 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
281 break;
282
283 case SIOCAIFADDR:
36a9a6d3
MK
284 maskIsNew = 0;
285 hostIsNew = 1;
286 error = 0;
b4dc7708
KS
287 if (ia->ia_addr.sin_family == AF_INET) {
288 if (ifra->ifra_addr.sin_len == 0) {
289 ifra->ifra_addr = ia->ia_addr;
290 hostIsNew = 0;
291 } else if (ifra->ifra_addr.sin_addr.s_addr ==
292 ia->ia_addr.sin_addr.s_addr)
293 hostIsNew = 0;
294 }
295 if (ifra->ifra_mask.sin_len) {
296 in_ifscrub(ifp, ia);
297 ia->ia_sockmask = ifra->ifra_mask;
298 ia->ia_subnetmask =
36a9a6d3 299 ntohl(ia->ia_sockmask.sin_addr.s_addr);
b4dc7708
KS
300 maskIsNew = 1;
301 }
302 if ((ifp->if_flags & IFF_POINTOPOINT) &&
303 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
304 in_ifscrub(ifp, ia);
305 ia->ia_dstaddr = ifra->ifra_dstaddr;
306 maskIsNew = 1; /* We lie; but the effect's the same */
307 }
308 if (ifra->ifra_addr.sin_family == AF_INET &&
36a9a6d3 309 (hostIsNew || maskIsNew))
b4dc7708
KS
310 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
311 if ((ifp->if_flags & IFF_BROADCAST) &&
312 (ifra->ifra_broadaddr.sin_family == AF_INET))
313 ia->ia_broadaddr = ifra->ifra_broadaddr;
314 return (error);
315
316 case SIOCDIFADDR:
317 in_ifscrub(ifp, ia);
318 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
319 ifp->if_addrlist = ifa->ifa_next;
320 else {
321 while (ifa->ifa_next &&
322 (ifa->ifa_next != (struct ifaddr *)ia))
323 ifa = ifa->ifa_next;
324 if (ifa->ifa_next)
36a9a6d3 325 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
b4dc7708
KS
326 else
327 printf("Couldn't unlink inifaddr from ifp\n");
328 }
329 oia = ia;
36a9a6d3 330 if (oia == (ia = in_ifaddr))
b4dc7708 331 in_ifaddr = ia->ia_next;
36a9a6d3
MK
332 else {
333 while (ia->ia_next && (ia->ia_next != oia))
b4dc7708 334 ia = ia->ia_next;
b4dc7708 335 if (ia->ia_next)
36a9a6d3 336 ia->ia_next = oia->ia_next;
b4dc7708
KS
337 else
338 printf("Didn't unlink inifadr from list\n");
339 }
b965365f 340 IFAFREE((&oia->ia_ifa));
65b95551
MK
341 break;
342
343 default:
344 if (ifp == 0 || ifp->if_ioctl == 0)
345 return (EOPNOTSUPP);
346 return ((*ifp->if_ioctl)(ifp, cmd, data));
99578149
MK
347 }
348 return (0);
349}
350
b4dc7708
KS
351/*
352 * Delete any existing route for an interface.
353 */
c46785cb 354void
b4dc7708
KS
355in_ifscrub(ifp, ia)
356 register struct ifnet *ifp;
357 register struct in_ifaddr *ia;
358{
359
360 if ((ia->ia_flags & IFA_ROUTE) == 0)
361 return;
362 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
363 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
364 else
365 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
366 ia->ia_flags &= ~IFA_ROUTE;
367}
368
8473bbab 369/*
65b95551
MK
370 * Initialize an interface's internet address
371 * and routing table entry.
8473bbab 372 */
b4dc7708 373in_ifinit(ifp, ia, sin, scrub)
8473bbab 374 register struct ifnet *ifp;
65b95551
MK
375 register struct in_ifaddr *ia;
376 struct sockaddr_in *sin;
db55c43b 377 int scrub;
65b95551
MK
378{
379 register u_long i = ntohl(sin->sin_addr.s_addr);
b4dc7708 380 struct sockaddr_in oldaddr;
d6fa15c2 381 int s = splimp(), flags = RTF_UP, error, ether_output();
65b95551 382
2c83bd95 383 oldaddr = ia->ia_addr;
b4dc7708 384 ia->ia_addr = *sin;
b9ce6c7a
MK
385 /*
386 * Give the interface a chance to initialize
387 * if this is its first address,
388 * and to validate the address if necessary.
389 */
db55c43b
CT
390 if (ifp->if_ioctl &&
391 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
b9ce6c7a 392 splx(s);
2c83bd95 393 ia->ia_addr = oldaddr;
b9ce6c7a
MK
394 return (error);
395 }
1459f4b8
KS
396 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
397 ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
398 ia->ia_ifa.ifa_flags |= RTF_CLONING;
399 }
7189a987 400 splx(s);
b4dc7708
KS
401 if (scrub) {
402 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
403 in_ifscrub(ifp, ia);
404 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
65b95551 405 }
65b95551
MK
406 if (IN_CLASSA(i))
407 ia->ia_netmask = IN_CLASSA_NET;
408 else if (IN_CLASSB(i))
409 ia->ia_netmask = IN_CLASSB_NET;
410 else
411 ia->ia_netmask = IN_CLASSC_NET;
65b95551 412 /*
f48fa6fd
KS
413 * The subnet mask usually includes at least the standard network part,
414 * but may may be smaller in the case of supernetting.
415 * If it is set, we believe it.
65b95551 416 */
f48fa6fd
KS
417 if (ia->ia_subnetmask == 0) {
418 ia->ia_subnetmask = ia->ia_netmask;
419 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
420 } else
421 ia->ia_netmask &= ia->ia_subnetmask;
422 ia->ia_net = i & ia->ia_netmask;
65b95551 423 ia->ia_subnet = i & ia->ia_subnetmask;
09ed489e 424 in_socktrim(&ia->ia_sockmask);
7189a987
KS
425 /*
426 * Add route for the network.
427 */
8965e0de 428 ia->ia_ifa.ifa_metric = ifp->if_metric;
65b95551 429 if (ifp->if_flags & IFF_BROADCAST) {
09ed489e
KS
430 ia->ia_broadaddr.sin_addr.s_addr =
431 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
4afb57fa 432 ia->ia_netbroadcast.s_addr =
09ed489e 433 htonl(ia->ia_net | ~ ia->ia_netmask);
7189a987 434 } else if (ifp->if_flags & IFF_LOOPBACK) {
b4dc7708 435 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
7189a987
KS
436 flags |= RTF_HOST;
437 } else if (ifp->if_flags & IFF_POINTOPOINT) {
438 if (ia->ia_dstaddr.sin_family != AF_INET)
439 return (0);
440 flags |= RTF_HOST;
2c83bd95 441 }
7189a987
KS
442 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
443 ia->ia_flags |= IFA_ROUTE;
d6fa15c2
KS
444 /*
445 * If the interface supports multicast, join the "all hosts"
446 * multicast group on that interface.
447 */
448 if (ifp->if_flags & IFF_MULTICAST) {
449 struct in_addr addr;
450
451 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
452 in_addmulti(&addr, ifp);
453 }
7189a987 454 return (error);
65b95551
MK
455}
456
65b95551
MK
457
458/*
d6c52d1d 459 * Return 1 if the address might be a local broadcast address.
65b95551 460 */
09ed489e 461in_broadcast(in, ifp)
65b95551 462 struct in_addr in;
09ed489e 463 struct ifnet *ifp;
8473bbab 464{
09ed489e 465 register struct ifaddr *ifa;
d6c52d1d 466 u_long t;
65b95551 467
09ed489e
KS
468 if (in.s_addr == INADDR_BROADCAST ||
469 in.s_addr == INADDR_ANY)
470 return 1;
471 if ((ifp->if_flags & IFF_BROADCAST) == 0)
472 return 0;
473 t = ntohl(in.s_addr);
65b95551
MK
474 /*
475 * Look through the list of addresses for a match
476 * with a broadcast address.
477 */
09ed489e
KS
478#define ia ((struct in_ifaddr *)ifa)
479 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
480 if (ifa->ifa_addr->sa_family == AF_INET &&
481 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
482 in.s_addr == ia->ia_netbroadcast.s_addr ||
483 /*
484 * Check for old-style (host 0) broadcast.
485 */
486 t == ia->ia_subnet || t == ia->ia_net))
487 return 1;
c46785cb 488 return (0);
09ed489e 489#undef ia
8473bbab 490}
d6fa15c2
KS
491/*
492 * Add an address to the list of IP multicast addresses for a given interface.
493 */
494struct in_multi *
495in_addmulti(ap, ifp)
496 register struct in_addr *ap;
497 register struct ifnet *ifp;
498{
499 register struct in_multi *inm;
500 struct ifreq ifr;
501 struct in_ifaddr *ia;
502 int s = splnet();
d6fa15c2
KS
503
504 /*
505 * See if address already in list.
506 */
507 IN_LOOKUP_MULTI(*ap, ifp, inm);
508 if (inm != NULL) {
509 /*
510 * Found it; just increment the reference count.
511 */
512 ++inm->inm_refcount;
513 }
514 else {
515 /*
516 * New address; allocate a new multicast record
517 * and link it into the interface's multicast list.
518 */
519 inm = (struct in_multi *)malloc(sizeof(*inm),
520 M_IPMADDR, M_NOWAIT);
521 if (inm == NULL) {
522 splx(s);
523 return (NULL);
524 }
525 inm->inm_addr = *ap;
526 inm->inm_ifp = ifp;
527 inm->inm_refcount = 1;
528 IFP_TO_IA(ifp, ia);
529 if (ia == NULL) {
530 free(inm, M_IPMADDR);
531 splx(s);
532 return (NULL);
533 }
534 inm->inm_ia = ia;
86ac2b7b
KS
535 inm->inm_next = ia->ia_multiaddrs;
536 ia->ia_multiaddrs = inm;
d6fa15c2
KS
537 /*
538 * Ask the network driver to update its multicast reception
539 * filter appropriately for the new address.
540 */
541 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
542 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
86ac2b7b
KS
543 if ((ifp->if_ioctl == NULL) ||
544 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
545 ia->ia_multiaddrs = inm->inm_next;
d6fa15c2
KS
546 free(inm, M_IPMADDR);
547 splx(s);
548 return (NULL);
549 }
550 /*
551 * Let IGMP know that we have joined a new IP multicast group.
552 */
553 igmp_joingroup(inm);
554 }
555 splx(s);
556 return (inm);
557}
558
559/*
560 * Delete a multicast address record.
561 */
562int
563in_delmulti(inm)
564 register struct in_multi *inm;
565{
566 register struct in_multi **p;
567 struct ifreq ifr;
568 int s = splnet();
569
570 if (--inm->inm_refcount == 0) {
571 /*
572 * No remaining claims to this record; let IGMP know that
573 * we are leaving the multicast group.
574 */
575 igmp_leavegroup(inm);
576 /*
577 * Unlink from list.
578 */
579 for (p = &inm->inm_ia->ia_multiaddrs;
580 *p != inm;
581 p = &(*p)->inm_next)
582 continue;
583 *p = (*p)->inm_next;
584 /*
585 * Notify the network driver to update its multicast reception
586 * filter.
587 */
588 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
589 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
590 inm->inm_addr;
591 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
592 (caddr_t)&ifr);
593 free(inm, M_IPMADDR);
594 }
595 splx(s);
596}
597#endif