Home | History | Annotate | Line # | Download | only in mrouted
rsrr.c revision 1.7
      1  1.7      wiz /*	$NetBSD: rsrr.c,v 1.7 2003/03/05 21:05:40 wiz Exp $	*/
      2  1.2  thorpej 
      3  1.1  mycroft /*
      4  1.7      wiz  * Copyright (c) 1993, 1998-2001.
      5  1.7      wiz  * The University of Southern California/Information Sciences Institute.
      6  1.1  mycroft  * All rights reserved.
      7  1.1  mycroft  *
      8  1.7      wiz  * Redistribution and use in source and binary forms, with or without
      9  1.7      wiz  * modification, are permitted provided that the following conditions
     10  1.7      wiz  * are met:
     11  1.7      wiz  * 1. Redistributions of source code must retain the above copyright
     12  1.7      wiz  *    notice, this list of conditions and the following disclaimer.
     13  1.7      wiz  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.7      wiz  *    notice, this list of conditions and the following disclaimer in the
     15  1.7      wiz  *    documentation and/or other materials provided with the distribution.
     16  1.7      wiz  * 3. Neither the name of the project nor the names of its contributors
     17  1.7      wiz  *    may be used to endorse or promote products derived from this software
     18  1.7      wiz  *    without specific prior written permission.
     19  1.1  mycroft  *
     20  1.7      wiz  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     21  1.7      wiz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  1.7      wiz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  1.7      wiz  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     24  1.7      wiz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  1.7      wiz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  1.7      wiz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  1.7      wiz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  1.7      wiz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  1.7      wiz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  1.7      wiz  * SUCH DAMAGE.
     31  1.1  mycroft  */
     32  1.1  mycroft 
     33  1.1  mycroft /* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
     34  1.1  mycroft  * April 1995.
     35  1.1  mycroft  */
     36  1.1  mycroft 
     37  1.3  mycroft /* May 1995 -- Added support for Route Change Notification */
     38  1.3  mycroft 
     39  1.1  mycroft #ifdef RSRR
     40  1.1  mycroft 
     41  1.1  mycroft #include "defs.h"
     42  1.3  mycroft #include <sys/param.h>
     43  1.3  mycroft #if (defined(BSD) && (BSD >= 199103))
     44  1.3  mycroft #include <stddef.h>
     45  1.3  mycroft #endif
     46  1.1  mycroft 
     47  1.1  mycroft /* Taken from prune.c */
     48  1.1  mycroft /*
     49  1.1  mycroft  * checks for scoped multicast addresses
     50  1.1  mycroft  */
     51  1.1  mycroft #define GET_SCOPE(gt) { \
     52  1.5      wiz 	int _i; \
     53  1.1  mycroft 	if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \
     54  1.1  mycroft 	    for (_i = 0; _i < numvifs; _i++) \
     55  1.1  mycroft 		if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
     56  1.1  mycroft 		    VIFM_SET(_i, (gt)->gt_scope); \
     57  1.1  mycroft 	}
     58  1.1  mycroft 
     59  1.1  mycroft /*
     60  1.1  mycroft  * Exported variables.
     61  1.1  mycroft  */
     62  1.1  mycroft int rsrr_socket;			/* interface to reservation protocol */
     63  1.1  mycroft 
     64  1.1  mycroft /*
     65  1.1  mycroft  * Global RSRR variables.
     66  1.1  mycroft  */
     67  1.1  mycroft char rsrr_recv_buf[RSRR_MAX_LEN];	/* RSRR receive buffer */
     68  1.1  mycroft char rsrr_send_buf[RSRR_MAX_LEN];	/* RSRR send buffer */
     69  1.1  mycroft 
     70  1.3  mycroft struct sockaddr_un client_addr;
     71  1.3  mycroft int client_length = sizeof(client_addr);
     72  1.3  mycroft 
     73  1.3  mycroft 
     74  1.1  mycroft /*
     75  1.1  mycroft  * Procedure definitions needed internally.
     76  1.1  mycroft  */
     77  1.5      wiz static void	rsrr_accept(int recvlen);
     78  1.5      wiz static void	rsrr_accept_iq(void);
     79  1.5      wiz static int	rsrr_accept_rq(struct rsrr_rq *route_query, int flags,
     80  1.5      wiz 			       struct gtable *gt_notify);
     81  1.5      wiz static int	rsrr_send(int sendlen);
     82  1.5      wiz static void	rsrr_cache(struct gtable *gt, struct rsrr_rq *route_query);
     83  1.1  mycroft 
     84  1.1  mycroft /* Initialize RSRR socket */
     85  1.1  mycroft void
     86  1.1  mycroft rsrr_init()
     87  1.1  mycroft {
     88  1.1  mycroft     int servlen;
     89  1.1  mycroft     struct sockaddr_un serv_addr;
     90  1.1  mycroft 
     91  1.4    lukem     if ((rsrr_socket = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
     92  1.7      wiz 	logit(LOG_ERR, errno, "Can't create RSRR socket");
     93  1.1  mycroft 
     94  1.1  mycroft     unlink(RSRR_SERV_PATH);
     95  1.1  mycroft     bzero((char *) &serv_addr, sizeof(serv_addr));
     96  1.4    lukem     serv_addr.sun_family = AF_LOCAL;
     97  1.1  mycroft     strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
     98  1.3  mycroft #if (defined(BSD) && (BSD >= 199103))
     99  1.3  mycroft     servlen = offsetof(struct sockaddr_un, sun_path) +
    100  1.3  mycroft 		strlen(serv_addr.sun_path);
    101  1.3  mycroft     serv_addr.sun_len = servlen;
    102  1.3  mycroft #else
    103  1.1  mycroft     servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
    104  1.3  mycroft #endif
    105  1.1  mycroft 
    106  1.1  mycroft     if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
    107  1.7      wiz 	logit(LOG_ERR, errno, "Can't bind RSRR socket");
    108  1.1  mycroft 
    109  1.1  mycroft     if (register_input_handler(rsrr_socket,rsrr_read) < 0)
    110  1.7      wiz 	logit(LOG_WARNING, 0, "Couldn't register RSRR as an input handler");
    111  1.1  mycroft }
    112  1.1  mycroft 
    113  1.1  mycroft /* Read a message from the RSRR socket */
    114  1.1  mycroft void
    115  1.3  mycroft rsrr_read(f, rfd)
    116  1.3  mycroft 	int f;
    117  1.3  mycroft 	fd_set *rfd;
    118  1.1  mycroft {
    119  1.5      wiz     int rsrr_recvlen;
    120  1.5      wiz     int omask;
    121  1.1  mycroft 
    122  1.1  mycroft     bzero((char *) &client_addr, sizeof(client_addr));
    123  1.1  mycroft     rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
    124  1.3  mycroft 			    0, (struct sockaddr *)&client_addr, &client_length);
    125  1.1  mycroft     if (rsrr_recvlen < 0) {
    126  1.1  mycroft 	if (errno != EINTR)
    127  1.7      wiz 	    logit(LOG_ERR, errno, "RSRR recvfrom");
    128  1.1  mycroft 	return;
    129  1.1  mycroft     }
    130  1.1  mycroft     /* Use of omask taken from main() */
    131  1.1  mycroft     omask = sigblock(sigmask(SIGALRM));
    132  1.3  mycroft     rsrr_accept(rsrr_recvlen);
    133  1.1  mycroft     (void)sigsetmask(omask);
    134  1.1  mycroft }
    135  1.1  mycroft 
    136  1.1  mycroft /* Accept a message from the reservation protocol and take
    137  1.1  mycroft  * appropriate action.
    138  1.1  mycroft  */
    139  1.3  mycroft static void
    140  1.3  mycroft rsrr_accept(recvlen)
    141  1.1  mycroft     int recvlen;
    142  1.1  mycroft {
    143  1.1  mycroft     struct rsrr_header *rsrr;
    144  1.1  mycroft     struct rsrr_rq *route_query;
    145  1.1  mycroft 
    146  1.1  mycroft     if (recvlen < RSRR_HEADER_LEN) {
    147  1.7      wiz 	logit(LOG_WARNING, 0,
    148  1.1  mycroft 	    "Received RSRR packet of %d bytes, which is less than min size",
    149  1.1  mycroft 	    recvlen);
    150  1.1  mycroft 	return;
    151  1.1  mycroft     }
    152  1.1  mycroft 
    153  1.1  mycroft     rsrr = (struct rsrr_header *) rsrr_recv_buf;
    154  1.1  mycroft 
    155  1.1  mycroft     if (rsrr->version > RSRR_MAX_VERSION) {
    156  1.7      wiz 	logit(LOG_WARNING, 0,
    157  1.1  mycroft 	    "Received RSRR packet version %d, which I don't understand",
    158  1.1  mycroft 	    rsrr->version);
    159  1.1  mycroft 	return;
    160  1.1  mycroft     }
    161  1.1  mycroft 
    162  1.1  mycroft     switch (rsrr->version) {
    163  1.1  mycroft       case 1:
    164  1.1  mycroft 	switch (rsrr->type) {
    165  1.1  mycroft 	  case RSRR_INITIAL_QUERY:
    166  1.1  mycroft 	    /* Send Initial Reply to client */
    167  1.7      wiz 	    logit(LOG_INFO, 0, "Received Initial Query\n");
    168  1.3  mycroft 	    rsrr_accept_iq();
    169  1.1  mycroft 	    break;
    170  1.1  mycroft 	  case RSRR_ROUTE_QUERY:
    171  1.1  mycroft 	    /* Check size */
    172  1.1  mycroft 	    if (recvlen < RSRR_RQ_LEN) {
    173  1.7      wiz 		logit(LOG_WARNING, 0,
    174  1.1  mycroft 		    "Received Route Query of %d bytes, which is too small",
    175  1.1  mycroft 		    recvlen);
    176  1.1  mycroft 		break;
    177  1.1  mycroft 	    }
    178  1.1  mycroft 	    /* Get the query */
    179  1.1  mycroft 	    route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
    180  1.7      wiz 	    logit(LOG_INFO, 0,
    181  1.1  mycroft 		"Received Route Query for src %s grp %s notification %d",
    182  1.1  mycroft 		inet_fmt(route_query->source_addr.s_addr, s1),
    183  1.1  mycroft 		inet_fmt(route_query->dest_addr.s_addr,s2),
    184  1.1  mycroft 		BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
    185  1.1  mycroft 	    /* Send Route Reply to client */
    186  1.3  mycroft 	    rsrr_accept_rq(route_query,rsrr->flags,NULL);
    187  1.1  mycroft 	    break;
    188  1.1  mycroft 	  default:
    189  1.7      wiz 	    logit(LOG_WARNING, 0,
    190  1.1  mycroft 		"Received RSRR packet type %d, which I don't handle",
    191  1.1  mycroft 		rsrr->type);
    192  1.1  mycroft 	    break;
    193  1.1  mycroft 	}
    194  1.1  mycroft 	break;
    195  1.1  mycroft 
    196  1.1  mycroft       default:
    197  1.7      wiz 	logit(LOG_WARNING, 0,
    198  1.1  mycroft 	    "Received RSRR packet version %d, which I don't understand",
    199  1.1  mycroft 	    rsrr->version);
    200  1.1  mycroft 	break;
    201  1.1  mycroft     }
    202  1.1  mycroft }
    203  1.1  mycroft 
    204  1.1  mycroft /* Send an Initial Reply to the reservation protocol. */
    205  1.3  mycroft static void
    206  1.3  mycroft rsrr_accept_iq()
    207  1.1  mycroft {
    208  1.1  mycroft     struct rsrr_header *rsrr;
    209  1.1  mycroft     struct rsrr_vif *vif_list;
    210  1.1  mycroft     struct uvif *v;
    211  1.1  mycroft     int vifi, sendlen;
    212  1.1  mycroft 
    213  1.1  mycroft     /* Check for space.  There should be room for plenty of vifs,
    214  1.1  mycroft      * but we should check anyway.
    215  1.1  mycroft      */
    216  1.1  mycroft     if (numvifs > RSRR_MAX_VIFS) {
    217  1.7      wiz 	logit(LOG_WARNING, 0,
    218  1.1  mycroft 	    "Can't send RSRR Route Reply because %d is too many vifs %d",
    219  1.1  mycroft 	    numvifs);
    220  1.1  mycroft 	return;
    221  1.1  mycroft     }
    222  1.1  mycroft 
    223  1.1  mycroft     /* Set up message */
    224  1.1  mycroft     rsrr = (struct rsrr_header *) rsrr_send_buf;
    225  1.1  mycroft     rsrr->version = 1;
    226  1.1  mycroft     rsrr->type = RSRR_INITIAL_REPLY;
    227  1.1  mycroft     rsrr->flags = 0;
    228  1.1  mycroft     rsrr->num = numvifs;
    229  1.1  mycroft 
    230  1.1  mycroft     vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
    231  1.1  mycroft 
    232  1.1  mycroft     /* Include the vif list. */
    233  1.1  mycroft     for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) {
    234  1.1  mycroft 	vif_list[vifi].id = vifi;
    235  1.1  mycroft 	vif_list[vifi].status = 0;
    236  1.1  mycroft 	if (v->uv_flags & VIFF_DISABLED)
    237  1.1  mycroft 	    BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
    238  1.1  mycroft 	vif_list[vifi].threshold = v->uv_threshold;
    239  1.1  mycroft 	vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr;
    240  1.1  mycroft     }
    241  1.1  mycroft 
    242  1.1  mycroft     /* Get the size. */
    243  1.1  mycroft     sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
    244  1.1  mycroft 
    245  1.1  mycroft     /* Send it. */
    246  1.7      wiz     logit(LOG_INFO, 0, "Send RSRR Initial Reply");
    247  1.3  mycroft     rsrr_send(sendlen);
    248  1.1  mycroft }
    249  1.1  mycroft 
    250  1.3  mycroft /* Send a Route Reply to the reservation protocol.  The Route Query
    251  1.3  mycroft  * contains the query to which we are responding.  The flags contain
    252  1.3  mycroft  * the incoming flags from the query or, for route change
    253  1.3  mycroft  * notification, the flags that should be set for the reply.  The
    254  1.3  mycroft  * kernel table entry contains the routing info to use for a route
    255  1.3  mycroft  * change notification.
    256  1.3  mycroft  */
    257  1.3  mycroft static int
    258  1.3  mycroft rsrr_accept_rq(route_query,flags,gt_notify)
    259  1.3  mycroft     struct rsrr_rq *route_query;
    260  1.3  mycroft     int flags;
    261  1.3  mycroft     struct gtable *gt_notify;
    262  1.1  mycroft {
    263  1.1  mycroft     struct rsrr_header *rsrr;
    264  1.1  mycroft     struct rsrr_rr *route_reply;
    265  1.1  mycroft     struct gtable *gt,local_g;
    266  1.1  mycroft     struct rtentry *r;
    267  1.1  mycroft     int sendlen,i;
    268  1.1  mycroft     u_long mcastgrp;
    269  1.1  mycroft 
    270  1.1  mycroft     /* Set up message */
    271  1.1  mycroft     rsrr = (struct rsrr_header *) rsrr_send_buf;
    272  1.1  mycroft     rsrr->version = 1;
    273  1.1  mycroft     rsrr->type = RSRR_ROUTE_REPLY;
    274  1.3  mycroft     rsrr->flags = 0;
    275  1.1  mycroft     rsrr->num = 0;
    276  1.1  mycroft 
    277  1.1  mycroft     route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
    278  1.1  mycroft     route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr;
    279  1.1  mycroft     route_reply->source_addr.s_addr = route_query->source_addr.s_addr;
    280  1.1  mycroft     route_reply->query_id = route_query->query_id;
    281  1.1  mycroft 
    282  1.1  mycroft     /* Blank routing entry for error. */
    283  1.1  mycroft     route_reply->in_vif = 0;
    284  1.1  mycroft     route_reply->reserved = 0;
    285  1.1  mycroft     route_reply->out_vif_bm = 0;
    286  1.1  mycroft 
    287  1.3  mycroft     /* Get the size. */
    288  1.3  mycroft     sendlen = RSRR_RR_LEN;
    289  1.3  mycroft 
    290  1.3  mycroft     /* If kernel table entry is defined, then we are sending a Route Reply
    291  1.3  mycroft      * due to a Route Change Notification event.  Use the kernel table entry
    292  1.3  mycroft      * to supply the routing info.
    293  1.3  mycroft      */
    294  1.3  mycroft     if (gt_notify) {
    295  1.3  mycroft 	/* Set flags */
    296  1.3  mycroft 	rsrr->flags = flags;
    297  1.3  mycroft 	/* Include the routing entry. */
    298  1.3  mycroft 	route_reply->in_vif = gt_notify->gt_route->rt_parent;
    299  1.3  mycroft 	route_reply->out_vif_bm = gt_notify->gt_grpmems;
    300  1.3  mycroft 
    301  1.3  mycroft     } else if (find_src_grp(route_query->source_addr.s_addr, 0,
    302  1.3  mycroft 			    route_query->dest_addr.s_addr)) {
    303  1.3  mycroft 
    304  1.3  mycroft 	/* Found kernel entry. Code taken from add_table_entry() */
    305  1.1  mycroft 	gt = gtp ? gtp->gt_gnext : kernel_table;
    306  1.1  mycroft 
    307  1.1  mycroft 	/* Include the routing entry. */
    308  1.1  mycroft 	route_reply->in_vif = gt->gt_route->rt_parent;
    309  1.1  mycroft 	route_reply->out_vif_bm = gt->gt_grpmems;
    310  1.3  mycroft 
    311  1.3  mycroft 	/* Cache reply if using route change notification. */
    312  1.3  mycroft 	if BIT_TST(flags,RSRR_NOTIFICATION_BIT) {
    313  1.3  mycroft 	    rsrr_cache(gt,route_query);
    314  1.3  mycroft 	    BIT_SET(rsrr->flags,RSRR_NOTIFICATION_BIT);
    315  1.3  mycroft 	}
    316  1.1  mycroft 
    317  1.1  mycroft     } else {
    318  1.1  mycroft 	/* No kernel entry; use routing table. */
    319  1.1  mycroft 	r = determine_route(route_query->source_addr.s_addr);
    320  1.1  mycroft 
    321  1.1  mycroft 	if (r != NULL) {
    322  1.1  mycroft 	    /* We need to mimic what will happen if a data packet
    323  1.1  mycroft 	     * is forwarded by multicast routing -- the kernel will
    324  1.1  mycroft 	     * make an upcall and mrouted will install a route in the kernel.
    325  1.1  mycroft 	     * Our outgoing vif bitmap should reflect what that table
    326  1.1  mycroft 	     * will look like.  Grab code from add_table_entry().
    327  1.1  mycroft 	     * This is gross, but it's probably better to be accurate.
    328  1.1  mycroft 	     */
    329  1.1  mycroft 
    330  1.1  mycroft 	    gt = &local_g;
    331  1.1  mycroft 	    mcastgrp = route_query->dest_addr.s_addr;
    332  1.1  mycroft 
    333  1.1  mycroft 	    gt->gt_mcastgrp    	= mcastgrp;
    334  1.1  mycroft 	    gt->gt_grpmems	= 0;
    335  1.1  mycroft 	    gt->gt_scope	= 0;
    336  1.1  mycroft 	    gt->gt_route        = r;
    337  1.1  mycroft 
    338  1.1  mycroft 	    /* obtain the multicast group membership list */
    339  1.1  mycroft 	    for (i = 0; i < numvifs; i++) {
    340  1.1  mycroft 		if (VIFM_ISSET(i, r->rt_children) &&
    341  1.1  mycroft 		    !(VIFM_ISSET(i, r->rt_leaves)))
    342  1.1  mycroft 		    VIFM_SET(i, gt->gt_grpmems);
    343  1.1  mycroft 
    344  1.1  mycroft 		if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
    345  1.1  mycroft 		    VIFM_SET(i, gt->gt_grpmems);
    346  1.1  mycroft 	    }
    347  1.1  mycroft 
    348  1.1  mycroft 	    GET_SCOPE(gt);
    349  1.1  mycroft 	    gt->gt_grpmems &= ~gt->gt_scope;
    350  1.1  mycroft 
    351  1.1  mycroft 	    /* Include the routing entry. */
    352  1.1  mycroft 	    route_reply->in_vif = gt->gt_route->rt_parent;
    353  1.1  mycroft 	    route_reply->out_vif_bm = gt->gt_grpmems;
    354  1.1  mycroft 
    355  1.1  mycroft 	} else {
    356  1.1  mycroft 	    /* Set error bit. */
    357  1.1  mycroft 	    BIT_SET(rsrr->flags,RSRR_ERROR_BIT);
    358  1.1  mycroft 	}
    359  1.1  mycroft     }
    360  1.1  mycroft 
    361  1.3  mycroft     if (gt_notify)
    362  1.7      wiz 	logit(LOG_INFO, 0, "Route Change: Send RSRR Route Reply");
    363  1.3  mycroft 
    364  1.3  mycroft     else
    365  1.7      wiz 	logit(LOG_INFO, 0, "Send RSRR Route Reply");
    366  1.3  mycroft 
    367  1.7      wiz     logit(LOG_INFO, 0, "for src %s dst %s in vif %d out vif %d\n",
    368  1.1  mycroft 	inet_fmt(route_reply->source_addr.s_addr,s1),
    369  1.3  mycroft 	inet_fmt(route_reply->dest_addr.s_addr,s2),
    370  1.1  mycroft 	route_reply->in_vif,route_reply->out_vif_bm);
    371  1.1  mycroft 
    372  1.1  mycroft     /* Send it. */
    373  1.3  mycroft     return rsrr_send(sendlen);
    374  1.1  mycroft }
    375  1.1  mycroft 
    376  1.1  mycroft /* Send an RSRR message. */
    377  1.3  mycroft static int
    378  1.3  mycroft rsrr_send(sendlen)
    379  1.1  mycroft     int sendlen;
    380  1.1  mycroft {
    381  1.1  mycroft     int error;
    382  1.1  mycroft 
    383  1.1  mycroft     /* Send it. */
    384  1.1  mycroft     error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
    385  1.3  mycroft 		   (struct sockaddr *)&client_addr, client_length);
    386  1.1  mycroft 
    387  1.1  mycroft     /* Check for errors. */
    388  1.1  mycroft     if (error < 0) {
    389  1.7      wiz 	logit(LOG_WARNING, errno, "Failed send on RSRR socket");
    390  1.3  mycroft     } else if (error != sendlen) {
    391  1.7      wiz 	logit(LOG_WARNING, 0,
    392  1.1  mycroft 	    "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
    393  1.1  mycroft     }
    394  1.3  mycroft     return error;
    395  1.3  mycroft }
    396  1.3  mycroft 
    397  1.3  mycroft /* Cache a message being sent to a client.  Currently only used for
    398  1.3  mycroft  * caching Route Reply messages for route change notification.
    399  1.3  mycroft  */
    400  1.3  mycroft static void
    401  1.3  mycroft rsrr_cache(gt,route_query)
    402  1.3  mycroft     struct gtable *gt;
    403  1.3  mycroft     struct rsrr_rq *route_query;
    404  1.3  mycroft {
    405  1.3  mycroft     struct rsrr_cache *rc, **rcnp;
    406  1.3  mycroft     struct rsrr_header *rsrr;
    407  1.3  mycroft 
    408  1.3  mycroft     rsrr = (struct rsrr_header *) rsrr_send_buf;
    409  1.3  mycroft 
    410  1.3  mycroft     rcnp = &gt->gt_rsrr_cache;
    411  1.3  mycroft     while ((rc = *rcnp) != NULL) {
    412  1.3  mycroft 	if ((rc->route_query.source_addr.s_addr ==
    413  1.3  mycroft 	     route_query->source_addr.s_addr) &&
    414  1.3  mycroft 	    (rc->route_query.dest_addr.s_addr ==
    415  1.3  mycroft 	     route_query->dest_addr.s_addr) &&
    416  1.3  mycroft 	    (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) {
    417  1.3  mycroft 	    /* Cache entry already exists.
    418  1.3  mycroft 	     * Check if route notification bit has been cleared.
    419  1.3  mycroft 	     */
    420  1.3  mycroft 	    if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) {
    421  1.3  mycroft 		/* Delete cache entry. */
    422  1.3  mycroft 		*rcnp = rc->next;
    423  1.3  mycroft 		free(rc);
    424  1.3  mycroft 	    } else {
    425  1.3  mycroft 		/* Update */
    426  1.3  mycroft 		rc->route_query.query_id = route_query->query_id;
    427  1.7      wiz 		logit(LOG_DEBUG, 0,
    428  1.3  mycroft 			"Update cached query id %ld from client %s\n",
    429  1.3  mycroft 			rc->route_query.query_id, rc->client_addr.sun_path);
    430  1.3  mycroft 	    }
    431  1.3  mycroft 	    return;
    432  1.3  mycroft 	}
    433  1.3  mycroft 	rcnp = &rc->next;
    434  1.3  mycroft     }
    435  1.3  mycroft 
    436  1.3  mycroft     /* Cache entry doesn't already exist.  Create one and insert at
    437  1.3  mycroft      * front of list.
    438  1.3  mycroft      */
    439  1.3  mycroft     rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache));
    440  1.3  mycroft     if (rc == NULL)
    441  1.7      wiz 	logit(LOG_ERR, 0, "ran out of memory");
    442  1.3  mycroft     rc->route_query.source_addr.s_addr = route_query->source_addr.s_addr;
    443  1.3  mycroft     rc->route_query.dest_addr.s_addr = route_query->dest_addr.s_addr;
    444  1.3  mycroft     rc->route_query.query_id = route_query->query_id;
    445  1.3  mycroft     strcpy(rc->client_addr.sun_path, client_addr.sun_path);
    446  1.3  mycroft     rc->client_length = client_length;
    447  1.3  mycroft     rc->next = gt->gt_rsrr_cache;
    448  1.3  mycroft     gt->gt_rsrr_cache = rc;
    449  1.7      wiz     logit(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
    450  1.3  mycroft 	   rc->route_query.query_id,rc->client_addr.sun_path);
    451  1.3  mycroft }
    452  1.3  mycroft 
    453  1.3  mycroft /* Send all the messages in the cache.  Currently this is used to send
    454  1.3  mycroft  * all the cached Route Reply messages for route change notification.
    455  1.3  mycroft  */
    456  1.3  mycroft void
    457  1.3  mycroft rsrr_cache_send(gt,notify)
    458  1.3  mycroft     struct gtable *gt;
    459  1.3  mycroft     int notify;
    460  1.3  mycroft {
    461  1.3  mycroft     struct rsrr_cache *rc, **rcnp;
    462  1.3  mycroft     int flags = 0;
    463  1.3  mycroft 
    464  1.3  mycroft     if (notify)
    465  1.3  mycroft 	BIT_SET(flags,RSRR_NOTIFICATION_BIT);
    466  1.3  mycroft 
    467  1.3  mycroft     rcnp = &gt->gt_rsrr_cache;
    468  1.3  mycroft     while ((rc = *rcnp) != NULL) {
    469  1.3  mycroft 	if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) {
    470  1.7      wiz 	    logit(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
    471  1.3  mycroft 		   rc->route_query.query_id,rc->client_addr.sun_path);
    472  1.3  mycroft 	    /* Delete cache entry. */
    473  1.3  mycroft 	    *rcnp = rc->next;
    474  1.3  mycroft 	    free(rc);
    475  1.3  mycroft 	} else {
    476  1.3  mycroft 	    rcnp = &rc->next;
    477  1.3  mycroft 	}
    478  1.3  mycroft     }
    479  1.3  mycroft }
    480  1.3  mycroft 
    481  1.3  mycroft /* Clean the cache by deleting all entries. */
    482  1.3  mycroft void
    483  1.3  mycroft rsrr_cache_clean(gt)
    484  1.3  mycroft     struct gtable *gt;
    485  1.3  mycroft {
    486  1.3  mycroft     struct rsrr_cache *rc,*rc_next;
    487  1.3  mycroft 
    488  1.3  mycroft     printf("cleaning cache for group %s\n",inet_fmt(gt->gt_mcastgrp, s1));
    489  1.3  mycroft     rc = gt->gt_rsrr_cache;
    490  1.3  mycroft     while (rc) {
    491  1.3  mycroft 	rc_next = rc->next;
    492  1.3  mycroft 	free(rc);
    493  1.3  mycroft 	rc = rc_next;
    494  1.3  mycroft     }
    495  1.3  mycroft     gt->gt_rsrr_cache = NULL;
    496  1.1  mycroft }
    497  1.1  mycroft 
    498  1.1  mycroft void
    499  1.1  mycroft rsrr_clean()
    500  1.1  mycroft {
    501  1.1  mycroft     unlink(RSRR_SERV_PATH);
    502  1.1  mycroft }
    503  1.1  mycroft 
    504  1.3  mycroft #endif /* RSRR */
    505