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_INSERT_IN:
370 case IP_FW_INSERT_OUT:
371 case IP_FW_INSERT_FWD:
372 case IP_FW_APPEND_IN:
373 case IP_FW_APPEND_OUT:
374 case IP_FW_APPEND_FWD:
375 case IP_FW_DELETE_IN:
376 case IP_FW_DELETE_OUT:
377 case IP_FW_DELETE_FWD:
378 case IP_FW_CHECK_IN:
379 case IP_FW_CHECK_OUT:
380 case IP_FW_CHECK_FWD:
381 case IP_FW_FLUSH_IN:
382 case IP_FW_FLUSH_OUT:
383 case IP_FW_FLUSH_FWD:
384 case IP_FW_ZERO_IN:
385 case IP_FW_ZERO_OUT:
386 case IP_FW_ZERO_FWD:
387 case IP_FW_POLICY_IN:
388 case IP_FW_POLICY_OUT:
389 case IP_FW_POLICY_FWD:
390 case IP_FW_MASQ_TIMEOUTS:
391 if(!suser())
392 return -EPERM;
393 if(optlen>sizeof(tmp_fw) || optlen<1)
394 return -EINVAL;
395 err=verify_area(VERIFY_READ,optval,optlen);
396 if(err)
397 return err;
398 memcpy_fromfs(&tmp_fw,optval,optlen);
399 err=ip_fw_ctl(optname, &tmp_fw,optlen);
400 return -err;
401
402 #endif
403 #ifdef CONFIG_IP_ACCT
404 case IP_ACCT_INSERT:
405 case IP_ACCT_APPEND:
406 case IP_ACCT_DELETE:
407 case IP_ACCT_FLUSH:
408 case IP_ACCT_ZERO:
409 if(!suser())
410 return -EPERM;
411 if(optlen>sizeof(tmp_fw) || optlen<1)
412 return -EINVAL;
413 err=verify_area(VERIFY_READ,optval,optlen);
414 if(err)
415 return err;
416 memcpy_fromfs(&tmp_fw, optval,optlen);
417 err=ip_acct_ctl(optname, &tmp_fw,optlen);
418 return -err;
419 #endif
420
421 default:
422 return(-ENOPROTOOPT);
423 }
424 }
425
426
427
428
429
430
431 int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
432 {
433 int val,err;
434 #ifdef CONFIG_IP_MULTICAST
435 int len;
436 #endif
437
438 if(level!=SOL_IP)
439 return -EOPNOTSUPP;
440
441 #ifdef CONFIG_IP_MROUTE
442 if(optname>=MRT_BASE && optname <=MRT_BASE+10)
443 {
444 return ip_mroute_getsockopt(sk,optname,optval,optlen);
445 }
446 #endif
447
448 switch(optname)
449 {
450 case IP_OPTIONS:
451 {
452 unsigned char optbuf[sizeof(struct options)+40];
453 struct options * opt = (struct options*)optbuf;
454 err = verify_area(VERIFY_WRITE, optlen, sizeof(int));
455 if (err)
456 return err;
457 cli();
458 opt->optlen = 0;
459 if (sk->opt)
460 memcpy(optbuf, sk->opt, sizeof(struct options)+sk->opt->optlen);
461 sti();
462 if (opt->optlen == 0)
463 {
464 put_fs_long(0,(unsigned long *) optlen);
465 return 0;
466 }
467 err = verify_area(VERIFY_WRITE, optval, opt->optlen);
468 if (err)
469 return err;
470
471
472
473 if (opt->srr)
474 {
475 unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr);
476 memmove(optptr+7, optptr+3, optptr[1]-7);
477 memcpy(optptr+3, &opt->faddr, 4);
478 }
479 if (opt->rr_needaddr)
480 {
481 unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr);
482 memset(&optptr[optptr[2]-1], 0, 4);
483 optptr[2] -= 4;
484 }
485 if (opt->ts)
486 {
487 unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr);
488 if (opt->ts_needtime)
489 {
490 memset(&optptr[optptr[2]-1], 0, 4);
491 optptr[2] -= 4;
492 }
493 if (opt->ts_needaddr)
494 {
495 memset(&optptr[optptr[2]-1], 0, 4);
496 optptr[2] -= 4;
497 }
498 }
499 put_fs_long(opt->optlen, (unsigned long *) optlen);
500 memcpy_tofs(optval, opt->__data, opt->optlen);
501 }
502 return 0;
503 case IP_TOS:
504 val=sk->ip_tos;
505 break;
506 case IP_TTL:
507 val=sk->ip_ttl;
508 break;
509 case IP_HDRINCL:
510 val=sk->ip_hdrincl;
511 break;
512 #ifdef CONFIG_IP_MULTICAST
513 case IP_MULTICAST_TTL:
514 val=sk->ip_mc_ttl;
515 break;
516 case IP_MULTICAST_LOOP:
517 val=sk->ip_mc_loop;
518 break;
519 case IP_MULTICAST_IF:
520 err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
521 if(err)
522 return err;
523 len=strlen(sk->ip_mc_name);
524 err=verify_area(VERIFY_WRITE, optval, len);
525 if(err)
526 return err;
527 put_user(len,(int *) optlen);
528 memcpy_tofs((void *)optval,sk->ip_mc_name, len);
529 return 0;
530 #endif
531 default:
532 return(-ENOPROTOOPT);
533 }
534 err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
535 if(err)
536 return err;
537 put_user(sizeof(int),(int *) optlen);
538
539 err=verify_area(VERIFY_WRITE, optval, sizeof(int));
540 if(err)
541 return err;
542 put_user(val,(int *) optval);
543
544 return(0);
545 }