Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Stateless NAT actions
0004  *
0005  * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
0006  */
0007 
0008 #include <linux/errno.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/netfilter.h>
0013 #include <linux/rtnetlink.h>
0014 #include <linux/skbuff.h>
0015 #include <linux/slab.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/string.h>
0018 #include <linux/tc_act/tc_nat.h>
0019 #include <net/act_api.h>
0020 #include <net/pkt_cls.h>
0021 #include <net/icmp.h>
0022 #include <net/ip.h>
0023 #include <net/netlink.h>
0024 #include <net/tc_act/tc_nat.h>
0025 #include <net/tcp.h>
0026 #include <net/udp.h>
0027 
0028 
0029 static unsigned int nat_net_id;
0030 static struct tc_action_ops act_nat_ops;
0031 
0032 static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
0033     [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
0034 };
0035 
0036 static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
0037             struct tc_action **a, struct tcf_proto *tp,
0038             u32 flags, struct netlink_ext_ack *extack)
0039 {
0040     struct tc_action_net *tn = net_generic(net, nat_net_id);
0041     bool bind = flags & TCA_ACT_FLAGS_BIND;
0042     struct nlattr *tb[TCA_NAT_MAX + 1];
0043     struct tcf_chain *goto_ch = NULL;
0044     struct tc_nat *parm;
0045     int ret = 0, err;
0046     struct tcf_nat *p;
0047     u32 index;
0048 
0049     if (nla == NULL)
0050         return -EINVAL;
0051 
0052     err = nla_parse_nested_deprecated(tb, TCA_NAT_MAX, nla, nat_policy,
0053                       NULL);
0054     if (err < 0)
0055         return err;
0056 
0057     if (tb[TCA_NAT_PARMS] == NULL)
0058         return -EINVAL;
0059     parm = nla_data(tb[TCA_NAT_PARMS]);
0060     index = parm->index;
0061     err = tcf_idr_check_alloc(tn, &index, a, bind);
0062     if (!err) {
0063         ret = tcf_idr_create(tn, index, est, a,
0064                      &act_nat_ops, bind, false, flags);
0065         if (ret) {
0066             tcf_idr_cleanup(tn, index);
0067             return ret;
0068         }
0069         ret = ACT_P_CREATED;
0070     } else if (err > 0) {
0071         if (bind)
0072             return 0;
0073         if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
0074             tcf_idr_release(*a, bind);
0075             return -EEXIST;
0076         }
0077     } else {
0078         return err;
0079     }
0080     err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
0081     if (err < 0)
0082         goto release_idr;
0083     p = to_tcf_nat(*a);
0084 
0085     spin_lock_bh(&p->tcf_lock);
0086     p->old_addr = parm->old_addr;
0087     p->new_addr = parm->new_addr;
0088     p->mask = parm->mask;
0089     p->flags = parm->flags;
0090 
0091     goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
0092     spin_unlock_bh(&p->tcf_lock);
0093     if (goto_ch)
0094         tcf_chain_put_by_act(goto_ch);
0095 
0096     return ret;
0097 release_idr:
0098     tcf_idr_release(*a, bind);
0099     return err;
0100 }
0101 
0102 static int tcf_nat_act(struct sk_buff *skb, const struct tc_action *a,
0103                struct tcf_result *res)
0104 {
0105     struct tcf_nat *p = to_tcf_nat(a);
0106     struct iphdr *iph;
0107     __be32 old_addr;
0108     __be32 new_addr;
0109     __be32 mask;
0110     __be32 addr;
0111     int egress;
0112     int action;
0113     int ihl;
0114     int noff;
0115 
0116     spin_lock(&p->tcf_lock);
0117 
0118     tcf_lastuse_update(&p->tcf_tm);
0119     old_addr = p->old_addr;
0120     new_addr = p->new_addr;
0121     mask = p->mask;
0122     egress = p->flags & TCA_NAT_FLAG_EGRESS;
0123     action = p->tcf_action;
0124 
0125     bstats_update(&p->tcf_bstats, skb);
0126 
0127     spin_unlock(&p->tcf_lock);
0128 
0129     if (unlikely(action == TC_ACT_SHOT))
0130         goto drop;
0131 
0132     noff = skb_network_offset(skb);
0133     if (!pskb_may_pull(skb, sizeof(*iph) + noff))
0134         goto drop;
0135 
0136     iph = ip_hdr(skb);
0137 
0138     if (egress)
0139         addr = iph->saddr;
0140     else
0141         addr = iph->daddr;
0142 
0143     if (!((old_addr ^ addr) & mask)) {
0144         if (skb_try_make_writable(skb, sizeof(*iph) + noff))
0145             goto drop;
0146 
0147         new_addr &= mask;
0148         new_addr |= addr & ~mask;
0149 
0150         /* Rewrite IP header */
0151         iph = ip_hdr(skb);
0152         if (egress)
0153             iph->saddr = new_addr;
0154         else
0155             iph->daddr = new_addr;
0156 
0157         csum_replace4(&iph->check, addr, new_addr);
0158     } else if ((iph->frag_off & htons(IP_OFFSET)) ||
0159            iph->protocol != IPPROTO_ICMP) {
0160         goto out;
0161     }
0162 
0163     ihl = iph->ihl * 4;
0164 
0165     /* It would be nice to share code with stateful NAT. */
0166     switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) {
0167     case IPPROTO_TCP:
0168     {
0169         struct tcphdr *tcph;
0170 
0171         if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
0172             skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff))
0173             goto drop;
0174 
0175         tcph = (void *)(skb_network_header(skb) + ihl);
0176         inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr,
0177                      true);
0178         break;
0179     }
0180     case IPPROTO_UDP:
0181     {
0182         struct udphdr *udph;
0183 
0184         if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
0185             skb_try_make_writable(skb, ihl + sizeof(*udph) + noff))
0186             goto drop;
0187 
0188         udph = (void *)(skb_network_header(skb) + ihl);
0189         if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
0190             inet_proto_csum_replace4(&udph->check, skb, addr,
0191                          new_addr, true);
0192             if (!udph->check)
0193                 udph->check = CSUM_MANGLED_0;
0194         }
0195         break;
0196     }
0197     case IPPROTO_ICMP:
0198     {
0199         struct icmphdr *icmph;
0200 
0201         if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff))
0202             goto drop;
0203 
0204         icmph = (void *)(skb_network_header(skb) + ihl);
0205 
0206         if (!icmp_is_err(icmph->type))
0207             break;
0208 
0209         if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) +
0210                     noff))
0211             goto drop;
0212 
0213         icmph = (void *)(skb_network_header(skb) + ihl);
0214         iph = (void *)(icmph + 1);
0215         if (egress)
0216             addr = iph->daddr;
0217         else
0218             addr = iph->saddr;
0219 
0220         if ((old_addr ^ addr) & mask)
0221             break;
0222 
0223         if (skb_try_make_writable(skb, ihl + sizeof(*icmph) +
0224                       sizeof(*iph) + noff))
0225             goto drop;
0226 
0227         icmph = (void *)(skb_network_header(skb) + ihl);
0228         iph = (void *)(icmph + 1);
0229 
0230         new_addr &= mask;
0231         new_addr |= addr & ~mask;
0232 
0233         /* XXX Fix up the inner checksums. */
0234         if (egress)
0235             iph->daddr = new_addr;
0236         else
0237             iph->saddr = new_addr;
0238 
0239         inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr,
0240                      false);
0241         break;
0242     }
0243     default:
0244         break;
0245     }
0246 
0247 out:
0248     return action;
0249 
0250 drop:
0251     spin_lock(&p->tcf_lock);
0252     p->tcf_qstats.drops++;
0253     spin_unlock(&p->tcf_lock);
0254     return TC_ACT_SHOT;
0255 }
0256 
0257 static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
0258             int bind, int ref)
0259 {
0260     unsigned char *b = skb_tail_pointer(skb);
0261     struct tcf_nat *p = to_tcf_nat(a);
0262     struct tc_nat opt = {
0263         .index    = p->tcf_index,
0264         .refcnt   = refcount_read(&p->tcf_refcnt) - ref,
0265         .bindcnt  = atomic_read(&p->tcf_bindcnt) - bind,
0266     };
0267     struct tcf_t t;
0268 
0269     spin_lock_bh(&p->tcf_lock);
0270     opt.old_addr = p->old_addr;
0271     opt.new_addr = p->new_addr;
0272     opt.mask = p->mask;
0273     opt.flags = p->flags;
0274     opt.action = p->tcf_action;
0275 
0276     if (nla_put(skb, TCA_NAT_PARMS, sizeof(opt), &opt))
0277         goto nla_put_failure;
0278 
0279     tcf_tm_dump(&t, &p->tcf_tm);
0280     if (nla_put_64bit(skb, TCA_NAT_TM, sizeof(t), &t, TCA_NAT_PAD))
0281         goto nla_put_failure;
0282     spin_unlock_bh(&p->tcf_lock);
0283 
0284     return skb->len;
0285 
0286 nla_put_failure:
0287     spin_unlock_bh(&p->tcf_lock);
0288     nlmsg_trim(skb, b);
0289     return -1;
0290 }
0291 
0292 static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
0293               struct netlink_callback *cb, int type,
0294               const struct tc_action_ops *ops,
0295               struct netlink_ext_ack *extack)
0296 {
0297     struct tc_action_net *tn = net_generic(net, nat_net_id);
0298 
0299     return tcf_generic_walker(tn, skb, cb, type, ops, extack);
0300 }
0301 
0302 static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
0303 {
0304     struct tc_action_net *tn = net_generic(net, nat_net_id);
0305 
0306     return tcf_idr_search(tn, a, index);
0307 }
0308 
0309 static struct tc_action_ops act_nat_ops = {
0310     .kind       =   "nat",
0311     .id     =   TCA_ID_NAT,
0312     .owner      =   THIS_MODULE,
0313     .act        =   tcf_nat_act,
0314     .dump       =   tcf_nat_dump,
0315     .init       =   tcf_nat_init,
0316     .walk       =   tcf_nat_walker,
0317     .lookup     =   tcf_nat_search,
0318     .size       =   sizeof(struct tcf_nat),
0319 };
0320 
0321 static __net_init int nat_init_net(struct net *net)
0322 {
0323     struct tc_action_net *tn = net_generic(net, nat_net_id);
0324 
0325     return tc_action_net_init(net, tn, &act_nat_ops);
0326 }
0327 
0328 static void __net_exit nat_exit_net(struct list_head *net_list)
0329 {
0330     tc_action_net_exit(net_list, nat_net_id);
0331 }
0332 
0333 static struct pernet_operations nat_net_ops = {
0334     .init = nat_init_net,
0335     .exit_batch = nat_exit_net,
0336     .id   = &nat_net_id,
0337     .size = sizeof(struct tc_action_net),
0338 };
0339 
0340 MODULE_DESCRIPTION("Stateless NAT actions");
0341 MODULE_LICENSE("GPL");
0342 
0343 static int __init nat_init_module(void)
0344 {
0345     return tcf_register_action(&act_nat_ops, &nat_net_ops);
0346 }
0347 
0348 static void __exit nat_cleanup_module(void)
0349 {
0350     tcf_unregister_action(&act_nat_ops, &nat_net_ops);
0351 }
0352 
0353 module_init(nat_init_module);
0354 module_exit(nat_cleanup_module);