aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94d4cd2d5ea4..ac6fde5d45f1 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1520,43 +1520,56 @@ struct rtable *rt_dst_alloc(struct net_device *dev,
1520EXPORT_SYMBOL(rt_dst_alloc); 1520EXPORT_SYMBOL(rt_dst_alloc);
1521 1521
1522/* called in rcu_read_lock() section */ 1522/* called in rcu_read_lock() section */
1523static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, 1523int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1524 u8 tos, struct net_device *dev, int our) 1524 u8 tos, struct net_device *dev,
1525 struct in_device *in_dev, u32 *itag)
1525{ 1526{
1526 struct rtable *rth;
1527 struct in_device *in_dev = __in_dev_get_rcu(dev);
1528 unsigned int flags = RTCF_MULTICAST;
1529 u32 itag = 0;
1530 int err; 1527 int err;
1531 1528
1532 /* Primary sanity checks. */ 1529 /* Primary sanity checks. */
1533
1534 if (!in_dev) 1530 if (!in_dev)
1535 return -EINVAL; 1531 return -EINVAL;
1536 1532
1537 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || 1533 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
1538 skb->protocol != htons(ETH_P_IP)) 1534 skb->protocol != htons(ETH_P_IP))
1539 goto e_inval; 1535 return -EINVAL;
1540 1536
1541 if (ipv4_is_loopback(saddr) && !IN_DEV_ROUTE_LOCALNET(in_dev)) 1537 if (ipv4_is_loopback(saddr) && !IN_DEV_ROUTE_LOCALNET(in_dev))
1542 goto e_inval; 1538 return -EINVAL;
1543 1539
1544 if (ipv4_is_zeronet(saddr)) { 1540 if (ipv4_is_zeronet(saddr)) {
1545 if (!ipv4_is_local_multicast(daddr)) 1541 if (!ipv4_is_local_multicast(daddr))
1546 goto e_inval; 1542 return -EINVAL;
1547 } else { 1543 } else {
1548 err = fib_validate_source(skb, saddr, 0, tos, 0, dev, 1544 err = fib_validate_source(skb, saddr, 0, tos, 0, dev,
1549 in_dev, &itag); 1545 in_dev, itag);
1550 if (err < 0) 1546 if (err < 0)
1551 goto e_err; 1547 return err;
1552 } 1548 }
1549 return 0;
1550}
1551
1552/* called in rcu_read_lock() section */
1553static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1554 u8 tos, struct net_device *dev, int our)
1555{
1556 struct in_device *in_dev = __in_dev_get_rcu(dev);
1557 unsigned int flags = RTCF_MULTICAST;
1558 struct rtable *rth;
1559 u32 itag = 0;
1560 int err;
1561
1562 err = ip_mc_validate_source(skb, daddr, saddr, tos, dev, in_dev, &itag);
1563 if (err)
1564 return err;
1565
1553 if (our) 1566 if (our)
1554 flags |= RTCF_LOCAL; 1567 flags |= RTCF_LOCAL;
1555 1568
1556 rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST, 1569 rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
1557 IN_DEV_CONF_GET(in_dev, NOPOLICY), false, false); 1570 IN_DEV_CONF_GET(in_dev, NOPOLICY), false, false);
1558 if (!rth) 1571 if (!rth)
1559 goto e_nobufs; 1572 return -ENOBUFS;
1560 1573
1561#ifdef CONFIG_IP_ROUTE_CLASSID 1574#ifdef CONFIG_IP_ROUTE_CLASSID
1562 rth->dst.tclassid = itag; 1575 rth->dst.tclassid = itag;
@@ -1572,13 +1585,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1572 1585
1573 skb_dst_set(skb, &rth->dst); 1586 skb_dst_set(skb, &rth->dst);
1574 return 0; 1587 return 0;
1575
1576e_nobufs:
1577 return -ENOBUFS;
1578e_inval:
1579 return -EINVAL;
1580e_err:
1581 return err;
1582} 1588}
1583 1589
1584 1590