netfilter: move Ebtables to use Xtables
[linux-2.6.git] / 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,eb}_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 static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
62         [NFPROTO_UNSPEC] = "x",
63         [NFPROTO_IPV4]   = "ip",
64         [NFPROTO_ARP]    = "arp",
65         [NFPROTO_BRIDGE] = "eb",
66         [NFPROTO_IPV6]   = "ip6",
67 };
68
69 /* Registration hooks for targets. */
70 int
71 xt_register_target(struct xt_target *target)
72 {
73         u_int8_t af = target->family;
74         int ret;
75
76         ret = mutex_lock_interruptible(&xt[af].mutex);
77         if (ret != 0)
78                 return ret;
79         list_add(&target->list, &xt[af].target);
80         mutex_unlock(&xt[af].mutex);
81         return ret;
82 }
83 EXPORT_SYMBOL(xt_register_target);
84
85 void
86 xt_unregister_target(struct xt_target *target)
87 {
88         u_int8_t af = target->family;
89
90         mutex_lock(&xt[af].mutex);
91         list_del(&target->list);
92         mutex_unlock(&xt[af].mutex);
93 }
94 EXPORT_SYMBOL(xt_unregister_target);
95
96 int
97 xt_register_targets(struct xt_target *target, unsigned int n)
98 {
99         unsigned int i;
100         int err = 0;
101
102         for (i = 0; i < n; i++) {
103                 err = xt_register_target(&target[i]);
104                 if (err)
105                         goto err;
106         }
107         return err;
108
109 err:
110         if (i > 0)
111                 xt_unregister_targets(target, i);
112         return err;
113 }
114 EXPORT_SYMBOL(xt_register_targets);
115
116 void
117 xt_unregister_targets(struct xt_target *target, unsigned int n)
118 {
119         unsigned int i;
120
121         for (i = 0; i < n; i++)
122                 xt_unregister_target(&target[i]);
123 }
124 EXPORT_SYMBOL(xt_unregister_targets);
125
126 int
127 xt_register_match(struct xt_match *match)
128 {
129         u_int8_t af = match->family;
130         int ret;
131
132         ret = mutex_lock_interruptible(&xt[af].mutex);
133         if (ret != 0)
134                 return ret;
135
136         list_add(&match->list, &xt[af].match);
137         mutex_unlock(&xt[af].mutex);
138
139         return ret;
140 }
141 EXPORT_SYMBOL(xt_register_match);
142
143 void
144 xt_unregister_match(struct xt_match *match)
145 {
146         u_int8_t af = match->family;
147
148         mutex_lock(&xt[af].mutex);
149         list_del(&match->list);
150         mutex_unlock(&xt[af].mutex);
151 }
152 EXPORT_SYMBOL(xt_unregister_match);
153
154 int
155 xt_register_matches(struct xt_match *match, unsigned int n)
156 {
157         unsigned int i;
158         int err = 0;
159
160         for (i = 0; i < n; i++) {
161                 err = xt_register_match(&match[i]);
162                 if (err)
163                         goto err;
164         }
165         return err;
166
167 err:
168         if (i > 0)
169                 xt_unregister_matches(match, i);
170         return err;
171 }
172 EXPORT_SYMBOL(xt_register_matches);
173
174 void
175 xt_unregister_matches(struct xt_match *match, unsigned int n)
176 {
177         unsigned int i;
178
179         for (i = 0; i < n; i++)
180                 xt_unregister_match(&match[i]);
181 }
182 EXPORT_SYMBOL(xt_unregister_matches);
183
184
185 /*
186  * These are weird, but module loading must not be done with mutex
187  * held (since they will register), and we have to have a single
188  * function to use try_then_request_module().
189  */
190
191 /* Find match, grabs ref.  Returns ERR_PTR() on error. */
192 struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
193 {
194         struct xt_match *m;
195         int err = 0;
196
197         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
198                 return ERR_PTR(-EINTR);
199
200         list_for_each_entry(m, &xt[af].match, list) {
201                 if (strcmp(m->name, name) == 0) {
202                         if (m->revision == revision) {
203                                 if (try_module_get(m->me)) {
204                                         mutex_unlock(&xt[af].mutex);
205                                         return m;
206                                 }
207                         } else
208                                 err = -EPROTOTYPE; /* Found something. */
209                 }
210         }
211         mutex_unlock(&xt[af].mutex);
212
213         if (af != NFPROTO_UNSPEC)
214                 /* Try searching again in the family-independent list */
215                 return xt_find_match(NFPROTO_UNSPEC, name, revision);
216
217         return ERR_PTR(err);
218 }
219 EXPORT_SYMBOL(xt_find_match);
220
221 /* Find target, grabs ref.  Returns ERR_PTR() on error. */
222 struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
223 {
224         struct xt_target *t;
225         int err = 0;
226
227         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
228                 return ERR_PTR(-EINTR);
229
230         list_for_each_entry(t, &xt[af].target, list) {
231                 if (strcmp(t->name, name) == 0) {
232                         if (t->revision == revision) {
233                                 if (try_module_get(t->me)) {
234                                         mutex_unlock(&xt[af].mutex);
235                                         return t;
236                                 }
237                         } else
238                                 err = -EPROTOTYPE; /* Found something. */
239                 }
240         }
241         mutex_unlock(&xt[af].mutex);
242
243         if (af != NFPROTO_UNSPEC)
244                 /* Try searching again in the family-independent list */
245                 return xt_find_target(NFPROTO_UNSPEC, name, revision);
246
247         return ERR_PTR(err);
248 }
249 EXPORT_SYMBOL(xt_find_target);
250
251 struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision)
252 {
253         struct xt_target *target;
254
255         target = try_then_request_module(xt_find_target(af, name, revision),
256                                          "%st_%s", xt_prefix[af], name);
257         if (IS_ERR(target) || !target)
258                 return NULL;
259         return target;
260 }
261 EXPORT_SYMBOL_GPL(xt_request_find_target);
262
263 static int match_revfn(u8 af, const char *name, u8 revision, int *bestp)
264 {
265         const struct xt_match *m;
266         int have_rev = 0;
267
268         list_for_each_entry(m, &xt[af].match, list) {
269                 if (strcmp(m->name, name) == 0) {
270                         if (m->revision > *bestp)
271                                 *bestp = m->revision;
272                         if (m->revision == revision)
273                                 have_rev = 1;
274                 }
275         }
276         return have_rev;
277 }
278
279 static int target_revfn(u8 af, const char *name, u8 revision, int *bestp)
280 {
281         const struct xt_target *t;
282         int have_rev = 0;
283
284         list_for_each_entry(t, &xt[af].target, list) {
285                 if (strcmp(t->name, name) == 0) {
286                         if (t->revision > *bestp)
287                                 *bestp = t->revision;
288                         if (t->revision == revision)
289                                 have_rev = 1;
290                 }
291         }
292         return have_rev;
293 }
294
295 /* Returns true or false (if no such extension at all) */
296 int xt_find_revision(u8 af, const char *name, u8 revision, int target,
297                      int *err)
298 {
299         int have_rev, best = -1;
300
301         if (mutex_lock_interruptible(&xt[af].mutex) != 0) {
302                 *err = -EINTR;
303                 return 1;
304         }
305         if (target == 1)
306                 have_rev = target_revfn(af, name, revision, &best);
307         else
308                 have_rev = match_revfn(af, name, revision, &best);
309         mutex_unlock(&xt[af].mutex);
310
311         /* Nothing at all?  Return 0 to try loading module. */
312         if (best == -1) {
313                 *err = -ENOENT;
314                 return 0;
315         }
316
317         *err = best;
318         if (!have_rev)
319                 *err = -EPROTONOSUPPORT;
320         return 1;
321 }
322 EXPORT_SYMBOL_GPL(xt_find_revision);
323
324 int xt_check_match(const struct xt_match *match, unsigned short family,
325                    unsigned int size, const char *table, unsigned int hook_mask,
326                    unsigned short proto, int inv_proto)
327 {
328         if (XT_ALIGN(match->matchsize) != size &&
329             match->matchsize != -1) {
330                 /*
331                  * ebt_among is exempt from centralized matchsize checking
332                  * because it uses a dynamic-size data set.
333                  */
334                 printk("%s_tables: %s match: invalid size %Zu != %u\n",
335                        xt_prefix[family], match->name,
336                        XT_ALIGN(match->matchsize), size);
337                 return -EINVAL;
338         }
339         if (match->table && strcmp(match->table, table)) {
340                 printk("%s_tables: %s match: only valid in %s table, not %s\n",
341                        xt_prefix[family], match->name, match->table, table);
342                 return -EINVAL;
343         }
344         if (match->hooks && (hook_mask & ~match->hooks) != 0) {
345                 printk("%s_tables: %s match: bad hook_mask %u/%u\n",
346                        xt_prefix[family], match->name, hook_mask, match->hooks);
347                 return -EINVAL;
348         }
349         if (match->proto && (match->proto != proto || inv_proto)) {
350                 printk("%s_tables: %s match: only valid for protocol %u\n",
351                        xt_prefix[family], match->name, match->proto);
352                 return -EINVAL;
353         }
354         return 0;
355 }
356 EXPORT_SYMBOL_GPL(xt_check_match);
357
358 #ifdef CONFIG_COMPAT
359 int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta)
360 {
361         struct compat_delta *tmp;
362
363         tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
364         if (!tmp)
365                 return -ENOMEM;
366
367         tmp->offset = offset;
368         tmp->delta = delta;
369
370         if (xt[af].compat_offsets) {
371                 tmp->next = xt[af].compat_offsets->next;
372                 xt[af].compat_offsets->next = tmp;
373         } else {
374                 xt[af].compat_offsets = tmp;
375                 tmp->next = NULL;
376         }
377         return 0;
378 }
379 EXPORT_SYMBOL_GPL(xt_compat_add_offset);
380
381 void xt_compat_flush_offsets(u_int8_t af)
382 {
383         struct compat_delta *tmp, *next;
384
385         if (xt[af].compat_offsets) {
386                 for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
387                         next = tmp->next;
388                         kfree(tmp);
389                 }
390                 xt[af].compat_offsets = NULL;
391         }
392 }
393 EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
394
395 short xt_compat_calc_jump(u_int8_t af, unsigned int offset)
396 {
397         struct compat_delta *tmp;
398         short delta;
399
400         for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
401                 if (tmp->offset < offset)
402                         delta += tmp->delta;
403         return delta;
404 }
405 EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
406
407 int xt_compat_match_offset(const struct xt_match *match)
408 {
409         u_int16_t csize = match->compatsize ? : match->matchsize;
410         return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
411 }
412 EXPORT_SYMBOL_GPL(xt_compat_match_offset);
413
414 int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
415                               unsigned int *size)
416 {
417         const struct xt_match *match = m->u.kernel.match;
418         struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
419         int pad, off = xt_compat_match_offset(match);
420         u_int16_t msize = cm->u.user.match_size;
421
422         m = *dstptr;
423         memcpy(m, cm, sizeof(*cm));
424         if (match->compat_from_user)
425                 match->compat_from_user(m->data, cm->data);
426         else
427                 memcpy(m->data, cm->data, msize - sizeof(*cm));
428         pad = XT_ALIGN(match->matchsize) - match->matchsize;
429         if (pad > 0)
430                 memset(m->data + match->matchsize, 0, pad);
431
432         msize += off;
433         m->u.user.match_size = msize;
434
435         *size += off;
436         *dstptr += msize;
437         return 0;
438 }
439 EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
440
441 int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
442                             unsigned int *size)
443 {
444         const struct xt_match *match = m->u.kernel.match;
445         struct compat_xt_entry_match __user *cm = *dstptr;
446         int off = xt_compat_match_offset(match);
447         u_int16_t msize = m->u.user.match_size - off;
448
449         if (copy_to_user(cm, m, sizeof(*cm)) ||
450             put_user(msize, &cm->u.user.match_size) ||
451             copy_to_user(cm->u.user.name, m->u.kernel.match->name,
452                          strlen(m->u.kernel.match->name) + 1))
453                 return -EFAULT;
454
455         if (match->compat_to_user) {
456                 if (match->compat_to_user((void __user *)cm->data, m->data))
457                         return -EFAULT;
458         } else {
459                 if (copy_to_user(cm->data, m->data, msize - sizeof(*cm)))
460                         return -EFAULT;
461         }
462
463         *size -= off;
464         *dstptr += msize;
465         return 0;
466 }
467 EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
468 #endif /* CONFIG_COMPAT */
469
470 int xt_check_target(const struct xt_target *target, unsigned short family,
471                     unsigned int size, const char *table, unsigned int hook_mask,
472                     unsigned short proto, int inv_proto)
473 {
474         if (XT_ALIGN(target->targetsize) != size) {
475                 printk("%s_tables: %s target: invalid size %Zu != %u\n",
476                        xt_prefix[family], target->name,
477                        XT_ALIGN(target->targetsize), size);
478                 return -EINVAL;
479         }
480         if (target->table && strcmp(target->table, table)) {
481                 printk("%s_tables: %s target: only valid in %s table, not %s\n",
482                        xt_prefix[family], target->name, target->table, table);
483                 return -EINVAL;
484         }
485         if (target->hooks && (hook_mask & ~target->hooks) != 0) {
486                 printk("%s_tables: %s target: bad hook_mask %u/%u\n",
487                        xt_prefix[family], target->name, hook_mask,
488                        target->hooks);
489                 return -EINVAL;
490         }
491         if (target->proto && (target->proto != proto || inv_proto)) {
492                 printk("%s_tables: %s target: only valid for protocol %u\n",
493                        xt_prefix[family], target->name, target->proto);
494                 return -EINVAL;
495         }
496         return 0;
497 }
498 EXPORT_SYMBOL_GPL(xt_check_target);
499
500 #ifdef CONFIG_COMPAT
501 int xt_compat_target_offset(const struct xt_target *target)
502 {
503         u_int16_t csize = target->compatsize ? : target->targetsize;
504         return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
505 }
506 EXPORT_SYMBOL_GPL(xt_compat_target_offset);
507
508 void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
509                                 unsigned int *size)
510 {
511         const struct xt_target *target = t->u.kernel.target;
512         struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
513         int pad, off = xt_compat_target_offset(target);
514         u_int16_t tsize = ct->u.user.target_size;
515
516         t = *dstptr;
517         memcpy(t, ct, sizeof(*ct));
518         if (target->compat_from_user)
519                 target->compat_from_user(t->data, ct->data);
520         else
521                 memcpy(t->data, ct->data, tsize - sizeof(*ct));
522         pad = XT_ALIGN(target->targetsize) - target->targetsize;
523         if (pad > 0)
524                 memset(t->data + target->targetsize, 0, pad);
525
526         tsize += off;
527         t->u.user.target_size = tsize;
528
529         *size += off;
530         *dstptr += tsize;
531 }
532 EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
533
534 int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
535                              unsigned int *size)
536 {
537         const struct xt_target *target = t->u.kernel.target;
538         struct compat_xt_entry_target __user *ct = *dstptr;
539         int off = xt_compat_target_offset(target);
540         u_int16_t tsize = t->u.user.target_size - off;
541
542         if (copy_to_user(ct, t, sizeof(*ct)) ||
543             put_user(tsize, &ct->u.user.target_size) ||
544             copy_to_user(ct->u.user.name, t->u.kernel.target->name,
545                          strlen(t->u.kernel.target->name) + 1))
546                 return -EFAULT;
547
548         if (target->compat_to_user) {
549                 if (target->compat_to_user((void __user *)ct->data, t->data))
550                         return -EFAULT;
551         } else {
552                 if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct)))
553                         return -EFAULT;
554         }
555
556         *size -= off;
557         *dstptr += tsize;
558         return 0;
559 }
560 EXPORT_SYMBOL_GPL(xt_compat_target_to_user);
561 #endif
562
563 struct xt_table_info *xt_alloc_table_info(unsigned int size)
564 {
565         struct xt_table_info *newinfo;
566         int cpu;
567
568         /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
569         if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
570                 return NULL;
571
572         newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL);
573         if (!newinfo)
574                 return NULL;
575
576         newinfo->size = size;
577
578         for_each_possible_cpu(cpu) {
579                 if (size <= PAGE_SIZE)
580                         newinfo->entries[cpu] = kmalloc_node(size,
581                                                         GFP_KERNEL,
582                                                         cpu_to_node(cpu));
583                 else
584                         newinfo->entries[cpu] = vmalloc_node(size,
585                                                         cpu_to_node(cpu));
586
587                 if (newinfo->entries[cpu] == NULL) {
588                         xt_free_table_info(newinfo);
589                         return NULL;
590                 }
591         }
592
593         return newinfo;
594 }
595 EXPORT_SYMBOL(xt_alloc_table_info);
596
597 void xt_free_table_info(struct xt_table_info *info)
598 {
599         int cpu;
600
601         for_each_possible_cpu(cpu) {
602                 if (info->size <= PAGE_SIZE)
603                         kfree(info->entries[cpu]);
604                 else
605                         vfree(info->entries[cpu]);
606         }
607         kfree(info);
608 }
609 EXPORT_SYMBOL(xt_free_table_info);
610
611 /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
612 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
613                                     const char *name)
614 {
615         struct xt_table *t;
616
617         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
618                 return ERR_PTR(-EINTR);
619
620         list_for_each_entry(t, &net->xt.tables[af], list)
621                 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
622                         return t;
623         mutex_unlock(&xt[af].mutex);
624         return NULL;
625 }
626 EXPORT_SYMBOL_GPL(xt_find_table_lock);
627
628 void xt_table_unlock(struct xt_table *table)
629 {
630         mutex_unlock(&xt[table->af].mutex);
631 }
632 EXPORT_SYMBOL_GPL(xt_table_unlock);
633
634 #ifdef CONFIG_COMPAT
635 void xt_compat_lock(u_int8_t af)
636 {
637         mutex_lock(&xt[af].compat_mutex);
638 }
639 EXPORT_SYMBOL_GPL(xt_compat_lock);
640
641 void xt_compat_unlock(u_int8_t af)
642 {
643         mutex_unlock(&xt[af].compat_mutex);
644 }
645 EXPORT_SYMBOL_GPL(xt_compat_unlock);
646 #endif
647
648 struct xt_table_info *
649 xt_replace_table(struct xt_table *table,
650               unsigned int num_counters,
651               struct xt_table_info *newinfo,
652               int *error)
653 {
654         struct xt_table_info *oldinfo, *private;
655
656         /* Do the substitution. */
657         write_lock_bh(&table->lock);
658         private = table->private;
659         /* Check inside lock: is the old number correct? */
660         if (num_counters != private->number) {
661                 duprintf("num_counters != table->private->number (%u/%u)\n",
662                          num_counters, private->number);
663                 write_unlock_bh(&table->lock);
664                 *error = -EAGAIN;
665                 return NULL;
666         }
667         oldinfo = private;
668         table->private = newinfo;
669         newinfo->initial_entries = oldinfo->initial_entries;
670         write_unlock_bh(&table->lock);
671
672         return oldinfo;
673 }
674 EXPORT_SYMBOL_GPL(xt_replace_table);
675
676 struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
677                                    struct xt_table_info *bootstrap,
678                                    struct xt_table_info *newinfo)
679 {
680         int ret;
681         struct xt_table_info *private;
682         struct xt_table *t;
683
684         /* Don't add one object to multiple lists. */
685         table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL);
686         if (!table) {
687                 ret = -ENOMEM;
688                 goto out;
689         }
690
691         ret = mutex_lock_interruptible(&xt[table->af].mutex);
692         if (ret != 0)
693                 goto out_free;
694
695         /* Don't autoload: we'd eat our tail... */
696         list_for_each_entry(t, &net->xt.tables[table->af], list) {
697                 if (strcmp(t->name, table->name) == 0) {
698                         ret = -EEXIST;
699                         goto unlock;
700                 }
701         }
702
703         /* Simplifies replace_table code. */
704         table->private = bootstrap;
705         rwlock_init(&table->lock);
706         if (!xt_replace_table(table, 0, newinfo, &ret))
707                 goto unlock;
708
709         private = table->private;
710         duprintf("table->private->number = %u\n", private->number);
711
712         /* save number of initial entries */
713         private->initial_entries = private->number;
714
715         list_add(&table->list, &net->xt.tables[table->af]);
716         mutex_unlock(&xt[table->af].mutex);
717         return table;
718
719  unlock:
720         mutex_unlock(&xt[table->af].mutex);
721 out_free:
722         kfree(table);
723 out:
724         return ERR_PTR(ret);
725 }
726 EXPORT_SYMBOL_GPL(xt_register_table);
727
728 void *xt_unregister_table(struct xt_table *table)
729 {
730         struct xt_table_info *private;
731
732         mutex_lock(&xt[table->af].mutex);
733         private = table->private;
734         list_del(&table->list);
735         mutex_unlock(&xt[table->af].mutex);
736         kfree(table);
737
738         return private;
739 }
740 EXPORT_SYMBOL_GPL(xt_unregister_table);
741
742 #ifdef CONFIG_PROC_FS
743 struct xt_names_priv {
744         struct seq_net_private p;
745         u_int8_t af;
746 };
747 static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
748 {
749         struct xt_names_priv *priv = seq->private;
750         struct net *net = seq_file_net(seq);
751         u_int8_t af = priv->af;
752
753         mutex_lock(&xt[af].mutex);
754         return seq_list_start(&net->xt.tables[af], *pos);
755 }
756
757 static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
758 {
759         struct xt_names_priv *priv = seq->private;
760         struct net *net = seq_file_net(seq);
761         u_int8_t af = priv->af;
762
763         return seq_list_next(v, &net->xt.tables[af], pos);
764 }
765
766 static void xt_table_seq_stop(struct seq_file *seq, void *v)
767 {
768         struct xt_names_priv *priv = seq->private;
769         u_int8_t af = priv->af;
770
771         mutex_unlock(&xt[af].mutex);
772 }
773
774 static int xt_table_seq_show(struct seq_file *seq, void *v)
775 {
776         struct xt_table *table = list_entry(v, struct xt_table, list);
777
778         if (strlen(table->name))
779                 return seq_printf(seq, "%s\n", table->name);
780         else
781                 return 0;
782 }
783
784 static const struct seq_operations xt_table_seq_ops = {
785         .start  = xt_table_seq_start,
786         .next   = xt_table_seq_next,
787         .stop   = xt_table_seq_stop,
788         .show   = xt_table_seq_show,
789 };
790
791 static int xt_table_open(struct inode *inode, struct file *file)
792 {
793         int ret;
794         struct xt_names_priv *priv;
795
796         ret = seq_open_net(inode, file, &xt_table_seq_ops,
797                            sizeof(struct xt_names_priv));
798         if (!ret) {
799                 priv = ((struct seq_file *)file->private_data)->private;
800                 priv->af = (unsigned long)PDE(inode)->data;
801         }
802         return ret;
803 }
804
805 static const struct file_operations xt_table_ops = {
806         .owner   = THIS_MODULE,
807         .open    = xt_table_open,
808         .read    = seq_read,
809         .llseek  = seq_lseek,
810         .release = seq_release_net,
811 };
812
813 static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
814 {
815         struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
816         u_int16_t af = (unsigned long)pde->data;
817
818         mutex_lock(&xt[af].mutex);
819         return seq_list_start(&xt[af].match, *pos);
820 }
821
822 static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos)
823 {
824         struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
825         u_int16_t af = (unsigned long)pde->data;
826
827         return seq_list_next(v, &xt[af].match, pos);
828 }
829
830 static void xt_match_seq_stop(struct seq_file *seq, void *v)
831 {
832         struct proc_dir_entry *pde = seq->private;
833         u_int16_t af = (unsigned long)pde->data;
834
835         mutex_unlock(&xt[af].mutex);
836 }
837
838 static int xt_match_seq_show(struct seq_file *seq, void *v)
839 {
840         struct xt_match *match = list_entry(v, struct xt_match, list);
841
842         if (strlen(match->name))
843                 return seq_printf(seq, "%s\n", match->name);
844         else
845                 return 0;
846 }
847
848 static const struct seq_operations xt_match_seq_ops = {
849         .start  = xt_match_seq_start,
850         .next   = xt_match_seq_next,
851         .stop   = xt_match_seq_stop,
852         .show   = xt_match_seq_show,
853 };
854
855 static int xt_match_open(struct inode *inode, struct file *file)
856 {
857         int ret;
858
859         ret = seq_open(file, &xt_match_seq_ops);
860         if (!ret) {
861                 struct seq_file *seq = file->private_data;
862
863                 seq->private = PDE(inode);
864         }
865         return ret;
866 }
867
868 static const struct file_operations xt_match_ops = {
869         .owner   = THIS_MODULE,
870         .open    = xt_match_open,
871         .read    = seq_read,
872         .llseek  = seq_lseek,
873         .release = seq_release,
874 };
875
876 static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos)
877 {
878         struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
879         u_int16_t af = (unsigned long)pde->data;
880
881         mutex_lock(&xt[af].mutex);
882         return seq_list_start(&xt[af].target, *pos);
883 }
884
885 static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos)
886 {
887         struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
888         u_int16_t af = (unsigned long)pde->data;
889
890         return seq_list_next(v, &xt[af].target, pos);
891 }
892
893 static void xt_target_seq_stop(struct seq_file *seq, void *v)
894 {
895         struct proc_dir_entry *pde = seq->private;
896         u_int16_t af = (unsigned long)pde->data;
897
898         mutex_unlock(&xt[af].mutex);
899 }
900
901 static int xt_target_seq_show(struct seq_file *seq, void *v)
902 {
903         struct xt_target *target = list_entry(v, struct xt_target, list);
904
905         if (strlen(target->name))
906                 return seq_printf(seq, "%s\n", target->name);
907         else
908                 return 0;
909 }
910
911 static const struct seq_operations xt_target_seq_ops = {
912         .start  = xt_target_seq_start,
913         .next   = xt_target_seq_next,
914         .stop   = xt_target_seq_stop,
915         .show   = xt_target_seq_show,
916 };
917
918 static int xt_target_open(struct inode *inode, struct file *file)
919 {
920         int ret;
921
922         ret = seq_open(file, &xt_target_seq_ops);
923         if (!ret) {
924                 struct seq_file *seq = file->private_data;
925
926                 seq->private = PDE(inode);
927         }
928         return ret;
929 }
930
931 static const struct file_operations xt_target_ops = {
932         .owner   = THIS_MODULE,
933         .open    = xt_target_open,
934         .read    = seq_read,
935         .llseek  = seq_lseek,
936         .release = seq_release,
937 };
938
939 #define FORMAT_TABLES   "_tables_names"
940 #define FORMAT_MATCHES  "_tables_matches"
941 #define FORMAT_TARGETS  "_tables_targets"
942
943 #endif /* CONFIG_PROC_FS */
944
945 int xt_proto_init(struct net *net, u_int8_t af)
946 {
947 #ifdef CONFIG_PROC_FS
948         char buf[XT_FUNCTION_MAXNAMELEN];
949         struct proc_dir_entry *proc;
950 #endif
951
952         if (af >= ARRAY_SIZE(xt_prefix))
953                 return -EINVAL;
954
955
956 #ifdef CONFIG_PROC_FS
957         strlcpy(buf, xt_prefix[af], sizeof(buf));
958         strlcat(buf, FORMAT_TABLES, sizeof(buf));
959         proc = proc_create_data(buf, 0440, net->proc_net, &xt_table_ops,
960                                 (void *)(unsigned long)af);
961         if (!proc)
962                 goto out;
963
964         strlcpy(buf, xt_prefix[af], sizeof(buf));
965         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
966         proc = proc_create_data(buf, 0440, net->proc_net, &xt_match_ops,
967                                 (void *)(unsigned long)af);
968         if (!proc)
969                 goto out_remove_tables;
970
971         strlcpy(buf, xt_prefix[af], sizeof(buf));
972         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
973         proc = proc_create_data(buf, 0440, net->proc_net, &xt_target_ops,
974                                 (void *)(unsigned long)af);
975         if (!proc)
976                 goto out_remove_matches;
977 #endif
978
979         return 0;
980
981 #ifdef CONFIG_PROC_FS
982 out_remove_matches:
983         strlcpy(buf, xt_prefix[af], sizeof(buf));
984         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
985         proc_net_remove(net, buf);
986
987 out_remove_tables:
988         strlcpy(buf, xt_prefix[af], sizeof(buf));
989         strlcat(buf, FORMAT_TABLES, sizeof(buf));
990         proc_net_remove(net, buf);
991 out:
992         return -1;
993 #endif
994 }
995 EXPORT_SYMBOL_GPL(xt_proto_init);
996
997 void xt_proto_fini(struct net *net, u_int8_t af)
998 {
999 #ifdef CONFIG_PROC_FS
1000         char buf[XT_FUNCTION_MAXNAMELEN];
1001
1002         strlcpy(buf, xt_prefix[af], sizeof(buf));
1003         strlcat(buf, FORMAT_TABLES, sizeof(buf));
1004         proc_net_remove(net, buf);
1005
1006         strlcpy(buf, xt_prefix[af], sizeof(buf));
1007         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
1008         proc_net_remove(net, buf);
1009
1010         strlcpy(buf, xt_prefix[af], sizeof(buf));
1011         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
1012         proc_net_remove(net, buf);
1013 #endif /*CONFIG_PROC_FS*/
1014 }
1015 EXPORT_SYMBOL_GPL(xt_proto_fini);
1016
1017 static int __net_init xt_net_init(struct net *net)
1018 {
1019         int i;
1020
1021         for (i = 0; i < NFPROTO_NUMPROTO; i++)
1022                 INIT_LIST_HEAD(&net->xt.tables[i]);
1023         return 0;
1024 }
1025
1026 static struct pernet_operations xt_net_ops = {
1027         .init = xt_net_init,
1028 };
1029
1030 static int __init xt_init(void)
1031 {
1032         int i, rv;
1033
1034         xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL);
1035         if (!xt)
1036                 return -ENOMEM;
1037
1038         for (i = 0; i < NFPROTO_NUMPROTO; i++) {
1039                 mutex_init(&xt[i].mutex);
1040 #ifdef CONFIG_COMPAT
1041                 mutex_init(&xt[i].compat_mutex);
1042                 xt[i].compat_offsets = NULL;
1043 #endif
1044                 INIT_LIST_HEAD(&xt[i].target);
1045                 INIT_LIST_HEAD(&xt[i].match);
1046         }
1047         rv = register_pernet_subsys(&xt_net_ops);
1048         if (rv < 0)
1049                 kfree(xt);
1050         return rv;
1051 }
1052
1053 static void __exit xt_fini(void)
1054 {
1055         unregister_pernet_subsys(&xt_net_ops);
1056         kfree(xt);
1057 }
1058
1059 module_init(xt_init);
1060 module_exit(xt_fini);
1061