|
14 | 14 | LOG target modules */ |
15 | 15 |
|
16 | 16 | #define NF_LOG_PREFIXLEN 128 |
| 17 | +#define NFLOGGER_NAME_LEN 64 |
17 | 18 |
|
18 | 19 | static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; |
19 | 20 | static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; |
@@ -207,18 +208,100 @@ static const struct file_operations nflog_file_ops = { |
207 | 208 | .release = seq_release, |
208 | 209 | }; |
209 | 210 |
|
| 211 | + |
210 | 212 | #endif /* PROC_FS */ |
211 | 213 |
|
| 214 | +#ifdef CONFIG_SYSCTL |
| 215 | +struct ctl_path nf_log_sysctl_path[] = { |
| 216 | + { .procname = "net", .ctl_name = CTL_NET, }, |
| 217 | + { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, |
| 218 | + { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, }, |
| 219 | + { } |
| 220 | +}; |
| 221 | + |
| 222 | +static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; |
| 223 | +static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; |
| 224 | +static struct ctl_table_header *nf_log_dir_header; |
212 | 225 |
|
213 | | -int __init netfilter_log_init(void) |
| 226 | +static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp, |
| 227 | + void *buffer, size_t *lenp, loff_t *ppos) |
| 228 | +{ |
| 229 | + const struct nf_logger *logger; |
| 230 | + int r = 0; |
| 231 | + int tindex = (unsigned long)table->extra1; |
| 232 | + |
| 233 | + if (write) { |
| 234 | + if (!strcmp(buffer, "NONE")) { |
| 235 | + nf_log_unbind_pf(tindex); |
| 236 | + return 0; |
| 237 | + } |
| 238 | + mutex_lock(&nf_log_mutex); |
| 239 | + logger = __find_logger(tindex, buffer); |
| 240 | + if (logger == NULL) { |
| 241 | + mutex_unlock(&nf_log_mutex); |
| 242 | + return -ENOENT; |
| 243 | + } |
| 244 | + rcu_assign_pointer(nf_loggers[tindex], logger); |
| 245 | + mutex_unlock(&nf_log_mutex); |
| 246 | + } else { |
| 247 | + rcu_read_lock(); |
| 248 | + logger = rcu_dereference(nf_loggers[tindex]); |
| 249 | + if (!logger) |
| 250 | + table->data = "NONE"; |
| 251 | + else |
| 252 | + table->data = logger->name; |
| 253 | + r = proc_dostring(table, write, filp, buffer, lenp, ppos); |
| 254 | + rcu_read_unlock(); |
| 255 | + } |
| 256 | + |
| 257 | + return r; |
| 258 | +} |
| 259 | + |
| 260 | +static __init int netfilter_log_sysctl_init(void) |
214 | 261 | { |
215 | 262 | int i; |
| 263 | + |
| 264 | + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { |
| 265 | + snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); |
| 266 | + nf_log_sysctl_table[i].ctl_name = CTL_UNNUMBERED; |
| 267 | + nf_log_sysctl_table[i].procname = |
| 268 | + nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; |
| 269 | + nf_log_sysctl_table[i].data = NULL; |
| 270 | + nf_log_sysctl_table[i].maxlen = |
| 271 | + NFLOGGER_NAME_LEN * sizeof(char); |
| 272 | + nf_log_sysctl_table[i].mode = 0644; |
| 273 | + nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; |
| 274 | + nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; |
| 275 | + } |
| 276 | + |
| 277 | + nf_log_dir_header = register_sysctl_paths(nf_log_sysctl_path, |
| 278 | + nf_log_sysctl_table); |
| 279 | + if (!nf_log_dir_header) |
| 280 | + return -ENOMEM; |
| 281 | + |
| 282 | + return 0; |
| 283 | +} |
| 284 | +#else |
| 285 | +static __init int netfilter_log_sysctl_init(void) |
| 286 | +{ |
| 287 | + return 0; |
| 288 | +} |
| 289 | +#endif /* CONFIG_SYSCTL */ |
| 290 | + |
| 291 | +int __init netfilter_log_init(void) |
| 292 | +{ |
| 293 | + int i, r; |
216 | 294 | #ifdef CONFIG_PROC_FS |
217 | 295 | if (!proc_create("nf_log", S_IRUGO, |
218 | 296 | proc_net_netfilter, &nflog_file_ops)) |
219 | 297 | return -1; |
220 | 298 | #endif |
221 | 299 |
|
| 300 | + /* Errors will trigger panic, unroll on error is unnecessary. */ |
| 301 | + r = netfilter_log_sysctl_init(); |
| 302 | + if (r < 0) |
| 303 | + return r; |
| 304 | + |
222 | 305 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) |
223 | 306 | INIT_LIST_HEAD(&(nf_loggers_l[i])); |
224 | 307 |
|
|
0 commit comments