1/* 2 * This is a module which is used for rejecting packets. 3 */ 4 5/* (C) 1999-2001 Paul `Rusty' Russell 6 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/module.h> 14#include <linux/skbuff.h> 15#include <linux/ip.h> 16#include <linux/udp.h> 17#include <linux/icmp.h> 18#include <net/icmp.h> 19#include <net/ip.h> 20#include <net/tcp.h> 21#include <net/route.h> 22#include <net/dst.h> 23#include <linux/netfilter/x_tables.h> 24#include <linux/netfilter_ipv4/ip_tables.h> 25#include <linux/netfilter_ipv4/ipt_REJECT.h> 26#ifdef CONFIG_BRIDGE_NETFILTER 27#include <linux/netfilter_bridge.h> 28#endif 29 30MODULE_LICENSE("GPL"); 31MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 32MODULE_DESCRIPTION("iptables REJECT target module"); 33 34#define DEBUGP(format, args...) 35 36/* Send RST reply */ 37static void send_reset(struct sk_buff *oldskb, int hook) 38{ 39 struct sk_buff *nskb; 40 struct iphdr *niph; 41 struct tcphdr _otcph, *oth, *tcph; 42 __be16 tmp_port; 43 __be32 tmp_addr; 44 int needs_ack; 45 unsigned int addr_type; 46 47 /* IP header checks: fragment. */ 48 if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) 49 return; 50 51 oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), 52 sizeof(_otcph), &_otcph); 53 if (oth == NULL) 54 return; 55 56 /* No RST for RST. */ 57 if (oth->rst) 58 return; 59 60 /* Check checksum */ 61 if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) 62 return; 63 64 /* We need a linear, writeable skb. We also need to expand 65 headroom in case hh_len of incoming interface < hh_len of 66 outgoing interface */ 67 nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb), 68 GFP_ATOMIC); 69 if (!nskb) 70 return; 71 72 /* This packet will not be the same as the other: clear nf fields */ 73 nf_reset(nskb); 74 nskb->mark = 0; 75 skb_init_secmark(nskb); 76 77 skb_shinfo(nskb)->gso_size = 0; 78 skb_shinfo(nskb)->gso_segs = 0; 79 skb_shinfo(nskb)->gso_type = 0; 80 81 tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb)); 82 83 /* Swap source and dest */ 84 niph = ip_hdr(nskb); 85 tmp_addr = niph->saddr; 86 niph->saddr = niph->daddr; 87 niph->daddr = tmp_addr; 88 tmp_port = tcph->source; 89 tcph->source = tcph->dest; 90 tcph->dest = tmp_port; 91 92 /* Truncate to length (no data) */ 93 tcph->doff = sizeof(struct tcphdr)/4; 94 skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr)); 95 niph->tot_len = htons(nskb->len); 96 97 if (tcph->ack) { 98 needs_ack = 0; 99 tcph->seq = oth->ack_seq; 100 tcph->ack_seq = 0; 101 } else { 102 needs_ack = 1; 103 tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + 104 oldskb->len - ip_hdrlen(oldskb) - 105 (oth->doff << 2)); 106 tcph->seq = 0; 107 } 108 109 /* Reset flags */ 110 ((u_int8_t *)tcph)[13] = 0; 111 tcph->rst = 1; 112 tcph->ack = needs_ack; 113 114 tcph->window = 0; 115 tcph->urg_ptr = 0; 116 117 /* Adjust TCP checksum */ 118 tcph->check = 0; 119 tcph->check = tcp_v4_check(sizeof(struct tcphdr), 120 niph->saddr, niph->daddr, 121 csum_partial((char *)tcph, 122 sizeof(struct tcphdr), 0)); 123 124 /* Set DF, id = 0 */ 125 niph->frag_off = htons(IP_DF); 126 niph->id = 0; 127 128 addr_type = RTN_UNSPEC; 129 if (hook != NF_IP_FORWARD 130#ifdef CONFIG_BRIDGE_NETFILTER 131 || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) 132#endif 133 ) 134 addr_type = RTN_LOCAL; 135 136 if (ip_route_me_harder(&nskb, addr_type)) 137 goto free_nskb; 138 139 nskb->ip_summed = CHECKSUM_NONE; 140 141 /* Adjust IP TTL */ 142 niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); 143 144 /* Adjust IP checksum */ 145 niph->check = 0; 146 niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl); 147 148 /* "Never happens" */ 149 if (nskb->len > dst_mtu(nskb->dst)) 150 goto free_nskb; 151 152 nf_ct_attach(nskb, oldskb); 153 154 NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, 155 dst_output); 156 return; 157 158 free_nskb: 159 kfree_skb(nskb); 160} 161 162static inline void send_unreach(struct sk_buff *skb_in, int code) 163{ 164 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); 165} 166 167static unsigned int reject(struct sk_buff **pskb, 168 const struct net_device *in, 169 const struct net_device *out, 170 unsigned int hooknum, 171 const struct xt_target *target, 172 const void *targinfo) 173{ 174 const struct ipt_reject_info *reject = targinfo; 175 176 /* Our naive response construction doesn't deal with IP 177 options, and probably shouldn't try. */ 178 if (ip_hdrlen(*pskb) != sizeof(struct iphdr)) 179 return NF_DROP; 180 181 /* WARNING: This code causes reentry within iptables. 182 This means that the iptables jump stack is now crap. We 183 must return an absolute verdict. --RR */ 184 switch (reject->with) { 185 case IPT_ICMP_NET_UNREACHABLE: 186 send_unreach(*pskb, ICMP_NET_UNREACH); 187 break; 188 case IPT_ICMP_HOST_UNREACHABLE: 189 send_unreach(*pskb, ICMP_HOST_UNREACH); 190 break; 191 case IPT_ICMP_PROT_UNREACHABLE: 192 send_unreach(*pskb, ICMP_PROT_UNREACH); 193 break; 194 case IPT_ICMP_PORT_UNREACHABLE: 195 send_unreach(*pskb, ICMP_PORT_UNREACH); 196 break; 197 case IPT_ICMP_NET_PROHIBITED: 198 send_unreach(*pskb, ICMP_NET_ANO); 199 break; 200 case IPT_ICMP_HOST_PROHIBITED: 201 send_unreach(*pskb, ICMP_HOST_ANO); 202 break; 203 case IPT_ICMP_ADMIN_PROHIBITED: 204 send_unreach(*pskb, ICMP_PKT_FILTERED); 205 break; 206 case IPT_TCP_RESET: 207 send_reset(*pskb, hooknum); 208 case IPT_ICMP_ECHOREPLY: 209 /* Doesn't happen. */ 210 break; 211 } 212 213 return NF_DROP; 214} 215 216static int check(const char *tablename, 217 const void *e_void, 218 const struct xt_target *target, 219 void *targinfo, 220 unsigned int hook_mask) 221{ 222 const struct ipt_reject_info *rejinfo = targinfo; 223 const struct ipt_entry *e = e_void; 224 225 if (rejinfo->with == IPT_ICMP_ECHOREPLY) { 226 printk("REJECT: ECHOREPLY no longer supported.\n"); 227 return 0; 228 } else if (rejinfo->with == IPT_TCP_RESET) { 229 /* Must specify that it's a TCP packet */ 230 if (e->ip.proto != IPPROTO_TCP 231 || (e->ip.invflags & XT_INV_PROTO)) { 232 DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n"); 233 return 0; 234 } 235 } 236 return 1; 237} 238 239static struct xt_target ipt_reject_reg = { 240 .name = "REJECT", 241 .family = AF_INET, 242 .target = reject, 243 .targetsize = sizeof(struct ipt_reject_info), 244 .table = "filter", 245 .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | 246 (1 << NF_IP_LOCAL_OUT), 247 .checkentry = check, 248 .me = THIS_MODULE, 249}; 250 251static int __init ipt_reject_init(void) 252{ 253 return xt_register_target(&ipt_reject_reg); 254} 255 256static void __exit ipt_reject_fini(void) 257{ 258 xt_unregister_target(&ipt_reject_reg); 259} 260 261module_init(ipt_reject_init); 262module_exit(ipt_reject_fini); 263