1 1.10 seanb /* $NetBSD: rsrr.c,v 1.10 2008/08/26 17:38:21 seanb 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.10 seanb socklen_t 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.8 itojun strlcpy(serv_addr.sun_path, RSRR_SERV_PATH, sizeof(serv_addr.sun_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.9 dsl inet_fmt(route_query->source_addr.s_addr), 183 1.10 seanb inet_fmt(route_query->dest_addr.s_addr), 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.10 seanb "Can't send RSRR Route Reply because %d is too many vifs", 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.10 seanb logit(LOG_INFO, 0, "for src %s dst %s in vif %d out vif %lu\n", 368 1.10 seanb inet_fmt(route_reply->source_addr.s_addr), 369 1.10 seanb inet_fmt(route_reply->dest_addr.s_addr), 370 1.10 seanb 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_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.8 itojun strlcpy(rc->client_addr.sun_path, client_addr.sun_path, 446 1.8 itojun sizeof(rc->client_addr.sun_path)); 447 1.3 mycroft rc->client_length = client_length; 448 1.3 mycroft rc->next = gt->gt_rsrr_cache; 449 1.3 mycroft gt->gt_rsrr_cache = rc; 450 1.7 wiz logit(LOG_DEBUG, 0, "Cached query id %ld from client %s\n", 451 1.3 mycroft rc->route_query.query_id,rc->client_addr.sun_path); 452 1.3 mycroft } 453 1.3 mycroft 454 1.3 mycroft /* Send all the messages in the cache. Currently this is used to send 455 1.3 mycroft * all the cached Route Reply messages for route change notification. 456 1.3 mycroft */ 457 1.3 mycroft void 458 1.3 mycroft rsrr_cache_send(gt,notify) 459 1.3 mycroft struct gtable *gt; 460 1.3 mycroft int notify; 461 1.3 mycroft { 462 1.3 mycroft struct rsrr_cache *rc, **rcnp; 463 1.3 mycroft int flags = 0; 464 1.3 mycroft 465 1.3 mycroft if (notify) 466 1.3 mycroft BIT_SET(flags,RSRR_NOTIFICATION_BIT); 467 1.3 mycroft 468 1.3 mycroft rcnp = >->gt_rsrr_cache; 469 1.3 mycroft while ((rc = *rcnp) != NULL) { 470 1.3 mycroft if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) { 471 1.7 wiz logit(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n", 472 1.3 mycroft rc->route_query.query_id,rc->client_addr.sun_path); 473 1.3 mycroft /* Delete cache entry. */ 474 1.3 mycroft *rcnp = rc->next; 475 1.3 mycroft free(rc); 476 1.3 mycroft } else { 477 1.3 mycroft rcnp = &rc->next; 478 1.3 mycroft } 479 1.3 mycroft } 480 1.3 mycroft } 481 1.3 mycroft 482 1.3 mycroft /* Clean the cache by deleting all entries. */ 483 1.3 mycroft void 484 1.3 mycroft rsrr_cache_clean(gt) 485 1.3 mycroft struct gtable *gt; 486 1.3 mycroft { 487 1.3 mycroft struct rsrr_cache *rc,*rc_next; 488 1.3 mycroft 489 1.8 itojun printf("cleaning cache for group %s\n", 490 1.9 dsl inet_fmt(gt->gt_mcastgrp)); 491 1.3 mycroft rc = gt->gt_rsrr_cache; 492 1.3 mycroft while (rc) { 493 1.3 mycroft rc_next = rc->next; 494 1.3 mycroft free(rc); 495 1.3 mycroft rc = rc_next; 496 1.3 mycroft } 497 1.3 mycroft gt->gt_rsrr_cache = NULL; 498 1.1 mycroft } 499 1.1 mycroft 500 1.1 mycroft void 501 1.1 mycroft rsrr_clean() 502 1.1 mycroft { 503 1.1 mycroft unlink(RSRR_SERV_PATH); 504 1.1 mycroft } 505 1.1 mycroft 506 1.3 mycroft #endif /* RSRR */ 507