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