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

1.1       misho       1: /*
                      2:  * Copyright (c) 1993, 1998-2001.
                      3:  * The 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: /* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
                     32:  * April 1995.
                     33:  */
                     34: 
                     35: /* May 1995 -- Added support for Route Change Notification */
                     36: 
                     37: #ifdef RSRR
                     38: 
                     39: #include "defs.h"
                     40: #include <sys/param.h>
                     41: #ifdef HAVE_SA_LEN
                     42: #include <stddef.h>            /* for offsetof */
                     43: #endif
                     44: 
                     45: /* 
                     46:  * Local RSRR variables.
                     47:  */
                     48: static int rsrr_socket;                /* interface to reservation protocol */
                     49: static char *rsrr_recv_buf;            /* RSRR receive buffer */
                     50: static char *rsrr_send_buf;            /* RSRR send buffer */
                     51: 
                     52: static struct sockaddr_un client_addr;
                     53: static socklen_t client_length = sizeof(client_addr);
                     54: 
                     55: /*
                     56:  * Procedure definitions needed internally.
                     57:  */
                     58: static void    rsrr_accept    (size_t recvlen);
                     59: static void    rsrr_accept_iq (void);
                     60: static int     rsrr_accept_rq (struct rsrr_rq *route_query, uint8_t flags, struct gtable *gt_notify);
                     61: static void    rsrr_read      (int, fd_set *);
                     62: static int     rsrr_send      (int sendlen);
                     63: static void    rsrr_cache     (struct gtable *gt, struct rsrr_rq *route_query);
                     64: 
                     65: /* Initialize RSRR socket */
                     66: void rsrr_init(void)
                     67: {
                     68:     int servlen;
                     69:     struct sockaddr_un serv_addr;
                     70: 
                     71:     rsrr_recv_buf = (char *)calloc(1, RSRR_MAX_LEN);
                     72:     rsrr_send_buf = (char *)calloc(1, RSRR_MAX_LEN);
                     73:     if (!rsrr_recv_buf || !rsrr_send_buf)
                     74:        logit(LOG_ERR, 0, "Ran out of memory in rsrr_init()");
                     75: 
                     76:     if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
                     77:        logit(LOG_ERR, errno, "Cannot create RSRR socket");
                     78: 
                     79:     unlink(RSRR_SERV_PATH);
                     80:     memset(&serv_addr, 0, sizeof(serv_addr));
                     81:     serv_addr.sun_family = AF_UNIX;
                     82:     strlcpy(serv_addr.sun_path, RSRR_SERV_PATH, sizeof(serv_addr.sun_path));
                     83: #ifdef HAVE_SA_LEN
                     84:     servlen = offsetof(struct sockaddr_un, sun_path) + strlen(serv_addr.sun_path);
                     85:     serv_addr.sun_len = servlen;
                     86: #else
                     87:     servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
                     88: #endif
                     89:  
                     90:     if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
                     91:        logit(LOG_ERR, errno, "Cannot bind RSRR socket");
                     92: 
                     93:     if (register_input_handler(rsrr_socket, rsrr_read) < 0)
                     94:        logit(LOG_ERR, 0, "Could not register RSRR as an input handler");
                     95: }
                     96: 
                     97: /* Read a message from the RSRR socket */
                     98: static void rsrr_read(int fd, fd_set *rfd __attribute__ ((unused)))
                     99: {
                    100:     ssize_t len;
                    101:     
                    102:     memset(&client_addr, 0, sizeof(client_addr));
                    103:     while ((len = recvfrom(fd, rsrr_recv_buf, sizeof(rsrr_recv_buf),
                    104:                           0, (struct sockaddr *)&client_addr, &client_length)) < 0) {
                    105:        if (errno == EINTR)
                    106:            continue;           /* Received signal, retry syscall. */
                    107: 
                    108:        logit(LOG_ERR, errno, "Failed recvfrom() in rsrr_read()");
                    109:        return;
                    110:     }
                    111: 
                    112:     rsrr_accept(len);
                    113: }
                    114: 
                    115: /* Accept a message from the reservation protocol and take
                    116:  * appropriate action.
                    117:  */
                    118: static void rsrr_accept(size_t recvlen)
                    119: {
                    120:     struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_recv_buf;
                    121:     struct rsrr_rq *route_query;
                    122:     
                    123:     if (recvlen < RSRR_HEADER_LEN) {
                    124:        logit(LOG_WARNING, 0, "Received RSRR packet of %d bytes, which is less than MIN size %d.",
                    125:              recvlen, RSRR_HEADER_LEN);
                    126:        return;
                    127:     }
                    128:     
                    129:     if (rsrr->version > RSRR_MAX_VERSION || rsrr->version != 1) {
                    130:        logit(LOG_WARNING, 0, "Received RSRR packet version %d, which I don't understand",
                    131:              rsrr->version);
                    132:        return;
                    133:     }
                    134: 
                    135:     switch (rsrr->type) {
                    136:        case RSRR_INITIAL_QUERY:
                    137:            /* Send Initial Reply to client */
                    138:            IF_DEBUG(DEBUG_RSRR) {
                    139:                logit(LOG_DEBUG, 0, "Received Initial Query\n");
                    140:            }
                    141:            rsrr_accept_iq();
                    142:            break;
                    143: 
                    144:        case RSRR_ROUTE_QUERY:
                    145:            /* Check size */
                    146:            if (recvlen < RSRR_RQ_LEN) {
                    147:                logit(LOG_WARNING, 0, "Received Route Query of %d bytes, which is too small", recvlen);
                    148:                break;
                    149:            }
                    150:            /* Get the query */
                    151:            route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
                    152:            IF_DEBUG(DEBUG_RSRR) {
                    153:                logit(LOG_DEBUG, 0,
                    154:                      "Received Route Query for src %s grp %s notification %d",
                    155:                      inet_fmt(route_query->source_addr, s1, sizeof(s1)),
                    156:                      inet_fmt(route_query->dest_addr, s2, sizeof(s2)),
                    157:                      BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
                    158:            }
                    159:            /* Send Route Reply to client */
                    160:            rsrr_accept_rq(route_query, rsrr->flags, NULL);
                    161:            break;
                    162: 
                    163:        default:
                    164:            logit(LOG_WARNING, 0, "Received RSRR packet type %d, which I don't handle", rsrr->type);
                    165:            break;
                    166:     }
                    167: }
                    168: 
                    169: /* Send an Initial Reply to the reservation protocol. */
                    170: /*
                    171:  * TODO: XXX: if a new interfaces come up and _IF_ the multicast routing
                    172:  * daemon automatically include it, have to inform the RSVP daemon.
                    173:  * However, this is not in the RSRRv1 draft (just expired and is not
                    174:  * available anymore from the internet-draft ftp sites). Probably has to
                    175:  * be included in RSRRv2.
                    176:  */
                    177: static void rsrr_accept_iq(void)
                    178: {
                    179:     struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
                    180:     struct rsrr_vif *vif_list;
                    181:     struct uvif *v;
                    182:     vifi_t vifi;
                    183:     int sendlen;
                    184:     
                    185:     /* Check for space.  There should be room for plenty of vifs,
                    186:      * but we should check anyway.
                    187:      */
                    188:     if (numvifs > RSRR_MAX_VIFS) {
                    189:        logit(LOG_WARNING, 0,
                    190:            "Cannot send RSRR Route Reply because %d is too many vifs %d",
                    191:            numvifs);
                    192:        return;
                    193:     }
                    194:     
                    195:     /* Set up message */
                    196:     rsrr->version = 1;
                    197:     rsrr->type = RSRR_INITIAL_REPLY;
                    198:     rsrr->flags = 0;
                    199:     rsrr->num = numvifs;
                    200:     
                    201:     vif_list = (struct rsrr_vif *)(rsrr_send_buf + RSRR_HEADER_LEN);
                    202:     
                    203:     /* Include the vif list. */
                    204:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    205:        vif_list[vifi].id = vifi;
                    206:        vif_list[vifi].status = 0;
                    207:        if (v->uv_flags & VIFF_DISABLED)
                    208:            BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
                    209:        vif_list[vifi].threshold = v->uv_threshold;
                    210:        vif_list[vifi].local_addr = v->uv_lcl_addr;
                    211:     }
                    212:     
                    213:     /* Get the size. */
                    214:     sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
                    215:     
                    216:     /* Send it. */
                    217:     IF_DEBUG(DEBUG_RSRR) {
                    218:        logit(LOG_DEBUG, 0, "Send RSRR Initial Reply");
                    219:     }
                    220:     rsrr_send(sendlen);
                    221: }
                    222: 
                    223: /* Send a Route Reply to the reservation protocol.  The Route Query
                    224:  * contains the query to which we are responding.  The flags contain
                    225:  * the incoming flags from the query or, for route change
                    226:  * notification, the flags that should be set for the reply.  The
                    227:  * kernel table entry contains the routing info to use for a route
                    228:  * change notification.
                    229:  */
                    230: /* XXX: must modify if your routing table structure/search is different */
                    231: static int rsrr_accept_rq(struct rsrr_rq *route_query, uint8_t flags, struct gtable *gt_notify)
                    232: {
                    233:     struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
                    234:     struct rsrr_rr *route_reply;
                    235:     int sendlen;
                    236:     struct gtable *gt;
                    237:     int status_ok;
                    238: #ifdef PIM
                    239:     int found;
                    240:     uint8_t tmp_flags;
                    241:     rp_grp_entry_t *rp_grp_entry;
                    242:     grpentry_t *grpentry_ptr;
                    243: #else
                    244:     struct gtable local_g;
                    245:     struct rtentry *r;
                    246:     uint32_t mcastgrp;
                    247: #endif /* PIM */
                    248:     
                    249:     /* Set up message */
                    250:     rsrr->version = 1;
                    251:     rsrr->type = RSRR_ROUTE_REPLY;
                    252:     rsrr->flags = flags;
                    253:     rsrr->num = 0;
                    254:     
                    255:     route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
                    256:     route_reply->dest_addr = route_query->dest_addr;
                    257:     route_reply->source_addr = route_query->source_addr;
                    258:     route_reply->query_id = route_query->query_id;
                    259:     
                    260:     /* Blank routing entry for error. */
                    261:     route_reply->in_vif = 0;
                    262:     route_reply->reserved = 0;
                    263:     route_reply->out_vif_bm = 0;
                    264:     
                    265:     /* Get the size. */
                    266:     sendlen = RSRR_RR_LEN;
                    267:     
                    268:     /* If routing table entry is defined, then we are sending a Route Reply
                    269:      * due to a Route Change Notification event.  Use the routing table entry
                    270:      * to supply the routing info.
                    271:      */
                    272:     status_ok = FALSE;
                    273: #ifdef PIM
                    274:     if (gt_notify) {
                    275:        /* Include the routing entry. */
                    276:        route_reply->in_vif = gt_notify->incoming;
                    277:        route_reply->out_vif_bm = gt_notify->oifs;
                    278:        gt = gt_notify;
                    279:        status_ok = TRUE;
                    280:     } else if ((gt = find_route(route_query->source_addr,
                    281:                                route_query->dest_addr,
                    282:                                MRTF_SG | MRTF_WC | MRTF_PMBR,
                    283:                                DONT_CREATE)) != (struct gtable *)NULL) {
                    284:        status_ok = TRUE;
                    285:        route_reply->in_vif = gt->incoming;
                    286:        route_reply->out_vif_bm = gt->oifs;
                    287:     }
                    288:     if (status_ok != TRUE) {
                    289:        /* Set error bit. */
                    290:        rsrr->flags = 0;
                    291:        BIT_SET(rsrr->flags, RSRR_ERROR_BIT);
                    292:     }
                    293:     else {
                    294:        if (gt->flags & (MRTF_WC | MRTF_PMBR)) {
                    295:            tmp_flags = 0;
                    296:            BIT_SET(tmp_flags, RSRR_THIS_SENDER_SHARED_TREE);
                    297:            BIT_SET(tmp_flags, RSRR_ALL_SENDERS_SHARED_TREE);
                    298:            if (!(flags & tmp_flags)) {
                    299:                /* Check whether need to setup the (*,G) related flags */
                    300:                found = FALSE;
                    301:                if (gt->flags & MRTF_PMBR) {
                    302:                    /* Check whether there is at least one (S,G) entry which is
                    303:                     * a longer match than this (*,*,RP) entry.
                    304:                     */
                    305:                    for (rp_grp_entry = gt->source->cand_rp->rp_grp_next;
                    306:                         rp_grp_entry != (rp_grp_entry_t *)NULL;
                    307:                         rp_grp_entry = rp_grp_entry->rp_grp_next) {
                    308:                        for (grpentry_ptr = rp_grp_entry->grplink;
                    309:                             grpentry_ptr != (grpentry_t *)NULL;
                    310:                             grpentry_ptr = grpentry_ptr->rpnext) {
                    311:                            if (grpentry_ptr->mrtlink != (mrtentry_t *)NULL) {
                    312:                                found = TRUE;
                    313:                                break;
                    314:                            }
                    315:                        }
                    316:                        if (found == TRUE)
                    317:                            break;
                    318:                    }
                    319:                }
                    320:                else if (gt->flags & MRTF_WC) {
                    321:                    if (gt->group->mrtlink != (mrtentry_t *)NULL)
                    322:                        found = TRUE;
                    323:                }
                    324:                if (found == TRUE) {
                    325:                    RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(rsrr->flags);
                    326:                }
                    327:                else {
                    328:                    RSRR_SET_ALL_SENDERS_SHARED_TREE(rsrr->flags);
                    329:                }
                    330:            }
                    331:        }
                    332:        /* Cache reply if using route change notification. */
                    333:        if (BIT_TST(flags, RSRR_NOTIFICATION_BIT)) {
                    334:            /* TODO: XXX: Originally the rsrr_cache() call was first, but
                    335:             * I think this is incorrect, because rsrr_cache() checks the
                    336:             * rsrr_send_buf "flag" first.
                    337:             */
                    338:            BIT_SET(rsrr->flags, RSRR_NOTIFICATION_BIT);
                    339:            rsrr_cache(gt, route_query);
                    340:        }
                    341:     }
                    342: #else /* Not PIM */
                    343:     if (gt_notify) {
                    344:        /* Set flags */
                    345:        rsrr->flags = flags;
                    346:        /* Include the routing entry. */
                    347:        /* The original code from mrouted-3.9b2 */
                    348:        route_reply->in_vif = gt_notify->gt_route->rt_parent;
                    349:        /* TODO: XXX: bug? See the PIM code above */
                    350:        if (BIT_TST(flags, RSRR_NOTIFICATION_BIT))
                    351:            route_reply->out_vif_bm = gt_notify->gt_grpmems;
                    352:        else
                    353:            route_reply->out_vif_bm = 0;
                    354:     } else if (find_src_grp(route_query->source_addr, 0,
                    355:                            route_query->dest_addr)) {
                    356: 
                    357:        /* Found kernel entry. Code taken from add_table_entry() */
                    358:        gt = gtp ? gtp->gt_gnext : kernel_table;
                    359:        
                    360:        /* Include the routing entry. */
                    361:        route_reply->in_vif = gt->gt_route->rt_parent;
                    362:        route_reply->out_vif_bm = gt->gt_grpmems;
                    363:        
                    364:        /* Cache reply if using route change notification. */
                    365:        if (BIT_TST(flags, RSRR_NOTIFICATION_BIT)) {
                    366:            /* TODO: XXX: Originally the rsrr_cache() call was first, but
                    367:             * I think this is incorrect, because rsrr_cache() checks the
                    368:             * rsrr_send_buf "flag" first.
                    369:             */
                    370:            BIT_SET(rsrr->flags, RSRR_NOTIFICATION_BIT);
                    371:            rsrr_cache(gt, route_query);
                    372:        }
                    373:     } else {
                    374:        /* No kernel entry; use routing table. */
                    375:        r = determine_route(route_query->source_addr);
                    376:        
                    377:        if (r != NULL) {
                    378:            /* We need to mimic what will happen if a data packet
                    379:             * is forwarded by multicast routing -- the kernel will
                    380:             * make an upcall and mrouted will install a route in the kernel.
                    381:             * Our outgoing vif bitmap should reflect what that table
                    382:             * will look like.  Grab code from add_table_entry().
                    383:             * This is gross, but it's probably better to be accurate.
                    384:             */
                    385:            
                    386:            gt = &local_g;
                    387:            mcastgrp = route_query->dest_addr;
                    388:            
                    389:            gt->gt_mcastgrp     = mcastgrp;
                    390:            gt->gt_grpmems      = 0;
                    391:            gt->gt_scope        = 0;
                    392:            gt->gt_route        = r;
                    393:            
                    394:            /* obtain the multicast group membership list */
                    395:            determine_forwvifs(gt);
                    396:            
                    397:            /* Include the routing entry. */
                    398:            route_reply->in_vif = gt->gt_route->rt_parent;
                    399:            route_reply->out_vif_bm = gt->gt_grpmems;
                    400:        } else {
                    401:            /* Set error bit. */
                    402:            BIT_SET(rsrr->flags, RSRR_ERROR_BIT);
                    403:        }
                    404:     }
                    405: #endif /* pimd - mrouted specific code */
                    406:     
                    407:     IF_DEBUG(DEBUG_RSRR) {
                    408:        logit(LOG_DEBUG, 0, "%sSend RSRR Route Reply for src %s dst %s in vif %d out vif %d\n",
                    409:              gt_notify ? "Route Change: " : "",
                    410:              inet_fmt(route_reply->source_addr, s1, sizeof(s1)),
                    411:              inet_fmt(route_reply->dest_addr, s2, sizeof(s2)),
                    412:              route_reply->in_vif,route_reply->out_vif_bm);
                    413:     }
                    414: 
                    415:     /* Send it. */
                    416:     return rsrr_send(sendlen);
                    417: }
                    418: 
                    419: /* Send an RSRR message. */
                    420: static int rsrr_send(int sendlen)
                    421: {
                    422:     int error;
                    423:     
                    424:     while ((error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
                    425:                           (struct sockaddr *)&client_addr, client_length)) < 0)
                    426:     {
                    427:        if (errno == EINTR)
                    428:            continue;           /* Received signal, retry syscall. */
                    429: 
                    430:        logit(LOG_WARNING, errno, "Failed sendto() in rsrr_send()");
                    431: 
                    432:        return error;
                    433:     } 
                    434: 
                    435:     if (error != sendlen)
                    436:        logit(LOG_WARNING, 0, "Sent only %d out of %d bytes on RSRR socket", error, sendlen);
                    437: 
                    438:     return error;
                    439: }
                    440: 
                    441: /* TODO: need to sort the rsrr_cache entries for faster access */
                    442: /* Cache a message being sent to a client.  Currently only used for
                    443:  * caching Route Reply messages for route change notification.
                    444:  */
                    445: static void rsrr_cache(struct gtable *gt, struct rsrr_rq *route_query)
                    446: {
                    447:     struct rsrr_cache *rc, **rcnp;
                    448:     struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
                    449: 
                    450: #ifdef PIM
                    451:     rcnp = &gt->rsrr_cache;
                    452: #else
                    453:     rcnp = &gt->gt_rsrr_cache;
                    454: #endif /* PIM */
                    455:     while ((rc = *rcnp) != NULL) {
                    456:        if ((rc->route_query.source_addr == 
                    457:             route_query->source_addr) &&
                    458:            (rc->route_query.dest_addr == 
                    459:             route_query->dest_addr) &&
                    460:            (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) {
                    461:            /* Cache entry already exists.
                    462:             * Check if route notification bit has been cleared.
                    463:             */
                    464:            if (!BIT_TST(rsrr->flags, RSRR_NOTIFICATION_BIT)) {
                    465:                /* Delete cache entry. */
                    466:                *rcnp = rc->next;
                    467:                free(rc);
                    468:            } else {
                    469:                /* Update */
                    470:                /* TODO: XXX: No need to update iif, oifs, flags */
                    471:                rc->route_query.query_id = route_query->query_id;
                    472:                IF_DEBUG(DEBUG_RSRR) {
                    473:                    logit(LOG_DEBUG, 0,
                    474:                          "Update cached query id %ld from client %s\n",
                    475:                          rc->route_query.query_id, rc->client_addr.sun_path);
                    476:                }
                    477:            }
                    478:            return;
                    479:        }
                    480:        rcnp = &rc->next;
                    481:     }
                    482: 
                    483:     /* Cache entry doesn't already exist.  Create one and insert at
                    484:      * front of list.
                    485:      */
                    486:     rc = (struct rsrr_cache *)calloc(1, sizeof(struct rsrr_cache));
                    487:     if (rc == NULL)
                    488:        logit(LOG_ERR, 0, "Ran out of memory in rsrr_cache()");
                    489: 
                    490:     rc->route_query.source_addr = route_query->source_addr;
                    491:     rc->route_query.dest_addr = route_query->dest_addr;
                    492:     rc->route_query.query_id = route_query->query_id;
                    493:     strlcpy(rc->client_addr.sun_path, client_addr.sun_path, sizeof(rc->client_addr.sun_path));
                    494:     rc->client_length = client_length;
                    495: #ifdef PIM
                    496:     rc->next = gt->rsrr_cache;
                    497:     gt->rsrr_cache = rc;
                    498: #else
                    499:     rc->next = gt->gt_rsrr_cache;
                    500:     gt->gt_rsrr_cache = rc;
                    501: #endif /* PIM */
                    502:     IF_DEBUG(DEBUG_RSRR) {
                    503:        logit(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
                    504:              rc->route_query.query_id, rc->client_addr.sun_path);
                    505:     }
                    506: }
                    507: 
                    508: /* Send all the messages in the cache for particular routing entry.
                    509:  * Currently this is used to send all the cached Route Reply messages
                    510:  * for route change notification.
                    511:  */
                    512: void rsrr_cache_send(struct gtable *gt, int notify)
                    513: {
                    514:     struct rsrr_cache *rc, **rcnp;
                    515:     uint8_t flags = 0;
                    516: 
                    517:     if (notify) {
                    518:        BIT_SET(flags, RSRR_NOTIFICATION_BIT);
                    519:     }
                    520: 
                    521: #ifdef PIM
                    522:     rcnp = &gt->rsrr_cache;
                    523: #else
                    524:     rcnp = &gt->gt_rsrr_cache;
                    525: #endif /* PIM */
                    526: 
                    527:     while ((rc = *rcnp) != NULL) {
                    528:        if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
                    529:            IF_DEBUG(DEBUG_RSRR) {
                    530:                logit(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
                    531:                      rc->route_query.query_id,rc->client_addr.sun_path);
                    532:            }
                    533:            /* Delete cache entry. */
                    534:            *rcnp = rc->next;
                    535:            free(rc);
                    536:        } else {
                    537:            rcnp = &rc->next;
                    538:        }
                    539:     }
                    540: }
                    541: 
                    542: /* Bring "up" the RSRR cache entries: the (S,G) entry brings up any
                    543:  * matching entry from (*,*,RP) or (*,G). The (*,G) entry brings up
                    544:  * any matching entries from (*,*,RP)
                    545:  */
                    546: void rsrr_cache_bring_up(struct gtable *gt)
                    547: {
                    548:     struct gtable *gt_rp, *gt_wide;
                    549:     uint8_t flags = 0;
                    550:     struct rsrr_cache *rc, **rcnp;
                    551: 
                    552:     if (gt == (struct gtable *)NULL)
                    553:        return;
                    554:     if (gt->flags & MRTF_PMBR)
                    555:        /* (*,*,RP) */
                    556:        return;
                    557:     if (gt->flags & MRTF_WC) {
                    558:        /* (*,G) */
                    559:        if (((gt_rp = gt->group->active_rp_grp->rp->rpentry->mrtlink) ==
                    560:            (struct gtable *)NULL)
                    561:            || (gt_rp->rsrr_cache == (struct rsrr_cache *)NULL))
                    562:            return;
                    563:        if ((gt_rp->incoming == gt->incoming)
                    564:            && (VIFM_SAME(gt->oifs, gt_rp->oifs))) {
                    565:            /* The (iif, oifs) are the same. Just link to the new routing
                    566:             * table entry. No need to send message to rsvpd */
                    567:            rcnp = &gt_rp->rsrr_cache;
                    568:            while ((rc = *rcnp) != NULL) {
                    569:                if (rc->route_query.dest_addr == gt->group->group) {
                    570:                    *rcnp = rc->next;
                    571:                    rc->next = gt->rsrr_cache;
                    572:                    gt->rsrr_cache = rc;
                    573:                }
                    574:                else {
                    575:                    rcnp = &rc->next;
                    576:                }
                    577:            }
                    578:        }
                    579:        else {
                    580:            /* Have to move the entries and at the same time
                    581:             * send an update message to rsvpd for each of them.
                    582:             */
                    583:            /* TODO: XXX: this can be done faster */
                    584:            rcnp = &gt_rp->rsrr_cache;
                    585:            BIT_SET(flags, RSRR_NOTIFICATION_BIT);
                    586:            if (gt->group->mrtlink != (mrtentry_t *)NULL) {
                    587:                RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(flags);
                    588:            }
                    589:             else {
                    590:                 RSRR_SET_ALL_SENDERS_SHARED_TREE(flags);
                    591:            }
                    592:            while ((rc = *rcnp) != NULL) {
                    593:                if (rc->route_query.dest_addr == gt->group->group) {
                    594:                    *rcnp = rc->next;
                    595:                    if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
                    596:                        IF_DEBUG(DEBUG_RSRR) {
                    597:                            logit(LOG_DEBUG, 0,
                    598:                                  "Deleting cached query id %ld from client %s\n",
                    599:                                  rc->route_query.query_id,
                    600:                                  rc->client_addr.sun_path);
                    601:                        }
                    602:                    }
                    603:                    /* Even on success have to delete it. */
                    604:                    *rcnp = rc->next;
                    605:                    free(rc);
                    606:                }
                    607:            }
                    608:        }
                    609:        return;
                    610:     } /* end of (*,G) */
                    611:     
                    612:     if (gt->flags & MRTF_SG) {
                    613:        /* (S,G) */
                    614:        /* Check first (*,*,RP) */
                    615:        if (((gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink) ==
                    616:            (struct gtable *)NULL)
                    617:            || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL)) {
                    618:            if (((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
                    619:                || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL))
                    620:                return;
                    621:        }
                    622:        BIT_SET(flags, RSRR_NOTIFICATION_BIT);
                    623:     try_again:
                    624:        rcnp = &gt_wide->rsrr_cache;
                    625:        while((rc = *rcnp) != NULL) {
                    626:            if ((rc->route_query.dest_addr == gt->group->group)
                    627:                && (rc->route_query.source_addr ==
                    628:                    gt->source->address)) {
                    629:                /* Found it. Need just this entry */
                    630:                *rcnp = rc->next; /* Free from the original chain */
                    631:                if ((gt_wide->incoming == gt->incoming)
                    632:                    && (VIFM_SAME(gt_wide->oifs, gt->oifs))) {
                    633:                    /* The (iif, oifs) are the same. Just link to the
                    634:                     * new routing table entry. No need to send
                    635:                     * message to rsvpd
                    636:                     */
                    637:                    rc->next = gt->rsrr_cache;
                    638:                    gt->rsrr_cache = rc;
                    639:                }
                    640:                else {
                    641:                    /* The iif and/or oifs are different. Send a message
                    642:                     * to rsvpd
                    643:                     */
                    644:                    if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
                    645:                        IF_DEBUG(DEBUG_RSRR) {
                    646:                            logit(LOG_DEBUG, 0,
                    647:                                  "Deleting cached query id %ld from client %s\n",
                    648:                                  rc->route_query.query_id,
                    649:                                  rc->client_addr.sun_path);
                    650:                        }
                    651:                    }
                    652:                    /* Even on success have to delete it. */
                    653:                    free(rc);
                    654:                }
                    655:                return;
                    656:            }
                    657:        }
                    658:        if (gt_wide->flags & MRTF_PMBR) {
                    659:            if (((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
                    660:                || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL))
                    661:                return;
                    662:            goto try_again;
                    663:        }
                    664:     }
                    665: }
                    666: 
                    667: /* Clean the cache by deleting or moving all entries. */
                    668: /* XXX: for PIM, if the routing entry is (S,G), will try first to
                    669:  * "transfer" the RSRR cache entry to the (*,G) or (*,*,RP) routing entry
                    670:  * (if any). If the current routing entry is (*,G), it will move the
                    671:  * cache entries to the (*,*,RP) routing entry (if existing).
                    672:  * If the old and the new (iif, oifs) are the same, then no need to send
                    673:  * route change message to the reservation daemon: just plug all entries at
                    674:  * the front of the rsrr_cache chain.
                    675:  */
                    676: void rsrr_cache_clean(struct gtable *gt)
                    677: {
                    678:     struct rsrr_cache *rc, *rc_next, **rcnp;
                    679:     struct gtable *gt_wide;
                    680: #ifdef PIM
                    681:     uint8_t flags = 0;
                    682: 
                    683:     IF_DEBUG(DEBUG_RSRR) {
                    684:        if (gt->flags & MRTF_SG)
                    685:            logit(LOG_DEBUG, 0, "cleaning cache for source %s and group %s",
                    686:                  inet_fmt(gt->source->address, s1, sizeof(s1)),
                    687:                  inet_fmt(gt->group->group, s2, sizeof(s2)));
                    688:        else if (gt->flags & MRTF_WC)
                    689:            logit(LOG_DEBUG, 0, "cleaning cache for group %s and ANY sources",
                    690:                  inet_fmt(gt->group->group, s1, sizeof(s1)));
                    691:        else if (gt->flags & MRTF_PMBR)
                    692:            logit(LOG_DEBUG, 0,
                    693:                  "cleaning cache for ALL groups matching to RP %s",
                    694:                  inet_fmt(gt->source->address, s1, sizeof(s1)));
                    695:     }
                    696:     rc = gt->rsrr_cache;
                    697:     if (rc == (struct rsrr_cache *)NULL)
                    698:        return;
                    699:     if (gt->flags & MRTF_SG) {
                    700:        if ((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
                    701:            gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink;
                    702:     }
                    703:     else if (gt->flags & MRTF_WC)
                    704:        gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink;
                    705:     else
                    706:        gt_wide = (struct gtable *)NULL;
                    707:     
                    708:     if (gt_wide == (struct gtable *)NULL) {
                    709:        /* No routing entry where to move down the rsrr cache entry.
                    710:         * Send a message with "cannot_notify" bit set.
                    711:         */
                    712:        rsrr_cache_send(gt, 0);
                    713:        while (rc) {
                    714:            rc_next = rc->next;
                    715:            free(rc);
                    716:            rc = rc_next;
                    717:        }
                    718:     } else if ((gt_wide->incoming == gt->incoming)
                    719:               && (VIFM_SAME(gt->oifs, gt_wide->oifs))) {
                    720:        /* The (iif, oifs) are the same. Just move to the beginning of the
                    721:         * RSRR cache chain. No need to send message */
                    722:        while (rc->next != (struct rsrr_cache *)NULL)
                    723:            rc = rc->next;
                    724:        rc->next = gt_wide->rsrr_cache;
                    725:        gt_wide->rsrr_cache = gt->rsrr_cache;
                    726:     }
                    727:     else {
                    728:        /* Have to move to the RSRR cache entries and at the same time
                    729:         * send an update for each of them.
                    730:         */
                    731:        rcnp = &gt->rsrr_cache;
                    732:        BIT_SET(flags, RSRR_NOTIFICATION_BIT);
                    733:        if (gt->group->mrtlink != (mrtentry_t *)NULL) {
                    734:            RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(flags);
                    735:        }
                    736:        else {
                    737:            RSRR_SET_ALL_SENDERS_SHARED_TREE(flags);
                    738:        }
                    739:        while ((rc = *rcnp) != NULL) {
                    740:            if (rsrr_accept_rq(&rc->route_query, flags, gt_wide) < 0) {
                    741:                IF_DEBUG(DEBUG_RSRR) {
                    742:                    logit(LOG_DEBUG, 0,
                    743:                          "Deleting cached query id %ld from client %s\n",
                    744:                          rc->route_query.query_id, rc->client_addr.sun_path);
                    745:                }
                    746:                /* Delete cache entry. */
                    747:                *rcnp = rc->next;
                    748:                free(rc);
                    749:            } else {
                    750:                rcnp = &rc->next;
                    751:            }
                    752:        }
                    753:     }
                    754:     gt->rsrr_cache = (struct rsrr_cache *)NULL;
                    755:     
                    756: #else
                    757:     IF_DEBUG(DEBUG_RSRR) {
                    758:         logit(LOG_DEBUG, 0, "cleaning cache for group %s\n",
                    759:              inet_fmt(gt->gt_mcastgrp, s1, sizeof(s1)));
                    760:     }
                    761:     rc = gt->gt_rsrr_cache;
                    762:     while (rc) {
                    763:        rc_next = rc->next;
                    764:        free(rc);
                    765:        rc = rc_next;
                    766:     }
                    767:     gt->gt_rsrr_cache = NULL;
                    768: #endif /* PIM */
                    769: }
                    770: 
                    771: void rsrr_clean(void)
                    772: {
                    773:     unlink(RSRR_SERV_PATH);
                    774: }
                    775: 
                    776: #else  /* !RSRR */
                    777: static int dummy __attribute__((unused));
                    778: #endif /* RSRR */
                    779: 
                    780: /**
                    781:  * Local Variables:
                    782:  *  version-control: t
                    783:  *  indent-tabs-mode: t
                    784:  *  c-file-style: "ellemtel"
                    785:  *  c-basic-offset: 4
                    786:  * End:
                    787:  */

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