aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipmr.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r--net/ipv4/ipmr.c100
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
151static int ipmr_fib_lookup(struct net *net, struct flowi *flp, 151static 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
286static int ipmr_fib_lookup(struct net *net, struct flowi *flp, 287static 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 = {
1548static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) 1549static 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
1792static 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))) {
1985drop: 1999drop:
1986 kfree_skb(skb); 2000 kfree_skb(skb);
@@ -2027,20 +2041,20 @@ rtattr_failure:
2027 return -EMSGSIZE; 2041 return -EMSGSIZE;
2028} 2042}
2029 2043
2030int ipmr_get_route(struct net *net, 2044int 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);