LCOV - code coverage report
Current view: top level - net/netfilter - nf_log.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 22 222 9.9 %
Date: 2020-09-30 20:25:40 Functions: 3 25 12.0 %
Branches: 9 122 7.4 %

           Branch data     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                 :            :         struct nf_logger *log;
      31                 :            :         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                 :            :                 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                 :            :         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                 :            :         int i;
      66                 :            :         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                 :            :         int i;
      82                 :            :         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                 :            :                                 ret = -EEXIST;
      93                 :            :                                 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                 :            :                         ret = -EEXIST;
     101                 :            :                         goto unlock;
     102                 :            :                 }
     103                 :          0 :                 rcu_assign_pointer(loggers[pf][logger->type], logger);
     104                 :            :         }
     105                 :            : 
     106                 :            : 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                 :            :         const struct nf_logger *log;
     115                 :            :         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                 :          0 :                 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                 :            :         struct nf_logger *logger;
     164                 :            :         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                 :            :         rcu_read_lock();
     184                 :          0 :         logger = rcu_dereference(loggers[pf][type]);
     185         [ #  # ]:          0 :         if (logger == NULL)
     186                 :            :                 goto out;
     187                 :            : 
     188         [ #  # ]:          0 :         if (try_module_get(logger->me))
     189                 :            :                 ret = 0;
     190                 :            : out:
     191                 :            :         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                 :            :         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                 :            :         rcu_read_lock();
     209                 :          0 :         logger = rcu_dereference(loggers[pf][type]);
     210                 :          0 :         module_put(logger->me);
     211                 :            :         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                 :            :         va_list args;
     225                 :            :         char prefix[NF_LOG_PREFIXLEN];
     226                 :            :         const struct nf_logger *logger;
     227                 :            : 
     228                 :            :         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                 :            :         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                 :            :         va_list args;
     253                 :            :         char prefix[NF_LOG_PREFIXLEN];
     254                 :            :         const struct nf_logger *logger;
     255                 :            : 
     256                 :            :         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                 :            :         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                 :            :         va_list args;
     279                 :            :         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                 :            :         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                 :            :         struct nf_log_buf *m = kmalloc(sizeof(*m), GFP_ATOMIC);
     299                 :            : 
     300         [ #  # ]:          0 :         if (unlikely(!m)) {
     301                 :            :                 local_bh_disable();
     302                 :            :                 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                 :            :                 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                 :            :         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                 :            :                 return NULL;
     334                 :            : 
     335                 :          0 :         return pos;
     336                 :            : }
     337                 :            : 
     338                 :          0 : static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
     339                 :            : {
     340                 :            :         struct net *net = seq_file_net(s);
     341                 :            : 
     342                 :          0 :         (*pos)++;
     343                 :            : 
     344         [ #  # ]:          0 :         if (*pos >= ARRAY_SIZE(net->nf.nf_loggers))
     345                 :            :                 return NULL;
     346                 :            : 
     347                 :          0 :         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                 :            :         loff_t *pos = v;
     358                 :            :         const struct nf_logger *logger;
     359                 :            :         int i;
     360                 :            :         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                 :            :                 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                 :            :                 return -ENOSPC;
     389                 :          0 :         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 __user *buffer, size_t *lenp, loff_t *ppos)
     418                 :            : {
     419                 :            :         const struct nf_logger *logger;
     420                 :            :         char buf[NFLOGGER_NAME_LEN];
     421                 :            :         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                 :          0 :         return r;
     464                 :            : }
     465                 :            : 
     466                 :        207 : static int netfilter_log_sysctl_init(struct net *net)
     467                 :            : {
     468                 :            :         int i;
     469                 :            :         struct ctl_table *table;
     470                 :            : 
     471                 :            :         table = nf_log_sysctl_table;
     472         [ +  - ]:        207 :         if (!net_eq(net, &init_net)) {
     473                 :          0 :                 table = kmemdup(nf_log_sysctl_table,
     474                 :            :                                  sizeof(nf_log_sysctl_table),
     475                 :            :                                  GFP_KERNEL);
     476         [ #  # ]:          0 :                 if (!table)
     477                 :            :                         goto err_alloc;
     478                 :            :         } else {
     479         [ +  + ]:       2691 :                 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
     480                 :       2691 :                         snprintf(nf_log_sysctl_fnames[i],
     481                 :            :                                  3, "%d", i);
     482                 :       2691 :                         nf_log_sysctl_table[i].procname =
     483                 :            :                                 nf_log_sysctl_fnames[i];
     484                 :       2691 :                         nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN;
     485                 :       2691 :                         nf_log_sysctl_table[i].mode = 0644;
     486                 :       2691 :                         nf_log_sysctl_table[i].proc_handler =
     487                 :            :                                 nf_log_proc_dostring;
     488                 :       2691 :                         nf_log_sysctl_table[i].extra1 =
     489                 :       2691 :                                 (void *)(unsigned long) i;
     490                 :            :                 }
     491                 :        207 :                 nf_log_sysctl_fhdr = register_net_sysctl(net, "net/netfilter",
     492                 :            :                                                          nf_log_sysctl_ftable);
     493         [ +  - ]:        207 :                 if (!nf_log_sysctl_fhdr)
     494                 :            :                         goto err_freg;
     495                 :            :         }
     496                 :            : 
     497         [ +  + ]:       2898 :         for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
     498                 :       2691 :                 table[i].extra2 = net;
     499                 :            : 
     500                 :        207 :         net->nf.nf_log_dir_header = register_net_sysctl(net,
     501                 :            :                                                 "net/netfilter/nf_log",
     502                 :            :                                                 table);
     503         [ -  + ]:        207 :         if (!net->nf.nf_log_dir_header)
     504                 :            :                 goto err_reg;
     505                 :            : 
     506                 :            :         return 0;
     507                 :            : 
     508                 :            : err_reg:
     509         [ #  # ]:          0 :         if (!net_eq(net, &init_net))
     510                 :          0 :                 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                 :            :         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                 :          0 :                 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                 :        207 : static int __net_init nf_log_net_init(struct net *net)
     541                 :            : {
     542                 :            :         int ret = -ENOMEM;
     543                 :            : 
     544                 :            : #ifdef CONFIG_PROC_FS
     545         [ +  - ]:        207 :         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                 :        207 :         ret = netfilter_log_sysctl_init(net);
     550         [ -  + ]:        207 :         if (ret < 0)
     551                 :            :                 goto out_sysctl;
     552                 :            : 
     553                 :            :         return 0;
     554                 :            : 
     555                 :            : 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                 :        207 : int __init netfilter_log_init(void)
     576                 :            : {
     577                 :        207 :         return register_pernet_subsys(&nf_log_net_ops);
     578                 :            : }

Generated by: LCOV version 1.14