1 #include <linux/kernel.h> 2 #include <linux/init.h> 3 #include <linux/module.h> 4 #include <linux/proc_fs.h> 5 #include <linux/skbuff.h> 6 #include <linux/netfilter.h> 7 #include <linux/seq_file.h> 8 #include <net/protocol.h> 9 #include <net/netfilter/nf_log.h> 10 11 #include "nf_internals.h" 12 13 /* Internal logging interface, which relies on the real 14 LOG target modules */ 15 16 #define NFLOGGER_NAME_LEN 64 17 18 int sysctl_nf_log_all_netns __read_mostly; 19 EXPORT_SYMBOL(sysctl_nf_log_all_netns); 20 21 static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly; 22 static DEFINE_MUTEX(nf_log_mutex); 23 24 #define nft_log_dereference(logger) \ 25 rcu_dereference_protected(logger, lockdep_is_held(&nf_log_mutex)) 26 27 static struct nf_logger *__find_logger(int pf, const char *str_logger) 28 { 29 struct nf_logger *log; 30 int i; 31 32 for (i = 0; i < NF_LOG_TYPE_MAX; i++) { 33 if (loggers[pf][i] == NULL) 34 continue; 35 36 log = nft_log_dereference(loggers[pf][i]); 37 if (!strncasecmp(str_logger, log->name, strlen(log->name))) 38 return log; 39 } 40 41 return NULL; 42 } 43 44 int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) 45 { 46 const struct nf_logger *log; 47 48 if (pf == NFPROTO_UNSPEC || pf >= ARRAY_SIZE(net->nf.nf_loggers)) 49 return -EOPNOTSUPP; 50 51 mutex_lock(&nf_log_mutex); 52 log = nft_log_dereference(net->nf.nf_loggers[pf]); 53 if (log == NULL) 54 rcu_assign_pointer(net->nf.nf_loggers[pf], logger); 55 56 mutex_unlock(&nf_log_mutex); 57 58 return 0; 59 } 60 EXPORT_SYMBOL(nf_log_set); 61 62 void nf_log_unset(struct net *net, const struct nf_logger *logger) 63 { 64 int i; 65 const struct nf_logger *log; 66 67 mutex_lock(&nf_log_mutex); 68 for (i = 0; i < NFPROTO_NUMPROTO; i++) { 69 log = nft_log_dereference(net->nf.nf_loggers[i]); 70 if (log == logger) 71 RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); 72 } 73 mutex_unlock(&nf_log_mutex); 74 } 75 EXPORT_SYMBOL(nf_log_unset); 76 77 /* return EEXIST if the same logger is registered, 0 on success. */ 78 int nf_log_register(u_int8_t pf, struct nf_logger *logger) 79 { 80 int i; 81 int ret = 0; 82 83 if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) 84 return -EINVAL; 85 86 mutex_lock(&nf_log_mutex); 87 88 if (pf == NFPROTO_UNSPEC) { 89 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { 90 if (rcu_access_pointer(loggers[i][logger->type])) { 91 ret = -EEXIST; 92 goto unlock; 93 } 94 } 95 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) 96 rcu_assign_pointer(loggers[i][logger->type], logger); 97 } else { 98 if (rcu_access_pointer(loggers[pf][logger->type])) { 99 ret = -EEXIST; 100 goto unlock; 101 } 102 rcu_assign_pointer(loggers[pf][logger->type], logger); 103 } 104 105 unlock: 106 mutex_unlock(&nf_log_mutex); 107 return ret; 108 } 109 EXPORT_SYMBOL(nf_log_register); 110 111 void nf_log_unregister(struct nf_logger *logger) 112 { 113 const struct nf_logger *log; 114 int i; 115 116 mutex_lock(&nf_log_mutex); 117 for (i = 0; i < NFPROTO_NUMPROTO; i++) { 118 log = nft_log_dereference(loggers[i][logger->type]); 119 if (log == logger) 120 RCU_INIT_POINTER(loggers[i][logger->type], NULL); 121 } 122 mutex_unlock(&nf_log_mutex); 123 synchronize_rcu(); 124 } 125 EXPORT_SYMBOL(nf_log_unregister); 126 127 int nf_log_bind_pf(struct net *net, u_int8_t pf, 128 const struct nf_logger *logger) 129 { 130 if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) 131 return -EINVAL; 132 mutex_lock(&nf_log_mutex); 133 if (__find_logger(pf, logger->name) == NULL) { 134 mutex_unlock(&nf_log_mutex); 135 return -ENOENT; 136 } 137 rcu_assign_pointer(net->nf.nf_loggers[pf], logger); 138 mutex_unlock(&nf_log_mutex); 139 return 0; 140 } 141 EXPORT_SYMBOL(nf_log_bind_pf); 142 143 void nf_log_unbind_pf(struct net *net, u_int8_t pf) 144 { 145 if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) 146 return; 147 mutex_lock(&nf_log_mutex); 148 RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL); 149 mutex_unlock(&nf_log_mutex); 150 } 151 EXPORT_SYMBOL(nf_log_unbind_pf); 152 153 void nf_logger_request_module(int pf, enum nf_log_type type) 154 { 155 if (loggers[pf][type] == NULL) 156 request_module("nf-logger-%u-%u", pf, type); 157 } 158 EXPORT_SYMBOL_GPL(nf_logger_request_module); 159 160 int nf_logger_find_get(int pf, enum nf_log_type type) 161 { 162 struct nf_logger *logger; 163 int ret = -ENOENT; 164 165 if (pf == NFPROTO_INET) { 166 ret = nf_logger_find_get(NFPROTO_IPV4, type); 167 if (ret < 0) 168 return ret; 169 170 ret = nf_logger_find_get(NFPROTO_IPV6, type); 171 if (ret < 0) { 172 nf_logger_put(NFPROTO_IPV4, type); 173 return ret; 174 } 175 176 return 0; 177 } 178 179 if (rcu_access_pointer(loggers[pf][type]) == NULL) 180 request_module("nf-logger-%u-%u", pf, type); 181 182 rcu_read_lock(); 183 logger = rcu_dereference(loggers[pf][type]); 184 if (logger == NULL) 185 goto out; 186 187 if (try_module_get(logger->me)) 188 ret = 0; 189 out: 190 rcu_read_unlock(); 191 return ret; 192 } 193 EXPORT_SYMBOL_GPL(nf_logger_find_get); 194 195 void nf_logger_put(int pf, enum nf_log_type type) 196 { 197 struct nf_logger *logger; 198 199 if (pf == NFPROTO_INET) { 200 nf_logger_put(NFPROTO_IPV4, type); 201 nf_logger_put(NFPROTO_IPV6, type); 202 return; 203 } 204 205 BUG_ON(loggers[pf][type] == NULL); 206 207 rcu_read_lock(); 208 logger = rcu_dereference(loggers[pf][type]); 209 module_put(logger->me); 210 rcu_read_unlock(); 211 } 212 EXPORT_SYMBOL_GPL(nf_logger_put); 213 214 void nf_log_packet(struct net *net, 215 u_int8_t pf, 216 unsigned int hooknum, 217 const struct sk_buff *skb, 218 const struct net_device *in, 219 const struct net_device *out, 220 const struct nf_loginfo *loginfo, 221 const char *fmt, ...) 222 { 223 va_list args; 224 char prefix[NF_LOG_PREFIXLEN]; 225 const struct nf_logger *logger; 226 227 rcu_read_lock(); 228 if (loginfo != NULL) 229 logger = rcu_dereference(loggers[pf][loginfo->type]); 230 else 231 logger = rcu_dereference(net->nf.nf_loggers[pf]); 232 233 if (logger) { 234 va_start(args, fmt); 235 vsnprintf(prefix, sizeof(prefix), fmt, args); 236 va_end(args); 237 logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix); 238 } 239 rcu_read_unlock(); 240 } 241 EXPORT_SYMBOL(nf_log_packet); 242 243 void nf_log_trace(struct net *net, 244 u_int8_t pf, 245 unsigned int hooknum, 246 const struct sk_buff *skb, 247 const struct net_device *in, 248 const struct net_device *out, 249 const struct nf_loginfo *loginfo, const char *fmt, ...) 250 { 251 va_list args; 252 char prefix[NF_LOG_PREFIXLEN]; 253 const struct nf_logger *logger; 254 255 rcu_read_lock(); 256 logger = rcu_dereference(net->nf.nf_loggers[pf]); 257 if (logger) { 258 va_start(args, fmt); 259 vsnprintf(prefix, sizeof(prefix), fmt, args); 260 va_end(args); 261 logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix); 262 } 263 rcu_read_unlock(); 264 } 265 EXPORT_SYMBOL(nf_log_trace); 266 267 #define S_SIZE (1024 - (sizeof(unsigned int) + 1)) 268 269 struct nf_log_buf { 270 unsigned int count; 271 char buf[S_SIZE + 1]; 272 }; 273 static struct nf_log_buf emergency, *emergency_ptr = &emergency; 274 275 __printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...) 276 { 277 va_list args; 278 int len; 279 280 if (likely(m->count < S_SIZE)) { 281 va_start(args, f); 282 len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args); 283 va_end(args); 284 if (likely(m->count + len < S_SIZE)) { 285 m->count += len; 286 return 0; 287 } 288 } 289 m->count = S_SIZE; 290 printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n"); 291 return -1; 292 } 293 EXPORT_SYMBOL_GPL(nf_log_buf_add); 294 295 struct nf_log_buf *nf_log_buf_open(void) 296 { 297 struct nf_log_buf *m = kmalloc(sizeof(*m), GFP_ATOMIC); 298 299 if (unlikely(!m)) { 300 local_bh_disable(); 301 do { 302 m = xchg(&emergency_ptr, NULL); 303 } while (!m); 304 } 305 m->count = 0; 306 return m; 307 } 308 EXPORT_SYMBOL_GPL(nf_log_buf_open); 309 310 void nf_log_buf_close(struct nf_log_buf *m) 311 { 312 m->buf[m->count] = 0; 313 printk("%s\n", m->buf); 314 315 if (likely(m != &emergency)) 316 kfree(m); 317 else { 318 emergency_ptr = m; 319 local_bh_enable(); 320 } 321 } 322 EXPORT_SYMBOL_GPL(nf_log_buf_close); 323 324 #ifdef CONFIG_PROC_FS 325 static void *seq_start(struct seq_file *seq, loff_t *pos) 326 { 327 struct net *net = seq_file_net(seq); 328 329 mutex_lock(&nf_log_mutex); 330 331 if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) 332 return NULL; 333 334 return pos; 335 } 336 337 static void *seq_next(struct seq_file *s, void *v, loff_t *pos) 338 { 339 struct net *net = seq_file_net(s); 340 341 (*pos)++; 342 343 if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) 344 return NULL; 345 346 return pos; 347 } 348 349 static void seq_stop(struct seq_file *s, void *v) 350 { 351 mutex_unlock(&nf_log_mutex); 352 } 353 354 static int seq_show(struct seq_file *s, void *v) 355 { 356 loff_t *pos = v; 357 const struct nf_logger *logger; 358 int i; 359 struct net *net = seq_file_net(s); 360 361 logger = nft_log_dereference(net->nf.nf_loggers[*pos]); 362 363 if (!logger) 364 seq_printf(s, "%2lld NONE (", *pos); 365 else 366 seq_printf(s, "%2lld %s (", *pos, logger->name); 367 368 if (seq_has_overflowed(s)) 369 return -ENOSPC; 370 371 for (i = 0; i < NF_LOG_TYPE_MAX; i++) { 372 if (loggers[*pos][i] == NULL) 373 continue; 374 375 logger = nft_log_dereference(loggers[*pos][i]); 376 seq_printf(s, "%s", logger->name); 377 if (i == 0 && loggers[*pos][i + 1] != NULL) 378 seq_puts(s, ","); 379 380 if (seq_has_overflowed(s)) 381 return -ENOSPC; 382 } 383 384 seq_puts(s, ")\n"); 385 386 if (seq_has_overflowed(s)) 387 return -ENOSPC; 388 return 0; 389 } 390 391 static const struct seq_operations nflog_seq_ops = { 392 .start = seq_start, 393 .next = seq_next, 394 .stop = seq_stop, 395 .show = seq_show, 396 }; 397 #endif /* PROC_FS */ 398 399 #ifdef CONFIG_SYSCTL 400 static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; 401 static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; 402 static struct ctl_table_header *nf_log_sysctl_fhdr; 403 404 static struct ctl_table nf_log_sysctl_ftable[] = { 405 { 406 .procname = "nf_log_all_netns", 407 .data = &sysctl_nf_log_all_netns, 408 .maxlen = sizeof(sysctl_nf_log_all_netns), 409 .mode = 0644, 410 .proc_handler = proc_dointvec, 411 }, 412 { } 413 }; 414 415 static int nf_log_proc_dostring(struct ctl_table *table, int write, 416 void __user *buffer, size_t *lenp, loff_t *ppos) 417 { 418 const struct nf_logger *logger; 419 char buf[NFLOGGER_NAME_LEN]; 420 int r = 0; 421 int tindex = (unsigned long)table->extra1; 422 struct net *net = table->extra2; 423 424 if (write) { 425 struct ctl_table tmp = *table; 426 427 tmp.data = buf; 428 r = proc_dostring(&tmp, write, buffer, lenp, ppos); 429 if (r) 430 return r; 431 432 if (!strcmp(buf, "NONE")) { 433 nf_log_unbind_pf(net, tindex); 434 return 0; 435 } 436 mutex_lock(&nf_log_mutex); 437 logger = __find_logger(tindex, buf); 438 if (logger == NULL) { 439 mutex_unlock(&nf_log_mutex); 440 return -ENOENT; 441 } 442 rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); 443 mutex_unlock(&nf_log_mutex); 444 } else { 445 mutex_lock(&nf_log_mutex); 446 logger = nft_log_dereference(net->nf.nf_loggers[tindex]); 447 if (!logger) 448 table->data = "NONE"; 449 else 450 table->data = logger->name; 451 r = proc_dostring(table, write, buffer, lenp, ppos); 452 mutex_unlock(&nf_log_mutex); 453 } 454 455 return r; 456 } 457 458 static int netfilter_log_sysctl_init(struct net *net) 459 { 460 int i; 461 struct ctl_table *table; 462 463 table = nf_log_sysctl_table; 464 if (!net_eq(net, &init_net)) { 465 table = kmemdup(nf_log_sysctl_table, 466 sizeof(nf_log_sysctl_table), 467 GFP_KERNEL); 468 if (!table) 469 goto err_alloc; 470 } else { 471 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { 472 snprintf(nf_log_sysctl_fnames[i], 473 3, "%d", i); 474 nf_log_sysctl_table[i].procname = 475 nf_log_sysctl_fnames[i]; 476 nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN; 477 nf_log_sysctl_table[i].mode = 0644; 478 nf_log_sysctl_table[i].proc_handler = 479 nf_log_proc_dostring; 480 nf_log_sysctl_table[i].extra1 = 481 (void *)(unsigned long) i; 482 } 483 nf_log_sysctl_fhdr = register_net_sysctl(net, "net/netfilter", 484 nf_log_sysctl_ftable); 485 if (!nf_log_sysctl_fhdr) 486 goto err_freg; 487 } 488 489 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) 490 table[i].extra2 = net; 491 492 net->nf.nf_log_dir_header = register_net_sysctl(net, 493 "net/netfilter/nf_log", 494 table); 495 if (!net->nf.nf_log_dir_header) 496 goto err_reg; 497 498 return 0; 499 500 err_reg: 501 if (!net_eq(net, &init_net)) 502 kfree(table); 503 else 504 unregister_net_sysctl_table(nf_log_sysctl_fhdr); 505 err_freg: 506 err_alloc: 507 return -ENOMEM; 508 } 509 510 static void netfilter_log_sysctl_exit(struct net *net) 511 { 512 struct ctl_table *table; 513 514 table = net->nf.nf_log_dir_header->ctl_table_arg; 515 unregister_net_sysctl_table(net->nf.nf_log_dir_header); 516 if (!net_eq(net, &init_net)) 517 kfree(table); 518 else 519 unregister_net_sysctl_table(nf_log_sysctl_fhdr); 520 } 521 #else 522 static int netfilter_log_sysctl_init(struct net *net) 523 { 524 return 0; 525 } 526 527 static void netfilter_log_sysctl_exit(struct net *net) 528 { 529 } 530 #endif /* CONFIG_SYSCTL */ 531 532 static int __net_init nf_log_net_init(struct net *net) 533 { 534 int ret = -ENOMEM; 535 536 #ifdef CONFIG_PROC_FS 537 if (!proc_create_net("nf_log", 0444, net->nf.proc_netfilter, 538 &nflog_seq_ops, sizeof(struct seq_net_private))) 539 return ret; 540 #endif 541 ret = netfilter_log_sysctl_init(net); 542 if (ret < 0) 543 goto out_sysctl; 544 545 return 0; 546 547 out_sysctl: 548 #ifdef CONFIG_PROC_FS 549 remove_proc_entry("nf_log", net->nf.proc_netfilter); 550 #endif 551 return ret; 552 } 553 554 static void __net_exit nf_log_net_exit(struct net *net) 555 { 556 netfilter_log_sysctl_exit(net); 557 #ifdef CONFIG_PROC_FS 558 remove_proc_entry("nf_log", net->nf.proc_netfilter); 559 #endif 560 } 561 562 static struct pernet_operations nf_log_net_ops = { 563 .init = nf_log_net_init, 564 .exit = nf_log_net_exit, 565 }; 566 567 int __init netfilter_log_init(void) 568 { 569 return register_pernet_subsys(&nf_log_net_ops); 570 } 571