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.4 2004/12/16 03:39:05 dillon Exp $
21 k_set_rcvbuf(int bufsize
, int minsize
)
23 int delta
= bufsize
/ 2;
27 * Set the socket buffer. If we can't set it as large as we
28 * want, search around to try to find the highest acceptable
29 * value. The highest acceptable value being smaller than
30 * minsize is a fatal error.
32 if (setsockopt(igmp_socket
, SOL_SOCKET
, SO_RCVBUF
,
33 (char *)&bufsize
, sizeof(bufsize
)) < 0) {
40 if (setsockopt(igmp_socket
, SOL_SOCKET
, SO_RCVBUF
,
41 (char *)&bufsize
, sizeof(bufsize
)) < 0) {
49 if (bufsize
< minsize
) {
50 log(LOG_ERR
, 0, "OS-allowed buffer size %u < app min %u",
56 log(LOG_DEBUG
, 0, "Got %d byte buffer size in %d iterations",
61 k_hdr_include(int boolv
)
64 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_HDRINCL
,
65 (char *)&boolv
, sizeof(boolv
)) < 0)
66 log(LOG_ERR
, errno
, "setsockopt IP_HDRINCL %u", boolv
);
73 #ifndef RAW_OUTPUT_IS_RAW
77 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_MULTICAST_TTL
,
78 (char *)&ttl
, sizeof(ttl
)) < 0)
79 log(LOG_ERR
, errno
, "setsockopt IP_MULTICAST_TTL %u", ttl
);
90 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_MULTICAST_LOOP
,
91 (char *)&loop
, sizeof(loop
)) < 0)
92 log(LOG_ERR
, errno
, "setsockopt IP_MULTICAST_LOOP %u", loop
);
101 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_MULTICAST_IF
,
102 (char *)&adr
, sizeof(adr
)) < 0)
103 log(LOG_ERR
, errno
, "setsockopt IP_MULTICAST_IF %s",
108 k_join(u_int32 grp
, u_int32 ifa
)
112 mreq
.imr_multiaddr
.s_addr
= grp
;
113 mreq
.imr_interface
.s_addr
= ifa
;
115 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
116 (char *)&mreq
, sizeof(mreq
)) < 0)
117 log(LOG_WARNING
, errno
, "can't join group %s on interface %s",
118 inet_fmt(grp
, s1
), inet_fmt(ifa
, s2
));
122 k_leave(u_int32 grp
, u_int32 ifa
)
126 mreq
.imr_multiaddr
.s_addr
= grp
;
127 mreq
.imr_interface
.s_addr
= ifa
;
129 if (setsockopt(igmp_socket
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
130 (char *)&mreq
, sizeof(mreq
)) < 0)
131 log(LOG_WARNING
, errno
, "can't leave group %s on interface %s",
132 inet_fmt(grp
, s1
), inet_fmt(ifa
, s2
));
139 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_INIT
,
140 (char *)NULL
, 0) < 0)
144 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_INIT
,
145 (char *)&v
, sizeof(int)) < 0)
147 log(LOG_ERR
, errno
, "can't enable Multicast routing in kernel");
153 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_DONE
,
154 (char *)NULL
, 0) < 0)
155 log(LOG_WARNING
, errno
, "can't disable Multicast routing in kernel");
159 k_add_vif(vifi_t vifi
, struct uvif
*v
)
164 vc
.vifc_flags
= v
->uv_flags
& VIFF_KERNEL_FLAGS
;
165 vc
.vifc_threshold
= v
->uv_threshold
;
166 vc
.vifc_rate_limit
= v
->uv_rate_limit
;
167 vc
.vifc_lcl_addr
.s_addr
= v
->uv_lcl_addr
;
168 vc
.vifc_rmt_addr
.s_addr
= v
->uv_rmt_addr
;
170 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_ADD_VIF
,
171 (char *)&vc
, sizeof(vc
)) < 0)
172 log(LOG_ERR
, errno
, "setsockopt MRT_ADD_VIF on vif %d", vifi
);
176 k_del_vif(vifi_t vifi
)
179 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_DEL_VIF
,
180 (char *)&vifi
, sizeof(vifi
)) < 0)
181 log(LOG_ERR
, errno
, "setsockopt MRT_DEL_VIF on vif %d", vifi
);
185 * Adds a (source, mcastgrp) entry to the kernel
188 k_add_rg(u_int32 origin
, struct gtable
*g
)
194 md_log(MD_ADD
, origin
, g
->gt_mcastgrp
);
196 /* copy table values so that setsockopt can process it */
197 mc
.mfcc_origin
.s_addr
= origin
;
199 mc
.mfcc_originmask
.s_addr
= 0xffffffff;
201 mc
.mfcc_mcastgrp
.s_addr
= g
->gt_mcastgrp
;
202 mc
.mfcc_parent
= g
->gt_route
? g
->gt_route
->rt_parent
: NO_VIF
;
203 for (i
= 0; i
< numvifs
; i
++)
204 mc
.mfcc_ttls
[i
] = g
->gt_ttls
[i
];
206 /* write to kernel space */
207 if (setsockopt(igmp_socket
, IPPROTO_IP
, MRT_ADD_MFC
,
208 (char *)&mc
, sizeof(mc
)) < 0) {
210 md_log(MD_ADD_FAIL
, origin
, g
->gt_mcastgrp
);
212 log(LOG_WARNING
, errno
, "setsockopt MRT_ADD_MFC",
213 inet_fmt(origin
, s1
), inet_fmt(g
->gt_mcastgrp
, s2
));
219 * Deletes a (source, mcastgrp) entry from the kernel
222 k_del_rg(u_int32 origin
, struct gtable
*g
)
228 md_log(MD_DEL
, origin
, g
->gt_mcastgrp
);
230 /* copy table values so that setsockopt can process it */
231 mc
.mfcc_origin
.s_addr
= origin
;
233 mc
.mfcc_originmask
.s_addr
= 0xffffffff;
235 mc
.mfcc_mcastgrp
.s_addr
= g
->gt_mcastgrp
;
237 /* write to kernel space */
238 if ((retval
= setsockopt(igmp_socket
, IPPROTO_IP
, MRT_DEL_MFC
,
239 (char *)&mc
, sizeof(mc
))) < 0) {
241 md_log(MD_DEL_FAIL
, origin
, g
->gt_mcastgrp
);
243 log(LOG_WARNING
, errno
, "setsockopt MRT_DEL_MFC of (%s %s)",
244 inet_fmt(origin
, s1
), inet_fmt(g
->gt_mcastgrp
, s2
));
251 * Get the kernel's idea of what version of mrouted needs to run with it.
260 int len
= sizeof(vers
);
262 if (getsockopt(igmp_socket
, IPPROTO_IP
, MRT_VERSION
,
263 (char *)&vers
, &len
) < 0)
265 "getsockopt MRT_VERSION: perhaps your kernel is too old");