aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-03-15 22:44:28 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2005-03-15 22:44:28 -0800
commit2c7ec2528b5776bd64a7c1240879087198e57da9 (patch)
tree9e1e1e4a97e2dee6b9ae90e6d3dd01b28a141b04
parentdbbd405f9c50f09367b854118f075971896e0062 (diff)
downloadhistory-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.c35
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c141
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,