This source file includes following definitions.
- vif_delete
- ipmr_vifi_find
- ipmr_cache_delete
- ipmr_cache_timer
- ipmr_cache_insert
- ipmr_cache_find
- ipmr_cache_alloc
- ipmr_cache_resolve
- ipmr_cache_report
- ipmr_cache_unresolved
- ipmr_mfc_modify
- ip_mroute_setsockopt
- ip_mroute_getsockopt
- ipmr_ioctl
- mroute_close
- ipmr_device_event
- ipmr_queue_xmit
- ipmr_forward
- ipmr_vif_info
- ipmr_mfc_info
- ip_mr_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <asm/system.h>
27 #include <asm/segment.h>
28 #include <linux/types.h>
29 #include <linux/sched.h>
30 #include <linux/errno.h>
31 #include <linux/timer.h>
32 #include <linux/mm.h>
33 #include <linux/kernel.h>
34 #include <linux/fcntl.h>
35 #include <linux/stat.h>
36 #include <linux/socket.h>
37 #include <linux/in.h>
38 #include <linux/inet.h>
39 #include <linux/netdevice.h>
40 #include <linux/proc_fs.h>
41 #include <linux/mroute.h>
42 #include <net/ip.h>
43 #include <net/protocol.h>
44 #include <linux/skbuff.h>
45 #include <net/sock.h>
46 #include <net/icmp.h>
47 #include <net/udp.h>
48 #include <linux/notifier.h>
49 #include <net/checksum.h>
50
51
52
53
54
55 static struct vif_device vif_table[MAXVIFS];
56 static unsigned long vifc_map;
57 int mroute_do_pim = 0;
58 static struct mfc_cache *mfc_cache_array[MFC_LINES];
59 static struct mfc_cache *cache_resolve_queue;
60 int cache_resolve_queue_len = 0;
61
62
63
64
65
66 static void vif_delete(struct vif_device *v)
67 {
68 if(!(v->flags&VIFF_TUNNEL))
69 {
70 v->dev->flags&=~IFF_ALLMULTI;
71 dev_mc_upload(v->dev);
72 }
73 v->dev=NULL;
74 }
75
76
77
78
79
80 static int ipmr_vifi_find(struct device *dev)
81 {
82 struct vif_device *v=&vif_table[0];
83 int ct;
84 for(ct=0;ct<MAXVIFS;ct++,v++)
85 {
86 if(v->dev==dev)
87 return ct;
88 }
89 return -1;
90 }
91
92
93
94
95
96 static void ipmr_cache_delete(struct mfc_cache *cache)
97 {
98 struct sk_buff *skb;
99 int line;
100 struct mfc_cache **cp;
101
102
103
104
105
106 if(cache->mfc_flags&MFC_QUEUED)
107 {
108 cp=&cache_resolve_queue;
109 del_timer(&cache->mfc_timer);
110 }
111 else
112 {
113 line=MFC_HASH(cache->mfc_mcastgrp,cache->mfc_origin);
114 cp=&(mfc_cache_array[line]);
115 }
116
117
118
119
120
121 while(*cp!=NULL)
122 {
123 if(*cp==cache)
124 {
125 *cp=cache->next;
126 break;
127 }
128 cp=&((*cp)->next);
129 }
130
131
132
133
134
135
136 if(cache->mfc_flags&MFC_QUEUED)
137 {
138 cache_resolve_queue_len--;
139 while((skb=skb_dequeue(&cache->mfc_unresolved)))
140 kfree_skb(skb, FREE_WRITE);
141 }
142 kfree_s(cache,sizeof(cache));
143 }
144
145
146
147
148
149 static void ipmr_cache_timer(unsigned long data)
150 {
151 struct mfc_cache *cache=(struct mfc_cache *)data;
152 ipmr_cache_delete(cache);
153 }
154
155
156
157
158
159 static void ipmr_cache_insert(struct mfc_cache *c)
160 {
161 int line=MFC_HASH(c->mfc_mcastgrp,c->mfc_origin);
162 c->next=mfc_cache_array[line];
163 mfc_cache_array[line]=c;
164 }
165
166
167
168
169
170 struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
171 {
172 int line=MFC_HASH(mcastgrp,origin);
173 struct mfc_cache *cache;
174 cache=mfc_cache_array[line];
175 while(cache!=NULL)
176 {
177 if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
178 return cache;
179 cache=cache->next;
180 }
181 cache=cache_resolve_queue;
182 while(cache!=NULL)
183 {
184 if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
185 return cache;
186 cache=cache->next;
187 }
188 return NULL;
189 }
190
191
192
193
194
195 static struct mfc_cache *ipmr_cache_alloc(int priority)
196 {
197 struct mfc_cache *c=(struct mfc_cache *)kmalloc(sizeof(struct mfc_cache), priority);
198 if(c==NULL)
199 return NULL;
200 c->mfc_queuelen=0;
201 skb_queue_head_init(&c->mfc_unresolved);
202 init_timer(&c->mfc_timer);
203 c->mfc_timer.data=(long)c;
204 c->mfc_timer.function=ipmr_cache_timer;
205 return c;
206 }
207
208
209
210
211
212 static void ipmr_cache_resolve(struct mfc_cache *cache)
213 {
214 struct mfc_cache **p;
215 struct sk_buff *skb;
216
217
218
219 del_timer(&cache->mfc_timer);
220 cache->mfc_flags&=~MFC_QUEUED;
221
222
223
224 p=&cache_resolve_queue;
225 while((*p)!=NULL)
226 {
227 if((*p)==cache)
228 {
229 *p=cache->next;
230 break;
231 }
232 p=&((*p)->next);
233 }
234 cache_resolve_queue_len--;
235 sti();
236
237
238
239 ipmr_cache_insert(cache);
240
241
242
243 while((skb=skb_dequeue(&cache->mfc_unresolved)))
244 ipmr_forward(skb, skb->protocol);
245 }
246
247
248
249
250
251
252 static void ipmr_cache_report(struct sk_buff *pkt)
253 {
254 struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
255 int ihl=pkt->ip_hdr->ihl<<2;
256 struct igmphdr *igmp;
257 if(!skb)
258 return;
259
260 skb->free=1;
261
262
263
264
265
266 skb->ip_hdr=(struct iphdr *)skb_put(skb,ihl);
267 skb->h.iph=skb->ip_hdr;
268 memcpy(skb->data,pkt->data,ihl);
269 skb->ip_hdr->protocol = 0;
270
271
272
273
274
275 igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
276 igmp->type = IGMPMSG_NOCACHE;
277 igmp->code = 0;
278 skb->ip_hdr->tot_len=htons(skb->len);
279
280
281
282
283 if(sock_queue_rcv_skb(mroute_socket,skb)<0)
284 {
285 skb->sk=NULL;
286 kfree_skb(skb, FREE_READ);
287 }
288 }
289
290
291
292
293
294
295 static void ipmr_cache_unresolved(struct mfc_cache *cache, vifi_t vifi, struct sk_buff *skb, int is_frag)
296 {
297 if(cache==NULL)
298 {
299
300
301
302 if(cache_resolve_queue_len>=10 || (cache=ipmr_cache_alloc(GFP_ATOMIC))==NULL)
303 {
304 kfree_skb(skb, FREE_WRITE);
305 return;
306 }
307
308
309
310 cache->mfc_parent=vifi;
311 cache->mfc_origin=skb->ip_hdr->saddr;
312 cache->mfc_mcastgrp=skb->ip_hdr->daddr;
313 cache->mfc_flags=MFC_QUEUED;
314
315
316
317 cache->next=cache_resolve_queue;
318 cache_resolve_queue=cache;
319 cache_resolve_queue_len++;
320
321
322
323 cache->mfc_timer.expires=jiffies+10*HZ;
324 add_timer(&cache->mfc_timer);
325
326
327
328 if(mroute_socket)
329 ipmr_cache_report(skb);
330 }
331
332
333
334 if(cache->mfc_queuelen>3)
335 {
336 kfree_skb(skb, FREE_WRITE);
337 return;
338 }
339
340
341
342
343 cache->mfc_queuelen++;
344 skb->protocol=is_frag;
345 skb_queue_tail(&cache->mfc_unresolved,skb);
346 }
347
348
349
350
351
352 int ipmr_mfc_modify(int action, struct mfcctl *mfc)
353 {
354 struct mfc_cache *cache;
355 if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr))
356 return -EINVAL;
357
358
359
360
361 cli();
362 cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
363
364
365
366
367 if(action==MRT_DEL_MFC)
368 {
369 if(cache)
370 {
371 ipmr_cache_delete(cache);
372 sti();
373 return 0;
374 }
375 sti();
376 return -ENOENT;
377 }
378 if(cache)
379 {
380
381
382
383
384 cache->mfc_flags|=MFC_RESOLVED;
385 memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
386
387
388
389
390
391
392 if(cache->mfc_flags&MFC_QUEUED)
393 ipmr_cache_resolve(cache);
394 sti();
395 return 0;
396 }
397
398
399
400
401
402 cache=ipmr_cache_alloc(GFP_ATOMIC);
403 if(cache==NULL)
404 {
405 sti();
406 return -ENOMEM;
407 }
408 cache->mfc_flags=MFC_RESOLVED;
409 cache->mfc_origin=mfc->mfcc_origin.s_addr;
410 cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
411 cache->mfc_parent=mfc->mfcc_parent;
412 memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
413 ipmr_cache_insert(cache);
414 sti();
415 return 0;
416 }
417
418
419
420
421
422
423
424
425 int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
426 {
427 int err;
428 struct vifctl vif;
429 struct mfcctl mfc;
430
431 if(optname!=MRT_INIT)
432 {
433 if(sk!=mroute_socket)
434 return -EACCES;
435 }
436
437 switch(optname)
438 {
439 case MRT_INIT:
440 if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
441 return -EOPNOTSUPP;
442 if(optlen!=sizeof(int))
443 return -ENOPROTOOPT;
444 if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
445 return err;
446 if(get_user((int *)optval)!=1)
447 return -ENOPROTOOPT;
448 if(mroute_socket)
449 return -EADDRINUSE;
450 mroute_socket=sk;
451
452 return 0;
453 case MRT_DONE:
454 mroute_close(sk);
455 mroute_socket=NULL;
456 return 0;
457 case MRT_ADD_VIF:
458 case MRT_DEL_VIF:
459 if(optlen!=sizeof(vif))
460 return -EINVAL;
461 if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
462 return err;
463 memcpy_fromfs(&vif,optval,sizeof(vif));
464 if(vif.vifc_vifi > MAXVIFS)
465 return -ENFILE;
466 if(optname==MRT_ADD_VIF)
467 {
468 struct vif_device *v=&vif_table[vif.vifc_vifi];
469 struct device *dev;
470
471 if(vifc_map&(1<<vif.vifc_vifi))
472 return -EADDRINUSE;
473
474 dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
475 if(!dev)
476 return -EADDRNOTAVAIL;
477
478 if(vif.vifc_flags&VIFF_TUNNEL)
479 {
480 if(vif.vifc_flags&VIFF_SRCRT)
481 return -EOPNOTSUPP;
482
483 }
484 else
485 {
486 if(dev->flags&IFF_MULTICAST)
487 {
488
489
490 dev->flags|=IFF_ALLMULTI;
491 dev_mc_upload(dev);
492 }
493 else
494 {
495
496 return -EOPNOTSUPP;
497 }
498 }
499
500
501
502 cli();
503 v->rate_limit=vif.vifc_rate_limit;
504 v->local=vif.vifc_lcl_addr.s_addr;
505 v->remote=vif.vifc_rmt_addr.s_addr;
506 v->flags=vif.vifc_flags;
507 v->threshold=vif.vifc_threshold;
508 v->dev=dev;
509 v->bytes_in = 0;
510 v->bytes_out = 0;
511 v->pkt_in = 0;
512 v->pkt_out = 0;
513 vifc_map|=(1<<vif.vifc_vifi);
514 sti();
515 return 0;
516 }
517 else
518
519
520
521 {
522 struct vif_device *v=&vif_table[vif.vifc_vifi];
523 if(vifc_map&(1<<vif.vifc_vifi))
524 {
525 vif_delete(v);
526 vifc_map&=~(1<<vif.vifc_vifi);
527 return 0;
528 }
529 else
530 return -EADDRNOTAVAIL;
531 }
532
533
534
535
536 case MRT_ADD_MFC:
537 case MRT_DEL_MFC:
538 err=verify_area(VERIFY_READ, optval, sizeof(mfc));
539 if(err)
540 return err;
541 memcpy_fromfs(&mfc,optval, sizeof(mfc));
542 return ipmr_mfc_modify(optname, &mfc);
543
544
545
546 case MRT_ASSERT:
547 if(optlen!=sizeof(int))
548 return -EINVAL;
549 if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
550 return err;
551 mroute_do_pim= (optval)?1:0;
552 return 0;
553
554
555
556
557 default:
558 return -EOPNOTSUPP;
559 }
560 }
561
562
563
564
565
566 int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
567 {
568 int olr;
569 int err;
570
571 if(sk!=mroute_socket)
572 return -EACCES;
573 if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
574 return -EOPNOTSUPP;
575
576 olr=get_user(optlen);
577 if(olr!=sizeof(int))
578 return -EINVAL;
579 err=verify_area(VERIFY_WRITE, optval,sizeof(int));
580 if(err)
581 return err;
582 put_user(sizeof(int),optlen);
583 if(optname==MRT_VERSION)
584 put_user(0x0305,(int *)optval);
585 else
586 put_user(mroute_do_pim,(int *)optval);
587 return 0;
588 }
589
590
591
592
593
594 int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
595 {
596 int err;
597 struct sioc_sg_req sr;
598 struct sioc_vif_req vr;
599 struct vif_device *vif;
600
601 switch(cmd)
602 {
603 case SIOCGETVIFCNT:
604 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
605 if(err)
606 return err;
607 memcpy_fromfs(&vr,(void *)arg,sizeof(vr));
608 if(vr.vifi>=MAXVIFS)
609 return -EINVAL;
610 vif=&vif_table[vr.vifi];
611 if(vifc_map&(1<<vr.vifi))
612 {
613 vr.icount=vif->pkt_in;
614 vr.ocount=vif->pkt_out;
615 vr.ibytes=vif->bytes_in;
616 vr.obytes=vif->bytes_out;
617 memcpy_tofs((void *)arg,&vr,sizeof(vr));
618 return 0;
619 }
620 return -EADDRNOTAVAIL;
621 case SIOCGETSGCNT:
622 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
623 if(err)
624 return err;
625 memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
626 memcpy_tofs((void *)arg,&sr,sizeof(sr));
627 return 0;
628 default:
629 return -EINVAL;
630 }
631 }
632
633
634
635
636
637 void mroute_close(struct sock *sk)
638 {
639 int i;
640 struct vif_device *v=&vif_table[0];
641
642
643
644
645
646 for(i=0;i<MAXVIFS;i++)
647 {
648 if(vifc_map&(1<<i))
649 {
650 if(!(v->flags&VIFF_TUNNEL))
651 {
652 v->dev->flags&=~IFF_ALLMULTI;
653 dev_mc_upload(v->dev);
654 }
655 }
656 v++;
657 }
658 vifc_map=0;
659
660
661
662 for(i=0;i<MFC_LINES;i++)
663 {
664 while(mfc_cache_array[i]!=NULL)
665 ipmr_cache_delete(mfc_cache_array[i]);
666 }
667
668 }
669
670 static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
671 {
672 struct vif_device *v;
673 int ct;
674 if(event!=NETDEV_DOWN)
675 return NOTIFY_DONE;
676 v=&vif_table[0];
677 for(ct=0;ct<MAXVIFS;ct++)
678 {
679 if((vifc_map&(1<<ct)) && v->dev==ptr)
680 {
681 vif_delete(v);
682 vifc_map&=~(1<<ct);
683 }
684 v++;
685 }
686 return NOTIFY_DONE;
687 }
688
689
690 static struct notifier_block ip_mr_notifier={
691 ipmr_device_event,
692 NULL,
693 0
694 };
695
696
697
698
699
700 static void ipmr_queue_xmit(struct sk_buff *skb, struct vif_device *vif, struct device *in_dev, int frag)
701 {
702 int tunnel=0;
703 __u32 raddr=skb->raddr;
704 if(vif->flags&VIFF_TUNNEL)
705 {
706 tunnel=16;
707 raddr=vif->remote;
708 }
709 vif->pkt_out++;
710 vif->bytes_out+=skb->len;
711 skb->dev=vif->dev;
712 skb->raddr=skb->h.iph->daddr;
713 if(ip_forward(skb, in_dev, frag|8|tunnel, raddr)==-1)
714 kfree_skb(skb, FREE_WRITE);
715 }
716
717
718
719
720
721 void ipmr_forward(struct sk_buff *skb, int is_frag)
722 {
723 struct mfc_cache *cache;
724 struct sk_buff *skb2;
725 int psend = -1;
726 int vif=ipmr_vifi_find(skb->dev);
727 if(vif==-1)
728 {
729 kfree_skb(skb, FREE_WRITE);
730 return;
731 }
732
733 vif_table[vif].pkt_in++;
734 vif_table[vif].bytes_in+=skb->len;
735
736 cache=ipmr_cache_find(skb->ip_hdr->saddr,skb->ip_hdr->daddr);
737
738
739
740
741
742 if(cache==NULL || (cache->mfc_flags&MFC_QUEUED))
743 ipmr_cache_unresolved(cache,vif,skb, is_frag);
744 else
745 {
746
747
748
749 int ct=0;
750 while(ct<MAXVIFS)
751 {
752
753
754
755 if(skb->ip_hdr->ttl > cache->mfc_ttls[ct] && cache->mfc_ttls[ct]>0)
756 {
757 if(psend!=-1)
758 {
759 skb2=skb_clone(skb, GFP_ATOMIC);
760 if(skb2)
761 {
762 skb2->free=1;
763 ipmr_queue_xmit(skb2, &vif_table[psend], skb->dev, is_frag);
764 }
765 }
766 psend=ct;
767 }
768 ct++;
769 }
770 if(psend==-1)
771 kfree_skb(skb, FREE_WRITE);
772 else
773 {
774 ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
775 }
776
777
778
779 }
780 }
781
782
783
784
785
786 int ipmr_vif_info(char *buffer, char **start, off_t offset, int length, int dummy)
787 {
788 struct vif_device *vif;
789 int len=0;
790 off_t pos=0;
791 off_t begin=0;
792 int size;
793 int ct;
794
795 len += sprintf(buffer,
796 "Interface Bytes In Pkts In Bytes Out Pkts Out Flags Local Remote\n");
797 pos=len;
798
799 for (ct=0;ct<MAXVIFS;ct++)
800 {
801 vif=&vif_table[ct];
802 if(!(vifc_map&(1<<ct)))
803 continue;
804 if(vif->dev==NULL)
805 continue;
806 size = sprintf(buffer+len, "%-10s %8ld %7ld %8ld %7ld %05X %08lX %08lX\n",
807 vif->dev->name,vif->bytes_in, vif->pkt_in, vif->bytes_out,vif->pkt_out,
808 vif->flags, vif->local, vif->remote);
809 len+=size;
810 pos+=size;
811 if(pos<offset)
812 {
813 len=0;
814 begin=pos;
815 }
816 if(pos>offset+length)
817 break;
818 }
819
820 *start=buffer+(offset-begin);
821 len-=(offset-begin);
822 if(len>length)
823 len=length;
824 return len;
825 }
826
827 int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length, int dummy)
828 {
829 struct mfc_cache *mfc;
830 int len=0;
831 off_t pos=0;
832 off_t begin=0;
833 int size;
834 int ct;
835
836 len += sprintf(buffer,
837 "Group Origin SrcIface \n");
838 pos=len;
839
840 for (ct=0;ct<MFC_LINES;ct++)
841 {
842 cli();
843 mfc=mfc_cache_array[ct];
844 while(mfc!=NULL)
845 {
846 char *name="none";
847 char vifmap[MAXVIFS+1];
848 int n;
849
850
851
852 if(vifc_map&(1<<mfc->mfc_parent))
853 name=vif_table[mfc->mfc_parent].dev->name;
854
855
856
857 for(n=0;n<MAXVIFS;n++)
858 if(vifc_map&(1<<n) && mfc->mfc_ttls[ct])
859 vifmap[n]='X';
860 else
861 vifmap[n]='-';
862 vifmap[n]=0;
863
864
865
866 size = sprintf(buffer+len, "%08lX %08lX %-8s %s\n",
867 (unsigned long)mfc->mfc_mcastgrp,
868 (unsigned long)mfc->mfc_origin,
869 name,
870 vifmap);
871 len+=size;
872 pos+=size;
873 if(pos<offset)
874 {
875 len=0;
876 begin=pos;
877 }
878 if(pos>offset+length)
879 {
880 sti();
881 goto done;
882 }
883 mfc=mfc->next;
884 }
885 sti();
886 }
887 done:
888 *start=buffer+(offset-begin);
889 len-=(offset-begin);
890 if(len>length)
891 len=length;
892 return len;
893 }
894
895
896
897
898
899 void ip_mr_init(void)
900 {
901 printk("Linux IP multicast router 0.04-might-work 8)\n");
902 register_netdevice_notifier(&ip_mr_notifier);
903 proc_net_register(&(struct proc_dir_entry) {
904 PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
905 S_IFREG | S_IRUGO, 1, 0, 0,
906 0, &proc_net_inode_operations,
907 ipmr_vif_info
908 });
909 proc_net_register(&(struct proc_dir_entry) {
910 PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
911 S_IFREG | S_IRUGO, 1, 0, 0,
912 0, &proc_net_inode_operations,
913 ipmr_mfc_info
914 });
915 }