0001
0002
0003
0004
0005
0006 #include <linux/init.h>
0007 #include <linux/module.h>
0008 #include <linux/kernel.h>
0009 #include <linux/skbuff.h>
0010 #include <linux/atomic.h>
0011 #include <linux/refcount.h>
0012 #include <linux/netlink.h>
0013 #include <linux/rculist.h>
0014 #include <linux/slab.h>
0015 #include <linux/types.h>
0016 #include <linux/errno.h>
0017 #include <net/netlink.h>
0018 #include <net/sock.h>
0019 #include <net/netns/generic.h>
0020
0021 #include <linux/netfilter.h>
0022 #include <linux/netfilter/nfnetlink.h>
0023 #include <linux/netfilter/nfnetlink_acct.h>
0024
0025 MODULE_LICENSE("GPL");
0026 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
0027 MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure");
0028
0029 struct nf_acct {
0030 atomic64_t pkts;
0031 atomic64_t bytes;
0032 unsigned long flags;
0033 struct list_head head;
0034 refcount_t refcnt;
0035 char name[NFACCT_NAME_MAX];
0036 struct rcu_head rcu_head;
0037 char data[];
0038 };
0039
0040 struct nfacct_filter {
0041 u32 value;
0042 u32 mask;
0043 };
0044
0045 struct nfnl_acct_net {
0046 struct list_head nfnl_acct_list;
0047 };
0048
0049 static unsigned int nfnl_acct_net_id __read_mostly;
0050
0051 static inline struct nfnl_acct_net *nfnl_acct_pernet(struct net *net)
0052 {
0053 return net_generic(net, nfnl_acct_net_id);
0054 }
0055
0056 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
0057 #define NFACCT_OVERQUOTA_BIT 2
0058
0059 static int nfnl_acct_new(struct sk_buff *skb, const struct nfnl_info *info,
0060 const struct nlattr * const tb[])
0061 {
0062 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
0063 struct nf_acct *nfacct, *matching = NULL;
0064 unsigned int size = 0;
0065 char *acct_name;
0066 u32 flags = 0;
0067
0068 if (!tb[NFACCT_NAME])
0069 return -EINVAL;
0070
0071 acct_name = nla_data(tb[NFACCT_NAME]);
0072 if (strlen(acct_name) == 0)
0073 return -EINVAL;
0074
0075 list_for_each_entry(nfacct, &nfnl_acct_net->nfnl_acct_list, head) {
0076 if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
0077 continue;
0078
0079 if (info->nlh->nlmsg_flags & NLM_F_EXCL)
0080 return -EEXIST;
0081
0082 matching = nfacct;
0083 break;
0084 }
0085
0086 if (matching) {
0087 if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
0088
0089 atomic64_set(&matching->pkts, 0);
0090 atomic64_set(&matching->bytes, 0);
0091 smp_mb__before_atomic();
0092
0093 if ((matching->flags & NFACCT_F_QUOTA))
0094 clear_bit(NFACCT_OVERQUOTA_BIT,
0095 &matching->flags);
0096 return 0;
0097 }
0098 return -EBUSY;
0099 }
0100
0101 if (tb[NFACCT_FLAGS]) {
0102 flags = ntohl(nla_get_be32(tb[NFACCT_FLAGS]));
0103 if (flags & ~NFACCT_F_QUOTA)
0104 return -EOPNOTSUPP;
0105 if ((flags & NFACCT_F_QUOTA) == NFACCT_F_QUOTA)
0106 return -EINVAL;
0107 if (flags & NFACCT_F_OVERQUOTA)
0108 return -EINVAL;
0109 if ((flags & NFACCT_F_QUOTA) && !tb[NFACCT_QUOTA])
0110 return -EINVAL;
0111
0112 size += sizeof(u64);
0113 }
0114
0115 nfacct = kzalloc(sizeof(struct nf_acct) + size, GFP_KERNEL);
0116 if (nfacct == NULL)
0117 return -ENOMEM;
0118
0119 if (flags & NFACCT_F_QUOTA) {
0120 u64 *quota = (u64 *)nfacct->data;
0121
0122 *quota = be64_to_cpu(nla_get_be64(tb[NFACCT_QUOTA]));
0123 nfacct->flags = flags;
0124 }
0125
0126 nla_strscpy(nfacct->name, tb[NFACCT_NAME], NFACCT_NAME_MAX);
0127
0128 if (tb[NFACCT_BYTES]) {
0129 atomic64_set(&nfacct->bytes,
0130 be64_to_cpu(nla_get_be64(tb[NFACCT_BYTES])));
0131 }
0132 if (tb[NFACCT_PKTS]) {
0133 atomic64_set(&nfacct->pkts,
0134 be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
0135 }
0136 refcount_set(&nfacct->refcnt, 1);
0137 list_add_tail_rcu(&nfacct->head, &nfnl_acct_net->nfnl_acct_list);
0138 return 0;
0139 }
0140
0141 static int
0142 nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
0143 int event, struct nf_acct *acct)
0144 {
0145 struct nlmsghdr *nlh;
0146 unsigned int flags = portid ? NLM_F_MULTI : 0;
0147 u64 pkts, bytes;
0148 u32 old_flags;
0149
0150 event = nfnl_msg_type(NFNL_SUBSYS_ACCT, event);
0151 nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
0152 NFNETLINK_V0, 0);
0153 if (!nlh)
0154 goto nlmsg_failure;
0155
0156 if (nla_put_string(skb, NFACCT_NAME, acct->name))
0157 goto nla_put_failure;
0158
0159 old_flags = acct->flags;
0160 if (type == NFNL_MSG_ACCT_GET_CTRZERO) {
0161 pkts = atomic64_xchg(&acct->pkts, 0);
0162 bytes = atomic64_xchg(&acct->bytes, 0);
0163 smp_mb__before_atomic();
0164 if (acct->flags & NFACCT_F_QUOTA)
0165 clear_bit(NFACCT_OVERQUOTA_BIT, &acct->flags);
0166 } else {
0167 pkts = atomic64_read(&acct->pkts);
0168 bytes = atomic64_read(&acct->bytes);
0169 }
0170 if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts),
0171 NFACCT_PAD) ||
0172 nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes),
0173 NFACCT_PAD) ||
0174 nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt))))
0175 goto nla_put_failure;
0176 if (acct->flags & NFACCT_F_QUOTA) {
0177 u64 *quota = (u64 *)acct->data;
0178
0179 if (nla_put_be32(skb, NFACCT_FLAGS, htonl(old_flags)) ||
0180 nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota),
0181 NFACCT_PAD))
0182 goto nla_put_failure;
0183 }
0184 nlmsg_end(skb, nlh);
0185 return skb->len;
0186
0187 nlmsg_failure:
0188 nla_put_failure:
0189 nlmsg_cancel(skb, nlh);
0190 return -1;
0191 }
0192
0193 static int
0194 nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
0195 {
0196 struct net *net = sock_net(skb->sk);
0197 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
0198 struct nf_acct *cur, *last;
0199 const struct nfacct_filter *filter = cb->data;
0200
0201 if (cb->args[2])
0202 return 0;
0203
0204 last = (struct nf_acct *)cb->args[1];
0205 if (cb->args[1])
0206 cb->args[1] = 0;
0207
0208 rcu_read_lock();
0209 list_for_each_entry_rcu(cur, &nfnl_acct_net->nfnl_acct_list, head) {
0210 if (last) {
0211 if (cur != last)
0212 continue;
0213
0214 last = NULL;
0215 }
0216
0217 if (filter && (cur->flags & filter->mask) != filter->value)
0218 continue;
0219
0220 if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid,
0221 cb->nlh->nlmsg_seq,
0222 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
0223 NFNL_MSG_ACCT_NEW, cur) < 0) {
0224 cb->args[1] = (unsigned long)cur;
0225 break;
0226 }
0227 }
0228 if (!cb->args[1])
0229 cb->args[2] = 1;
0230 rcu_read_unlock();
0231 return skb->len;
0232 }
0233
0234 static int nfnl_acct_done(struct netlink_callback *cb)
0235 {
0236 kfree(cb->data);
0237 return 0;
0238 }
0239
0240 static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = {
0241 [NFACCT_FILTER_MASK] = { .type = NLA_U32 },
0242 [NFACCT_FILTER_VALUE] = { .type = NLA_U32 },
0243 };
0244
0245 static int nfnl_acct_start(struct netlink_callback *cb)
0246 {
0247 const struct nlattr *const attr = cb->data;
0248 struct nlattr *tb[NFACCT_FILTER_MAX + 1];
0249 struct nfacct_filter *filter;
0250 int err;
0251
0252 if (!attr)
0253 return 0;
0254
0255 err = nla_parse_nested_deprecated(tb, NFACCT_FILTER_MAX, attr,
0256 filter_policy, NULL);
0257 if (err < 0)
0258 return err;
0259
0260 if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
0261 return -EINVAL;
0262
0263 filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
0264 if (!filter)
0265 return -ENOMEM;
0266
0267 filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
0268 filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
0269 cb->data = filter;
0270
0271 return 0;
0272 }
0273
0274 static int nfnl_acct_get(struct sk_buff *skb, const struct nfnl_info *info,
0275 const struct nlattr * const tb[])
0276 {
0277 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
0278 int ret = -ENOENT;
0279 struct nf_acct *cur;
0280 char *acct_name;
0281
0282 if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
0283 struct netlink_dump_control c = {
0284 .dump = nfnl_acct_dump,
0285 .start = nfnl_acct_start,
0286 .done = nfnl_acct_done,
0287 .data = (void *)tb[NFACCT_FILTER],
0288 };
0289
0290 return netlink_dump_start(info->sk, skb, info->nlh, &c);
0291 }
0292
0293 if (!tb[NFACCT_NAME])
0294 return -EINVAL;
0295 acct_name = nla_data(tb[NFACCT_NAME]);
0296
0297 list_for_each_entry(cur, &nfnl_acct_net->nfnl_acct_list, head) {
0298 struct sk_buff *skb2;
0299
0300 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
0301 continue;
0302
0303 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0304 if (skb2 == NULL) {
0305 ret = -ENOMEM;
0306 break;
0307 }
0308
0309 ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).portid,
0310 info->nlh->nlmsg_seq,
0311 NFNL_MSG_TYPE(info->nlh->nlmsg_type),
0312 NFNL_MSG_ACCT_NEW, cur);
0313 if (ret <= 0) {
0314 kfree_skb(skb2);
0315 break;
0316 }
0317
0318 ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
0319 break;
0320 }
0321
0322 return ret;
0323 }
0324
0325
0326 static int nfnl_acct_try_del(struct nf_acct *cur)
0327 {
0328 int ret = 0;
0329
0330
0331
0332
0333 if (refcount_dec_if_one(&cur->refcnt)) {
0334
0335 list_del_rcu(&cur->head);
0336 kfree_rcu(cur, rcu_head);
0337 } else {
0338 ret = -EBUSY;
0339 }
0340 return ret;
0341 }
0342
0343 static int nfnl_acct_del(struct sk_buff *skb, const struct nfnl_info *info,
0344 const struct nlattr * const tb[])
0345 {
0346 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
0347 struct nf_acct *cur, *tmp;
0348 int ret = -ENOENT;
0349 char *acct_name;
0350
0351 if (!tb[NFACCT_NAME]) {
0352 list_for_each_entry_safe(cur, tmp, &nfnl_acct_net->nfnl_acct_list, head)
0353 nfnl_acct_try_del(cur);
0354
0355 return 0;
0356 }
0357 acct_name = nla_data(tb[NFACCT_NAME]);
0358
0359 list_for_each_entry(cur, &nfnl_acct_net->nfnl_acct_list, head) {
0360 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0)
0361 continue;
0362
0363 ret = nfnl_acct_try_del(cur);
0364 if (ret < 0)
0365 return ret;
0366
0367 break;
0368 }
0369 return ret;
0370 }
0371
0372 static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {
0373 [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 },
0374 [NFACCT_BYTES] = { .type = NLA_U64 },
0375 [NFACCT_PKTS] = { .type = NLA_U64 },
0376 [NFACCT_FLAGS] = { .type = NLA_U32 },
0377 [NFACCT_QUOTA] = { .type = NLA_U64 },
0378 [NFACCT_FILTER] = {.type = NLA_NESTED },
0379 };
0380
0381 static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {
0382 [NFNL_MSG_ACCT_NEW] = {
0383 .call = nfnl_acct_new,
0384 .type = NFNL_CB_MUTEX,
0385 .attr_count = NFACCT_MAX,
0386 .policy = nfnl_acct_policy
0387 },
0388 [NFNL_MSG_ACCT_GET] = {
0389 .call = nfnl_acct_get,
0390 .type = NFNL_CB_MUTEX,
0391 .attr_count = NFACCT_MAX,
0392 .policy = nfnl_acct_policy
0393 },
0394 [NFNL_MSG_ACCT_GET_CTRZERO] = {
0395 .call = nfnl_acct_get,
0396 .type = NFNL_CB_MUTEX,
0397 .attr_count = NFACCT_MAX,
0398 .policy = nfnl_acct_policy
0399 },
0400 [NFNL_MSG_ACCT_DEL] = {
0401 .call = nfnl_acct_del,
0402 .type = NFNL_CB_MUTEX,
0403 .attr_count = NFACCT_MAX,
0404 .policy = nfnl_acct_policy
0405 },
0406 };
0407
0408 static const struct nfnetlink_subsystem nfnl_acct_subsys = {
0409 .name = "acct",
0410 .subsys_id = NFNL_SUBSYS_ACCT,
0411 .cb_count = NFNL_MSG_ACCT_MAX,
0412 .cb = nfnl_acct_cb,
0413 };
0414
0415 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT);
0416
0417 struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
0418 {
0419 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
0420 struct nf_acct *cur, *acct = NULL;
0421
0422 rcu_read_lock();
0423 list_for_each_entry_rcu(cur, &nfnl_acct_net->nfnl_acct_list, head) {
0424 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
0425 continue;
0426
0427 if (!try_module_get(THIS_MODULE))
0428 goto err;
0429
0430 if (!refcount_inc_not_zero(&cur->refcnt)) {
0431 module_put(THIS_MODULE);
0432 goto err;
0433 }
0434
0435 acct = cur;
0436 break;
0437 }
0438 err:
0439 rcu_read_unlock();
0440 return acct;
0441 }
0442 EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
0443
0444 void nfnl_acct_put(struct nf_acct *acct)
0445 {
0446 if (refcount_dec_and_test(&acct->refcnt))
0447 kfree_rcu(acct, rcu_head);
0448
0449 module_put(THIS_MODULE);
0450 }
0451 EXPORT_SYMBOL_GPL(nfnl_acct_put);
0452
0453 void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct)
0454 {
0455 atomic64_inc(&nfacct->pkts);
0456 atomic64_add(skb->len, &nfacct->bytes);
0457 }
0458 EXPORT_SYMBOL_GPL(nfnl_acct_update);
0459
0460 static void nfnl_overquota_report(struct net *net, struct nf_acct *nfacct)
0461 {
0462 int ret;
0463 struct sk_buff *skb;
0464
0465 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
0466 if (skb == NULL)
0467 return;
0468
0469 ret = nfnl_acct_fill_info(skb, 0, 0, NFNL_MSG_ACCT_OVERQUOTA, 0,
0470 nfacct);
0471 if (ret <= 0) {
0472 kfree_skb(skb);
0473 return;
0474 }
0475 nfnetlink_broadcast(net, skb, 0, NFNLGRP_ACCT_QUOTA, GFP_ATOMIC);
0476 }
0477
0478 int nfnl_acct_overquota(struct net *net, struct nf_acct *nfacct)
0479 {
0480 u64 now;
0481 u64 *quota;
0482 int ret = NFACCT_UNDERQUOTA;
0483
0484
0485 if (!(nfacct->flags & NFACCT_F_QUOTA))
0486 return NFACCT_NO_QUOTA;
0487
0488 quota = (u64 *)nfacct->data;
0489 now = (nfacct->flags & NFACCT_F_QUOTA_PKTS) ?
0490 atomic64_read(&nfacct->pkts) : atomic64_read(&nfacct->bytes);
0491
0492 ret = now > *quota;
0493
0494 if (now >= *quota &&
0495 !test_and_set_bit(NFACCT_OVERQUOTA_BIT, &nfacct->flags)) {
0496 nfnl_overquota_report(net, nfacct);
0497 }
0498
0499 return ret;
0500 }
0501 EXPORT_SYMBOL_GPL(nfnl_acct_overquota);
0502
0503 static int __net_init nfnl_acct_net_init(struct net *net)
0504 {
0505 INIT_LIST_HEAD(&nfnl_acct_pernet(net)->nfnl_acct_list);
0506
0507 return 0;
0508 }
0509
0510 static void __net_exit nfnl_acct_net_exit(struct net *net)
0511 {
0512 struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
0513 struct nf_acct *cur, *tmp;
0514
0515 list_for_each_entry_safe(cur, tmp, &nfnl_acct_net->nfnl_acct_list, head) {
0516 list_del_rcu(&cur->head);
0517
0518 if (refcount_dec_and_test(&cur->refcnt))
0519 kfree_rcu(cur, rcu_head);
0520 }
0521 }
0522
0523 static struct pernet_operations nfnl_acct_ops = {
0524 .init = nfnl_acct_net_init,
0525 .exit = nfnl_acct_net_exit,
0526 .id = &nfnl_acct_net_id,
0527 .size = sizeof(struct nfnl_acct_net),
0528 };
0529
0530 static int __init nfnl_acct_init(void)
0531 {
0532 int ret;
0533
0534 ret = register_pernet_subsys(&nfnl_acct_ops);
0535 if (ret < 0) {
0536 pr_err("nfnl_acct_init: failed to register pernet ops\n");
0537 goto err_out;
0538 }
0539
0540 ret = nfnetlink_subsys_register(&nfnl_acct_subsys);
0541 if (ret < 0) {
0542 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");
0543 goto cleanup_pernet;
0544 }
0545 return 0;
0546
0547 cleanup_pernet:
0548 unregister_pernet_subsys(&nfnl_acct_ops);
0549 err_out:
0550 return ret;
0551 }
0552
0553 static void __exit nfnl_acct_exit(void)
0554 {
0555 nfnetlink_subsys_unregister(&nfnl_acct_subsys);
0556 unregister_pernet_subsys(&nfnl_acct_ops);
0557 }
0558
0559 module_init(nfnl_acct_init);
0560 module_exit(nfnl_acct_exit);