Home | History | Annotate | Line # | Download | only in mrouted
rsrr.c revision 1.1
      1 /*
      2  * Copyright (c) 1993 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 non-commercial 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 
     31 #ifdef RSRR
     32 
     33 #include "defs.h"
     34 
     35 /* Taken from prune.c */
     36 /*
     37  * checks for scoped multicast addresses
     38  */
     39 #define GET_SCOPE(gt) { \
     40 	register int _i; \
     41 	if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \
     42 	    for (_i = 0; _i < numvifs; _i++) \
     43 		if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
     44 		    VIFM_SET(_i, (gt)->gt_scope); \
     45 	}
     46 
     47 /*
     48  * Exported variables.
     49  */
     50 int rsrr_socket;			/* interface to reservation protocol */
     51 
     52 /*
     53  * Global RSRR variables.
     54  */
     55 char rsrr_recv_buf[RSRR_MAX_LEN];	/* RSRR receive buffer */
     56 char rsrr_send_buf[RSRR_MAX_LEN];	/* RSRR send buffer */
     57 
     58 /*
     59  * Procedure definitions needed internally.
     60  */
     61 void rsrr_accept();
     62 void rsrr_send();
     63 void rsrr_accept_iq();
     64 void rsrr_accept_rq();
     65 
     66 /* Initialize RSRR socket */
     67 void
     68 rsrr_init()
     69 {
     70     int servlen;
     71     struct sockaddr_un serv_addr;
     72 
     73     if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
     74 	log(LOG_ERR, errno, "Can't create RSRR socket");
     75 
     76     unlink(RSRR_SERV_PATH);
     77     bzero((char *) &serv_addr, sizeof(serv_addr));
     78     serv_addr.sun_family = AF_UNIX;
     79     strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
     80     servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
     81 
     82     if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
     83 	log(LOG_ERR, errno, "Can't bind RSRR socket");
     84 
     85     if (register_input_handler(rsrr_socket,rsrr_read) < 0)
     86 	log(LOG_WARNING, 0, "Couldn't register RSRR as an input handler");
     87 }
     88 
     89 /* Read a message from the RSRR socket */
     90 void
     91 rsrr_read()
     92 {
     93     register int rsrr_recvlen;
     94     struct sockaddr_un client_addr;
     95     int client_length = sizeof(client_addr);
     96     register int omask;
     97 
     98     bzero((char *) &client_addr, sizeof(client_addr));
     99     rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
    100 			    0, &client_addr, &client_length);
    101     if (rsrr_recvlen < 0) {
    102 	if (errno != EINTR)
    103 	    log(LOG_ERR, errno, "RSRR recvfrom");
    104 	return;
    105     }
    106     /* Use of omask taken from main() */
    107     omask = sigblock(sigmask(SIGALRM));
    108     rsrr_accept(rsrr_recvlen,&client_addr,client_length);
    109     (void)sigsetmask(omask);
    110 }
    111 
    112 /* Accept a message from the reservation protocol and take
    113  * appropriate action.
    114  */
    115 void
    116 rsrr_accept(recvlen,client_addr,client_length)
    117     int recvlen;
    118     struct sockaddr_un *client_addr;
    119     int client_length;
    120 {
    121     struct rsrr_header *rsrr;
    122     struct rsrr_rq *route_query;
    123 
    124     if (recvlen < RSRR_HEADER_LEN) {
    125 	log(LOG_WARNING, 0,
    126 	    "Received RSRR packet of %d bytes, which is less than min size",
    127 	    recvlen);
    128 	return;
    129     }
    130 
    131     rsrr = (struct rsrr_header *) rsrr_recv_buf;
    132 
    133     if (rsrr->version > RSRR_MAX_VERSION) {
    134 	log(LOG_WARNING, 0,
    135 	    "Received RSRR packet version %d, which I don't understand",
    136 	    rsrr->version);
    137 	return;
    138     }
    139 
    140     switch (rsrr->version) {
    141       case 1:
    142 	switch (rsrr->type) {
    143 	  case RSRR_INITIAL_QUERY:
    144 	    /* Send Initial Reply to client */
    145 	    log(LOG_INFO, 0, "Received Initial Query\n");
    146 	    rsrr_accept_iq(client_addr,client_length);
    147 	    break;
    148 	  case RSRR_ROUTE_QUERY:
    149 	    /* Check size */
    150 	    if (recvlen < RSRR_RQ_LEN) {
    151 		log(LOG_WARNING, 0,
    152 		    "Received Route Query of %d bytes, which is too small",
    153 		    recvlen);
    154 		break;
    155 	    }
    156 	    /* Get the query */
    157 	    route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
    158 	    log(LOG_INFO, 0,
    159 		"Received Route Query for src %s grp %s notification %d",
    160 		inet_fmt(route_query->source_addr.s_addr, s1),
    161 		inet_fmt(route_query->dest_addr.s_addr,s2),
    162 		BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
    163 	    /* Send Route Reply to client */
    164 	    rsrr_accept_rq(rsrr,route_query,client_addr,client_length);
    165 	    break;
    166 	  default:
    167 	    log(LOG_WARNING, 0,
    168 		"Received RSRR packet type %d, which I don't handle",
    169 		rsrr->type);
    170 	    break;
    171 	}
    172 	break;
    173 
    174       default:
    175 	log(LOG_WARNING, 0,
    176 	    "Received RSRR packet version %d, which I don't understand",
    177 	    rsrr->version);
    178 	break;
    179     }
    180 }
    181 
    182 /* Send an Initial Reply to the reservation protocol. */
    183 void
    184 rsrr_accept_iq(client_addr,client_length)
    185     struct sockaddr_un *client_addr;
    186     int client_length;
    187 {
    188     struct rsrr_header *rsrr;
    189     struct rsrr_vif *vif_list;
    190     struct uvif *v;
    191     int vifi, sendlen;
    192 
    193     /* Check for space.  There should be room for plenty of vifs,
    194      * but we should check anyway.
    195      */
    196     if (numvifs > RSRR_MAX_VIFS) {
    197 	log(LOG_WARNING, 0,
    198 	    "Can't send RSRR Route Reply because %d is too many vifs %d",
    199 	    numvifs);
    200 	return;
    201     }
    202 
    203     /* Set up message */
    204     rsrr = (struct rsrr_header *) rsrr_send_buf;
    205     rsrr->version = 1;
    206     rsrr->type = RSRR_INITIAL_REPLY;
    207     rsrr->flags = 0;
    208     rsrr->num = numvifs;
    209 
    210     vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
    211 
    212     /* Include the vif list. */
    213     for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) {
    214 	vif_list[vifi].id = vifi;
    215 	vif_list[vifi].status = 0;
    216 	if (v->uv_flags & VIFF_DISABLED)
    217 	    BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
    218 	vif_list[vifi].threshold = v->uv_threshold;
    219 	vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr;
    220     }
    221 
    222     /* Get the size. */
    223     sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
    224 
    225     /* Send it. */
    226     log(LOG_INFO, 0, "Send RSRR Initial Reply");
    227     rsrr_send(sendlen,client_addr,client_length);
    228 }
    229 
    230 /* Send a Route Reply to the reservation protocol. */
    231 void
    232 rsrr_accept_rq(rsrr_in,route_query,client_addr,client_length)
    233     struct rsrr_header *rsrr_in;
    234     struct rsrr_rq *route_query;
    235     struct sockaddr_un *client_addr;
    236     int client_length;
    237 {
    238     struct rsrr_header *rsrr;
    239     struct rsrr_rr *route_reply;
    240     struct gtable *gt,local_g;
    241     struct rtentry *r;
    242     int sendlen,i;
    243     u_long mcastgrp;
    244 
    245     /* Set up message */
    246     rsrr = (struct rsrr_header *) rsrr_send_buf;
    247     rsrr->version = 1;
    248     rsrr->type = RSRR_ROUTE_REPLY;
    249     rsrr->flags = rsrr_in->flags;
    250     rsrr->num = 0;
    251 
    252     route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
    253     route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr;
    254     route_reply->source_addr.s_addr = route_query->source_addr.s_addr;
    255     route_reply->query_id = route_query->query_id;
    256 
    257     /* Blank routing entry for error. */
    258     route_reply->in_vif = 0;
    259     route_reply->reserved = 0;
    260     route_reply->out_vif_bm = 0;
    261 
    262     /* Clear error bit. */
    263     BIT_CLR(rsrr->flags,RSRR_ERROR_BIT);
    264     /* Turn notification off.  We don't do it yet. */
    265     BIT_CLR(rsrr->flags,RSRR_NOTIFICATION_BIT);
    266 
    267     /* First check kernel. Code taken from add_table_entry() */
    268     if (find_src_grp(route_query->source_addr.s_addr, 0,
    269 		     route_query->dest_addr.s_addr)) {
    270 	gt = gtp ? gtp->gt_gnext : kernel_table;
    271 
    272 	/* Include the routing entry. */
    273 	route_reply->in_vif = gt->gt_route->rt_parent;
    274 	route_reply->out_vif_bm = gt->gt_grpmems;
    275 
    276     } else {
    277 	/* No kernel entry; use routing table. */
    278 	r = determine_route(route_query->source_addr.s_addr);
    279 
    280 	if (r != NULL) {
    281 	    /* We need to mimic what will happen if a data packet
    282 	     * is forwarded by multicast routing -- the kernel will
    283 	     * make an upcall and mrouted will install a route in the kernel.
    284 	     * Our outgoing vif bitmap should reflect what that table
    285 	     * will look like.  Grab code from add_table_entry().
    286 	     * This is gross, but it's probably better to be accurate.
    287 	     */
    288 
    289 	    gt = &local_g;
    290 	    mcastgrp = route_query->dest_addr.s_addr;
    291 
    292 	    gt->gt_mcastgrp    	= mcastgrp;
    293 	    gt->gt_grpmems	= 0;
    294 	    gt->gt_scope	= 0;
    295 	    gt->gt_route        = r;
    296 
    297 	    /* obtain the multicast group membership list */
    298 	    for (i = 0; i < numvifs; i++) {
    299 		if (VIFM_ISSET(i, r->rt_children) &&
    300 		    !(VIFM_ISSET(i, r->rt_leaves)))
    301 		    VIFM_SET(i, gt->gt_grpmems);
    302 
    303 		if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
    304 		    VIFM_SET(i, gt->gt_grpmems);
    305 	    }
    306 
    307 	    GET_SCOPE(gt);
    308 	    gt->gt_grpmems &= ~gt->gt_scope;
    309 
    310 	    /* Include the routing entry. */
    311 	    route_reply->in_vif = gt->gt_route->rt_parent;
    312 	    route_reply->out_vif_bm = gt->gt_grpmems;
    313 
    314 	} else {
    315 	    /* Set error bit. */
    316 	    BIT_SET(rsrr->flags,RSRR_ERROR_BIT);
    317 	}
    318     }
    319 
    320     /* Get the size. */
    321     sendlen = RSRR_RR_LEN;
    322 
    323     log(LOG_INFO, 0, "Send RSRR Route Reply for src %s grp %s ",
    324 	inet_fmt(route_reply->source_addr.s_addr,s1),
    325 	inet_fmt(route_reply->dest_addr.s_addr,s2));
    326     log(LOG_INFO, 0, "in vif %d out vif %d\n",
    327 	route_reply->in_vif,route_reply->out_vif_bm);
    328 
    329     /* Send it. */
    330     rsrr_send(sendlen,client_addr,client_length);
    331 }
    332 
    333 /* Send an RSRR message. */
    334 void
    335 rsrr_send(sendlen,client_addr,client_length)
    336     int sendlen;
    337     struct sockaddr_un *client_addr;
    338     int client_length;
    339 {
    340     int error;
    341 
    342     /* Send it. */
    343     error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
    344 		   *client_addr, client_length);
    345 
    346     /* Check for errors. */
    347     if (error < 0) {
    348 	log(LOG_WARNING, errno, "Failed send on RSRR socket");
    349 	return;
    350     }
    351     if (error != sendlen) {
    352 	log(LOG_WARNING, 0,
    353 	    "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
    354 	return;
    355     }
    356 }
    357 
    358 void
    359 rsrr_clean()
    360 {
    361     unlink(RSRR_SERV_PATH);
    362 }
    363 
    364 #endif RSRR
    365