1 /* 2 * Stateless NAT actions 3 * 4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 */ 11 12 #include <linux/errno.h> 13 #include <linux/init.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/netfilter.h> 17 #include <linux/rtnetlink.h> 18 #include <linux/skbuff.h> 19 #include <linux/slab.h> 20 #include <linux/spinlock.h> 21 #include <linux/string.h> 22 #include <linux/tc_act/tc_nat.h> 23 #include <net/act_api.h> 24 #include <net/icmp.h> 25 #include <net/ip.h> 26 #include <net/netlink.h> 27 #include <net/tc_act/tc_nat.h> 28 #include <net/tcp.h> 29 #include <net/udp.h> 30 31 32 #define NAT_TAB_MASK 15 33 34 static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { 35 [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, 36 }; 37 38 static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, 39 struct tc_action *a, int ovr, int bind) 40 { 41 struct nlattr *tb[TCA_NAT_MAX + 1]; 42 struct tc_nat *parm; 43 int ret = 0, err; 44 struct tcf_nat *p; 45 46 if (nla == NULL) 47 return -EINVAL; 48 49 err = nla_parse_nested(tb, TCA_NAT_MAX, nla, nat_policy); 50 if (err < 0) 51 return err; 52 53 if (tb[TCA_NAT_PARMS] == NULL) 54 return -EINVAL; 55 parm = nla_data(tb[TCA_NAT_PARMS]); 56 57 if (!tcf_hash_check(parm->index, a, bind)) { 58 ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); 59 if (ret) 60 return ret; 61 ret = ACT_P_CREATED; 62 } else { 63 if (bind) 64 return 0; 65 tcf_hash_release(a, bind); 66 if (!ovr) 67 return -EEXIST; 68 } 69 p = to_tcf_nat(a); 70 71 spin_lock_bh(&p->tcf_lock); 72 p->old_addr = parm->old_addr; 73 p->new_addr = parm->new_addr; 74 p->mask = parm->mask; 75 p->flags = parm->flags; 76 77 p->tcf_action = parm->action; 78 spin_unlock_bh(&p->tcf_lock); 79 80 if (ret == ACT_P_CREATED) 81 tcf_hash_insert(a); 82 83 return ret; 84 } 85 86 static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, 87 struct tcf_result *res) 88 { 89 struct tcf_nat *p = a->priv; 90 struct iphdr *iph; 91 __be32 old_addr; 92 __be32 new_addr; 93 __be32 mask; 94 __be32 addr; 95 int egress; 96 int action; 97 int ihl; 98 int noff; 99 100 spin_lock(&p->tcf_lock); 101 102 p->tcf_tm.lastuse = jiffies; 103 old_addr = p->old_addr; 104 new_addr = p->new_addr; 105 mask = p->mask; 106 egress = p->flags & TCA_NAT_FLAG_EGRESS; 107 action = p->tcf_action; 108 109 bstats_update(&p->tcf_bstats, skb); 110 111 spin_unlock(&p->tcf_lock); 112 113 if (unlikely(action == TC_ACT_SHOT)) 114 goto drop; 115 116 noff = skb_network_offset(skb); 117 if (!pskb_may_pull(skb, sizeof(*iph) + noff)) 118 goto drop; 119 120 iph = ip_hdr(skb); 121 122 if (egress) 123 addr = iph->saddr; 124 else 125 addr = iph->daddr; 126 127 if (!((old_addr ^ addr) & mask)) { 128 if (skb_cloned(skb) && 129 !skb_clone_writable(skb, sizeof(*iph) + noff) && 130 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 131 goto drop; 132 133 new_addr &= mask; 134 new_addr |= addr & ~mask; 135 136 /* Rewrite IP header */ 137 iph = ip_hdr(skb); 138 if (egress) 139 iph->saddr = new_addr; 140 else 141 iph->daddr = new_addr; 142 143 csum_replace4(&iph->check, addr, new_addr); 144 } else if ((iph->frag_off & htons(IP_OFFSET)) || 145 iph->protocol != IPPROTO_ICMP) { 146 goto out; 147 } 148 149 ihl = iph->ihl * 4; 150 151 /* It would be nice to share code with stateful NAT. */ 152 switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) { 153 case IPPROTO_TCP: 154 { 155 struct tcphdr *tcph; 156 157 if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) || 158 (skb_cloned(skb) && 159 !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) && 160 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 161 goto drop; 162 163 tcph = (void *)(skb_network_header(skb) + ihl); 164 inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, 1); 165 break; 166 } 167 case IPPROTO_UDP: 168 { 169 struct udphdr *udph; 170 171 if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) || 172 (skb_cloned(skb) && 173 !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) && 174 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 175 goto drop; 176 177 udph = (void *)(skb_network_header(skb) + ihl); 178 if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { 179 inet_proto_csum_replace4(&udph->check, skb, addr, 180 new_addr, 1); 181 if (!udph->check) 182 udph->check = CSUM_MANGLED_0; 183 } 184 break; 185 } 186 case IPPROTO_ICMP: 187 { 188 struct icmphdr *icmph; 189 190 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff)) 191 goto drop; 192 193 icmph = (void *)(skb_network_header(skb) + ihl); 194 195 if ((icmph->type != ICMP_DEST_UNREACH) && 196 (icmph->type != ICMP_TIME_EXCEEDED) && 197 (icmph->type != ICMP_PARAMETERPROB)) 198 break; 199 200 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) + 201 noff)) 202 goto drop; 203 204 icmph = (void *)(skb_network_header(skb) + ihl); 205 iph = (void *)(icmph + 1); 206 if (egress) 207 addr = iph->daddr; 208 else 209 addr = iph->saddr; 210 211 if ((old_addr ^ addr) & mask) 212 break; 213 214 if (skb_cloned(skb) && 215 !skb_clone_writable(skb, ihl + sizeof(*icmph) + 216 sizeof(*iph) + noff) && 217 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 218 goto drop; 219 220 icmph = (void *)(skb_network_header(skb) + ihl); 221 iph = (void *)(icmph + 1); 222 223 new_addr &= mask; 224 new_addr |= addr & ~mask; 225 226 /* XXX Fix up the inner checksums. */ 227 if (egress) 228 iph->daddr = new_addr; 229 else 230 iph->saddr = new_addr; 231 232 inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr, 233 0); 234 break; 235 } 236 default: 237 break; 238 } 239 240 out: 241 return action; 242 243 drop: 244 spin_lock(&p->tcf_lock); 245 p->tcf_qstats.drops++; 246 spin_unlock(&p->tcf_lock); 247 return TC_ACT_SHOT; 248 } 249 250 static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, 251 int bind, int ref) 252 { 253 unsigned char *b = skb_tail_pointer(skb); 254 struct tcf_nat *p = a->priv; 255 struct tc_nat opt = { 256 .old_addr = p->old_addr, 257 .new_addr = p->new_addr, 258 .mask = p->mask, 259 .flags = p->flags, 260 261 .index = p->tcf_index, 262 .action = p->tcf_action, 263 .refcnt = p->tcf_refcnt - ref, 264 .bindcnt = p->tcf_bindcnt - bind, 265 }; 266 struct tcf_t t; 267 268 if (nla_put(skb, TCA_NAT_PARMS, sizeof(opt), &opt)) 269 goto nla_put_failure; 270 t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); 271 t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); 272 t.expires = jiffies_to_clock_t(p->tcf_tm.expires); 273 if (nla_put(skb, TCA_NAT_TM, sizeof(t), &t)) 274 goto nla_put_failure; 275 276 return skb->len; 277 278 nla_put_failure: 279 nlmsg_trim(skb, b); 280 return -1; 281 } 282 283 static struct tc_action_ops act_nat_ops = { 284 .kind = "nat", 285 .type = TCA_ACT_NAT, 286 .owner = THIS_MODULE, 287 .act = tcf_nat, 288 .dump = tcf_nat_dump, 289 .init = tcf_nat_init, 290 }; 291 292 MODULE_DESCRIPTION("Stateless NAT actions"); 293 MODULE_LICENSE("GPL"); 294 295 static int __init nat_init_module(void) 296 { 297 return tcf_register_action(&act_nat_ops, NAT_TAB_MASK); 298 } 299 300 static void __exit nat_cleanup_module(void) 301 { 302 tcf_unregister_action(&act_nat_ops); 303 } 304 305 module_init(nat_init_module); 306 module_exit(nat_cleanup_module); 307