00001
00002
00003
00004
00005
00006
#include <linux/config.h>
00007
#include <linux/module.h>
00008
#include <linux/skbuff.h>
00009
#include <linux/ip.h>
00010
#include <linux/udp.h>
00011
#include <linux/icmp.h>
00012
#include <net/icmp.h>
00013
#include <net/ip.h>
00014
#include <net/tcp.h>
00015
#include <net/route.h>
00016
#include <linux/netfilter_ipv4/ip_tables.h>
00017
#include <linux/netfilter_ipv4/ipt_REJECT.h>
00018
00019
#if 0
00020
#define DEBUGP printk
00021
#else
00022 #define DEBUGP(format, args...)
00023
#endif
00024
00025
00026
00027
00028 static void connection_attach(
struct sk_buff *new_skb,
struct nf_ct_info *nfct)
00029 {
00030 void (*attach)(
struct sk_buff *,
struct nf_ct_info *);
00031
00032
00033
if (nfct && (attach =
ip_ct_attach) != NULL)
00034 attach(new_skb, nfct);
00035 }
00036
00037 static inline struct rtable *
route_reverse(
struct sk_buff *skb,
int hook)
00038 {
00039
struct iphdr *iph = skb->
nh.iph;
00040
struct dst_entry *odst;
00041
struct rt_key key = {};
00042
struct rtable *rt;
00043
00044
if (hook !=
NF_IP_FORWARD) {
00045 key.
dst = iph->saddr;
00046
if (hook ==
NF_IP_LOCAL_IN)
00047 key.
src = iph->daddr;
00048 key.
tos = RT_TOS(iph->tos);
00049
00050
if (
ip_route_output_key(&rt, &key) != 0)
00051
return NULL;
00052 }
else {
00053
00054
00055 key.
dst = iph->daddr;
00056
if (
ip_route_output_key(&rt, &key) != 0)
00057
return NULL;
00058
00059 odst = skb->
dst;
00060
if (
ip_route_input(skb, iph->saddr, iph->daddr,
00061 RT_TOS(iph->tos), rt->u.
dst.
dev) != 0) {
00062
dst_release(&rt->u.dst);
00063
return NULL;
00064 }
00065
dst_release(&rt->u.dst);
00066 rt = (
struct rtable *)skb->
dst;
00067 skb->
dst = odst;
00068 }
00069
00070
if (rt->u.dst.error) {
00071
dst_release(&rt->u.dst);
00072 rt = NULL;
00073 }
00074
00075
return rt;
00076 }
00077
00078
00079 static void send_reset(
struct sk_buff *oldskb,
int hook)
00080 {
00081
struct sk_buff *nskb;
00082
struct tcphdr *otcph, *tcph;
00083
struct rtable *rt;
00084
unsigned int otcplen;
00085 u_int16_t tmp_port;
00086 u_int32_t tmp_addr;
00087
int needs_ack;
00088
int hh_len;
00089
00090
00091
if (oldskb->
nh.iph->frag_off & htons(
IP_OFFSET)
00092 || oldskb->
len < (oldskb->
nh.iph->ihl<<2) +
sizeof(
struct tcphdr))
00093 return;
00094
00095 otcph = (
struct tcphdr *)((u_int32_t*)oldskb->
nh.iph + oldskb->
nh.iph->ihl);
00096 otcplen = oldskb->
len - oldskb->
nh.iph->ihl*4;
00097
00098
00099
if (otcph->rst)
00100
return;
00101
00102
00103
if (
tcp_v4_check(otcph, otcplen, oldskb->
nh.iph->saddr,
00104 oldskb->
nh.iph->daddr,
00105
csum_partial((
char *)otcph, otcplen, 0)) != 0)
00106
return;
00107
00108
if ((rt =
route_reverse(oldskb, hook)) == NULL)
00109
return;
00110
00111 hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
00112
00113
00114
00115
00116
00117
00118 nskb =
skb_copy_expand(oldskb, hh_len,
skb_tailroom(oldskb),
00119 GFP_ATOMIC);
00120
if (!nskb) {
00121
dst_release(&rt->u.dst);
00122
return;
00123 }
00124
00125
dst_release(nskb->dst);
00126 nskb->dst = &rt->u.dst;
00127
00128
00129 nf_conntrack_put(nskb->nfct);
00130 nskb->nfct = NULL;
00131 nskb->nfcache = 0;
00132
#ifdef CONFIG_NETFILTER_DEBUG
00133
nskb->nf_debug = 0;
00134
#endif
00135
nskb->nfmark = 0;
00136
00137 tcph = (
struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
00138
00139
00140 tmp_addr = nskb->nh.iph->saddr;
00141 nskb->nh.iph->saddr = nskb->nh.iph->daddr;
00142 nskb->nh.iph->daddr = tmp_addr;
00143 tmp_port = tcph->source;
00144 tcph->source = tcph->dest;
00145 tcph->dest = tmp_port;
00146
00147
00148 tcph->doff =
sizeof(
struct tcphdr)/4;
00149
skb_trim(nskb, nskb->nh.iph->ihl*4 +
sizeof(
struct tcphdr));
00150 nskb->nh.iph->tot_len = htons(nskb->len);
00151
00152
if (tcph->ack) {
00153 needs_ack = 0;
00154 tcph->seq = otcph->ack_seq;
00155 tcph->ack_seq = 0;
00156 }
else {
00157 needs_ack = 1;
00158 tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
00159 + otcplen - (otcph->doff<<2));
00160 tcph->seq = 0;
00161 }
00162
00163
00164 ((u_int8_t *)tcph)[13] = 0;
00165 tcph->rst = 1;
00166 tcph->ack = needs_ack;
00167
00168 tcph->window = 0;
00169 tcph->urg_ptr = 0;
00170
00171
00172 tcph->check = 0;
00173 tcph->check =
tcp_v4_check(tcph,
sizeof(
struct tcphdr),
00174 nskb->nh.iph->saddr,
00175 nskb->nh.iph->daddr,
00176
csum_partial((
char *)tcph,
00177
sizeof(
struct tcphdr), 0));
00178
00179
00180 nskb->nh.iph->ttl =
MAXTTL;
00181
00182 nskb->nh.iph->frag_off = htons(
IP_DF);
00183 nskb->nh.iph->id = 0;
00184
00185
00186 nskb->nh.iph->check = 0;
00187 nskb->nh.iph->check =
ip_fast_csum((
unsigned char *)nskb->nh.iph,
00188 nskb->nh.iph->ihl);
00189
00190
00191
if (nskb->len > nskb->dst->pmtu)
00192
goto free_nskb;
00193
00194
connection_attach(nskb, oldskb->nfct);
00195
00196
NF_HOOK(PF_INET,
NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
00197
ip_finish_output);
00198
return;
00199
00200 free_nskb:
00201
kfree_skb(nskb);
00202 }
00203
00204 static void send_unreach(
struct sk_buff *skb_in,
int code)
00205 {
00206
struct iphdr *iph;
00207
struct udphdr *udph;
00208
struct icmphdr *icmph;
00209
struct sk_buff *nskb;
00210 u32 saddr;
00211 u8 tos;
00212
int hh_len, length;
00213
struct rtable *rt = (
struct rtable*)skb_in->
dst;
00214
unsigned char *data;
00215
00216
if (!rt)
00217
return;
00218
00219
00220
if (!
xrlim_allow(&rt->u.dst, 1*HZ))
00221
return;
00222
00223 iph = skb_in->
nh.iph;
00224
00225
00226
if (skb_in->
pkt_type!=PACKET_HOST)
00227
return;
00228
00229
00230
if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
00231
return;
00232
00233
00234
if (iph->frag_off&htons(
IP_OFFSET))
00235
return;
00236
00237
00238
if (iph->protocol ==
IPPROTO_UDP
00239 && skb_in->
tail-(u8*)iph >=
sizeof(
struct udphdr)) {
00240
int datalen = skb_in->
len - (iph->ihl<<2);
00241 udph = (
struct udphdr *)((
char *)iph + (iph->ihl<<2));
00242
if (udph->check
00243 &&
csum_tcpudp_magic(iph->saddr, iph->daddr,
00244 datalen,
IPPROTO_UDP,
00245
csum_partial((
char *)udph, datalen,
00246 0)) != 0)
00247
return;
00248 }
00249
00250
00251
if (iph->protocol ==
IPPROTO_ICMP
00252 && skb_in->
tail-(u8*)iph >=
sizeof(
struct icmphdr)) {
00253 icmph = (
struct icmphdr *)((
char *)iph + (iph->ihl<<2));
00254
00255
00256
00257
00258
if ((icmph->type < ICMP_TIMESTAMP
00259 && icmph->type != ICMP_ECHOREPLY
00260 && icmph->type != ICMP_ECHO)
00261 || icmph->type > NR_ICMP_TYPES)
00262
return;
00263 }
00264
00265 saddr = iph->daddr;
00266
if (!(rt->rt_flags & RTCF_LOCAL))
00267 saddr = 0;
00268
00269 tos = (iph->tos &
IPTOS_TOS_MASK) |
IPTOS_PREC_INTERNETCONTROL;
00270
00271
if (
ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0))
00272
return;
00273
00274
00275 length = skb_in->
len +
sizeof(
struct iphdr) + sizeof(struct icmphdr);
00276
00277
if (length > rt->u.dst.pmtu)
00278 length = rt->u.dst.pmtu;
00279
if (length > 576)
00280 length = 576;
00281
00282 hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
00283
00284 nskb =
alloc_skb(hh_len+15+length, GFP_ATOMIC);
00285
if (!nskb) {
00286
ip_rt_put(rt);
00287
return;
00288 }
00289
00290 nskb->priority = 0;
00291 nskb->dst = &rt->u.dst;
00292
skb_reserve(nskb, hh_len);
00293
00294
00295 iph = nskb->nh.iph
00296 = (
struct iphdr *)
skb_put(nskb,
sizeof(
struct iphdr));
00297 iph->version=4;
00298 iph->ihl=5;
00299 iph->tos=tos;
00300 iph->tot_len = htons(length);
00301
00302
00303 iph->frag_off = 0;
00304
00305 iph->ttl =
MAXTTL;
00306
ip_select_ident(iph, &rt->u.dst, NULL);
00307 iph->protocol=
IPPROTO_ICMP;
00308 iph->saddr=rt->rt_src;
00309 iph->daddr=rt->rt_dst;
00310 iph->check=0;
00311 iph->check =
ip_fast_csum((
unsigned char *)iph, iph->ihl);
00312
00313
00314 icmph = nskb->h.icmph
00315 = (
struct icmphdr *)
skb_put(nskb,
sizeof(
struct icmphdr));
00316 icmph->type = ICMP_DEST_UNREACH;
00317 icmph->code = code;
00318 icmph->un.gateway = 0;
00319 icmph->checksum = 0;
00320
00321
00322 data =
skb_put(nskb,
00323 length -
sizeof(
struct iphdr) -
sizeof(
struct icmphdr));
00324
00325 memcpy(data, skb_in->
nh.iph,
00326 length -
sizeof(
struct iphdr) -
sizeof(
struct icmphdr));
00327 icmph->checksum =
ip_compute_csum((
unsigned char *)icmph,
00328 length -
sizeof(
struct iphdr));
00329
00330
connection_attach(nskb, skb_in->nfct);
00331
00332
NF_HOOK(PF_INET,
NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
00333
ip_finish_output);
00334 }
00335
00336 static unsigned int reject(
struct sk_buff **pskb,
00337
unsigned int hooknum,
00338
const struct net_device *in,
00339
const struct net_device *out,
00340
const void *targinfo,
00341
void *userinfo)
00342 {
00343
const struct ipt_reject_info *
reject = targinfo;
00344
00345
00346
00347
if ((*pskb)->nh.iph->ihl<<2 !=
sizeof(
struct iphdr))
00348 return
NF_DROP;
00349
00350
00351
00352
00353
switch (
reject->with) {
00354
case IPT_ICMP_NET_UNREACHABLE:
00355
send_unreach(*pskb, ICMP_NET_UNREACH);
00356
break;
00357
case IPT_ICMP_HOST_UNREACHABLE:
00358
send_unreach(*pskb, ICMP_HOST_UNREACH);
00359
break;
00360
case IPT_ICMP_PROT_UNREACHABLE:
00361
send_unreach(*pskb, ICMP_PROT_UNREACH);
00362
break;
00363
case IPT_ICMP_PORT_UNREACHABLE:
00364
send_unreach(*pskb, ICMP_PORT_UNREACH);
00365
break;
00366
case IPT_ICMP_NET_PROHIBITED:
00367
send_unreach(*pskb, ICMP_NET_ANO);
00368
break;
00369
case IPT_ICMP_HOST_PROHIBITED:
00370
send_unreach(*pskb, ICMP_HOST_ANO);
00371
break;
00372
case IPT_ICMP_ADMIN_PROHIBITED:
00373
send_unreach(*pskb, ICMP_PKT_FILTERED);
00374
break;
00375
case IPT_TCP_RESET:
00376
send_reset(*pskb, hooknum);
00377
case IPT_ICMP_ECHOREPLY:
00378
00379
break;
00380 }
00381
00382
return NF_DROP;
00383 }
00384
00385 static int check(
const char *tablename,
00386
const struct ipt_entry *e,
00387
void *targinfo,
00388
unsigned int targinfosize,
00389
unsigned int hook_mask)
00390 {
00391
const struct ipt_reject_info *rejinfo = targinfo;
00392
00393
if (targinfosize != IPT_ALIGN(
sizeof(
struct ipt_reject_info))) {
00394
DEBUGP(
"REJECT: targinfosize %u != 0\n", targinfosize);
00395
return 0;
00396 }
00397
00398
00399
if (strcmp(tablename,
"filter") != 0) {
00400
DEBUGP(
"REJECT: bad table `%s'.\n", tablename);
00401
return 0;
00402 }
00403
if ((hook_mask & ~((1 <<
NF_IP_LOCAL_IN)
00404 | (1 <<
NF_IP_FORWARD)
00405 | (1 <<
NF_IP_LOCAL_OUT))) != 0) {
00406
DEBUGP(
"REJECT: bad hook mask %X\n", hook_mask);
00407
return 0;
00408 }
00409
00410
if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
00411 printk(
"REJECT: ECHOREPLY no longer supported.\n");
00412
return 0;
00413 }
else if (rejinfo->with == IPT_TCP_RESET) {
00414
00415
if (e->ip.proto !=
IPPROTO_TCP
00416 || (e->ip.invflags & IPT_INV_PROTO)) {
00417
DEBUGP(
"REJECT: TCP_RESET illegal for non-tcp\n");
00418
return 0;
00419 }
00420 }
00421
00422
return 1;
00423 }
00424
00425
static struct ipt_target
ipt_reject_reg
00426 = { { NULL, NULL },
"REJECT",
reject,
check, NULL, THIS_MODULE };
00427
00428 static int __init
init(
void)
00429 {
00430
if (
ipt_register_target(&
ipt_reject_reg))
00431
return -EINVAL;
00432
return 0;
00433 }
00434
00435 static void __exit
fini(
void)
00436 {
00437
ipt_unregister_target(&
ipt_reject_reg);
00438 }
00439
00440
module_init(init);
00441
module_exit(fini);
00442
MODULE_LICENSE(
"GPL");