diff options
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 280 |
1 files changed, 137 insertions, 143 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 25924b1eb2ef..14666449dc1c 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -124,8 +124,8 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | |||
124 | 124 | ||
125 | dev = __dev_get_by_name(&init_net, "tunl0"); | 125 | dev = __dev_get_by_name(&init_net, "tunl0"); |
126 | if (dev) { | 126 | if (dev) { |
127 | const struct net_device_ops *ops = dev->netdev_ops; | ||
127 | struct ifreq ifr; | 128 | struct ifreq ifr; |
128 | mm_segment_t oldfs; | ||
129 | struct ip_tunnel_parm p; | 129 | struct ip_tunnel_parm p; |
130 | 130 | ||
131 | memset(&p, 0, sizeof(p)); | 131 | memset(&p, 0, sizeof(p)); |
@@ -137,9 +137,13 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | |||
137 | sprintf(p.name, "dvmrp%d", v->vifc_vifi); | 137 | sprintf(p.name, "dvmrp%d", v->vifc_vifi); |
138 | ifr.ifr_ifru.ifru_data = (__force void __user *)&p; | 138 | ifr.ifr_ifru.ifru_data = (__force void __user *)&p; |
139 | 139 | ||
140 | oldfs = get_fs(); set_fs(KERNEL_DS); | 140 | if (ops->ndo_do_ioctl) { |
141 | dev->do_ioctl(dev, &ifr, SIOCDELTUNNEL); | 141 | mm_segment_t oldfs = get_fs(); |
142 | set_fs(oldfs); | 142 | |
143 | set_fs(KERNEL_DS); | ||
144 | ops->ndo_do_ioctl(dev, &ifr, SIOCDELTUNNEL); | ||
145 | set_fs(oldfs); | ||
146 | } | ||
143 | } | 147 | } |
144 | } | 148 | } |
145 | 149 | ||
@@ -151,9 +155,9 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) | |||
151 | dev = __dev_get_by_name(&init_net, "tunl0"); | 155 | dev = __dev_get_by_name(&init_net, "tunl0"); |
152 | 156 | ||
153 | if (dev) { | 157 | if (dev) { |
158 | const struct net_device_ops *ops = dev->netdev_ops; | ||
154 | int err; | 159 | int err; |
155 | struct ifreq ifr; | 160 | struct ifreq ifr; |
156 | mm_segment_t oldfs; | ||
157 | struct ip_tunnel_parm p; | 161 | struct ip_tunnel_parm p; |
158 | struct in_device *in_dev; | 162 | struct in_device *in_dev; |
159 | 163 | ||
@@ -166,9 +170,14 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) | |||
166 | sprintf(p.name, "dvmrp%d", v->vifc_vifi); | 170 | sprintf(p.name, "dvmrp%d", v->vifc_vifi); |
167 | ifr.ifr_ifru.ifru_data = (__force void __user *)&p; | 171 | ifr.ifr_ifru.ifru_data = (__force void __user *)&p; |
168 | 172 | ||
169 | oldfs = get_fs(); set_fs(KERNEL_DS); | 173 | if (ops->ndo_do_ioctl) { |
170 | err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL); | 174 | mm_segment_t oldfs = get_fs(); |
171 | set_fs(oldfs); | 175 | |
176 | set_fs(KERNEL_DS); | ||
177 | err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL); | ||
178 | set_fs(oldfs); | ||
179 | } else | ||
180 | err = -EOPNOTSUPP; | ||
172 | 181 | ||
173 | dev = NULL; | 182 | dev = NULL; |
174 | 183 | ||
@@ -213,12 +222,16 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | |||
213 | return 0; | 222 | return 0; |
214 | } | 223 | } |
215 | 224 | ||
225 | static const struct net_device_ops reg_vif_netdev_ops = { | ||
226 | .ndo_start_xmit = reg_vif_xmit, | ||
227 | }; | ||
228 | |||
216 | static void reg_vif_setup(struct net_device *dev) | 229 | static void reg_vif_setup(struct net_device *dev) |
217 | { | 230 | { |
218 | dev->type = ARPHRD_PIMREG; | 231 | dev->type = ARPHRD_PIMREG; |
219 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; | 232 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; |
220 | dev->flags = IFF_NOARP; | 233 | dev->flags = IFF_NOARP; |
221 | dev->hard_start_xmit = reg_vif_xmit; | 234 | dev->netdev_ops = ®_vif_netdev_ops, |
222 | dev->destructor = free_netdev; | 235 | dev->destructor = free_netdev; |
223 | } | 236 | } |
224 | 237 | ||
@@ -331,7 +344,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) | |||
331 | 344 | ||
332 | atomic_dec(&cache_resolve_queue_len); | 345 | atomic_dec(&cache_resolve_queue_len); |
333 | 346 | ||
334 | while ((skb=skb_dequeue(&c->mfc_un.unres.unresolved))) { | 347 | while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { |
335 | if (ip_hdr(skb)->version == 0) { | 348 | if (ip_hdr(skb)->version == 0) { |
336 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 349 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
337 | nlh->nlmsg_type = NLMSG_ERROR; | 350 | nlh->nlmsg_type = NLMSG_ERROR; |
@@ -477,13 +490,13 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
477 | /* | 490 | /* |
478 | * Fill in the VIF structures | 491 | * Fill in the VIF structures |
479 | */ | 492 | */ |
480 | v->rate_limit=vifc->vifc_rate_limit; | 493 | v->rate_limit = vifc->vifc_rate_limit; |
481 | v->local=vifc->vifc_lcl_addr.s_addr; | 494 | v->local = vifc->vifc_lcl_addr.s_addr; |
482 | v->remote=vifc->vifc_rmt_addr.s_addr; | 495 | v->remote = vifc->vifc_rmt_addr.s_addr; |
483 | v->flags=vifc->vifc_flags; | 496 | v->flags = vifc->vifc_flags; |
484 | if (!mrtsock) | 497 | if (!mrtsock) |
485 | v->flags |= VIFF_STATIC; | 498 | v->flags |= VIFF_STATIC; |
486 | v->threshold=vifc->vifc_threshold; | 499 | v->threshold = vifc->vifc_threshold; |
487 | v->bytes_in = 0; | 500 | v->bytes_in = 0; |
488 | v->bytes_out = 0; | 501 | v->bytes_out = 0; |
489 | v->pkt_in = 0; | 502 | v->pkt_in = 0; |
@@ -494,7 +507,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
494 | 507 | ||
495 | /* And finish update writing critical data */ | 508 | /* And finish update writing critical data */ |
496 | write_lock_bh(&mrt_lock); | 509 | write_lock_bh(&mrt_lock); |
497 | v->dev=dev; | 510 | v->dev = dev; |
498 | #ifdef CONFIG_IP_PIMSM | 511 | #ifdef CONFIG_IP_PIMSM |
499 | if (v->flags&VIFF_REGISTER) | 512 | if (v->flags&VIFF_REGISTER) |
500 | reg_vif_num = vifi; | 513 | reg_vif_num = vifi; |
@@ -507,7 +520,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
507 | 520 | ||
508 | static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) | 521 | static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) |
509 | { | 522 | { |
510 | int line=MFC_HASH(mcastgrp,origin); | 523 | int line = MFC_HASH(mcastgrp, origin); |
511 | struct mfc_cache *c; | 524 | struct mfc_cache *c; |
512 | 525 | ||
513 | for (c=mfc_cache_array[line]; c; c = c->next) { | 526 | for (c=mfc_cache_array[line]; c; c = c->next) { |
@@ -522,8 +535,8 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) | |||
522 | */ | 535 | */ |
523 | static struct mfc_cache *ipmr_cache_alloc(void) | 536 | static struct mfc_cache *ipmr_cache_alloc(void) |
524 | { | 537 | { |
525 | struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 538 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
526 | if (c==NULL) | 539 | if (c == NULL) |
527 | return NULL; | 540 | return NULL; |
528 | c->mfc_un.res.minvif = MAXVIFS; | 541 | c->mfc_un.res.minvif = MAXVIFS; |
529 | return c; | 542 | return c; |
@@ -531,8 +544,8 @@ static struct mfc_cache *ipmr_cache_alloc(void) | |||
531 | 544 | ||
532 | static struct mfc_cache *ipmr_cache_alloc_unres(void) | 545 | static struct mfc_cache *ipmr_cache_alloc_unres(void) |
533 | { | 546 | { |
534 | struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); | 547 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); |
535 | if (c==NULL) | 548 | if (c == NULL) |
536 | return NULL; | 549 | return NULL; |
537 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | 550 | skb_queue_head_init(&c->mfc_un.unres.unresolved); |
538 | c->mfc_un.unres.expires = jiffies + 10*HZ; | 551 | c->mfc_un.unres.expires = jiffies + 10*HZ; |
@@ -552,7 +565,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
552 | * Play the pending entries through our router | 565 | * Play the pending entries through our router |
553 | */ | 566 | */ |
554 | 567 | ||
555 | while ((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) { | 568 | while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { |
556 | if (ip_hdr(skb)->version == 0) { | 569 | if (ip_hdr(skb)->version == 0) { |
557 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 570 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
558 | 571 | ||
@@ -637,7 +650,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
637 | * Add our header | 650 | * Add our header |
638 | */ | 651 | */ |
639 | 652 | ||
640 | igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr)); | 653 | igmp=(struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); |
641 | igmp->type = | 654 | igmp->type = |
642 | msg->im_msgtype = assert; | 655 | msg->im_msgtype = assert; |
643 | igmp->code = 0; | 656 | igmp->code = 0; |
@@ -653,7 +666,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
653 | /* | 666 | /* |
654 | * Deliver to mrouted | 667 | * Deliver to mrouted |
655 | */ | 668 | */ |
656 | if ((ret=sock_queue_rcv_skb(mroute_socket,skb))<0) { | 669 | if ((ret = sock_queue_rcv_skb(mroute_socket, skb))<0) { |
657 | if (net_ratelimit()) | 670 | if (net_ratelimit()) |
658 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); | 671 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); |
659 | kfree_skb(skb); | 672 | kfree_skb(skb); |
@@ -685,7 +698,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
685 | * Create a new entry if allowable | 698 | * Create a new entry if allowable |
686 | */ | 699 | */ |
687 | 700 | ||
688 | if (atomic_read(&cache_resolve_queue_len)>=10 || | 701 | if (atomic_read(&cache_resolve_queue_len) >= 10 || |
689 | (c=ipmr_cache_alloc_unres())==NULL) { | 702 | (c=ipmr_cache_alloc_unres())==NULL) { |
690 | spin_unlock_bh(&mfc_unres_lock); | 703 | spin_unlock_bh(&mfc_unres_lock); |
691 | 704 | ||
@@ -728,7 +741,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
728 | kfree_skb(skb); | 741 | kfree_skb(skb); |
729 | err = -ENOBUFS; | 742 | err = -ENOBUFS; |
730 | } else { | 743 | } else { |
731 | skb_queue_tail(&c->mfc_un.unres.unresolved,skb); | 744 | skb_queue_tail(&c->mfc_un.unres.unresolved, skb); |
732 | err = 0; | 745 | err = 0; |
733 | } | 746 | } |
734 | 747 | ||
@@ -745,7 +758,7 @@ static int ipmr_mfc_delete(struct mfcctl *mfc) | |||
745 | int line; | 758 | int line; |
746 | struct mfc_cache *c, **cp; | 759 | struct mfc_cache *c, **cp; |
747 | 760 | ||
748 | line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 761 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
749 | 762 | ||
750 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { | 763 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { |
751 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 764 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
@@ -766,7 +779,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
766 | int line; | 779 | int line; |
767 | struct mfc_cache *uc, *c, **cp; | 780 | struct mfc_cache *uc, *c, **cp; |
768 | 781 | ||
769 | line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 782 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
770 | 783 | ||
771 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { | 784 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { |
772 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 785 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
@@ -787,13 +800,13 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
787 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) | 800 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) |
788 | return -EINVAL; | 801 | return -EINVAL; |
789 | 802 | ||
790 | c=ipmr_cache_alloc(); | 803 | c = ipmr_cache_alloc(); |
791 | if (c==NULL) | 804 | if (c == NULL) |
792 | return -ENOMEM; | 805 | return -ENOMEM; |
793 | 806 | ||
794 | c->mfc_origin=mfc->mfcc_origin.s_addr; | 807 | c->mfc_origin = mfc->mfcc_origin.s_addr; |
795 | c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr; | 808 | c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr; |
796 | c->mfc_parent=mfc->mfcc_parent; | 809 | c->mfc_parent = mfc->mfcc_parent; |
797 | ipmr_update_thresholds(c, mfc->mfcc_ttls); | 810 | ipmr_update_thresholds(c, mfc->mfcc_ttls); |
798 | if (!mrtsock) | 811 | if (!mrtsock) |
799 | c->mfc_flags |= MFC_STATIC; | 812 | c->mfc_flags |= MFC_STATIC; |
@@ -846,7 +859,7 @@ static void mroute_clean_tables(struct sock *sk) | |||
846 | /* | 859 | /* |
847 | * Wipe the cache | 860 | * Wipe the cache |
848 | */ | 861 | */ |
849 | for (i=0;i<MFC_LINES;i++) { | 862 | for (i=0; i<MFC_LINES; i++) { |
850 | struct mfc_cache *c, **cp; | 863 | struct mfc_cache *c, **cp; |
851 | 864 | ||
852 | cp = &mfc_cache_array[i]; | 865 | cp = &mfc_cache_array[i]; |
@@ -887,7 +900,7 @@ static void mrtsock_destruct(struct sock *sk) | |||
887 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--; | 900 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--; |
888 | 901 | ||
889 | write_lock_bh(&mrt_lock); | 902 | write_lock_bh(&mrt_lock); |
890 | mroute_socket=NULL; | 903 | mroute_socket = NULL; |
891 | write_unlock_bh(&mrt_lock); | 904 | write_unlock_bh(&mrt_lock); |
892 | 905 | ||
893 | mroute_clean_tables(sk); | 906 | mroute_clean_tables(sk); |
@@ -902,7 +915,7 @@ static void mrtsock_destruct(struct sock *sk) | |||
902 | * MOSPF/PIM router set up we can clean this up. | 915 | * MOSPF/PIM router set up we can clean this up. |
903 | */ | 916 | */ |
904 | 917 | ||
905 | int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int optlen) | 918 | int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen) |
906 | { | 919 | { |
907 | int ret; | 920 | int ret; |
908 | struct vifctl vif; | 921 | struct vifctl vif; |
@@ -918,7 +931,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
918 | if (sk->sk_type != SOCK_RAW || | 931 | if (sk->sk_type != SOCK_RAW || |
919 | inet_sk(sk)->num != IPPROTO_IGMP) | 932 | inet_sk(sk)->num != IPPROTO_IGMP) |
920 | return -EOPNOTSUPP; | 933 | return -EOPNOTSUPP; |
921 | if (optlen!=sizeof(int)) | 934 | if (optlen != sizeof(int)) |
922 | return -ENOPROTOOPT; | 935 | return -ENOPROTOOPT; |
923 | 936 | ||
924 | rtnl_lock(); | 937 | rtnl_lock(); |
@@ -930,7 +943,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
930 | ret = ip_ra_control(sk, 1, mrtsock_destruct); | 943 | ret = ip_ra_control(sk, 1, mrtsock_destruct); |
931 | if (ret == 0) { | 944 | if (ret == 0) { |
932 | write_lock_bh(&mrt_lock); | 945 | write_lock_bh(&mrt_lock); |
933 | mroute_socket=sk; | 946 | mroute_socket = sk; |
934 | write_unlock_bh(&mrt_lock); | 947 | write_unlock_bh(&mrt_lock); |
935 | 948 | ||
936 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++; | 949 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++; |
@@ -938,19 +951,19 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
938 | rtnl_unlock(); | 951 | rtnl_unlock(); |
939 | return ret; | 952 | return ret; |
940 | case MRT_DONE: | 953 | case MRT_DONE: |
941 | if (sk!=mroute_socket) | 954 | if (sk != mroute_socket) |
942 | return -EACCES; | 955 | return -EACCES; |
943 | return ip_ra_control(sk, 0, NULL); | 956 | return ip_ra_control(sk, 0, NULL); |
944 | case MRT_ADD_VIF: | 957 | case MRT_ADD_VIF: |
945 | case MRT_DEL_VIF: | 958 | case MRT_DEL_VIF: |
946 | if (optlen!=sizeof(vif)) | 959 | if (optlen != sizeof(vif)) |
947 | return -EINVAL; | 960 | return -EINVAL; |
948 | if (copy_from_user(&vif,optval,sizeof(vif))) | 961 | if (copy_from_user(&vif, optval, sizeof(vif))) |
949 | return -EFAULT; | 962 | return -EFAULT; |
950 | if (vif.vifc_vifi >= MAXVIFS) | 963 | if (vif.vifc_vifi >= MAXVIFS) |
951 | return -ENFILE; | 964 | return -ENFILE; |
952 | rtnl_lock(); | 965 | rtnl_lock(); |
953 | if (optname==MRT_ADD_VIF) { | 966 | if (optname == MRT_ADD_VIF) { |
954 | ret = vif_add(&vif, sk==mroute_socket); | 967 | ret = vif_add(&vif, sk==mroute_socket); |
955 | } else { | 968 | } else { |
956 | ret = vif_delete(vif.vifc_vifi, 0); | 969 | ret = vif_delete(vif.vifc_vifi, 0); |
@@ -964,12 +977,12 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
964 | */ | 977 | */ |
965 | case MRT_ADD_MFC: | 978 | case MRT_ADD_MFC: |
966 | case MRT_DEL_MFC: | 979 | case MRT_DEL_MFC: |
967 | if (optlen!=sizeof(mfc)) | 980 | if (optlen != sizeof(mfc)) |
968 | return -EINVAL; | 981 | return -EINVAL; |
969 | if (copy_from_user(&mfc,optval, sizeof(mfc))) | 982 | if (copy_from_user(&mfc, optval, sizeof(mfc))) |
970 | return -EFAULT; | 983 | return -EFAULT; |
971 | rtnl_lock(); | 984 | rtnl_lock(); |
972 | if (optname==MRT_DEL_MFC) | 985 | if (optname == MRT_DEL_MFC) |
973 | ret = ipmr_mfc_delete(&mfc); | 986 | ret = ipmr_mfc_delete(&mfc); |
974 | else | 987 | else |
975 | ret = ipmr_mfc_add(&mfc, sk==mroute_socket); | 988 | ret = ipmr_mfc_add(&mfc, sk==mroute_socket); |
@@ -1028,12 +1041,12 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
1028 | * Getsock opt support for the multicast routing system. | 1041 | * Getsock opt support for the multicast routing system. |
1029 | */ | 1042 | */ |
1030 | 1043 | ||
1031 | int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __user *optlen) | 1044 | int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen) |
1032 | { | 1045 | { |
1033 | int olr; | 1046 | int olr; |
1034 | int val; | 1047 | int val; |
1035 | 1048 | ||
1036 | if (optname!=MRT_VERSION && | 1049 | if (optname != MRT_VERSION && |
1037 | #ifdef CONFIG_IP_PIMSM | 1050 | #ifdef CONFIG_IP_PIMSM |
1038 | optname!=MRT_PIM && | 1051 | optname!=MRT_PIM && |
1039 | #endif | 1052 | #endif |
@@ -1047,17 +1060,17 @@ int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __u | |||
1047 | if (olr < 0) | 1060 | if (olr < 0) |
1048 | return -EINVAL; | 1061 | return -EINVAL; |
1049 | 1062 | ||
1050 | if (put_user(olr,optlen)) | 1063 | if (put_user(olr, optlen)) |
1051 | return -EFAULT; | 1064 | return -EFAULT; |
1052 | if (optname==MRT_VERSION) | 1065 | if (optname == MRT_VERSION) |
1053 | val=0x0305; | 1066 | val = 0x0305; |
1054 | #ifdef CONFIG_IP_PIMSM | 1067 | #ifdef CONFIG_IP_PIMSM |
1055 | else if (optname==MRT_PIM) | 1068 | else if (optname == MRT_PIM) |
1056 | val=mroute_do_pim; | 1069 | val = mroute_do_pim; |
1057 | #endif | 1070 | #endif |
1058 | else | 1071 | else |
1059 | val=mroute_do_assert; | 1072 | val = mroute_do_assert; |
1060 | if (copy_to_user(optval,&val,olr)) | 1073 | if (copy_to_user(optval, &val, olr)) |
1061 | return -EFAULT; | 1074 | return -EFAULT; |
1062 | return 0; | 1075 | return 0; |
1063 | } | 1076 | } |
@@ -1075,27 +1088,27 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1075 | 1088 | ||
1076 | switch (cmd) { | 1089 | switch (cmd) { |
1077 | case SIOCGETVIFCNT: | 1090 | case SIOCGETVIFCNT: |
1078 | if (copy_from_user(&vr,arg,sizeof(vr))) | 1091 | if (copy_from_user(&vr, arg, sizeof(vr))) |
1079 | return -EFAULT; | 1092 | return -EFAULT; |
1080 | if (vr.vifi>=maxvif) | 1093 | if (vr.vifi >= maxvif) |
1081 | return -EINVAL; | 1094 | return -EINVAL; |
1082 | read_lock(&mrt_lock); | 1095 | read_lock(&mrt_lock); |
1083 | vif=&vif_table[vr.vifi]; | 1096 | vif=&vif_table[vr.vifi]; |
1084 | if (VIF_EXISTS(vr.vifi)) { | 1097 | if (VIF_EXISTS(vr.vifi)) { |
1085 | vr.icount=vif->pkt_in; | 1098 | vr.icount = vif->pkt_in; |
1086 | vr.ocount=vif->pkt_out; | 1099 | vr.ocount = vif->pkt_out; |
1087 | vr.ibytes=vif->bytes_in; | 1100 | vr.ibytes = vif->bytes_in; |
1088 | vr.obytes=vif->bytes_out; | 1101 | vr.obytes = vif->bytes_out; |
1089 | read_unlock(&mrt_lock); | 1102 | read_unlock(&mrt_lock); |
1090 | 1103 | ||
1091 | if (copy_to_user(arg,&vr,sizeof(vr))) | 1104 | if (copy_to_user(arg, &vr, sizeof(vr))) |
1092 | return -EFAULT; | 1105 | return -EFAULT; |
1093 | return 0; | 1106 | return 0; |
1094 | } | 1107 | } |
1095 | read_unlock(&mrt_lock); | 1108 | read_unlock(&mrt_lock); |
1096 | return -EADDRNOTAVAIL; | 1109 | return -EADDRNOTAVAIL; |
1097 | case SIOCGETSGCNT: | 1110 | case SIOCGETSGCNT: |
1098 | if (copy_from_user(&sr,arg,sizeof(sr))) | 1111 | if (copy_from_user(&sr, arg, sizeof(sr))) |
1099 | return -EFAULT; | 1112 | return -EFAULT; |
1100 | 1113 | ||
1101 | read_lock(&mrt_lock); | 1114 | read_lock(&mrt_lock); |
@@ -1106,7 +1119,7 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1106 | sr.wrong_if = c->mfc_un.res.wrong_if; | 1119 | sr.wrong_if = c->mfc_un.res.wrong_if; |
1107 | read_unlock(&mrt_lock); | 1120 | read_unlock(&mrt_lock); |
1108 | 1121 | ||
1109 | if (copy_to_user(arg,&sr,sizeof(sr))) | 1122 | if (copy_to_user(arg, &sr, sizeof(sr))) |
1110 | return -EFAULT; | 1123 | return -EFAULT; |
1111 | return 0; | 1124 | return 0; |
1112 | } | 1125 | } |
@@ -1130,15 +1143,15 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1130 | if (event != NETDEV_UNREGISTER) | 1143 | if (event != NETDEV_UNREGISTER) |
1131 | return NOTIFY_DONE; | 1144 | return NOTIFY_DONE; |
1132 | v=&vif_table[0]; | 1145 | v=&vif_table[0]; |
1133 | for (ct=0;ct<maxvif;ct++,v++) { | 1146 | for (ct=0; ct<maxvif; ct++,v++) { |
1134 | if (v->dev==dev) | 1147 | if (v->dev == dev) |
1135 | vif_delete(ct, 1); | 1148 | vif_delete(ct, 1); |
1136 | } | 1149 | } |
1137 | return NOTIFY_DONE; | 1150 | return NOTIFY_DONE; |
1138 | } | 1151 | } |
1139 | 1152 | ||
1140 | 1153 | ||
1141 | static struct notifier_block ip_mr_notifier={ | 1154 | static struct notifier_block ip_mr_notifier = { |
1142 | .notifier_call = ipmr_device_event, | 1155 | .notifier_call = ipmr_device_event, |
1143 | }; | 1156 | }; |
1144 | 1157 | ||
@@ -1204,7 +1217,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1204 | #ifdef CONFIG_IP_PIMSM | 1217 | #ifdef CONFIG_IP_PIMSM |
1205 | if (vif->flags & VIFF_REGISTER) { | 1218 | if (vif->flags & VIFF_REGISTER) { |
1206 | vif->pkt_out++; | 1219 | vif->pkt_out++; |
1207 | vif->bytes_out+=skb->len; | 1220 | vif->bytes_out += skb->len; |
1208 | vif->dev->stats.tx_bytes += skb->len; | 1221 | vif->dev->stats.tx_bytes += skb->len; |
1209 | vif->dev->stats.tx_packets++; | 1222 | vif->dev->stats.tx_packets++; |
1210 | ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); | 1223 | ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); |
@@ -1254,7 +1267,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1254 | } | 1267 | } |
1255 | 1268 | ||
1256 | vif->pkt_out++; | 1269 | vif->pkt_out++; |
1257 | vif->bytes_out+=skb->len; | 1270 | vif->bytes_out += skb->len; |
1258 | 1271 | ||
1259 | dst_release(skb->dst); | 1272 | dst_release(skb->dst); |
1260 | skb->dst = &rt->u.dst; | 1273 | skb->dst = &rt->u.dst; |
@@ -1352,7 +1365,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1352 | } | 1365 | } |
1353 | 1366 | ||
1354 | vif_table[vif].pkt_in++; | 1367 | vif_table[vif].pkt_in++; |
1355 | vif_table[vif].bytes_in+=skb->len; | 1368 | vif_table[vif].bytes_in += skb->len; |
1356 | 1369 | ||
1357 | /* | 1370 | /* |
1358 | * Forward the frame | 1371 | * Forward the frame |
@@ -1364,7 +1377,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1364 | if (skb2) | 1377 | if (skb2) |
1365 | ipmr_queue_xmit(skb2, cache, psend); | 1378 | ipmr_queue_xmit(skb2, cache, psend); |
1366 | } | 1379 | } |
1367 | psend=ct; | 1380 | psend = ct; |
1368 | } | 1381 | } |
1369 | } | 1382 | } |
1370 | if (psend != -1) { | 1383 | if (psend != -1) { |
@@ -1428,7 +1441,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
1428 | /* | 1441 | /* |
1429 | * No usable cache entry | 1442 | * No usable cache entry |
1430 | */ | 1443 | */ |
1431 | if (cache==NULL) { | 1444 | if (cache == NULL) { |
1432 | int vif; | 1445 | int vif; |
1433 | 1446 | ||
1434 | if (local) { | 1447 | if (local) { |
@@ -1469,29 +1482,13 @@ dont_forward: | |||
1469 | return 0; | 1482 | return 0; |
1470 | } | 1483 | } |
1471 | 1484 | ||
1472 | #ifdef CONFIG_IP_PIMSM_V1 | 1485 | #ifdef CONFIG_IP_PIMSM |
1473 | /* | 1486 | static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) |
1474 | * Handle IGMP messages of PIMv1 | ||
1475 | */ | ||
1476 | |||
1477 | int pim_rcv_v1(struct sk_buff * skb) | ||
1478 | { | 1487 | { |
1479 | struct igmphdr *pim; | 1488 | struct net_device *reg_dev = NULL; |
1480 | struct iphdr *encap; | 1489 | struct iphdr *encap; |
1481 | struct net_device *reg_dev = NULL; | ||
1482 | |||
1483 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) | ||
1484 | goto drop; | ||
1485 | 1490 | ||
1486 | pim = igmp_hdr(skb); | 1491 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); |
1487 | |||
1488 | if (!mroute_do_pim || | ||
1489 | skb->len < sizeof(*pim) + sizeof(*encap) || | ||
1490 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | ||
1491 | goto drop; | ||
1492 | |||
1493 | encap = (struct iphdr *)(skb_transport_header(skb) + | ||
1494 | sizeof(struct igmphdr)); | ||
1495 | /* | 1492 | /* |
1496 | Check that: | 1493 | Check that: |
1497 | a. packet is really destinted to a multicast group | 1494 | a. packet is really destinted to a multicast group |
@@ -1500,8 +1497,8 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1500 | */ | 1497 | */ |
1501 | if (!ipv4_is_multicast(encap->daddr) || | 1498 | if (!ipv4_is_multicast(encap->daddr) || |
1502 | encap->tot_len == 0 || | 1499 | encap->tot_len == 0 || |
1503 | ntohs(encap->tot_len) + sizeof(*pim) > skb->len) | 1500 | ntohs(encap->tot_len) + pimlen > skb->len) |
1504 | goto drop; | 1501 | return 1; |
1505 | 1502 | ||
1506 | read_lock(&mrt_lock); | 1503 | read_lock(&mrt_lock); |
1507 | if (reg_vif_num >= 0) | 1504 | if (reg_vif_num >= 0) |
@@ -1511,7 +1508,7 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1511 | read_unlock(&mrt_lock); | 1508 | read_unlock(&mrt_lock); |
1512 | 1509 | ||
1513 | if (reg_dev == NULL) | 1510 | if (reg_dev == NULL) |
1514 | goto drop; | 1511 | return 1; |
1515 | 1512 | ||
1516 | skb->mac_header = skb->network_header; | 1513 | skb->mac_header = skb->network_header; |
1517 | skb_pull(skb, (u8*)encap - skb->data); | 1514 | skb_pull(skb, (u8*)encap - skb->data); |
@@ -1527,9 +1524,33 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1527 | nf_reset(skb); | 1524 | nf_reset(skb); |
1528 | netif_rx(skb); | 1525 | netif_rx(skb); |
1529 | dev_put(reg_dev); | 1526 | dev_put(reg_dev); |
1527 | |||
1530 | return 0; | 1528 | return 0; |
1531 | drop: | 1529 | } |
1532 | kfree_skb(skb); | 1530 | #endif |
1531 | |||
1532 | #ifdef CONFIG_IP_PIMSM_V1 | ||
1533 | /* | ||
1534 | * Handle IGMP messages of PIMv1 | ||
1535 | */ | ||
1536 | |||
1537 | int pim_rcv_v1(struct sk_buff * skb) | ||
1538 | { | ||
1539 | struct igmphdr *pim; | ||
1540 | |||
1541 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) | ||
1542 | goto drop; | ||
1543 | |||
1544 | pim = igmp_hdr(skb); | ||
1545 | |||
1546 | if (!mroute_do_pim || | ||
1547 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | ||
1548 | goto drop; | ||
1549 | |||
1550 | if (__pim_rcv(skb, sizeof(*pim))) { | ||
1551 | drop: | ||
1552 | kfree_skb(skb); | ||
1553 | } | ||
1533 | return 0; | 1554 | return 0; |
1534 | } | 1555 | } |
1535 | #endif | 1556 | #endif |
@@ -1538,10 +1559,8 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1538 | static int pim_rcv(struct sk_buff * skb) | 1559 | static int pim_rcv(struct sk_buff * skb) |
1539 | { | 1560 | { |
1540 | struct pimreghdr *pim; | 1561 | struct pimreghdr *pim; |
1541 | struct iphdr *encap; | ||
1542 | struct net_device *reg_dev = NULL; | ||
1543 | 1562 | ||
1544 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) | 1563 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) |
1545 | goto drop; | 1564 | goto drop; |
1546 | 1565 | ||
1547 | pim = (struct pimreghdr *)skb_transport_header(skb); | 1566 | pim = (struct pimreghdr *)skb_transport_header(skb); |
@@ -1551,41 +1570,10 @@ static int pim_rcv(struct sk_buff * skb) | |||
1551 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 1570 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
1552 | goto drop; | 1571 | goto drop; |
1553 | 1572 | ||
1554 | /* check if the inner packet is destined to mcast group */ | 1573 | if (__pim_rcv(skb, sizeof(*pim))) { |
1555 | encap = (struct iphdr *)(skb_transport_header(skb) + | 1574 | drop: |
1556 | sizeof(struct pimreghdr)); | 1575 | kfree_skb(skb); |
1557 | if (!ipv4_is_multicast(encap->daddr) || | 1576 | } |
1558 | encap->tot_len == 0 || | ||
1559 | ntohs(encap->tot_len) + sizeof(*pim) > skb->len) | ||
1560 | goto drop; | ||
1561 | |||
1562 | read_lock(&mrt_lock); | ||
1563 | if (reg_vif_num >= 0) | ||
1564 | reg_dev = vif_table[reg_vif_num].dev; | ||
1565 | if (reg_dev) | ||
1566 | dev_hold(reg_dev); | ||
1567 | read_unlock(&mrt_lock); | ||
1568 | |||
1569 | if (reg_dev == NULL) | ||
1570 | goto drop; | ||
1571 | |||
1572 | skb->mac_header = skb->network_header; | ||
1573 | skb_pull(skb, (u8*)encap - skb->data); | ||
1574 | skb_reset_network_header(skb); | ||
1575 | skb->dev = reg_dev; | ||
1576 | skb->protocol = htons(ETH_P_IP); | ||
1577 | skb->ip_summed = 0; | ||
1578 | skb->pkt_type = PACKET_HOST; | ||
1579 | dst_release(skb->dst); | ||
1580 | reg_dev->stats.rx_bytes += skb->len; | ||
1581 | reg_dev->stats.rx_packets++; | ||
1582 | skb->dst = NULL; | ||
1583 | nf_reset(skb); | ||
1584 | netif_rx(skb); | ||
1585 | dev_put(reg_dev); | ||
1586 | return 0; | ||
1587 | drop: | ||
1588 | kfree_skb(skb); | ||
1589 | return 0; | 1577 | return 0; |
1590 | } | 1578 | } |
1591 | #endif | 1579 | #endif |
@@ -1602,13 +1590,13 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) | |||
1602 | if (dev) | 1590 | if (dev) |
1603 | RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); | 1591 | RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); |
1604 | 1592 | ||
1605 | mp_head = (struct rtattr*)skb_put(skb, RTA_LENGTH(0)); | 1593 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); |
1606 | 1594 | ||
1607 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { | 1595 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { |
1608 | if (c->mfc_un.res.ttls[ct] < 255) { | 1596 | if (c->mfc_un.res.ttls[ct] < 255) { |
1609 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | 1597 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) |
1610 | goto rtattr_failure; | 1598 | goto rtattr_failure; |
1611 | nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 1599 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); |
1612 | nhp->rtnh_flags = 0; | 1600 | nhp->rtnh_flags = 0; |
1613 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | 1601 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; |
1614 | nhp->rtnh_ifindex = vif_table[ct].dev->ifindex; | 1602 | nhp->rtnh_ifindex = vif_table[ct].dev->ifindex; |
@@ -1634,7 +1622,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) | |||
1634 | read_lock(&mrt_lock); | 1622 | read_lock(&mrt_lock); |
1635 | cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); | 1623 | cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); |
1636 | 1624 | ||
1637 | if (cache==NULL) { | 1625 | if (cache == NULL) { |
1638 | struct sk_buff *skb2; | 1626 | struct sk_buff *skb2; |
1639 | struct iphdr *iph; | 1627 | struct iphdr *iph; |
1640 | struct net_device *dev; | 1628 | struct net_device *dev; |
@@ -1866,15 +1854,16 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
1866 | const struct mfc_cache *mfc = v; | 1854 | const struct mfc_cache *mfc = v; |
1867 | const struct ipmr_mfc_iter *it = seq->private; | 1855 | const struct ipmr_mfc_iter *it = seq->private; |
1868 | 1856 | ||
1869 | seq_printf(seq, "%08lX %08lX %-3d %8ld %8ld %8ld", | 1857 | seq_printf(seq, "%08lX %08lX %-3hd", |
1870 | (unsigned long) mfc->mfc_mcastgrp, | 1858 | (unsigned long) mfc->mfc_mcastgrp, |
1871 | (unsigned long) mfc->mfc_origin, | 1859 | (unsigned long) mfc->mfc_origin, |
1872 | mfc->mfc_parent, | 1860 | mfc->mfc_parent); |
1873 | mfc->mfc_un.res.pkt, | ||
1874 | mfc->mfc_un.res.bytes, | ||
1875 | mfc->mfc_un.res.wrong_if); | ||
1876 | 1861 | ||
1877 | if (it->cache != &mfc_unres_queue) { | 1862 | if (it->cache != &mfc_unres_queue) { |
1863 | seq_printf(seq, " %8lu %8lu %8lu", | ||
1864 | mfc->mfc_un.res.pkt, | ||
1865 | mfc->mfc_un.res.bytes, | ||
1866 | mfc->mfc_un.res.wrong_if); | ||
1878 | for (n = mfc->mfc_un.res.minvif; | 1867 | for (n = mfc->mfc_un.res.minvif; |
1879 | n < mfc->mfc_un.res.maxvif; n++ ) { | 1868 | n < mfc->mfc_un.res.maxvif; n++ ) { |
1880 | if (VIF_EXISTS(n) | 1869 | if (VIF_EXISTS(n) |
@@ -1883,6 +1872,11 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
1883 | " %2d:%-3d", | 1872 | " %2d:%-3d", |
1884 | n, mfc->mfc_un.res.ttls[n]); | 1873 | n, mfc->mfc_un.res.ttls[n]); |
1885 | } | 1874 | } |
1875 | } else { | ||
1876 | /* unresolved mfc_caches don't contain | ||
1877 | * pkt, bytes and wrong_if values | ||
1878 | */ | ||
1879 | seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul); | ||
1886 | } | 1880 | } |
1887 | seq_putc(seq, '\n'); | 1881 | seq_putc(seq, '\n'); |
1888 | } | 1882 | } |