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

1.1       misho       1: /*
                      2:  * Copyright (c) 1993, 1998 by the University of Southern California
                      3:  * All rights reserved.
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software and its
                      6:  * documentation in source and binary forms for lawful purposes
                      7:  * and without fee is hereby granted, provided that the above copyright
                      8:  * notice appear in all copies and that both the copyright notice and
                      9:  * this permission notice appear in supporting documentation. and that
                     10:  * any documentation, advertising materials, and other materials related
                     11:  * to such distribution and use acknowledge that the software was
                     12:  * developed by the University of Southern California, Information
                     13:  * Sciences Institute.  The name of the University may not be used to
                     14:  * endorse or promote products derived from this software without
                     15:  * specific prior written permission.
                     16:  *
                     17:  * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
                     18:  * the suitability of this software for any purpose.  THIS SOFTWARE IS
                     19:  * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
                     20:  * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     22:  *
                     23:  * Other copyrights might apply to parts of this software and are so
                     24:  * noted when applicable.
                     25:  */
                     26: 
                     27: /* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
                     28:  * April 1995.
                     29:  *
                     30:  * Modified by Kurtw Windisch (kurtw@antc.uoregon.edu) for use with 
                     31:  * Dense-mode pimd.
                     32:  */
                     33: 
                     34: /* May 1995 -- Added support for Route Change Notification */
                     35: 
                     36: #ifdef RSRR
                     37: 
                     38: #include "defs.h"
                     39: #include <sys/param.h>
                     40: #if (defined(BSD) && (BSD >= 199103))
                     41: #include <stddef.h>
                     42: #endif
                     43: 
                     44: 
                     45: /*
                     46:  * Exported variables.
                     47:  */
                     48: int rsrr_socket;               /* interface to reservation protocol */
                     49: 
                     50: /* 
                     51:  * Global RSRR variables.
                     52:  */
                     53: char *rsrr_recv_buf;           /* RSRR receive buffer */
                     54: char *rsrr_send_buf;           /* RSRR send buffer */
                     55: 
                     56: struct sockaddr_un client_addr;
                     57: int client_length = sizeof(client_addr);
                     58: 
                     59: 
                     60: /*
                     61:  * Local functions definition
                     62:  */
                     63: static void    rsrr_accept    __P((int recvlen));
                     64: static void    rsrr_accept_iq __P((void));
                     65: static int     rsrr_accept_rq __P((struct rsrr_rq *route_query, u_int8 flags,
                     66:                                    struct gtable *gt_notify));
                     67: static void    rsrr_read      __P((int, fd_set *));
                     68: static int     rsrr_send      __P((int sendlen));
                     69: static void    rsrr_cache     __P((struct gtable *gt,
                     70:                                        struct rsrr_rq *route_query));
                     71: 
                     72: /* Initialize RSRR socket */
                     73: void
                     74: rsrr_init()
                     75: {
                     76:     int servlen;
                     77:     struct sockaddr_un serv_addr;
                     78: 
                     79:     rsrr_recv_buf = malloc(RSRR_MAX_LEN);
                     80:     rsrr_send_buf = malloc(RSRR_MAX_LEN);
                     81: 
                     82:     if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
                     83:        log(LOG_ERR, errno, "Can't create RSRR socket");
                     84: 
                     85:     unlink(RSRR_SERV_PATH);
                     86:     bzero((char *) &serv_addr, sizeof(serv_addr));
                     87:     serv_addr.sun_family = AF_UNIX;
                     88:     strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
                     89: #if (defined(BSD) && (BSD >= 199103))
                     90:     servlen = offsetof(struct sockaddr_un, sun_path) +
                     91:                strlen(serv_addr.sun_path);
                     92:     serv_addr.sun_len = servlen;
                     93: #else
                     94:     servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
                     95: #endif
                     96:  
                     97:     if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
                     98:        log(LOG_ERR, errno, "Can't bind RSRR socket");
                     99: 
                    100:     if (register_input_handler(rsrr_socket, rsrr_read) < 0)
                    101:        log(LOG_ERR, 0, "Couldn't register RSRR as an input handler");
                    102: }
                    103: 
                    104: /* Read a message from the RSRR socket */
                    105: static void
                    106: rsrr_read(f, rfd)
                    107:        int f;
                    108:        fd_set *rfd;
                    109: {
                    110:     register int rsrr_recvlen;
                    111:     
                    112:     bzero((char *) &client_addr, sizeof(client_addr));
                    113:     rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
                    114:                            0, (struct sockaddr *)&client_addr,
                    115:                            &client_length);
                    116:     if (rsrr_recvlen < 0) {    
                    117:        if (errno != EINTR)
                    118:            log(LOG_ERR, errno, "RSRR recvfrom");
                    119:        return;
                    120:     }
                    121:     rsrr_accept(rsrr_recvlen);
                    122: }
                    123: 
                    124: /*
                    125:  * Accept a message from the reservation protocol and take
                    126:  * appropriate action.
                    127:  */
                    128: static void
                    129: rsrr_accept(recvlen)
                    130:     int recvlen;
                    131: {
                    132:     struct rsrr_header *rsrr;
                    133:     struct rsrr_rq *route_query;
                    134:     
                    135:     if (recvlen < RSRR_HEADER_LEN) {
                    136:        log(LOG_WARNING, 0,
                    137:            "Received RSRR packet of %d bytes, which is less than min size",
                    138:            recvlen);
                    139:        return;
                    140:     }
                    141:     
                    142:     rsrr = (struct rsrr_header *) rsrr_recv_buf;
                    143:     
                    144:     if (rsrr->version > RSRR_MAX_VERSION) {
                    145:        log(LOG_WARNING, 0,
                    146:            "Received RSRR packet version %d, which I don't understand",
                    147:            rsrr->version);
                    148:        return;
                    149:     }
                    150:     
                    151:     switch (rsrr->version) {
                    152:       case 1:
                    153:        switch (rsrr->type) {
                    154:          case RSRR_INITIAL_QUERY:
                    155:            /* Send Initial Reply to client */
                    156:            IF_DEBUG(DEBUG_RSRR)
                    157:                log(LOG_DEBUG, 0, "Received Initial Query\n");
                    158:            rsrr_accept_iq();
                    159:            break;
                    160:          case RSRR_ROUTE_QUERY:
                    161:            /* Check size */
                    162:            if (recvlen < RSRR_RQ_LEN) {
                    163:                log(LOG_WARNING, 0,
                    164:                    "Received Route Query of %d bytes, which is too small",
                    165:                    recvlen);
                    166:                break;
                    167:            }
                    168:            /* Get the query */
                    169:            route_query =
                    170:                (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
                    171:            IF_DEBUG(DEBUG_RSRR)
                    172:                log(LOG_DEBUG, 0,
                    173:                    "Received Route Query for src %s grp %s notification %d",
                    174:                    inet_fmt(route_query->source_addr, s1),
                    175:                    inet_fmt(route_query->dest_addr, s2),
                    176:                    BIT_TST(rsrr->flags, RSRR_NOTIFICATION_BIT));
                    177:            /* Send Route Reply to client */
                    178:            rsrr_accept_rq(route_query, rsrr->flags, (struct gtable *)NULL);
                    179:            break;
                    180:          default:
                    181:            log(LOG_WARNING, 0,
                    182:                "Received RSRR packet type %d, which I don't handle",
                    183:                rsrr->type);
                    184:            break;
                    185:        }
                    186:        break;
                    187:        
                    188:       default:
                    189:        log(LOG_WARNING, 0,
                    190:            "Received RSRR packet version %d, which I don't understand",
                    191:            rsrr->version);
                    192:        break;
                    193:     }
                    194: }
                    195: 
                    196: /* Send an Initial Reply to the reservation protocol. */
                    197: /*
                    198:  * TODO: XXX: if a new interfaces come up and _IF_ the multicast routing
                    199:  * daemon automatically include it, have to inform the RSVP daemon.
                    200:  * However, this is not in the RSRRv1 draft (just expired and is not
                    201:  * available anymore from the internet-draft ftp sites). Probably has to
                    202:  * be included in RSRRv2.
                    203:  */
                    204: static void
                    205: rsrr_accept_iq()
                    206: {
                    207:     struct rsrr_header *rsrr;
                    208:     struct rsrr_vif *vif_list;
                    209:     struct uvif *v;
                    210:     vifi_t vifi;
                    211:     int sendlen;
                    212:     
                    213:     /* Check for space.  There should be room for plenty of vifs,
                    214:      * but we should check anyway.
                    215:      */
                    216:     if (numvifs > RSRR_MAX_VIFS) {
                    217:        log(LOG_WARNING, 0,
                    218:            "Can't send RSRR Route Reply because %d is too many vifs %d",
                    219:            numvifs);
                    220:        return;
                    221:     }
                    222:     
                    223:     /* Set up message */
                    224:     rsrr = (struct rsrr_header *) rsrr_send_buf;
                    225:     rsrr->version = 1;
                    226:     rsrr->type = RSRR_INITIAL_REPLY;
                    227:     rsrr->flags = 0;
                    228:     rsrr->num = numvifs;
                    229:     
                    230:     vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
                    231:     
                    232:     /* Include the vif list. */
                    233:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    234:        vif_list[vifi].id = vifi;
                    235:        vif_list[vifi].status = 0;
                    236:        if (v->uv_flags & (VIFF_DISABLED))
                    237:            BIT_SET(vif_list[vifi].status, RSRR_DISABLED_BIT);
                    238:        vif_list[vifi].threshold = v->uv_threshold;
                    239:        vif_list[vifi].local_addr = v->uv_lcl_addr;
                    240:     }
                    241:     
                    242:     /* Get the size. */
                    243:     sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
                    244:     
                    245:     /* Send it. */
                    246:     IF_DEBUG(DEBUG_RSRR)
                    247:        log(LOG_DEBUG, 0, "Send RSRR Initial Reply");
                    248:     rsrr_send(sendlen);
                    249: }
                    250: 
                    251: /* Send a Route Reply to the reservation protocol.  The Route Query
                    252:  * contains the query to which we are responding.  The flags contain
                    253:  * the incoming flags from the query or, for route change
                    254:  * notification, the flags that should be set for the reply.  The
                    255:  * kernel table entry contains the routing info to use for a route
                    256:  * change notification.
                    257:  */
                    258: /* XXX: must modify if your routing table structure/search is different */
                    259: static int
                    260: rsrr_accept_rq(route_query, flags, gt_notify)
                    261:     struct rsrr_rq *route_query;
                    262:     u_int8 flags;
                    263:     struct gtable *gt_notify;
                    264: {
                    265:     struct rsrr_header *rsrr;
                    266:     struct rsrr_rr *route_reply;
                    267:     int sendlen;
                    268:     struct gtable *gt;
                    269:     int status_ok;
                    270:     
                    271:     /* Set up message */
                    272:     rsrr = (struct rsrr_header *) rsrr_send_buf;
                    273:     rsrr->version = 1;
                    274:     rsrr->type = RSRR_ROUTE_REPLY;
                    275:     rsrr->flags = flags;
                    276:     rsrr->num = 0;
                    277:     
                    278:     route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
                    279:     route_reply->dest_addr = route_query->dest_addr;
                    280:     route_reply->source_addr = route_query->source_addr;
                    281:     route_reply->query_id = route_query->query_id;
                    282:     
                    283:     /* Blank routing entry for error. */
                    284:     route_reply->in_vif = 0;
                    285:     route_reply->reserved = 0;
                    286:     route_reply->out_vif_bm = 0;
                    287:     
                    288:     /* Get the size. */
                    289:     sendlen = RSRR_RR_LEN;
                    290:     
                    291:     /* If routing table entry is defined, then we are sending a Route Reply
                    292:      * due to a Route Change Notification event.  Use the routing table entry
                    293:      * to supply the routing info.
                    294:      */
                    295:     status_ok = FALSE;
                    296:     if (gt_notify) {
                    297:        /* Include the routing entry. */
                    298:        route_reply->in_vif = gt_notify->incoming;
                    299:        route_reply->out_vif_bm = gt_notify->oifs;
                    300:        gt = gt_notify;
                    301:        status_ok = TRUE;
                    302:     } else if ((gt = find_route(route_query->source_addr,
                    303:                                route_query->dest_addr,
                    304:                                MRTF_SG | MRTF_WC | MRTF_PMBR,
                    305:                                DONT_CREATE)) != (struct gtable *)NULL) {
                    306:        status_ok = TRUE;
                    307:        route_reply->in_vif = gt->incoming;
                    308:        route_reply->out_vif_bm = gt->oifs;
                    309:     }
                    310:     if (status_ok != TRUE) {
                    311:        /* Set error bit. */
                    312:        rsrr->flags = 0;
                    313:        BIT_SET(rsrr->flags, RSRR_ERROR_BIT);
                    314:     }
                    315:     else {
                    316:        /* Cache reply if using route change notification. */
                    317:        if (BIT_TST(flags, RSRR_NOTIFICATION_BIT)) {
                    318:            /* TODO: XXX: Originally the rsrr_cache() call was first, but
                    319:             * I think this is incorrect, because rsrr_cache() checks the
                    320:             * rsrr_send_buf "flag" first.
                    321:             */
                    322:            BIT_SET(rsrr->flags, RSRR_NOTIFICATION_BIT);
                    323:            rsrr_cache(gt, route_query);
                    324:        }
                    325:     }
                    326:     
                    327:     IF_DEBUG(DEBUG_RSRR)
                    328:        log(LOG_DEBUG, 0, "%sSend RSRR Route Reply for src %s dst %s in vif %d out vifs 0x%x\n",
                    329:            gt_notify ? "Route Change: " : "",
                    330:            inet_fmt(route_reply->source_addr,s1),
                    331:            inet_fmt(route_reply->dest_addr,s2),
                    332:            route_reply->in_vif, route_reply->out_vif_bm);
                    333:     
                    334:     /* Send it. */
                    335:     return rsrr_send(sendlen);
                    336: }
                    337: 
                    338: /* Send an RSRR message. */
                    339: static int
                    340: rsrr_send(sendlen)
                    341:     int sendlen;
                    342: {
                    343:     int error;
                    344:     
                    345:     /* Send it. */
                    346:     error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
                    347:                   (struct sockaddr *)&client_addr, client_length);
                    348:     
                    349:     /* Check for errors. */
                    350:     if (error < 0) {
                    351:        log(LOG_WARNING, errno, "Failed send on RSRR socket");
                    352:     } else if (error != sendlen) {
                    353:        log(LOG_WARNING, 0,
                    354:            "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
                    355:     }
                    356:     return error;
                    357: }
                    358: 
                    359: /* TODO: need to sort the rsrr_cache entries for faster access */
                    360: /* Cache a message being sent to a client.  Currently only used for
                    361:  * caching Route Reply messages for route change notification.
                    362:  */
                    363: static void
                    364: rsrr_cache(gt, route_query)
                    365:     struct gtable *gt;
                    366:     struct rsrr_rq *route_query;
                    367: {
                    368:     struct rsrr_cache *rc, **rcnp;
                    369:     struct rsrr_header *rsrr;
                    370: 
                    371:     rsrr = (struct rsrr_header *) rsrr_send_buf;
                    372: 
                    373:     rcnp = &gt->rsrr_cache;
                    374:     while ((rc = *rcnp) != NULL) {
                    375:        if ((rc->route_query.source_addr == 
                    376:             route_query->source_addr) &&
                    377:            (rc->route_query.dest_addr == 
                    378:             route_query->dest_addr) &&
                    379:            (!strcmp(rc->client_addr.sun_path, client_addr.sun_path))) {
                    380:            /* Cache entry already exists.
                    381:             * Check if route notification bit has been cleared.
                    382:             */
                    383:            if (!BIT_TST(rsrr->flags, RSRR_NOTIFICATION_BIT)) {
                    384:                /* Delete cache entry. */
                    385:                *rcnp = rc->next;
                    386:                free(rc);
                    387:            } else {
                    388:                /* Update */
                    389:                /* TODO: XXX: No need to update iif, oifs, flags */
                    390:                rc->route_query.query_id = route_query->query_id;
                    391:                IF_DEBUG(DEBUG_RSRR)
                    392:                    log(LOG_DEBUG, 0,
                    393:                        "Update cached query id %ld from client %s\n",
                    394:                        rc->route_query.query_id, rc->client_addr.sun_path);
                    395:            }
                    396:            return;
                    397:        }
                    398:        rcnp = &rc->next;
                    399:     }
                    400:     
                    401:     /* Cache entry doesn't already exist.  Create one and insert at
                    402:      * front of list.
                    403:      */
                    404:     rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache));
                    405:     if (rc == NULL)
                    406:        log(LOG_ERR, 0, "ran out of memory");
                    407:     rc->route_query.source_addr = route_query->source_addr;
                    408:     rc->route_query.dest_addr = route_query->dest_addr;
                    409:     rc->route_query.query_id = route_query->query_id;
                    410:     strcpy(rc->client_addr.sun_path, client_addr.sun_path);
                    411:     rc->client_length = client_length;
                    412:     rc->next = gt->rsrr_cache;
                    413:     gt->rsrr_cache = rc;
                    414:     IF_DEBUG(DEBUG_RSRR)
                    415:        log(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
                    416:            rc->route_query.query_id, rc->client_addr.sun_path);
                    417: }
                    418: 
                    419: /* Send all the messages in the cache for particular routing entry.
                    420:  * Currently this is used to send all the cached Route Reply messages
                    421:  * for route change notification.
                    422:  */
                    423: void
                    424: rsrr_cache_send(gt, notify)
                    425:     struct gtable *gt;
                    426:     int notify;
                    427: {
                    428:     struct rsrr_cache *rc, **rcnp;
                    429:     u_int8 flags = 0;
                    430: 
                    431:     if (notify)
                    432:        BIT_SET(flags, RSRR_NOTIFICATION_BIT);
                    433: 
                    434:     rcnp = &gt->rsrr_cache;
                    435: 
                    436:     while ((rc = *rcnp) != NULL) {
                    437:        if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
                    438:            IF_DEBUG(DEBUG_RSRR)
                    439:                log(LOG_DEBUG, 0,
                    440:                    "Deleting cached query id %ld from client %s\n",
                    441:                    rc->route_query.query_id, rc->client_addr.sun_path);
                    442:            /* Delete cache entry. */
                    443:            *rcnp = rc->next;
                    444:            free(rc);
                    445:        } else {
                    446:            rcnp = &rc->next;
                    447:        }
                    448:     }
                    449: }
                    450: 
                    451: /* Clean the cache by deleting or moving all entries. */
                    452: /* XXX: for PIM, if the routing entry is (S,G), will try first to
                    453:  * "transfer" the RSRR cache entry to the (*,G) or (*,*,RP) routing entry
                    454:  * (if any). If the current routing entry is (*,G), it will move the
                    455:  * cache entries to the (*,*,RP) routing entry (if existing).
                    456:  * If the old and the new (iif, oifs) are the same, then no need to send
                    457:  * route change message to the reservation daemon: just plug all entries at
                    458:  * the front of the rsrr_cache chain.
                    459:  */
                    460: void
                    461: rsrr_cache_clean(gt)
                    462:     struct gtable *gt;
                    463: {
                    464:     struct rsrr_cache *rc, *rc_next;
                    465: 
                    466:     IF_DEBUG(DEBUG_RSRR) {
                    467:        log(LOG_DEBUG, 0, "cleaning cache for source %s and group %s",
                    468:            inet_fmt(gt->source->address, s1),
                    469:            inet_fmt(gt->group->group, s2));
                    470:     }
                    471:     rc = gt->rsrr_cache;
                    472:     if (rc == (struct rsrr_cache *)NULL)
                    473:        return;
                    474: 
                    475:     while(rc) {
                    476:         rc_next = rc->next;
                    477:         free(rc);
                    478:         rc = rc_next;
                    479:      }
                    480: 
                    481:     gt->rsrr_cache = (struct rsrr_cache *)NULL;
                    482: }
                    483: 
                    484: void
                    485: rsrr_clean()
                    486: {
                    487:     unlink(RSRR_SERV_PATH);
                    488: }
                    489: 
                    490: #endif /* RSRR */

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