nf_log.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
  16. static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly;
  17. static DEFINE_MUTEX(nf_log_mutex);
  18. static struct nf_logger *__find_logger(int pf, const char *str_logger)
  19. {
  20. struct nf_logger *t;
  21. list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) {
  22. if (!strnicmp(str_logger, t->name, strlen(t->name)))
  23. return t;
  24. }
  25. return NULL;
  26. }
  27. /* return EEXIST if the same logger is registred, 0 on success. */
  28. int nf_log_register(u_int8_t pf, struct nf_logger *logger)
  29. {
  30. const struct nf_logger *llog;
  31. int i;
  32. if (pf >= ARRAY_SIZE(nf_loggers))
  33. return -EINVAL;
  34. for (i = 0; i < ARRAY_SIZE(logger->list); i++)
  35. INIT_LIST_HEAD(&logger->list[i]);
  36. mutex_lock(&nf_log_mutex);
  37. if (pf == NFPROTO_UNSPEC) {
  38. for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
  39. list_add_tail(&(logger->list[i]), &(nf_loggers_l[i]));
  40. } else {
  41. /* register at end of list to honor first register win */
  42. list_add_tail(&logger->list[pf], &nf_loggers_l[pf]);
  43. llog = rcu_dereference_protected(nf_loggers[pf],
  44. lockdep_is_held(&nf_log_mutex));
  45. if (llog == NULL)
  46. rcu_assign_pointer(nf_loggers[pf], logger);
  47. }
  48. mutex_unlock(&nf_log_mutex);
  49. return 0;
  50. }
  51. EXPORT_SYMBOL(nf_log_register);
  52. void nf_log_unregister(struct nf_logger *logger)
  53. {
  54. const struct nf_logger *c_logger;
  55. int i;
  56. mutex_lock(&nf_log_mutex);
  57. for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) {
  58. c_logger = rcu_dereference_protected(nf_loggers[i],
  59. lockdep_is_held(&nf_log_mutex));
  60. if (c_logger == logger)
  61. rcu_assign_pointer(nf_loggers[i], NULL);
  62. list_del(&logger->list[i]);
  63. }
  64. mutex_unlock(&nf_log_mutex);
  65. synchronize_rcu();
  66. }
  67. EXPORT_SYMBOL(nf_log_unregister);
  68. int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger)
  69. {
  70. if (pf >= ARRAY_SIZE(nf_loggers))
  71. return -EINVAL;
  72. mutex_lock(&nf_log_mutex);
  73. if (__find_logger(pf, logger->name) == NULL) {
  74. mutex_unlock(&nf_log_mutex);
  75. return -ENOENT;
  76. }
  77. rcu_assign_pointer(nf_loggers[pf], logger);
  78. mutex_unlock(&nf_log_mutex);
  79. return 0;
  80. }
  81. EXPORT_SYMBOL(nf_log_bind_pf);
  82. void nf_log_unbind_pf(u_int8_t pf)
  83. {
  84. if (pf >= ARRAY_SIZE(nf_loggers))
  85. return;
  86. mutex_lock(&nf_log_mutex);
  87. rcu_assign_pointer(nf_loggers[pf], NULL);
  88. mutex_unlock(&nf_log_mutex);
  89. }
  90. EXPORT_SYMBOL(nf_log_unbind_pf);
  91. void nf_log_packet(u_int8_t pf,
  92. unsigned int hooknum,
  93. const struct sk_buff *skb,
  94. const struct net_device *in,
  95. const struct net_device *out,
  96. const struct nf_loginfo *loginfo,
  97. const char *fmt, ...)
  98. {
  99. va_list args;
  100. char prefix[NF_LOG_PREFIXLEN];
  101. const struct nf_logger *logger;
  102. rcu_read_lock();
  103. logger = rcu_dereference(nf_loggers[pf]);
  104. if (logger) {
  105. va_start(args, fmt);
  106. vsnprintf(prefix, sizeof(prefix), fmt, args);
  107. va_end(args);
  108. logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
  109. }
  110. rcu_read_unlock();
  111. }
  112. EXPORT_SYMBOL(nf_log_packet);
  113. #ifdef CONFIG_PROC_FS
  114. static void *seq_start(struct seq_file *seq, loff_t *pos)
  115. {
  116. mutex_lock(&nf_log_mutex);
  117. if (*pos >= ARRAY_SIZE(nf_loggers))
  118. return NULL;
  119. return pos;
  120. }
  121. static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
  122. {
  123. (*pos)++;
  124. if (*pos >= ARRAY_SIZE(nf_loggers))
  125. return NULL;
  126. return pos;
  127. }
  128. static void seq_stop(struct seq_file *s, void *v)
  129. {
  130. mutex_unlock(&nf_log_mutex);
  131. }
  132. static int seq_show(struct seq_file *s, void *v)
  133. {
  134. loff_t *pos = v;
  135. const struct nf_logger *logger;
  136. struct nf_logger *t;
  137. int ret;
  138. logger = rcu_dereference_protected(nf_loggers[*pos],
  139. lockdep_is_held(&nf_log_mutex));
  140. if (!logger)
  141. ret = seq_printf(s, "%2lld NONE (", *pos);
  142. else
  143. ret = seq_printf(s, "%2lld %s (", *pos, logger->name);
  144. if (ret < 0)
  145. return ret;
  146. list_for_each_entry(t, &nf_loggers_l[*pos], list[*pos]) {
  147. ret = seq_printf(s, "%s", t->name);
  148. if (ret < 0)
  149. return ret;
  150. if (&t->list[*pos] != nf_loggers_l[*pos].prev) {
  151. ret = seq_printf(s, ",");
  152. if (ret < 0)
  153. return ret;
  154. }
  155. }
  156. return seq_printf(s, ")\n");
  157. }
  158. static const struct seq_operations nflog_seq_ops = {
  159. .start = seq_start,
  160. .next = seq_next,
  161. .stop = seq_stop,
  162. .show = seq_show,
  163. };
  164. static int nflog_open(struct inode *inode, struct file *file)
  165. {
  166. return seq_open(file, &nflog_seq_ops);
  167. }
  168. static const struct file_operations nflog_file_ops = {
  169. .owner = THIS_MODULE,
  170. .open = nflog_open,
  171. .read = seq_read,
  172. .llseek = seq_lseek,
  173. .release = seq_release,
  174. };
  175. #endif /* PROC_FS */
  176. #ifdef CONFIG_SYSCTL
  177. static struct ctl_path nf_log_sysctl_path[] = {
  178. { .procname = "net", },
  179. { .procname = "netfilter", },
  180. { .procname = "nf_log", },
  181. { }
  182. };
  183. static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3];
  184. static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
  185. static struct ctl_table_header *nf_log_dir_header;
  186. static int nf_log_proc_dostring(ctl_table *table, int write,
  187. void __user *buffer, size_t *lenp, loff_t *ppos)
  188. {
  189. const struct nf_logger *logger;
  190. char buf[NFLOGGER_NAME_LEN];
  191. size_t size = *lenp;
  192. int r = 0;
  193. int tindex = (unsigned long)table->extra1;
  194. if (write) {
  195. if (size > sizeof(buf))
  196. size = sizeof(buf);
  197. if (copy_from_user(buf, buffer, size))
  198. return -EFAULT;
  199. if (!strcmp(buf, "NONE")) {
  200. nf_log_unbind_pf(tindex);
  201. return 0;
  202. }
  203. mutex_lock(&nf_log_mutex);
  204. logger = __find_logger(tindex, buf);
  205. if (logger == NULL) {
  206. mutex_unlock(&nf_log_mutex);
  207. return -ENOENT;
  208. }
  209. rcu_assign_pointer(nf_loggers[tindex], logger);
  210. mutex_unlock(&nf_log_mutex);
  211. } else {
  212. mutex_lock(&nf_log_mutex);
  213. logger = rcu_dereference_protected(nf_loggers[tindex],
  214. lockdep_is_held(&nf_log_mutex));
  215. if (!logger)
  216. table->data = "NONE";
  217. else
  218. table->data = logger->name;
  219. r = proc_dostring(table, write, buffer, lenp, ppos);
  220. mutex_unlock(&nf_log_mutex);
  221. }
  222. return r;
  223. }
  224. static __init int netfilter_log_sysctl_init(void)
  225. {
  226. int i;
  227. for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
  228. snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i);
  229. nf_log_sysctl_table[i].procname =
  230. nf_log_sysctl_fnames[i-NFPROTO_UNSPEC];
  231. nf_log_sysctl_table[i].data = NULL;
  232. nf_log_sysctl_table[i].maxlen =
  233. NFLOGGER_NAME_LEN * sizeof(char);
  234. nf_log_sysctl_table[i].mode = 0644;
  235. nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring;
  236. nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i;
  237. }
  238. nf_log_dir_header = register_sysctl_paths(nf_log_sysctl_path,
  239. nf_log_sysctl_table);
  240. if (!nf_log_dir_header)
  241. return -ENOMEM;
  242. return 0;
  243. }
  244. #else
  245. static __init int netfilter_log_sysctl_init(void)
  246. {
  247. return 0;
  248. }
  249. #endif /* CONFIG_SYSCTL */
  250. int __init netfilter_log_init(void)
  251. {
  252. int i, r;
  253. #ifdef CONFIG_PROC_FS
  254. if (!proc_create("nf_log", S_IRUGO,
  255. proc_net_netfilter, &nflog_file_ops))
  256. return -1;
  257. #endif
  258. /* Errors will trigger panic, unroll on error is unnecessary. */
  259. r = netfilter_log_sysctl_init();
  260. if (r < 0)
  261. return r;
  262. for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
  263. INIT_LIST_HEAD(&(nf_loggers_l[i]));
  264. return 0;
  265. }