1 /* 2 * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org> 3 * (C) 2011 Intra2net AG <http://www.intra2net.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation (or any later at your option). 8 */ 9 #include <linux/init.h> 10 #include <linux/module.h> 11 #include <linux/kernel.h> 12 #include <linux/skbuff.h> 13 #include <linux/atomic.h> 14 #include <linux/refcount.h> 15 #include <linux/netlink.h> 16 #include <linux/rculist.h> 17 #include <linux/slab.h> 18 #include <linux/types.h> 19 #include <linux/errno.h> 20 #include <net/netlink.h> 21 #include <net/sock.h> 22 23 #include <linux/netfilter.h> 24 #include <linux/netfilter/nfnetlink.h> 25 #include <linux/netfilter/nfnetlink_acct.h> 26 27 MODULE_LICENSE("GPL"); 28 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 29 MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure"); 30 31 struct nf_acct { 32 atomic64_t pkts; 33 atomic64_t bytes; 34 unsigned long flags; 35 struct list_head head; 36 refcount_t refcnt; 37 char name[NFACCT_NAME_MAX]; 38 struct rcu_head rcu_head; 39 char data[0]; 40 }; 41 42 struct nfacct_filter { 43 u32 value; 44 u32 mask; 45 }; 46 47 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES) 48 #define NFACCT_OVERQUOTA_BIT 2 /* NFACCT_F_OVERQUOTA */ 49 50 static int nfnl_acct_new(struct net *net, struct sock *nfnl, 51 struct sk_buff *skb, const struct nlmsghdr *nlh, 52 const struct nlattr * const tb[], 53 struct netlink_ext_ack *extack) 54 { 55 struct nf_acct *nfacct, *matching = NULL; 56 char *acct_name; 57 unsigned int size = 0; 58 u32 flags = 0; 59 60 if (!tb[NFACCT_NAME]) 61 return -EINVAL; 62 63 acct_name = nla_data(tb[NFACCT_NAME]); 64 if (strlen(acct_name) == 0) 65 return -EINVAL; 66 67 list_for_each_entry(nfacct, &net->nfnl_acct_list, head) { 68 if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0) 69 continue; 70 71 if (nlh->nlmsg_flags & NLM_F_EXCL) 72 return -EEXIST; 73 74 matching = nfacct; 75 break; 76 } 77 78 if (matching) { 79 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 80 /* reset counters if you request a replacement. */ 81 atomic64_set(&matching->pkts, 0); 82 atomic64_set(&matching->bytes, 0); 83 smp_mb__before_atomic(); 84 /* reset overquota flag if quota is enabled. */ 85 if ((matching->flags & NFACCT_F_QUOTA)) 86 clear_bit(NFACCT_OVERQUOTA_BIT, 87 &matching->flags); 88 return 0; 89 } 90 return -EBUSY; 91 } 92 93 if (tb[NFACCT_FLAGS]) { 94 flags = ntohl(nla_get_be32(tb[NFACCT_FLAGS])); 95 if (flags & ~NFACCT_F_QUOTA) 96 return -EOPNOTSUPP; 97 if ((flags & NFACCT_F_QUOTA) == NFACCT_F_QUOTA) 98 return -EINVAL; 99 if (flags & NFACCT_F_OVERQUOTA) 100 return -EINVAL; 101 if ((flags & NFACCT_F_QUOTA) && !tb[NFACCT_QUOTA]) 102 return -EINVAL; 103 104 size += sizeof(u64); 105 } 106 107 nfacct = kzalloc(sizeof(struct nf_acct) + size, GFP_KERNEL); 108 if (nfacct == NULL) 109 return -ENOMEM; 110 111 if (flags & NFACCT_F_QUOTA) { 112 u64 *quota = (u64 *)nfacct->data; 113 114 *quota = be64_to_cpu(nla_get_be64(tb[NFACCT_QUOTA])); 115 nfacct->flags = flags; 116 } 117 118 nla_strlcpy(nfacct->name, tb[NFACCT_NAME], NFACCT_NAME_MAX); 119 120 if (tb[NFACCT_BYTES]) { 121 atomic64_set(&nfacct->bytes, 122 be64_to_cpu(nla_get_be64(tb[NFACCT_BYTES]))); 123 } 124 if (tb[NFACCT_PKTS]) { 125 atomic64_set(&nfacct->pkts, 126 be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS]))); 127 } 128 refcount_set(&nfacct->refcnt, 1); 129 list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list); 130 return 0; 131 } 132 133 static int 134 nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, 135 int event, struct nf_acct *acct) 136 { 137 struct nlmsghdr *nlh; 138 struct nfgenmsg *nfmsg; 139 unsigned int flags = portid ? NLM_F_MULTI : 0; 140 u64 pkts, bytes; 141 u32 old_flags; 142 143 event = nfnl_msg_type(NFNL_SUBSYS_ACCT, event); 144 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); 145 if (nlh == NULL) 146 goto nlmsg_failure; 147 148 nfmsg = nlmsg_data(nlh); 149 nfmsg->nfgen_family = AF_UNSPEC; 150 nfmsg->version = NFNETLINK_V0; 151 nfmsg->res_id = 0; 152 153 if (nla_put_string(skb, NFACCT_NAME, acct->name)) 154 goto nla_put_failure; 155 156 old_flags = acct->flags; 157 if (type == NFNL_MSG_ACCT_GET_CTRZERO) { 158 pkts = atomic64_xchg(&acct->pkts, 0); 159 bytes = atomic64_xchg(&acct->bytes, 0); 160 smp_mb__before_atomic(); 161 if (acct->flags & NFACCT_F_QUOTA) 162 clear_bit(NFACCT_OVERQUOTA_BIT, &acct->flags); 163 } else { 164 pkts = atomic64_read(&acct->pkts); 165 bytes = atomic64_read(&acct->bytes); 166 } 167 if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts), 168 NFACCT_PAD) || 169 nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes), 170 NFACCT_PAD) || 171 nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt)))) 172 goto nla_put_failure; 173 if (acct->flags & NFACCT_F_QUOTA) { 174 u64 *quota = (u64 *)acct->data; 175 176 if (nla_put_be32(skb, NFACCT_FLAGS, htonl(old_flags)) || 177 nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota), 178 NFACCT_PAD)) 179 goto nla_put_failure; 180 } 181 nlmsg_end(skb, nlh); 182 return skb->len; 183 184 nlmsg_failure: 185 nla_put_failure: 186 nlmsg_cancel(skb, nlh); 187 return -1; 188 } 189 190 static int 191 nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb) 192 { 193 struct net *net = sock_net(skb->sk); 194 struct nf_acct *cur, *last; 195 const struct nfacct_filter *filter = cb->data; 196 197 if (cb->args[2]) 198 return 0; 199 200 last = (struct nf_acct *)cb->args[1]; 201 if (cb->args[1]) 202 cb->args[1] = 0; 203 204 rcu_read_lock(); 205 list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) { 206 if (last) { 207 if (cur != last) 208 continue; 209 210 last = NULL; 211 } 212 213 if (filter && (cur->flags & filter->mask) != filter->value) 214 continue; 215 216 if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid, 217 cb->nlh->nlmsg_seq, 218 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 219 NFNL_MSG_ACCT_NEW, cur) < 0) { 220 cb->args[1] = (unsigned long)cur; 221 break; 222 } 223 } 224 if (!cb->args[1]) 225 cb->args[2] = 1; 226 rcu_read_unlock(); 227 return skb->len; 228 } 229 230 static int nfnl_acct_done(struct netlink_callback *cb) 231 { 232 kfree(cb->data); 233 return 0; 234 } 235 236 static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = { 237 [NFACCT_FILTER_MASK] = { .type = NLA_U32 }, 238 [NFACCT_FILTER_VALUE] = { .type = NLA_U32 }, 239 }; 240 241 static int nfnl_acct_start(struct netlink_callback *cb) 242 { 243 const struct nlattr *const attr = cb->data; 244 struct nlattr *tb[NFACCT_FILTER_MAX + 1]; 245 struct nfacct_filter *filter; 246 int err; 247 248 if (!attr) 249 return 0; 250 251 err = nla_parse_nested_deprecated(tb, NFACCT_FILTER_MAX, attr, 252 filter_policy, NULL); 253 if (err < 0) 254 return err; 255 256 if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE]) 257 return -EINVAL; 258 259 filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL); 260 if (!filter) 261 return -ENOMEM; 262 263 filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK])); 264 filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE])); 265 cb->data = filter; 266 267 return 0; 268 } 269 270 static int nfnl_acct_get(struct net *net, struct sock *nfnl, 271 struct sk_buff *skb, const struct nlmsghdr *nlh, 272 const struct nlattr * const tb[], 273 struct netlink_ext_ack *extack) 274 { 275 int ret = -ENOENT; 276 struct nf_acct *cur; 277 char *acct_name; 278 279 if (nlh->nlmsg_flags & NLM_F_DUMP) { 280 struct netlink_dump_control c = { 281 .dump = nfnl_acct_dump, 282 .start = nfnl_acct_start, 283 .done = nfnl_acct_done, 284 .data = (void *)tb[NFACCT_FILTER], 285 }; 286 287 return netlink_dump_start(nfnl, skb, nlh, &c); 288 } 289 290 if (!tb[NFACCT_NAME]) 291 return -EINVAL; 292 acct_name = nla_data(tb[NFACCT_NAME]); 293 294 list_for_each_entry(cur, &net->nfnl_acct_list, head) { 295 struct sk_buff *skb2; 296 297 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0) 298 continue; 299 300 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 301 if (skb2 == NULL) { 302 ret = -ENOMEM; 303 break; 304 } 305 306 ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).portid, 307 nlh->nlmsg_seq, 308 NFNL_MSG_TYPE(nlh->nlmsg_type), 309 NFNL_MSG_ACCT_NEW, cur); 310 if (ret <= 0) { 311 kfree_skb(skb2); 312 break; 313 } 314 ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid, 315 MSG_DONTWAIT); 316 if (ret > 0) 317 ret = 0; 318 319 /* this avoids a loop in nfnetlink. */ 320 return ret == -EAGAIN ? -ENOBUFS : ret; 321 } 322 return ret; 323 } 324 325 /* try to delete object, fail if it is still in use. */ 326 static int nfnl_acct_try_del(struct nf_acct *cur) 327 { 328 int ret = 0; 329 330 /* We want to avoid races with nfnl_acct_put. So only when the current 331 * refcnt is 1, we decrease it to 0. 332 */ 333 if (refcount_dec_if_one(&cur->refcnt)) { 334 /* We are protected by nfnl mutex. */ 335 list_del_rcu(&cur->head); 336 kfree_rcu(cur, rcu_head); 337 } else { 338 ret = -EBUSY; 339 } 340 return ret; 341 } 342 343 static int nfnl_acct_del(struct net *net, struct sock *nfnl, 344 struct sk_buff *skb, const struct nlmsghdr *nlh, 345 const struct nlattr * const tb[], 346 struct netlink_ext_ack *extack) 347 { 348 struct nf_acct *cur, *tmp; 349 int ret = -ENOENT; 350 char *acct_name; 351 352 if (!tb[NFACCT_NAME]) { 353 list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) 354 nfnl_acct_try_del(cur); 355 356 return 0; 357 } 358 acct_name = nla_data(tb[NFACCT_NAME]); 359 360 list_for_each_entry(cur, &net->nfnl_acct_list, head) { 361 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0) 362 continue; 363 364 ret = nfnl_acct_try_del(cur); 365 if (ret < 0) 366 return ret; 367 368 break; 369 } 370 return ret; 371 } 372 373 static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = { 374 [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 }, 375 [NFACCT_BYTES] = { .type = NLA_U64 }, 376 [NFACCT_PKTS] = { .type = NLA_U64 }, 377 [NFACCT_FLAGS] = { .type = NLA_U32 }, 378 [NFACCT_QUOTA] = { .type = NLA_U64 }, 379 [NFACCT_FILTER] = {.type = NLA_NESTED }, 380 }; 381 382 static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = { 383 [NFNL_MSG_ACCT_NEW] = { .call = nfnl_acct_new, 384 .attr_count = NFACCT_MAX, 385 .policy = nfnl_acct_policy }, 386 [NFNL_MSG_ACCT_GET] = { .call = nfnl_acct_get, 387 .attr_count = NFACCT_MAX, 388 .policy = nfnl_acct_policy }, 389 [NFNL_MSG_ACCT_GET_CTRZERO] = { .call = nfnl_acct_get, 390 .attr_count = NFACCT_MAX, 391 .policy = nfnl_acct_policy }, 392 [NFNL_MSG_ACCT_DEL] = { .call = nfnl_acct_del, 393 .attr_count = NFACCT_MAX, 394 .policy = nfnl_acct_policy }, 395 }; 396 397 static const struct nfnetlink_subsystem nfnl_acct_subsys = { 398 .name = "acct", 399 .subsys_id = NFNL_SUBSYS_ACCT, 400 .cb_count = NFNL_MSG_ACCT_MAX, 401 .cb = nfnl_acct_cb, 402 }; 403 404 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT); 405 406 struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name) 407 { 408 struct nf_acct *cur, *acct = NULL; 409 410 rcu_read_lock(); 411 list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) { 412 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0) 413 continue; 414 415 if (!try_module_get(THIS_MODULE)) 416 goto err; 417 418 if (!refcount_inc_not_zero(&cur->refcnt)) { 419 module_put(THIS_MODULE); 420 goto err; 421 } 422 423 acct = cur; 424 break; 425 } 426 err: 427 rcu_read_unlock(); 428 return acct; 429 } 430 EXPORT_SYMBOL_GPL(nfnl_acct_find_get); 431 432 void nfnl_acct_put(struct nf_acct *acct) 433 { 434 if (refcount_dec_and_test(&acct->refcnt)) 435 kfree_rcu(acct, rcu_head); 436 437 module_put(THIS_MODULE); 438 } 439 EXPORT_SYMBOL_GPL(nfnl_acct_put); 440 441 void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct) 442 { 443 atomic64_inc(&nfacct->pkts); 444 atomic64_add(skb->len, &nfacct->bytes); 445 } 446 EXPORT_SYMBOL_GPL(nfnl_acct_update); 447 448 static void nfnl_overquota_report(struct net *net, struct nf_acct *nfacct) 449 { 450 int ret; 451 struct sk_buff *skb; 452 453 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 454 if (skb == NULL) 455 return; 456 457 ret = nfnl_acct_fill_info(skb, 0, 0, NFNL_MSG_ACCT_OVERQUOTA, 0, 458 nfacct); 459 if (ret <= 0) { 460 kfree_skb(skb); 461 return; 462 } 463 netlink_broadcast(net->nfnl, skb, 0, NFNLGRP_ACCT_QUOTA, 464 GFP_ATOMIC); 465 } 466 467 int nfnl_acct_overquota(struct net *net, struct nf_acct *nfacct) 468 { 469 u64 now; 470 u64 *quota; 471 int ret = NFACCT_UNDERQUOTA; 472 473 /* no place here if we don't have a quota */ 474 if (!(nfacct->flags & NFACCT_F_QUOTA)) 475 return NFACCT_NO_QUOTA; 476 477 quota = (u64 *)nfacct->data; 478 now = (nfacct->flags & NFACCT_F_QUOTA_PKTS) ? 479 atomic64_read(&nfacct->pkts) : atomic64_read(&nfacct->bytes); 480 481 ret = now > *quota; 482 483 if (now >= *quota && 484 !test_and_set_bit(NFACCT_OVERQUOTA_BIT, &nfacct->flags)) { 485 nfnl_overquota_report(net, nfacct); 486 } 487 488 return ret; 489 } 490 EXPORT_SYMBOL_GPL(nfnl_acct_overquota); 491 492 static int __net_init nfnl_acct_net_init(struct net *net) 493 { 494 INIT_LIST_HEAD(&net->nfnl_acct_list); 495 496 return 0; 497 } 498 499 static void __net_exit nfnl_acct_net_exit(struct net *net) 500 { 501 struct nf_acct *cur, *tmp; 502 503 list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) { 504 list_del_rcu(&cur->head); 505 506 if (refcount_dec_and_test(&cur->refcnt)) 507 kfree_rcu(cur, rcu_head); 508 } 509 } 510 511 static struct pernet_operations nfnl_acct_ops = { 512 .init = nfnl_acct_net_init, 513 .exit = nfnl_acct_net_exit, 514 }; 515 516 static int __init nfnl_acct_init(void) 517 { 518 int ret; 519 520 ret = register_pernet_subsys(&nfnl_acct_ops); 521 if (ret < 0) { 522 pr_err("nfnl_acct_init: failed to register pernet ops\n"); 523 goto err_out; 524 } 525 526 ret = nfnetlink_subsys_register(&nfnl_acct_subsys); 527 if (ret < 0) { 528 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n"); 529 goto cleanup_pernet; 530 } 531 return 0; 532 533 cleanup_pernet: 534 unregister_pernet_subsys(&nfnl_acct_ops); 535 err_out: 536 return ret; 537 } 538 539 static void __exit nfnl_acct_exit(void) 540 { 541 nfnetlink_subsys_unregister(&nfnl_acct_subsys); 542 unregister_pernet_subsys(&nfnl_acct_ops); 543 } 544 545 module_init(nfnl_acct_init); 546 module_exit(nfnl_acct_exit); 547