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