Annotation of embedaddon/pimdd/kern.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998 by the University of Southern California.
3: * All rights reserved.
4: *
5: * Permission to use, copy, modify, and distribute this software and
6: * its documentation in source and binary forms for lawful
7: * purposes and without fee is hereby granted, provided
8: * that the above copyright notice appear in all copies and that both
9: * the copyright notice and this permission notice appear in supporting
10: * documentation, and that any documentation, advertising materials,
11: * and other materials related to such distribution and use acknowledge
12: * that the software was developed by the University of Southern
13: * California and/or Information Sciences Institute.
14: * The name of the University of Southern California may not
15: * be used to endorse or promote products derived from this software
16: * without specific prior written permission.
17: *
18: * THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
19: * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
20: * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
21: * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
23: * NON-INFRINGEMENT.
24: *
25: * IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
26: * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
27: * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
28: * THE USE OR PERFORMANCE OF THIS SOFTWARE.
29: *
30: * Other copyrights might apply to parts of this software and are so
31: * noted when applicable.
32: */
33: /*
34: * Questions concerning this software should be directed to
35: * Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
36: *
37: * $Id: kern.c,v 1.2 1998/06/01 22:27:14 kurtw Exp $
38: */
39: /*
40: * Part of this program has been derived from mrouted.
41: * The mrouted program is covered by the license in the accompanying file
42: * named "LICENSE.mrouted".
43: *
44: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
45: * Leland Stanford Junior University.
46: *
47: */
48:
49: #include "defs.h"
50:
51: #ifdef RAW_OUTPUT_IS_RAW
52: int curttl = 0;
53: #endif
54:
55:
56: /*
57: * Open/init the multicast routing in the kernel and sets the MRT_ASSERT
58: * flag in the kernel.
59: *
60: */
61: void
62: k_init_pim(socket)
63: int socket;
64: {
65: int v = 1;
66:
67: if (setsockopt(socket, IPPROTO_IP, MRT_INIT, (char *)&v, sizeof(int)) < 0)
68: log(LOG_ERR, errno, "cannot enable multicast routing in kernel");
69:
70: if(setsockopt(socket, IPPROTO_IP, MRT_ASSERT, (char *)&v, sizeof(int)) < 0)
71: log(LOG_ERR, errno, "cannot set ASSERT flag in kernel");
72: }
73:
74:
75: /*
76: * Stops the multicast routing in the kernel and resets the MRT_ASSERT
77: * flag in the kernel.
78: */
79: void
80: k_stop_pim(socket)
81: int socket;
82: {
83: int v = 0;
84:
85: if (setsockopt(socket, IPPROTO_IP, MRT_DONE, (char *)NULL, 0) < 0)
86: log(LOG_ERR, errno, "cannot disable multicast routing in kernel");
87:
88: if(setsockopt(socket, IPPROTO_IP, MRT_ASSERT, (char *)&v, sizeof(int)) < 0)
89: log(LOG_ERR, errno, "cannot reset ASSERT flag in kernel");
90: }
91:
92:
93: /*
94: * Set the socket receiving buffer. `bufsize` is the preferred size,
95: * `minsize` is the smallest acceptable size.
96: */
97: void k_set_rcvbuf(socket, bufsize, minsize)
98: int socket;
99: int bufsize;
100: int minsize;
101: {
102: int delta = bufsize / 2;
103: int iter = 0;
104:
105: /*
106: * Set the socket buffer. If we can't set it as large as we
107: * want, search around to try to find the highest acceptable
108: * value. The highest acceptable value being smaller than
109: * minsize is a fatal error.
110: */
111: if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
112: (char *)&bufsize, sizeof(bufsize)) < 0) {
113: bufsize -= delta;
114: while (1) {
115: iter++;
116: if (delta > 1)
117: delta /= 2;
118:
119: if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
120: (char *)&bufsize, sizeof(bufsize)) < 0) {
121: bufsize -= delta;
122: } else {
123: if (delta < 1024)
124: break;
125: bufsize += delta;
126: }
127: }
128: if (bufsize < minsize) {
129: log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
130: bufsize, minsize);
131: /*NOTREACHED*/
132: }
133: }
134: IF_DEBUG(DEBUG_KERN)
135: log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
136: bufsize, iter);
137: }
138:
139:
140: /*
141: * Set/reset the IP_HDRINCL option. My guess is we don't need it for raw
142: * sockets, but having it here won't hurt. Well, unless you are running
143: * an older version of FreeBSD (older than 2.2.2). If the multicast
144: * raw packet is bigger than 208 bytes, then IP_HDRINCL triggers a bug
145: * in the kernel and "panic". The kernel patch for netinet/ip_raw.c
146: * coming with this distribution fixes it.
147: */
148: void k_hdr_include(socket, bool)
149: int socket;
150: int bool;
151: {
152: #ifdef IP_HDRINCL
153: if (setsockopt(socket, IPPROTO_IP, IP_HDRINCL,
154: (char *)&bool, sizeof(bool)) < 0)
155: log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);
156: #endif
157: }
158:
159:
160: /*
161: * Set the default TTL for the multicast packets outgoing from this
162: * socket.
163: * TODO: Does it affect the unicast packets?
164: */
165: void k_set_ttl(socket, t)
166: int socket;
167: int t;
168: {
169: #ifdef RAW_OUTPUT_IS_RAW
170: curttl = t;
171: #else
172: u_char ttl;
173:
174: ttl = t;
175: if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,
176: (char *)&ttl, sizeof(ttl)) < 0)
177: log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
178: #endif
179: }
180:
181:
182: /*
183: * Set/reset the IP_MULTICAST_LOOP. Set/reset is specified by "flag".
184: */
185: void k_set_loop(socket, flag)
186: int socket;
187: int flag;
188: {
189: u_char loop;
190:
191: loop = flag;
192: if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
193: (char *)&loop, sizeof(loop)) < 0)
194: log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
195: }
196:
197:
198: /*
199: * Set the IP_MULTICAST_IF option on local interface ifa.
200: */
201: void k_set_if(socket, ifa)
202: int socket;
203: u_int32 ifa;
204: {
205: struct in_addr adr;
206:
207: adr.s_addr = ifa;
208: if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF,
209: (char *)&adr, sizeof(adr)) < 0)
210: log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
211: inet_fmt(ifa, s1));
212: }
213:
214:
215: /*
216: * Join a multicast grp group on local interface ifa.
217: */
218: void k_join(socket, grp, ifa)
219: int socket;
220: u_int32 grp;
221: u_int32 ifa;
222: {
223: struct ip_mreq mreq;
224:
225: mreq.imr_multiaddr.s_addr = grp;
226: mreq.imr_interface.s_addr = ifa;
227:
228: if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
229: (char *)&mreq, sizeof(mreq)) < 0)
230: log(LOG_WARNING, errno, "cannot join group %s on interface %s",
231: inet_fmt(grp, s1), inet_fmt(ifa, s2));
232: }
233:
234:
235: /*
236: * Leave a multicats grp group on local interface ifa.
237: */
238: void k_leave(socket, grp, ifa)
239: int socket;
240: u_int32 grp;
241: u_int32 ifa;
242: {
243: struct ip_mreq mreq;
244:
245: mreq.imr_multiaddr.s_addr = grp;
246: mreq.imr_interface.s_addr = ifa;
247:
248: if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
249: (char *)&mreq, sizeof(mreq)) < 0)
250: log(LOG_WARNING, errno, "cannot leave group %s on interface %s",
251: inet_fmt(grp, s1), inet_fmt(ifa, s2));
252: }
253:
254:
255: /*
256: * Add a virtual interface in the kernel.
257: */
258: void k_add_vif(socket, vifi, v)
259: int socket;
260: vifi_t vifi;
261: struct uvif *v;
262: {
263: struct vifctl vc;
264:
265: vc.vifc_vifi = vifi;
266: /* TODO: only for DVMRP tunnels?
267: vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS;
268: */
269: vc.vifc_flags = v->uv_flags;
270: vc.vifc_threshold = v->uv_threshold;
271: vc.vifc_rate_limit = v->uv_rate_limit;
272: vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
273: vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
274:
275: if (setsockopt(socket, IPPROTO_IP, MRT_ADD_VIF,
276: (char *)&vc, sizeof(vc)) < 0)
277: log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
278: }
279:
280:
281: /*
282: * Delete a virtual interface in the kernel.
283: */
284: void k_del_vif(socket, vifi)
285: int socket;
286: vifi_t vifi;
287: {
288: if (setsockopt(socket, IPPROTO_IP, MRT_DEL_VIF,
289: (char *)&vifi, sizeof(vifi)) < 0)
290: log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
291: }
292:
293:
294: /*
295: * Delete all MFC entries for particular routing entry from the kernel.
296: */
297: int
298: k_del_mfc(socket, source, group)
299: int socket;
300: u_int32 source;
301: u_int32 group;
302: {
303: struct mfcctl mc;
304:
305: mc.mfcc_origin.s_addr = source;
306: mc.mfcc_mcastgrp.s_addr = group;
307:
308: if (setsockopt(socket, IPPROTO_IP, MRT_DEL_MFC, (char *)&mc,
309: sizeof(mc)) < 0) {
310: log(LOG_WARNING, errno, "setsockopt k_del_mfc");
311: return FALSE;
312: }
313:
314: IF_DEBUG(DEBUG_MFC)
315: log(LOG_DEBUG, 0, "Deleted MFC entry: src %s, grp %s",
316: inet_fmt(mc.mfcc_origin.s_addr, s1),
317: inet_fmt(mc.mfcc_mcastgrp.s_addr, s2));
318:
319: return(TRUE);
320: }
321:
322:
323: /*
324: * Install/modify a MFC entry in the kernel
325: */
326: int
327: k_chg_mfc(socket, source, group, iif, oifs)
328: int socket;
329: u_int32 source;
330: u_int32 group;
331: vifi_t iif;
332: vifbitmap_t oifs;
333: {
334: struct mfcctl mc;
335: vifi_t vifi;
336: struct uvif *v;
337:
338: mc.mfcc_origin.s_addr = source;
339: #ifdef OLD_KERNEL
340: mc.mfcc_originmas.s_addr = 0xffffffff; /* Got it from mrouted-3.9 */
341: #endif /* OLD_KERNEL */
342: mc.mfcc_mcastgrp.s_addr = group;
343: mc.mfcc_parent = iif;
344: for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
345: if (VIFM_ISSET(vifi, oifs))
346: mc.mfcc_ttls[vifi] = v->uv_threshold;
347: else
348: mc.mfcc_ttls[vifi] = 0;
349: }
350:
351: if (setsockopt(socket, IPPROTO_IP, MRT_ADD_MFC, (char *)&mc,
352: sizeof(mc)) < 0) {
353: log(LOG_WARNING, errno,
354: "setsockopt MRT_ADD_MFC for source %s and group %s",
355: inet_fmt(source, s1), inet_fmt(group, s2));
356: return(FALSE);
357: }
358: return(TRUE);
359: }
360:
361:
362: /*
363: * Get packet counters for particular interface
364: */
365: /*
366: * XXX: TODO: currently not used, but keep just in case we need it later.
367: */
368: int k_get_vif_count(vifi, retval)
369: vifi_t vifi;
370: struct vif_count *retval;
371: {
372: struct sioc_vif_req vreq;
373:
374: vreq.vifi = vifi;
375: if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
376: log(LOG_WARNING, errno, "SIOCGETVIFCNT on vif %d", vifi);
377: retval->icount = retval->ocount = retval->ibytes =
378: retval->obytes = 0xffffffff;
379: return (1);
380: }
381: retval->icount = vreq.icount;
382: retval->ocount = vreq.ocount;
383: retval->ibytes = vreq.ibytes;
384: retval->obytes = vreq.obytes;
385: return (0);
386: }
387:
388:
389: /*
390: * Gets the number of packets, bytes, and number op packets arrived
391: * on wrong if in the kernel for particular (S,G) entry.
392: */
393: int
394: k_get_sg_cnt(socket, source, group, retval)
395: int socket; /* udp_socket */
396: u_int32 source;
397: u_int32 group;
398: struct sg_count *retval;
399: {
400: struct sioc_sg_req sgreq;
401:
402: sgreq.src.s_addr = source;
403: sgreq.grp.s_addr = group;
404: if ((ioctl(socket, SIOCGETSGCNT, (char *)&sgreq) < 0)
405: || (sgreq.wrong_if == 0xffffffff)) {
406: /* XXX: ipmulti-3.5 has bug in ip_mroute.c, get_sg_cnt():
407: * the return code is always 0, so this is why we need to check
408: * the wrong_if value.
409: */
410: log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
411: inet_fmt(source, s1), inet_fmt(group, s2));
412: retval->pktcnt = retval->bytecnt = retval->wrong_if = ~0;
413: return(1);
414: }
415: retval->pktcnt = sgreq.pktcnt;
416: retval->bytecnt = sgreq.bytecnt;
417: retval->wrong_if = sgreq.wrong_if;
418: return(0);
419: }
420:
421:
422:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>