Pre-2.0 release: Sync with HAMMER 65 - simplify PFS operations.
[dragonfly.git] / usr.sbin / mrouted / kern.c
blobe15b72cd85b4301d68077cf4695e11d793563001
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.
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 $
16 #include "defs.h"
18 int curttl = 0;
20 void
21 k_set_rcvbuf(int bufsize, int minsize)
23 int delta = bufsize / 2;
24 int iter = 0;
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) {
34 bufsize -= delta;
35 while (1) {
36 iter++;
37 if (delta > 1)
38 delta /= 2;
40 if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
41 (char *)&bufsize, sizeof(bufsize)) < 0) {
42 bufsize -= delta;
43 } else {
44 if (delta < 1024)
45 break;
46 bufsize += delta;
49 if (bufsize < minsize) {
50 log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
51 bufsize, minsize);
52 /*NOTREACHED*/
55 IF_DEBUG(DEBUG_KERN)
56 log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
57 bufsize, iter);
60 void
61 k_hdr_include(int boolv)
63 #ifdef IP_HDRINCL
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);
67 #endif
70 void
71 k_set_ttl(int t)
73 #ifndef RAW_OUTPUT_IS_RAW
74 u_char ttl;
76 ttl = t;
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);
80 #endif
81 curttl = t;
84 void
85 k_set_loop(int l)
87 u_char loop;
89 loop = l;
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);
95 void
96 k_set_if(u_int32 ifa)
98 struct in_addr adr;
100 adr.s_addr = ifa;
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",
104 inet_fmt(ifa, s1));
107 void
108 k_join(u_int32 grp, u_int32 ifa)
110 struct ip_mreq mreq;
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));
121 void
122 k_leave(u_int32 grp, u_int32 ifa)
124 struct ip_mreq mreq;
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));
135 void
136 k_init_dvmrp(void)
138 #ifdef OLD_KERNEL
139 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
140 (char *)NULL, 0) < 0)
141 #else
142 int v=1;
144 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
145 (char *)&v, sizeof(int)) < 0)
146 #endif
147 log(LOG_ERR, errno, "can't enable Multicast routing in kernel");
150 void
151 k_stop_dvmrp(void)
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");
158 void
159 k_add_vif(vifi_t vifi, struct uvif *v)
161 struct vifctl vc;
163 vc.vifc_vifi = vifi;
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);
175 void
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
187 void
188 k_add_rg(u_int32 origin, struct gtable *g)
190 struct mfcctl mc;
191 vifi_t i;
193 #ifdef DEBUG_MFC
194 md_log(MD_ADD, origin, g->gt_mcastgrp);
195 #endif
196 /* copy table values so that setsockopt can process it */
197 mc.mfcc_origin.s_addr = origin;
198 #ifdef OLD_KERNEL
199 mc.mfcc_originmask.s_addr = 0xffffffff;
200 #endif
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) {
209 #ifdef DEBUG_MFC
210 md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
211 #endif
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)
224 struct mfcctl mc;
225 int retval;
227 #ifdef DEBUG_MFC
228 md_log(MD_DEL, origin, g->gt_mcastgrp);
229 #endif
230 /* copy table values so that setsockopt can process it */
231 mc.mfcc_origin.s_addr = origin;
232 #ifdef OLD_KERNEL
233 mc.mfcc_originmask.s_addr = 0xffffffff;
234 #endif
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) {
240 #ifdef DEBUG_MFC
241 md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
242 #endif
243 log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
244 inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
247 return retval;
251 * Get the kernel's idea of what version of mrouted needs to run with it.
254 k_get_version(void)
256 #ifdef OLD_KERNEL
257 return -1;
258 #else
259 int vers;
260 int len = sizeof(vers);
262 if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
263 (char *)&vers, &len) < 0)
264 log(LOG_ERR, errno,
265 "getsockopt MRT_VERSION: perhaps your kernel is too old");
267 return vers;
268 #endif