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

VxWorks

开发平台:

C/C++

  1. /* if.c - network interface utility routines */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /* $NetBSD: if.c,v 1.18 1994/10/30 21:48:46 cgd Exp $ */
  5. /*
  6.  * Copyright (c) 1980, 1986, 1993
  7.  * The Regents of the University of California.  All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  * This product includes software developed by the University of
  20.  * California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  *
  37.  * @(#)if.c 8.3 (Berkeley) 1/4/94
  38.  */
  39. /*
  40. modification history
  41. --------------------
  42. 01u,25apr02,vvv  removed unused ifAttachChange (SPR #74391)
  43. 01t,06mar02,vvv  clean up multicast memberships when interface is detached
  44.  (SPR #72486)
  45. 01s,29oct01,wap  ifconf() fails with unit numbers greater than 9 (SPR #31752)
  46. 01r,26oct01,vvv  fixed memory leak in if_dettach (SPR #71081) 
  47. 01q,12oct01,rae  merge from truestack ver 01w base 01m
  48.                  SPR #69112, Windview events, etc.
  49. 01p,30mar01,rae  allow m2 stuff to be excluded (SPR# 65428)
  50. 01o,24oct00,niq  Merging in RFC2233 changes from tor2_0.open_stack-f1 branch.
  51. 01n,17oct00,spm  merged from version 01j of tor2_0_x branch (base version 01h):
  52.                  updated if_attach to report memory allocation failures
  53. 01m,29apr99,pul  Upgraded NPT phase3 code to tor2.0.0
  54. 01l,25mar99,sj   removed logMsg within SIOCSIFASYNCFLAGS ioctl 
  55. 01k,24mar99,ead  Added a call to m2SetIfLastChange() in ifioctl() when the
  56.                  interfaces operational status changes. (SPR #23290)
  57. 01j,19mar99,sj   SIOCSIFASYNCFLAGS ioctl recvd only when we didn't change flags
  58. 01i,18mar99,sj   added SIOCSIFASYNCFLAGS for async flag change report from END
  59. 01h,16jul98,n_s  fixed ifioctl to pass correct flags to driver Ioctl. SPR 21124 
  60. 01g,16dec97,vin  fixed if_dettach SPR 9970.
  61. 01f,10dec97,vin  added spl protection to ifreset, if_dettach, if_attach,
  62.  ifIndexToIfp SPR 9987.
  63. 01e,05oct97,vin  fixed if_dettach, for changes in multicast code.
  64. 01d,12aug97,rjc  made if_index global to support non ip interfaces (SPR 9060).
  65. 01c,02jul97,vin  fixed warnings. added _rtIfaceMsgHook for scaling out routing
  66.  sockets.
  67. 01b,05dec96,vin  moved ifafree() from route.c(), added ifIndexToIfp(),
  68.  deleted ifnet_addrs in ifattach(), made if_index static.
  69.  made ifqmaxlen static, replaced calloc with MALLOC, replaced
  70.  free(..) with FREE(..)
  71. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02t of if.c.
  72.  rewrote if_dettach(), added in_ifaddr_remove in if_dettach
  73. */
  74. /*
  75. DESCRIPTION
  76. */
  77. #include "vxWorks.h"
  78. #include "sys/socket.h"
  79. #include "net/socketvar.h"
  80. #include "net/protosw.h"
  81. /* #include "net/route.h" */
  82. #include "routeEnhLib.h"
  83. #include "net/if_dl.h"
  84. #include "net/if_subr.h"
  85. #include "sys/ioctl.h"
  86. #include "errno.h"
  87. #include "ifIndexLib.h"
  88. #include "net/if.h"
  89. #include "wdLib.h"
  90. #include "net/systm.h"
  91. #include "net/mbuf.h"
  92. #ifdef INET
  93. #include "netinet/in_var.h"
  94. #endif /* INET */
  95. #include "m2Lib.h"
  96. #ifdef WV_INSTRUMENTATION
  97. #ifdef INCLUDE_WVNET
  98. #include "wvNetLib.h"
  99. #endif /* INCLUDE_WVNET */
  100. #endif
  101. #ifdef VIRTUAL_STACK
  102. #include "netinet/vsLib.h"
  103. #endif
  104. #include "logLib.h"
  105. IMPORT STATUS netJobAdd (FUNCPTR, int, int, int, int, int);
  106. extern void pfctlinput(int cmd, struct sockaddr * sa);
  107. extern int sysClkRateGet();
  108. extern void in_ifaddr_remove ();
  109. extern int arpioctl (int cmd, caddr_t data); 
  110. extern int splnet2 (int timeout);
  111. /* XXX temporary fix should be removed after updating all drivers */
  112. extern void ether_ifattach(struct ifnet * ifp);
  113. extern int ether_output (); 
  114. #ifndef VIRTUAL_STACK
  115. IMPORT struct inpcbhead         udb;
  116. #endif
  117. #ifndef VIRTUAL_STACK
  118. struct ifnet *ifnet; /* head of linked list of interfaces */
  119. LOCAL WDOG_ID ifslowtimoWd; /* watchdog timer for slowtimo routine */
  120. #endif /* VIRTUAL_STACK */
  121. /* locals */
  122. static int ifqmaxlen = IFQ_MAXLEN;
  123. static char * sprint_d(unsigned int, char *, int);
  124. #ifdef WV_INSTRUMENTATION
  125. #ifdef INCLUDE_WVNET
  126.     /* Set common fields of event identifiers for this module. */
  127. LOCAL UCHAR wvNetModuleId = WV_NET_IF_MODULE;  /* Value for if.c */
  128. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;  /* Available event filter */
  129. LOCAL ULONG wvNetEventId;  /* Event identifier: see wvNetLib.h */
  130. #endif  /* INCLUDE_WVNET */
  131. #endif
  132. /* forward declarations */
  133. LOCAL void ifMultiDelete (struct ifnet *);
  134. /* globals */
  135. FUNCPTR _m2SetIfLastChange;
  136. FUNCPTR _m2IfTableUpdate;
  137. /*
  138.  * Network interface utility routines.
  139.  *
  140.  * Routines with ifa_ifwith* names take sockaddr *'s as
  141.  * parameters.
  142.  */
  143. void ifinit()
  144.     {
  145.     register struct ifnet *ifp;
  146. #ifdef WV_INSTRUMENTATION
  147. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  148.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 0, 8,
  149.                      WV_NETEVENT_IFINIT_START)
  150. #endif  /* INCLUDE_WVNET */
  151. #endif
  152. #ifdef VIRTUAL_STACK
  153.     if (_ifnet != NULL)
  154. #else
  155.     if (ifnet != NULL)
  156. #endif
  157.         {
  158. #ifdef VIRTUAL_STACK
  159.         for (ifp = _ifnet; ifp; ifp = ifp->if_next)
  160. #else
  161.         for (ifp = ifnet; ifp; ifp = ifp->if_next)
  162. #endif
  163.             if (ifp->if_snd.ifq_maxlen == 0)
  164.                 ifp->if_snd.ifq_maxlen = ifqmaxlen;
  165.         }
  166.     /* XXX using watchdogs good idea? -gae */
  167.     ifslowtimoWd = wdCreate ();
  168. #ifdef VIRTUAL_STACK
  169.     if_slowtimo (myStackNum);
  170. #else
  171.     if_slowtimo ();
  172. #endif
  173.     }
  174. /*
  175.  * Actuall interface reset invocation.
  176.  */
  177. void ifreset2 ()
  178.     {
  179.     register struct ifnet *ifp;
  180.     register struct ifnet *ifpnext;
  181. #ifdef VIRTUAL_STACK
  182.     ifp = _ifnet;
  183. #else
  184.     ifp = ifnet;
  185. #endif
  186.     while (ifp)
  187.         {
  188.         ifpnext = ifp->if_next;
  189.         if (ifp->if_reset)
  190.             (*ifp->if_reset)(ifp->if_unit);
  191.         ifp = ifpnext;
  192.         }
  193.     }
  194. /*
  195.  * Call each interface on a reset.
  196.  */
  197. void ifreset ()
  198.     {
  199.     int  s;
  200. #ifdef WV_INSTRUMENTATION
  201. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  202.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 1, 9,
  203.                          WV_NETEVENT_IFRESET_START)
  204. #endif  /* INCLUDE_WVNET */
  205. #endif
  206.     s = splnet ();
  207.     ifreset2();
  208.     splx (s);
  209.     }
  210. /*
  211.  * For rebootHook use only - Immediate i/f reset
  212.  *
  213.  * WARNING:  Calling this routine that does not wait spl semaphore
  214.  * is a violation of mutual exclusion and will cause problems in a
  215.  * running system.
  216.  * This routine should only be used if the system is being rebooted
  217.  * (i.e. when called from a reboot hook) or if the application has
  218.  * very specific knowledge of the state of all ENDs in the system.
  219.  */
  220. void ifresetImmediate ()
  221.     {
  222.     int  s;
  223. #ifdef WV_INSTRUMENTATION
  224. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  225.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 1, 9,
  226.                          WV_NETEVENT_IFRESET_START)
  227. #endif  /* INCLUDE_WVNET */
  228. #endif
  229.     s = splnet2 (0); /* don't wait spl semaphore */
  230.     ifreset2();
  231.     splx(s);
  232.     }
  233. /*
  234.  * Attach an interface to the list of "active" interfaces.
  235.  */
  236. STATUS if_attach(ifp)
  237.     struct ifnet *ifp;
  238.     {
  239.     unsigned socksize, ifasize;
  240.     int namelen, unitlen, masklen;
  241.     char workbuf[12], *unitname;
  242. #ifdef VIRTUAL_STACK
  243.     register struct ifnet **p = &_ifnet;
  244. #else
  245.     register struct ifnet **p = &ifnet;
  246. #endif
  247.     register struct sockaddr_dl *sdl;
  248.     register struct ifaddr *ifa;
  249.     extern void link_rtrequest();
  250.     int  s;
  251. #ifdef WV_INSTRUMENTATION
  252. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  253.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 2, 10,
  254.                      WV_NETEVENT_IFATTACH_START, ifp)
  255. #endif  /* INCLUDE_WVNET */
  256. #endif
  257.     /* make interface not use trailer protocol by default */
  258.     ifp->if_flags |= IFF_NOTRAILERS;
  259.     /* make send queue maxlen be default if none specified;
  260.      * this relaxes the requirement that all interfaces be attached
  261.      * before calling ifinit */
  262.     if (ifp->if_snd.ifq_maxlen == 0)
  263. ifp->if_snd.ifq_maxlen = ifqmaxlen;
  264.     /*
  265.      * create a Link Level name for this device
  266.      */
  267.     unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
  268.     namelen = strlen(ifp->if_name);
  269.     unitlen = strlen(unitname);
  270. #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  271.     masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
  272.     unitlen + namelen;
  273.     socksize = masklen + ifp->if_addrlen;
  274. #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  275.     socksize = ROUNDUP(socksize);
  276.     if (socksize < sizeof(*sdl))
  277. socksize = sizeof(*sdl);
  278.     ifasize = sizeof(*ifa) + 2 * socksize;
  279.     MALLOC (ifa, struct ifaddr *, ifasize, MT_IFADDR, M_WAIT); 
  280.     if (ifa == 0)
  281. return (ERROR);
  282.     /* Make interface globally visible after all memory is allocated. */
  283.     s = splnet ();
  284.     while (*p)
  285.         p = &((*p)->if_next);
  286.     splx (s);
  287.     *p = ifp;
  288.     ifp->if_index = ifIndexAlloc();
  289.     bzero((caddr_t)ifa, ifasize);
  290.     sdl = (struct sockaddr_dl *)(ifa + 1);
  291.     sdl->sdl_len = socksize;
  292.     sdl->sdl_family = AF_LINK;
  293.     bcopy(ifp->if_name, sdl->sdl_data, namelen);
  294.     bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
  295.     sdl->sdl_nlen = (namelen += unitlen);
  296.     sdl->sdl_index = ifp->if_index;
  297.     sdl->sdl_type = ifp->if_type;
  298.     ifa->ifa_ifp = ifp;
  299.     ifa->ifa_next = ifp->if_addrlist;
  300.     ifa->ifa_rtrequest = link_rtrequest;
  301.     ifp->if_addrlist = ifa;
  302.     ifa->ifa_addr = (struct sockaddr *)sdl;
  303.     sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  304.     ifa->ifa_netmask = (struct sockaddr *)sdl;
  305.     sdl->sdl_len = masklen;
  306.     while (namelen != 0)
  307. sdl->sdl_data[--namelen] = 0xff;
  308.     if (_m2IfTableUpdate)
  309.         _m2IfTableUpdate(ifp, M2_IF_TABLE_INSERT, 0, 0);
  310.     /* XXX Temporary fix before changing ethernet drivers */
  311.     s = splnet ();
  312.     if (ifp->if_output == ether_output)
  313. ether_ifattach (ifp);
  314.     splx (s);
  315.     return (OK);
  316.     }
  317. /***************************************************************************
  318. *
  319. * if_dettach - dettaches an interface from the linked list of interfaces
  320. *
  321. * if_dettach is used to dettach an interface from the linked list of
  322. * all available interfaces.  This function needs to be used with
  323. * if_down () when shutting down a network interface.
  324. */
  325. void if_dettach (ifp)
  326.     struct ifnet *ifp; /* inteface pointer */
  327.     {
  328.     FAST struct ifnet ** pPtrIfp;
  329.     FAST struct ifaddr *  pIfAddr;
  330.     FAST struct ifaddr ** pPtrIfAddr;
  331.     int  s;
  332. #ifdef WV_INSTRUMENTATION
  333. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  334.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 3, 11,
  335.                      WV_NETEVENT_IFDETACH_START, ifp)
  336. #endif  /* INCLUDE_WVNET */
  337. #endif
  338. #ifdef VIRTUAL_STACK
  339.     pPtrIfp = &_ifnet;
  340. #else
  341.     pPtrIfp = &ifnet;
  342. #endif
  343.     s = splnet ();
  344.     while (*pPtrIfp != NULL)
  345. {
  346. if (*pPtrIfp == ifp)
  347.     {
  348.     pPtrIfAddr = &(*pPtrIfp)->if_addrlist; 
  349.     while (*pPtrIfAddr != NULL)
  350. {
  351. pIfAddr = *pPtrIfAddr; 
  352. *pPtrIfAddr = (*pPtrIfAddr)->ifa_next; 
  353. #ifdef INET
  354. if (pIfAddr->ifa_addr->sa_family == AF_INET)
  355.     in_ifaddr_remove (pIfAddr);
  356.         else
  357. #endif
  358.     IFAFREE (pIfAddr);
  359. }
  360. #ifdef INET
  361.             if ((*pPtrIfp)->pInmMblk != NULL)
  362.                 in_delmulti ((*pPtrIfp)->pInmMblk, NULL);
  363.     if (ifp->if_flags & IFF_MULTICAST)
  364.                 ifMultiDelete (ifp);
  365. #endif /* INET */
  366.     *pPtrIfp = (*pPtrIfp)->if_next; 
  367.             /* Notify MIB-II of change */
  368.             if (_m2IfTableUpdate)
  369.                 _m2IfTableUpdate(ifp, M2_IF_TABLE_REMOVE, 0, 0);
  370.     break; 
  371.     }
  372. pPtrIfp = &(*pPtrIfp)->if_next; 
  373. }
  374.     splx (s);
  375.     }
  376. /*******************************************************************************
  377. *
  378. * ifIndexToIfp - obtain the ifnet pointer from the index
  379. *
  380. * This function obtains the ifnet pointer from the if_index.
  381. * The interface index is unique for every new interface added.
  382. * NOMANUAL
  383. *
  384. * RETURNS ifnet/NULL
  385. */
  386. struct ifnet * ifIndexToIfp
  387.     (
  388.     int ifIndex /* index of the interface to find */
  389.     )
  390.     {
  391.     register struct ifnet *  pIfp;
  392.     int  s;
  393.     s = splnet ();
  394.     /* traverse the list of ifnet structures in the system */
  395. #ifdef VIRTUAL_STACK
  396.     for (pIfp = _ifnet; pIfp != NULL; pIfp = pIfp->if_next)
  397. #else
  398.     for (pIfp = ifnet; pIfp != NULL; pIfp = pIfp->if_next)
  399. #endif
  400. {
  401. if (pIfp->if_index == ifIndex)
  402.     break;
  403. }
  404.     splx (s);
  405.     return (pIfp); 
  406.     }
  407. /*
  408.  * Locate an interface based on a complete address.
  409.  */
  410. /*ARGSUSED*/
  411. struct ifaddr *
  412. ifa_ifwithaddr(addr)
  413. register struct sockaddr *addr;
  414. {
  415. register struct ifnet *ifp;
  416. register struct ifaddr *ifa;
  417. #define equal(a1, a2) 
  418.   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  419. #ifdef VIRTUAL_STACK
  420. for (ifp = _ifnet; ifp; ifp = ifp->if_next)
  421. #else
  422. for (ifp = ifnet; ifp; ifp = ifp->if_next)
  423. #endif
  424.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  425. if (ifa->ifa_addr->sa_family != addr->sa_family)
  426. continue;
  427. if (equal(addr, ifa->ifa_addr))
  428. return (ifa);
  429. if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  430.     equal(ifa->ifa_broadaddr, addr))
  431. return (ifa);
  432. }
  433. return ((struct ifaddr *)0);
  434. }
  435. /*
  436.  * Locate the point to point interface with a given destination address.
  437.  */
  438. /*ARGSUSED*/
  439. struct ifaddr *
  440. ifa_ifwithdstaddr(addr)
  441. register struct sockaddr *addr;
  442. {
  443. register struct ifnet *ifp;
  444. register struct ifaddr *ifa;
  445. #ifdef VIRTUAL_STACK
  446. for (ifp = _ifnet; ifp; ifp = ifp->if_next) 
  447. #else
  448. for (ifp = ifnet; ifp; ifp = ifp->if_next) 
  449. #endif
  450.     if (ifp->if_flags & IFF_POINTOPOINT)
  451. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  452. if (ifa->ifa_addr->sa_family != addr->sa_family)
  453. continue;
  454. if (equal(addr, ifa->ifa_dstaddr))
  455. return (ifa);
  456. }
  457. return ((struct ifaddr *)0);
  458. }
  459. /*
  460.  * Find an interface on a specific network.  If many, choice
  461.  * is most specific found.
  462.  */
  463. struct ifaddr *
  464. ifa_ifwithnet(addr)
  465. struct sockaddr *addr;
  466. {
  467. register struct ifnet *ifp;
  468. register struct ifaddr *ifa;
  469. struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
  470. u_int af = addr->sa_family;
  471. char *addr_data = addr->sa_data, *cplim;
  472. if (af == AF_LINK) {
  473.     register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  474.     /* eliminated need for ifnet_addrs array*/     
  475.     if (ifIndexTest(sdl->sdl_index))
  476. {
  477. ifp = ifIndexToIfp (sdl->sdl_index); 
  478.                 if (ifp == NULL)
  479.                     {
  480.                     logMsg("ifa_ifwithnet: NULL ifp for index:%dn",
  481.                            (int)sdl->sdl_index, 0, 0, 0, 0, 0);
  482.                     return(NULL);
  483.                     }
  484. for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
  485.     if (ifa->ifa_addr->sa_family == af)
  486. break; 
  487. return (ifa); 
  488. }
  489. }
  490. #ifdef VIRTUAL_STACK
  491. for (ifp = _ifnet; ifp; ifp = ifp->if_next)
  492. #else
  493. for (ifp = ifnet; ifp; ifp = ifp->if_next)
  494. #endif
  495.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  496. register char *cp, *cp2, *cp3;
  497. if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
  498. next: continue;
  499. cp = addr_data;
  500. cp2 = ifa->ifa_addr->sa_data;
  501. cp3 = ifa->ifa_netmask->sa_data;
  502. cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  503. while (cp3 < cplim)
  504. if ((*cp++ ^ *cp2++) & *cp3++)
  505. goto next;
  506. if (ifa_maybe == 0 ||
  507.     rn_refines((caddr_t)ifa->ifa_netmask,
  508.     (caddr_t)ifa_maybe->ifa_netmask))
  509. ifa_maybe = ifa;
  510.     }
  511. return (ifa_maybe);
  512. }
  513. /*
  514.  * Find an interface using a specific address family
  515.  */
  516. struct ifaddr *
  517. ifa_ifwithaf(af)
  518. register int af;
  519. {
  520. register struct ifnet *ifp;
  521. register struct ifaddr *ifa;
  522. #ifdef VIRTUAL_STACK
  523. for (ifp = _ifnet; ifp; ifp = ifp->if_next)
  524. #else
  525. for (ifp = ifnet; ifp; ifp = ifp->if_next)
  526. #endif
  527.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  528. if (ifa->ifa_addr->sa_family == af)
  529. return (ifa);
  530. return ((struct ifaddr *)0);
  531. }
  532. /*
  533.  * Find an interface address specific to an interface best matching
  534.  * a given address.
  535.  */
  536. struct ifaddr *
  537. ifaof_ifpforaddr(addr, ifp)
  538. struct sockaddr *addr;
  539. register struct ifnet *ifp;
  540. {
  541. register struct ifaddr *ifa;
  542. register char *cp, *cp2, *cp3;
  543. register char *cplim;
  544. struct ifaddr *ifa_maybe = 0;
  545. u_int af = addr->sa_family;
  546. if (af >= AF_MAX)
  547. return (0);
  548. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  549. if (ifa->ifa_addr->sa_family != af)
  550. continue;
  551. ifa_maybe = ifa;
  552. if (ifa->ifa_netmask == 0) {
  553. if (equal(addr, ifa->ifa_addr) ||
  554.     (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  555. return (ifa);
  556. continue;
  557. }
  558. cp = addr->sa_data;
  559. cp2 = ifa->ifa_addr->sa_data;
  560. cp3 = ifa->ifa_netmask->sa_data;
  561. cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  562. for (; cp3 < cplim; cp3++)
  563. if ((*cp++ ^ *cp2++) & *cp3)
  564. break;
  565. if (cp3 == cplim)
  566. return (ifa);
  567. }
  568. return (ifa_maybe);
  569. }
  570. /* 
  571.  * Find an interface address for a specified destination or gateway
  572.  */
  573. struct ifaddr *
  574. ifa_ifwithroute(flags, dst, gateway)
  575. int flags;
  576. struct sockaddr *dst, *gateway;
  577. {
  578. register struct ifaddr *ifa;
  579. if ((flags & RTF_GATEWAY) == 0) {
  580. /*
  581.  * If we are adding a route to an interface,
  582.  * and the interface is a pt to pt link
  583.  * we should search for the destination
  584.  * as our clue to the interface.  Otherwise
  585.  * we can use the local address.
  586.  */
  587. ifa = 0;
  588. if (flags & RTF_HOST) 
  589. ifa = ifa_ifwithdstaddr(dst);
  590. if (ifa == 0)
  591. ifa = ifa_ifwithaddr(gateway);
  592. } else {
  593. /*
  594.  * If we are adding a route to a remote net
  595.  * or host, the gateway may still be on the
  596.  * other end of a pt to pt link.
  597.  */
  598. ifa = ifa_ifwithdstaddr(gateway);
  599. }
  600. if (ifa == 0)
  601. ifa = ifa_ifwithnet(gateway);
  602. if (ifa == 0) {
  603. struct rtentry *rt = rtalloc1(dst, 0);
  604. if (rt == 0)
  605. return (0);
  606. rt->rt_refcnt--;
  607. if ((ifa = rt->rt_ifa) == 0)
  608. return (0);
  609. }
  610. if (ifa->ifa_addr->sa_family != dst->sa_family) {
  611. struct ifaddr *oifa = ifa;
  612. ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
  613. if (ifa == 0)
  614. ifa = oifa;
  615. }
  616. return (ifa);
  617. }
  618. /* free the interface address */
  619. void
  620. ifafree(ifa)
  621. register struct ifaddr *ifa;
  622. {
  623. if (ifa == NULL)
  624.                 {   
  625. #ifdef WV_INSTRUMENTATION
  626. #ifdef INCLUDE_WVNET  /* WV_NET_EMERGENCY event */
  627.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 0, 1,
  628.                      WV_NETEVENT_IFAFREE_PANIC)
  629. #endif  /* INCLUDE_WVNET */
  630. #endif
  631. panic("ifafree");
  632.                 }
  633. if (ifa->ifa_refcnt == 0)
  634. {
  635. FREE(ifa, MT_IFADDR);  
  636. }
  637. else
  638. ifa->ifa_refcnt--;
  639. }
  640. /*
  641.  * Default action when installing a route with a Link Level gateway.
  642.  * Lookup an appropriate real ifa to point to.
  643.  * This should be moved to /sys/net/link.c eventually.
  644.  */
  645. void
  646. link_rtrequest(cmd, rt, sa)
  647. int cmd;
  648. register struct rtentry *rt;
  649. struct sockaddr *sa;
  650. {
  651. register struct ifaddr *ifa;
  652. struct sockaddr *dst;
  653. struct ifnet *ifp;
  654. if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  655.     ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  656.          {
  657. /* XXX - This event does not occur because this routine is never called
  658.  *       by the existing network stack. It is always replaced with the
  659.  *       arp_rtrequest routine for all Ethernet devices. 
  660. #ifdef WV_INSTRUMENTATION
  661. #ifdef INCLUDE_WVNET    /@ WV_NET_WARNING event @/
  662.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_WARNING, 0, 5,
  663.                      WV_NETEVENT_LINKRTREQ_FAIL)
  664. #endif  /@ INCLUDE_WVNET @/
  665. #endif
  666.   * XXX - end of unused event
  667.   */
  668. return;
  669.         }
  670. if ((ifa = ifaof_ifpforaddr(dst, ifp))) {
  671. IFAFREE(rt->rt_ifa);
  672. rt->rt_ifa = ifa;
  673. ifa->ifa_refcnt++;
  674. if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
  675. ifa->ifa_rtrequest(cmd, rt, sa);
  676. }
  677. }
  678. /*
  679.  * Mark an interface down and notify protocols of
  680.  * the transition.
  681.  * NOTE: must be called at splnet or eqivalent.
  682.  */
  683. void
  684. if_down(ifp)
  685. register struct ifnet *ifp;
  686. {
  687. register struct ifaddr *ifa;
  688. #ifdef WV_INSTRUMENTATION
  689. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  690.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 4, 12,
  691.                      WV_NETEVENT_IFDOWN_START, ifp)
  692. #endif  /* INCLUDE_WVNET */
  693. #endif
  694. ifp->if_flags &= ~IFF_UP;
  695. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  696. pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  697. if_qflush(&ifp->if_snd);
  698.         if (rtIfaceMsgHook) 
  699.             (*rtIfaceMsgHook) (ifp);
  700. }
  701. /*
  702.  * Mark an interface up and notify protocols of
  703.  * the transition.
  704.  * NOTE: must be called at splnet or equivalent.
  705.  */
  706. void
  707. if_up(ifp)
  708. register struct ifnet *ifp;
  709. {
  710. #ifdef WV_INSTRUMENTATION
  711. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  712.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 5, 13,
  713.                      WV_NETEVENT_IFUP_START, ifp)
  714. #endif  /* INCLUDE_WVNET */
  715. #endif
  716. ifp->if_flags |= IFF_UP;
  717. #ifdef notyet
  718.         {
  719. register struct ifaddr *ifa;
  720. /* this has no effect on IP, and will kill all ISO connections XXX */
  721. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  722. pfctlinput(PRC_IFUP, ifa->ifa_addr);
  723.         }
  724. #endif
  725.         if (rtIfaceMsgHook) 
  726.             (*rtIfaceMsgHook) (ifp);
  727. }
  728. /*
  729.  * Flush an interface queue.
  730.  */
  731. void
  732. if_qflush(ifq)
  733. register struct ifqueue *ifq;
  734. {
  735. register struct mbuf *m, *n;
  736. n = ifq->ifq_head;
  737. while ((m = n)) {
  738. n = m->m_act;
  739. m_freem(m);
  740. }
  741. ifq->ifq_head = 0;
  742. ifq->ifq_tail = 0;
  743. ifq->ifq_len = 0;
  744. }
  745. void if_slowtimoRestart
  746.     (
  747.     int stackNum
  748.     )
  749.     {
  750.     netJobAdd ((FUNCPTR)if_slowtimo, stackNum, 0, 0, 0, 0);
  751.     }
  752. /*
  753.  * Handle interface watchdog timer routines.  Called
  754.  * from softclock, we decrement timers (if set) and
  755.  * call the appropriate interface routine on expiration.
  756.  */
  757. void if_slowtimo
  758.     (
  759. #ifdef VIRTUAL_STACK
  760.     int stackNum
  761. #endif /* VIRTUAL_STACK */    
  762.     )
  763.     {
  764.     register struct ifnet *ifp;
  765.     int s;
  766. #ifdef VIRTUAL_STACK
  767.     virtualStackNumTaskIdSet(stackNum);
  768. #endif
  769.     s = splnet();
  770. #ifdef VIRTUAL_STACK
  771.     if (_ifnet != NULL)
  772. #else
  773.     if (ifnet != NULL)
  774. #endif
  775.         {
  776. #ifdef VIRTUAL_STACK
  777.         for (ifp = _ifnet; ifp; ifp = ifp->if_next)
  778. #else
  779.         for (ifp = ifnet; ifp; ifp = ifp->if_next)
  780. #endif
  781.             {
  782.             if (ifp->if_timer == 0 || --ifp->if_timer)
  783.                 continue;
  784.             if (ifp->if_watchdog)
  785.                 {
  786. #ifdef WV_INSTRUMENTATION
  787. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  788.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 0, 6,
  789.                      WV_NETEVENT_IFWATCHDOG, ifp)
  790. #endif  /* INCLUDE_WVNET */
  791. #endif
  792.                 (*ifp->if_watchdog)(ifp->if_unit);
  793.                 }
  794.             }
  795.         }
  796.     splx (s);
  797.     /* XXX using watchdogs good idea? calculate clock rate once only -gae */
  798.     wdStart (ifslowtimoWd, sysClkRateGet()/IFNET_SLOWHZ,
  799. #ifdef VIRTUAL_STACK
  800.     (FUNCPTR) if_slowtimoRestart, (int) stackNum);
  801. #else
  802.     (FUNCPTR) netJobAdd, (int) if_slowtimo);
  803. #endif
  804.     }
  805. /* ifunit () has been moved to ifLib.c */
  806. /*
  807.  * Interface ioctls.
  808.  */
  809. int
  810. ifioctl(so, cmd, data)
  811. struct socket *so;
  812. u_long cmd;
  813. caddr_t data;
  814. {
  815. register struct ifnet *ifp;
  816. register struct ifreq *ifr;
  817. #ifdef WV_INSTRUMENTATION
  818. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  819.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 1, 7,
  820.                      WV_NETEVENT_IFIOCTL_START, so->so_fd, cmd)
  821. #endif  /* INCLUDE_WVNET */
  822. #endif
  823. switch (cmd) {
  824. case SIOCGIFCONF:
  825. case OSIOCGIFCONF:
  826. return (ifconf(cmd, data));
  827. #ifdef INET
  828. case SIOCSARP:
  829. case SIOCDARP:
  830. /* FALL THROUGH */
  831. case SIOCGARP:
  832. return (arpioctl(cmd, data));
  833. #endif /* INET */
  834. }
  835. ifr = (struct ifreq *)data;
  836. ifp = ifunit(ifr->ifr_name);
  837. if (ifp == 0)
  838.         {
  839. #ifdef WV_INSTRUMENTATION
  840. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  841.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 0, 3,
  842.                          WV_NETEVENT_IFIOCTL_BADIFNAME, so->so_fd, cmd)
  843. #endif  /* INCLUDE_WVNET */
  844. #endif
  845. return (ENXIO);
  846.         }
  847. switch (cmd) {
  848. case SIOCGIFFLAGS:
  849. ifr->ifr_flags = ifp->if_flags;
  850. break;
  851. case SIOCGIFMETRIC:
  852. ifr->ifr_metric = ifp->if_metric;
  853. break;
  854. case SIOCSIFASYNCFLAGS:
  855. /*
  856.  * we got a asynchronous flag change report from the interface;
  857.  */
  858. /* FALL THROUGH */
  859. case SIOCSIFFLAGS:
  860. if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
  861. int s = splimp();
  862. if_down(ifp);
  863. splx(s);
  864.                         if (_m2SetIfLastChange)
  865.                             _m2SetIfLastChange(ifp->if_index);
  866. }
  867. if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
  868. int s = splimp();
  869. if_up(ifp);
  870. splx(s);
  871.                         if (_m2SetIfLastChange)
  872.                             _m2SetIfLastChange(ifp->if_index);
  873. }
  874. ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  875. (ifr->ifr_flags &~ IFF_CANTCHANGE);
  876. ifr->ifr_flags = ifp->if_flags;
  877. /* command the interface only if we are initiating the change */
  878. if ((cmd == SIOCSIFFLAGS) &&  ifp->if_ioctl)
  879. (void) (*ifp->if_ioctl)(ifp, cmd, data);
  880. break;
  881. case SIOCSIFMETRIC:
  882. ifp->if_metric = ifr->ifr_metric;
  883. break;
  884. case SIOCADDMULTI:
  885. case SIOCDELMULTI:
  886. if (ifp->if_ioctl == 0)
  887. return (EOPNOTSUPP);
  888. return ((*ifp->if_ioctl)(ifp, cmd, data));
  889. default:
  890. if (so->so_proto == 0)
  891.                 {
  892. #ifdef WV_INSTRUMENTATION
  893. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  894.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 1, 4,
  895.                          WV_NETEVENT_IFIOCTL_NOPROTO, so->so_fd, cmd)
  896. #endif  /* INCLUDE_WVNET */
  897. #endif
  898. return (EOPNOTSUPP);
  899.                 }
  900. #ifndef COMPAT_43
  901. return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  902. cmd, data, ifp));
  903. #else
  904.     {
  905.                 int error = 0;
  906. int ocmd = cmd;
  907. switch (cmd) {
  908. case SIOCSIFDSTADDR:
  909. case SIOCSIFADDR:
  910. case SIOCSIFBRDADDR:
  911. case SIOCSIFNETMASK:
  912. #if _BYTE_ORDER != _BIG_ENDIAN
  913. if (ifr->ifr_addr.sa_family == 0 &&
  914.     ifr->ifr_addr.sa_len < 16) {
  915. ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  916. ifr->ifr_addr.sa_len = 16;
  917. }
  918. #else
  919. if (ifr->ifr_addr.sa_len == 0)
  920. ifr->ifr_addr.sa_len = 16;
  921. #endif
  922. break;
  923. case OSIOCGIFADDR:
  924. cmd = SIOCGIFADDR;
  925. break;
  926. case OSIOCGIFDSTADDR:
  927. cmd = SIOCGIFDSTADDR;
  928. break;
  929. case OSIOCGIFBRDADDR:
  930. cmd = SIOCGIFBRDADDR;
  931. break;
  932. case OSIOCGIFNETMASK:
  933. cmd = SIOCGIFNETMASK;
  934. }
  935. error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  936.     cmd, data, ifp));
  937. switch (ocmd) {
  938. case OSIOCGIFADDR:
  939. case OSIOCGIFDSTADDR:
  940. case OSIOCGIFBRDADDR:
  941. case OSIOCGIFNETMASK:
  942. *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  943. }
  944. return (error);
  945.     }
  946. #endif
  947. }
  948. return (0);
  949. }
  950. /*
  951.  * Return interface configuration
  952.  * of system.  List may be used
  953.  * in later ioctl's (above) to get
  954.  * other information.
  955.  */
  956. /*ARGSUSED*/
  957. int
  958. ifconf(cmd, data)
  959. int cmd;
  960. caddr_t data;
  961. {
  962. register struct ifconf *ifc = (struct ifconf *)data;
  963. #ifdef VIRTUAL_STACK
  964. register struct ifnet *ifp = _ifnet;
  965. #else
  966. register struct ifnet *ifp = ifnet;
  967. #endif
  968. register struct ifaddr *ifa;
  969. register char *cp, *ep;
  970. struct ifreq ifr, *ifrp;
  971. int space = ifc->ifc_len, error = 0;
  972. char workbuf[12], *unitname;
  973. ifrp = ifc->ifc_req;
  974. ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
  975. for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
  976. strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2);
  977. for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
  978. continue;
  979. unitname = sprint_d ((u_int)ifp->if_unit, workbuf,
  980.      sizeof(workbuf));
  981. for (; cp <= ep && *unitname != ''; *cp++ = *unitname++);
  982. if (*unitname != '') {
  983. error = ENAMETOOLONG;
  984. break;
  985. }
  986. *cp = '';
  987. if ((ifa = ifp->if_addrlist) == 0) {
  988. bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
  989. error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  990.     sizeof(ifr));
  991. if (error)
  992. break;
  993. space -= sizeof (ifr), ifrp++;
  994. } else 
  995.     for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
  996. register struct sockaddr *sa = ifa->ifa_addr;
  997. #ifdef COMPAT_43
  998. if (cmd == OSIOCGIFCONF) {
  999. struct osockaddr *osa =
  1000.  (struct osockaddr *)&ifr.ifr_addr;
  1001. ifr.ifr_addr = *sa;
  1002. osa->sa_family = sa->sa_family;
  1003. error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  1004. sizeof (ifr));
  1005. ifrp++;
  1006. } else
  1007. #endif
  1008. if (sa->sa_len <= sizeof(*sa)) {
  1009. ifr.ifr_addr = *sa;
  1010. error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  1011. sizeof (ifr));
  1012. ifrp++;
  1013. } else {
  1014. space -= sa->sa_len - sizeof(*sa);
  1015. if (space < sizeof (ifr))
  1016. break;
  1017. error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  1018. sizeof (ifr.ifr_name));
  1019. if (error == 0)
  1020.     error = copyout((caddr_t)sa,
  1021.       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  1022. ifrp = (struct ifreq *)
  1023. (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
  1024. }
  1025. if (error)
  1026. break;
  1027. space -= sizeof (ifr);
  1028. }
  1029. }
  1030. ifc->ifc_len -= space;
  1031. return (error);
  1032. }
  1033. /*
  1034.  * Set/clear promiscuous mode on interface ifp based on the truth value
  1035.  * of pswitch.  The calls are reference counted so that only the first
  1036.  * "on" request actually has an effect, as does the final "off" request.
  1037.  * Results are undefined if the "off" and "on" requests are not matched.
  1038.  */
  1039. int
  1040. ifpromisc(ifp, pswitch)
  1041. struct ifnet *ifp;
  1042. int pswitch;
  1043. {
  1044. struct ifreq ifr;
  1045. #ifdef WV_INSTRUMENTATION
  1046. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  1047.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 6, 14,
  1048.                      WV_NETEVENT_IFPROMISC_START, ifp, pswitch)
  1049. #endif  /* INCLUDE_WVNET */
  1050. #endif
  1051. /*
  1052.  * If the device is not configured up, we cannot put it in
  1053.  * promiscuous mode.
  1054.  */
  1055. if ((ifp->if_flags & IFF_UP) == 0)
  1056.         {
  1057. #ifdef WV_INSTRUMENTATION
  1058. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1059.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 0, 2,
  1060.                      WV_NETEVENT_IFPROMISC_FAIL, ifp, pswitch)
  1061. #endif  /* INCLUDE_WVNET */
  1062. #endif
  1063. return (ENETDOWN);
  1064.         }
  1065. if (pswitch) {
  1066. if (ifp->if_pcount++ != 0)
  1067. return (0);
  1068. ifp->if_flags |= IFF_PROMISC;
  1069. } else {
  1070. if (--ifp->if_pcount > 0)
  1071. return (0);
  1072. ifp->if_flags &= ~IFF_PROMISC;
  1073. }
  1074. ifr.ifr_flags = ifp->if_flags;
  1075. return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
  1076. }
  1077. static char *
  1078. sprint_d(n, buf, buflen)
  1079. u_int n;
  1080. char *buf;
  1081. int buflen;
  1082. {
  1083. register char *cp = buf + buflen - 1;
  1084. *cp = 0;
  1085. do {
  1086. cp--;
  1087. *cp = "0123456789"[n % 10];
  1088. n /= 10;
  1089. } while (n != 0);
  1090. return (cp);
  1091. }
  1092. /******************************************************************************
  1093. *
  1094. * ifMultiDelete - deletes multicast membership based on interface
  1095. *
  1096. * This routine takes an interface and deletes multicast group membership on
  1097. * all sockets for the groups using the specified interface.
  1098. *
  1099. * RETURNS: N/A
  1100. *
  1101. * NOMANUAL
  1102. *
  1103. */
  1104. void ifMultiDelete
  1105.     (
  1106.     struct ifnet *pIf
  1107.     )
  1108.     {
  1109.     struct inpcb       *pInpcb;
  1110.     struct mBlk        **ppMblk;
  1111.     struct mBlk        *pInm;
  1112.     struct in_multi    *inm;
  1113.     struct ip_moptions *pImo;
  1114.     /* Search all open UDP sockets */
  1115.     for (pInpcb = udb.lh_first; pInpcb != NULL; 
  1116.  pInpcb = pInpcb->inp_list.le_next)
  1117.         {
  1118. pImo = pInpcb->inp_moptions;
  1119.         /* No multicast memberships on this socket. */
  1120. if ((pImo == NULL) || (pImo->imo_num_memberships == 0))
  1121.     continue;
  1122. ppMblk = &pImo->pInmMblk;
  1123.         /* Search list of multicast memberships on this socket */
  1124. while (*ppMblk)
  1125.     {
  1126.     inm = mtod (*ppMblk, struct in_multi *);
  1127.     if (inm->inm_ifp == pIf)
  1128. {
  1129. pInm = *ppMblk;
  1130. *ppMblk = (*ppMblk)->mBlkHdr.mNext;  /* delete from list */
  1131.         in_delmulti (pInm, pInpcb);
  1132. pImo->imo_num_memberships--;
  1133. continue;
  1134. }
  1135.     ppMblk = &(*ppMblk)->mBlkHdr.mNext;
  1136.     }
  1137. /* If all options have default values, no need to keep ip_moptions. */
  1138.         if (pImo->imo_num_memberships == 0 &&
  1139.     pImo->imo_multicast_ifp == NULL &&
  1140.     pImo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
  1141.     pImo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP)
  1142.     {
  1143.     FREE (pImo, MT_IPMOPTS);
  1144.     pInpcb->inp_moptions = NULL;
  1145.     }
  1146. }
  1147.     return;
  1148.     }