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.41 2005/02/03 03:49:01 perry 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.41 2005/02/03 03:49:01 perry 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         LIST_FOREACH(rti, &rti_head, rti_link) {
   84                 if (rti->rti_ifp == inm->inm_ifp) {
   85                         inm->inm_rti = rti;
   86                         if (rti->rti_type == IGMP_v1_ROUTER)
   87                                 return (IGMP_v1_HOST_MEMBERSHIP_REPORT);
   88                         else
   89                                 return (IGMP_v2_HOST_MEMBERSHIP_REPORT);
   90                 }
   91         }
   92 
   93         rti = pool_get(&igmp_rti_pool, PR_NOWAIT);
   94         if (rti == NULL)
   95                 return 0;
   96         rti->rti_ifp = inm->inm_ifp;
   97         rti->rti_type = IGMP_v2_ROUTER;
   98         LIST_INSERT_HEAD(&rti_head, rti, rti_link);
   99         inm->inm_rti = rti;
  100         return (IGMP_v2_HOST_MEMBERSHIP_REPORT);
  101 }
  102 
  103 static struct router_info *
  104 rti_find(struct ifnet *ifp)
  105 {
  106         struct router_info *rti;
  107 
  108         LIST_FOREACH(rti, &rti_head, rti_link) {
  109                 if (rti->rti_ifp == ifp)
  110                         return (rti);
  111         }
  112 
  113         rti = pool_get(&igmp_rti_pool, PR_NOWAIT);
  114         if (rti == NULL)
  115                 return NULL;
  116         rti->rti_ifp = ifp;
  117         rti->rti_type = IGMP_v2_ROUTER;
  118         LIST_INSERT_HEAD(&rti_head, rti, rti_link);
  119         return (rti);
  120 }
  121 
  122 static void
  123 rti_delete(struct ifnet *ifp)
  124 {
  125         struct router_info *rti;
  126 
  127         LIST_FOREACH(rti, &rti_head, rti_link) {
  128                 if (rti->rti_ifp == ifp) {
  129                         LIST_REMOVE(rti, rti_link);
  130                         pool_put(&igmp_rti_pool, rti);
  131                         return;
  132                 }
  133         }
  134 }
  135 
  136 void
  137 igmp_input(struct mbuf *m, ...)
  138 {
  139         int proto;
  140         int iphlen;
  141         struct ifnet *ifp = m->m_pkthdr.rcvif;
  142         struct ip *ip = mtod(m, struct ip *);
  143         struct igmp *igmp;
  144         u_int minlen;
  145         struct in_multi *inm;
  146         struct in_multistep step;
  147         struct router_info *rti;
  148         struct in_ifaddr *ia;
  149         u_int timer;
  150         va_list ap;
  151         u_int16_t ip_len;
  152 
  153         va_start(ap, m);
  154         iphlen = va_arg(ap, int);
  155         proto = va_arg(ap, int);
  156         va_end(ap);
  157 
  158         ++igmpstat.igps_rcv_total;
  159 
  160         /*
  161          * Validate lengths
  162          */
  163         minlen = iphlen + IGMP_MINLEN;
  164         ip_len = ntohs(ip->ip_len);
  165         if (ip_len < minlen) {
  166                 ++igmpstat.igps_rcv_tooshort;
  167                 m_freem(m);
  168                 return;
  169         }
  170         if (((m->m_flags & M_EXT) && (ip->ip_src.s_addr & IN_CLASSA_NET) == 0)
  171             || m->m_len < minlen) {
  172                 if ((m = m_pullup(m, minlen)) == 0) {
  173                         ++igmpstat.igps_rcv_tooshort;
  174                         return;
  175                 }
  176                 ip = mtod(m, struct ip *);
  177         }
  178 
  179         /*
  180          * Validate checksum
  181          */
  182         m->m_data += iphlen;
  183         m->m_len -= iphlen;
  184         igmp = mtod(m, struct igmp *);
  185         /* No need to assert alignment here. */
  186         if (in_cksum(m, ip_len - iphlen)) {
  187                 ++igmpstat.igps_rcv_badsum;
  188                 m_freem(m);
  189                 return;
  190         }
  191         m->m_data -= iphlen;
  192         m->m_len += iphlen;
  193 
  194         switch (igmp->igmp_type) {
  195 
  196         case IGMP_HOST_MEMBERSHIP_QUERY:
  197                 ++igmpstat.igps_rcv_queries;
  198 
  199                 if (ifp->if_flags & IFF_LOOPBACK)
  200                         break;
  201 
  202                 if (igmp->igmp_code == 0) {
  203                         rti = rti_find(ifp);
  204                         if (rti == NULL)
  205                                 break;
  206                         rti->rti_type = IGMP_v1_ROUTER;
  207                         rti->rti_age = 0;
  208 
  209                         if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) {
  210                                 ++igmpstat.igps_rcv_badqueries;
  211                                 m_freem(m);
  212                                 return;
  213                         }
  214 
  215                         /*
  216                          * Start the timers in all of our membership records
  217                          * for the interface on which the query arrived,
  218                          * except those that are already running and those
  219                          * that belong to a "local" group (224.0.0.X).
  220                          */
  221                         IN_FIRST_MULTI(step, inm);
  222                         while (inm != NULL) {
  223                                 if (inm->inm_ifp == ifp &&
  224                                     inm->inm_timer == 0 &&
  225                                     !IN_LOCAL_GROUP(inm->inm_addr.s_addr)) {
  226                                         inm->inm_state = IGMP_DELAYING_MEMBER;
  227                                         inm->inm_timer = IGMP_RANDOM_DELAY(
  228                                             IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ);
  229                                         igmp_timers_are_running = 1;
  230                                 }
  231                                 IN_NEXT_MULTI(step, inm);
  232                         }
  233                 } else {
  234                         if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
  235                                 ++igmpstat.igps_rcv_badqueries;
  236                                 m_freem(m);
  237                                 return;
  238                         }
  239 
  240                         timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE;
  241                         if (timer == 0)
  242                                 timer =1;
  243 
  244                         /*
  245                          * Start the timers in all of our membership records
  246                          * for the interface on which the query arrived,
  247                          * except those that are already running and those
  248                          * that belong to a "local" group (224.0.0.X).  For
  249                          * timers already running, check if they need to be
  250                          * reset.
  251                          */
  252                         IN_FIRST_MULTI(step, inm);
  253                         while (inm != NULL) {
  254                                 if (inm->inm_ifp == ifp &&
  255                                     !IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  256                                     (ip->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP ||
  257                                      in_hosteq(ip->ip_dst, inm->inm_addr))) {
  258                                         switch (inm->inm_state) {
  259                                         case IGMP_DELAYING_MEMBER:
  260                                                 if (inm->inm_timer <= timer)
  261                                                         break;
  262                                                 /* FALLTHROUGH */
  263                                         case IGMP_IDLE_MEMBER:
  264                                         case IGMP_LAZY_MEMBER:
  265                                         case IGMP_AWAKENING_MEMBER:
  266                                                 inm->inm_state =
  267                                                     IGMP_DELAYING_MEMBER;
  268                                                 inm->inm_timer =
  269                                                     IGMP_RANDOM_DELAY(timer);
  270                                                 igmp_timers_are_running = 1;
  271                                                 break;
  272                                         case IGMP_SLEEPING_MEMBER:
  273                                                 inm->inm_state =
  274                                                     IGMP_AWAKENING_MEMBER;
  275                                                 break;
  276                                         }
  277                                 }
  278                                 IN_NEXT_MULTI(step, inm);
  279                         }
  280                 }
  281 
  282                 break;
  283 
  284         case IGMP_v1_HOST_MEMBERSHIP_REPORT:
  285                 ++igmpstat.igps_rcv_reports;
  286 
  287                 if (ifp->if_flags & IFF_LOOPBACK)
  288                         break;
  289 
  290                 if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
  291                     !in_hosteq(igmp->igmp_group, ip->ip_dst)) {
  292                         ++igmpstat.igps_rcv_badreports;
  293                         m_freem(m);
  294                         return;
  295                 }
  296 
  297                 /*
  298                  * KLUDGE: if the IP source address of the report has an
  299                  * unspecified (i.e., zero) subnet number, as is allowed for
  300                  * a booting host, replace it with the correct subnet number
  301                  * so that a process-level multicast routing daemon can
  302                  * determine which subnet it arrived from.  This is necessary
  303                  * to compensate for the lack of any way for a process to
  304                  * determine the arrival interface of an incoming packet.
  305                  */
  306                 if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
  307                         IFP_TO_IA(ifp, ia);             /* XXX */
  308                         if (ia)
  309                                 ip->ip_src.s_addr = ia->ia_subnet;
  310                 }
  311 
  312                 /*
  313                  * If we belong to the group being reported, stop
  314                  * our timer for that group.
  315                  */
  316                 IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
  317                 if (inm != NULL) {
  318                         inm->inm_timer = 0;
  319                         ++igmpstat.igps_rcv_ourreports;
  320 
  321                         switch (inm->inm_state) {
  322                         case IGMP_IDLE_MEMBER:
  323                         case IGMP_LAZY_MEMBER:
  324                         case IGMP_AWAKENING_MEMBER:
  325                         case IGMP_SLEEPING_MEMBER:
  326                                 inm->inm_state = IGMP_SLEEPING_MEMBER;
  327                                 break;
  328                         case IGMP_DELAYING_MEMBER:
  329                                 if (inm->inm_rti->rti_type == IGMP_v1_ROUTER)
  330                                         inm->inm_state = IGMP_LAZY_MEMBER;
  331                                 else
  332                                         inm->inm_state = IGMP_SLEEPING_MEMBER;
  333                                 break;
  334                         }
  335                 }
  336 
  337                 break;
  338 
  339         case IGMP_v2_HOST_MEMBERSHIP_REPORT:
  340 #ifdef MROUTING
  341                 /*
  342                  * Make sure we don't hear our own membership report.  Fast
  343                  * leave requires knowing that we are the only member of a
  344                  * group.
  345                  */
  346                 IFP_TO_IA(ifp, ia);                     /* XXX */
  347                 if (ia && in_hosteq(ip->ip_src, ia->ia_addr.sin_addr))
  348                         break;
  349 #endif
  350 
  351                 ++igmpstat.igps_rcv_reports;
  352 
  353                 if (ifp->if_flags & IFF_LOOPBACK)
  354                         break;
  355 
  356                 if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
  357                     !in_hosteq(igmp->igmp_group, ip->ip_dst)) {
  358                         ++igmpstat.igps_rcv_badreports;
  359                         m_freem(m);
  360                         return;
  361                 }
  362 
  363                 /*
  364                  * KLUDGE: if the IP source address of the report has an
  365                  * unspecified (i.e., zero) subnet number, as is allowed for
  366                  * a booting host, replace it with the correct subnet number
  367                  * so that a process-level multicast routing daemon can
  368                  * determine which subnet it arrived from.  This is necessary
  369                  * to compensate for the lack of any way for a process to
  370                  * determine the arrival interface of an incoming packet.
  371                  */
  372                 if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
  373 #ifndef MROUTING
  374                         IFP_TO_IA(ifp, ia);             /* XXX */
  375 #endif
  376                         if (ia)
  377                                 ip->ip_src.s_addr = ia->ia_subnet;
  378                 }
  379 
  380                 /*
  381                  * If we belong to the group being reported, stop
  382                  * our timer for that group.
  383                  */
  384                 IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
  385                 if (inm != NULL) {
  386                         inm->inm_timer = 0;
  387                         ++igmpstat.igps_rcv_ourreports;
  388 
  389                         switch (inm->inm_state) {
  390                         case IGMP_DELAYING_MEMBER:
  391                         case IGMP_IDLE_MEMBER:
  392                         case IGMP_AWAKENING_MEMBER:
  393                                 inm->inm_state = IGMP_LAZY_MEMBER;
  394                                 break;
  395                         case IGMP_LAZY_MEMBER:
  396                         case IGMP_SLEEPING_MEMBER:
  397                                 break;
  398                         }
  399                 }
  400 
  401                 break;
  402 
  403         }
  404 
  405         /*
  406          * Pass all valid IGMP packets up to any process(es) listening
  407          * on a raw IGMP socket.
  408          */
  409         rip_input(m, iphlen, proto);
  410         return;
  411 }
  412 
  413 int
  414 igmp_joingroup(struct in_multi *inm)
  415 {
  416         int report_type;
  417         int s = splsoftnet();
  418 
  419         inm->inm_state = IGMP_IDLE_MEMBER;
  420 
  421         if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  422             (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0) {
  423                 report_type = rti_fill(inm);
  424                 if (report_type == 0) {
  425                         splx(s);
  426                         return ENOMEM;
  427                 }
  428                 igmp_sendpkt(inm, report_type);
  429                 inm->inm_state = IGMP_DELAYING_MEMBER;
  430                 inm->inm_timer = IGMP_RANDOM_DELAY(
  431                     IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ);
  432                 igmp_timers_are_running = 1;
  433         } else
  434                 inm->inm_timer = 0;
  435         splx(s);
  436         return 0;
  437 }
  438 
  439 void
  440 igmp_leavegroup(struct in_multi *inm)
  441 {
  442 
  443         switch (inm->inm_state) {
  444         case IGMP_DELAYING_MEMBER:
  445         case IGMP_IDLE_MEMBER:
  446                 if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) &&
  447                     (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0)
  448                         if (inm->inm_rti->rti_type != IGMP_v1_ROUTER)
  449                                 igmp_sendpkt(inm, IGMP_HOST_LEAVE_MESSAGE);
  450                 break;
  451         case IGMP_LAZY_MEMBER:
  452         case IGMP_AWAKENING_MEMBER:
  453         case IGMP_SLEEPING_MEMBER:
  454                 break;
  455         }
  456 }
  457 
  458 void
  459 igmp_fasttimo(void)
  460 {
  461         struct in_multi *inm;
  462         struct in_multistep step;
  463         int s;
  464 
  465         /*
  466          * Quick check to see if any work needs to be done, in order
  467          * to minimize the overhead of fasttimo processing.
  468          */
  469         if (!igmp_timers_are_running)
  470                 return;
  471 
  472         s = splsoftnet();
  473         igmp_timers_are_running = 0;
  474         IN_FIRST_MULTI(step, inm);
  475         while (inm != NULL) {
  476                 if (inm->inm_timer == 0) {
  477                         /* do nothing */
  478                 } else if (--inm->inm_timer == 0) {
  479                         if (inm->inm_state == IGMP_DELAYING_MEMBER) {
  480                                 if (inm->inm_rti->rti_type == IGMP_v1_ROUTER)
  481                                         igmp_sendpkt(inm,
  482                                             IGMP_v1_HOST_MEMBERSHIP_REPORT);
  483                                 else
  484                                         igmp_sendpkt(inm,
  485                                             IGMP_v2_HOST_MEMBERSHIP_REPORT);
  486                                 inm->inm_state = IGMP_IDLE_MEMBER;
  487                         }
  488                 } else {
  489                         igmp_timers_are_running = 1;
  490                 }
  491                 IN_NEXT_MULTI(step, inm);
  492         }
  493         splx(s);
  494 }
  495 
  496 void
  497 igmp_slowtimo(void)
  498 {
  499         struct router_info *rti;
  500         int s;
  501 
  502         s = splsoftnet();
  503         LIST_FOREACH(rti, &rti_head, rti_link) {
  504                 if (rti->rti_type == IGMP_v1_ROUTER &&
  505                     ++rti->rti_age >= IGMP_AGE_THRESHOLD) {
  506                         rti->rti_type = IGMP_v2_ROUTER;
  507                 }
  508         }
  509         splx(s);
  510 }
  511 
  512 void
  513 igmp_sendpkt(struct in_multi *inm, int type)
  514 {
  515         struct mbuf *m;
  516         struct igmp *igmp;
  517         struct ip *ip;
  518         struct ip_moptions imo;
  519 #ifdef MROUTING
  520         extern struct socket *ip_mrouter;
  521 #endif /* MROUTING */
  522 
  523         MGETHDR(m, M_DONTWAIT, MT_HEADER);
  524         if (m == NULL)
  525                 return;
  526         /*
  527          * Assume max_linkhdr + sizeof(struct ip) + IGMP_MINLEN
  528          * is smaller than mbuf size returned by MGETHDR.
  529          */
  530         m->m_data += max_linkhdr;
  531         m->m_len = sizeof(struct ip) + IGMP_MINLEN;
  532         m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
  533 
  534         ip = mtod(m, struct ip *);
  535         ip->ip_tos = 0;
  536         ip->ip_len = htons(sizeof(struct ip) + IGMP_MINLEN);
  537         ip->ip_off = htons(0);
  538         ip->ip_p = IPPROTO_IGMP;
  539         ip->ip_src = zeroin_addr;
  540         ip->ip_dst = inm->inm_addr;
  541 
  542         m->m_data += sizeof(struct ip);
  543         m->m_len -= sizeof(struct ip);
  544         igmp = mtod(m, struct igmp *);
  545         igmp->igmp_type = type;
  546         igmp->igmp_code = 0;
  547         igmp->igmp_group = inm->inm_addr;
  548         igmp->igmp_cksum = 0;
  549         igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN);
  550         m->m_data -= sizeof(struct ip);
  551         m->m_len += sizeof(struct ip);
  552 
  553         imo.imo_multicast_ifp = inm->inm_ifp;
  554         imo.imo_multicast_ttl = 1;
  555 #ifdef RSVP_ISI
  556         imo.imo_multicast_vif = -1;
  557 #endif
  558         /*
  559          * Request loopback of the report if we are acting as a multicast
  560          * router, so that the process-level routing demon can hear it.
  561          */
  562 #ifdef MROUTING
  563         imo.imo_multicast_loop = (ip_mrouter != NULL);
  564 #else
  565         imo.imo_multicast_loop = 0;
  566 #endif /* MROUTING */
  567 
  568         ip_output(m, (struct mbuf *)NULL, (struct route *)NULL,
  569             IP_MULTICASTOPTS, &imo, (struct socket *)NULL);
  570 
  571         ++igmpstat.igps_snd_reports;
  572 }
  573 
  574 void
  575 igmp_purgeif(struct ifnet *ifp)
  576 {
  577 
  578         rti_delete(ifp);
  579 }

Cache object: 53a9769ced674b364fff3543c3aeedc0


[ 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.