git://git.onelab.eu
/
sliver-openvswitch.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
b4181ae
)
Pull data into headers properly, and checksum ICMP replies correctly.
author
Ben Pfaff
<blp@nicira.com>
Wed, 12 Nov 2008 22:42:51 +0000
(14:42 -0800)
committer
Ben Pfaff
<blp@nicira.com>
Thu, 13 Nov 2008 20:45:38 +0000
(12:45 -0800)
datapath/nx_act_snat.c
patch
|
blob
|
history
diff --git
a/datapath/nx_act_snat.c
b/datapath/nx_act_snat.c
index
e577c9d
..
2d0306a
100644
(file)
--- a/
datapath/nx_act_snat.c
+++ b/
datapath/nx_act_snat.c
@@
-235,29
+235,28
@@
handle_icmp_snat(struct sk_buff *skb)
{
struct net_bridge_port *p = skb->dev->br_port;
struct ethhdr *eh;
{
struct net_bridge_port *p = skb->dev->br_port;
struct ethhdr *eh;
- struct iphdr *iph
= ip_hdr(skb)
;
+ struct iphdr *iph;
struct icmphdr *icmph;
struct icmphdr *icmph;
- unsigned int datalen;
uint8_t tmp_eth[ETH_ALEN];
uint32_t tmp_ip;
struct sk_buff *nskb;
/* We're only interested in addresses we rewrite. */
uint8_t tmp_eth[ETH_ALEN];
uint32_t tmp_ip;
struct sk_buff *nskb;
/* We're only interested in addresses we rewrite. */
+ iph = ip_hdr(skb);
if (!snat_this_address(p, iph->daddr)) {
return 0;
}
if (!snat_this_address(p, iph->daddr)) {
return 0;
}
- icmph = (struct icmphdr *) ((u_int32_t *)iph + iph->ihl);
- datalen = skb->len - iph->ihl * 4;
-
/* Drop fragments and packets not long enough to hold the ICMP
* header. */
/* Drop fragments and packets not long enough to hold the ICMP
* header. */
- if (((ntohs(iph->frag_off) & IP_OFFSET) != 0) || datalen < 4)
+ if ((ntohs(iph->frag_off) & IP_OFFSET) != 0 ||
+ !pskb_may_pull(skb, skb_transport_offset(skb) + 4))
return 0;
/* We only respond to echo requests to our address. Continue
* processing replies and other ICMP messages since they may be
* intended for NAT'd hosts. */
return 0;
/* We only respond to echo requests to our address. Continue
* processing replies and other ICMP messages since they may be
* intended for NAT'd hosts. */
+ icmph = icmp_hdr(skb);
if (icmph->type != ICMP_ECHO)
return 0;
if (icmph->type != ICMP_ECHO)
return 0;
@@
-269,19
+268,31
@@
handle_icmp_snat(struct sk_buff *skb)
return -1;
}
return -1;
}
+ /* Update Ethernet header. */
eh = eth_hdr(nskb);
eh = eth_hdr(nskb);
- iph = ip_hdr(nskb);
- icmph = (struct icmphdr *) ((u_int32_t *)iph + iph->ihl);
+ memcpy(tmp_eth, eh->h_dest, ETH_ALEN);
+ memcpy(eh->h_dest, eh->h_source, ETH_ALEN);
+ memcpy(eh->h_source, tmp_eth, ETH_ALEN);
+ /* Update IP header.
+ * This is kind of busted, at least in that it doesn't check that the
+ * echoed IP options make sense. */
+ iph = ip_hdr(nskb);
+ iph->id = 0;
+ iph->frag_off = 0;
+ iph->ttl = IPDEFTTL;
+ iph->check = 0;
tmp_ip = iph->daddr;
iph->daddr = iph->saddr;
iph->saddr = tmp_ip;
tmp_ip = iph->daddr;
iph->daddr = iph->saddr;
iph->saddr = tmp_ip;
+ iph->check = ip_fast_csum(iph, iph->ihl);
- memcpy(tmp_eth, eh->h_dest, ETH_ALEN);
- memcpy(eh->h_dest, eh->h_source, ETH_ALEN);
- memcpy(eh->h_source, tmp_eth, ETH_ALEN);
-
+ /* Update ICMP header. */
+ icmph = icmp_hdr(nskb);
icmph->type = ICMP_ECHOREPLY;
icmph->type = ICMP_ECHOREPLY;
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum(icmph,
+ nskb->tail - nskb->transport_header);
dp_xmit_skb_push(nskb);
dp_xmit_skb_push(nskb);
@@
-303,6
+314,7
@@
snat_pre_route(struct sk_buff *skb)
struct iphdr *iph;
int len;
struct iphdr *iph;
int len;
+ WARN_ON_ONCE(skb_network_offset(skb));
if (skb->protocol == htons(ETH_P_ARP))
return handle_arp_snat(skb);
else if (skb->protocol != htons(ETH_P_IP))
if (skb->protocol == htons(ETH_P_ARP))
return handle_arp_snat(skb);
else if (skb->protocol != htons(ETH_P_IP))
@@
-315,14
+327,17
@@
snat_pre_route(struct sk_buff *skb)
if (iph->ihl < 5 || iph->version != 4)
goto ipv4_error;
if (iph->ihl < 5 || iph->version != 4)
goto ipv4_error;
- if (!pskb_may_pull(skb, ip
h->ihl*4
))
+ if (!pskb_may_pull(skb, ip
_hdrlen(skb)
))
goto ipv4_error;
goto ipv4_error;
+ skb_set_transport_header(skb, ip_hdrlen(skb));
/* Check if we need to echo reply for this address */
/* Check if we need to echo reply for this address */
+ iph = ip_hdr(skb);
if ((iph->protocol == IPPROTO_ICMP) && (handle_icmp_snat(skb)))
return -1;
if ((iph->protocol == IPPROTO_ICMP) && (handle_icmp_snat(skb)))
return -1;
- if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+ iph = ip_hdr(skb);
+ if (unlikely(ip_fast_csum(iph, iph->ihl)))
goto ipv4_error;
len = ntohs(iph->tot_len);
goto ipv4_error;
len = ntohs(iph->tot_len);