Annotation of embedaddon/pimd/kern.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 1998-2001
                      3:  * University of Southern California/Information Sciences Institute.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. Neither the name of the project nor the names of its contributors
                     15:  *    may be used to endorse or promote products derived from this software
                     16:  *    without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  */
                     30: /*
                     31:  * Part of this program has been derived from mrouted.
                     32:  * The mrouted program is covered by the license in the accompanying file
                     33:  * named "LICENSE.mrouted".
                     34:  *
                     35:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
                     36:  * Leland Stanford Junior University.
                     37:  *
                     38:  */
                     39: 
                     40: #include "defs.h"
                     41: 
                     42: #ifdef RAW_OUTPUT_IS_RAW
                     43: int curttl = 0;
                     44: #endif
                     45: 
                     46: /*
                     47:  * XXX: in Some BSD's there is only MRT_ASSERT, but in Linux there are
                     48:  *      both MRT_ASSERT and MRT_PIM
                     49:  */
                     50: #ifndef MRT_PIM
                     51: #define MRT_PIM MRT_ASSERT
                     52: #endif
                     53: 
                     54: #ifdef __linux__ /* Currently only available on Linux  */
                     55: # ifndef MRT_TABLE
                     56: #  define MRT_TABLE       (MRT_BASE + 9)
                     57: # endif
                     58: #endif
                     59: 
                     60: /*
                     61:  * Open/init the multicast routing in the kernel and sets the
                     62:  * MRT_PIM (aka MRT_ASSERT) flag in the kernel.
                     63:  */
                     64: void k_init_pim(int socket)
                     65: {
                     66:     int v = 1;
                     67: 
                     68: #ifdef MRT_TABLE /* Currently only available on Linux  */
                     69:     if (mrt_table_id != 0) {
                     70:         logit(LOG_INFO, 0, "Initializing multicast routing table id %u", mrt_table_id);
                     71:         if (setsockopt(socket, IPPROTO_IP, MRT_TABLE, &mrt_table_id, sizeof(mrt_table_id)) < 0) {
                     72:             logit(LOG_WARNING, errno, "Cannot set multicast routing table id");
                     73:            logit(LOG_ERR, 0, "Make sure your kernel has CONFIG_IP_MROUTE_MULTIPLE_TABLES=y");
                     74:        }
                     75:     }
                     76: #endif
                     77: 
                     78:     if (setsockopt(socket, IPPROTO_IP, MRT_INIT, (char *)&v, sizeof(int)) < 0) {
                     79:        if (errno == EADDRINUSE)
                     80:            logit(LOG_ERR, 0, "Another multicast routing application is already running.");
                     81:        else
                     82:            logit(LOG_ERR, errno, "Cannot enable multicast routing in kernel");
                     83:     }
                     84: 
                     85:     if (setsockopt(socket, IPPROTO_IP, MRT_PIM, (char *)&v, sizeof(int)) < 0)
                     86:        logit(LOG_ERR, errno, "Cannot set PIM flag in kernel");
                     87: }
                     88: 
                     89: 
                     90: /*
                     91:  * Stops the multicast routing in the kernel and resets the
                     92:  * MRT_PIM (aka MRT_ASSERT) flag in the kernel.
                     93:  */
                     94: void k_stop_pim(int socket)
                     95: {
                     96:     int v = 0;
                     97: 
                     98:     if (setsockopt(socket, IPPROTO_IP, MRT_PIM, (char *)&v, sizeof(int)) < 0)
                     99:        logit(LOG_ERR, errno, "Cannot reset PIM flag in kernel");
                    100: 
                    101:     if (setsockopt(socket, IPPROTO_IP, MRT_DONE, (char *)NULL, 0) < 0)
                    102:        logit(LOG_ERR, errno, "Cannot disable multicast routing in kernel");
                    103: }
                    104: 
                    105: 
                    106: /*
                    107:  * Set the socket sending buffer. `bufsize` is the preferred size,
                    108:  * `minsize` is the smallest acceptable size.
                    109:  */
                    110: void k_set_sndbuf(int socket, int bufsize, int minsize)
                    111: {
                    112:     int delta = bufsize / 2;
                    113:     int iter = 0;
                    114: 
                    115:     /*
                    116:      * Set the socket buffer.  If we can't set it as large as we
                    117:      * want, search around to try to find the highest acceptable
                    118:      * value.  The highest acceptable value being smaller than
                    119:      * minsize is a fatal error.
                    120:      */
                    121:     if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize)) < 0) {
                    122:        bufsize -= delta;
                    123:        while (1) {
                    124:            iter++;
                    125:            if (delta > 1)
                    126:                delta /= 2;
                    127: 
                    128:            if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize)) < 0) {
                    129:                bufsize -= delta;
                    130:            } else {
                    131:                if (delta < 1024)
                    132:                    break;
                    133:                bufsize += delta;
                    134:            }
                    135:        }
                    136:        if (bufsize < minsize) {
                    137:            logit(LOG_ERR, 0, "OS-allowed send buffer size %u < app min %u",
                    138:                  bufsize, minsize);
                    139:            /*NOTREACHED*/
                    140:        }
                    141:     }
                    142: 
                    143:     IF_DEBUG(DEBUG_KERN) {
                    144:        logit(LOG_DEBUG, 0, "Got %d byte send buffer size in %d iterations",
                    145:              bufsize, iter);
                    146:     }
                    147: }
                    148: 
                    149: 
                    150: /*
                    151:  * Set the socket receiving buffer. `bufsize` is the preferred size,
                    152:  * `minsize` is the smallest acceptable size.
                    153:  */
                    154: void k_set_rcvbuf(int socket, int bufsize, int minsize)
                    155: {
                    156:     int delta = bufsize / 2;
                    157:     int iter = 0;
                    158: 
                    159:     /*
                    160:      * Set the socket buffer.  If we can't set it as large as we
                    161:      * want, search around to try to find the highest acceptable
                    162:      * value.  The highest acceptable value being smaller than
                    163:      * minsize is a fatal error.
                    164:      */
                    165:     if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)) < 0) {
                    166:        bufsize -= delta;
                    167:        while (1) {
                    168:            iter++;
                    169:            if (delta > 1)
                    170:                delta /= 2;
                    171: 
                    172:            if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)) < 0) {
                    173:                bufsize -= delta;
                    174:            } else {
                    175:                if (delta < 1024)
                    176:                    break;
                    177:                bufsize += delta;
                    178:            }
                    179:        }
                    180: 
                    181:        if (bufsize < minsize) {
                    182:            logit(LOG_ERR, 0, "OS-allowed recv buffer size %u < app min %u", bufsize, minsize);
                    183:            /*NOTREACHED*/
                    184:        }
                    185:     }
                    186: 
                    187:     IF_DEBUG(DEBUG_KERN) {
                    188:        logit(LOG_DEBUG, 0, "Got %d byte recv buffer size in %d iterations",
                    189:              bufsize, iter);
                    190:     }
                    191: }
                    192: 
                    193: 
                    194: /*
                    195:  * Set/reset the IP_HDRINCL option. My guess is we don't need it for raw
                    196:  * sockets, but having it here won't hurt. Well, unless you are running
                    197:  * an older version of FreeBSD (older than 2.2.2). If the multicast
                    198:  * raw packet is bigger than 208 bytes, then IP_HDRINCL triggers a bug
                    199:  * in the kernel and "panic". The kernel patch for netinet/ip_raw.c
                    200:  * coming with this distribution fixes it.
                    201:  */
                    202: void k_hdr_include(int socket, int val)
                    203: {
                    204: #ifdef IP_HDRINCL
                    205:     if (setsockopt(socket, IPPROTO_IP, IP_HDRINCL, (char *)&val, sizeof(val)) < 0)
                    206:        logit(LOG_ERR, errno, "Failed %s IP_HDRINCL on socket %d",
                    207:              ENABLINGSTR(val), socket);
                    208: #endif
                    209: }
                    210: 
                    211: 
                    212: /*
                    213:  * Set the default TTL for the multicast packets outgoing from this
                    214:  * socket.
                    215:  * TODO: Does it affect the unicast packets?
                    216:  */
                    217: void k_set_ttl(int socket __attribute__((unused)), int t)
                    218: {
                    219: #ifdef RAW_OUTPUT_IS_RAW
                    220:     curttl = t;
                    221: #else
                    222:     uint8_t ttl;
                    223: 
                    224:     ttl = t;
                    225:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) < 0)
                    226:        logit(LOG_ERR, errno, "Failed setting IP_MULTICAST_TTL %u on socket %d", ttl, socket);
                    227: #endif
                    228: }
                    229: 
                    230: 
                    231: /*
                    232:  * Set/reset the IP_MULTICAST_LOOP. Set/reset is specified by "flag".
                    233:  */
                    234: void k_set_loop(int socket, int flag)
                    235: {
                    236:     uint8_t loop;
                    237: 
                    238:     loop = flag;
                    239:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loop, sizeof(loop)) < 0)
                    240:        logit(LOG_ERR, errno, "Failed %s IP_MULTICAST_LOOP on socket %d",
                    241:              ENABLINGSTR(flag), socket);
                    242: }
                    243: 
                    244: 
                    245: /*
                    246:  * Set the IP_MULTICAST_IF option on local interface ifa.
                    247:  */
                    248: void k_set_if(int socket, uint32_t ifa)
                    249: {
                    250:     struct in_addr adr;
                    251: 
                    252:     adr.s_addr = ifa;
                    253:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&adr, sizeof(adr)) < 0) {
                    254:        if (errno == EADDRNOTAVAIL || errno == EINVAL)
                    255:            return;
                    256: 
                    257:        logit(LOG_ERR, errno, "Failed setting IP_MULTICAST_IF option on %s",
                    258:              inet_fmt(adr.s_addr, s1, sizeof(s1)));
                    259:     }
                    260: }
                    261: 
                    262: 
                    263: /*
                    264:  * Set Router Alert IP option, RFC2113
                    265:  */
                    266: void k_set_router_alert(int socket)
                    267: {
                    268:     char router_alert[4];      /* Router Alert IP Option           */
                    269: 
                    270:     router_alert[0] = IPOPT_RA;        /* Router Alert */
                    271:     router_alert[1] = 4;       /* 4 bytes */
                    272:     router_alert[2] = 0;
                    273:     router_alert[3] = 0;
                    274: 
                    275:     if (setsockopt(socket, IPPROTO_IP, IP_OPTIONS, router_alert, sizeof(router_alert) )< 0)
                    276:        logit(LOG_ERR, errno, "setsockopt IP_OPTIONS IPOPT_RA");
                    277: }
                    278: 
                    279: 
                    280: /*
                    281:  * Join a multicast group on virtual interface 'v'.
                    282:  */
                    283: void k_join(int socket, uint32_t grp, struct uvif *v)
                    284: {
                    285: #ifdef __linux__
                    286:     struct ip_mreqn mreq;
                    287: #else
                    288:     struct ip_mreq mreq;
                    289: #endif /* __linux__ */
                    290: 
                    291: #ifdef __linux__
                    292:     mreq.imr_ifindex         = v->uv_ifindex;
                    293:     mreq.imr_address.s_addr   = v->uv_lcl_addr;
                    294: #else
                    295:     mreq.imr_interface.s_addr = v->uv_lcl_addr;
                    296: #endif /* __linux__ */
                    297:     mreq.imr_multiaddr.s_addr = grp;
                    298: 
                    299:     if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                    300:                   (char *)&mreq, sizeof(mreq)) < 0) {
                    301: #ifdef __linux__
                    302:        logit(LOG_WARNING, errno,
                    303:              "Cannot join group %s on interface %s (ifindex %d)",
                    304:              inet_fmt(grp, s1, sizeof(s1)), inet_fmt(v->uv_lcl_addr, s2, sizeof(s2)), v->uv_ifindex);
                    305: #else
                    306:        logit(LOG_WARNING, errno,
                    307:              "Cannot join group %s on interface %s",
                    308:              inet_fmt(grp, s1, sizeof(s1)), inet_fmt(v->uv_lcl_addr, s2, sizeof(s2)));
                    309: #endif /* __linux__ */
                    310:     }
                    311: }
                    312: 
                    313: 
                    314: /*
                    315:  * Leave a multicast group on virtual interface 'v'.
                    316:  */
                    317: void k_leave(int socket, uint32_t grp, struct uvif *v)
                    318: {
                    319: #ifdef __linux__
                    320:     struct ip_mreqn mreq;
                    321: #else
                    322:     struct ip_mreq mreq;
                    323: #endif /* __linux__ */
                    324: 
                    325: #ifdef __linux__
                    326:     mreq.imr_ifindex         = v->uv_ifindex;
                    327:     mreq.imr_address.s_addr   = v->uv_lcl_addr;
                    328: #else
                    329:     mreq.imr_interface.s_addr = v->uv_lcl_addr;
                    330: #endif /* __linux__ */
                    331:     mreq.imr_multiaddr.s_addr = grp;
                    332: 
                    333:     if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) {
                    334: #ifdef __linux__
                    335:        logit(LOG_WARNING, errno,
                    336:              "Cannot leave group %s on interface %s (ifindex %d)",
                    337:              inet_fmt(grp, s1, sizeof(s1)), inet_fmt(v->uv_lcl_addr, s2, sizeof(s2)), v->uv_ifindex);
                    338: #else
                    339:        logit(LOG_WARNING, errno,
                    340:              "Cannot leave group %s on interface %s",
                    341:              inet_fmt(grp, s1, sizeof(s1)), inet_fmt(v->uv_lcl_addr, s2, sizeof(s2)));
                    342: #endif /* __linux__ */
                    343:     }
                    344: }
                    345: 
                    346: /*
                    347:  * Fill struct vifctl using corresponding fields from struct uvif.
                    348:  */
                    349: static void uvif_to_vifctl(struct vifctl *vc, struct uvif *v)
                    350: {
                    351:     /* XXX: we don't support VIFF_TUNNEL; VIFF_SRCRT is obsolete */
                    352:     vc->vifc_flags          = 0;
                    353:     if (v->uv_flags & VIFF_REGISTER)
                    354:        vc->vifc_flags      |= VIFF_REGISTER;
                    355:     vc->vifc_threshold       = v->uv_threshold;
                    356:     vc->vifc_rate_limit      = v->uv_rate_limit;
                    357:     vc->vifc_lcl_addr.s_addr = v->uv_lcl_addr;
                    358:     vc->vifc_rmt_addr.s_addr = v->uv_rmt_addr;
                    359: }
                    360: 
                    361: /*
                    362:  * Add a virtual interface in the kernel.
                    363:  */
                    364: void k_add_vif(int socket, vifi_t vifi, struct uvif *v)
                    365: {
                    366:     struct vifctl vc;
                    367: 
                    368:     vc.vifc_vifi = vifi;
                    369:     uvif_to_vifctl(&vc, v);
                    370:     if (setsockopt(socket, IPPROTO_IP, MRT_ADD_VIF, (char *)&vc, sizeof(vc)) < 0)
                    371:        logit(LOG_ERR, errno, "Failed adding VIF %d (MRT_ADD_VIF) for iface %s",
                    372:              vifi, v->uv_name);
                    373: }
                    374: 
                    375: 
                    376: /*
                    377:  * Delete a virtual interface in the kernel.
                    378:  */
                    379: void k_del_vif(int socket, vifi_t vifi, struct uvif *v __attribute__((unused)))
                    380: {
                    381:     /*
                    382:      * Unfortunately Linux MRT_DEL_VIF API differs a bit from the *BSD one.  It
                    383:      * expects to receive a pointer to struct vifctl that corresponds to the VIF
                    384:      * we're going to delete.  *BSD systems on the other hand exepect only the
                    385:      * index of that VIF.
                    386:      */
                    387: #ifdef __linux__
                    388:     struct vifctl vc;
                    389: 
                    390:     vc.vifc_vifi = vifi;
                    391:     uvif_to_vifctl(&vc, v);           /* 'v' is used only on Linux systems. */
                    392: 
                    393:     if (setsockopt(socket, IPPROTO_IP, MRT_DEL_VIF, (char *)&vc, sizeof(vc)) < 0)
                    394: #else /* *BSD et al. */
                    395:     if (setsockopt(socket, IPPROTO_IP, MRT_DEL_VIF, (char *)&vifi, sizeof(vifi)) < 0)
                    396: #endif /* !__linux__ */
                    397:     {
                    398:        if (errno == EADDRNOTAVAIL || errno == EINVAL)
                    399:            return;
                    400: 
                    401:        logit(LOG_ERR, errno, "Failed removing VIF %d (MRT_DEL_VIF)", vifi);
                    402:     }
                    403: }
                    404: 
                    405: 
                    406: /*
                    407:  * Delete all MFC entries for particular routing entry from the kernel.
                    408:  */
                    409: int k_del_mfc(int socket, uint32_t source, uint32_t group)
                    410: {
                    411:     struct mfcctl mc;
                    412: 
                    413:     memset(&mc, 0, sizeof(mc));
                    414:     mc.mfcc_origin.s_addr   = source;
                    415:     mc.mfcc_mcastgrp.s_addr = group;
                    416: 
                    417:     if (setsockopt(socket, IPPROTO_IP, MRT_DEL_MFC, (char *)&mc, sizeof(mc)) < 0) {
                    418:        logit(LOG_WARNING, errno, "Failed removing MFC entry src %s, grp %s",
                    419:              inet_fmt(mc.mfcc_origin.s_addr, s1, sizeof(s1)),
                    420:              inet_fmt(mc.mfcc_mcastgrp.s_addr, s2, sizeof(s2)));
                    421: 
                    422:        return FALSE;
                    423:     }
                    424: 
                    425:     logit(LOG_INFO, 0, "Removed MFC entry src %s, grp %s",
                    426:        inet_fmt(mc.mfcc_origin.s_addr, s1, sizeof(s1)),
                    427:        inet_fmt(mc.mfcc_mcastgrp.s_addr, s2, sizeof(s2)));
                    428: 
                    429:     return TRUE;
                    430: }
                    431: 
                    432: 
                    433: /*
                    434:  * Install/modify a MFC entry in the kernel
                    435:  */
                    436: int k_chg_mfc(int socket, uint32_t source, uint32_t group, vifi_t iif, vifbitmap_t oifs, uint32_t rp_addr __attribute__((unused)))
                    437: {
                    438:     char           input[IFNAMSIZ], output[MAXVIFS * (IFNAMSIZ + 2)] = "";
                    439:     vifi_t        vifi;
                    440:     struct uvif   *v;
                    441:     struct mfcctl  mc;
                    442: 
                    443:     memset(&mc, 0, sizeof(mc));
                    444:     mc.mfcc_origin.s_addr    = source;
                    445:     mc.mfcc_mcastgrp.s_addr  = group;
                    446:     mc.mfcc_parent          = iif;
                    447:     /*
                    448:      * draft-ietf-pim-sm-v2-new-05.txt section 4.2 mentions iif is removed
                    449:      * at the packet forwarding phase
                    450:      */
                    451:     VIFM_CLR(mc.mfcc_parent, oifs);
                    452: 
                    453:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    454:        if (VIFM_ISSET(vifi, oifs)) {
                    455:            mc.mfcc_ttls[vifi] = v->uv_threshold;
                    456:            if (output[0] != 0)
                    457:                strlcat(output, ", ", sizeof(output));
                    458:            strlcat(output, v->uv_name, sizeof(output));
                    459:        } else {
                    460:            mc.mfcc_ttls[vifi] = 0;
                    461:        }
                    462:     }
                    463:     strlcpy(input, uvifs[iif].uv_name, sizeof(input));
                    464: 
                    465: #ifdef PIM_REG_KERNEL_ENCAP
                    466:     mc.mfcc_rp_addr.s_addr = rp_addr;
                    467: #endif
                    468:     if (setsockopt(socket, IPPROTO_IP, MRT_ADD_MFC, (char *)&mc, sizeof(mc)) < 0) {
                    469:        logit(LOG_WARNING, errno, "Failed adding MFC entry src %s grp %s from %s to %s",
                    470:              inet_fmt(mc.mfcc_origin.s_addr, s1, sizeof(s1)),
                    471:              inet_fmt(mc.mfcc_mcastgrp.s_addr, s2, sizeof(s2)),
                    472:              input, output);
                    473: 
                    474:        return FALSE;
                    475:     }
                    476: 
                    477:     logit(LOG_INFO, 0, "Added kernel MFC entry src %s grp %s from %s to %s",
                    478:          inet_fmt(mc.mfcc_origin.s_addr, s1, sizeof(s1)),
                    479:          inet_fmt(mc.mfcc_mcastgrp.s_addr, s2, sizeof(s2)),
                    480:          input, output);
                    481: 
                    482:     return TRUE;
                    483: }
                    484: 
                    485: 
                    486: /*
                    487:  * Get packet counters for particular interface
                    488:  * XXX: TODO: currently not used, but keep just in case we need it later.
                    489:  */
                    490: int k_get_vif_count(vifi_t vifi, struct vif_count *retval)
                    491: {
                    492:     struct sioc_vif_req vreq;
                    493: 
                    494:     memset(&vreq, 0, sizeof(vreq));
                    495:     vreq.vifi = vifi;
                    496:     if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
                    497:        logit(LOG_WARNING, errno, "Failed reading kernel packet count (SIOCGETVIFCNT) on vif %d", vifi);
                    498: 
                    499:        retval->icount =
                    500:            retval->ocount =
                    501:            retval->ibytes =
                    502:            retval->obytes = 0xffffffff;
                    503: 
                    504:        return 1;
                    505:     }
                    506: 
                    507:     retval->icount = vreq.icount;
                    508:     retval->ocount = vreq.ocount;
                    509:     retval->ibytes = vreq.ibytes;
                    510:     retval->obytes = vreq.obytes;
                    511: 
                    512:     return 0;
                    513: }
                    514: 
                    515: 
                    516: /*
                    517:  * Gets the number of packets, bytes, and number op packets arrived
                    518:  * on wrong if in the kernel for particular (S,G) entry.
                    519:  */
                    520: int k_get_sg_cnt(int socket, uint32_t source, uint32_t group, struct sg_count *retval)
                    521: {
                    522:     struct sioc_sg_req sgreq;
                    523: 
                    524:     memset(&sgreq, 0, sizeof(sgreq));
                    525:     sgreq.src.s_addr = source;
                    526:     sgreq.grp.s_addr = group;
                    527:     if ((ioctl(socket, SIOCGETSGCNT, (char *)&sgreq) < 0) || (sgreq.wrong_if == 0xffffffff)) {
                    528:        /* XXX: ipmulti-3.5 has bug in ip_mroute.c, get_sg_cnt():
                    529:         * the return code is always 0, so this is why we need to check
                    530:         * the wrong_if value.
                    531:         */
                    532:        logit(LOG_WARNING, errno, "Failed reading kernel count (SIOCGETSGCNT) for (S,G) on (%s, %s)",
                    533:              inet_fmt(source, s1, sizeof(s1)), inet_fmt(group, s2, sizeof(s2)));
                    534:        retval->pktcnt = retval->bytecnt = retval->wrong_if = ~0;
                    535: 
                    536:        return 1;
                    537:     }
                    538: 
                    539:     retval->pktcnt = sgreq.pktcnt;
                    540:     retval->bytecnt = sgreq.bytecnt;
                    541:     retval->wrong_if = sgreq.wrong_if;
                    542: 
                    543:     return 0;
                    544: }
                    545: 
                    546: /**
                    547:  * Local Variables:
                    548:  *  version-control: t
                    549:  *  indent-tabs-mode: t
                    550:  *  c-file-style: "ellemtel"
                    551:  *  c-basic-offset: 4
                    552:  * End:
                    553:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>