rsrr.c revision 1.2 1 /* $NetBSD: rsrr.c,v 1.2 1995/10/09 03:51:56 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1993 by the University of Southern California
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation in source and binary forms for non-commercial purposes
9 * and without fee is hereby granted, provided that the above copyright
10 * notice appear in all copies and that both the copyright notice and
11 * this permission notice appear in supporting documentation. and that
12 * any documentation, advertising materials, and other materials related
13 * to such distribution and use acknowledge that the software was
14 * developed by the University of Southern California, Information
15 * Sciences Institute. The name of the University may not be used to
16 * endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
20 * the suitability of this software for any purpose. THIS SOFTWARE IS
21 * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 *
25 * Other copyrights might apply to parts of this software and are so
26 * noted when applicable.
27 */
28
29 /* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
30 * April 1995.
31 */
32
33 #ifdef RSRR
34
35 #include "defs.h"
36
37 /* Taken from prune.c */
38 /*
39 * checks for scoped multicast addresses
40 */
41 #define GET_SCOPE(gt) { \
42 register int _i; \
43 if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \
44 for (_i = 0; _i < numvifs; _i++) \
45 if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
46 VIFM_SET(_i, (gt)->gt_scope); \
47 }
48
49 /*
50 * Exported variables.
51 */
52 int rsrr_socket; /* interface to reservation protocol */
53
54 /*
55 * Global RSRR variables.
56 */
57 char rsrr_recv_buf[RSRR_MAX_LEN]; /* RSRR receive buffer */
58 char rsrr_send_buf[RSRR_MAX_LEN]; /* RSRR send buffer */
59
60 /*
61 * Procedure definitions needed internally.
62 */
63 void rsrr_accept();
64 void rsrr_send();
65 void rsrr_accept_iq();
66 void rsrr_accept_rq();
67
68 /* Initialize RSRR socket */
69 void
70 rsrr_init()
71 {
72 int servlen;
73 struct sockaddr_un serv_addr;
74
75 if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
76 log(LOG_ERR, errno, "Can't create RSRR socket");
77
78 unlink(RSRR_SERV_PATH);
79 bzero((char *) &serv_addr, sizeof(serv_addr));
80 serv_addr.sun_family = AF_UNIX;
81 strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
82 servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
83
84 if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
85 log(LOG_ERR, errno, "Can't bind RSRR socket");
86
87 if (register_input_handler(rsrr_socket,rsrr_read) < 0)
88 log(LOG_WARNING, 0, "Couldn't register RSRR as an input handler");
89 }
90
91 /* Read a message from the RSRR socket */
92 void
93 rsrr_read()
94 {
95 register int rsrr_recvlen;
96 struct sockaddr_un client_addr;
97 int client_length = sizeof(client_addr);
98 register int omask;
99
100 bzero((char *) &client_addr, sizeof(client_addr));
101 rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
102 0, &client_addr, &client_length);
103 if (rsrr_recvlen < 0) {
104 if (errno != EINTR)
105 log(LOG_ERR, errno, "RSRR recvfrom");
106 return;
107 }
108 /* Use of omask taken from main() */
109 omask = sigblock(sigmask(SIGALRM));
110 rsrr_accept(rsrr_recvlen,&client_addr,client_length);
111 (void)sigsetmask(omask);
112 }
113
114 /* Accept a message from the reservation protocol and take
115 * appropriate action.
116 */
117 void
118 rsrr_accept(recvlen,client_addr,client_length)
119 int recvlen;
120 struct sockaddr_un *client_addr;
121 int client_length;
122 {
123 struct rsrr_header *rsrr;
124 struct rsrr_rq *route_query;
125
126 if (recvlen < RSRR_HEADER_LEN) {
127 log(LOG_WARNING, 0,
128 "Received RSRR packet of %d bytes, which is less than min size",
129 recvlen);
130 return;
131 }
132
133 rsrr = (struct rsrr_header *) rsrr_recv_buf;
134
135 if (rsrr->version > RSRR_MAX_VERSION) {
136 log(LOG_WARNING, 0,
137 "Received RSRR packet version %d, which I don't understand",
138 rsrr->version);
139 return;
140 }
141
142 switch (rsrr->version) {
143 case 1:
144 switch (rsrr->type) {
145 case RSRR_INITIAL_QUERY:
146 /* Send Initial Reply to client */
147 log(LOG_INFO, 0, "Received Initial Query\n");
148 rsrr_accept_iq(client_addr,client_length);
149 break;
150 case RSRR_ROUTE_QUERY:
151 /* Check size */
152 if (recvlen < RSRR_RQ_LEN) {
153 log(LOG_WARNING, 0,
154 "Received Route Query of %d bytes, which is too small",
155 recvlen);
156 break;
157 }
158 /* Get the query */
159 route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
160 log(LOG_INFO, 0,
161 "Received Route Query for src %s grp %s notification %d",
162 inet_fmt(route_query->source_addr.s_addr, s1),
163 inet_fmt(route_query->dest_addr.s_addr,s2),
164 BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
165 /* Send Route Reply to client */
166 rsrr_accept_rq(rsrr,route_query,client_addr,client_length);
167 break;
168 default:
169 log(LOG_WARNING, 0,
170 "Received RSRR packet type %d, which I don't handle",
171 rsrr->type);
172 break;
173 }
174 break;
175
176 default:
177 log(LOG_WARNING, 0,
178 "Received RSRR packet version %d, which I don't understand",
179 rsrr->version);
180 break;
181 }
182 }
183
184 /* Send an Initial Reply to the reservation protocol. */
185 void
186 rsrr_accept_iq(client_addr,client_length)
187 struct sockaddr_un *client_addr;
188 int client_length;
189 {
190 struct rsrr_header *rsrr;
191 struct rsrr_vif *vif_list;
192 struct uvif *v;
193 int vifi, sendlen;
194
195 /* Check for space. There should be room for plenty of vifs,
196 * but we should check anyway.
197 */
198 if (numvifs > RSRR_MAX_VIFS) {
199 log(LOG_WARNING, 0,
200 "Can't send RSRR Route Reply because %d is too many vifs %d",
201 numvifs);
202 return;
203 }
204
205 /* Set up message */
206 rsrr = (struct rsrr_header *) rsrr_send_buf;
207 rsrr->version = 1;
208 rsrr->type = RSRR_INITIAL_REPLY;
209 rsrr->flags = 0;
210 rsrr->num = numvifs;
211
212 vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
213
214 /* Include the vif list. */
215 for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) {
216 vif_list[vifi].id = vifi;
217 vif_list[vifi].status = 0;
218 if (v->uv_flags & VIFF_DISABLED)
219 BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
220 vif_list[vifi].threshold = v->uv_threshold;
221 vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr;
222 }
223
224 /* Get the size. */
225 sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
226
227 /* Send it. */
228 log(LOG_INFO, 0, "Send RSRR Initial Reply");
229 rsrr_send(sendlen,client_addr,client_length);
230 }
231
232 /* Send a Route Reply to the reservation protocol. */
233 void
234 rsrr_accept_rq(rsrr_in,route_query,client_addr,client_length)
235 struct rsrr_header *rsrr_in;
236 struct rsrr_rq *route_query;
237 struct sockaddr_un *client_addr;
238 int client_length;
239 {
240 struct rsrr_header *rsrr;
241 struct rsrr_rr *route_reply;
242 struct gtable *gt,local_g;
243 struct rtentry *r;
244 int sendlen,i;
245 u_long mcastgrp;
246
247 /* Set up message */
248 rsrr = (struct rsrr_header *) rsrr_send_buf;
249 rsrr->version = 1;
250 rsrr->type = RSRR_ROUTE_REPLY;
251 rsrr->flags = rsrr_in->flags;
252 rsrr->num = 0;
253
254 route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
255 route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr;
256 route_reply->source_addr.s_addr = route_query->source_addr.s_addr;
257 route_reply->query_id = route_query->query_id;
258
259 /* Blank routing entry for error. */
260 route_reply->in_vif = 0;
261 route_reply->reserved = 0;
262 route_reply->out_vif_bm = 0;
263
264 /* Clear error bit. */
265 BIT_CLR(rsrr->flags,RSRR_ERROR_BIT);
266 /* Turn notification off. We don't do it yet. */
267 BIT_CLR(rsrr->flags,RSRR_NOTIFICATION_BIT);
268
269 /* First check kernel. Code taken from add_table_entry() */
270 if (find_src_grp(route_query->source_addr.s_addr, 0,
271 route_query->dest_addr.s_addr)) {
272 gt = gtp ? gtp->gt_gnext : kernel_table;
273
274 /* Include the routing entry. */
275 route_reply->in_vif = gt->gt_route->rt_parent;
276 route_reply->out_vif_bm = gt->gt_grpmems;
277
278 } else {
279 /* No kernel entry; use routing table. */
280 r = determine_route(route_query->source_addr.s_addr);
281
282 if (r != NULL) {
283 /* We need to mimic what will happen if a data packet
284 * is forwarded by multicast routing -- the kernel will
285 * make an upcall and mrouted will install a route in the kernel.
286 * Our outgoing vif bitmap should reflect what that table
287 * will look like. Grab code from add_table_entry().
288 * This is gross, but it's probably better to be accurate.
289 */
290
291 gt = &local_g;
292 mcastgrp = route_query->dest_addr.s_addr;
293
294 gt->gt_mcastgrp = mcastgrp;
295 gt->gt_grpmems = 0;
296 gt->gt_scope = 0;
297 gt->gt_route = r;
298
299 /* obtain the multicast group membership list */
300 for (i = 0; i < numvifs; i++) {
301 if (VIFM_ISSET(i, r->rt_children) &&
302 !(VIFM_ISSET(i, r->rt_leaves)))
303 VIFM_SET(i, gt->gt_grpmems);
304
305 if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
306 VIFM_SET(i, gt->gt_grpmems);
307 }
308
309 GET_SCOPE(gt);
310 gt->gt_grpmems &= ~gt->gt_scope;
311
312 /* Include the routing entry. */
313 route_reply->in_vif = gt->gt_route->rt_parent;
314 route_reply->out_vif_bm = gt->gt_grpmems;
315
316 } else {
317 /* Set error bit. */
318 BIT_SET(rsrr->flags,RSRR_ERROR_BIT);
319 }
320 }
321
322 /* Get the size. */
323 sendlen = RSRR_RR_LEN;
324
325 log(LOG_INFO, 0, "Send RSRR Route Reply for src %s grp %s ",
326 inet_fmt(route_reply->source_addr.s_addr,s1),
327 inet_fmt(route_reply->dest_addr.s_addr,s2));
328 log(LOG_INFO, 0, "in vif %d out vif %d\n",
329 route_reply->in_vif,route_reply->out_vif_bm);
330
331 /* Send it. */
332 rsrr_send(sendlen,client_addr,client_length);
333 }
334
335 /* Send an RSRR message. */
336 void
337 rsrr_send(sendlen,client_addr,client_length)
338 int sendlen;
339 struct sockaddr_un *client_addr;
340 int client_length;
341 {
342 int error;
343
344 /* Send it. */
345 error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
346 *client_addr, client_length);
347
348 /* Check for errors. */
349 if (error < 0) {
350 log(LOG_WARNING, errno, "Failed send on RSRR socket");
351 return;
352 }
353 if (error != sendlen) {
354 log(LOG_WARNING, 0,
355 "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
356 return;
357 }
358 }
359
360 void
361 rsrr_clean()
362 {
363 unlink(RSRR_SERV_PATH);
364 }
365
366 #endif RSRR
367