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