Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 78827
b: refs/heads/master
c: 9ba99b0
h: refs/heads/master
i:
  78825: 102621c
  78823: a67bb5d
v: v3
  • Loading branch information
Denys Vlasenko authored and David S. Miller committed Jan 28, 2008
1 parent b8d8353 commit 3e87894
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 66 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 022748a9357c4c1a0113ec1ce5612f383b80156f
refs/heads/master: 9ba99b0d3f45d0aedeafce1cfa4f720b19d04477
102 changes: 37 additions & 65 deletions trunk/net/ipv4/netfilter/ipt_REJECT.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,8 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
static void send_reset(struct sk_buff *oldskb, int hook)
{
struct sk_buff *nskb;
struct iphdr *niph;
struct iphdr *oiph, *niph;
struct tcphdr _otcph, *oth, *tcph;
__be16 tmp_port;
__be32 tmp_addr;
int needs_ack;
unsigned int addr_type;

/* IP header checks: fragment. */
Expand All @@ -58,69 +55,47 @@ static void send_reset(struct sk_buff *oldskb, int hook)
/* Check checksum */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
return;
oiph = ip_hdr(oldskb);

/* We need a linear, writeable skb. We also need to expand
headroom in case hh_len of incoming interface < hh_len of
outgoing interface */
nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb),
GFP_ATOMIC);
nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
LL_MAX_HEADER, GFP_ATOMIC);
if (!nskb)
return;

/* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb);
nskb->mark = 0;
skb_init_secmark(nskb);

skb_shinfo(nskb)->gso_size = 0;
skb_shinfo(nskb)->gso_segs = 0;
skb_shinfo(nskb)->gso_type = 0;

tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));

/* Swap source and dest */
niph = ip_hdr(nskb);
tmp_addr = niph->saddr;
niph->saddr = niph->daddr;
niph->daddr = tmp_addr;
tmp_port = tcph->source;
tcph->source = tcph->dest;
tcph->dest = tmp_port;

/* Truncate to length (no data) */
tcph->doff = sizeof(struct tcphdr)/4;
skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));

if (tcph->ack) {
needs_ack = 0;
skb_reserve(nskb, LL_MAX_HEADER);

skb_reset_network_header(nskb);
niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
niph->version = 4;
niph->ihl = sizeof(struct iphdr) / 4;
niph->tos = 0;
niph->id = 0;
niph->frag_off = htons(IP_DF);
niph->protocol = IPPROTO_TCP;
niph->check = 0;
niph->saddr = oiph->daddr;
niph->daddr = oiph->saddr;

tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;

if (oth->ack)
tcph->seq = oth->ack_seq;
tcph->ack_seq = 0;
} else {
needs_ack = 1;
else {
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
oldskb->len - ip_hdrlen(oldskb) -
(oth->doff << 2));
tcph->seq = 0;
tcph->ack = 1;
}

/* Reset flags */
((u_int8_t *)tcph)[13] = 0;
tcph->rst = 1;
tcph->ack = needs_ack;

tcph->window = 0;
tcph->urg_ptr = 0;

/* Adjust TCP checksum */
tcph->check = 0;
tcph->check = tcp_v4_check(sizeof(struct tcphdr),
niph->saddr, niph->daddr,
csum_partial(tcph,
sizeof(struct tcphdr), 0));

/* Set DF, id = 0 */
niph->frag_off = htons(IP_DF);
niph->id = 0;
tcph->rst = 1;
tcph->check = tcp_v4_check(sizeof(struct tcphdr),
niph->saddr, niph->daddr,
csum_partial(tcph,
sizeof(struct tcphdr), 0));

addr_type = RTN_UNSPEC;
if (hook != NF_INET_FORWARD
Expand All @@ -130,14 +105,16 @@ static void send_reset(struct sk_buff *oldskb, int hook)
)
addr_type = RTN_LOCAL;

/* ip_route_me_harder expects skb->dst to be set */
dst_hold(oldskb->dst);
nskb->dst = oldskb->dst;

if (ip_route_me_harder(nskb, addr_type))
goto free_nskb;

niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
nskb->ip_summed = CHECKSUM_NONE;

/* Adjust IP TTL */
niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);

/* "Never happens" */
if (nskb->len > dst_mtu(nskb->dst))
goto free_nskb;
Expand All @@ -163,11 +140,6 @@ reject_tg(struct sk_buff *skb, const struct net_device *in,
{
const struct ipt_reject_info *reject = targinfo;

/* Our naive response construction doesn't deal with IP
options, and probably shouldn't try. */
if (ip_hdrlen(skb) != sizeof(struct iphdr))
return NF_DROP;

/* WARNING: This code causes reentry within iptables.
This means that the iptables jump stack is now crap. We
must return an absolute verdict. --RR */
Expand Down

0 comments on commit 3e87894

Please sign in to comment.