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