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>
This commit is contained in:
parent
c40cf519f0
commit
b1879204dd
|
@ -1482,29 +1482,13 @@ dont_forward:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IP_PIMSM_V1
|
#ifdef CONFIG_IP_PIMSM
|
||||||
/*
|
static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
|
||||||
* Handle IGMP messages of PIMv1
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pim_rcv_v1(struct sk_buff * skb)
|
|
||||||
{
|
{
|
||||||
struct igmphdr *pim;
|
|
||||||
struct iphdr *encap;
|
|
||||||
struct net_device *reg_dev = NULL;
|
struct net_device *reg_dev = NULL;
|
||||||
|
struct iphdr *encap;
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
|
encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
|
||||||
goto drop;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
encap = (struct iphdr *)(skb_transport_header(skb) +
|
|
||||||
sizeof(struct igmphdr));
|
|
||||||
/*
|
/*
|
||||||
Check that:
|
Check that:
|
||||||
a. packet is really destinted to a multicast group
|
a. packet is really destinted to a multicast group
|
||||||
|
@ -1513,8 +1497,8 @@ int pim_rcv_v1(struct sk_buff * skb)
|
||||||
*/
|
*/
|
||||||
if (!ipv4_is_multicast(encap->daddr) ||
|
if (!ipv4_is_multicast(encap->daddr) ||
|
||||||
encap->tot_len == 0 ||
|
encap->tot_len == 0 ||
|
||||||
ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
|
ntohs(encap->tot_len) + pimlen > skb->len)
|
||||||
goto drop;
|
return 1;
|
||||||
|
|
||||||
read_lock(&mrt_lock);
|
read_lock(&mrt_lock);
|
||||||
if (reg_vif_num >= 0)
|
if (reg_vif_num >= 0)
|
||||||
|
@ -1524,7 +1508,7 @@ int pim_rcv_v1(struct sk_buff * skb)
|
||||||
read_unlock(&mrt_lock);
|
read_unlock(&mrt_lock);
|
||||||
|
|
||||||
if (reg_dev == NULL)
|
if (reg_dev == NULL)
|
||||||
goto drop;
|
return 1;
|
||||||
|
|
||||||
skb->mac_header = skb->network_header;
|
skb->mac_header = skb->network_header;
|
||||||
skb_pull(skb, (u8*)encap - skb->data);
|
skb_pull(skb, (u8*)encap - skb->data);
|
||||||
|
@ -1540,9 +1524,33 @@ int pim_rcv_v1(struct sk_buff * skb)
|
||||||
nf_reset(skb);
|
nf_reset(skb);
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
dev_put(reg_dev);
|
dev_put(reg_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
drop:
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_IP_PIMSM_V1
|
||||||
|
/*
|
||||||
|
* Handle IGMP messages of PIMv1
|
||||||
|
*/
|
||||||
|
|
||||||
|
int pim_rcv_v1(struct sk_buff * skb)
|
||||||
|
{
|
||||||
|
struct igmphdr *pim;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
pim = igmp_hdr(skb);
|
||||||
|
|
||||||
|
if (!mroute_do_pim ||
|
||||||
|
pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
if (__pim_rcv(skb, sizeof(*pim))) {
|
||||||
|
drop:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1551,10 +1559,8 @@ int pim_rcv_v1(struct sk_buff * skb)
|
||||||
static int pim_rcv(struct sk_buff * skb)
|
static int pim_rcv(struct sk_buff * skb)
|
||||||
{
|
{
|
||||||
struct pimreghdr *pim;
|
struct pimreghdr *pim;
|
||||||
struct iphdr *encap;
|
|
||||||
struct net_device *reg_dev = NULL;
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
|
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
pim = (struct pimreghdr *)skb_transport_header(skb);
|
pim = (struct pimreghdr *)skb_transport_header(skb);
|
||||||
|
@ -1564,41 +1570,10 @@ static int pim_rcv(struct sk_buff * skb)
|
||||||
csum_fold(skb_checksum(skb, 0, skb->len, 0))))
|
csum_fold(skb_checksum(skb, 0, skb->len, 0))))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
/* check if the inner packet is destined to mcast group */
|
if (__pim_rcv(skb, sizeof(*pim))) {
|
||||||
encap = (struct iphdr *)(skb_transport_header(skb) +
|
drop:
|
||||||
sizeof(struct pimreghdr));
|
|
||||||
if (!ipv4_is_multicast(encap->daddr) ||
|
|
||||||
encap->tot_len == 0 ||
|
|
||||||
ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
read_lock(&mrt_lock);
|
|
||||||
if (reg_vif_num >= 0)
|
|
||||||
reg_dev = vif_table[reg_vif_num].dev;
|
|
||||||
if (reg_dev)
|
|
||||||
dev_hold(reg_dev);
|
|
||||||
read_unlock(&mrt_lock);
|
|
||||||
|
|
||||||
if (reg_dev == NULL)
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
skb->mac_header = skb->network_header;
|
|
||||||
skb_pull(skb, (u8*)encap - skb->data);
|
|
||||||
skb_reset_network_header(skb);
|
|
||||||
skb->dev = reg_dev;
|
|
||||||
skb->protocol = htons(ETH_P_IP);
|
|
||||||
skb->ip_summed = 0;
|
|
||||||
skb->pkt_type = PACKET_HOST;
|
|
||||||
dst_release(skb->dst);
|
|
||||||
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);
|
|
||||||
return 0;
|
|
||||||
drop:
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue