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.
6 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
7 * Leland Stanford Junior University.
10 * kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp
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 $
20 void k_set_rcvbuf(bufsize, minsize)
24 int delta = bufsize / 2;
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.
33 if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
34 (char *)&bufsize, sizeof(bufsize)) < 0) {
41 if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
42 (char *)&bufsize, sizeof(bufsize)) < 0) {
50 if (bufsize < minsize) {
51 log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
57 log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
62 void k_hdr_include(bool)
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);
76 #ifndef RAW_OUTPUT_IS_RAW
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);
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);
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",
113 void k_join(grp, ifa)
119 mreq.imr_multiaddr.s_addr = grp;
120 mreq.imr_interface.s_addr = ifa;
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));
129 void k_leave(grp, ifa)
135 mreq.imr_multiaddr.s_addr = grp;
136 mreq.imr_interface.s_addr = ifa;
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));
148 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
149 (char *)NULL, 0) < 0)
153 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
154 (char *)&v, sizeof(int)) < 0)
156 log(LOG_ERR, errno, "can't enable Multicast routing in kernel");
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");
168 void k_add_vif(vifi, v)
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;
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);
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);
197 * Adds a (source, mcastgrp) entry to the kernel
199 void k_add_rg(origin, g)
207 md_log(MD_ADD, origin, g->gt_mcastgrp);
209 /* copy table values so that setsockopt can process it */
210 mc.mfcc_origin.s_addr = origin;
212 mc.mfcc_originmask.s_addr = 0xffffffff;
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];
219 /* write to kernel space */
220 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
221 (char *)&mc, sizeof(mc)) < 0) {
223 md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
225 log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC",
226 inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
232 * Deletes a (source, mcastgrp) entry from the kernel
234 int k_del_rg(origin, g)
242 md_log(MD_DEL, origin, g->gt_mcastgrp);
244 /* copy table values so that setsockopt can process it */
245 mc.mfcc_origin.s_addr = origin;
247 mc.mfcc_originmask.s_addr = 0xffffffff;
249 mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
251 /* write to kernel space */
252 if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
253 (char *)&mc, sizeof(mc))) < 0) {
255 md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
257 log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
258 inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
265 * Get the kernel's idea of what version of mrouted needs to run with it.
273 int len = sizeof(vers);
275 if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
276 (char *)&vers, &len) < 0)
278 "getsockopt MRT_VERSION: perhaps your kernel is too old");
286 * Get packet counters
289 k_get_vif_count(vifi, icount, ocount, ibytes, obytes)
291 int *icount, *ocount, *ibytes, *obytes;
293 struct sioc_vif_req vreq;
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;
304 *icount = vreq.icount;
306 *ocount = vreq.ocount;
308 *ibytes = vreq.ibytes;
310 *obytes = vreq.obytes;
315 * Get counters for a desired source and group.
318 k_get_sg_count(src, grp, pktcnt, bytecnt, wrong_if)
321 struct sg_count *retval;
323 struct sioc_sg_req sgreq;
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;
335 *pktcnt = sgreq.pktcnt;
337 *bytecnt = sgreq.bytecnt;
339 *wrong_if = sgreq.wrong_if;