This source file includes following definitions.
- vif_delete
- ip_mroute_setsockopt
- ip_mroute_getsockopt
- ipmr_ioctl
- mroute_close
- ipmr_device_event
- ip_mr_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <asm/system.h>
22 #include <asm/segment.h>
23 #include <linux/types.h>
24 #include <linux/sched.h>
25 #include <linux/errno.h>
26 #include <linux/timer.h>
27 #include <linux/mm.h>
28 #include <linux/kernel.h>
29 #include <linux/fcntl.h>
30 #include <linux/socket.h>
31 #include <linux/in.h>
32 #include <linux/inet.h>
33 #include <linux/netdevice.h>
34 #include <linux/mroute.h>
35 #include <net/ip.h>
36 #include <net/protocol.h>
37 #include <linux/skbuff.h>
38 #include <net/sock.h>
39 #include <net/icmp.h>
40 #include <net/udp.h>
41 #include <linux/notifier.h>
42 #include <net/checksum.h>
43
44 #ifdef CONFIG_IP_MROUTE
45
46
47
48
49
50 static struct vif_device vif_table[MAXVIFS];
51 static unsigned long vifc_map;
52 int mroute_do_pim = 0;
53
54
55
56
57
58 static void vif_delete(struct vif_device *v)
59 {
60 if(!(v->flags&VIFF_TUNNEL))
61 {
62 v->dev->flags&=~IFF_ALLMULTI;
63 dev_mc_upload(v->dev);
64 }
65 v->dev=NULL;
66 }
67
68
69
70
71
72
73
74
75 int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
76 {
77 int err;
78 struct vifctl vif;
79
80 if(optname!=MRT_INIT)
81 {
82 if(sk!=mroute_socket)
83 return -EACCES;
84 }
85
86 switch(optname)
87 {
88 case MRT_INIT:
89 if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
90 return -EOPNOTSUPP;
91 if(optlen!=sizeof(int))
92 return -ENOPROTOOPT;
93 if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
94 return err;
95 if(get_user((int *)optval)!=1)
96 return -ENOPROTOOPT;
97 if(mroute_socket)
98 return -EADDRINUSE;
99 mroute_socket=sk;
100
101 return 0;
102 case MRT_DONE:
103 mroute_close(sk);
104 mroute_socket=NULL;
105 return 0;
106 case MRT_ADD_VIF:
107 case MRT_DEL_VIF:
108 if(optlen!=sizeof(vif))
109 return -EINVAL;
110 if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
111 return err;
112 memcpy_fromfs(&vif,optval,sizeof(vif));
113 if(vif.vifc_vifi > MAXVIFS)
114 return -ENFILE;
115 if(optname==MRT_ADD_VIF)
116 {
117 struct vif_device *v=&vif_table[vif.vifc_vifi];
118 struct device *dev;
119
120 if(vifc_map&(1<<vif.vifc_vifi))
121 return -EADDRINUSE;
122
123 dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
124 if(!dev)
125 return -EADDRNOTAVAIL;
126
127 if(vif.vifc_flags&VIFF_TUNNEL)
128 {
129 if(vif.vifc_flags&VIFF_SRCRT)
130 return -EOPNOTSUPP;
131
132 }
133 else
134 {
135 if(dev->flags&IFF_MULTICAST)
136 {
137
138
139 dev->flags|=IFF_ALLMULTI;
140 dev_mc_upload(dev);
141 }
142 else
143 {
144
145 return -EOPNOTSUPP;
146 }
147 }
148
149
150
151 cli();
152 v->rate_limit=vif.vifc_rate_limit;
153 v->local=vif.vifc_lcl_addr.s_addr;
154 v->remote=vif.vifc_rmt_addr.s_addr;
155 v->flags=vif.vifc_flags;
156 v->threshold=vif.vifc_threshold;
157 v->dev=dev;
158 v->bytes_in = 0;
159 v->bytes_out = 0;
160 v->pkt_in = 0;
161 v->pkt_out = 0;
162 vifc_map|=(1<<vif.vifc_vifi);
163 sti();
164 return 0;
165 }
166 else
167
168
169
170 {
171 struct vif_device *v=&vif_table[vif.vifc_vifi];
172 if(vifc_map&(1<<vif.vifc_vifi))
173 {
174 vif_delete(v);
175 vifc_map&=~(1<<vif.vifc_vifi);
176 return 0;
177 }
178 else
179 return -EADDRNOTAVAIL;
180 }
181
182
183
184
185 case MRT_ADD_MFC:
186 case MRT_DEL_MFC:
187 return -EOPNOTSUPP;
188
189
190
191 case MRT_ASSERT:
192 if(optlen!=sizeof(int))
193 return -EINVAL;
194 if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
195 return err;
196 mroute_do_pim= (optval)?1:0;
197 return 0;
198
199
200
201
202 default:
203 return -EOPNOTSUPP;
204 }
205 }
206
207
208
209
210
211 int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
212 {
213 int olr;
214 int err;
215
216 if(sk!=mroute_socket)
217 return -EACCES;
218 if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
219 return -EOPNOTSUPP;
220
221 olr=get_user(optlen);
222 if(olr!=sizeof(int))
223 return -EINVAL;
224 err=verify_area(VERIFY_WRITE, optval,sizeof(int));
225 if(err)
226 return err;
227 put_user(sizeof(int),optlen);
228 if(optname==MRT_VERSION)
229 put_user(0x0305,(int *)optval);
230 else
231 put_user(mroute_do_pim,(int *)optval);
232 return 0;
233 }
234
235
236
237
238
239 int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
240 {
241 int err;
242 struct sioc_sg_req sr;
243 struct sioc_vif_req vr;
244 struct vif_device *vif;
245
246 switch(cmd)
247 {
248 case SIOCGETVIFCNT:
249 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
250 if(err)
251 return err;
252 memcpy_fromfs(&vr,(void *)arg,sizeof(vr));
253 if(vr.vifi>=MAXVIFS)
254 return -EINVAL;
255 vif=&vif_table[vr.vifi];
256 if(vifc_map&(1<<vr.vifi))
257 {
258 vr.icount=vif->pkt_in;
259 vr.ocount=vif->pkt_out;
260 vr.ibytes=vif->bytes_in;
261 vr.obytes=vif->bytes_out;
262 memcpy_tofs((void *)arg,&vr,sizeof(vr));
263 return 0;
264 }
265 return -EADDRNOTAVAIL;
266 case SIOCGETSGCNT:
267 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
268 if(err)
269 return err;
270 memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
271 memcpy_tofs((void *)arg,&sr,sizeof(sr));
272 return 0;
273 default:
274 return -EINVAL;
275 }
276 }
277
278
279
280
281
282 void mroute_close(struct sock *sk)
283 {
284 int i;
285 struct vif_device *v=&vif_table[0];
286
287
288
289
290
291 for(i=0;i<MAXVIFS;i++)
292 {
293 if(vifc_map&(1<<i))
294 {
295 if(!(v->flags&VIFF_TUNNEL))
296 {
297 v->dev->flags&=~IFF_ALLMULTI;
298 dev_mc_upload(v->dev);
299 }
300 }
301 v++;
302 }
303 vifc_map=0;
304 }
305
306 static int ipmr_device_event(unsigned long event, void *ptr)
307 {
308 struct vif_device *v;
309 int ct;
310 if(event!=NETDEV_DOWN)
311 return NOTIFY_DONE;
312 v=&vif_table[0];
313 for(ct=0;ct<MAXVIFS;ct++)
314 {
315 if((vifc_map&(1<<ct)) && v->dev==ptr)
316 {
317 vif_delete(v);
318 vifc_map&=~(1<<ct);
319 }
320 v++;
321 }
322 return NOTIFY_DONE;
323 }
324
325
326 static struct notifier_block ip_mr_notifier={
327 ipmr_device_event,
328 NULL,
329 0
330 };
331
332
333 void ip_mr_init(void)
334 {
335 printk("Linux IP multicast router 0.00pre-working 8)\n");
336 register_netdevice_notifier(&ip_mr_notifier);
337 }
338
339 #endif