in.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:35k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* in.c - internet routines */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1991, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)in.c 8.4 (Berkeley) 1/9/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01m,12oct01,rae  merge from truestack ver 01n, base 01j (SPR #67536 etc)
  42. 01l,30jan01,spm  ignored existing routes for alias IP addresses (SPR #62333)
  43. 01k,20apr00,rae  fixed memory leak in in_ifinit, SPR#28903
  44. 01j,22feb99,ham  called in_socktrim() in SIOCSIFNETMASK, SPR#24251.
  45. 01h,06oct98,ham  cancelled "01g" moidification, new fix for SPR#22267.
  46. 01g,08sep98,ham  fixed SIOCAIFADDR inproper work in in_control SPR#22267.
  47. 01f,08dec97,vin  fixed a bug in_addmulti incremented the ref count SPR 9971
  48. 01e,03dec97,vin  changed _pNetDpool to _pNetSysPool
  49. 01d,05oct97,vin  added fast multicasting.
  50. 01c,07jan96,vin  added _igmpJoinGrpHook and _igmpLeaveGrpHook for scaling igmp.
  51. 01b,05dec96,vin  replaced malloc with MALLOC and free with FREE(),
  52. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02n of in.c.
  53. */
  54. /*
  55. DESCRIPTION
  56. */
  57. #include "vxWorks.h"
  58. #include "logLib.h"
  59. #include "sys/ioctl.h"
  60. #include "net/mbuf.h"
  61. #include "net/protosw.h"
  62. #include "sys/socket.h"
  63. #include "net/socketvar.h"
  64. #include "net/uio.h"
  65. #include "errno.h"
  66. #include "netinet/in_systm.h"
  67. #include "net/if.h"
  68. #include "net/route.h"
  69. #include "netinet/in.h"
  70. #include "netinet/in_var.h"
  71. #include "net/systm.h"
  72. #include "netinet/igmp_var.h"
  73. #include "net/unixLib.h"
  74. #ifdef VIRTUAL_STACK
  75. #include "netinet/vsLib.h"
  76. #include "netinet/vsIgmp.h"
  77. #endif /* VIRTUAL_STACK */
  78. #ifdef INET
  79. #ifdef WV_INSTRUMENTATION
  80. #ifdef INCLUDE_WVNET
  81. #include "wvNetLib.h"
  82. #endif
  83. #endif
  84. /* defines */
  85. /* externals */
  86. extern void arp_rtrequest (); 
  87. extern VOIDFUNCPTR _igmpJoinGrpHook; 
  88. extern VOIDFUNCPTR _igmpLeaveGrpHook; 
  89. /* globals */
  90. #ifndef SUBNETSARELOCAL
  91. #define SUBNETSARELOCAL 1
  92. #endif
  93. int subnetsarelocal = SUBNETSARELOCAL;
  94. int in_interfaces; /* number of external internet interfaces */
  95. #ifndef VIRTUAL_STACK
  96. extern struct ifnet loif[]; /* loop back interface */
  97. struct mcastHashInfo mCastHashInfo;
  98. #endif
  99. int mCastHashTblSize = 64; /* default size of hash table */
  100. #ifdef WV_INSTRUMENTATION
  101. #ifdef INCLUDE_WVNET
  102.     /* Set common fields of event identifiers for this module. */
  103. LOCAL UCHAR wvNetModuleId = WV_NET_IN_MODULE;   /* Value for in.c */
  104. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  105. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  106. #endif    /* INCLUDE_WVNET */
  107. #endif
  108. BOOL inet_netmatch(sin1, sin2)
  109. struct sockaddr_in *sin1;
  110. struct sockaddr_in *sin2;
  111. {
  112. return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
  113. }
  114. /*
  115.  * The following routines, in_netof, and in_lnaof,
  116.  * are similar to the corresponding routines in inetLib, except that
  117.  * these routines take subnet masks into account.
  118.  */
  119. /*
  120.  * Return the network number from an internet address.
  121.  */
  122. u_long
  123. in_netof(in)
  124. struct in_addr in;
  125. {
  126. register u_long i = ntohl(in.s_addr);
  127. register u_long net;
  128. register struct in_ifaddr *ia;
  129. if (IN_CLASSA(i))
  130. net = i & IN_CLASSA_NET; 
  131. else if (IN_CLASSB(i))
  132. net = i & IN_CLASSB_NET;
  133. else if (IN_CLASSC(i))
  134. net = i & IN_CLASSC_NET;
  135. else if (IN_CLASSD(i))
  136. net = i & IN_CLASSD_NET;
  137. else
  138. return (0);
  139. /*
  140.  * Check whether network is a subnet;
  141.  * if so, return subnet number.
  142.  */
  143. #ifdef VIRTUAL_STACK
  144. for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  145. #else
  146. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  147. #endif /* VIRTUAL_STACK */
  148. if (net == ia->ia_net)
  149. return (i & ia->ia_subnetmask);
  150. return (net);
  151. }
  152. /*
  153.  * Return 1 if an internet address is for a ``local'' host
  154.  * (one to which we have a connection).  If subnetsarelocal
  155.  * is true, this includes other subnets of the local net.
  156.  * Otherwise, it includes only the directly-connected (sub)nets.
  157.  */
  158. int
  159. in_localaddr(in)
  160. struct in_addr in;
  161. {
  162. register u_long i = ntohl(in.s_addr);
  163. register struct in_ifaddr *ia;
  164. if (subnetsarelocal) {
  165. #ifdef VIRTUAL_STACK
  166. for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  167. #else
  168. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  169. #endif /* VIRTUAL_STACK */
  170. if ((i & ia->ia_netmask) == ia->ia_net)
  171. return (1);
  172. } else {
  173. #ifdef VIRTUAL_STACK
  174. for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  175. #else
  176. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  177. #endif /* VIRTUAL_STACK */
  178. if ((i & ia->ia_subnetmask) == ia->ia_subnet)
  179. return (1);
  180. }
  181. return (0);
  182. }
  183. /*
  184.  * Determine whether an IP address is in a reserved set of addresses
  185.  * that may not be forwarded, or whether datagrams to that destination
  186.  * may be forwarded.
  187.  */
  188. int
  189. in_canforward(in)
  190. struct in_addr in;
  191. {
  192. register u_long i = ntohl(in.s_addr);
  193. register u_long net;
  194. if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
  195. return (0);
  196. if (IN_CLASSA(i)) {
  197. net = i & IN_CLASSA_NET;
  198. if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
  199. return (0);
  200. }
  201. return (1);
  202. }
  203. /*
  204.  * Trim a mask in a sockaddr
  205.  */
  206. void
  207. in_socktrim(ap)
  208. struct sockaddr_in *ap;
  209. {
  210.     register char *cplim = (char *) &ap->sin_addr;
  211.     register char *cp = (char *) (&ap->sin_addr + 1);
  212.     ap->sin_len = 0;
  213.     while (--cp >= cplim)
  214.         if (*cp) {
  215.     (ap)->sin_len = cp - (char *) (ap) + 1;
  216.     break;
  217. }
  218. }
  219. /*
  220.  * Return the host portion of an internet address.
  221.  */
  222. u_long
  223. in_lnaof(in)
  224.         struct in_addr in;
  225. {
  226.         register u_long i = ntohl(in.s_addr);
  227.         register u_long net, host;
  228.         register struct in_ifaddr *ia;
  229.         if (IN_CLASSA(i)) {
  230.                 net = i & IN_CLASSA_NET;
  231.                 host = i & IN_CLASSA_HOST;
  232.         } else if (IN_CLASSB(i)) {
  233.                 net = i & IN_CLASSB_NET;
  234.                 host = i & IN_CLASSB_HOST;
  235.         } else if (IN_CLASSC(i)) {
  236.                 net = i & IN_CLASSC_NET;
  237.                 host = i & IN_CLASSC_HOST;
  238.         } else if (IN_CLASSD(i)) {
  239.                 net = i & IN_CLASSD_NET;
  240.                 host = i & IN_CLASSD_HOST;
  241.         } else
  242.                 return (i);
  243.         /*
  244.          * Check whether network is a subnet;
  245.          * if so, use the modified interpretation of `host'.
  246.          */
  247. #ifdef VIRTUAL_STACK
  248.         for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  249. #else
  250.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  251. #endif /* VIRTUAL_STACK */
  252.                 if (net == ia->ia_net)
  253.                         return (host &~ ia->ia_subnetmask);
  254.         return (host);
  255. }
  256. /*
  257.  * Generic internet control operations (ioctl's).
  258.  * Ifp is 0 if not an interface-specific ioctl.
  259.  */
  260. /* ARGSUSED */
  261. int
  262. in_control(so, cmd, data, ifp)
  263. struct socket *so;
  264. u_long cmd;
  265. caddr_t data;
  266. register struct ifnet *ifp;
  267. {
  268. register struct ifreq *ifr = (struct ifreq *)data;
  269. register struct in_ifaddr *ia = 0;
  270. register struct ifaddr *ifa;
  271. struct in_ifaddr *oia;
  272. struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  273. struct sockaddr_in oldaddr;
  274. int error, hostIsNew, maskIsNew;
  275. u_long i;
  276.         BOOL newRouteFlag = FALSE;  /* Connection to new IP subnet? */
  277. #ifdef WV_INSTRUMENTATION
  278. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  279.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 18, 7,
  280.                          WV_NETEVENT_INCTRL_START, cmd)
  281. #endif  /* INCLUDE_WVNET */
  282. #endif
  283.             /*
  284.              * Find address for this interface, if it exists.
  285.              */
  286.             if (ifp)
  287. #ifdef VIRTUAL_STACK
  288.                 for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  289. #else
  290.                     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  291. #endif /* VIRTUAL_STACK */
  292. if (ia->ia_ifp == ifp)
  293.                             break;
  294.         
  295. switch (cmd) {
  296.         
  297. case SIOCAIFADDR:
  298.             
  299.             if (ia == 0)
  300.                 {
  301.                 /* First IP address: no matching route should exist. */
  302.                 
  303.                 newRouteFlag = TRUE;
  304.                 }
  305.             
  306.             /* fall-through */
  307.             
  308. case SIOCDIFADDR:
  309.             if (ifra->ifra_addr.sin_family == AF_INET)
  310.                 for (oia = ia; ia; ia = ia->ia_next) {
  311.                 if (ia->ia_ifp == ifp  &&
  312.     ia->ia_addr.sin_addr.s_addr ==
  313.                     ifra->ifra_addr.sin_addr.s_addr)
  314.                     break;
  315. }
  316.             if (cmd == SIOCDIFADDR && ia == 0)
  317.                 {
  318. #ifdef WV_INSTRUMENTATION
  319. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  320.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 8, 4, 
  321.                                  WV_NETEVENT_INCTRL_SEARCHFAIL, cmd, ifp)
  322. #endif  /* INCLUDE_WVNET */
  323. #endif
  324.                     return (EADDRNOTAVAIL);
  325.                 }
  326.             
  327.             /* FALLTHROUGH */
  328. case SIOCSIFADDR:
  329. case SIOCSIFNETMASK:
  330. case SIOCSIFDSTADDR:
  331.             if ((so->so_state & SS_PRIV) == 0)
  332.                 {
  333. #ifdef WV_INSTRUMENTATION
  334. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  335.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_WARNING, 6, 6, 
  336.                                  WV_NETEVENT_INCTRL_BADSOCK, so->so_fd, cmd)
  337. #endif  /* INCLUDE_WVNET */
  338. #endif
  339.                     return (EPERM);
  340.                 }
  341.             if (ifp == 0)
  342.                 {
  343. #ifdef WV_INSTRUMENTATION
  344. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  345.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 10, 1, 
  346.                                  WV_NETEVENT_INCTRL_PANIC, cmd)
  347. #endif  /* INCLUDE_WVNET */
  348. #endif
  349.                     panic("in_control");
  350.                 }
  351.             if (ia == (struct in_ifaddr *)0) {
  352.             MALLOC (oia, struct in_ifaddr *, sizeof(*oia),
  353. MT_IFADDR, M_WAIT); 
  354. if (oia == (struct in_ifaddr *)NULL)
  355.                             {
  356. #ifdef WV_INSTRUMENTATION
  357. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  358.                             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 11, 2, 
  359.                                              WV_NETEVENT_INCTRL_NOBUFS, cmd)
  360. #endif  /* INCLUDE_WVNET */
  361. #endif
  362.                             return (ENOBUFS);
  363.                             }
  364. bzero((caddr_t)oia, sizeof *oia);
  365. #ifdef VIRTUAL_STACK
  366. if ((ia = _in_ifaddr)) {
  367. #else
  368. if ((ia = in_ifaddr)) {
  369. #endif /* VIRTUAL_STACK */
  370. for ( ; ia->ia_next; ia = ia->ia_next)
  371. continue;
  372. ia->ia_next = oia;
  373. } else
  374. #ifdef VIRTUAL_STACK
  375. _in_ifaddr = oia;
  376. #else
  377. in_ifaddr = oia;
  378. #endif /* VIRTUAL_STACK */
  379. ia = oia;
  380. if ((ifa = ifp->if_addrlist)) {
  381. for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
  382. continue;
  383. ifa->ifa_next = (struct ifaddr *) ia;
  384. } else
  385. ifp->if_addrlist = (struct ifaddr *) ia;
  386. ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  387. ia->ia_ifa.ifa_dstaddr
  388. = (struct sockaddr *)&ia->ia_dstaddr;
  389. ia->ia_ifa.ifa_netmask
  390. = (struct sockaddr *)&ia->ia_sockmask;
  391. ia->ia_sockmask.sin_len = 8;
  392. if (ifp->if_flags & IFF_BROADCAST) {
  393. ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  394. ia->ia_broadaddr.sin_family = AF_INET;
  395. }
  396. ia->ia_ifp = ifp;
  397. if (ifp != loif)
  398. in_interfaces++;
  399. }
  400. break;
  401. case SIOCSIFBRDADDR:
  402. if ((so->so_state & SS_PRIV) == 0)
  403. return (EPERM);
  404. /* FALLTHROUGH */
  405. case SIOCGIFADDR:
  406. case SIOCGIFNETMASK:
  407. case SIOCGIFDSTADDR:
  408. case SIOCGIFBRDADDR:
  409. if (ia == (struct in_ifaddr *)0)
  410.                     {
  411. #ifdef WV_INSTRUMENTATION
  412. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  413.                     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 8, 4, 
  414.                                      WV_NETEVENT_INCTRL_SEARCHFAIL, cmd, ifp)
  415. #endif  /* INCLUDE_WVNET */
  416. #endif
  417.                     return (EADDRNOTAVAIL);
  418.                     }
  419. break;
  420. }
  421. switch (cmd) {
  422. case SIOCGIFADDR:
  423. *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
  424. break;
  425. case SIOCGIFBRDADDR:
  426. if ((ifp->if_flags & IFF_BROADCAST) == 0)
  427.                     {
  428. #ifdef WV_INSTRUMENTATION
  429. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  430.                     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 9, 5, 
  431.                                      WV_NETEVENT_INCTRL_BADFLAGS, cmd, ifp)
  432. #endif  /* INCLUDE_WVNET */
  433. #endif
  434.                     return (EINVAL);
  435.                     }
  436. *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  437. break;
  438. case SIOCGIFDSTADDR:
  439. if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  440.                     {
  441. #ifdef WV_INSTRUMENTATION
  442. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  443.                     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 9, 5, 
  444.                                      WV_NETEVENT_INCTRL_BADFLAGS, cmd, ifp)
  445. #endif  /* INCLUDE_WVNET */
  446. #endif
  447.                     return (EINVAL);
  448.                     }
  449. *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  450. break;
  451. case SIOCGIFNETMASK:
  452. *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
  453. break;
  454. case SIOCSIFDSTADDR:
  455. if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  456.                     {
  457. #ifdef WV_INSTRUMENTATION
  458. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  459.                     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 9, 5, 
  460.                                      WV_NETEVENT_INCTRL_BADFLAGS, cmd, ifp)
  461. #endif  /* INCLUDE_WVNET */
  462. #endif
  463.                     return (EINVAL);
  464.                     }
  465. oldaddr = ia->ia_dstaddr;
  466. ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
  467. if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
  468. (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
  469. ia->ia_dstaddr = oldaddr;
  470. return (error);
  471. }
  472. if (ia->ia_flags & IFA_ROUTE) {
  473. ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
  474. rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  475. ia->ia_ifa.ifa_dstaddr =
  476. (struct sockaddr *)&ia->ia_dstaddr;
  477. rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  478. }
  479. break;
  480. case SIOCSIFBRDADDR:
  481. if ((ifp->if_flags & IFF_BROADCAST) == 0)
  482.                     {
  483. #ifdef WV_INSTRUMENTATION
  484. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  485.                     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 9, 5, 
  486.                                      WV_NETEVENT_INCTRL_BADFLAGS, cmd, ifp)
  487. #endif  /* INCLUDE_WVNET */
  488. #endif
  489.                     return (EINVAL);
  490.                     }
  491. ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
  492. break;
  493. case SIOCSIFADDR:
  494. return (in_ifinit(ifp, ia,
  495.     (struct sockaddr_in *) &ifr->ifr_addr, 1));
  496. case SIOCSIFNETMASK:
  497. i = ifra->ifra_addr.sin_addr.s_addr;
  498. ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
  499. in_socktrim (&ia->ia_sockmask);
  500. break;
  501. case SIOCAIFADDR:
  502. maskIsNew = 0;
  503. hostIsNew = 1;
  504. error = 0;
  505. if (ia->ia_addr.sin_family == AF_INET) {
  506. if (ifra->ifra_addr.sin_len == 0) {
  507. ifra->ifra_addr = ia->ia_addr;
  508. hostIsNew = 0;
  509. } else if (ifra->ifra_addr.sin_addr.s_addr ==
  510.        ia->ia_addr.sin_addr.s_addr)
  511. hostIsNew = 0;
  512. }
  513. if (ifra->ifra_mask.sin_len) {
  514. in_ifscrub(ifp, ia);
  515. ia->ia_sockmask = ifra->ifra_mask;
  516. ia->ia_subnetmask =
  517.      ntohl(ia->ia_sockmask.sin_addr.s_addr);
  518. maskIsNew = 1;
  519. }
  520. if ((ifp->if_flags & IFF_POINTOPOINT) &&
  521.     (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  522. in_ifscrub(ifp, ia);
  523. ia->ia_dstaddr = ifra->ifra_dstaddr;
  524. maskIsNew  = 1; /* We lie; but the effect's the same */
  525. }
  526. if (ifra->ifra_addr.sin_family == AF_INET &&
  527.     (hostIsNew || maskIsNew))
  528. error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  529.                 /*
  530.                  * Ignore the report of an existing route entry if
  531.                  * this new (alias) IP address might use the same
  532.                  * logical subnet as another address/netmask pair.
  533.                  * The SIOCAIFADDR operation continues to provide
  534.                  * the duplicate route error when assigning the
  535.                  * initial address for an interface.
  536.                  */
  537.                 if (error == EEXIST)
  538.                     {
  539.                     /*
  540.                      * The information necessary to determine whether this
  541.                      * address/netmask assignment absolutely requires an
  542.                      * associated route entry is not readily available.
  543.                      * This operation assumes existing routes to a logical
  544.                      * subnet use the same interface as the new address entry.
  545.                      * Under certain circumstances, the ability to ignore
  546.                      * existing routes when assigning additional IP addresses
  547.                      * might allow users to successfully configure interfaces
  548.                      * which are unable to transmit data.
  549.                      */
  550.                     if (newRouteFlag == FALSE)
  551.                         error = 0;
  552.                     }
  553.                 /*
  554.                  * Replace the mask-based broadcast address if the
  555.                  * user provides a specific value.
  556.                  */
  557.                 if ((ifp->if_flags & IFF_BROADCAST) &&
  558.                     (ifra->ifra_broadaddr.sin_family == AF_INET) &&
  559.                     (ifra->ifra_broadaddr.sin_addr.s_addr))
  560.                         ia->ia_broadaddr = ifra->ifra_broadaddr;
  561. return (error);
  562. case SIOCDIFADDR:
  563. in_ifscrub(ifp, ia);
  564. if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
  565. ifp->if_addrlist = ifa->ifa_next;
  566. else {
  567. while (ifa->ifa_next &&
  568.        (ifa->ifa_next != (struct ifaddr *)ia))
  569.     ifa = ifa->ifa_next;
  570. if (ifa->ifa_next)
  571. ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
  572. else
  573. logMsg("Couldn't unlink inifaddr from ifpn",
  574.        0,0,0,0,0,0);
  575. }
  576. oia = ia;
  577. #ifdef VIRTUAL_STACK
  578. if (oia == (ia = _in_ifaddr))
  579. _in_ifaddr = ia->ia_next;
  580. #else
  581. if (oia == (ia = in_ifaddr))
  582. in_ifaddr = ia->ia_next;
  583. #endif /* VIRTUAL_STACK */
  584. else {
  585. while (ia->ia_next && (ia->ia_next != oia))
  586. ia = ia->ia_next;
  587. if (ia->ia_next)
  588. ia->ia_next = oia->ia_next;
  589. else
  590. logMsg("Didn't unlink inifadr from listn",
  591.        0,0,0,0,0,0);
  592. }
  593. IFAFREE((&oia->ia_ifa));
  594. break;
  595. default:
  596. if (ifp == 0 || ifp->if_ioctl == 0)
  597. return (EOPNOTSUPP);
  598. return ((*ifp->if_ioctl)(ifp, cmd, data));
  599. }
  600. return (0);
  601. }
  602. /*
  603.  * Delete any existing route for an interface.
  604.  */
  605. void
  606. in_ifscrub(ifp, ia)
  607. register struct ifnet *ifp;
  608. register struct in_ifaddr *ia;
  609. {
  610. #ifdef WV_INSTRUMENTATION
  611. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  612.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 19, 8, 
  613.                          WV_NETEVENT_INROUTEDEL_START, ifp)
  614. #endif  /* INCLUDE_WVNET */
  615. #endif
  616. if ((ia->ia_flags & IFA_ROUTE) == 0)
  617. return;
  618. if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
  619. rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  620. else
  621. rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  622. ia->ia_flags &= ~IFA_ROUTE;
  623. }
  624. /*
  625.  * Initialize an interface's internet address
  626.  * and routing table entry.
  627.  */
  628. int
  629. in_ifinit(ifp, ia, sin, scrub)
  630. register struct ifnet *ifp;
  631. register struct in_ifaddr *ia;
  632. struct sockaddr_in *sin;
  633. int scrub;
  634. {
  635. register u_long i = ntohl(sin->sin_addr.s_addr);
  636. struct sockaddr_in oldaddr;
  637. int s = splimp(), flags = RTF_UP, error, ether_output();
  638. #ifdef WV_INSTRUMENTATION
  639. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  640.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 20, 9, 
  641.                      WV_NETEVENT_INIFINIT_START, ifp, sin->sin_addr.s_addr)
  642. #endif  /* INCLUDE_WVNET */
  643. #endif
  644. oldaddr = ia->ia_addr;
  645. ia->ia_addr = *sin;
  646. /*
  647.  * Give the interface a chance to initialize
  648.  * if this is its first address,
  649.  * and to validate the address if necessary.
  650.  */
  651. if (ifp->if_ioctl &&
  652.     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
  653. splx(s);
  654. ia->ia_addr = oldaddr;
  655. return (error);
  656. }
  657. if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
  658. ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
  659. ia->ia_ifa.ifa_flags |= RTF_CLONING;
  660. }
  661. splx(s);
  662. if (scrub) {
  663. ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  664. in_ifscrub(ifp, ia);
  665. ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  666. }
  667. if (IN_CLASSA(i))
  668. ia->ia_netmask = IN_CLASSA_NET;
  669. else if (IN_CLASSB(i))
  670. ia->ia_netmask = IN_CLASSB_NET;
  671. else
  672. ia->ia_netmask = IN_CLASSC_NET;
  673. /*
  674.  * The subnet mask usually includes at least the standard network part,
  675.  * but may may be smaller in the case of supernetting.
  676.  * If it is set, we believe it.
  677.  */
  678. if (ia->ia_subnetmask == 0) {
  679. ia->ia_subnetmask = ia->ia_netmask;
  680. ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
  681. } else
  682. ia->ia_netmask &= ia->ia_subnetmask;
  683. ia->ia_net = i & ia->ia_netmask;
  684. ia->ia_subnet = i & ia->ia_subnetmask;
  685. in_socktrim(&ia->ia_sockmask);
  686. /*
  687.  * Add route for the network.
  688.  */
  689. ia->ia_ifa.ifa_metric = ifp->if_metric;
  690. if (ifp->if_flags & IFF_BROADCAST) {
  691. ia->ia_broadaddr.sin_addr.s_addr =
  692. htonl(ia->ia_subnet | ~ia->ia_subnetmask);
  693. ia->ia_netbroadcast.s_addr =
  694. htonl(ia->ia_net | ~ ia->ia_netmask);
  695. } else if (ifp->if_flags & IFF_LOOPBACK) {
  696. ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
  697. flags |= RTF_HOST;
  698. } else if (ifp->if_flags & IFF_POINTOPOINT) {
  699. if (ia->ia_dstaddr.sin_family != AF_INET)
  700. return (0);
  701. flags |= RTF_HOST;
  702. }
  703. if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
  704. ia->ia_flags |= IFA_ROUTE;
  705. /*
  706.  * If the interface supports multicast, join the "all hosts"
  707.  * multicast group on that interface.
  708.  */
  709. if (ifp->if_flags & IFF_MULTICAST) {
  710. struct in_addr addr;
  711.                 struct in_multi * inm;
  712. addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
  713.                 IN_LOOKUP_MULTI(addr, ifp, inm);
  714.                 if (inm == NULL)             /* don't add if already there ... SPR#28903 */
  715.                     ifp->pInmMblk = in_addmulti (&addr, ifp, NULL); 
  716. }
  717. return (error);
  718. }
  719. /*******************************************************************************
  720. *
  721. * in_ifaddr_remove - remove an interface from the in_ifaddr list
  722. *
  723. * This function removes the internet interface address given as an input
  724. * parameter, from the global linked-list of internet interface addresses
  725. * pointed by in_ifaddr. This function is called before dettaching an interface
  726. * This function also removes all the internet multicast addresses hooked to 
  727. * the in_ifaddr. It calls in_delmulti() which in turn calls the ioctl for the
  728. * driver to remove the ethernet multicast addresses.
  729. * NOMANUAL
  730. * RETURNS: N/A
  731. */
  732.  
  733. void in_ifaddr_remove 
  734.     (
  735.     struct ifaddr * pIfAddr /* pointer to interface address */
  736.     ) 
  737.     {
  738.     struct in_ifaddr ** pPtrInIfAddr;  /* pointer to pointer to in_ifaddr */
  739.     struct in_ifaddr *  pInIfAddr;  /* pointer to in_ifaddr */
  740. #ifdef WV_INSTRUMENTATION
  741. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  742.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 21, 10, 
  743.                      WV_NETEVENT_INIFADDRDEL_START)
  744. #endif  /* INCLUDE_WVNET */
  745. #endif
  746.  
  747.  
  748. #ifdef VIRTUAL_STACK
  749.     pPtrInIfAddr = &_in_ifaddr;  /* global variable */
  750. #else
  751.     pPtrInIfAddr = &in_ifaddr;  /* global variable */
  752. #endif /* VIRTUAL_STACK */
  753.     while (*pPtrInIfAddr != NULL)
  754. {
  755. if (*pPtrInIfAddr == (struct in_ifaddr *)pIfAddr)
  756.     {
  757.     pInIfAddr = *pPtrInIfAddr; 
  758.     *pPtrInIfAddr = (*pPtrInIfAddr)->ia_next;  /* delete from list */
  759.     IFAFREE (&pInIfAddr->ia_ifa); /* free address */
  760.     break; 
  761.     }
  762. pPtrInIfAddr = &(*pPtrInIfAddr)->ia_next; 
  763. }
  764.     } 
  765. /*
  766.  * Return 1 if the address might be a local broadcast address.
  767.  */
  768. int
  769. in_broadcast(in, ifp)
  770. struct in_addr in;
  771.         struct ifnet *ifp;
  772. {
  773. register struct ifaddr *ifa;
  774. u_long t;
  775. if (in.s_addr == INADDR_BROADCAST ||
  776.     in.s_addr == INADDR_ANY)
  777. return 1;
  778. if ((ifp->if_flags & IFF_BROADCAST) == 0)
  779. return 0;
  780. t = ntohl(in.s_addr);
  781. /*
  782.  * Look through the list of addresses for a match
  783.  * with a broadcast address.
  784.  */
  785. #define ia ((struct in_ifaddr *)ifa)
  786. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  787. if (ifa->ifa_addr->sa_family == AF_INET &&
  788.     (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
  789.      in.s_addr == ia->ia_netbroadcast.s_addr ||
  790.      /*
  791.       * Check for old-style (host 0) broadcast.
  792.       */
  793.      t == ia->ia_subnet || t == ia->ia_net))
  794.     return 1;
  795. return (0);
  796. #undef ia
  797. }
  798. /*
  799.  * Add an address to the list of IP multicast addresses for a given interface.
  800.  */
  801. struct mBlk *
  802. in_addmulti(ap, ifp, pInPcb)
  803. register struct in_addr *ap;
  804. register struct ifnet *ifp;
  805. register struct inpcb * pInPcb;
  806. {
  807. register struct in_multi *inm;
  808. struct ifreq ifr;
  809.         struct mBlk * pInPcbMblk = NULL;
  810.         struct mBlk * pInmMblk = NULL;
  811. struct mBlk * pInmFirstMblk = NULL;
  812. int s = splnet();
  813. #ifdef WV_INSTRUMENTATION
  814. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  815.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 58, 11, 
  816.                      WV_NETEVENT_INADDMULT_START, ifp, ap->s_addr)
  817. #endif  /* INCLUDE_WVNET */
  818. #endif
  819. /*
  820.  * See if address already in list.
  821.  */
  822. IN_LOOKUP_MULTI(*ap, ifp, inm);
  823. if (inm != NULL) {
  824. /*
  825.  * Found it; duplicate the mBlk, increment reference count.
  826.  */
  827.          if ((pInmMblk = mBlkGet (_pNetSysPool, M_DONTWAIT, MT_IPMADDR))
  828.                     == NULL)
  829.                     {
  830. #ifdef WV_INSTRUMENTATION
  831. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  832.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, 
  833.                              WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)
  834. #endif  /* INCLUDE_WVNET */
  835. #endif
  836.                     goto inAddMultiError;
  837.                     }
  838.                 /*
  839.  * XXX - The in_multi structures are stored in Mblk chains
  840.  * instead of arrays like in BSD. Therefore when a second 
  841.  * socket joins a multicast group, the Mblk for the in_multi
  842.  * structure is duplicated for this new member. The Mblk
  843.  * address for the in_multi is obtained by using a pointer
  844.  * to the start of the Mblk. This pointer is located just
  845.  * before the structure and is retrieved using DATA_TO_MBLK.
  846.  * This poses a problem when there is more than one Mblk
  847.  * accessing the in_multi structure (like in this case) since
  848.  * Mblk information for the second Mblk is lost. To fix this
  849.  * (SPR #67536), we use the mNextPkt field of the first Mblk
  850.  * to store the Mblk address for the second Mblk. When the 
  851.  * first Mblk is deleted (leaving group), the address of
  852.  * second Mblk can be still be retrieved through the pointer.
  853.  * Though this is not the best way to fix this problem, we
  854.  * leave it this way since the entire design needs to be 
  855.  * rethought (using the Mblk back-ptr is not a good idea).
  856.  */
  857.                 pInmFirstMblk = DATA_TO_MBLK (inm);
  858.                 netMblkDup (pInmFirstMblk, pInmMblk);
  859. pInmFirstMblk->mBlkHdr.mNextPkt = pInmMblk;
  860. pInmMblk->mBlkHdr.mNextPkt = NULL;
  861.                 ++inm->inm_refcount;
  862. }
  863. else {
  864. /*
  865.  * New address; allocate a new multicast record
  866.  * and link it into the interface's multicast list.
  867.  */
  868.         MALLOC(inm, struct in_multi *, sizeof(*inm), MT_IPMADDR,
  869.                        M_DONTWAIT);
  870.                 if (inm == NULL)
  871.                     {
  872. #ifdef WV_INSTRUMENTATION
  873. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  874.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, 
  875.                              WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)
  876. #endif  /* INCLUDE_WVNET */
  877. #endif
  878.                     goto inAddMultiError;
  879.                     }
  880.                 pInmMblk = DATA_TO_MBLK (inm);
  881. pInmMblk->mBlkHdr.mNextPkt = NULL;
  882.                 bzero ((char *)inm, sizeof (*inm));  /* zero the structure */
  883. inm->inm_addr = *ap;
  884. inm->inm_ifp = ifp;
  885. inm->inm_refcount = 1;
  886.                 /* insert the multicast address into the hash table */
  887.                 if (mcastHashTblInsert (inm) != OK)
  888.                     goto inAddMultiError;
  889. /*
  890.  * Ask the network driver to update its multicast reception
  891.  * filter appropriately for the new address.
  892.  */
  893. ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
  894. ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
  895. if ((ifp->if_ioctl == NULL) ||
  896.     (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
  897.                  mcastHashTblDelete (inm);
  898.                         goto inAddMultiError;
  899. }
  900. /*
  901.  * Let IGMP know that we have joined a new IP multicast group.
  902.  */
  903. if (_igmpJoinGrpHook != NULL)
  904.     (*_igmpJoinGrpHook) (inm); 
  905. }
  906.         /*
  907.          * insert the protocol control block into inm pcb list
  908.          * this is done to get to the list of pcbs which have joined a
  909.          * multicast group. When the hash table is looked up the inm
  910.          * returned should have a list of pcbs which the datagram
  911.          * should be delivered to. refer udp_usrreq.c where the pcb
  912.          * list is used.
  913.          */
  914.         if (pInPcb != NULL)
  915.             {
  916.             if ((pInPcbMblk = mBlkGet (_pNetSysPool, M_DONTWAIT, MT_PCB))
  917.                 == NULL)
  918.                 {
  919. #ifdef WV_INSTRUMENTATION
  920. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  921.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, 
  922.                              WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)
  923. #endif  /* INCLUDE_WVNET */
  924. #endif
  925.                 goto inAddMultiError;
  926.                 }
  927.             netMblkDup (DATA_TO_MBLK (pInPcb), pInPcbMblk);
  928.             pInPcbMblk->mBlkHdr.mNext = inm->pInPcbMblk;
  929.             inm->pInPcbMblk = pInPcbMblk;
  930.             }
  931.         
  932. splx(s);
  933. return (pInmMblk); /* return the mBlk pointing to the inm */
  934. inAddMultiError:
  935.         splx (s);
  936.         if (pInmMblk)
  937.             m_free (pInmMblk);
  938.         return (NULL);
  939. }
  940. /*
  941.  * Delete a multicast address record.
  942.  * deletes all pcbs if pInPcb is NULL. 
  943.  */
  944. int
  945. in_delmulti(pInmMblk, pInPcb)
  946.      register struct mBlk * pInmMblk;
  947. register struct inpcb * pInPcb;
  948. {
  949. register struct in_multi *inm;
  950.         M_BLK_ID *  ppMblk;
  951.         M_BLK_ID  pInPcbMblk; 
  952. struct mBlk **           ppInmMblk;
  953. struct ifreq ifr;
  954. int s = splnet();
  955. #ifdef WV_INSTRUMENTATION
  956. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  957.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 22, 12, 
  958.                      WV_NETEVENT_INDELMULT_START)
  959. #endif  /* INCLUDE_WVNET */
  960. #endif
  961.         inm = mtod (pInmMblk, struct in_multi *);
  962.         /* delete the pcb from the list */
  963.         ppMblk = &inm->pInPcbMblk;
  964.         if (pInPcb != NULL)
  965.             {
  966.             while ((pInPcbMblk = *ppMblk))
  967.                 {
  968.                 if (pInPcb == mtod (pInPcbMblk, struct inpcb *))
  969.                     {
  970.                     *ppMblk = (*ppMblk)->mBlkHdr.mNext;
  971.                     m_free (pInPcbMblk);
  972.                     break; /* jump out of the while loop */
  973.                     }
  974.                 ppMblk = &(*ppMblk)->mBlkHdr.mNext;
  975.                 }
  976.             }
  977.         else if (inm->pInPcbMblk != NULL)
  978.             m_freem (inm->pInPcbMblk); /* free up all pcbs */
  979. if (--inm->inm_refcount == 0) {
  980. /*
  981.  * No remaining claims to this record; let IGMP know that
  982.  * we are leaving the multicast group.
  983.  */
  984. if (_igmpLeaveGrpHook != NULL)
  985.     (*_igmpLeaveGrpHook) (inm); 
  986. /*
  987.  * Notify the network driver to update its multicast reception
  988.  * filter.
  989.  */
  990. ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
  991. ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
  992. inm->inm_addr;
  993. (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
  994.      (caddr_t)&ifr);
  995.                 /* time to delete entry from hash table */
  996.                 mcastHashTblDelete (inm);
  997. }
  998.         /*
  999.  * If there is another socket listening to this group, replace
  1000.  * inm's back-ptr to its Mblk (currently that of socket leaving
  1001.  * the group) with the pointer to the Mblk of the other socket
  1002.  */
  1003.         if ((inm != NULL) && (pInmMblk->mBlkHdr.mNextPkt != NULL))
  1004.     {
  1005.     ppInmMblk = (struct mbuf **)((char *)inm - sizeof (struct mbuf **));
  1006.     *ppInmMblk = pInmMblk->mBlkHdr.mNextPkt;
  1007.     (*ppInmMblk)->mBlkHdr.mNextPkt = NULL;
  1008.     }
  1009.         /* free the mblk & inm, actual free only clRefCnt is 1 */
  1010.         m_free (pInmMblk); 
  1011. splx(s);
  1012. return (OK);
  1013. }
  1014. /*
  1015.  * Return address info for specified internet network.
  1016.  */
  1017. struct in_ifaddr *
  1018. in_iaonnetof(net)
  1019. u_long net;
  1020. {
  1021. register struct in_ifaddr *ia;
  1022. #ifdef VIRTUAL_STACK
  1023. for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  1024. #else
  1025. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  1026. #endif /* VIRTUAL_STACK */
  1027. if (ia->ia_subnet == net)
  1028. return (ia);
  1029. return ((struct in_ifaddr *)0);
  1030. }
  1031. /* multicast hashing functions */
  1032. void mcastHashInit ()
  1033.     {
  1034.     /* initialize the mcast hash table */
  1035.     mCastHashInfo.hashBase =  hashinit (mCastHashTblSize,
  1036.                                         MT_IPMADDR,
  1037.                                         &mCastHashInfo.hashMask);
  1038.     }
  1039. STATUS mcastHashTblInsert
  1040.     (
  1041.     struct in_multi *  pInMulti
  1042.     )
  1043.     {
  1044.     IN_MULTI_HEAD *  inMultiHead;
  1045.     int  s; 
  1046.     s = splnet();
  1047.     inMultiHead = &mCastHashInfo.hashBase[MCAST_HASH(pInMulti->inm_addr.s_addr,
  1048.                                                      pInMulti->inm_ifp,
  1049.                                                      mCastHashInfo.hashMask)];
  1050.     /* insert a multicast address structure into the hash table */
  1051.     LIST_INSERT_HEAD(inMultiHead, pInMulti, inm_hash);
  1052.     
  1053.     splx(s);
  1054.     return (OK); 
  1055.     }
  1056. STATUS mcastHashTblDelete
  1057.     (
  1058.     struct in_multi * pInMulti
  1059.     )
  1060.     {
  1061.     int  s; 
  1062.     s = splnet();
  1063.     LIST_REMOVE(pInMulti, inm_hash);
  1064.     splx(s);
  1065.     return (OK); 
  1066.     }
  1067. struct in_multi * mcastHashTblLookup
  1068.     (
  1069.     int mcastAddr, /* multicast Address always in NBO */
  1070.     struct ifnet *  pIf /* interface pointer */
  1071.     )
  1072.     {
  1073.     IN_MULTI_HEAD *  inMultiHead;
  1074.     IN_MULTI *  pInMulti;
  1075.     int  s;
  1076.     s = splnet();
  1077.     /* search a hash table for the appropriate multicast address tied to
  1078.        a particular network interface
  1079.      */
  1080.     inMultiHead = &mCastHashInfo.hashBase[MCAST_HASH(mcastAddr, pIf,
  1081.                                                      mCastHashInfo.hashMask)];
  1082.     for (pInMulti = inMultiHead->lh_first; pInMulti != NULL;
  1083.          pInMulti = pInMulti->inm_hash.le_next)
  1084.         {
  1085.         if (pInMulti->inm_addr.s_addr == mcastAddr &&
  1086.             pInMulti->inm_ifp == pIf)
  1087.             goto found;
  1088.         }
  1089.     splx(s);
  1090.     return (NULL);
  1091.     found:
  1092.     /*
  1093.      * Move IN_MULTI to head of this hash chain so that it can be
  1094.      * found more quickly in the future.
  1095.      * XXX - this is a pessimization on machines with few
  1096.      * concurrent connections.
  1097.      */
  1098.     if (pInMulti != inMultiHead->lh_first)
  1099.         {
  1100.         LIST_REMOVE(pInMulti, inm_hash);
  1101.         LIST_INSERT_HEAD(inMultiHead, pInMulti, inm_hash);
  1102.         }
  1103.     splx(s);
  1104.     return (pInMulti);
  1105.     }
  1106. #endif