nf_log.c 13 KB

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