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