LCOV - code coverage report
Current view: top level - net/netfilter - nf_log.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 26 278 9.4 %
Date: 2021-04-22 12:43:58 Functions: 3 25 12.0 %

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

Generated by: LCOV version 1.14