Commit b1879204dda06a92a4ff55b681c99ee185180003
Committed by
David S. Miller
1 parent
c40cf519f0
Exists in
master
and in
7 other branches
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
net/ipv4/ipmr.c
... | ... | @@ -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 |