u_int16_t tmp_port;
u_int32_t tmp_addr;
int needs_ack;
+ int hh_len;
/* IP header checks: fragment, too short. */
if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
csum_partial((char *)otcph, otcplen, 0)) != 0)
return;
+
+ {
+ struct flowi fl = { .nl_u = { .ip4_u =
+ { .daddr = oldskb->nh.iph->saddr,
+ .saddr = (local ?
+ oldskb->nh.iph->daddr :
+ 0),
+ .tos = (RT_TOS(oldskb->nh.iph->tos) |
+ RTO_CONN) } } };
+
+ /* Routing: if not headed for us, route won't like source */
+ if (ip_route_output_key(&rt, &fl))
+ return;
+
+ hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+ }
+
+
/* Copy skb (even if skb is about to be dropped, we can't just
clone it because there may be other things, such as tcpdump,
- interested in it) */
- nskb = skb_copy(oldskb, GFP_ATOMIC);
+ interested in it). We also need to expand headroom in case
+ hh_len of incoming interface < hh_len of outgoing interface */
+ nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb),
+ GFP_ATOMIC);
if (!nskb)
return;
+ dst_release(nskb->dst);
+ nskb->dst = &rt->u.dst;
+
/* This packet will not be the same as the other: clear nf fields */
nf_conntrack_put(nskb->nfct);
nskb->nfct = NULL;
nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
nskb->nh.iph->ihl);
- {
- struct flowi fl = { .nl_u = { .ip4_u =
- { .daddr = nskb->nh.iph->daddr,
- .saddr = (local ?
- nskb->nh.iph->saddr :
- 0),
- .tos = (RT_TOS(nskb->nh.iph->tos) |
- RTO_CONN) } } };
-
- /* Routing: if not headed for us, route won't like source */
- if (ip_route_output_key(&rt, &fl))
- goto free_nskb;
- }
-
- dst_release(nskb->dst);
- nskb->dst = &rt->u.dst;
-
/* "Never happens" */
if (nskb->len > dst_pmtu(nskb->dst))
goto free_nskb;