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

1.1       misho       1: /*
                      2:  *  Copyright (c) 1998 by the University of Southern California.
                      3:  *  All rights reserved.
                      4:  *
                      5:  *  Permission to use, copy, modify, and distribute this software and
                      6:  *  its documentation in source and binary forms for lawful
                      7:  *  purposes and without fee is hereby granted, provided
                      8:  *  that the above copyright notice appear in all copies and that both
                      9:  *  the copyright notice and this permission notice appear in supporting
                     10:  *  documentation, and that any documentation, advertising materials,
                     11:  *  and other materials related to such distribution and use acknowledge
                     12:  *  that the software was developed by the University of Southern
                     13:  *  California and/or Information Sciences Institute.
                     14:  *  The name of the University of Southern California may not
                     15:  *  be used to endorse or promote products derived from this software
                     16:  *  without specific prior written permission.
                     17:  *
                     18:  *  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
                     19:  *  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
                     20:  *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
                     21:  *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     22:  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
                     23:  *  NON-INFRINGEMENT.
                     24:  *
                     25:  *  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
                     26:  *  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
                     27:  *  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
                     28:  *  THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     29:  *
                     30:  *  Other copyrights might apply to parts of this software and are so
                     31:  *  noted when applicable.
                     32:  */
                     33: /*
                     34:  *  Questions concerning this software should be directed to 
                     35:  *  Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
                     36:  *
                     37:  *  $Id: kern.c,v 1.2 1998/06/01 22:27:14 kurtw Exp $
                     38:  */
                     39: /*
                     40:  * Part of this program has been derived from mrouted.
                     41:  * The mrouted program is covered by the license in the accompanying file
                     42:  * named "LICENSE.mrouted".
                     43:  *
                     44:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
                     45:  * Leland Stanford Junior University.
                     46:  *
                     47:  */
                     48: 
                     49: #include "defs.h"
                     50: 
                     51: #ifdef RAW_OUTPUT_IS_RAW
                     52: int curttl = 0;
                     53: #endif
                     54: 
                     55: 
                     56: /*
                     57:  * Open/init the multicast routing in the kernel and sets the MRT_ASSERT
                     58:  * flag in the kernel.
                     59:  * 
                     60:  */
                     61: void
                     62: k_init_pim(socket)
                     63:   int socket;
                     64: {
                     65:     int v = 1;
                     66:     
                     67:     if (setsockopt(socket, IPPROTO_IP, MRT_INIT, (char *)&v, sizeof(int)) < 0)
                     68:        log(LOG_ERR, errno, "cannot enable multicast routing in kernel");
                     69:     
                     70:     if(setsockopt(socket, IPPROTO_IP, MRT_ASSERT, (char *)&v, sizeof(int)) < 0)
                     71:        log(LOG_ERR, errno, "cannot set ASSERT flag in kernel");
                     72: }
                     73: 
                     74: 
                     75: /*
                     76:  * Stops the multicast routing in the kernel and resets the MRT_ASSERT
                     77:  * flag in the kernel.
                     78:  */
                     79: void
                     80: k_stop_pim(socket)
                     81:     int socket;
                     82: {
                     83:     int v = 0;
                     84:     
                     85:     if (setsockopt(socket, IPPROTO_IP, MRT_DONE, (char *)NULL, 0) < 0)
                     86:        log(LOG_ERR, errno, "cannot disable multicast routing in kernel");
                     87:     
                     88:     if(setsockopt(socket, IPPROTO_IP, MRT_ASSERT, (char *)&v, sizeof(int)) < 0)
                     89:        log(LOG_ERR, errno, "cannot reset ASSERT flag in kernel");
                     90: }
                     91: 
                     92: 
                     93: /*
                     94:  * Set the socket receiving buffer. `bufsize` is the preferred size,
                     95:  * `minsize` is the smallest acceptable size.
                     96:  */
                     97: void k_set_rcvbuf(socket, bufsize, minsize)
                     98:     int socket;
                     99:     int bufsize;
                    100:     int minsize;
                    101: {
                    102:     int delta = bufsize / 2;
                    103:     int iter = 0;
                    104:     
                    105:     /*
                    106:      * Set the socket buffer.  If we can't set it as large as we
                    107:      * want, search around to try to find the highest acceptable
                    108:      * value.  The highest acceptable value being smaller than
                    109:      * minsize is a fatal error.
                    110:      */
                    111:     if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                    112:                   (char *)&bufsize, sizeof(bufsize)) < 0) {
                    113:        bufsize -= delta;
                    114:        while (1) {
                    115:            iter++;
                    116:            if (delta > 1)
                    117:              delta /= 2;
                    118:            
                    119:            if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                    120:                           (char *)&bufsize, sizeof(bufsize)) < 0) {
                    121:                bufsize -= delta;
                    122:            } else {
                    123:                if (delta < 1024)
                    124:                    break;
                    125:                bufsize += delta;
                    126:            }
                    127:        }
                    128:        if (bufsize < minsize) {
                    129:            log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
                    130:                bufsize, minsize);
                    131:            /*NOTREACHED*/
                    132:        }
                    133:     }
                    134:     IF_DEBUG(DEBUG_KERN)
                    135:        log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
                    136:            bufsize, iter);
                    137: }
                    138: 
                    139: 
                    140: /*
                    141:  * Set/reset the IP_HDRINCL option. My guess is we don't need it for raw
                    142:  * sockets, but having it here won't hurt. Well, unless you are running
                    143:  * an older version of FreeBSD (older than 2.2.2). If the multicast
                    144:  * raw packet is bigger than 208 bytes, then IP_HDRINCL triggers a bug
                    145:  * in the kernel and "panic". The kernel patch for netinet/ip_raw.c
                    146:  * coming with this distribution fixes it.
                    147:  */
                    148: void k_hdr_include(socket, bool)
                    149:     int socket;
                    150:     int bool;
                    151: {
                    152: #ifdef IP_HDRINCL
                    153:     if (setsockopt(socket, IPPROTO_IP, IP_HDRINCL,
                    154:                   (char *)&bool, sizeof(bool)) < 0)
                    155:        log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);
                    156: #endif
                    157: }
                    158: 
                    159: 
                    160: /*
                    161:  * Set the default TTL for the multicast packets outgoing from this
                    162:  * socket.
                    163:  * TODO: Does it affect the unicast packets?
                    164:  */
                    165: void k_set_ttl(socket, t)
                    166:     int socket;
                    167:     int t;
                    168: {
                    169: #ifdef RAW_OUTPUT_IS_RAW
                    170:     curttl = t;
                    171: #else
                    172:     u_char ttl;
                    173:     
                    174:     ttl = t;
                    175:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,
                    176:                   (char *)&ttl, sizeof(ttl)) < 0)
                    177:        log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
                    178: #endif
                    179: }
                    180: 
                    181: 
                    182: /*
                    183:  * Set/reset the IP_MULTICAST_LOOP. Set/reset is specified by "flag".
                    184:  */
                    185: void k_set_loop(socket, flag)
                    186:     int socket;
                    187:     int flag;
                    188: {
                    189:     u_char loop;
                    190: 
                    191:     loop = flag;
                    192:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
                    193:                   (char *)&loop, sizeof(loop)) < 0)
                    194:        log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
                    195: }
                    196: 
                    197: 
                    198: /*
                    199:  * Set the IP_MULTICAST_IF option on local interface ifa.
                    200:  */
                    201: void k_set_if(socket, ifa)
                    202:     int socket;
                    203:     u_int32 ifa;
                    204: {
                    205:     struct in_addr adr;
                    206: 
                    207:     adr.s_addr = ifa;
                    208:     if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF,
                    209:                   (char *)&adr, sizeof(adr)) < 0)
                    210:        log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
                    211:            inet_fmt(ifa, s1));
                    212: }
                    213: 
                    214: 
                    215: /*
                    216:  * Join a multicast grp group on local interface ifa.
                    217:  */
                    218: void k_join(socket, grp, ifa)
                    219:     int socket;
                    220:     u_int32 grp;
                    221:     u_int32 ifa;
                    222: {
                    223:     struct ip_mreq mreq;
                    224:     
                    225:     mreq.imr_multiaddr.s_addr = grp;
                    226:     mreq.imr_interface.s_addr = ifa;
                    227: 
                    228:     if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                    229:                   (char *)&mreq, sizeof(mreq)) < 0)
                    230:        log(LOG_WARNING, errno, "cannot join group %s on interface %s",
                    231:            inet_fmt(grp, s1), inet_fmt(ifa, s2));
                    232: }
                    233: 
                    234: 
                    235: /*
                    236:  * Leave a multicats grp group on local interface ifa.
                    237:  */
                    238: void k_leave(socket, grp, ifa)
                    239:     int socket;
                    240:     u_int32 grp;
                    241:     u_int32 ifa;
                    242: {
                    243:     struct ip_mreq mreq;
                    244: 
                    245:     mreq.imr_multiaddr.s_addr = grp;
                    246:     mreq.imr_interface.s_addr = ifa;
                    247:     
                    248:     if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                    249:                   (char *)&mreq, sizeof(mreq)) < 0)
                    250:        log(LOG_WARNING, errno, "cannot leave group %s on interface %s",
                    251:            inet_fmt(grp, s1), inet_fmt(ifa, s2));
                    252: }
                    253: 
                    254: 
                    255: /*
                    256:  * Add a virtual interface in the kernel.
                    257:  */
                    258: void k_add_vif(socket, vifi, v)
                    259:     int socket;
                    260:     vifi_t vifi;
                    261:     struct uvif *v;
                    262: {
                    263:     struct vifctl vc;
                    264: 
                    265:     vc.vifc_vifi            = vifi;
                    266:     /* TODO: only for DVMRP tunnels?
                    267:     vc.vifc_flags           = v->uv_flags & VIFF_KERNEL_FLAGS;
                    268:     */
                    269:     vc.vifc_flags           = v->uv_flags;
                    270:     vc.vifc_threshold       = v->uv_threshold;
                    271:     vc.vifc_rate_limit     = v->uv_rate_limit;
                    272:     vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
                    273:     vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
                    274: 
                    275:     if (setsockopt(socket, IPPROTO_IP, MRT_ADD_VIF,
                    276:                   (char *)&vc, sizeof(vc)) < 0)
                    277:        log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
                    278: }
                    279: 
                    280: 
                    281: /*
                    282:  * Delete a virtual interface in the kernel.
                    283:  */
                    284: void k_del_vif(socket, vifi)
                    285:     int socket;
                    286:     vifi_t vifi;
                    287: {
                    288:     if (setsockopt(socket, IPPROTO_IP, MRT_DEL_VIF,
                    289:                   (char *)&vifi, sizeof(vifi)) < 0)
                    290:        log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
                    291: }
                    292: 
                    293: 
                    294: /*
                    295:  * Delete all MFC entries for particular routing entry from the kernel.
                    296:  */
                    297: int
                    298: k_del_mfc(socket, source, group)
                    299:     int socket;
                    300:     u_int32 source;
                    301:     u_int32 group;
                    302: {
                    303:     struct mfcctl mc;
                    304: 
                    305:     mc.mfcc_origin.s_addr   = source;
                    306:     mc.mfcc_mcastgrp.s_addr = group;
                    307:        
                    308:     if (setsockopt(socket, IPPROTO_IP, MRT_DEL_MFC, (char *)&mc,
                    309:                   sizeof(mc)) < 0) {
                    310:        log(LOG_WARNING, errno, "setsockopt k_del_mfc");
                    311:        return FALSE;
                    312:     }
                    313:        
                    314:     IF_DEBUG(DEBUG_MFC)
                    315:        log(LOG_DEBUG, 0, "Deleted MFC entry: src %s, grp %s",
                    316:            inet_fmt(mc.mfcc_origin.s_addr, s1),
                    317:            inet_fmt(mc.mfcc_mcastgrp.s_addr, s2));
                    318: 
                    319:     return(TRUE);
                    320: }
                    321: 
                    322: 
                    323: /*
                    324:  * Install/modify a MFC entry in the kernel
                    325:  */
                    326: int
                    327: k_chg_mfc(socket, source, group, iif, oifs)
                    328:     int socket;
                    329:     u_int32 source;
                    330:     u_int32 group;
                    331:     vifi_t iif;
                    332:     vifbitmap_t oifs;
                    333: {
                    334:     struct mfcctl mc;
                    335:     vifi_t vifi;
                    336:     struct uvif *v;
                    337: 
                    338:     mc.mfcc_origin.s_addr = source;
                    339: #ifdef OLD_KERNEL
                    340:     mc.mfcc_originmas.s_addr = 0xffffffff;    /* Got it from mrouted-3.9 */
                    341: #endif /* OLD_KERNEL */
                    342:     mc.mfcc_mcastgrp.s_addr = group;
                    343:     mc.mfcc_parent = iif;
                    344:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    345:        if (VIFM_ISSET(vifi, oifs))
                    346:            mc.mfcc_ttls[vifi] = v->uv_threshold;
                    347:        else
                    348:            mc.mfcc_ttls[vifi] = 0;
                    349:     }
                    350:     
                    351:     if (setsockopt(socket, IPPROTO_IP, MRT_ADD_MFC, (char *)&mc,
                    352:                    sizeof(mc)) < 0) {
                    353:         log(LOG_WARNING, errno,
                    354:            "setsockopt MRT_ADD_MFC for source %s and group %s",
                    355:            inet_fmt(source, s1), inet_fmt(group, s2));
                    356:         return(FALSE);
                    357:     }
                    358:     return(TRUE);
                    359: }
                    360: 
                    361: 
                    362: /*
                    363:  * Get packet counters for particular interface
                    364:  */
                    365: /*
                    366:  * XXX: TODO: currently not used, but keep just in case we need it later.
                    367:  */
                    368: int k_get_vif_count(vifi, retval)
                    369:     vifi_t vifi;
                    370:     struct vif_count *retval;
                    371: {
                    372:     struct sioc_vif_req vreq;
                    373:     
                    374:     vreq.vifi = vifi;
                    375:     if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
                    376:        log(LOG_WARNING, errno, "SIOCGETVIFCNT on vif %d", vifi);
                    377:        retval->icount = retval->ocount = retval->ibytes =
                    378:            retval->obytes = 0xffffffff;
                    379:        return (1);
                    380:     }
                    381:     retval->icount = vreq.icount;
                    382:     retval->ocount = vreq.ocount;
                    383:     retval->ibytes = vreq.ibytes;
                    384:     retval->obytes = vreq.obytes;
                    385:     return (0);
                    386: }
                    387: 
                    388: 
                    389: /*
                    390:  * Gets the number of packets, bytes, and number op packets arrived
                    391:  * on wrong if in the kernel for particular (S,G) entry.
                    392:  */
                    393: int
                    394: k_get_sg_cnt(socket, source, group, retval)
                    395:     int socket;    /* udp_socket */
                    396:     u_int32 source;
                    397:     u_int32 group;
                    398:     struct sg_count *retval;
                    399: {
                    400:     struct sioc_sg_req sgreq;
                    401:     
                    402:     sgreq.src.s_addr = source;
                    403:     sgreq.grp.s_addr = group;
                    404:     if ((ioctl(socket, SIOCGETSGCNT, (char *)&sgreq) < 0)
                    405:        || (sgreq.wrong_if == 0xffffffff)) {
                    406:        /* XXX: ipmulti-3.5 has bug in ip_mroute.c, get_sg_cnt():
                    407:         * the return code is always 0, so this is why we need to check
                    408:         * the wrong_if value.
                    409:         */
                    410:        log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
                    411:            inet_fmt(source, s1), inet_fmt(group, s2));
                    412:        retval->pktcnt = retval->bytecnt = retval->wrong_if = ~0;
                    413:        return(1);
                    414:     }
                    415:     retval->pktcnt = sgreq.pktcnt;
                    416:     retval->bytecnt = sgreq.bytecnt;
                    417:     retval->wrong_if = sgreq.wrong_if;
                    418:     return(0);
                    419: }
                    420: 
                    421: 
                    422: 

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