aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ipmr.c103
1 files changed, 39 insertions, 64 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 244a624e0b18..14666449dc1c 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1482,29 +1482,13 @@ dont_forward:
1482 return 0; 1482 return 0;
1483} 1483}
1484 1484
1485#ifdef CONFIG_IP_PIMSM_V1 1485#ifdef CONFIG_IP_PIMSM
1486/* 1486static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
1487 * Handle IGMP messages of PIMv1
1488 */
1489
1490int pim_rcv_v1(struct sk_buff * skb)
1491{ 1487{
1492 struct igmphdr *pim; 1488 struct net_device *reg_dev = NULL;
1493 struct iphdr *encap; 1489 struct iphdr *encap;
1494 struct net_device *reg_dev = NULL;
1495
1496 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
1497 goto drop;
1498 1490
1499 pim = igmp_hdr(skb); 1491 encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
1500
1501 if (!mroute_do_pim ||
1502 skb->len < sizeof(*pim) + sizeof(*encap) ||
1503 pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
1504 goto drop;
1505
1506 encap = (struct iphdr *)(skb_transport_header(skb) +
1507 sizeof(struct igmphdr));
1508 /* 1492 /*
1509 Check that: 1493 Check that:
1510 a. packet is really destinted to a multicast group 1494 a. packet is really destinted to a multicast group
@@ -1513,8 +1497,8 @@ int pim_rcv_v1(struct sk_buff * skb)
1513 */ 1497 */
1514 if (!ipv4_is_multicast(encap->daddr) || 1498 if (!ipv4_is_multicast(encap->daddr) ||
1515 encap->tot_len == 0 || 1499 encap->tot_len == 0 ||
1516 ntohs(encap->tot_len) + sizeof(*pim) > skb->len) 1500 ntohs(encap->tot_len) + pimlen > skb->len)
1517 goto drop; 1501 return 1;
1518 1502
1519 read_lock(&mrt_lock); 1503 read_lock(&mrt_lock);
1520 if (reg_vif_num >= 0) 1504 if (reg_vif_num >= 0)
@@ -1524,7 +1508,7 @@ int pim_rcv_v1(struct sk_buff * skb)
1524 read_unlock(&mrt_lock); 1508 read_unlock(&mrt_lock);
1525 1509
1526 if (reg_dev == NULL) 1510 if (reg_dev == NULL)
1527 goto drop; 1511 return 1;
1528 1512
1529 skb->mac_header = skb->network_header; 1513 skb->mac_header = skb->network_header;
1530 skb_pull(skb, (u8*)encap - skb->data); 1514 skb_pull(skb, (u8*)encap - skb->data);
@@ -1540,9 +1524,33 @@ int pim_rcv_v1(struct sk_buff * skb)
1540 nf_reset(skb); 1524 nf_reset(skb);
1541 netif_rx(skb); 1525 netif_rx(skb);
1542 dev_put(reg_dev); 1526 dev_put(reg_dev);
1527
1543 return 0; 1528 return 0;
1544 drop: 1529}
1545 kfree_skb(skb); 1530#endif
1531
1532#ifdef CONFIG_IP_PIMSM_V1
1533/*
1534 * Handle IGMP messages of PIMv1
1535 */
1536
1537int pim_rcv_v1(struct sk_buff * skb)
1538{
1539 struct igmphdr *pim;
1540
1541 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
1542 goto drop;
1543
1544 pim = igmp_hdr(skb);
1545
1546 if (!mroute_do_pim ||
1547 pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
1548 goto drop;
1549
1550 if (__pim_rcv(skb, sizeof(*pim))) {
1551drop:
1552 kfree_skb(skb);
1553 }
1546 return 0; 1554 return 0;
1547} 1555}
1548#endif 1556#endif
@@ -1551,10 +1559,8 @@ int pim_rcv_v1(struct sk_buff * skb)
1551static int pim_rcv(struct sk_buff * skb) 1559static int pim_rcv(struct sk_buff * skb)
1552{ 1560{
1553 struct pimreghdr *pim; 1561 struct pimreghdr *pim;
1554 struct iphdr *encap;
1555 struct net_device *reg_dev = NULL;
1556 1562
1557 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) 1563 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
1558 goto drop; 1564 goto drop;
1559 1565
1560 pim = (struct pimreghdr *)skb_transport_header(skb); 1566 pim = (struct pimreghdr *)skb_transport_header(skb);
@@ -1564,41 +1570,10 @@ static int pim_rcv(struct sk_buff * skb)
1564 csum_fold(skb_checksum(skb, 0, skb->len, 0)))) 1570 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
1565 goto drop; 1571 goto drop;
1566 1572
1567 /* check if the inner packet is destined to mcast group */ 1573 if (__pim_rcv(skb, sizeof(*pim))) {
1568 encap = (struct iphdr *)(skb_transport_header(skb) + 1574drop:
1569 sizeof(struct pimreghdr)); 1575 kfree_skb(skb);
1570 if (!ipv4_is_multicast(encap->daddr) || 1576 }
1571 encap->tot_len == 0 ||
1572 ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
1573 goto drop;
1574
1575 read_lock(&mrt_lock);
1576 if (reg_vif_num >= 0)
1577 reg_dev = vif_table[reg_vif_num].dev;
1578 if (reg_dev)
1579 dev_hold(reg_dev);
1580 read_unlock(&mrt_lock);
1581
1582 if (reg_dev == NULL)
1583 goto drop;
1584
1585 skb->mac_header = skb->network_header;
1586 skb_pull(skb, (u8*)encap - skb->data);
1587 skb_reset_network_header(skb);
1588 skb->dev = reg_dev;
1589 skb->protocol = htons(ETH_P_IP);
1590 skb->ip_summed = 0;
1591 skb->pkt_type = PACKET_HOST;
1592 dst_release(skb->dst);
1593 reg_dev->stats.rx_bytes += skb->len;
1594 reg_dev->stats.rx_packets++;
1595 skb->dst = NULL;
1596 nf_reset(skb);
1597 netif_rx(skb);
1598 dev_put(reg_dev);
1599 return 0;
1600 drop:
1601 kfree_skb(skb);
1602 return 0; 1577 return 0;
1603} 1578}
1604#endif 1579#endif