diff options
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 100 |
1 files changed, 57 insertions, 43 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8b65a12654e7..30a7763c400e 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -148,14 +148,15 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id) | |||
148 | return NULL; | 148 | return NULL; |
149 | } | 149 | } |
150 | 150 | ||
151 | static int ipmr_fib_lookup(struct net *net, struct flowi *flp, | 151 | static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, |
152 | struct mr_table **mrt) | 152 | struct mr_table **mrt) |
153 | { | 153 | { |
154 | struct ipmr_result res; | 154 | struct ipmr_result res; |
155 | struct fib_lookup_arg arg = { .result = &res, }; | 155 | struct fib_lookup_arg arg = { .result = &res, }; |
156 | int err; | 156 | int err; |
157 | 157 | ||
158 | err = fib_rules_lookup(net->ipv4.mr_rules_ops, flp, 0, &arg); | 158 | err = fib_rules_lookup(net->ipv4.mr_rules_ops, |
159 | flowi4_to_flowi(flp4), 0, &arg); | ||
159 | if (err < 0) | 160 | if (err < 0) |
160 | return err; | 161 | return err; |
161 | *mrt = res.mrt; | 162 | *mrt = res.mrt; |
@@ -283,7 +284,7 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id) | |||
283 | return net->ipv4.mrt; | 284 | return net->ipv4.mrt; |
284 | } | 285 | } |
285 | 286 | ||
286 | static int ipmr_fib_lookup(struct net *net, struct flowi *flp, | 287 | static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, |
287 | struct mr_table **mrt) | 288 | struct mr_table **mrt) |
288 | { | 289 | { |
289 | *mrt = net->ipv4.mrt; | 290 | *mrt = net->ipv4.mrt; |
@@ -435,14 +436,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | |||
435 | { | 436 | { |
436 | struct net *net = dev_net(dev); | 437 | struct net *net = dev_net(dev); |
437 | struct mr_table *mrt; | 438 | struct mr_table *mrt; |
438 | struct flowi fl = { | 439 | struct flowi4 fl4 = { |
439 | .oif = dev->ifindex, | 440 | .flowi4_oif = dev->ifindex, |
440 | .iif = skb->skb_iif, | 441 | .flowi4_iif = skb->skb_iif, |
441 | .mark = skb->mark, | 442 | .flowi4_mark = skb->mark, |
442 | }; | 443 | }; |
443 | int err; | 444 | int err; |
444 | 445 | ||
445 | err = ipmr_fib_lookup(net, &fl, &mrt); | 446 | err = ipmr_fib_lookup(net, &fl4, &mrt); |
446 | if (err < 0) { | 447 | if (err < 0) { |
447 | kfree_skb(skb); | 448 | kfree_skb(skb); |
448 | return err; | 449 | return err; |
@@ -1548,7 +1549,7 @@ static struct notifier_block ip_mr_notifier = { | |||
1548 | static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) | 1549 | static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) |
1549 | { | 1550 | { |
1550 | struct iphdr *iph; | 1551 | struct iphdr *iph; |
1551 | struct iphdr *old_iph = ip_hdr(skb); | 1552 | const struct iphdr *old_iph = ip_hdr(skb); |
1552 | 1553 | ||
1553 | skb_push(skb, sizeof(struct iphdr)); | 1554 | skb_push(skb, sizeof(struct iphdr)); |
1554 | skb->transport_header = skb->network_header; | 1555 | skb->transport_header = skb->network_header; |
@@ -1594,6 +1595,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1594 | struct vif_device *vif = &mrt->vif_table[vifi]; | 1595 | struct vif_device *vif = &mrt->vif_table[vifi]; |
1595 | struct net_device *dev; | 1596 | struct net_device *dev; |
1596 | struct rtable *rt; | 1597 | struct rtable *rt; |
1598 | struct flowi4 fl4; | ||
1597 | int encap = 0; | 1599 | int encap = 0; |
1598 | 1600 | ||
1599 | if (vif->dev == NULL) | 1601 | if (vif->dev == NULL) |
@@ -1611,26 +1613,20 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1611 | #endif | 1613 | #endif |
1612 | 1614 | ||
1613 | if (vif->flags & VIFF_TUNNEL) { | 1615 | if (vif->flags & VIFF_TUNNEL) { |
1614 | struct flowi fl = { | 1616 | rt = ip_route_output_ports(net, &fl4, NULL, |
1615 | .oif = vif->link, | 1617 | vif->remote, vif->local, |
1616 | .fl4_dst = vif->remote, | 1618 | 0, 0, |
1617 | .fl4_src = vif->local, | 1619 | IPPROTO_IPIP, |
1618 | .fl4_tos = RT_TOS(iph->tos), | 1620 | RT_TOS(iph->tos), vif->link); |
1619 | .proto = IPPROTO_IPIP | 1621 | if (IS_ERR(rt)) |
1620 | }; | ||
1621 | |||
1622 | if (ip_route_output_key(net, &rt, &fl)) | ||
1623 | goto out_free; | 1622 | goto out_free; |
1624 | encap = sizeof(struct iphdr); | 1623 | encap = sizeof(struct iphdr); |
1625 | } else { | 1624 | } else { |
1626 | struct flowi fl = { | 1625 | rt = ip_route_output_ports(net, &fl4, NULL, iph->daddr, 0, |
1627 | .oif = vif->link, | 1626 | 0, 0, |
1628 | .fl4_dst = iph->daddr, | 1627 | IPPROTO_IPIP, |
1629 | .fl4_tos = RT_TOS(iph->tos), | 1628 | RT_TOS(iph->tos), vif->link); |
1630 | .proto = IPPROTO_IPIP | 1629 | if (IS_ERR(rt)) |
1631 | }; | ||
1632 | |||
1633 | if (ip_route_output_key(net, &rt, &fl)) | ||
1634 | goto out_free; | 1630 | goto out_free; |
1635 | } | 1631 | } |
1636 | 1632 | ||
@@ -1793,6 +1789,26 @@ dont_forward: | |||
1793 | return 0; | 1789 | return 0; |
1794 | } | 1790 | } |
1795 | 1791 | ||
1792 | static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb) | ||
1793 | { | ||
1794 | struct rtable *rt = skb_rtable(skb); | ||
1795 | struct iphdr *iph = ip_hdr(skb); | ||
1796 | struct flowi4 fl4 = { | ||
1797 | .daddr = iph->daddr, | ||
1798 | .saddr = iph->saddr, | ||
1799 | .flowi4_tos = iph->tos, | ||
1800 | .flowi4_oif = rt->rt_oif, | ||
1801 | .flowi4_iif = rt->rt_iif, | ||
1802 | .flowi4_mark = rt->rt_mark, | ||
1803 | }; | ||
1804 | struct mr_table *mrt; | ||
1805 | int err; | ||
1806 | |||
1807 | err = ipmr_fib_lookup(net, &fl4, &mrt); | ||
1808 | if (err) | ||
1809 | return ERR_PTR(err); | ||
1810 | return mrt; | ||
1811 | } | ||
1796 | 1812 | ||
1797 | /* | 1813 | /* |
1798 | * Multicast packets for forwarding arrive here | 1814 | * Multicast packets for forwarding arrive here |
@@ -1805,7 +1821,6 @@ int ip_mr_input(struct sk_buff *skb) | |||
1805 | struct net *net = dev_net(skb->dev); | 1821 | struct net *net = dev_net(skb->dev); |
1806 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; | 1822 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; |
1807 | struct mr_table *mrt; | 1823 | struct mr_table *mrt; |
1808 | int err; | ||
1809 | 1824 | ||
1810 | /* Packet is looped back after forward, it should not be | 1825 | /* Packet is looped back after forward, it should not be |
1811 | * forwarded second time, but still can be delivered locally. | 1826 | * forwarded second time, but still can be delivered locally. |
@@ -1813,12 +1828,11 @@ int ip_mr_input(struct sk_buff *skb) | |||
1813 | if (IPCB(skb)->flags & IPSKB_FORWARDED) | 1828 | if (IPCB(skb)->flags & IPSKB_FORWARDED) |
1814 | goto dont_forward; | 1829 | goto dont_forward; |
1815 | 1830 | ||
1816 | err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt); | 1831 | mrt = ipmr_rt_fib_lookup(net, skb); |
1817 | if (err < 0) { | 1832 | if (IS_ERR(mrt)) { |
1818 | kfree_skb(skb); | 1833 | kfree_skb(skb); |
1819 | return err; | 1834 | return PTR_ERR(mrt); |
1820 | } | 1835 | } |
1821 | |||
1822 | if (!local) { | 1836 | if (!local) { |
1823 | if (IPCB(skb)->opt.router_alert) { | 1837 | if (IPCB(skb)->opt.router_alert) { |
1824 | if (ip_call_ra_chain(skb)) | 1838 | if (ip_call_ra_chain(skb)) |
@@ -1946,9 +1960,9 @@ int pim_rcv_v1(struct sk_buff *skb) | |||
1946 | 1960 | ||
1947 | pim = igmp_hdr(skb); | 1961 | pim = igmp_hdr(skb); |
1948 | 1962 | ||
1949 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) | 1963 | mrt = ipmr_rt_fib_lookup(net, skb); |
1964 | if (IS_ERR(mrt)) | ||
1950 | goto drop; | 1965 | goto drop; |
1951 | |||
1952 | if (!mrt->mroute_do_pim || | 1966 | if (!mrt->mroute_do_pim || |
1953 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | 1967 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) |
1954 | goto drop; | 1968 | goto drop; |
@@ -1978,9 +1992,9 @@ static int pim_rcv(struct sk_buff *skb) | |||
1978 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 1992 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
1979 | goto drop; | 1993 | goto drop; |
1980 | 1994 | ||
1981 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) | 1995 | mrt = ipmr_rt_fib_lookup(net, skb); |
1996 | if (IS_ERR(mrt)) | ||
1982 | goto drop; | 1997 | goto drop; |
1983 | |||
1984 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { | 1998 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { |
1985 | drop: | 1999 | drop: |
1986 | kfree_skb(skb); | 2000 | kfree_skb(skb); |
@@ -2027,20 +2041,20 @@ rtattr_failure: | |||
2027 | return -EMSGSIZE; | 2041 | return -EMSGSIZE; |
2028 | } | 2042 | } |
2029 | 2043 | ||
2030 | int ipmr_get_route(struct net *net, | 2044 | int ipmr_get_route(struct net *net, struct sk_buff *skb, |
2031 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 2045 | __be32 saddr, __be32 daddr, |
2046 | struct rtmsg *rtm, int nowait) | ||
2032 | { | 2047 | { |
2033 | int err; | ||
2034 | struct mr_table *mrt; | ||
2035 | struct mfc_cache *cache; | 2048 | struct mfc_cache *cache; |
2036 | struct rtable *rt = skb_rtable(skb); | 2049 | struct mr_table *mrt; |
2050 | int err; | ||
2037 | 2051 | ||
2038 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); | 2052 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); |
2039 | if (mrt == NULL) | 2053 | if (mrt == NULL) |
2040 | return -ENOENT; | 2054 | return -ENOENT; |
2041 | 2055 | ||
2042 | rcu_read_lock(); | 2056 | rcu_read_lock(); |
2043 | cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst); | 2057 | cache = ipmr_cache_find(mrt, saddr, daddr); |
2044 | 2058 | ||
2045 | if (cache == NULL) { | 2059 | if (cache == NULL) { |
2046 | struct sk_buff *skb2; | 2060 | struct sk_buff *skb2; |
@@ -2073,8 +2087,8 @@ int ipmr_get_route(struct net *net, | |||
2073 | skb_reset_network_header(skb2); | 2087 | skb_reset_network_header(skb2); |
2074 | iph = ip_hdr(skb2); | 2088 | iph = ip_hdr(skb2); |
2075 | iph->ihl = sizeof(struct iphdr) >> 2; | 2089 | iph->ihl = sizeof(struct iphdr) >> 2; |
2076 | iph->saddr = rt->rt_src; | 2090 | iph->saddr = saddr; |
2077 | iph->daddr = rt->rt_dst; | 2091 | iph->daddr = daddr; |
2078 | iph->version = 0; | 2092 | iph->version = 0; |
2079 | err = ipmr_cache_unresolved(mrt, vif, skb2); | 2093 | err = ipmr_cache_unresolved(mrt, vif, skb2); |
2080 | read_unlock(&mrt_lock); | 2094 | read_unlock(&mrt_lock); |