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