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