Commit b1879204dda06a92a4ff55b681c99ee185180003

Authored by Ilpo Järvinen
Committed by David S. Miller
1 parent c40cf519f0

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>

Showing 1 changed file with 39 additions and 64 deletions Side-by-side Diff

... ... @@ -1482,29 +1482,13 @@
1482 1482 return 0;
1483 1483 }
1484 1484  
1485   -#ifdef CONFIG_IP_PIMSM_V1
1486   -/*
1487   - * Handle IGMP messages of PIMv1
1488   - */
1489   -
1490   -int pim_rcv_v1(struct sk_buff * skb)
  1485 +#ifdef CONFIG_IP_PIMSM
  1486 +static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
1491 1487 {
1492   - struct igmphdr *pim;
1493   - struct iphdr *encap;
1494   - struct net_device *reg_dev = NULL;
  1488 + struct net_device *reg_dev = NULL;
  1489 + struct iphdr *encap;
1495 1490  
1496   - if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
1497   - goto drop;
1498   -
1499   - pim = igmp_hdr(skb);
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));
  1491 + encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
1508 1492 /*
1509 1493 Check that:
1510 1494 a. packet is really destinted to a multicast group
... ... @@ -1513,8 +1497,8 @@
1513 1497 */
1514 1498 if (!ipv4_is_multicast(encap->daddr) ||
1515 1499 encap->tot_len == 0 ||
1516   - ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
1517   - goto drop;
  1500 + ntohs(encap->tot_len) + pimlen > skb->len)
  1501 + return 1;
1518 1502  
1519 1503 read_lock(&mrt_lock);
1520 1504 if (reg_vif_num >= 0)
... ... @@ -1524,7 +1508,7 @@
1524 1508 read_unlock(&mrt_lock);
1525 1509  
1526 1510 if (reg_dev == NULL)
1527   - goto drop;
  1511 + return 1;
1528 1512  
1529 1513 skb->mac_header = skb->network_header;
1530 1514 skb_pull(skb, (u8*)encap - skb->data);
1531 1515  
... ... @@ -1540,9 +1524,33 @@
1540 1524 nf_reset(skb);
1541 1525 netif_rx(skb);
1542 1526 dev_put(reg_dev);
  1527 +
1543 1528 return 0;
1544   - drop:
1545   - kfree_skb(skb);
  1529 +}
  1530 +#endif
  1531 +
  1532 +#ifdef CONFIG_IP_PIMSM_V1
  1533 +/*
  1534 + * Handle IGMP messages of PIMv1
  1535 + */
  1536 +
  1537 +int 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))) {
  1551 +drop:
  1552 + kfree_skb(skb);
  1553 + }
1546 1554 return 0;
1547 1555 }
1548 1556 #endif
1549 1557  
... ... @@ -1551,10 +1559,8 @@
1551 1559 static int pim_rcv(struct sk_buff * skb)
1552 1560 {
1553 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 1564 goto drop;
1559 1565  
1560 1566 pim = (struct pimreghdr *)skb_transport_header(skb);
... ... @@ -1564,41 +1570,10 @@
1564 1570 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
1565 1571 goto drop;
1566 1572  
1567   - /* check if the inner packet is destined to mcast group */
1568   - encap = (struct iphdr *)(skb_transport_header(skb) +
1569   - sizeof(struct pimreghdr));
1570   - if (!ipv4_is_multicast(encap->daddr) ||
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);
  1573 + if (__pim_rcv(skb, sizeof(*pim))) {
  1574 +drop:
  1575 + kfree_skb(skb);
  1576 + }
1602 1577 return 0;
1603 1578 }
1604 1579 #endif