diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2005-03-15 22:44:28 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-03-15 22:44:28 -0800 |
commit | 2c7ec2528b5776bd64a7c1240879087198e57da9 (patch) | |
tree | 9e1e1e4a97e2dee6b9ae90e6d3dd01b28a141b04 | |
parent | dbbd405f9c50f09367b854118f075971896e0062 (diff) | |
download | history-2c7ec2528b5776bd64a7c1240879087198e57da9.tar.gz |
[IPV4]: Make ipt_REJECT use icmp_send again.
As it is ipt_REJECT doesn't work at all with IPsec. Despite my efforts
previously in making the policy lookups work there I neglected to change
the final call to dst_output so the policy lookup is useless.
ipt_REJECT also had a number of deviations from icmp_send which seems to
be unjustified. For examples it ignored source routing IP options.
There was a bug in icmp_send too :) It didn't set the ICMP type/code
values for the policy lookup.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/icmp.c | 35 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 141 |
2 files changed, 22 insertions, 154 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 004a1502ffffd..85bf0d3e294b2 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -518,14 +518,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) IPTOS_PREC_INTERNETCONTROL) : iph->tos; - { - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr, - .saddr = saddr, - .tos = RT_TOS(tos) } }, - .proto = IPPROTO_ICMP }; - if (ip_route_output_key(&rt, &fl)) - goto out_unlock; - } if (ip_options_echo(&icmp_param.replyopts, skb_in)) goto ende; @@ -544,13 +536,26 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) inet_sk(icmp_socket->sk)->tos = tos; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; - if (icmp_param.replyopts.srr) { - struct flowi fl = { .nl_u = { .ip4_u = - { .daddr = icmp_param.replyopts.faddr, - .saddr = saddr, - .tos = RT_TOS(tos) } }, - .proto = IPPROTO_ICMP }; - ip_rt_put(rt); + + { + struct flowi fl = { + .nl_u = { + .ip4_u = { + .daddr = icmp_param.replyopts.srr ? + icmp_param.replyopts.faddr : + iph->saddr, + .saddr = saddr, + .tos = RT_TOS(tos) + } + }, + .proto = IPPROTO_ICMP, + .uli_u = { + .icmpt = { + .type = type, + .code = code + } + } + }; if (ip_route_output_key(&rt, &fl)) goto out_unlock; } diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index f1cbefb9a6e63..f38cc6379c7b0 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -220,146 +220,9 @@ static void send_reset(struct sk_buff *oldskb, int hook) kfree_skb(nskb); } -static void send_unreach(struct sk_buff *skb_in, int code) +static inline void send_unreach(struct sk_buff *skb_in, int code) { - struct iphdr *iph; - struct icmphdr *icmph; - struct sk_buff *nskb; - u32 saddr; - u8 tos; - int hh_len, length; - struct rtable *rt = (struct rtable*)skb_in->dst; - unsigned char *data; - - if (!rt) - return; - - /* FIXME: Use sysctl number. --RR */ - if (!xrlim_allow(&rt->u.dst, 1*HZ)) - return; - - iph = skb_in->nh.iph; - - /* No replies to physical multicast/broadcast */ - if (skb_in->pkt_type!=PACKET_HOST) - return; - - /* Now check at the protocol level */ - if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST)) - return; - - /* Only reply to fragment 0. */ - if (iph->frag_off&htons(IP_OFFSET)) - return; - - /* If we send an ICMP error to an ICMP error a mess would result.. */ - if (iph->protocol == IPPROTO_ICMP) { - struct icmphdr ihdr; - - icmph = skb_header_pointer(skb_in, skb_in->nh.iph->ihl*4, - sizeof(ihdr), &ihdr); - if (!icmph) - return; - - /* Between echo-reply (0) and timestamp (13), - everything except echo-request (8) is an error. - Also, anything greater than NR_ICMP_TYPES is - unknown, and hence should be treated as an error... */ - if ((icmph->type < ICMP_TIMESTAMP - && icmph->type != ICMP_ECHOREPLY - && icmph->type != ICMP_ECHO) - || icmph->type > NR_ICMP_TYPES) - return; - } - - saddr = iph->daddr; - if (!(rt->rt_flags & RTCF_LOCAL)) - saddr = 0; - - tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL; - - { - struct flowi fl = { - .nl_u = { - .ip4_u = { - .daddr = skb_in->nh.iph->saddr, - .saddr = saddr, - .tos = RT_TOS(tos) - } - }, - .proto = IPPROTO_ICMP, - .uli_u = { - .icmpt = { - .type = ICMP_DEST_UNREACH, - .code = code - } - } - }; - - if (ip_route_output_key(&rt, &fl)) - return; - } - /* RFC says return as much as we can without exceeding 576 bytes. */ - length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr); - - if (length > dst_pmtu(&rt->u.dst)) - length = dst_pmtu(&rt->u.dst); - if (length > 576) - length = 576; - - hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); - - nskb = alloc_skb(hh_len + length, GFP_ATOMIC); - if (!nskb) { - ip_rt_put(rt); - return; - } - - nskb->priority = 0; - nskb->dst = &rt->u.dst; - skb_reserve(nskb, hh_len); - - /* Set up IP header */ - iph = nskb->nh.iph - = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); - iph->version=4; - iph->ihl=5; - iph->tos=tos; - iph->tot_len = htons(length); - - /* PMTU discovery never applies to ICMP packets. */ - iph->frag_off = 0; - - iph->ttl = MAXTTL; - ip_select_ident(iph, &rt->u.dst, NULL); - iph->protocol=IPPROTO_ICMP; - iph->saddr=rt->rt_src; - iph->daddr=rt->rt_dst; - iph->check=0; - iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); - - /* Set up ICMP header. */ - icmph = nskb->h.icmph - = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); - icmph->type = ICMP_DEST_UNREACH; - icmph->code = code; - icmph->un.gateway = 0; - icmph->checksum = 0; - - /* Copy as much of original packet as will fit */ - data = skb_put(nskb, - length - sizeof(struct iphdr) - sizeof(struct icmphdr)); - - skb_copy_bits(skb_in, 0, data, - length - sizeof(struct iphdr) - sizeof(struct icmphdr)); - - icmph->checksum = ip_compute_csum((unsigned char *)icmph, - length - sizeof(struct iphdr)); - - nf_ct_attach(nskb, skb_in); - - NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, - ip_finish_output); + icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); } static unsigned int reject(struct sk_buff **pskb, |