IN.C
上传用户:tjbfgc
上传日期:2013-03-31
资源大小:140k
文件大小:17k
源码类别:

网络编程

开发平台:

C/C++

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