This source file includes following definitions.
- ip_mc_procinfo
- ip_mc_find_devfor
- ip_setsockopt
- ip_getsockopt
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/config.h>
15 #include <linux/types.h>
16 #include <linux/mm.h>
17 #include <linux/sched.h>
18 #include <linux/skbuff.h>
19 #include <linux/ip.h>
20 #include <linux/icmp.h>
21 #include <linux/netdevice.h>
22 #include <net/sock.h>
23 #include <net/ip.h>
24 #include <net/icmp.h>
25 #include <linux/tcp.h>
26 #include <linux/udp.h>
27 #include <linux/firewall.h>
28 #include <linux/ip_fw.h>
29 #include <net/checksum.h>
30 #include <linux/route.h>
31 #include <linux/mroute.h>
32 #include <net/route.h>
33
34 #include <asm/segment.h>
35
36 #ifdef CONFIG_IP_MULTICAST
37
38
39
40
41
42
43 int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length, int dummy)
44 {
45 off_t pos=0, begin=0;
46 struct ip_mc_list *im;
47 unsigned long flags;
48 int len=0;
49 struct device *dev;
50
51 len=sprintf(buffer,"Device : Count\tGroup Users Timer\n");
52 save_flags(flags);
53 cli();
54
55 for(dev = dev_base; dev; dev = dev->next)
56 {
57 if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST))
58 {
59 len+=sprintf(buffer+len,"%-10s: %5d\n",
60 dev->name, dev->mc_count);
61 for(im = dev->ip_mc_list; im; im = im->next)
62 {
63 len+=sprintf(buffer+len,
64 "\t\t\t%08lX %5d %d:%08lX\n",
65 im->multiaddr, im->users,
66 im->tm_running, im->timer.expires-jiffies);
67 pos=begin+len;
68 if(pos<offset)
69 {
70 len=0;
71 begin=pos;
72 }
73 if(pos>offset+length)
74 break;
75 }
76 }
77 }
78 restore_flags(flags);
79 *start=buffer+(offset-begin);
80 len-=(offset-begin);
81 if(len>length)
82 len=length;
83 return len;
84 }
85
86
87
88
89
90
91
92
93
94
95
96 static struct device *ip_mc_find_devfor(unsigned long addr)
97 {
98 struct device *dev;
99 for(dev = dev_base; dev; dev = dev->next)
100 {
101 if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST)&&
102 (dev->pa_addr==addr))
103 return dev;
104 }
105
106 return NULL;
107 }
108
109 #endif
110
111 int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
112 {
113 int val,err;
114 unsigned char ucval;
115 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
116 struct ip_fw tmp_fw;
117 #endif
118 if (optval == NULL)
119 {
120 val=0;
121 ucval=0;
122 }
123 else
124 {
125 err=verify_area(VERIFY_READ, optval, sizeof(int));
126 if(err)
127 return err;
128 val = get_user((int *) optval);
129 ucval=get_user((unsigned char *) optval);
130 }
131
132 if(level!=SOL_IP)
133 return -EOPNOTSUPP;
134 #ifdef CONFIG_IP_MROUTE
135 if(optname>=MRT_BASE && optname <=MRT_BASE+10)
136 {
137 return ip_mroute_setsockopt(sk,optname,optval,optlen);
138 }
139 #endif
140
141 switch(optname)
142 {
143 case IP_OPTIONS:
144 {
145 struct options * opt = NULL;
146 struct options * old_opt;
147 if (optlen > 40 || optlen < 0)
148 return -EINVAL;
149 err = verify_area(VERIFY_READ, optval, optlen);
150 if (err)
151 return err;
152 opt = kmalloc(sizeof(struct options)+((optlen+3)&~3), GFP_KERNEL);
153 if (!opt)
154 return -ENOMEM;
155 memset(opt, 0, sizeof(struct options));
156 if (optlen)
157 memcpy_fromfs(opt->__data, optval, optlen);
158 while (optlen & 3)
159 opt->__data[optlen++] = IPOPT_END;
160 opt->optlen = optlen;
161 opt->is_data = 1;
162 opt->is_setbyuser = 1;
163 if (optlen && ip_options_compile(opt, NULL))
164 {
165 kfree_s(opt, sizeof(struct options) + optlen);
166 return -EINVAL;
167 }
168
169
170
171
172 cli();
173 old_opt = sk->opt;
174 sk->opt = opt;
175 sti();
176 if (old_opt)
177 kfree_s(old_opt, sizeof(struct optlen) + old_opt->optlen);
178 return 0;
179 }
180 case IP_TOS:
181 if(val<0||val>255)
182 return -EINVAL;
183 sk->ip_tos=val;
184 if(val==IPTOS_LOWDELAY)
185 sk->priority=SOPRI_INTERACTIVE;
186 if(val==IPTOS_THROUGHPUT)
187 sk->priority=SOPRI_BACKGROUND;
188 return 0;
189 case IP_TTL:
190 if(val<1||val>255)
191 return -EINVAL;
192 sk->ip_ttl=val;
193 return 0;
194 case IP_HDRINCL:
195 if(sk->type!=SOCK_RAW)
196 return -ENOPROTOOPT;
197 sk->ip_hdrincl=val?1:0;
198 return 0;
199 #ifdef CONFIG_IP_MULTICAST
200 case IP_MULTICAST_TTL:
201 {
202 sk->ip_mc_ttl=(int)ucval;
203 return 0;
204 }
205 case IP_MULTICAST_LOOP:
206 {
207 if(ucval!=0 && ucval!=1)
208 return -EINVAL;
209 sk->ip_mc_loop=(int)ucval;
210 return 0;
211 }
212 case IP_MULTICAST_IF:
213 {
214 struct in_addr addr;
215 struct device *dev=NULL;
216
217
218
219
220
221 err=verify_area(VERIFY_READ, optval, sizeof(addr));
222 if(err)
223 return err;
224
225 memcpy_fromfs(&addr,optval,sizeof(addr));
226
227
228
229
230
231
232 if(addr.s_addr==INADDR_ANY)
233 {
234 sk->ip_mc_name[0]=0;
235 return 0;
236 }
237
238
239
240
241
242 dev=ip_mc_find_devfor(addr.s_addr);
243
244
245
246
247
248 if(dev)
249 {
250 strcpy(sk->ip_mc_name,dev->name);
251 return 0;
252 }
253 return -EADDRNOTAVAIL;
254 }
255
256 case IP_ADD_MEMBERSHIP:
257 {
258
259
260
261
262 struct ip_mreq mreq;
263 __u32 route_src;
264 struct rtable *rt;
265 struct device *dev=NULL;
266
267
268
269
270
271 err=verify_area(VERIFY_READ, optval, sizeof(mreq));
272 if(err)
273 return err;
274
275 memcpy_fromfs(&mreq,optval,sizeof(mreq));
276
277
278
279
280
281 if(mreq.imr_interface.s_addr==INADDR_ANY)
282 {
283
284
285
286 if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,0))!=NULL)
287 {
288 dev=rt->rt_dev;
289 route_src = rt->rt_src;
290 ATOMIC_DECR(&rt->rt_use);
291 ip_rt_put(rt);
292 }
293 }
294 else
295 {
296
297
298
299
300 dev=ip_mc_find_devfor(mreq.imr_interface.s_addr);
301 }
302
303
304
305
306
307 if(!dev)
308 return -ENODEV;
309
310
311
312
313
314 return ip_mc_join_group(sk,dev,mreq.imr_multiaddr.s_addr);
315 }
316
317 case IP_DROP_MEMBERSHIP:
318 {
319 struct ip_mreq mreq;
320 struct rtable *rt;
321 __u32 route_src;
322 struct device *dev=NULL;
323
324
325
326
327
328 err=verify_area(VERIFY_READ, optval, sizeof(mreq));
329 if(err)
330 return err;
331
332 memcpy_fromfs(&mreq,optval,sizeof(mreq));
333
334
335
336
337
338 if(mreq.imr_interface.s_addr==INADDR_ANY)
339 {
340 if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,0))!=NULL)
341 {
342 dev=rt->rt_dev;
343 ATOMIC_DECR(&rt->rt_use);
344 route_src = rt->rt_src;
345 ip_rt_put(rt);
346 }
347 }
348 else
349 {
350
351 dev=ip_mc_find_devfor(mreq.imr_interface.s_addr);
352 }
353
354
355
356
357
358 if(!dev)
359 return -ENODEV;
360
361
362
363
364
365 return ip_mc_leave_group(sk,dev,mreq.imr_multiaddr.s_addr);
366 }
367 #endif
368 #ifdef CONFIG_IP_FIREWALL
369 case IP_FW_ADD_BLK:
370 case IP_FW_DEL_BLK:
371 case IP_FW_ADD_FWD:
372 case IP_FW_DEL_FWD:
373 case IP_FW_CHK_BLK:
374 case IP_FW_CHK_FWD:
375 case IP_FW_FLUSH_BLK:
376 case IP_FW_FLUSH_FWD:
377 case IP_FW_ZERO_BLK:
378 case IP_FW_ZERO_FWD:
379 case IP_FW_POLICY_BLK:
380 case IP_FW_POLICY_FWD:
381 if(!suser())
382 return -EPERM;
383 if(optlen>sizeof(tmp_fw) || optlen<1)
384 return -EINVAL;
385 err=verify_area(VERIFY_READ,optval,optlen);
386 if(err)
387 return err;
388 memcpy_fromfs(&tmp_fw,optval,optlen);
389 err=ip_fw_ctl(optname, &tmp_fw,optlen);
390 return -err;
391
392 #endif
393 #ifdef CONFIG_IP_ACCT
394 case IP_ACCT_DEL:
395 case IP_ACCT_ADD:
396 case IP_ACCT_FLUSH:
397 case IP_ACCT_ZERO:
398 if(!suser())
399 return -EPERM;
400 if(optlen>sizeof(tmp_fw) || optlen<1)
401 return -EINVAL;
402 err=verify_area(VERIFY_READ,optval,optlen);
403 if(err)
404 return err;
405 memcpy_fromfs(&tmp_fw, optval,optlen);
406 err=ip_acct_ctl(optname, &tmp_fw,optlen);
407 return -err;
408 #endif
409
410 default:
411 return(-ENOPROTOOPT);
412 }
413 }
414
415
416
417
418
419
420 int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
421 {
422 int val,err;
423 #ifdef CONFIG_IP_MULTICAST
424 int len;
425 #endif
426
427 if(level!=SOL_IP)
428 return -EOPNOTSUPP;
429
430 #ifdef CONFIG_IP_MROUTE
431 if(optname>=MRT_BASE && optname <=MRT_BASE+10)
432 {
433 return ip_mroute_getsockopt(sk,optname,optval,optlen);
434 }
435 #endif
436
437 switch(optname)
438 {
439 case IP_OPTIONS:
440 {
441 unsigned char optbuf[sizeof(struct options)+40];
442 struct options * opt = (struct options*)optbuf;
443 err = verify_area(VERIFY_WRITE, optlen, sizeof(int));
444 if (err)
445 return err;
446 cli();
447 opt->optlen = 0;
448 if (sk->opt)
449 memcpy(optbuf, sk->opt, sizeof(struct options)+sk->opt->optlen);
450 sti();
451 if (opt->optlen == 0)
452 {
453 put_fs_long(0,(unsigned long *) optlen);
454 return 0;
455 }
456 err = verify_area(VERIFY_WRITE, optval, opt->optlen);
457 if (err)
458 return err;
459
460
461
462 if (opt->srr)
463 {
464 unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr);
465 memmove(optptr+7, optptr+4, optptr[1]-7);
466 memcpy(optptr+3, &opt->faddr, 4);
467 }
468 if (opt->rr_needaddr)
469 {
470 unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr);
471 memset(&optptr[optptr[2]-1], 0, 4);
472 optptr[2] -= 4;
473 }
474 if (opt->ts)
475 {
476 unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr);
477 if (opt->ts_needtime)
478 {
479 memset(&optptr[optptr[2]-1], 0, 4);
480 optptr[2] -= 4;
481 }
482 if (opt->ts_needaddr)
483 {
484 memset(&optptr[optptr[2]-1], 0, 4);
485 optptr[2] -= 4;
486 }
487 }
488 put_fs_long(opt->optlen, (unsigned long *) optlen);
489 memcpy_tofs(optval, opt->__data, opt->optlen);
490 }
491 return 0;
492 case IP_TOS:
493 val=sk->ip_tos;
494 break;
495 case IP_TTL:
496 val=sk->ip_ttl;
497 break;
498 case IP_HDRINCL:
499 val=sk->ip_hdrincl;
500 break;
501 #ifdef CONFIG_IP_MULTICAST
502 case IP_MULTICAST_TTL:
503 val=sk->ip_mc_ttl;
504 break;
505 case IP_MULTICAST_LOOP:
506 val=sk->ip_mc_loop;
507 break;
508 case IP_MULTICAST_IF:
509 err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
510 if(err)
511 return err;
512 len=strlen(sk->ip_mc_name);
513 err=verify_area(VERIFY_WRITE, optval, len);
514 if(err)
515 return err;
516 put_user(len,(int *) optlen);
517 memcpy_tofs((void *)optval,sk->ip_mc_name, len);
518 return 0;
519 #endif
520 default:
521 return(-ENOPROTOOPT);
522 }
523 err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
524 if(err)
525 return err;
526 put_user(sizeof(int),(int *) optlen);
527
528 err=verify_area(VERIFY_WRITE, optval, sizeof(int));
529 if(err)
530 return err;
531 put_user(val,(int *) optval);
532
533 return(0);
534 }