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