Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / mrouted / kern.c
1 /*
2  * The mrouted program is covered by the license in the accompanying file
3  * named "LICENSE".  Use of the mrouted program represents acceptance of
4  * the terms and conditions listed in that file.
5  *
6  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
7  * Leland Stanford Junior University.
8  *
9  *
10  * kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp
11  *
12  * $FreeBSD: src/usr.sbin/mrouted/kern.c,v 1.12 1999/08/28 01:17:04 peter Exp $
13  * $DragonFly: src/usr.sbin/mrouted/kern.c,v 1.2 2003/06/17 04:29:57 dillon Exp $
14  */
15
16 #include "defs.h"
17
18 int curttl = 0;
19
20 void k_set_rcvbuf(bufsize, minsize)
21     int bufsize;
22     int minsize;
23 {
24     int delta = bufsize / 2;
25     int iter = 0;
26
27     /*
28      * Set the socket buffer.  If we can't set it as large as we
29      * want, search around to try to find the highest acceptable
30      * value.  The highest acceptable value being smaller than
31      * minsize is a fatal error.
32      */
33     if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
34                 (char *)&bufsize, sizeof(bufsize)) < 0) {
35         bufsize -= delta;
36         while (1) {
37             iter++;
38             if (delta > 1)
39                 delta /= 2;
40
41             if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
42                         (char *)&bufsize, sizeof(bufsize)) < 0) {
43                     bufsize -= delta;
44             } else {
45                     if (delta < 1024)
46                         break;
47                     bufsize += delta;
48             }
49         }
50         if (bufsize < minsize) {
51             log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
52                 bufsize, minsize);
53             /*NOTREACHED*/
54         }
55     }
56     IF_DEBUG(DEBUG_KERN)
57     log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
58             bufsize, iter);
59 }
60
61
62 void k_hdr_include(bool)
63     int bool;
64 {
65 #ifdef IP_HDRINCL
66     if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL,
67                    (char *)&bool, sizeof(bool)) < 0)
68         log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);
69 #endif
70 }
71
72
73 void k_set_ttl(t)
74     int t;
75 {
76 #ifndef RAW_OUTPUT_IS_RAW
77     u_char ttl;
78
79     ttl = t;
80     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL,
81                    (char *)&ttl, sizeof(ttl)) < 0)
82         log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
83 #endif
84     curttl = t;
85 }
86
87
88 void k_set_loop(l)
89     int l;
90 {
91     u_char loop;
92
93     loop = l;
94     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP,
95                    (char *)&loop, sizeof(loop)) < 0)
96         log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
97 }
98
99
100 void k_set_if(ifa)
101     u_int32 ifa;
102 {
103     struct in_addr adr;
104
105     adr.s_addr = ifa;
106     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF,
107                    (char *)&adr, sizeof(adr)) < 0)
108         log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
109                             inet_fmt(ifa, s1));
110 }
111
112
113 void k_join(grp, ifa)
114     u_int32 grp;
115     u_int32 ifa;
116 {
117     struct ip_mreq mreq;
118
119     mreq.imr_multiaddr.s_addr = grp;
120     mreq.imr_interface.s_addr = ifa;
121
122     if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
123                    (char *)&mreq, sizeof(mreq)) < 0)
124         log(LOG_WARNING, errno, "can't join group %s on interface %s",
125                                 inet_fmt(grp, s1), inet_fmt(ifa, s2));
126 }
127
128
129 void k_leave(grp, ifa)
130     u_int32 grp;
131     u_int32 ifa;
132 {
133     struct ip_mreq mreq;
134
135     mreq.imr_multiaddr.s_addr = grp;
136     mreq.imr_interface.s_addr = ifa;
137
138     if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
139                    (char *)&mreq, sizeof(mreq)) < 0)
140         log(LOG_WARNING, errno, "can't leave group %s on interface %s",
141                                 inet_fmt(grp, s1), inet_fmt(ifa, s2));
142 }
143
144
145 void k_init_dvmrp()
146 {
147 #ifdef OLD_KERNEL
148     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
149                    (char *)NULL, 0) < 0)
150 #else
151     int v=1;
152
153     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
154                    (char *)&v, sizeof(int)) < 0)
155 #endif
156         log(LOG_ERR, errno, "can't enable Multicast routing in kernel");
157 }
158
159
160 void k_stop_dvmrp()
161 {
162     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE,
163                    (char *)NULL, 0) < 0)
164         log(LOG_WARNING, errno, "can't disable Multicast routing in kernel");
165 }
166
167
168 void k_add_vif(vifi, v)
169     vifi_t vifi;
170     struct uvif *v;
171 {
172     struct vifctl vc;
173
174     vc.vifc_vifi            = vifi;
175     vc.vifc_flags           = v->uv_flags & VIFF_KERNEL_FLAGS;
176     vc.vifc_threshold       = v->uv_threshold;
177     vc.vifc_rate_limit      = v->uv_rate_limit;
178     vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
179     vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
180
181     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF,
182                    (char *)&vc, sizeof(vc)) < 0)
183         log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
184 }
185
186
187 void k_del_vif(vifi)
188     vifi_t vifi;
189 {
190     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
191                    (char *)&vifi, sizeof(vifi)) < 0)
192         log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
193 }
194
195
196 /*
197  * Adds a (source, mcastgrp) entry to the kernel
198  */
199 void k_add_rg(origin, g)
200     u_int32 origin;
201     struct gtable *g;
202 {
203     struct mfcctl mc;
204     vifi_t i;
205
206 #ifdef DEBUG_MFC
207     md_log(MD_ADD, origin, g->gt_mcastgrp);
208 #endif
209     /* copy table values so that setsockopt can process it */
210     mc.mfcc_origin.s_addr = origin;
211 #ifdef OLD_KERNEL
212     mc.mfcc_originmask.s_addr = 0xffffffff;
213 #endif
214     mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
215     mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF;
216     for (i = 0; i < numvifs; i++)
217         mc.mfcc_ttls[i] = g->gt_ttls[i];
218
219     /* write to kernel space */
220     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
221                    (char *)&mc, sizeof(mc)) < 0) {
222 #ifdef DEBUG_MFC
223         md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
224 #endif
225         log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC",
226                 inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
227     }
228 }
229
230
231 /*
232  * Deletes a (source, mcastgrp) entry from the kernel
233  */
234 int k_del_rg(origin, g)
235     u_int32 origin;
236     struct gtable *g;
237 {
238     struct mfcctl mc;
239     int retval;
240
241 #ifdef DEBUG_MFC
242     md_log(MD_DEL, origin, g->gt_mcastgrp);
243 #endif
244     /* copy table values so that setsockopt can process it */
245     mc.mfcc_origin.s_addr = origin;
246 #ifdef OLD_KERNEL
247     mc.mfcc_originmask.s_addr = 0xffffffff;
248 #endif
249     mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
250
251     /* write to kernel space */
252     if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
253                    (char *)&mc, sizeof(mc))) < 0) {
254 #ifdef DEBUG_MFC
255         md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
256 #endif
257         log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
258                 inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
259     }
260
261     return retval;
262 }       
263
264 /*
265  * Get the kernel's idea of what version of mrouted needs to run with it.
266  */
267 int k_get_version()
268 {
269 #ifdef OLD_KERNEL
270     return -1;
271 #else
272     int vers;
273     int len = sizeof(vers);
274
275     if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
276                         (char *)&vers, &len) < 0)
277         log(LOG_ERR, errno,
278                 "getsockopt MRT_VERSION: perhaps your kernel is too old");
279
280     return vers;
281 #endif
282 }
283
284 #if 0
285 /*
286  * Get packet counters
287  */
288 int
289 k_get_vif_count(vifi, icount, ocount, ibytes, obytes)
290     vifi_t vifi;
291     int *icount, *ocount, *ibytes, *obytes;
292 {
293     struct sioc_vif_req vreq;
294     int retval = 0;
295
296     vreq.vifi = vifi;
297     if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
298         log(LOG_WARNING, errno, "SIOCGETVIFCNT on vif %d", vifi);
299         vreq.icount = vreq.ocount = vreq.ibytes =
300                 vreq.obytes = 0xffffffff;
301         retval = 1;
302     }
303     if (icount)
304         *icount = vreq.icount;
305     if (ocount)
306         *ocount = vreq.ocount;
307     if (ibytes)
308         *ibytes = vreq.ibytes;
309     if (obytes)
310         *obytes = vreq.obytes;
311     return retval;
312 }
313
314 /*
315  * Get counters for a desired source and group.
316  */
317 int
318 k_get_sg_count(src, grp, pktcnt, bytecnt, wrong_if)
319     u_int32 src;
320     u_int32 grp;
321     struct sg_count *retval;
322 {
323     struct sioc_sg_req sgreq;
324     int retval = 0;
325
326     sgreq.src.s_addr = src;
327     sgreq.grp.s_addr = grp;
328     if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sgreq) < 0) {
329         log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
330             inet_fmt(src, s1), inet_fmt(grp, s2));
331         sgreq.pktcnt = sgreq.bytecnt = sgreq.wrong_if = 0xffffffff;
332         return 1;
333     }
334     if (pktcnt)
335         *pktcnt = sgreq.pktcnt;
336     if (bytecnt)
337         *bytecnt = sgreq.bytecnt;
338     if (wrong_if)
339         *wrong_if = sgreq.wrong_if;
340     return retval;
341 }
342 #endif