diff options
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 5fff865a4fa7..a1ad0e7180d2 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -312,7 +312,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
312 | return NULL; | 312 | return NULL; |
313 | } | 313 | } |
314 | 314 | ||
315 | skb_dst_set(skb, &rt->u.dst); | 315 | skb_dst_set(skb, &rt->dst); |
316 | skb->dev = dev; | 316 | skb->dev = dev; |
317 | 317 | ||
318 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 318 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
@@ -330,7 +330,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
330 | pip->saddr = rt->rt_src; | 330 | pip->saddr = rt->rt_src; |
331 | pip->protocol = IPPROTO_IGMP; | 331 | pip->protocol = IPPROTO_IGMP; |
332 | pip->tot_len = 0; /* filled in later */ | 332 | pip->tot_len = 0; /* filled in later */ |
333 | ip_select_ident(pip, &rt->u.dst, NULL); | 333 | ip_select_ident(pip, &rt->dst, NULL); |
334 | ((u8*)&pip[1])[0] = IPOPT_RA; | 334 | ((u8*)&pip[1])[0] = IPOPT_RA; |
335 | ((u8*)&pip[1])[1] = 4; | 335 | ((u8*)&pip[1])[1] = 4; |
336 | ((u8*)&pip[1])[2] = 0; | 336 | ((u8*)&pip[1])[2] = 0; |
@@ -660,7 +660,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
660 | return -1; | 660 | return -1; |
661 | } | 661 | } |
662 | 662 | ||
663 | skb_dst_set(skb, &rt->u.dst); | 663 | skb_dst_set(skb, &rt->dst); |
664 | 664 | ||
665 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 665 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
666 | 666 | ||
@@ -676,7 +676,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
676 | iph->daddr = dst; | 676 | iph->daddr = dst; |
677 | iph->saddr = rt->rt_src; | 677 | iph->saddr = rt->rt_src; |
678 | iph->protocol = IPPROTO_IGMP; | 678 | iph->protocol = IPPROTO_IGMP; |
679 | ip_select_ident(iph, &rt->u.dst, NULL); | 679 | ip_select_ident(iph, &rt->dst, NULL); |
680 | ((u8*)&iph[1])[0] = IPOPT_RA; | 680 | ((u8*)&iph[1])[0] = IPOPT_RA; |
681 | ((u8*)&iph[1])[1] = 4; | 681 | ((u8*)&iph[1])[1] = 4; |
682 | ((u8*)&iph[1])[2] = 0; | 682 | ((u8*)&iph[1])[2] = 0; |
@@ -916,18 +916,19 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, | |||
916 | read_unlock(&in_dev->mc_list_lock); | 916 | read_unlock(&in_dev->mc_list_lock); |
917 | } | 917 | } |
918 | 918 | ||
919 | /* called in rcu_read_lock() section */ | ||
919 | int igmp_rcv(struct sk_buff *skb) | 920 | int igmp_rcv(struct sk_buff *skb) |
920 | { | 921 | { |
921 | /* This basically follows the spec line by line -- see RFC1112 */ | 922 | /* This basically follows the spec line by line -- see RFC1112 */ |
922 | struct igmphdr *ih; | 923 | struct igmphdr *ih; |
923 | struct in_device *in_dev = in_dev_get(skb->dev); | 924 | struct in_device *in_dev = __in_dev_get_rcu(skb->dev); |
924 | int len = skb->len; | 925 | int len = skb->len; |
925 | 926 | ||
926 | if (in_dev == NULL) | 927 | if (in_dev == NULL) |
927 | goto drop; | 928 | goto drop; |
928 | 929 | ||
929 | if (!pskb_may_pull(skb, sizeof(struct igmphdr))) | 930 | if (!pskb_may_pull(skb, sizeof(struct igmphdr))) |
930 | goto drop_ref; | 931 | goto drop; |
931 | 932 | ||
932 | switch (skb->ip_summed) { | 933 | switch (skb->ip_summed) { |
933 | case CHECKSUM_COMPLETE: | 934 | case CHECKSUM_COMPLETE: |
@@ -937,7 +938,7 @@ int igmp_rcv(struct sk_buff *skb) | |||
937 | case CHECKSUM_NONE: | 938 | case CHECKSUM_NONE: |
938 | skb->csum = 0; | 939 | skb->csum = 0; |
939 | if (__skb_checksum_complete(skb)) | 940 | if (__skb_checksum_complete(skb)) |
940 | goto drop_ref; | 941 | goto drop; |
941 | } | 942 | } |
942 | 943 | ||
943 | ih = igmp_hdr(skb); | 944 | ih = igmp_hdr(skb); |
@@ -957,7 +958,6 @@ int igmp_rcv(struct sk_buff *skb) | |||
957 | break; | 958 | break; |
958 | case IGMP_PIM: | 959 | case IGMP_PIM: |
959 | #ifdef CONFIG_IP_PIMSM_V1 | 960 | #ifdef CONFIG_IP_PIMSM_V1 |
960 | in_dev_put(in_dev); | ||
961 | return pim_rcv_v1(skb); | 961 | return pim_rcv_v1(skb); |
962 | #endif | 962 | #endif |
963 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | 963 | case IGMPV3_HOST_MEMBERSHIP_REPORT: |
@@ -971,8 +971,6 @@ int igmp_rcv(struct sk_buff *skb) | |||
971 | break; | 971 | break; |
972 | } | 972 | } |
973 | 973 | ||
974 | drop_ref: | ||
975 | in_dev_put(in_dev); | ||
976 | drop: | 974 | drop: |
977 | kfree_skb(skb); | 975 | kfree_skb(skb); |
978 | return 0; | 976 | return 0; |
@@ -1246,6 +1244,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) | |||
1246 | out: | 1244 | out: |
1247 | return; | 1245 | return; |
1248 | } | 1246 | } |
1247 | EXPORT_SYMBOL(ip_mc_inc_group); | ||
1249 | 1248 | ||
1250 | /* | 1249 | /* |
1251 | * Resend IGMP JOIN report; used for bonding. | 1250 | * Resend IGMP JOIN report; used for bonding. |
@@ -1268,6 +1267,7 @@ void ip_mc_rejoin_group(struct ip_mc_list *im) | |||
1268 | igmp_ifc_event(in_dev); | 1267 | igmp_ifc_event(in_dev); |
1269 | #endif | 1268 | #endif |
1270 | } | 1269 | } |
1270 | EXPORT_SYMBOL(ip_mc_rejoin_group); | ||
1271 | 1271 | ||
1272 | /* | 1272 | /* |
1273 | * A socket has left a multicast group on device dev | 1273 | * A socket has left a multicast group on device dev |
@@ -1298,6 +1298,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) | |||
1298 | } | 1298 | } |
1299 | } | 1299 | } |
1300 | } | 1300 | } |
1301 | EXPORT_SYMBOL(ip_mc_dec_group); | ||
1301 | 1302 | ||
1302 | /* Device changing type */ | 1303 | /* Device changing type */ |
1303 | 1304 | ||
@@ -1427,7 +1428,7 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) | |||
1427 | } | 1428 | } |
1428 | 1429 | ||
1429 | if (!dev && !ip_route_output_key(net, &rt, &fl)) { | 1430 | if (!dev && !ip_route_output_key(net, &rt, &fl)) { |
1430 | dev = rt->u.dst.dev; | 1431 | dev = rt->dst.dev; |
1431 | ip_rt_put(rt); | 1432 | ip_rt_put(rt); |
1432 | } | 1433 | } |
1433 | if (dev) { | 1434 | if (dev) { |
@@ -1646,8 +1647,7 @@ static int sf_setstate(struct ip_mc_list *pmc) | |||
1646 | if (dpsf->sf_inaddr == psf->sf_inaddr) | 1647 | if (dpsf->sf_inaddr == psf->sf_inaddr) |
1647 | break; | 1648 | break; |
1648 | if (!dpsf) { | 1649 | if (!dpsf) { |
1649 | dpsf = (struct ip_sf_list *) | 1650 | dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC); |
1650 | kmalloc(sizeof(*dpsf), GFP_ATOMIC); | ||
1651 | if (!dpsf) | 1651 | if (!dpsf) |
1652 | continue; | 1652 | continue; |
1653 | *dpsf = *psf; | 1653 | *dpsf = *psf; |
@@ -1807,6 +1807,7 @@ done: | |||
1807 | rtnl_unlock(); | 1807 | rtnl_unlock(); |
1808 | return err; | 1808 | return err; |
1809 | } | 1809 | } |
1810 | EXPORT_SYMBOL(ip_mc_join_group); | ||
1810 | 1811 | ||
1811 | static void ip_sf_socklist_reclaim(struct rcu_head *rp) | 1812 | static void ip_sf_socklist_reclaim(struct rcu_head *rp) |
1812 | { | 1813 | { |
@@ -2679,8 +2680,3 @@ int __init igmp_mc_proc_init(void) | |||
2679 | return register_pernet_subsys(&igmp_net_ops); | 2680 | return register_pernet_subsys(&igmp_net_ops); |
2680 | } | 2681 | } |
2681 | #endif | 2682 | #endif |
2682 | |||
2683 | EXPORT_SYMBOL(ip_mc_dec_group); | ||
2684 | EXPORT_SYMBOL(ip_mc_inc_group); | ||
2685 | EXPORT_SYMBOL(ip_mc_join_group); | ||
2686 | EXPORT_SYMBOL(ip_mc_rejoin_group); | ||