aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipmr.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2008-12-16 04:15:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 04:15:11 -0500
commitb1879204dda06a92a4ff55b681c99ee185180003 (patch)
tree3045f326dcff6bb1ca3768803bfc62e98e69c6dc /net/ipv4/ipmr.c
parentc40cf519f0c0f0cb0579d853949ef517a8bb494d (diff)
ipmr: merge common code
Also removes redundant skb->len < x check which can't be true once pskb_may_pull(skb, x) succeeded. $ diff-funcs pim_rcv ipmr.c ipmr.c pim_rcv_v1 --- ipmr.c:pim_rcv() +++ ipmr.c:pim_rcv_v1() @@ -1,22 +1,27 @@ -static int pim_rcv(struct sk_buff * skb) +int pim_rcv_v1(struct sk_buff * skb) { - struct pimreghdr *pim; + struct igmphdr *pim; struct iphdr *encap; struct net_device *reg_dev = NULL; if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) goto drop; - pim = (struct pimreghdr *)skb_transport_header(skb); - if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) || - (pim->flags&PIM_NULL_REGISTER) || - (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && - csum_fold(skb_checksum(skb, 0, skb->len, 0)))) + pim = igmp_hdr(skb); + + if (!mroute_do_pim || + skb->len < sizeof(*pim) + sizeof(*encap) || + pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) goto drop; - /* check if the inner packet is destined to mcast group */ encap = (struct iphdr *)(skb_transport_header(skb) + - sizeof(struct pimreghdr)); + sizeof(struct igmphdr)); + /* + Check that: + a. packet is really destinted to a multicast group + b. packet is not a NULL-REGISTER + c. packet is not truncated + */ if (!ipv4_is_multicast(encap->daddr) || encap->tot_len == 0 || ntohs(encap->tot_len) + sizeof(*pim) > skb->len) @@ -40,9 +45,9 @@ skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; dst_release(skb->dst); + skb->dst = NULL; reg_dev->stats.rx_bytes += skb->len; reg_dev->stats.rx_packets++; - skb->dst = NULL; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); $ codiff net/ipv4/ipmr.o.old net/ipv4/ipmr.o.new net/ipv4/ipmr.c: pim_rcv_v1 | -283 pim_rcv | -284 2 functions changed, 567 bytes removed net/ipv4/ipmr.c: __pim_rcv | +307 1 function changed, 307 bytes added net/ipv4/ipmr.o.new: 3 functions changed, 307 bytes added, 567 bytes removed, diff: -260 (Tested on x86_64). It seems that pimlen arg could be left out as well and eq-sizedness of structs trapped with BUILD_BUG_ON but I don't think that's more than a cosmetic flaw since there aren't that many args anyway. Compile tested. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipmr.c')
-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