diff options
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8b65a12654e7..1f62eaeb6de4 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; |
@@ -1611,26 +1612,20 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1611 | #endif | 1612 | #endif |
1612 | 1613 | ||
1613 | if (vif->flags & VIFF_TUNNEL) { | 1614 | if (vif->flags & VIFF_TUNNEL) { |
1614 | struct flowi fl = { | 1615 | rt = ip_route_output_ports(net, NULL, |
1615 | .oif = vif->link, | 1616 | vif->remote, vif->local, |
1616 | .fl4_dst = vif->remote, | 1617 | 0, 0, |
1617 | .fl4_src = vif->local, | 1618 | IPPROTO_IPIP, |
1618 | .fl4_tos = RT_TOS(iph->tos), | 1619 | RT_TOS(iph->tos), vif->link); |
1619 | .proto = IPPROTO_IPIP | 1620 | if (IS_ERR(rt)) |
1620 | }; | ||
1621 | |||
1622 | if (ip_route_output_key(net, &rt, &fl)) | ||
1623 | goto out_free; | 1621 | goto out_free; |
1624 | encap = sizeof(struct iphdr); | 1622 | encap = sizeof(struct iphdr); |
1625 | } else { | 1623 | } else { |
1626 | struct flowi fl = { | 1624 | rt = ip_route_output_ports(net, NULL, iph->daddr, 0, |
1627 | .oif = vif->link, | 1625 | 0, 0, |
1628 | .fl4_dst = iph->daddr, | 1626 | IPPROTO_IPIP, |
1629 | .fl4_tos = RT_TOS(iph->tos), | 1627 | RT_TOS(iph->tos), vif->link); |
1630 | .proto = IPPROTO_IPIP | 1628 | if (IS_ERR(rt)) |
1631 | }; | ||
1632 | |||
1633 | if (ip_route_output_key(net, &rt, &fl)) | ||
1634 | goto out_free; | 1629 | goto out_free; |
1635 | } | 1630 | } |
1636 | 1631 | ||
@@ -1793,6 +1788,24 @@ dont_forward: | |||
1793 | return 0; | 1788 | return 0; |
1794 | } | 1789 | } |
1795 | 1790 | ||
1791 | static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct rtable *rt) | ||
1792 | { | ||
1793 | struct flowi4 fl4 = { | ||
1794 | .daddr = rt->rt_key_dst, | ||
1795 | .saddr = rt->rt_key_src, | ||
1796 | .flowi4_tos = rt->rt_tos, | ||
1797 | .flowi4_oif = rt->rt_oif, | ||
1798 | .flowi4_iif = rt->rt_iif, | ||
1799 | .flowi4_mark = rt->rt_mark, | ||
1800 | }; | ||
1801 | struct mr_table *mrt; | ||
1802 | int err; | ||
1803 | |||
1804 | err = ipmr_fib_lookup(net, &fl4, &mrt); | ||
1805 | if (err) | ||
1806 | return ERR_PTR(err); | ||
1807 | return mrt; | ||
1808 | } | ||
1796 | 1809 | ||
1797 | /* | 1810 | /* |
1798 | * Multicast packets for forwarding arrive here | 1811 | * Multicast packets for forwarding arrive here |
@@ -1805,7 +1818,6 @@ int ip_mr_input(struct sk_buff *skb) | |||
1805 | struct net *net = dev_net(skb->dev); | 1818 | struct net *net = dev_net(skb->dev); |
1806 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; | 1819 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; |
1807 | struct mr_table *mrt; | 1820 | struct mr_table *mrt; |
1808 | int err; | ||
1809 | 1821 | ||
1810 | /* Packet is looped back after forward, it should not be | 1822 | /* Packet is looped back after forward, it should not be |
1811 | * forwarded second time, but still can be delivered locally. | 1823 | * forwarded second time, but still can be delivered locally. |
@@ -1813,12 +1825,11 @@ int ip_mr_input(struct sk_buff *skb) | |||
1813 | if (IPCB(skb)->flags & IPSKB_FORWARDED) | 1825 | if (IPCB(skb)->flags & IPSKB_FORWARDED) |
1814 | goto dont_forward; | 1826 | goto dont_forward; |
1815 | 1827 | ||
1816 | err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt); | 1828 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); |
1817 | if (err < 0) { | 1829 | if (IS_ERR(mrt)) { |
1818 | kfree_skb(skb); | 1830 | kfree_skb(skb); |
1819 | return err; | 1831 | return PTR_ERR(mrt); |
1820 | } | 1832 | } |
1821 | |||
1822 | if (!local) { | 1833 | if (!local) { |
1823 | if (IPCB(skb)->opt.router_alert) { | 1834 | if (IPCB(skb)->opt.router_alert) { |
1824 | if (ip_call_ra_chain(skb)) | 1835 | if (ip_call_ra_chain(skb)) |
@@ -1946,9 +1957,9 @@ int pim_rcv_v1(struct sk_buff *skb) | |||
1946 | 1957 | ||
1947 | pim = igmp_hdr(skb); | 1958 | pim = igmp_hdr(skb); |
1948 | 1959 | ||
1949 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) | 1960 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); |
1961 | if (IS_ERR(mrt)) | ||
1950 | goto drop; | 1962 | goto drop; |
1951 | |||
1952 | if (!mrt->mroute_do_pim || | 1963 | if (!mrt->mroute_do_pim || |
1953 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | 1964 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) |
1954 | goto drop; | 1965 | goto drop; |
@@ -1978,9 +1989,9 @@ static int pim_rcv(struct sk_buff *skb) | |||
1978 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 1989 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
1979 | goto drop; | 1990 | goto drop; |
1980 | 1991 | ||
1981 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) | 1992 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); |
1993 | if (IS_ERR(mrt)) | ||
1982 | goto drop; | 1994 | goto drop; |
1983 | |||
1984 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { | 1995 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { |
1985 | drop: | 1996 | drop: |
1986 | kfree_skb(skb); | 1997 | kfree_skb(skb); |