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