diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/ipv6/ip6mr.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'net/ipv6/ip6mr.c')
-rw-r--r-- | net/ipv6/ip6mr.c | 140 |
1 files changed, 107 insertions, 33 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 66078dad7fe8..82a809901f8e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/compat.h> | ||
37 | #include <net/protocol.h> | 38 | #include <net/protocol.h> |
38 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
39 | #include <net/sock.h> | 40 | #include <net/sock.h> |
@@ -134,14 +135,15 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | |||
134 | return NULL; | 135 | return NULL; |
135 | } | 136 | } |
136 | 137 | ||
137 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | 138 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, |
138 | struct mr6_table **mrt) | 139 | struct mr6_table **mrt) |
139 | { | 140 | { |
140 | struct ip6mr_result res; | 141 | struct ip6mr_result res; |
141 | struct fib_lookup_arg arg = { .result = &res, }; | 142 | struct fib_lookup_arg arg = { .result = &res, }; |
142 | int err; | 143 | int err; |
143 | 144 | ||
144 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flp, 0, &arg); | 145 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, |
146 | flowi6_to_flowi(flp6), 0, &arg); | ||
145 | if (err < 0) | 147 | if (err < 0) |
146 | return err; | 148 | return err; |
147 | *mrt = res.mrt; | 149 | *mrt = res.mrt; |
@@ -269,7 +271,7 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | |||
269 | return net->ipv6.mrt6; | 271 | return net->ipv6.mrt6; |
270 | } | 272 | } |
271 | 273 | ||
272 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | 274 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, |
273 | struct mr6_table **mrt) | 275 | struct mr6_table **mrt) |
274 | { | 276 | { |
275 | *mrt = net->ipv6.mrt6; | 277 | *mrt = net->ipv6.mrt6; |
@@ -616,9 +618,9 @@ static int pim6_rcv(struct sk_buff *skb) | |||
616 | struct net_device *reg_dev = NULL; | 618 | struct net_device *reg_dev = NULL; |
617 | struct net *net = dev_net(skb->dev); | 619 | struct net *net = dev_net(skb->dev); |
618 | struct mr6_table *mrt; | 620 | struct mr6_table *mrt; |
619 | struct flowi fl = { | 621 | struct flowi6 fl6 = { |
620 | .iif = skb->dev->ifindex, | 622 | .flowi6_iif = skb->dev->ifindex, |
621 | .mark = skb->mark, | 623 | .flowi6_mark = skb->mark, |
622 | }; | 624 | }; |
623 | int reg_vif_num; | 625 | int reg_vif_num; |
624 | 626 | ||
@@ -643,7 +645,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
643 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) | 645 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) |
644 | goto drop; | 646 | goto drop; |
645 | 647 | ||
646 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | 648 | if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0) |
647 | goto drop; | 649 | goto drop; |
648 | reg_vif_num = mrt->mroute_reg_vif_num; | 650 | reg_vif_num = mrt->mroute_reg_vif_num; |
649 | 651 | ||
@@ -661,12 +663,13 @@ static int pim6_rcv(struct sk_buff *skb) | |||
661 | skb_pull(skb, (u8 *)encap - skb->data); | 663 | skb_pull(skb, (u8 *)encap - skb->data); |
662 | skb_reset_network_header(skb); | 664 | skb_reset_network_header(skb); |
663 | skb->protocol = htons(ETH_P_IPV6); | 665 | skb->protocol = htons(ETH_P_IPV6); |
664 | skb->ip_summed = 0; | 666 | skb->ip_summed = CHECKSUM_NONE; |
665 | skb->pkt_type = PACKET_HOST; | 667 | skb->pkt_type = PACKET_HOST; |
666 | 668 | ||
667 | skb_tunnel_rx(skb, reg_dev); | 669 | skb_tunnel_rx(skb, reg_dev); |
668 | 670 | ||
669 | netif_rx(skb); | 671 | netif_rx(skb); |
672 | |||
670 | dev_put(reg_dev); | 673 | dev_put(reg_dev); |
671 | return 0; | 674 | return 0; |
672 | drop: | 675 | drop: |
@@ -685,14 +688,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
685 | { | 688 | { |
686 | struct net *net = dev_net(dev); | 689 | struct net *net = dev_net(dev); |
687 | struct mr6_table *mrt; | 690 | struct mr6_table *mrt; |
688 | struct flowi fl = { | 691 | struct flowi6 fl6 = { |
689 | .oif = dev->ifindex, | 692 | .flowi6_oif = dev->ifindex, |
690 | .iif = skb->skb_iif, | 693 | .flowi6_iif = skb->skb_iif, |
691 | .mark = skb->mark, | 694 | .flowi6_mark = skb->mark, |
692 | }; | 695 | }; |
693 | int err; | 696 | int err; |
694 | 697 | ||
695 | err = ip6mr_fib_lookup(net, &fl, &mrt); | 698 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
696 | if (err < 0) | 699 | if (err < 0) |
697 | return err; | 700 | return err; |
698 | 701 | ||
@@ -986,8 +989,8 @@ static int mif6_add(struct net *net, struct mr6_table *mrt, | |||
986 | } | 989 | } |
987 | 990 | ||
988 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, | 991 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, |
989 | struct in6_addr *origin, | 992 | const struct in6_addr *origin, |
990 | struct in6_addr *mcastgrp) | 993 | const struct in6_addr *mcastgrp) |
991 | { | 994 | { |
992 | int line = MFC6_HASH(mcastgrp, origin); | 995 | int line = MFC6_HASH(mcastgrp, origin); |
993 | struct mfc6_cache *c; | 996 | struct mfc6_cache *c; |
@@ -1037,7 +1040,6 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1037 | 1040 | ||
1038 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { | 1041 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { |
1039 | if (ipv6_hdr(skb)->version == 0) { | 1042 | if (ipv6_hdr(skb)->version == 0) { |
1040 | int err; | ||
1041 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1043 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
1042 | 1044 | ||
1043 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 1045 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
@@ -1048,7 +1050,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1048 | skb_trim(skb, nlh->nlmsg_len); | 1050 | skb_trim(skb, nlh->nlmsg_len); |
1049 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1051 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; |
1050 | } | 1052 | } |
1051 | err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid); | 1053 | rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
1052 | } else | 1054 | } else |
1053 | ip6_mr_forward(net, mrt, skb, c); | 1055 | ip6_mr_forward(net, mrt, skb, c); |
1054 | } | 1056 | } |
@@ -1546,13 +1548,13 @@ int ip6mr_sk_done(struct sock *sk) | |||
1546 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) | 1548 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) |
1547 | { | 1549 | { |
1548 | struct mr6_table *mrt; | 1550 | struct mr6_table *mrt; |
1549 | struct flowi fl = { | 1551 | struct flowi6 fl6 = { |
1550 | .iif = skb->skb_iif, | 1552 | .flowi6_iif = skb->skb_iif, |
1551 | .oif = skb->dev->ifindex, | 1553 | .flowi6_oif = skb->dev->ifindex, |
1552 | .mark = skb->mark, | 1554 | .flowi6_mark = skb->mark, |
1553 | }; | 1555 | }; |
1554 | 1556 | ||
1555 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | 1557 | if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0) |
1556 | return NULL; | 1558 | return NULL; |
1557 | 1559 | ||
1558 | return mrt->mroute6_sk; | 1560 | return mrt->mroute6_sk; |
@@ -1803,6 +1805,80 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1803 | } | 1805 | } |
1804 | } | 1806 | } |
1805 | 1807 | ||
1808 | #ifdef CONFIG_COMPAT | ||
1809 | struct compat_sioc_sg_req6 { | ||
1810 | struct sockaddr_in6 src; | ||
1811 | struct sockaddr_in6 grp; | ||
1812 | compat_ulong_t pktcnt; | ||
1813 | compat_ulong_t bytecnt; | ||
1814 | compat_ulong_t wrong_if; | ||
1815 | }; | ||
1816 | |||
1817 | struct compat_sioc_mif_req6 { | ||
1818 | mifi_t mifi; | ||
1819 | compat_ulong_t icount; | ||
1820 | compat_ulong_t ocount; | ||
1821 | compat_ulong_t ibytes; | ||
1822 | compat_ulong_t obytes; | ||
1823 | }; | ||
1824 | |||
1825 | int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) | ||
1826 | { | ||
1827 | struct compat_sioc_sg_req6 sr; | ||
1828 | struct compat_sioc_mif_req6 vr; | ||
1829 | struct mif_device *vif; | ||
1830 | struct mfc6_cache *c; | ||
1831 | struct net *net = sock_net(sk); | ||
1832 | struct mr6_table *mrt; | ||
1833 | |||
1834 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1835 | if (mrt == NULL) | ||
1836 | return -ENOENT; | ||
1837 | |||
1838 | switch (cmd) { | ||
1839 | case SIOCGETMIFCNT_IN6: | ||
1840 | if (copy_from_user(&vr, arg, sizeof(vr))) | ||
1841 | return -EFAULT; | ||
1842 | if (vr.mifi >= mrt->maxvif) | ||
1843 | return -EINVAL; | ||
1844 | read_lock(&mrt_lock); | ||
1845 | vif = &mrt->vif6_table[vr.mifi]; | ||
1846 | if (MIF_EXISTS(mrt, vr.mifi)) { | ||
1847 | vr.icount = vif->pkt_in; | ||
1848 | vr.ocount = vif->pkt_out; | ||
1849 | vr.ibytes = vif->bytes_in; | ||
1850 | vr.obytes = vif->bytes_out; | ||
1851 | read_unlock(&mrt_lock); | ||
1852 | |||
1853 | if (copy_to_user(arg, &vr, sizeof(vr))) | ||
1854 | return -EFAULT; | ||
1855 | return 0; | ||
1856 | } | ||
1857 | read_unlock(&mrt_lock); | ||
1858 | return -EADDRNOTAVAIL; | ||
1859 | case SIOCGETSGCNT_IN6: | ||
1860 | if (copy_from_user(&sr, arg, sizeof(sr))) | ||
1861 | return -EFAULT; | ||
1862 | |||
1863 | read_lock(&mrt_lock); | ||
1864 | c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); | ||
1865 | if (c) { | ||
1866 | sr.pktcnt = c->mfc_un.res.pkt; | ||
1867 | sr.bytecnt = c->mfc_un.res.bytes; | ||
1868 | sr.wrong_if = c->mfc_un.res.wrong_if; | ||
1869 | read_unlock(&mrt_lock); | ||
1870 | |||
1871 | if (copy_to_user(arg, &sr, sizeof(sr))) | ||
1872 | return -EFAULT; | ||
1873 | return 0; | ||
1874 | } | ||
1875 | read_unlock(&mrt_lock); | ||
1876 | return -EADDRNOTAVAIL; | ||
1877 | default: | ||
1878 | return -ENOIOCTLCMD; | ||
1879 | } | ||
1880 | } | ||
1881 | #endif | ||
1806 | 1882 | ||
1807 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) | 1883 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) |
1808 | { | 1884 | { |
@@ -1822,7 +1898,7 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1822 | struct mif_device *vif = &mrt->vif6_table[vifi]; | 1898 | struct mif_device *vif = &mrt->vif6_table[vifi]; |
1823 | struct net_device *dev; | 1899 | struct net_device *dev; |
1824 | struct dst_entry *dst; | 1900 | struct dst_entry *dst; |
1825 | struct flowi fl; | 1901 | struct flowi6 fl6; |
1826 | 1902 | ||
1827 | if (vif->dev == NULL) | 1903 | if (vif->dev == NULL) |
1828 | goto out_free; | 1904 | goto out_free; |
@@ -1840,14 +1916,12 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1840 | 1916 | ||
1841 | ipv6h = ipv6_hdr(skb); | 1917 | ipv6h = ipv6_hdr(skb); |
1842 | 1918 | ||
1843 | fl = (struct flowi) { | 1919 | fl6 = (struct flowi6) { |
1844 | .oif = vif->link, | 1920 | .flowi6_oif = vif->link, |
1845 | .nl_u = { .ip6_u = | 1921 | .daddr = ipv6h->daddr, |
1846 | { .daddr = ipv6h->daddr, } | ||
1847 | } | ||
1848 | }; | 1922 | }; |
1849 | 1923 | ||
1850 | dst = ip6_route_output(net, NULL, &fl); | 1924 | dst = ip6_route_output(net, NULL, &fl6); |
1851 | if (!dst) | 1925 | if (!dst) |
1852 | goto out_free; | 1926 | goto out_free; |
1853 | 1927 | ||
@@ -1970,13 +2044,13 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1970 | struct mfc6_cache *cache; | 2044 | struct mfc6_cache *cache; |
1971 | struct net *net = dev_net(skb->dev); | 2045 | struct net *net = dev_net(skb->dev); |
1972 | struct mr6_table *mrt; | 2046 | struct mr6_table *mrt; |
1973 | struct flowi fl = { | 2047 | struct flowi6 fl6 = { |
1974 | .iif = skb->dev->ifindex, | 2048 | .flowi6_iif = skb->dev->ifindex, |
1975 | .mark = skb->mark, | 2049 | .flowi6_mark = skb->mark, |
1976 | }; | 2050 | }; |
1977 | int err; | 2051 | int err; |
1978 | 2052 | ||
1979 | err = ip6mr_fib_lookup(net, &fl, &mrt); | 2053 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
1980 | if (err < 0) | 2054 | if (err < 0) |
1981 | return err; | 2055 | return err; |
1982 | 2056 | ||