nf_log.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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 NF_LOG_PREFIXLEN 128
  14. #define NFLOGGER_NAME_LEN 64
  15. static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
  16. static DEFINE_MUTEX(nf_log_mutex);
  17. static struct nf_logger *__find_logger(int pf, const char *str_logger)
  18. {
  19. struct nf_logger *log;
  20. int i;
  21. for (i = 0; i < NF_LOG_TYPE_MAX; i++) {
  22. if (loggers[pf][i] == NULL)
  23. continue;
  24. log = rcu_dereference_protected(loggers[pf][i],
  25. lockdep_is_held(&nf_log_mutex));
  26. if (!strncasecmp(str_logger, log->name, strlen(log->name)))
  27. return log;
  28. }
  29. return NULL;
  30. }
  31. void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger)
  32. {
  33. const struct nf_logger *log;
  34. if (pf == NFPROTO_UNSPEC)
  35. return;
  36. mutex_lock(&nf_log_mutex);
  37. log = rcu_dereference_protected(net->nf.nf_loggers[pf],
  38. lockdep_is_held(&nf_log_mutex));
  39. if (log == NULL)
  40. rcu_assign_pointer(net->nf.nf_loggers[pf], logger);
  41. mutex_unlock(&nf_log_mutex);
  42. }
  43. EXPORT_SYMBOL(nf_log_set);
  44. void nf_log_unset(struct net *net, const struct nf_logger *logger)
  45. {
  46. int i;
  47. const struct nf_logger *log;
  48. mutex_lock(&nf_log_mutex);
  49. for (i = 0; i < NFPROTO_NUMPROTO; i++) {
  50. log = rcu_dereference_protected(net->nf.nf_loggers[i],
  51. lockdep_is_held(&nf_log_mutex));
  52. if (log == logger)
  53. RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL);
  54. }
  55. mutex_unlock(&nf_log_mutex);
  56. synchronize_rcu();
  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. if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers))
  64. return -EINVAL;
  65. mutex_lock(&nf_log_mutex);
  66. if (pf == NFPROTO_UNSPEC) {
  67. for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
  68. rcu_assign_pointer(loggers[i][logger->type], logger);
  69. } else {
  70. /* register at end of list to honor first register win */
  71. rcu_assign_pointer(loggers[pf][logger->type], logger);
  72. }
  73. mutex_unlock(&nf_log_mutex);
  74. return 0;
  75. }
  76. EXPORT_SYMBOL(nf_log_register);
  77. void nf_log_unregister(struct nf_logger *logger)
  78. {
  79. int i;
  80. mutex_lock(&nf_log_mutex);
  81. for (i = 0; i < NFPROTO_NUMPROTO; i++)
  82. RCU_INIT_POINTER(loggers[i][logger->type], NULL);
  83. mutex_unlock(&nf_log_mutex);
  84. }
  85. EXPORT_SYMBOL(nf_log_unregister);
  86. int nf_log_bind_pf(struct net *net, u_int8_t pf,
  87. const struct nf_logger *logger)
  88. {
  89. if (pf >= ARRAY_SIZE(net->nf.nf_loggers))
  90. return -EINVAL;
  91. mutex_lock(&nf_log_mutex);
  92. if (__find_logger(pf, logger->name) == NULL) {
  93. mutex_unlock(&nf_log_mutex);
  94. return -ENOENT;
  95. }
  96. rcu_assign_pointer(net->nf.nf_loggers[pf], logger);
  97. mutex_unlock(&nf_log_mutex);
  98. return 0;
  99. }
  100. EXPORT_SYMBOL(nf_log_bind_pf);
  101. void nf_log_unbind_pf(struct net *net, u_int8_t pf)
  102. {
  103. if (pf >= ARRAY_SIZE(net->nf.nf_loggers))
  104. return;
  105. mutex_lock(&nf_log_mutex);
  106. RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL);
  107. mutex_unlock(&nf_log_mutex);
  108. }
  109. EXPORT_SYMBOL(nf_log_unbind_pf);
  110. void nf_logger_request_module(int pf, enum nf_log_type type)
  111. {
  112. if (loggers[pf][type] == NULL)
  113. request_module("nf-logger-%u-%u", pf, type);
  114. }
  115. EXPORT_SYMBOL_GPL(nf_logger_request_module);
  116. int nf_logger_find_get(int pf, enum nf_log_type type)
  117. {
  118. struct nf_logger *logger;
  119. int ret = -ENOENT;
  120. logger = loggers[pf][type];
  121. if (logger == NULL)
  122. request_module("nf-logger-%u-%u", pf, type);
  123. rcu_read_lock();
  124. logger = rcu_dereference(loggers[pf][type]);
  125. if (logger == NULL)
  126. goto out;
  127. if (logger && try_module_get(logger->me))
  128. ret = 0;
  129. out:
  130. rcu_read_unlock();
  131. return ret;
  132. }
  133. EXPORT_SYMBOL_GPL(nf_logger_find_get);
  134. void nf_logger_put(int pf, enum nf_log_type type)
  135. {
  136. struct nf_logger *logger;
  137. BUG_ON(loggers[pf][type] == NULL);
  138. rcu_read_lock();
  139. logger = rcu_dereference(loggers[pf][type]);
  140. module_put(logger->me);
  141. rcu_read_unlock();
  142. }
  143. EXPORT_SYMBOL_GPL(nf_logger_put);
  144. void nf_log_packet(struct net *net,
  145. u_int8_t pf,
  146. unsigned int hooknum,
  147. const struct sk_buff *skb,
  148. const struct net_device *in,
  149. const struct net_device *out,
  150. const struct nf_loginfo *loginfo,
  151. const char *fmt, ...)
  152. {
  153. va_list args;
  154. char prefix[NF_LOG_PREFIXLEN];
  155. const struct nf_logger *logger;
  156. rcu_read_lock();
  157. if (loginfo != NULL)
  158. logger = rcu_dereference(loggers[pf][loginfo->type]);
  159. else
  160. logger = rcu_dereference(net->nf.nf_loggers[pf]);
  161. if (logger) {
  162. va_start(args, fmt);
  163. vsnprintf(prefix, sizeof(prefix), fmt, args);
  164. va_end(args);
  165. logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
  166. }
  167. rcu_read_unlock();
  168. }
  169. EXPORT_SYMBOL(nf_log_packet);
  170. #define S_SIZE (1024 - (sizeof(unsigned int) + 1))
  171. struct nf_log_buf {
  172. unsigned int count;
  173. char buf[S_SIZE + 1];
  174. };
  175. static struct nf_log_buf emergency, *emergency_ptr = &emergency;
  176. __printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...)
  177. {
  178. va_list args;
  179. int len;
  180. if (likely(m->count < S_SIZE)) {
  181. va_start(args, f);
  182. len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args);
  183. va_end(args);
  184. if (likely(m->count + len < S_SIZE)) {
  185. m->count += len;
  186. return 0;
  187. }
  188. }
  189. m->count = S_SIZE;
  190. printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n");
  191. return -1;
  192. }
  193. EXPORT_SYMBOL_GPL(nf_log_buf_add);
  194. struct nf_log_buf *nf_log_buf_open(void)
  195. {
  196. struct nf_log_buf *m = kmalloc(sizeof(*m), GFP_ATOMIC);
  197. if (unlikely(!m)) {
  198. local_bh_disable();
  199. do {
  200. m = xchg(&emergency_ptr, NULL);
  201. } while (!m);
  202. }
  203. m->count = 0;
  204. return m;
  205. }
  206. EXPORT_SYMBOL_GPL(nf_log_buf_open);
  207. void nf_log_buf_close(struct nf_log_buf *m)
  208. {
  209. m->buf[m->count] = 0;
  210. printk("%s\n", m->buf);
  211. if (likely(m != &emergency))
  212. kfree(m);
  213. else {
  214. emergency_ptr = m;
  215. local_bh_enable();
  216. }
  217. }
  218. EXPORT_SYMBOL_GPL(nf_log_buf_close);
  219. #ifdef CONFIG_PROC_FS
  220. static void *seq_start(struct seq_file *seq, loff_t *pos)
  221. {
  222. struct net *net = seq_file_net(seq);
  223. mutex_lock(&nf_log_mutex);
  224. if (*pos >= ARRAY_SIZE(net->nf.nf_loggers))
  225. return NULL;
  226. return pos;
  227. }
  228. static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
  229. {
  230. struct net *net = seq_file_net(s);
  231. (*pos)++;
  232. if (*pos >= ARRAY_SIZE(net->nf.nf_loggers))
  233. return NULL;
  234. return pos;
  235. }
  236. static void seq_stop(struct seq_file *s, void *v)
  237. {
  238. mutex_unlock(&nf_log_mutex);
  239. }
  240. static int seq_show(struct seq_file *s, void *v)
  241. {
  242. loff_t *pos = v;
  243. const struct nf_logger *logger;
  244. int i, ret;
  245. struct net *net = seq_file_net(s);
  246. logger = rcu_dereference_protected(net->nf.nf_loggers[*pos],
  247. lockdep_is_held(&nf_log_mutex));
  248. if (!logger)
  249. ret = seq_printf(s, "%2lld NONE (", *pos);
  250. else
  251. ret = seq_printf(s, "%2lld %s (", *pos, logger->name);
  252. if (ret < 0)
  253. return ret;
  254. for (i = 0; i < NF_LOG_TYPE_MAX; i++) {
  255. if (loggers[*pos][i] == NULL)
  256. continue;
  257. logger = rcu_dereference_protected(loggers[*pos][i],
  258. lockdep_is_held(&nf_log_mutex));
  259. ret = seq_printf(s, "%s", logger->name);
  260. if (ret < 0)
  261. return ret;
  262. if (i == 0 && loggers[*pos][i + 1] != NULL) {
  263. ret = seq_printf(s, ",");
  264. if (ret < 0)
  265. return ret;
  266. }
  267. }
  268. return seq_printf(s, ")\n");
  269. }
  270. static const struct seq_operations nflog_seq_ops = {
  271. .start = seq_start,
  272. .next = seq_next,
  273. .stop = seq_stop,
  274. .show = seq_show,
  275. };
  276. static int nflog_open(struct inode *inode, struct file *file)
  277. {
  278. return seq_open_net(inode, file, &nflog_seq_ops,
  279. sizeof(struct seq_net_private));
  280. }
  281. static const struct file_operations nflog_file_ops = {
  282. .owner = THIS_MODULE,
  283. .open = nflog_open,
  284. .read = seq_read,
  285. .llseek = seq_lseek,
  286. .release = seq_release_net,
  287. };
  288. #endif /* PROC_FS */
  289. #ifdef CONFIG_SYSCTL
  290. static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3];
  291. static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
  292. static int nf_log_proc_dostring(struct ctl_table *table, int write,
  293. void __user *buffer, size_t *lenp, loff_t *ppos)
  294. {
  295. const struct nf_logger *logger;
  296. char buf[NFLOGGER_NAME_LEN];
  297. size_t size = *lenp;
  298. int r = 0;
  299. int tindex = (unsigned long)table->extra1;
  300. struct net *net = current->nsproxy->net_ns;
  301. if (write) {
  302. if (size > sizeof(buf))
  303. size = sizeof(buf);
  304. if (copy_from_user(buf, buffer, size))
  305. return -EFAULT;
  306. if (!strcmp(buf, "NONE")) {
  307. nf_log_unbind_pf(net, tindex);
  308. return 0;
  309. }
  310. mutex_lock(&nf_log_mutex);
  311. logger = __find_logger(tindex, buf);
  312. if (logger == NULL) {
  313. mutex_unlock(&nf_log_mutex);
  314. return -ENOENT;
  315. }
  316. rcu_assign_pointer(net->nf.nf_loggers[tindex], logger);
  317. mutex_unlock(&nf_log_mutex);
  318. } else {
  319. mutex_lock(&nf_log_mutex);
  320. logger = rcu_dereference_protected(net->nf.nf_loggers[tindex],
  321. lockdep_is_held(&nf_log_mutex));
  322. if (!logger)
  323. table->data = "NONE";
  324. else
  325. table->data = logger->name;
  326. r = proc_dostring(table, write, buffer, lenp, ppos);
  327. mutex_unlock(&nf_log_mutex);
  328. }
  329. return r;
  330. }
  331. static int netfilter_log_sysctl_init(struct net *net)
  332. {
  333. int i;
  334. struct ctl_table *table;
  335. table = nf_log_sysctl_table;
  336. if (!net_eq(net, &init_net)) {
  337. table = kmemdup(nf_log_sysctl_table,
  338. sizeof(nf_log_sysctl_table),
  339. GFP_KERNEL);
  340. if (!table)
  341. goto err_alloc;
  342. } else {
  343. for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
  344. snprintf(nf_log_sysctl_fnames[i],
  345. 3, "%d", i);
  346. nf_log_sysctl_table[i].procname =
  347. nf_log_sysctl_fnames[i];
  348. nf_log_sysctl_table[i].data = NULL;
  349. nf_log_sysctl_table[i].maxlen =
  350. NFLOGGER_NAME_LEN * sizeof(char);
  351. nf_log_sysctl_table[i].mode = 0644;
  352. nf_log_sysctl_table[i].proc_handler =
  353. nf_log_proc_dostring;
  354. nf_log_sysctl_table[i].extra1 =
  355. (void *)(unsigned long) i;
  356. }
  357. }
  358. net->nf.nf_log_dir_header = register_net_sysctl(net,
  359. "net/netfilter/nf_log",
  360. table);
  361. if (!net->nf.nf_log_dir_header)
  362. goto err_reg;
  363. return 0;
  364. err_reg:
  365. if (!net_eq(net, &init_net))
  366. kfree(table);
  367. err_alloc:
  368. return -ENOMEM;
  369. }
  370. static void netfilter_log_sysctl_exit(struct net *net)
  371. {
  372. struct ctl_table *table;
  373. table = net->nf.nf_log_dir_header->ctl_table_arg;
  374. unregister_net_sysctl_table(net->nf.nf_log_dir_header);
  375. if (!net_eq(net, &init_net))
  376. kfree(table);
  377. }
  378. #else
  379. static int netfilter_log_sysctl_init(struct net *net)
  380. {
  381. return 0;
  382. }
  383. static void netfilter_log_sysctl_exit(struct net *net)
  384. {
  385. }
  386. #endif /* CONFIG_SYSCTL */
  387. static int __net_init nf_log_net_init(struct net *net)
  388. {
  389. int ret = -ENOMEM;
  390. #ifdef CONFIG_PROC_FS
  391. if (!proc_create("nf_log", S_IRUGO,
  392. net->nf.proc_netfilter, &nflog_file_ops))
  393. return ret;
  394. #endif
  395. ret = netfilter_log_sysctl_init(net);
  396. if (ret < 0)
  397. goto out_sysctl;
  398. return 0;
  399. out_sysctl:
  400. #ifdef CONFIG_PROC_FS
  401. remove_proc_entry("nf_log", net->nf.proc_netfilter);
  402. #endif
  403. return ret;
  404. }
  405. static void __net_exit nf_log_net_exit(struct net *net)
  406. {
  407. netfilter_log_sysctl_exit(net);
  408. #ifdef CONFIG_PROC_FS
  409. remove_proc_entry("nf_log", net->nf.proc_netfilter);
  410. #endif
  411. }
  412. static struct pernet_operations nf_log_net_ops = {
  413. .init = nf_log_net_init,
  414. .exit = nf_log_net_exit,
  415. };
  416. int __init netfilter_log_init(void)
  417. {
  418. return register_pernet_subsys(&nf_log_net_ops);
  419. }