[NETFILTER]: x_tables: per-netns xt_tables
[safe/jmp/linux-2.6] / net / netfilter / x_tables.c
1 /*
2  * x_tables core - Backend for {ip,ip6,arp}_tables
3  *
4  * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
5  *
6  * Based on existing ip_tables code which is
7  *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
8  *   Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/socket.h>
18 #include <linux/net.h>
19 #include <linux/proc_fs.h>
20 #include <linux/seq_file.h>
21 #include <linux/string.h>
22 #include <linux/vmalloc.h>
23 #include <linux/mutex.h>
24 #include <linux/mm.h>
25 #include <net/net_namespace.h>
26
27 #include <linux/netfilter/x_tables.h>
28 #include <linux/netfilter_arp.h>
29
30
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
33 MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
34
35 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
36
37 struct compat_delta {
38         struct compat_delta *next;
39         unsigned int offset;
40         short delta;
41 };
42
43 struct xt_af {
44         struct mutex mutex;
45         struct list_head match;
46         struct list_head target;
47 #ifdef CONFIG_COMPAT
48         struct mutex compat_mutex;
49         struct compat_delta *compat_offsets;
50 #endif
51 };
52
53 static struct xt_af *xt;
54
55 #ifdef DEBUG_IP_FIREWALL_USER
56 #define duprintf(format, args...) printk(format , ## args)
57 #else
58 #define duprintf(format, args...)
59 #endif
60
61 enum {
62         TABLE,
63         TARGET,
64         MATCH,
65 };
66
67 static const char *xt_prefix[NPROTO] = {
68         [AF_INET]       = "ip",
69         [AF_INET6]      = "ip6",
70         [NF_ARP]        = "arp",
71 };
72
73 /* Registration hooks for targets. */
74 int
75 xt_register_target(struct xt_target *target)
76 {
77         int ret, af = target->family;
78
79         ret = mutex_lock_interruptible(&xt[af].mutex);
80         if (ret != 0)
81                 return ret;
82         list_add(&target->list, &xt[af].target);
83         mutex_unlock(&xt[af].mutex);
84         return ret;
85 }
86 EXPORT_SYMBOL(xt_register_target);
87
88 void
89 xt_unregister_target(struct xt_target *target)
90 {
91         int af = target->family;
92
93         mutex_lock(&xt[af].mutex);
94         list_del(&target->list);
95         mutex_unlock(&xt[af].mutex);
96 }
97 EXPORT_SYMBOL(xt_unregister_target);
98
99 int
100 xt_register_targets(struct xt_target *target, unsigned int n)
101 {
102         unsigned int i;
103         int err = 0;
104
105         for (i = 0; i < n; i++) {
106                 err = xt_register_target(&target[i]);
107                 if (err)
108                         goto err;
109         }
110         return err;
111
112 err:
113         if (i > 0)
114                 xt_unregister_targets(target, i);
115         return err;
116 }
117 EXPORT_SYMBOL(xt_register_targets);
118
119 void
120 xt_unregister_targets(struct xt_target *target, unsigned int n)
121 {
122         unsigned int i;
123
124         for (i = 0; i < n; i++)
125                 xt_unregister_target(&target[i]);
126 }
127 EXPORT_SYMBOL(xt_unregister_targets);
128
129 int
130 xt_register_match(struct xt_match *match)
131 {
132         int ret, af = match->family;
133
134         ret = mutex_lock_interruptible(&xt[af].mutex);
135         if (ret != 0)
136                 return ret;
137
138         list_add(&match->list, &xt[af].match);
139         mutex_unlock(&xt[af].mutex);
140
141         return ret;
142 }
143 EXPORT_SYMBOL(xt_register_match);
144
145 void
146 xt_unregister_match(struct xt_match *match)
147 {
148         int af =  match->family;
149
150         mutex_lock(&xt[af].mutex);
151         list_del(&match->list);
152         mutex_unlock(&xt[af].mutex);
153 }
154 EXPORT_SYMBOL(xt_unregister_match);
155
156 int
157 xt_register_matches(struct xt_match *match, unsigned int n)
158 {
159         unsigned int i;
160         int err = 0;
161
162         for (i = 0; i < n; i++) {
163                 err = xt_register_match(&match[i]);
164                 if (err)
165                         goto err;
166         }
167         return err;
168
169 err:
170         if (i > 0)
171                 xt_unregister_matches(match, i);
172         return err;
173 }
174 EXPORT_SYMBOL(xt_register_matches);
175
176 void
177 xt_unregister_matches(struct xt_match *match, unsigned int n)
178 {
179         unsigned int i;
180
181         for (i = 0; i < n; i++)
182                 xt_unregister_match(&match[i]);
183 }
184 EXPORT_SYMBOL(xt_unregister_matches);
185
186
187 /*
188  * These are weird, but module loading must not be done with mutex
189  * held (since they will register), and we have to have a single
190  * function to use try_then_request_module().
191  */
192
193 /* Find match, grabs ref.  Returns ERR_PTR() on error. */
194 struct xt_match *xt_find_match(int af, const char *name, u8 revision)
195 {
196         struct xt_match *m;
197         int err = 0;
198
199         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
200                 return ERR_PTR(-EINTR);
201
202         list_for_each_entry(m, &xt[af].match, list) {
203                 if (strcmp(m->name, name) == 0) {
204                         if (m->revision == revision) {
205                                 if (try_module_get(m->me)) {
206                                         mutex_unlock(&xt[af].mutex);
207                                         return m;
208                                 }
209                         } else
210                                 err = -EPROTOTYPE; /* Found something. */
211                 }
212         }
213         mutex_unlock(&xt[af].mutex);
214         return ERR_PTR(err);
215 }
216 EXPORT_SYMBOL(xt_find_match);
217
218 /* Find target, grabs ref.  Returns ERR_PTR() on error. */
219 struct xt_target *xt_find_target(int af, const char *name, u8 revision)
220 {
221         struct xt_target *t;
222         int err = 0;
223
224         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
225                 return ERR_PTR(-EINTR);
226
227         list_for_each_entry(t, &xt[af].target, list) {
228                 if (strcmp(t->name, name) == 0) {
229                         if (t->revision == revision) {
230                                 if (try_module_get(t->me)) {
231                                         mutex_unlock(&xt[af].mutex);
232                                         return t;
233                                 }
234                         } else
235                                 err = -EPROTOTYPE; /* Found something. */
236                 }
237         }
238         mutex_unlock(&xt[af].mutex);
239         return ERR_PTR(err);
240 }
241 EXPORT_SYMBOL(xt_find_target);
242
243 struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
244 {
245         struct xt_target *target;
246
247         target = try_then_request_module(xt_find_target(af, name, revision),
248                                          "%st_%s", xt_prefix[af], name);
249         if (IS_ERR(target) || !target)
250                 return NULL;
251         return target;
252 }
253 EXPORT_SYMBOL_GPL(xt_request_find_target);
254
255 static int match_revfn(int af, const char *name, u8 revision, int *bestp)
256 {
257         struct xt_match *m;
258         int have_rev = 0;
259
260         list_for_each_entry(m, &xt[af].match, list) {
261                 if (strcmp(m->name, name) == 0) {
262                         if (m->revision > *bestp)
263                                 *bestp = m->revision;
264                         if (m->revision == revision)
265                                 have_rev = 1;
266                 }
267         }
268         return have_rev;
269 }
270
271 static int target_revfn(int af, const char *name, u8 revision, int *bestp)
272 {
273         struct xt_target *t;
274         int have_rev = 0;
275
276         list_for_each_entry(t, &xt[af].target, list) {
277                 if (strcmp(t->name, name) == 0) {
278                         if (t->revision > *bestp)
279                                 *bestp = t->revision;
280                         if (t->revision == revision)
281                                 have_rev = 1;
282                 }
283         }
284         return have_rev;
285 }
286
287 /* Returns true or false (if no such extension at all) */
288 int xt_find_revision(int af, const char *name, u8 revision, int target,
289                      int *err)
290 {
291         int have_rev, best = -1;
292
293         if (mutex_lock_interruptible(&xt[af].mutex) != 0) {
294                 *err = -EINTR;
295                 return 1;
296         }
297         if (target == 1)
298                 have_rev = target_revfn(af, name, revision, &best);
299         else
300                 have_rev = match_revfn(af, name, revision, &best);
301         mutex_unlock(&xt[af].mutex);
302
303         /* Nothing at all?  Return 0 to try loading module. */
304         if (best == -1) {
305                 *err = -ENOENT;
306                 return 0;
307         }
308
309         *err = best;
310         if (!have_rev)
311                 *err = -EPROTONOSUPPORT;
312         return 1;
313 }
314 EXPORT_SYMBOL_GPL(xt_find_revision);
315
316 int xt_check_match(const struct xt_match *match, unsigned short family,
317                    unsigned int size, const char *table, unsigned int hook_mask,
318                    unsigned short proto, int inv_proto)
319 {
320         if (XT_ALIGN(match->matchsize) != size) {
321                 printk("%s_tables: %s match: invalid size %Zu != %u\n",
322                        xt_prefix[family], match->name,
323                        XT_ALIGN(match->matchsize), size);
324                 return -EINVAL;
325         }
326         if (match->table && strcmp(match->table, table)) {
327                 printk("%s_tables: %s match: only valid in %s table, not %s\n",
328                        xt_prefix[family], match->name, match->table, table);
329                 return -EINVAL;
330         }
331         if (match->hooks && (hook_mask & ~match->hooks) != 0) {
332                 printk("%s_tables: %s match: bad hook_mask %u/%u\n",
333                        xt_prefix[family], match->name, hook_mask, match->hooks);
334                 return -EINVAL;
335         }
336         if (match->proto && (match->proto != proto || inv_proto)) {
337                 printk("%s_tables: %s match: only valid for protocol %u\n",
338                        xt_prefix[family], match->name, match->proto);
339                 return -EINVAL;
340         }
341         return 0;
342 }
343 EXPORT_SYMBOL_GPL(xt_check_match);
344
345 #ifdef CONFIG_COMPAT
346 int xt_compat_add_offset(int af, unsigned int offset, short delta)
347 {
348         struct compat_delta *tmp;
349
350         tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
351         if (!tmp)
352                 return -ENOMEM;
353
354         tmp->offset = offset;
355         tmp->delta = delta;
356
357         if (xt[af].compat_offsets) {
358                 tmp->next = xt[af].compat_offsets->next;
359                 xt[af].compat_offsets->next = tmp;
360         } else {
361                 xt[af].compat_offsets = tmp;
362                 tmp->next = NULL;
363         }
364         return 0;
365 }
366 EXPORT_SYMBOL_GPL(xt_compat_add_offset);
367
368 void xt_compat_flush_offsets(int af)
369 {
370         struct compat_delta *tmp, *next;
371
372         if (xt[af].compat_offsets) {
373                 for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
374                         next = tmp->next;
375                         kfree(tmp);
376                 }
377                 xt[af].compat_offsets = NULL;
378         }
379 }
380 EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
381
382 short xt_compat_calc_jump(int af, unsigned int offset)
383 {
384         struct compat_delta *tmp;
385         short delta;
386
387         for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
388                 if (tmp->offset < offset)
389                         delta += tmp->delta;
390         return delta;
391 }
392 EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
393
394 int xt_compat_match_offset(struct xt_match *match)
395 {
396         u_int16_t csize = match->compatsize ? : match->matchsize;
397         return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
398 }
399 EXPORT_SYMBOL_GPL(xt_compat_match_offset);
400
401 int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
402                               int *size)
403 {
404         struct xt_match *match = m->u.kernel.match;
405         struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
406         int pad, off = xt_compat_match_offset(match);
407         u_int16_t msize = cm->u.user.match_size;
408
409         m = *dstptr;
410         memcpy(m, cm, sizeof(*cm));
411         if (match->compat_from_user)
412                 match->compat_from_user(m->data, cm->data);
413         else
414                 memcpy(m->data, cm->data, msize - sizeof(*cm));
415         pad = XT_ALIGN(match->matchsize) - match->matchsize;
416         if (pad > 0)
417                 memset(m->data + match->matchsize, 0, pad);
418
419         msize += off;
420         m->u.user.match_size = msize;
421
422         *size += off;
423         *dstptr += msize;
424         return 0;
425 }
426 EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
427
428 int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
429                             int *size)
430 {
431         struct xt_match *match = m->u.kernel.match;
432         struct compat_xt_entry_match __user *cm = *dstptr;
433         int off = xt_compat_match_offset(match);
434         u_int16_t msize = m->u.user.match_size - off;
435
436         if (copy_to_user(cm, m, sizeof(*cm)) ||
437             put_user(msize, &cm->u.user.match_size) ||
438             copy_to_user(cm->u.user.name, m->u.kernel.match->name,
439                          strlen(m->u.kernel.match->name) + 1))
440                 return -EFAULT;
441
442         if (match->compat_to_user) {
443                 if (match->compat_to_user((void __user *)cm->data, m->data))
444                         return -EFAULT;
445         } else {
446                 if (copy_to_user(cm->data, m->data, msize - sizeof(*cm)))
447                         return -EFAULT;
448         }
449
450         *size -= off;
451         *dstptr += msize;
452         return 0;
453 }
454 EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
455 #endif /* CONFIG_COMPAT */
456
457 int xt_check_target(const struct xt_target *target, unsigned short family,
458                     unsigned int size, const char *table, unsigned int hook_mask,
459                     unsigned short proto, int inv_proto)
460 {
461         if (XT_ALIGN(target->targetsize) != size) {
462                 printk("%s_tables: %s target: invalid size %Zu != %u\n",
463                        xt_prefix[family], target->name,
464                        XT_ALIGN(target->targetsize), size);
465                 return -EINVAL;
466         }
467         if (target->table && strcmp(target->table, table)) {
468                 printk("%s_tables: %s target: only valid in %s table, not %s\n",
469                        xt_prefix[family], target->name, target->table, table);
470                 return -EINVAL;
471         }
472         if (target->hooks && (hook_mask & ~target->hooks) != 0) {
473                 printk("%s_tables: %s target: bad hook_mask %u/%u\n",
474                        xt_prefix[family], target->name, hook_mask,
475                        target->hooks);
476                 return -EINVAL;
477         }
478         if (target->proto && (target->proto != proto || inv_proto)) {
479                 printk("%s_tables: %s target: only valid for protocol %u\n",
480                        xt_prefix[family], target->name, target->proto);
481                 return -EINVAL;
482         }
483         return 0;
484 }
485 EXPORT_SYMBOL_GPL(xt_check_target);
486
487 #ifdef CONFIG_COMPAT
488 int xt_compat_target_offset(struct xt_target *target)
489 {
490         u_int16_t csize = target->compatsize ? : target->targetsize;
491         return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
492 }
493 EXPORT_SYMBOL_GPL(xt_compat_target_offset);
494
495 void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
496                                 int *size)
497 {
498         struct xt_target *target = t->u.kernel.target;
499         struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
500         int pad, off = xt_compat_target_offset(target);
501         u_int16_t tsize = ct->u.user.target_size;
502
503         t = *dstptr;
504         memcpy(t, ct, sizeof(*ct));
505         if (target->compat_from_user)
506                 target->compat_from_user(t->data, ct->data);
507         else
508                 memcpy(t->data, ct->data, tsize - sizeof(*ct));
509         pad = XT_ALIGN(target->targetsize) - target->targetsize;
510         if (pad > 0)
511                 memset(t->data + target->targetsize, 0, pad);
512
513         tsize += off;
514         t->u.user.target_size = tsize;
515
516         *size += off;
517         *dstptr += tsize;
518 }
519 EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
520
521 int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
522                              int *size)
523 {
524         struct xt_target *target = t->u.kernel.target;
525         struct compat_xt_entry_target __user *ct = *dstptr;
526         int off = xt_compat_target_offset(target);
527         u_int16_t tsize = t->u.user.target_size - off;
528
529         if (copy_to_user(ct, t, sizeof(*ct)) ||
530             put_user(tsize, &ct->u.user.target_size) ||
531             copy_to_user(ct->u.user.name, t->u.kernel.target->name,
532                          strlen(t->u.kernel.target->name) + 1))
533                 return -EFAULT;
534
535         if (target->compat_to_user) {
536                 if (target->compat_to_user((void __user *)ct->data, t->data))
537                         return -EFAULT;
538         } else {
539                 if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct)))
540                         return -EFAULT;
541         }
542
543         *size -= off;
544         *dstptr += tsize;
545         return 0;
546 }
547 EXPORT_SYMBOL_GPL(xt_compat_target_to_user);
548 #endif
549
550 struct xt_table_info *xt_alloc_table_info(unsigned int size)
551 {
552         struct xt_table_info *newinfo;
553         int cpu;
554
555         /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
556         if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
557                 return NULL;
558
559         newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL);
560         if (!newinfo)
561                 return NULL;
562
563         newinfo->size = size;
564
565         for_each_possible_cpu(cpu) {
566                 if (size <= PAGE_SIZE)
567                         newinfo->entries[cpu] = kmalloc_node(size,
568                                                         GFP_KERNEL,
569                                                         cpu_to_node(cpu));
570                 else
571                         newinfo->entries[cpu] = vmalloc_node(size,
572                                                         cpu_to_node(cpu));
573
574                 if (newinfo->entries[cpu] == NULL) {
575                         xt_free_table_info(newinfo);
576                         return NULL;
577                 }
578         }
579
580         return newinfo;
581 }
582 EXPORT_SYMBOL(xt_alloc_table_info);
583
584 void xt_free_table_info(struct xt_table_info *info)
585 {
586         int cpu;
587
588         for_each_possible_cpu(cpu) {
589                 if (info->size <= PAGE_SIZE)
590                         kfree(info->entries[cpu]);
591                 else
592                         vfree(info->entries[cpu]);
593         }
594         kfree(info);
595 }
596 EXPORT_SYMBOL(xt_free_table_info);
597
598 /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
599 struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name)
600 {
601         struct xt_table *t;
602
603         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
604                 return ERR_PTR(-EINTR);
605
606         list_for_each_entry(t, &net->xt.tables[af], list)
607                 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
608                         return t;
609         mutex_unlock(&xt[af].mutex);
610         return NULL;
611 }
612 EXPORT_SYMBOL_GPL(xt_find_table_lock);
613
614 void xt_table_unlock(struct xt_table *table)
615 {
616         mutex_unlock(&xt[table->af].mutex);
617 }
618 EXPORT_SYMBOL_GPL(xt_table_unlock);
619
620 #ifdef CONFIG_COMPAT
621 void xt_compat_lock(int af)
622 {
623         mutex_lock(&xt[af].compat_mutex);
624 }
625 EXPORT_SYMBOL_GPL(xt_compat_lock);
626
627 void xt_compat_unlock(int af)
628 {
629         mutex_unlock(&xt[af].compat_mutex);
630 }
631 EXPORT_SYMBOL_GPL(xt_compat_unlock);
632 #endif
633
634 struct xt_table_info *
635 xt_replace_table(struct xt_table *table,
636               unsigned int num_counters,
637               struct xt_table_info *newinfo,
638               int *error)
639 {
640         struct xt_table_info *oldinfo, *private;
641
642         /* Do the substitution. */
643         write_lock_bh(&table->lock);
644         private = table->private;
645         /* Check inside lock: is the old number correct? */
646         if (num_counters != private->number) {
647                 duprintf("num_counters != table->private->number (%u/%u)\n",
648                          num_counters, private->number);
649                 write_unlock_bh(&table->lock);
650                 *error = -EAGAIN;
651                 return NULL;
652         }
653         oldinfo = private;
654         table->private = newinfo;
655         newinfo->initial_entries = oldinfo->initial_entries;
656         write_unlock_bh(&table->lock);
657
658         return oldinfo;
659 }
660 EXPORT_SYMBOL_GPL(xt_replace_table);
661
662 struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
663                                    struct xt_table_info *bootstrap,
664                                    struct xt_table_info *newinfo)
665 {
666         int ret;
667         struct xt_table_info *private;
668         struct xt_table *t;
669
670         ret = mutex_lock_interruptible(&xt[table->af].mutex);
671         if (ret != 0)
672                 goto out;
673
674         /* Don't autoload: we'd eat our tail... */
675         list_for_each_entry(t, &net->xt.tables[table->af], list) {
676                 if (strcmp(t->name, table->name) == 0) {
677                         ret = -EEXIST;
678                         goto unlock;
679                 }
680         }
681
682         /* Simplifies replace_table code. */
683         table->private = bootstrap;
684         rwlock_init(&table->lock);
685         if (!xt_replace_table(table, 0, newinfo, &ret))
686                 goto unlock;
687
688         private = table->private;
689         duprintf("table->private->number = %u\n", private->number);
690
691         /* save number of initial entries */
692         private->initial_entries = private->number;
693
694         list_add(&table->list, &net->xt.tables[table->af]);
695         mutex_unlock(&xt[table->af].mutex);
696         return table;
697
698  unlock:
699         mutex_unlock(&xt[table->af].mutex);
700 out:
701         return ERR_PTR(ret);
702 }
703 EXPORT_SYMBOL_GPL(xt_register_table);
704
705 void *xt_unregister_table(struct xt_table *table)
706 {
707         struct xt_table_info *private;
708
709         mutex_lock(&xt[table->af].mutex);
710         private = table->private;
711         list_del(&table->list);
712         mutex_unlock(&xt[table->af].mutex);
713
714         return private;
715 }
716 EXPORT_SYMBOL_GPL(xt_unregister_table);
717
718 #ifdef CONFIG_PROC_FS
719 static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
720 {
721         struct list_head *head = list->next;
722
723         if (!head || list_empty(list))
724                 return NULL;
725
726         while (pos && (head = head->next)) {
727                 if (head == list)
728                         return NULL;
729                 pos--;
730         }
731         return pos ? NULL : head;
732 }
733
734 static struct list_head *type2list(u_int16_t af, u_int16_t type)
735 {
736         struct list_head *list;
737
738         switch (type) {
739         case TARGET:
740                 list = &xt[af].target;
741                 break;
742         case MATCH:
743                 list = &xt[af].match;
744                 break;
745         case TABLE:
746                 list = &init_net.xt.tables[af];
747                 break;
748         default:
749                 list = NULL;
750                 break;
751         }
752
753         return list;
754 }
755
756 static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
757 {
758         struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
759         u_int16_t af = (unsigned long)pde->data & 0xffff;
760         u_int16_t type = (unsigned long)pde->data >> 16;
761         struct list_head *list;
762
763         if (af >= NPROTO)
764                 return NULL;
765
766         list = type2list(af, type);
767         if (!list)
768                 return NULL;
769
770         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
771                 return NULL;
772
773         return xt_get_idx(list, seq, *pos);
774 }
775
776 static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
777 {
778         struct proc_dir_entry *pde = seq->private;
779         u_int16_t af = (unsigned long)pde->data & 0xffff;
780         u_int16_t type = (unsigned long)pde->data >> 16;
781         struct list_head *list;
782
783         if (af >= NPROTO)
784                 return NULL;
785
786         list = type2list(af, type);
787         if (!list)
788                 return NULL;
789
790         (*pos)++;
791         return xt_get_idx(list, seq, *pos);
792 }
793
794 static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
795 {
796         struct proc_dir_entry *pde = seq->private;
797         u_int16_t af = (unsigned long)pde->data & 0xffff;
798
799         mutex_unlock(&xt[af].mutex);
800 }
801
802 static int xt_name_seq_show(struct seq_file *seq, void *v)
803 {
804         char *name = (char *)v + sizeof(struct list_head);
805
806         if (strlen(name))
807                 return seq_printf(seq, "%s\n", name);
808         else
809                 return 0;
810 }
811
812 static const struct seq_operations xt_tgt_seq_ops = {
813         .start  = xt_tgt_seq_start,
814         .next   = xt_tgt_seq_next,
815         .stop   = xt_tgt_seq_stop,
816         .show   = xt_name_seq_show,
817 };
818
819 static int xt_tgt_open(struct inode *inode, struct file *file)
820 {
821         int ret;
822
823         ret = seq_open(file, &xt_tgt_seq_ops);
824         if (!ret) {
825                 struct seq_file *seq = file->private_data;
826                 struct proc_dir_entry *pde = PDE(inode);
827
828                 seq->private = pde;
829         }
830
831         return ret;
832 }
833
834 static const struct file_operations xt_file_ops = {
835         .owner   = THIS_MODULE,
836         .open    = xt_tgt_open,
837         .read    = seq_read,
838         .llseek  = seq_lseek,
839         .release = seq_release,
840 };
841
842 #define FORMAT_TABLES   "_tables_names"
843 #define FORMAT_MATCHES  "_tables_matches"
844 #define FORMAT_TARGETS  "_tables_targets"
845
846 #endif /* CONFIG_PROC_FS */
847
848 int xt_proto_init(int af)
849 {
850 #ifdef CONFIG_PROC_FS
851         char buf[XT_FUNCTION_MAXNAMELEN];
852         struct proc_dir_entry *proc;
853 #endif
854
855         if (af >= NPROTO)
856                 return -EINVAL;
857
858
859 #ifdef CONFIG_PROC_FS
860         strlcpy(buf, xt_prefix[af], sizeof(buf));
861         strlcat(buf, FORMAT_TABLES, sizeof(buf));
862         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
863         if (!proc)
864                 goto out;
865         proc->data = (void *) ((unsigned long) af | (TABLE << 16));
866
867
868         strlcpy(buf, xt_prefix[af], sizeof(buf));
869         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
870         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
871         if (!proc)
872                 goto out_remove_tables;
873         proc->data = (void *) ((unsigned long) af | (MATCH << 16));
874
875         strlcpy(buf, xt_prefix[af], sizeof(buf));
876         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
877         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
878         if (!proc)
879                 goto out_remove_matches;
880         proc->data = (void *) ((unsigned long) af | (TARGET << 16));
881 #endif
882
883         return 0;
884
885 #ifdef CONFIG_PROC_FS
886 out_remove_matches:
887         strlcpy(buf, xt_prefix[af], sizeof(buf));
888         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
889         proc_net_remove(&init_net, buf);
890
891 out_remove_tables:
892         strlcpy(buf, xt_prefix[af], sizeof(buf));
893         strlcat(buf, FORMAT_TABLES, sizeof(buf));
894         proc_net_remove(&init_net, buf);
895 out:
896         return -1;
897 #endif
898 }
899 EXPORT_SYMBOL_GPL(xt_proto_init);
900
901 void xt_proto_fini(int af)
902 {
903 #ifdef CONFIG_PROC_FS
904         char buf[XT_FUNCTION_MAXNAMELEN];
905
906         strlcpy(buf, xt_prefix[af], sizeof(buf));
907         strlcat(buf, FORMAT_TABLES, sizeof(buf));
908         proc_net_remove(&init_net, buf);
909
910         strlcpy(buf, xt_prefix[af], sizeof(buf));
911         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
912         proc_net_remove(&init_net, buf);
913
914         strlcpy(buf, xt_prefix[af], sizeof(buf));
915         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
916         proc_net_remove(&init_net, buf);
917 #endif /*CONFIG_PROC_FS*/
918 }
919 EXPORT_SYMBOL_GPL(xt_proto_fini);
920
921 static int __net_init xt_net_init(struct net *net)
922 {
923         int i;
924
925         for (i = 0; i < NPROTO; i++)
926                 INIT_LIST_HEAD(&net->xt.tables[i]);
927         return 0;
928 }
929
930 static struct pernet_operations xt_net_ops = {
931         .init = xt_net_init,
932 };
933
934 static int __init xt_init(void)
935 {
936         int i, rv;
937
938         xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
939         if (!xt)
940                 return -ENOMEM;
941
942         for (i = 0; i < NPROTO; i++) {
943                 mutex_init(&xt[i].mutex);
944 #ifdef CONFIG_COMPAT
945                 mutex_init(&xt[i].compat_mutex);
946                 xt[i].compat_offsets = NULL;
947 #endif
948                 INIT_LIST_HEAD(&xt[i].target);
949                 INIT_LIST_HEAD(&xt[i].match);
950         }
951         rv = register_pernet_subsys(&xt_net_ops);
952         if (rv < 0)
953                 kfree(xt);
954         return rv;
955 }
956
957 static void __exit xt_fini(void)
958 {
959         unregister_pernet_subsys(&xt_net_ops);
960         kfree(xt);
961 }
962
963 module_init(xt_init);
964 module_exit(xt_fini);
965