[NETFILTER]: {ip,arp,ip6}_tables: fix sparse warnings in compat code
[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]_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                               unsigned 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                             unsigned 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                                 unsigned 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                              unsigned 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         /* Don't add one object to multiple lists. */
671         table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL);
672         if (!table) {
673                 ret = -ENOMEM;
674                 goto out;
675         }
676
677         ret = mutex_lock_interruptible(&xt[table->af].mutex);
678         if (ret != 0)
679                 goto out_free;
680
681         /* Don't autoload: we'd eat our tail... */
682         list_for_each_entry(t, &net->xt.tables[table->af], list) {
683                 if (strcmp(t->name, table->name) == 0) {
684                         ret = -EEXIST;
685                         goto unlock;
686                 }
687         }
688
689         /* Simplifies replace_table code. */
690         table->private = bootstrap;
691         rwlock_init(&table->lock);
692         if (!xt_replace_table(table, 0, newinfo, &ret))
693                 goto unlock;
694
695         private = table->private;
696         duprintf("table->private->number = %u\n", private->number);
697
698         /* save number of initial entries */
699         private->initial_entries = private->number;
700
701         list_add(&table->list, &net->xt.tables[table->af]);
702         mutex_unlock(&xt[table->af].mutex);
703         return table;
704
705  unlock:
706         mutex_unlock(&xt[table->af].mutex);
707 out_free:
708         kfree(table);
709 out:
710         return ERR_PTR(ret);
711 }
712 EXPORT_SYMBOL_GPL(xt_register_table);
713
714 void *xt_unregister_table(struct xt_table *table)
715 {
716         struct xt_table_info *private;
717
718         mutex_lock(&xt[table->af].mutex);
719         private = table->private;
720         list_del(&table->list);
721         mutex_unlock(&xt[table->af].mutex);
722         kfree(table);
723
724         return private;
725 }
726 EXPORT_SYMBOL_GPL(xt_unregister_table);
727
728 #ifdef CONFIG_PROC_FS
729 static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
730 {
731         struct list_head *head = list->next;
732
733         if (!head || list_empty(list))
734                 return NULL;
735
736         while (pos && (head = head->next)) {
737                 if (head == list)
738                         return NULL;
739                 pos--;
740         }
741         return pos ? NULL : head;
742 }
743
744 static struct list_head *type2list(u_int16_t af, u_int16_t type)
745 {
746         struct list_head *list;
747
748         switch (type) {
749         case TARGET:
750                 list = &xt[af].target;
751                 break;
752         case MATCH:
753                 list = &xt[af].match;
754                 break;
755         case TABLE:
756                 list = &init_net.xt.tables[af];
757                 break;
758         default:
759                 list = NULL;
760                 break;
761         }
762
763         return list;
764 }
765
766 static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
767 {
768         struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
769         u_int16_t af = (unsigned long)pde->data & 0xffff;
770         u_int16_t type = (unsigned long)pde->data >> 16;
771         struct list_head *list;
772
773         if (af >= NPROTO)
774                 return NULL;
775
776         list = type2list(af, type);
777         if (!list)
778                 return NULL;
779
780         if (mutex_lock_interruptible(&xt[af].mutex) != 0)
781                 return NULL;
782
783         return xt_get_idx(list, seq, *pos);
784 }
785
786 static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
787 {
788         struct proc_dir_entry *pde = seq->private;
789         u_int16_t af = (unsigned long)pde->data & 0xffff;
790         u_int16_t type = (unsigned long)pde->data >> 16;
791         struct list_head *list;
792
793         if (af >= NPROTO)
794                 return NULL;
795
796         list = type2list(af, type);
797         if (!list)
798                 return NULL;
799
800         (*pos)++;
801         return xt_get_idx(list, seq, *pos);
802 }
803
804 static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
805 {
806         struct proc_dir_entry *pde = seq->private;
807         u_int16_t af = (unsigned long)pde->data & 0xffff;
808
809         mutex_unlock(&xt[af].mutex);
810 }
811
812 static int xt_name_seq_show(struct seq_file *seq, void *v)
813 {
814         char *name = (char *)v + sizeof(struct list_head);
815
816         if (strlen(name))
817                 return seq_printf(seq, "%s\n", name);
818         else
819                 return 0;
820 }
821
822 static const struct seq_operations xt_tgt_seq_ops = {
823         .start  = xt_tgt_seq_start,
824         .next   = xt_tgt_seq_next,
825         .stop   = xt_tgt_seq_stop,
826         .show   = xt_name_seq_show,
827 };
828
829 static int xt_tgt_open(struct inode *inode, struct file *file)
830 {
831         int ret;
832
833         ret = seq_open(file, &xt_tgt_seq_ops);
834         if (!ret) {
835                 struct seq_file *seq = file->private_data;
836                 struct proc_dir_entry *pde = PDE(inode);
837
838                 seq->private = pde;
839         }
840
841         return ret;
842 }
843
844 static const struct file_operations xt_file_ops = {
845         .owner   = THIS_MODULE,
846         .open    = xt_tgt_open,
847         .read    = seq_read,
848         .llseek  = seq_lseek,
849         .release = seq_release,
850 };
851
852 #define FORMAT_TABLES   "_tables_names"
853 #define FORMAT_MATCHES  "_tables_matches"
854 #define FORMAT_TARGETS  "_tables_targets"
855
856 #endif /* CONFIG_PROC_FS */
857
858 int xt_proto_init(int af)
859 {
860 #ifdef CONFIG_PROC_FS
861         char buf[XT_FUNCTION_MAXNAMELEN];
862         struct proc_dir_entry *proc;
863 #endif
864
865         if (af >= NPROTO)
866                 return -EINVAL;
867
868
869 #ifdef CONFIG_PROC_FS
870         strlcpy(buf, xt_prefix[af], sizeof(buf));
871         strlcat(buf, FORMAT_TABLES, sizeof(buf));
872         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
873         if (!proc)
874                 goto out;
875         proc->data = (void *) ((unsigned long) af | (TABLE << 16));
876
877
878         strlcpy(buf, xt_prefix[af], sizeof(buf));
879         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
880         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
881         if (!proc)
882                 goto out_remove_tables;
883         proc->data = (void *) ((unsigned long) af | (MATCH << 16));
884
885         strlcpy(buf, xt_prefix[af], sizeof(buf));
886         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
887         proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
888         if (!proc)
889                 goto out_remove_matches;
890         proc->data = (void *) ((unsigned long) af | (TARGET << 16));
891 #endif
892
893         return 0;
894
895 #ifdef CONFIG_PROC_FS
896 out_remove_matches:
897         strlcpy(buf, xt_prefix[af], sizeof(buf));
898         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
899         proc_net_remove(&init_net, buf);
900
901 out_remove_tables:
902         strlcpy(buf, xt_prefix[af], sizeof(buf));
903         strlcat(buf, FORMAT_TABLES, sizeof(buf));
904         proc_net_remove(&init_net, buf);
905 out:
906         return -1;
907 #endif
908 }
909 EXPORT_SYMBOL_GPL(xt_proto_init);
910
911 void xt_proto_fini(int af)
912 {
913 #ifdef CONFIG_PROC_FS
914         char buf[XT_FUNCTION_MAXNAMELEN];
915
916         strlcpy(buf, xt_prefix[af], sizeof(buf));
917         strlcat(buf, FORMAT_TABLES, sizeof(buf));
918         proc_net_remove(&init_net, buf);
919
920         strlcpy(buf, xt_prefix[af], sizeof(buf));
921         strlcat(buf, FORMAT_TARGETS, sizeof(buf));
922         proc_net_remove(&init_net, buf);
923
924         strlcpy(buf, xt_prefix[af], sizeof(buf));
925         strlcat(buf, FORMAT_MATCHES, sizeof(buf));
926         proc_net_remove(&init_net, buf);
927 #endif /*CONFIG_PROC_FS*/
928 }
929 EXPORT_SYMBOL_GPL(xt_proto_fini);
930
931 static int __net_init xt_net_init(struct net *net)
932 {
933         int i;
934
935         for (i = 0; i < NPROTO; i++)
936                 INIT_LIST_HEAD(&net->xt.tables[i]);
937         return 0;
938 }
939
940 static struct pernet_operations xt_net_ops = {
941         .init = xt_net_init,
942 };
943
944 static int __init xt_init(void)
945 {
946         int i, rv;
947
948         xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
949         if (!xt)
950                 return -ENOMEM;
951
952         for (i = 0; i < NPROTO; i++) {
953                 mutex_init(&xt[i].mutex);
954 #ifdef CONFIG_COMPAT
955                 mutex_init(&xt[i].compat_mutex);
956                 xt[i].compat_offsets = NULL;
957 #endif
958                 INIT_LIST_HEAD(&xt[i].target);
959                 INIT_LIST_HEAD(&xt[i].match);
960         }
961         rv = register_pernet_subsys(&xt_net_ops);
962         if (rv < 0)
963                 kfree(xt);
964         return rv;
965 }
966
967 static void __exit xt_fini(void)
968 {
969         unregister_pernet_subsys(&xt_net_ops);
970         kfree(xt);
971 }
972
973 module_init(xt_init);
974 module_exit(xt_fini);
975