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