The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/igmp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: igmp.c,v 1.43 2006/10/05 17:35:19 tls Exp $    */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Internet Group Management Protocol (IGMP) routines.
   34  *
   35  * Written by Steve Deering, Stanford, May 1988.
   36  * Modified by Rosen Sharma, Stanford, Aug 1994.
   37  * Modified by Bill Fenner, Xerox PARC, Feb 1995.
   38  *
   39  * MULTICAST Revision: 1.3
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.43 2006/10/05 17:35:19 tls Exp $");
   44 
   45 #include "opt_mrouting.h"
   46 
   47 #include <sys/param.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/socket.h>
   50 #include <sys/protosw.h>
   51 #include <sys/systm.h>
   52 
   53 #include <net/if.h>
   54 #include <net/route.h>
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/in_var.h>
   58 #include <netinet/in_systm.h>
   59 #include <netinet/ip.h>
   60 #include <netinet/ip_var.h>
   61 #include <netinet/igmp.h>
   62 #include <netinet/igmp_var.h>
   63 
   64 #include <machine/stdarg.h>
   65 
   66 #define IP_MULTICASTOPTS        0
   67 
   68 POOL_INIT(igmp_rti_pool, sizeof(struct router_info), 0, 0, 0, "igmppl", NULL);
   69 struct igmpstat igmpstat;
   70 int igmp_timers_are_running;
   71 static LIST_HEAD(, router_info) rti_head = LIST_HEAD_INITIALIZER(rti_head);
   72 
   73 void igmp_sendpkt(struct in_multi *, int);
   74 static int rti_fill(struct in_multi *);
   75 static struct router_info *rti_find(struct ifnet *);
   76 static void rti_delete(struct ifnet *);
   77 
   78 static int
   79 rti_fill(struct in_multi *inm)
   80 {
   81         struct router_info *rti;
   82 
   83         /* this function is called at splsoftnet() */
   84         LIST_FOREACH(rti, &rti_head, rti_link) {
   85                 if (rti->rti_ifp == inm->inm_ifp) {
   86                         inm->inm_rti = rti;
   87                         if (rti->rti_type == IGMP_v1_ROUTER)
   88                                 return (IGMP_v1_HOST_MEMBERSHIP_REPORT);
   89                         else
   90                                 return (IGMP_v2_HOST_MEMBERSHIP_REPORT);
   91                 }
   92         }
   93 
   94         rti = pool_get(&igmp_rti_pool, PR_NOWAIT);
   95         if (rti == NULL)
   96                 return 0;
   97         rti->rti_ifp = inm->inm_ifp;
   98         rti->rti_type = IGMP_v2_ROUTER;
   99         LIST_INSERT_HEAD(&rti_head, rti, rti_link);
  100         inm->inm_rti = rti;
  101         return (IGMP_v2_HOST_MEMBERSHIP_REPORT);
  102 }
  103 
  104 static struct router_info *
  105 rti_find(struct ifnet *ifp)
  106 {
  107         struct router_info *rti;
  108         int s = splsoftnet();
  109 
  110         LIST_FOREACH(rti, &rti_head, rti_link) {
  111                 if (rti->rti_ifp == ifp)
  112                         return (rti);
  113         }
  114 
  115         rti = pool_get(&igmp_rti_pool, PR_NOWAIT);
  116         if (rti == NULL) {
  117                 splx(s);
  118                 return NULL;
  119         }
  120         rti->rti_ifp = ifp;
  121         rti->rti_type = IGMP_v2_ROUTER;
  122         LIST_INSERT_HEAD(&rti_head, rti, rti_link);
  123         splx(s);
  124         return (rti);
  125 }
  126 
  127 static void
  128 rti_delete(struct ifnet *ifp)   /* MUST be called at splsoftnet */
  129 {
  130         struct router_info *rti;
  131 
  132         LIST_FOREACH(rti, &rti_head, rti_link) {
  133                 if (rti->rti_ifp == ifp) {
  134                         LIST_REMOVE(rti, rti_link);
  135                         pool_put(&igmp_rti_pool, rti);
  136                         return;
  137                 }
  138         }
  139 }
  140 
  141 void
  142 igmp_input(struct mbuf *m, ...)
  143 {
  144         int proto;
  145         int iphlen;
  146         struct ifnet *ifp = m->m_pkthdr.rcvif;
  147         struct ip *ip = mtod(m, struct ip *);
  148         struct igmp *igmp;
  149         u_int minlen;
  150         struct in_multi *inm;
  151         struct in_multistep step;
  152         struct router_info *rti;
  153         struct in_ifaddr *ia;
  154         u_int timer;
  155         va_list ap;
  156         u_int16_t ip_len;
  157 
  158         va_start(ap, m);
  159         iphlen = va_arg(ap, int);
  160         proto = va_arg(ap, int);
  161         va_end(ap);
  162 
  163         ++igmpstat.igps_rcv_total;
  164 
  165         /*
  166          * Validate lengths
  167          */
  168         minlen = iphlen + IGMP_MINLEN;
  169         ip_len = ntohs(ip->ip_len);
  170         if (ip_len < minlen) {
  171                 ++igmpstat.igps_rcv_tooshort;
  172                 m_freem(m);
  173                 return;
  174         }
  175         if (((m->m_flags & M_EXT) && (ip->ip_src.s_addr & IN_CLASSA_NET) == 0)
  176             || m->m_len < minlen) {
  177                 if ((m = m_pullup(m, minlen)) == 0) {
  178                         ++igmpstat.igps_rcv_tooshort;
  179                         return;
  180                 }
  181                 ip = mtod(m, struct ip *);
  182         }
  183 
  184         /*
  185          * Validate checksum
  186          */
  187         m->m_data += iphlen;
  188         m->m_len -= iphlen;
  189         igmp = mtod(m, struct igmp *);
  190         /* No need to assert alignment here. */
  191         if (in_cksum(m, ip_len - iphlen)) {
  192                 ++igmpstat.igps_rcv_badsum;
  193                 m_freem(m);
  194                 return;
  195         }
  196         m->m_data -= iphlen;
  197         m->m_len += iphlen;
  198 
  199         switch (igmp->igmp_type) {
  200 
  201         case IGMP_HOST_MEMBERSHIP_QUERY:
  202                 ++igmpstat.igps_rcv_queries;
  203 
  204                 if (ifp->if_flags & IFF_LOOPBACK)
  205                         break;
  206 
  207                 if (igmp->igmp_code == 0) {
  208                         rti = rti_find(ifp);
  209                         if (rti == NULL)
  210                                 break;
  211                         rti->rti_type = IGMP_v1_ROUTER;
  212                         rti->rti_age = 0;
  213 
  214                         if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) {
  215                                 ++igmpstat.igps_rcv_badqueries;
  216                                 m_freem(m);
  217                                 return;
  218                         }
  219 
  220                         /*
  221                          * Start the timers in all of our membership records
  222                          * for the interface on which the query arrived,
  223                          * except those that are already running and those
  224                          * that belong to a "local" group (224.0.0.X).
  225                          */
  226                         IN_FIRST_MULTI(step, inm);
  227                         while (inm != NULL) {
  228                                 if (inm->inm_ifp == ifp &&
  229                                     inm->inm_timer == 0 &&
  230                                     !IN_LOCAL_GROUP(inm->inm_addr.s_addr)) {
  231                                         inm->inm_state = IGMP_DELAYING_MEMBER;
  232                                         inm->inm_timer = IGMP_RANDOM_DELAY(
  233                                             IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ);
  234                                         igmp_timers_are_running = 1;
  235                                 }
  236                                 IN_NEXT_MULTI(step, inm);
  237                         }
  238                 } else {
  239                         if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
  240                                 ++igmpstat.igps_rcv_badqueries;
  241                                 m_freem(m);
  242                                 return;
  243                         }
  244 
  245                         timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE;
  246                         if (timer == 0)
  247                                 timer =1;
  248 
  249                         /*
  250                          * Start the timers in all of our membership records
  251                          * for the interface on which the query arrived,
  252                          * except those that are already running and those
  253                          * that belong to a "local" group (224.0.0.X).  For
  254                          * timers already running, check if they need to be
  255                          * reset.
  256                          */
  257                         IN_FIRST_MULTI(step, inm);
  258                         while (inm != NULL) {
  259                                 if (inm->inm_ifp == ifp &&
  260                                     !IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  261                                     (ip->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP ||
  262                                      in_hosteq(ip->ip_dst, inm->inm_addr))) {
  263                                         switch (inm->inm_state) {
  264                                         case IGMP_DELAYING_MEMBER:
  265                                                 if (inm->inm_timer <= timer)
  266                                                         break;
  267                                                 /* FALLTHROUGH */
  268                                         case IGMP_IDLE_MEMBER:
  269                                         case IGMP_LAZY_MEMBER:
  270                                         case IGMP_AWAKENING_MEMBER:
  271                                                 inm->inm_state =
  272                                                     IGMP_DELAYING_MEMBER;
  273                                                 inm->inm_timer =
  274                                                     IGMP_RANDOM_DELAY(timer);
  275                                                 igmp_timers_are_running = 1;
  276                                                 break;
  277                                         case IGMP_SLEEPING_MEMBER:
  278                                                 inm->inm_state =
  279                                                     IGMP_AWAKENING_MEMBER;
  280                                                 break;
  281                                         }
  282                                 }
  283                                 IN_NEXT_MULTI(step, inm);
  284                         }
  285                 }
  286 
  287                 break;
  288 
  289         case IGMP_v1_HOST_MEMBERSHIP_REPORT:
  290                 ++igmpstat.igps_rcv_reports;
  291 
  292                 if (ifp->if_flags & IFF_LOOPBACK)
  293                         break;
  294 
  295                 if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
  296                     !in_hosteq(igmp->igmp_group, ip->ip_dst)) {
  297                         ++igmpstat.igps_rcv_badreports;
  298                         m_freem(m);
  299                         return;
  300                 }
  301 
  302                 /*
  303                  * KLUDGE: if the IP source address of the report has an
  304                  * unspecified (i.e., zero) subnet number, as is allowed for
  305                  * a booting host, replace it with the correct subnet number
  306                  * so that a process-level multicast routing daemon can
  307                  * determine which subnet it arrived from.  This is necessary
  308                  * to compensate for the lack of any way for a process to
  309                  * determine the arrival interface of an incoming packet.
  310                  */
  311                 if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
  312                         IFP_TO_IA(ifp, ia);             /* XXX */
  313                         if (ia)
  314                                 ip->ip_src.s_addr = ia->ia_subnet;
  315                 }
  316 
  317                 /*
  318                  * If we belong to the group being reported, stop
  319                  * our timer for that group.
  320                  */
  321                 IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
  322                 if (inm != NULL) {
  323                         inm->inm_timer = 0;
  324                         ++igmpstat.igps_rcv_ourreports;
  325 
  326                         switch (inm->inm_state) {
  327                         case IGMP_IDLE_MEMBER:
  328                         case IGMP_LAZY_MEMBER:
  329                         case IGMP_AWAKENING_MEMBER:
  330                         case IGMP_SLEEPING_MEMBER:
  331                                 inm->inm_state = IGMP_SLEEPING_MEMBER;
  332                                 break;
  333                         case IGMP_DELAYING_MEMBER:
  334                                 if (inm->inm_rti->rti_type == IGMP_v1_ROUTER)
  335                                         inm->inm_state = IGMP_LAZY_MEMBER;
  336                                 else
  337                                         inm->inm_state = IGMP_SLEEPING_MEMBER;
  338                                 break;
  339                         }
  340                 }
  341 
  342                 break;
  343 
  344         case IGMP_v2_HOST_MEMBERSHIP_REPORT:
  345 #ifdef MROUTING
  346                 /*
  347                  * Make sure we don't hear our own membership report.  Fast
  348                  * leave requires knowing that we are the only member of a
  349                  * group.
  350                  */
  351                 IFP_TO_IA(ifp, ia);                     /* XXX */
  352                 if (ia && in_hosteq(ip->ip_src, ia->ia_addr.sin_addr))
  353                         break;
  354 #endif
  355 
  356                 ++igmpstat.igps_rcv_reports;
  357 
  358                 if (ifp->if_flags & IFF_LOOPBACK)
  359                         break;
  360 
  361                 if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
  362                     !in_hosteq(igmp->igmp_group, ip->ip_dst)) {
  363                         ++igmpstat.igps_rcv_badreports;
  364                         m_freem(m);
  365                         return;
  366                 }
  367 
  368                 /*
  369                  * KLUDGE: if the IP source address of the report has an
  370                  * unspecified (i.e., zero) subnet number, as is allowed for
  371                  * a booting host, replace it with the correct subnet number
  372                  * so that a process-level multicast routing daemon can
  373                  * determine which subnet it arrived from.  This is necessary
  374                  * to compensate for the lack of any way for a process to
  375                  * determine the arrival interface of an incoming packet.
  376                  */
  377                 if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
  378 #ifndef MROUTING
  379                         IFP_TO_IA(ifp, ia);             /* XXX */
  380 #endif
  381                         if (ia)
  382                                 ip->ip_src.s_addr = ia->ia_subnet;
  383                 }
  384 
  385                 /*
  386                  * If we belong to the group being reported, stop
  387                  * our timer for that group.
  388                  */
  389                 IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
  390                 if (inm != NULL) {
  391                         inm->inm_timer = 0;
  392                         ++igmpstat.igps_rcv_ourreports;
  393 
  394                         switch (inm->inm_state) {
  395                         case IGMP_DELAYING_MEMBER:
  396                         case IGMP_IDLE_MEMBER:
  397                         case IGMP_AWAKENING_MEMBER:
  398                                 inm->inm_state = IGMP_LAZY_MEMBER;
  399                                 break;
  400                         case IGMP_LAZY_MEMBER:
  401                         case IGMP_SLEEPING_MEMBER:
  402                                 break;
  403                         }
  404                 }
  405 
  406                 break;
  407 
  408         }
  409 
  410         /*
  411          * Pass all valid IGMP packets up to any process(es) listening
  412          * on a raw IGMP socket.
  413          */
  414         rip_input(m, iphlen, proto);
  415         return;
  416 }
  417 
  418 int
  419 igmp_joingroup(struct in_multi *inm)
  420 {
  421         int report_type;
  422         int s = splsoftnet();
  423 
  424         inm->inm_state = IGMP_IDLE_MEMBER;
  425 
  426         if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  427             (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0) {
  428                 report_type = rti_fill(inm);
  429                 if (report_type == 0) {
  430                         splx(s);
  431                         return ENOMEM;
  432                 }
  433                 igmp_sendpkt(inm, report_type);
  434                 inm->inm_state = IGMP_DELAYING_MEMBER;
  435                 inm->inm_timer = IGMP_RANDOM_DELAY(
  436                     IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ);
  437                 igmp_timers_are_running = 1;
  438         } else
  439                 inm->inm_timer = 0;
  440         splx(s);
  441         return 0;
  442 }
  443 
  444 void
  445 igmp_leavegroup(struct in_multi *inm)
  446 {
  447 
  448         switch (inm->inm_state) {
  449         case IGMP_DELAYING_MEMBER:
  450         case IGMP_IDLE_MEMBER:
  451                 if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  452                     (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0)
  453                         if (inm->inm_rti->rti_type != IGMP_v1_ROUTER)
  454                                 igmp_sendpkt(inm, IGMP_HOST_LEAVE_MESSAGE);
  455                 break;
  456         case IGMP_LAZY_MEMBER:
  457         case IGMP_AWAKENING_MEMBER:
  458         case IGMP_SLEEPING_MEMBER:
  459                 break;
  460         }
  461 }
  462 
  463 void
  464 igmp_fasttimo(void)
  465 {
  466         struct in_multi *inm;
  467         struct in_multistep step;
  468         int s;
  469 
  470         /*
  471          * Quick check to see if any work needs to be done, in order
  472          * to minimize the overhead of fasttimo processing.
  473          */
  474         if (!igmp_timers_are_running)
  475                 return;
  476 
  477         s = splsoftnet();
  478         igmp_timers_are_running = 0;
  479         IN_FIRST_MULTI(step, inm);
  480         while (inm != NULL) {
  481                 if (inm->inm_timer == 0) {
  482                         /* do nothing */
  483                 } else if (--inm->inm_timer == 0) {
  484                         if (inm->inm_state == IGMP_DELAYING_MEMBER) {
  485                                 if (inm->inm_rti->rti_type == IGMP_v1_ROUTER)
  486                                         igmp_sendpkt(inm,
  487                                             IGMP_v1_HOST_MEMBERSHIP_REPORT);
  488                                 else
  489                                         igmp_sendpkt(inm,
  490                                             IGMP_v2_HOST_MEMBERSHIP_REPORT);
  491                                 inm->inm_state = IGMP_IDLE_MEMBER;
  492                         }
  493                 } else {
  494                         igmp_timers_are_running = 1;
  495                 }
  496                 IN_NEXT_MULTI(step, inm);
  497         }
  498         splx(s);
  499 }
  500 
  501 void
  502 igmp_slowtimo(void)
  503 {
  504         struct router_info *rti;
  505         int s;
  506 
  507         s = splsoftnet();
  508         LIST_FOREACH(rti, &rti_head, rti_link) {
  509                 if (rti->rti_type == IGMP_v1_ROUTER &&
  510                     ++rti->rti_age >= IGMP_AGE_THRESHOLD) {
  511                         rti->rti_type = IGMP_v2_ROUTER;
  512                 }
  513         }
  514         splx(s);
  515 }
  516 
  517 void
  518 igmp_sendpkt(struct in_multi *inm, int type)
  519 {
  520         struct mbuf *m;
  521         struct igmp *igmp;
  522         struct ip *ip;
  523         struct ip_moptions imo;
  524 #ifdef MROUTING
  525         extern struct socket *ip_mrouter;
  526 #endif /* MROUTING */
  527 
  528         MGETHDR(m, M_DONTWAIT, MT_HEADER);
  529         if (m == NULL)
  530                 return;
  531         /*
  532          * Assume max_linkhdr + sizeof(struct ip) + IGMP_MINLEN
  533          * is smaller than mbuf size returned by MGETHDR.
  534          */
  535         m->m_data += max_linkhdr;
  536         m->m_len = sizeof(struct ip) + IGMP_MINLEN;
  537         m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
  538 
  539         ip = mtod(m, struct ip *);
  540         ip->ip_tos = 0;
  541         ip->ip_len = htons(sizeof(struct ip) + IGMP_MINLEN);
  542         ip->ip_off = htons(0);
  543         ip->ip_p = IPPROTO_IGMP;
  544         ip->ip_src = zeroin_addr;
  545         ip->ip_dst = inm->inm_addr;
  546 
  547         m->m_data += sizeof(struct ip);
  548         m->m_len -= sizeof(struct ip);
  549         igmp = mtod(m, struct igmp *);
  550         igmp->igmp_type = type;
  551         igmp->igmp_code = 0;
  552         igmp->igmp_group = inm->inm_addr;
  553         igmp->igmp_cksum = 0;
  554         igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN);
  555         m->m_data -= sizeof(struct ip);
  556         m->m_len += sizeof(struct ip);
  557 
  558         imo.imo_multicast_ifp = inm->inm_ifp;
  559         imo.imo_multicast_ttl = 1;
  560 #ifdef RSVP_ISI
  561         imo.imo_multicast_vif = -1;
  562 #endif
  563         /*
  564          * Request loopback of the report if we are acting as a multicast
  565          * router, so that the process-level routing demon can hear it.
  566          */
  567 #ifdef MROUTING
  568         imo.imo_multicast_loop = (ip_mrouter != NULL);
  569 #else
  570         imo.imo_multicast_loop = 0;
  571 #endif /* MROUTING */
  572 
  573         ip_output(m, (struct mbuf *)NULL, (struct route *)NULL,
  574             IP_MULTICASTOPTS, &imo, (struct socket *)NULL);
  575 
  576         ++igmpstat.igps_snd_reports;
  577 }
  578 
  579 void
  580 igmp_purgeif(struct ifnet *ifp) /* MUST be called at splsoftnet() */
  581 {
  582         rti_delete(ifp);        /* manipulates pools */
  583 }

Cache object: ba16ce780171b940a34d1616a79ea9ec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.