File: /usr/src/linux/net/ipv4/netfilter/ipt_REJECT.c
1 /*
2 * This is a module which is used for rejecting packets.
3 * Added support for customized reject packets (Jozsef Kadlecsik).
4 */
5 #include <linux/config.h>
6 #include <linux/module.h>
7 #include <linux/skbuff.h>
8 #include <linux/ip.h>
9 #include <net/icmp.h>
10 #include <net/ip.h>
11 #include <net/tcp.h>
12 struct in_device;
13 #include <net/route.h>
14 #include <linux/netfilter_ipv4/ip_tables.h>
15 #include <linux/netfilter_ipv4/ipt_REJECT.h>
16
17 #if 0
18 #define DEBUGP printk
19 #else
20 #define DEBUGP(format, args...)
21 #endif
22
23 /* If the original packet is part of a connection, but the connection
24 is not confirmed, our manufactured reply will not be associated
25 with it, so we need to do this manually. */
26 static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
27 {
28 void (*attach)(struct sk_buff *, struct nf_ct_info *);
29
30 /* Avoid module unload race with ip_ct_attach being NULLed out */
31 if (nfct && (attach = ip_ct_attach) != NULL)
32 attach(new_skb, nfct);
33 }
34
35 /* Send RST reply */
36 static void send_reset(struct sk_buff *oldskb, int local)
37 {
38 struct sk_buff *nskb;
39 struct tcphdr *otcph, *tcph;
40 struct rtable *rt;
41 unsigned int otcplen;
42 u_int16_t tmp;
43 int needs_ack;
44
45 /* IP header checks: fragment, too short. */
46 if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
47 || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
48 return;
49
50 otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
51 otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
52
53 /* No RST for RST. */
54 if (otcph->rst)
55 return;
56
57 /* Check checksum. */
58 if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
59 oldskb->nh.iph->daddr,
60 csum_partial((char *)otcph, otcplen, 0)) != 0)
61 return;
62
63 /* Copy skb (even if skb is about to be dropped, we can't just
64 clone it because there may be other things, such as tcpdump,
65 interested in it) */
66 nskb = skb_copy(oldskb, GFP_ATOMIC);
67 if (!nskb)
68 return;
69
70 /* This packet will not be the same as the other: clear nf fields */
71 nf_conntrack_put(nskb->nfct);
72 nskb->nfct = NULL;
73 nskb->nfcache = 0;
74 #ifdef CONFIG_NETFILTER_DEBUG
75 nskb->nf_debug = 0;
76 #endif
77
78 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
79
80 /* Swap source and dest */
81 nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
82 tmp = tcph->source;
83 tcph->source = tcph->dest;
84 tcph->dest = tmp;
85
86 /* Truncate to length (no data) */
87 tcph->doff = sizeof(struct tcphdr)/4;
88 skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
89 nskb->nh.iph->tot_len = htons(nskb->len);
90
91 if (tcph->ack) {
92 needs_ack = 0;
93 tcph->seq = otcph->ack_seq;
94 tcph->ack_seq = 0;
95 } else {
96 needs_ack = 1;
97 tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
98 + otcplen - (otcph->doff<<2));
99 tcph->seq = 0;
100 }
101
102 /* Reset flags */
103 ((u_int8_t *)tcph)[13] = 0;
104 tcph->rst = 1;
105 tcph->ack = needs_ack;
106
107 tcph->window = 0;
108 tcph->urg_ptr = 0;
109
110 /* Adjust TCP checksum */
111 tcph->check = 0;
112 tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
113 nskb->nh.iph->saddr,
114 nskb->nh.iph->daddr,
115 csum_partial((char *)tcph,
116 sizeof(struct tcphdr), 0));
117
118 /* Adjust IP TTL, DF */
119 nskb->nh.iph->ttl = MAXTTL;
120 /* Set DF, id = 0 */
121 nskb->nh.iph->frag_off = htons(IP_DF);
122 nskb->nh.iph->id = 0;
123
124 /* Adjust IP checksum */
125 nskb->nh.iph->check = 0;
126 nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
127 nskb->nh.iph->ihl);
128
129 /* Routing: if not headed for us, route won't like source */
130 if (ip_route_output(&rt, nskb->nh.iph->daddr,
131 local ? nskb->nh.iph->saddr : 0,
132 RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
133 0) != 0)
134 goto free_nskb;
135
136 dst_release(nskb->dst);
137 nskb->dst = &rt->u.dst;
138
139 /* "Never happens" */
140 if (nskb->len > nskb->dst->pmtu)
141 goto free_nskb;
142
143 connection_attach(nskb, oldskb->nfct);
144
145 NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
146 ip_finish_output);
147 return;
148
149 free_nskb:
150 kfree_skb(nskb);
151 }
152
153 static void send_unreach(struct sk_buff *skb_in, int code)
154 {
155 struct iphdr *iph;
156 struct icmphdr *icmph;
157 struct sk_buff *nskb;
158 u32 saddr;
159 u8 tos;
160 int hh_len, length;
161 struct rtable *rt = (struct rtable*)skb_in->dst;
162 unsigned char *data;
163
164 if (!rt)
165 return;
166
167 /* FIXME: Use sysctl number. --RR */
168 if (!xrlim_allow(&rt->u.dst, 1*HZ))
169 return;
170
171 iph = skb_in->nh.iph;
172
173 /* No replies to physical multicast/broadcast */
174 if (skb_in->pkt_type!=PACKET_HOST)
175 return;
176
177 /* Now check at the protocol level */
178 if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
179 return;
180
181 /* Only reply to fragment 0. */
182 if (iph->frag_off&htons(IP_OFFSET))
183 return;
184
185 /* If we send an ICMP error to an ICMP error a mess would result.. */
186 if (iph->protocol == IPPROTO_ICMP
187 && skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) {
188 icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
189 /* Between echo-reply (0) and timestamp (13),
190 everything except echo-request (8) is an error.
191 Also, anything greater than NR_ICMP_TYPES is
192 unknown, and hence should be treated as an error... */
193 if ((icmph->type < ICMP_TIMESTAMP
194 && icmph->type != ICMP_ECHOREPLY
195 && icmph->type != ICMP_ECHO)
196 || icmph->type > NR_ICMP_TYPES)
197 return;
198 }
199
200 saddr = iph->daddr;
201 if (!(rt->rt_flags & RTCF_LOCAL))
202 saddr = 0;
203
204 tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL;
205
206 if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0))
207 return;
208
209 /* RFC says return as much as we can without exceeding 576 bytes. */
210 length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr);
211
212 if (length > rt->u.dst.pmtu)
213 length = rt->u.dst.pmtu;
214 if (length > 576)
215 length = 576;
216
217 hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
218
219 nskb = alloc_skb(hh_len+15+length, GFP_ATOMIC);
220 if (!nskb) {
221 ip_rt_put(rt);
222 return;
223 }
224
225 nskb->priority = 0;
226 nskb->dst = &rt->u.dst;
227 skb_reserve(nskb, hh_len);
228
229 /* Set up IP header */
230 iph = nskb->nh.iph
231 = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
232 iph->version=4;
233 iph->ihl=5;
234 iph->tos=tos;
235 iph->tot_len = htons(length);
236
237 /* This abbreviates icmp->send->ip_build_xmit->ip_dont_fragment */
238 if (!ipv4_config.no_pmtu_disc
239 && !(rt->u.dst.mxlock&(1<<RTAX_MTU)))
240 iph->frag_off = htons(IP_DF);
241 else iph->frag_off = 0;
242
243 iph->ttl = MAXTTL;
244 ip_select_ident(iph, &rt->u.dst, NULL);
245 iph->protocol=IPPROTO_ICMP;
246 iph->saddr=rt->rt_src;
247 iph->daddr=rt->rt_dst;
248 iph->check=0;
249 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
250
251 /* Set up ICMP header. */
252 icmph = nskb->h.icmph
253 = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
254 icmph->type = ICMP_DEST_UNREACH;
255 icmph->code = code;
256 icmph->un.gateway = 0;
257 icmph->checksum = 0;
258
259 /* Copy as much of original packet as will fit */
260 data = skb_put(nskb,
261 length - sizeof(struct iphdr) - sizeof(struct icmphdr));
262 /* FIXME: won't work with nonlinear skbs --RR */
263 memcpy(data, skb_in->nh.iph,
264 length - sizeof(struct iphdr) - sizeof(struct icmphdr));
265 icmph->checksum = ip_compute_csum((unsigned char *)icmph,
266 length - sizeof(struct iphdr));
267
268 connection_attach(nskb, skb_in->nfct);
269
270 NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
271 ip_finish_output);
272 }
273
274 static unsigned int reject(struct sk_buff **pskb,
275 unsigned int hooknum,
276 const struct net_device *in,
277 const struct net_device *out,
278 const void *targinfo,
279 void *userinfo)
280 {
281 const struct ipt_reject_info *reject = targinfo;
282
283 /* Our naive response construction doesn't deal with IP
284 options, and probably shouldn't try. */
285 if ((*pskb)->nh.iph->ihl<<2 != sizeof(struct iphdr))
286 return NF_DROP;
287
288 /* WARNING: This code causes reentry within iptables.
289 This means that the iptables jump stack is now crap. We
290 must return an absolute verdict. --RR */
291 switch (reject->with) {
292 case IPT_ICMP_NET_UNREACHABLE:
293 send_unreach(*pskb, ICMP_NET_UNREACH);
294 break;
295 case IPT_ICMP_HOST_UNREACHABLE:
296 send_unreach(*pskb, ICMP_HOST_UNREACH);
297 break;
298 case IPT_ICMP_PROT_UNREACHABLE:
299 send_unreach(*pskb, ICMP_PROT_UNREACH);
300 break;
301 case IPT_ICMP_PORT_UNREACHABLE:
302 send_unreach(*pskb, ICMP_PORT_UNREACH);
303 break;
304 case IPT_ICMP_NET_PROHIBITED:
305 send_unreach(*pskb, ICMP_NET_ANO);
306 break;
307 case IPT_ICMP_HOST_PROHIBITED:
308 send_unreach(*pskb, ICMP_HOST_ANO);
309 break;
310 case IPT_TCP_RESET:
311 send_reset(*pskb, hooknum == NF_IP_LOCAL_IN);
312 case IPT_ICMP_ECHOREPLY:
313 /* Doesn't happen. */
314 break;
315 }
316
317 return NF_DROP;
318 }
319
320 static int check(const char *tablename,
321 const struct ipt_entry *e,
322 void *targinfo,
323 unsigned int targinfosize,
324 unsigned int hook_mask)
325 {
326 const struct ipt_reject_info *rejinfo = targinfo;
327
328 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_icmp))) {
329 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
330 return 0;
331 }
332
333 /* Only allow these for packet filtering. */
334 if (strcmp(tablename, "filter") != 0) {
335 DEBUGP("REJECT: bad table `%s'.\n", tablename);
336 return 0;
337 }
338 if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
339 | (1 << NF_IP_FORWARD)
340 | (1 << NF_IP_LOCAL_OUT))) != 0) {
341 DEBUGP("REJECT: bad hook mask %X\n", hook_mask);
342 return 0;
343 }
344
345 if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
346 printk("REJECT: ECHOREPLY no longer supported.\n");
347 return 0;
348 } else if (rejinfo->with == IPT_TCP_RESET) {
349 /* Must specify that it's a TCP packet */
350 if (e->ip.proto != IPPROTO_TCP
351 || (e->ip.invflags & IPT_INV_PROTO)) {
352 DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
353 return 0;
354 }
355 }
356
357 return 1;
358 }
359
360 static struct ipt_target ipt_reject_reg
361 = { { NULL, NULL }, "REJECT", reject, check, NULL, THIS_MODULE };
362
363 static int __init init(void)
364 {
365 if (ipt_register_target(&ipt_reject_reg))
366 return -EINVAL;
367 return 0;
368 }
369
370 static void __exit fini(void)
371 {
372 ipt_unregister_target(&ipt_reject_reg);
373 }
374
375 module_init(init);
376 module_exit(fini);
377