diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-12-16 04:15:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-16 04:15:11 -0500 |
commit | b1879204dda06a92a4ff55b681c99ee185180003 (patch) | |
tree | 3045f326dcff6bb1ca3768803bfc62e98e69c6dc /net/ipv4 | |
parent | c40cf519f0c0f0cb0579d853949ef517a8bb494d (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')
-rw-r--r-- | net/ipv4/ipmr.c | 103 |
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 | /* | 1486 | static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) |
1487 | * Handle IGMP messages of PIMv1 | ||
1488 | */ | ||
1489 | |||
1490 | int 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 | |||
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 | return 0; | 1554 | return 0; |
1547 | } | 1555 | } |
1548 | #endif | 1556 | #endif |
@@ -1551,10 +1559,8 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1551 | static int pim_rcv(struct sk_buff * skb) | 1559 | static 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) + | 1574 | drop: |
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 |