xref: /netbsd-src/usr.sbin/mrouted/kern.c (revision 9f61b80465425a3cc94c6438ccec8497c7340a45)
1*9f61b804Splunky /*	$NetBSD: kern.c,v 1.12 2011/08/31 16:24:59 plunky Exp $	*/
2c60d41a9Swiz 
3c60d41a9Swiz /*
4c60d41a9Swiz  * The mrouted program is covered by the license in the accompanying file
5c60d41a9Swiz  * named "LICENSE".  Use of the mrouted program represents acceptance of
6c60d41a9Swiz  * the terms and conditions listed in that file.
7c60d41a9Swiz  *
8c60d41a9Swiz  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
9c60d41a9Swiz  * Leland Stanford Junior University.
10c60d41a9Swiz  */
11c60d41a9Swiz 
12c60d41a9Swiz 
13c60d41a9Swiz #include "defs.h"
14c60d41a9Swiz 
15c60d41a9Swiz 
k_set_rcvbuf(int bufsize)16c60d41a9Swiz void k_set_rcvbuf(int bufsize)
17c60d41a9Swiz {
18c60d41a9Swiz     if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
19c60d41a9Swiz 		   (char *)&bufsize, sizeof(bufsize)) < 0)
20c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize);
21c60d41a9Swiz }
22c60d41a9Swiz 
23c60d41a9Swiz 
k_hdr_include(int onoff)246c185a0bSdyoung void k_hdr_include(int onoff)
25c60d41a9Swiz {
26c60d41a9Swiz #ifdef IP_HDRINCL
27c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL,
286c185a0bSdyoung 		   (char *)&onoff, sizeof(onoff)) < 0)
296c185a0bSdyoung 	logit(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", onoff);
30c60d41a9Swiz #endif
31c60d41a9Swiz }
32c60d41a9Swiz 
33c60d41a9Swiz 
k_set_ttl(int t)34c60d41a9Swiz void k_set_ttl(int t)
35c60d41a9Swiz {
36c60d41a9Swiz     u_char ttl;
37c60d41a9Swiz 
38c60d41a9Swiz     ttl = t;
39c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL,
40c60d41a9Swiz 		   (char *)&ttl, sizeof(ttl)) < 0)
41c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
42c60d41a9Swiz }
43c60d41a9Swiz 
44c60d41a9Swiz 
k_set_loop(int l)45c60d41a9Swiz void k_set_loop(int l)
46c60d41a9Swiz {
47c60d41a9Swiz     u_char loop;
48c60d41a9Swiz 
49c60d41a9Swiz     loop = l;
50c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP,
51c60d41a9Swiz 		   (char *)&loop, sizeof(loop)) < 0)
52c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
53c60d41a9Swiz }
54c60d41a9Swiz 
55c60d41a9Swiz 
k_set_if(u_int32_t ifa)56c60d41a9Swiz void k_set_if(u_int32_t ifa)
57c60d41a9Swiz {
58c60d41a9Swiz     struct in_addr adr;
59c60d41a9Swiz 
60c60d41a9Swiz     adr.s_addr = ifa;
61c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF,
62c60d41a9Swiz 		   (char *)&adr, sizeof(adr)) < 0)
63c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
64ee70b5d6Sdsl 	    		    inet_fmt(ifa));
65c60d41a9Swiz }
66c60d41a9Swiz 
67c60d41a9Swiz 
k_join(u_int32_t grp,u_int32_t ifa)68c60d41a9Swiz void k_join(u_int32_t grp, u_int32_t ifa)
69c60d41a9Swiz {
70c60d41a9Swiz     struct ip_mreq mreq;
71c60d41a9Swiz 
72c60d41a9Swiz     mreq.imr_multiaddr.s_addr = grp;
73c60d41a9Swiz     mreq.imr_interface.s_addr = ifa;
74c60d41a9Swiz 
75c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
76c60d41a9Swiz 		   (char *)&mreq, sizeof(mreq)) < 0)
77c60d41a9Swiz 	logit(LOG_WARNING, errno, "can't join group %s on interface %s",
78ee70b5d6Sdsl 				inet_fmt(grp),
79ee70b5d6Sdsl 				inet_fmt(ifa));
80c60d41a9Swiz }
81c60d41a9Swiz 
82c60d41a9Swiz 
k_leave(u_int32_t grp,u_int32_t ifa)83c60d41a9Swiz void k_leave(u_int32_t grp, u_int32_t ifa)
84c60d41a9Swiz {
85c60d41a9Swiz     struct ip_mreq mreq;
86c60d41a9Swiz 
87c60d41a9Swiz     mreq.imr_multiaddr.s_addr = grp;
88c60d41a9Swiz     mreq.imr_interface.s_addr = ifa;
89c60d41a9Swiz 
90c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
91c60d41a9Swiz 		   (char *)&mreq, sizeof(mreq)) < 0)
92c60d41a9Swiz 	logit(LOG_WARNING, errno, "can't leave group %s on interface %s",
93ee70b5d6Sdsl 				inet_fmt(grp),
94ee70b5d6Sdsl 				inet_fmt(ifa));
95c60d41a9Swiz }
96c60d41a9Swiz 
97c60d41a9Swiz 
k_init_dvmrp(void)98c60d41a9Swiz void k_init_dvmrp(void)
99c60d41a9Swiz {
100c60d41a9Swiz #ifdef OLD_KERNEL
101c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
102*9f61b804Splunky 		   NULL, 0) < 0)
103c60d41a9Swiz #else
104c60d41a9Swiz     int v=1;
105c60d41a9Swiz 
106c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
107c60d41a9Swiz 		   (char *)&v, sizeof(int)) < 0)
108c60d41a9Swiz #endif
109c60d41a9Swiz 	logit(LOG_ERR, errno, "can't enable Multicast routing in kernel");
110c60d41a9Swiz }
111c60d41a9Swiz 
112c60d41a9Swiz 
k_stop_dvmrp(void)113c60d41a9Swiz void k_stop_dvmrp(void)
114c60d41a9Swiz {
115c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE,
116*9f61b804Splunky 		   NULL, 0) < 0)
117c60d41a9Swiz 	logit(LOG_WARNING, errno, "can't disable Multicast routing in kernel");
118c60d41a9Swiz }
119c60d41a9Swiz 
120c60d41a9Swiz 
k_add_vif(vifi_t vifi,struct uvif * v)121c60d41a9Swiz void k_add_vif(vifi_t vifi, struct uvif *v)
122c60d41a9Swiz {
123c60d41a9Swiz     struct vifctl vc;
124c60d41a9Swiz 
125c60d41a9Swiz     vc.vifc_vifi            = vifi;
126c60d41a9Swiz     vc.vifc_flags           = v->uv_flags & VIFF_KERNEL_FLAGS;
127c60d41a9Swiz     vc.vifc_threshold       = v->uv_threshold;
128c60d41a9Swiz     vc.vifc_rate_limit	    = v->uv_rate_limit;
129c60d41a9Swiz     vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
130c60d41a9Swiz     vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
131c60d41a9Swiz 
132c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF,
133c60d41a9Swiz 		   (char *)&vc, sizeof(vc)) < 0)
134c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt MRT_ADD_VIF");
135c60d41a9Swiz }
136c60d41a9Swiz 
137c60d41a9Swiz 
k_del_vif(vifi_t vifi)138c60d41a9Swiz void k_del_vif(vifi_t vifi)
139c60d41a9Swiz {
140c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
141c60d41a9Swiz 		   (char *)&vifi, sizeof(vifi)) < 0)
142c60d41a9Swiz 	logit(LOG_ERR, errno, "setsockopt MRT_DEL_VIF");
143c60d41a9Swiz }
144c60d41a9Swiz 
145c60d41a9Swiz 
146c60d41a9Swiz /*
147c60d41a9Swiz  * Adds a (source, mcastgrp) entry to the kernel
148c60d41a9Swiz  */
k_add_rg(u_int32_t origin,struct gtable * g)149c60d41a9Swiz void k_add_rg(u_int32_t origin, struct gtable *g)
150c60d41a9Swiz {
151c60d41a9Swiz     struct mfcctl mc;
152c60d41a9Swiz     vifi_t i;
153c60d41a9Swiz 
154c60d41a9Swiz #ifdef DEBUG_MFC
155c60d41a9Swiz     md_log(MD_ADD, origin, g->gt_mcastgrp);
156c60d41a9Swiz #endif
157c60d41a9Swiz     /* copy table values so that setsockopt can process it */
158c60d41a9Swiz     mc.mfcc_origin.s_addr = origin;
159c60d41a9Swiz #ifdef OLD_KERNEL
160c60d41a9Swiz     mc.mfcc_originmask.s_addr = 0xffffffff;
161c60d41a9Swiz #endif
162c60d41a9Swiz     mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
163c60d41a9Swiz     mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF;
164c60d41a9Swiz     for (i = 0; i < numvifs; i++)
165c60d41a9Swiz 	mc.mfcc_ttls[i] = g->gt_ttls[i];
166c60d41a9Swiz 
167c60d41a9Swiz     /* write to kernel space */
168c60d41a9Swiz     if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
169c60d41a9Swiz 		   (char *)&mc, sizeof(mc)) < 0) {
170c60d41a9Swiz #ifdef DEBUG_MFC
171c60d41a9Swiz 	md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
172c60d41a9Swiz #endif
173c60d41a9Swiz 	logit(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC");
174c60d41a9Swiz     }
175c60d41a9Swiz }
176c60d41a9Swiz 
177c60d41a9Swiz 
178c60d41a9Swiz /*
179c60d41a9Swiz  * Deletes a (source, mcastgrp) entry from the kernel
180c60d41a9Swiz  */
k_del_rg(u_int32_t origin,struct gtable * g)181c60d41a9Swiz int k_del_rg(u_int32_t origin, struct gtable *g)
182c60d41a9Swiz {
183c60d41a9Swiz     struct mfcctl mc;
184c60d41a9Swiz     int retval;
185c60d41a9Swiz 
186c60d41a9Swiz #ifdef DEBUG_MFC
187c60d41a9Swiz     md_log(MD_DEL, origin, g->gt_mcastgrp);
188c60d41a9Swiz #endif
189c60d41a9Swiz     /* copy table values so that setsockopt can process it */
190c60d41a9Swiz     mc.mfcc_origin.s_addr = origin;
191c60d41a9Swiz #ifdef OLD_KERNEL
192c60d41a9Swiz     mc.mfcc_originmask.s_addr = 0xffffffff;
193c60d41a9Swiz #endif
194c60d41a9Swiz     mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
195c60d41a9Swiz 
196c60d41a9Swiz     /* write to kernel space */
197c60d41a9Swiz     if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
198c60d41a9Swiz 		   (char *)&mc, sizeof(mc))) < 0) {
199c60d41a9Swiz #ifdef DEBUG_MFC
200c60d41a9Swiz 	md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
201c60d41a9Swiz #endif
202c60d41a9Swiz 	logit(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC");
203c60d41a9Swiz     }
204c60d41a9Swiz 
205c60d41a9Swiz     return retval;
206c60d41a9Swiz }
207c60d41a9Swiz 
208c60d41a9Swiz /*
209c60d41a9Swiz  * Get the kernel's idea of what version of mrouted needs to run with it.
210c60d41a9Swiz  */
k_get_version(void)211c60d41a9Swiz int k_get_version(void)
212c60d41a9Swiz {
213c60d41a9Swiz #ifdef OLD_KERNEL
214c60d41a9Swiz     return -1;
215c60d41a9Swiz #else
216c60d41a9Swiz     int vers;
2170c37c63eSmrg     socklen_t len = sizeof(vers);
218c60d41a9Swiz 
219c60d41a9Swiz     if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
220c60d41a9Swiz 			(char *)&vers, &len) < 0)
221c60d41a9Swiz 	logit(LOG_ERR, errno,
222c60d41a9Swiz 		"getsockopt MRT_VERSION: perhaps your kernel is too old");
223c60d41a9Swiz 
224c60d41a9Swiz     return vers;
225c60d41a9Swiz #endif
226c60d41a9Swiz }
227