~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/nf_log.c

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp