12e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* 22e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * x_tables core - Backend for {ip,ip6,arp}_tables 32e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * 42e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org> 5f229f6ce481ceb33a966311722b8ef0cb6c25de7Patrick McHardy * Copyright (C) 2006-2012 Patrick McHardy <kaber@trash.net> 62e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * 72e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Based on existing ip_tables code which is 82e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 92e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> 102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * 112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * This program is free software; you can redistribute it and/or modify 122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * it under the terms of the GNU General Public License version 2 as 132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * published by the Free Software Foundation. 142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * 152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte */ 16be91fd5e323b46450ca82f6828e933e3791fb2f2Jan Engelhardt#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/kernel.h> 183a9a231d977222eea36eae091df2c358e03ac839Paul Gortmaker#include <linux/module.h> 192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/socket.h> 202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/net.h> 212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/proc_fs.h> 222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/seq_file.h> 232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/string.h> 242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/vmalloc.h> 259e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar#include <linux/mutex.h> 26d7fe0f241dceade9c8d4af75498765c5ff7f27e6Al Viro#include <linux/mm.h> 275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 28fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf#include <linux/audit.h> 29457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h> 302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/netfilter/x_tables.h> 322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#include <linux/netfilter_arp.h> 33e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h> 34e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h> 35e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt#include <linux/netfilter_arp/arp_tables.h> 369e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar 372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_LICENSE("GPL"); 382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 39043ef46c7690bfdbd5b012e15812a14a19ca5604Jan EngelhardtMODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module"); 402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 43b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardystruct compat_delta { 44255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet unsigned int offset; /* offset in kernel */ 45255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet int delta; /* delta in 32bit user land */ 46b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy}; 47b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_af { 499e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar struct mutex mutex; 502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct list_head match; 512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct list_head target; 52b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy#ifdef CONFIG_COMPAT 532722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin struct mutex compat_mutex; 54255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet struct compat_delta *compat_tab; 55255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet unsigned int number; /* number of slots in compat_tab[] */ 56255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet unsigned int cur; /* number of used slots in compat_tab[] */ 57b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy#endif 582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}; 592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic struct xt_af *xt; 612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 627e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardtstatic const char *const xt_prefix[NFPROTO_NUMPROTO] = { 637e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt [NFPROTO_UNSPEC] = "x", 647e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt [NFPROTO_IPV4] = "ip", 657e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt [NFPROTO_ARP] = "arp", 667e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt [NFPROTO_BRIDGE] = "eb", 677e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt [NFPROTO_IPV6] = "ip6", 6837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy}; 6937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy 70f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt/* Allow this many total (re)entries. */ 71f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardtstatic const unsigned int xt_jumpstack_multiplier = 2; 72f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Registration hooks for targets. */ 747926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayusoint xt_register_target(struct xt_target *target) 752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 7676108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = target->family; 772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 787926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_add(&target->list, &xt[af].target); 809e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 817926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso return 0; 822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_register_target); 842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid 86a45049c51ce6a3fecf2a909b591b28164c927112Pablo Neira Ayusoxt_unregister_target(struct xt_target *target) 872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 8876108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = target->family; 89a45049c51ce6a3fecf2a909b591b28164c927112Pablo Neira Ayuso 909e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_lock(&xt[af].mutex); 91df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy list_del(&target->list); 929e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_unregister_target); 952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteint 9752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyxt_register_targets(struct xt_target *target, unsigned int n) 9852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy{ 9952d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy unsigned int i; 10052d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy int err = 0; 10152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 10252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy for (i = 0; i < n; i++) { 10352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy err = xt_register_target(&target[i]); 10452d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy if (err) 10552d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy goto err; 10652d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy } 10752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy return err; 10852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 10952d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyerr: 11052d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy if (i > 0) 11152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy xt_unregister_targets(target, i); 11252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy return err; 11352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy} 11452d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyEXPORT_SYMBOL(xt_register_targets); 11552d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 11652d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyvoid 11752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyxt_unregister_targets(struct xt_target *target, unsigned int n) 11852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy{ 119f68c53015c5b9aa98ffd87a34009f89bdbbd7160Changli Gao while (n-- > 0) 120f68c53015c5b9aa98ffd87a34009f89bdbbd7160Changli Gao xt_unregister_target(&target[n]); 12152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy} 12252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyEXPORT_SYMBOL(xt_unregister_targets); 12352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 1247926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayusoint xt_register_match(struct xt_match *match) 1252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 12676108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = match->family; 1272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1287926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 1292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_add(&match->list, &xt[af].match); 1309e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 1317926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso return 0; 1322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 1332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_register_match); 1342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid 136a45049c51ce6a3fecf2a909b591b28164c927112Pablo Neira Ayusoxt_unregister_match(struct xt_match *match) 1372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 13876108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = match->family; 139a45049c51ce6a3fecf2a909b591b28164c927112Pablo Neira Ayuso 1409e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_lock(&xt[af].mutex); 141df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy list_del(&match->list); 1429e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 1432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 1442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_unregister_match); 1452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 14652d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyint 14752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyxt_register_matches(struct xt_match *match, unsigned int n) 14852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy{ 14952d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy unsigned int i; 15052d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy int err = 0; 15152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 15252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy for (i = 0; i < n; i++) { 15352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy err = xt_register_match(&match[i]); 15452d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy if (err) 15552d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy goto err; 15652d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy } 15752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy return err; 15852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 15952d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyerr: 16052d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy if (i > 0) 16152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy xt_unregister_matches(match, i); 16252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy return err; 16352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy} 16452d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyEXPORT_SYMBOL(xt_register_matches); 16552d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 16652d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyvoid 16752d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyxt_unregister_matches(struct xt_match *match, unsigned int n) 16852d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy{ 169f68c53015c5b9aa98ffd87a34009f89bdbbd7160Changli Gao while (n-- > 0) 170f68c53015c5b9aa98ffd87a34009f89bdbbd7160Changli Gao xt_unregister_match(&match[n]); 17152d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy} 17252d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardyEXPORT_SYMBOL(xt_unregister_matches); 17352d9c42ef2563d2c420eb23b96bf5a4cae9e167bPatrick McHardy 1742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* 1762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * These are weird, but module loading must not be done with mutex 1772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte * held (since they will register), and we have to have a single 178adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger * function to use. 1792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte */ 1802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find match, grabs ref. Returns ERR_PTR() on error. */ 18276108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstruct xt_match *xt_find_match(u8 af, const char *name, u8 revision) 1832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_match *m; 18542046e2e45c109ba703993c510401a11f716c8dfPatrick McHardy int err = -ENOENT; 1862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1877926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 1882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_for_each_entry(m, &xt[af].match, list) { 1892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (strcmp(m->name, name) == 0) { 1902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (m->revision == revision) { 1912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (try_module_get(m->me)) { 1929e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 1932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return m; 1942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 1952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } else 1962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte err = -EPROTOTYPE; /* Found something. */ 1972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 1982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 1999e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 20055b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt 20155b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt if (af != NFPROTO_UNSPEC) 20255b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt /* Try searching again in the family-independent list */ 20355b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt return xt_find_match(NFPROTO_UNSPEC, name, revision); 20455b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt 2052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return ERR_PTR(err); 2062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 2072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_find_match); 2082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 209fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardtstruct xt_match * 210fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardtxt_request_find_match(uint8_t nfproto, const char *name, uint8_t revision) 211fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardt{ 212fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardt struct xt_match *match; 213fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardt 214adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger match = xt_find_match(nfproto, name, revision); 215adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger if (IS_ERR(match)) { 216adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger request_module("%st_%s", xt_prefix[nfproto], name); 217adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger match = xt_find_match(nfproto, name, revision); 218adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger } 219adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger 220adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger return match; 221fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardt} 222fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan EngelhardtEXPORT_SYMBOL_GPL(xt_request_find_match); 223fd0ec0e6216baea854465bbdb177f2d1b2ccaf22Jan Engelhardt 2242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find target, grabs ref. Returns ERR_PTR() on error. */ 22576108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstruct xt_target *xt_find_target(u8 af, const char *name, u8 revision) 2262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 2272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_target *t; 22842046e2e45c109ba703993c510401a11f716c8dfPatrick McHardy int err = -ENOENT; 2292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 2307926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 2312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_for_each_entry(t, &xt[af].target, list) { 2322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (strcmp(t->name, name) == 0) { 2332e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (t->revision == revision) { 2342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (try_module_get(t->me)) { 2359e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 2362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return t; 2372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 2382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } else 2392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte err = -EPROTOTYPE; /* Found something. */ 2402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 2412e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 2429e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 24355b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt 24455b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt if (af != NFPROTO_UNSPEC) 24555b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt /* Try searching again in the family-independent list */ 24655b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt return xt_find_target(NFPROTO_UNSPEC, name, revision); 24755b69e91040c685a064198bd76e59885b7ad26c6Jan Engelhardt 2482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return ERR_PTR(err); 2492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 2502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_find_target); 2512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 25276108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstruct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision) 2532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 2542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_target *target; 2552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 256adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger target = xt_find_target(af, name, revision); 257adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger if (IS_ERR(target)) { 258adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger request_module("%st_%s", xt_prefix[af], name); 259adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger target = xt_find_target(af, name, revision); 260adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger } 261adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger 262adb00ae2ea0ec65f9d3d06079950c0f0ade3b614Stephen Hemminger return target; 2632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 2642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_request_find_target); 2652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 26676108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstatic int match_revfn(u8 af, const char *name, u8 revision, int *bestp) 2672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 2685452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_match *m; 2692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int have_rev = 0; 2702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 2712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_for_each_entry(m, &xt[af].match, list) { 2722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (strcmp(m->name, name) == 0) { 2732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (m->revision > *bestp) 2742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *bestp = m->revision; 2752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (m->revision == revision) 2762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte have_rev = 1; 2772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 2782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 279656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy 280656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy if (af != NFPROTO_UNSPEC && !have_rev) 281656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy return match_revfn(NFPROTO_UNSPEC, name, revision, bestp); 282656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy 2832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return have_rev; 2842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 2852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 28676108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstatic int target_revfn(u8 af, const char *name, u8 revision, int *bestp) 2872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 2885452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_target *t; 2892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int have_rev = 0; 2902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 2912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte list_for_each_entry(t, &xt[af].target, list) { 2922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (strcmp(t->name, name) == 0) { 2932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (t->revision > *bestp) 2942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *bestp = t->revision; 2952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (t->revision == revision) 2962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte have_rev = 1; 2972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 2982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 299656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy 300656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy if (af != NFPROTO_UNSPEC && !have_rev) 301656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy return target_revfn(NFPROTO_UNSPEC, name, revision, bestp); 302656caff20e12ba6e07b4bf342641df5ab33b4e49Patrick McHardy 3032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return have_rev; 3042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 3052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 3062e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Returns true or false (if no such extension at all) */ 30776108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtint xt_find_revision(u8 af, const char *name, u8 revision, int target, 3082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int *err) 3092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 3102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int have_rev, best = -1; 3112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 3127926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 3132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (target == 1) 3142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte have_rev = target_revfn(af, name, revision, &best); 3152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte else 3162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte have_rev = match_revfn(af, name, revision, &best); 3179e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 3182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 3192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Nothing at all? Return 0 to try loading module. */ 3202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (best == -1) { 3212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *err = -ENOENT; 3222e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return 0; 3232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 3242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 3252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *err = best; 3262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!have_rev) 3272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *err = -EPROTONOSUPPORT; 3282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return 1; 3292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 3302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_find_revision); 3312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 3325b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardtstatic char * 3335b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardttextify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto) 334451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt{ 3355b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt static const char *const inetbr_names[] = { 336451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt "PREROUTING", "INPUT", "FORWARD", 337451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt "OUTPUT", "POSTROUTING", "BROUTING", 338451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt }; 3395b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt static const char *const arp_names[] = { 3405b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt "INPUT", "FORWARD", "OUTPUT", 3415b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt }; 3425b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt const char *const *names; 3435b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt unsigned int i, max; 344451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt char *p = buf; 345451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt bool np = false; 346451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt int res; 347451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt 3485b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt names = (nfproto == NFPROTO_ARP) ? arp_names : inetbr_names; 3495b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt max = (nfproto == NFPROTO_ARP) ? ARRAY_SIZE(arp_names) : 3505b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt ARRAY_SIZE(inetbr_names); 351451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt *p = '\0'; 3525b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt for (i = 0; i < max; ++i) { 353451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt if (!(mask & (1 << i))) 354451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt continue; 355451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]); 356451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt if (res > 0) { 357451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt size -= res; 358451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt p += res; 359451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt } 360451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt np = true; 361451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt } 362451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt 363451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt return buf; 364451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt} 365451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt 366916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardtint xt_check_match(struct xt_mtchk_param *par, 3679b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt unsigned int size, u_int8_t proto, bool inv_proto) 36837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy{ 369bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt int ret; 370bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt 3719b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt if (XT_ALIGN(par->match->matchsize) != size && 3729b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt par->match->matchsize != -1) { 373043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt /* 374043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt * ebt_among is exempt from centralized matchsize checking 375043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt * because it uses a dynamic-size data set. 376043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt */ 377b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt pr_err("%s_tables: %s.%u match: invalid size " 378b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt "%u (kernel) != (user) %u\n", 379916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->match->name, 380b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt par->match->revision, 3819b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt XT_ALIGN(par->match->matchsize), size); 38237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 38337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 3849b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt if (par->match->table != NULL && 3859b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt strcmp(par->match->table, par->table) != 0) { 3863dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s match: only valid in %s table, not %s\n", 387916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->match->name, 3889b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt par->match->table, par->table); 38937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 39037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 3919b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) { 392451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt char used[64], allow[64]; 393451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt 3943dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s match: used from hooks %s, but only " 395451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt "valid from %s\n", 396916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->match->name, 3975b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt textify_hooks(used, sizeof(used), par->hook_mask, 3985b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt par->family), 3995b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt textify_hooks(allow, sizeof(allow), par->match->hooks, 4005b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt par->family)); 40137f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 40237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 4039b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt if (par->match->proto && (par->match->proto != proto || inv_proto)) { 4043dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s match: only valid for protocol %u\n", 405916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->match->name, 406916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt par->match->proto); 40737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 40837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 409bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt if (par->match->checkentry != NULL) { 410bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt ret = par->match->checkentry(par); 411bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt if (ret < 0) 412bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt return ret; 413bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt else if (ret > 0) 414bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt /* Flag up potential errors. */ 415bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt return -EIO; 416bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt } 41737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return 0; 41837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy} 41937f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyEXPORT_SYMBOL_GPL(xt_check_match); 42037f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy 4212722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#ifdef CONFIG_COMPAT 422255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazetint xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta) 423b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy{ 424255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet struct xt_af *xp = &xt[af]; 425b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 426255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (!xp->compat_tab) { 427255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (!xp->number) 428255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet return -EINVAL; 429255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xp->compat_tab = vmalloc(sizeof(struct compat_delta) * xp->number); 430255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (!xp->compat_tab) 431255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet return -ENOMEM; 432255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xp->cur = 0; 433255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet } 434b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 435255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (xp->cur >= xp->number) 436255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet return -EINVAL; 437b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 438255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (xp->cur) 439255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet delta += xp->compat_tab[xp->cur - 1].delta; 440255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xp->compat_tab[xp->cur].offset = offset; 441255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xp->compat_tab[xp->cur].delta = delta; 442255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xp->cur++; 443b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy return 0; 444b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy} 445b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_add_offset); 446b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 44776108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtvoid xt_compat_flush_offsets(u_int8_t af) 448b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy{ 449255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (xt[af].compat_tab) { 450255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet vfree(xt[af].compat_tab); 451255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xt[af].compat_tab = NULL; 452255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xt[af].number = 0; 4535a6351eecf8c87afed9c883bb6341d09406d74baEric Dumazet xt[af].cur = 0; 454b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy } 455b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy} 456b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_flush_offsets); 457b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 4583e5e524ffb5fcf2447eb5dd9f8e54ad22dd9baa7Florian Westphalint xt_compat_calc_jump(u_int8_t af, unsigned int offset) 459b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy{ 460255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet struct compat_delta *tmp = xt[af].compat_tab; 461255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet int mid, left = 0, right = xt[af].cur - 1; 462255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet 463255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet while (left <= right) { 464255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet mid = (left + right) >> 1; 465255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet if (offset > tmp[mid].offset) 466255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet left = mid + 1; 467255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet else if (offset < tmp[mid].offset) 468255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet right = mid - 1; 469255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet else 470255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet return mid ? tmp[mid - 1].delta : 0; 471255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet } 4725a6351eecf8c87afed9c883bb6341d09406d74baEric Dumazet return left ? tmp[left - 1].delta : 0; 473b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy} 474b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_calc_jump); 475b386d9f5960a9afce7f077edf2095fccfbb1a8e6Patrick McHardy 476255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazetvoid xt_compat_init_offsets(u_int8_t af, unsigned int number) 477255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet{ 478255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xt[af].number = number; 479255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xt[af].cur = 0; 480255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet} 481255d0dc34068a976550ce555e153c0bfcfec7cc6Eric DumazetEXPORT_SYMBOL(xt_compat_init_offsets); 482255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet 4835452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardtint xt_compat_match_offset(const struct xt_match *match) 4842722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin{ 4859fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t csize = match->compatsize ? : match->matchsize; 4869fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize); 4879fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy} 4889fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_match_offset); 4899fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 4908956695131b8a7878891667469899d667eb5892bPatrick McHardyint xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, 491b0a6363c2418c93f25dd30b8ffcd3fdd4ce23ad6Patrick McHardy unsigned int *size) 4929fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy{ 4935452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_match *match = m->u.kernel.match; 4949fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; 4959fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy int pad, off = xt_compat_match_offset(match); 4969fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t msize = cm->u.user.match_size; 4979fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 4989fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy m = *dstptr; 4999fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memcpy(m, cm, sizeof(*cm)); 5009fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (match->compat_from_user) 5019fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy match->compat_from_user(m->data, cm->data); 5029fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy else 5039fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memcpy(m->data, cm->data, msize - sizeof(*cm)); 5049fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy pad = XT_ALIGN(match->matchsize) - match->matchsize; 5059fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (pad > 0) 5069fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memset(m->data + match->matchsize, 0, pad); 5079fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 5089fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy msize += off; 5099fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy m->u.user.match_size = msize; 5109fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 5119fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *size += off; 5129fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *dstptr += msize; 5138956695131b8a7878891667469899d667eb5892bPatrick McHardy return 0; 5149fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy} 5159fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_match_from_user); 5169fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 517739674fb7febf116e7d647031fab16989a08a965Jan Engelhardtint xt_compat_match_to_user(const struct xt_entry_match *m, 518739674fb7febf116e7d647031fab16989a08a965Jan Engelhardt void __user **dstptr, unsigned int *size) 5199fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy{ 5205452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_match *match = m->u.kernel.match; 5219fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy struct compat_xt_entry_match __user *cm = *dstptr; 5229fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy int off = xt_compat_match_offset(match); 5239fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t msize = m->u.user.match_size - off; 5249fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 5259fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (copy_to_user(cm, m, sizeof(*cm)) || 526a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy put_user(msize, &cm->u.user.match_size) || 527a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy copy_to_user(cm->u.user.name, m->u.kernel.match->name, 528a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy strlen(m->u.kernel.match->name) + 1)) 529601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki return -EFAULT; 5309fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 5319fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (match->compat_to_user) { 5329fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (match->compat_to_user((void __user *)cm->data, m->data)) 5339fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return -EFAULT; 5349fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy } else { 5359fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (copy_to_user(cm->data, m->data, msize - sizeof(*cm))) 5369fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return -EFAULT; 5372722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin } 5389fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 5399fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *size -= off; 5409fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *dstptr += msize; 5419fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return 0; 5422722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin} 5439fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_match_to_user); 5449fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy#endif /* CONFIG_COMPAT */ 5452722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin 546916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardtint xt_check_target(struct xt_tgchk_param *par, 547af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt unsigned int size, u_int8_t proto, bool inv_proto) 54837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy{ 549d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt int ret; 550d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt 551af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt if (XT_ALIGN(par->target->targetsize) != size) { 552b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt pr_err("%s_tables: %s.%u target: invalid size " 553b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt "%u (kernel) != (user) %u\n", 554916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->target->name, 555b402405d71beed8e4df354844353f66b4e18269fJan Engelhardt par->target->revision, 556af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt XT_ALIGN(par->target->targetsize), size); 55737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 55837f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 559af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt if (par->target->table != NULL && 560af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt strcmp(par->target->table, par->table) != 0) { 5613dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s target: only valid in %s table, not %s\n", 562916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->target->name, 563af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt par->target->table, par->table); 56437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 56537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 566af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) { 567451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt char used[64], allow[64]; 568451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt 5693dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s target: used from hooks %s, but only " 570451853645f3cb804b523227eca054701e4cbc589Jan Engelhardt "usable from %s\n", 571916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->target->name, 5725b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt textify_hooks(used, sizeof(used), par->hook_mask, 5735b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt par->family), 5745b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt textify_hooks(allow, sizeof(allow), par->target->hooks, 5755b76c4948fe6977bead2359c2054f3e6a2dcf3d0Jan Engelhardt par->family)); 57637f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 57737f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 578af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt if (par->target->proto && (par->target->proto != proto || inv_proto)) { 5793dd5d7e3ba5e9b05586ff0d59ae6d700b7b7c607Joe Perches pr_err("%s_tables: %s target: only valid for protocol %u\n", 580916a917dfec18535ff9e2afdafba82e6279eb4f4Jan Engelhardt xt_prefix[par->family], par->target->name, 581af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt par->target->proto); 58237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return -EINVAL; 58337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy } 584d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt if (par->target->checkentry != NULL) { 585d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt ret = par->target->checkentry(par); 586d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt if (ret < 0) 587d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt return ret; 588d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt else if (ret > 0) 589d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt /* Flag up potential errors. */ 590d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt return -EIO; 591d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt } 59237f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy return 0; 59337f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy} 59437f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardyEXPORT_SYMBOL_GPL(xt_check_target); 59537f9f7334b86ffc3b8a1921842ae33cb9aa22ee3Patrick McHardy 5962722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#ifdef CONFIG_COMPAT 5975452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardtint xt_compat_target_offset(const struct xt_target *target) 5982722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin{ 5999fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t csize = target->compatsize ? : target->targetsize; 6009fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize); 6019fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy} 6029fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_target_offset); 6039fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6049fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyvoid xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, 605b0a6363c2418c93f25dd30b8ffcd3fdd4ce23ad6Patrick McHardy unsigned int *size) 6069fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy{ 6075452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_target *target = t->u.kernel.target; 6089fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; 6099fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy int pad, off = xt_compat_target_offset(target); 6109fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t tsize = ct->u.user.target_size; 6119fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6129fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy t = *dstptr; 6139fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memcpy(t, ct, sizeof(*ct)); 6149fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (target->compat_from_user) 6159fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy target->compat_from_user(t->data, ct->data); 6169fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy else 6179fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memcpy(t->data, ct->data, tsize - sizeof(*ct)); 6189fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy pad = XT_ALIGN(target->targetsize) - target->targetsize; 6199fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (pad > 0) 6209fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy memset(t->data + target->targetsize, 0, pad); 6219fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6229fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy tsize += off; 6239fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy t->u.user.target_size = tsize; 6249fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6259fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *size += off; 6269fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *dstptr += tsize; 6279fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy} 6289fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_target_from_user); 6299fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 630739674fb7febf116e7d647031fab16989a08a965Jan Engelhardtint xt_compat_target_to_user(const struct xt_entry_target *t, 631739674fb7febf116e7d647031fab16989a08a965Jan Engelhardt void __user **dstptr, unsigned int *size) 6329fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy{ 6335452e425adfdfc4647b618e303f73d48f2405b0eJan Engelhardt const struct xt_target *target = t->u.kernel.target; 6349fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy struct compat_xt_entry_target __user *ct = *dstptr; 6359fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy int off = xt_compat_target_offset(target); 6369fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy u_int16_t tsize = t->u.user.target_size - off; 6379fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6389fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (copy_to_user(ct, t, sizeof(*ct)) || 639a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy put_user(tsize, &ct->u.user.target_size) || 640a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy copy_to_user(ct->u.user.name, t->u.kernel.target->name, 641a18aa31b7774d8b36048e256a02d9d689533fc96Patrick McHardy strlen(t->u.kernel.target->name) + 1)) 642601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki return -EFAULT; 6439fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6449fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (target->compat_to_user) { 6459fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (target->compat_to_user((void __user *)ct->data, t->data)) 6469fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return -EFAULT; 6479fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy } else { 6489fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct))) 6499fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return -EFAULT; 6502722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin } 6519fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy 6529fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *size -= off; 6539fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy *dstptr += tsize; 6549fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardy return 0; 6552722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin} 6569fa492cdc160cd27ce1046cb36f47d3b2b1efa21Patrick McHardyEXPORT_SYMBOL_GPL(xt_compat_target_to_user); 6572722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#endif 6582722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin 6592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_table_info *xt_alloc_table_info(unsigned int size) 6602e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 6612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_table_info *newinfo; 6622e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int cpu; 6632e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 6654481374ce88ba8f460c8b89f2572027bd27057d0Jan Beulich if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages) 6662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return NULL; 6672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 668259d4e41f3ec25f22169daece42729f597b89f9aEric Dumazet newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL); 6692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!newinfo) 6702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return NULL; 6712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte newinfo->size = size; 6732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6746f912042256c12b0927438122594f5379b364f5dKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) { 6752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (size <= PAGE_SIZE) 6762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte newinfo->entries[cpu] = kmalloc_node(size, 6772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte GFP_KERNEL, 6782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte cpu_to_node(cpu)); 6792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte else 6802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte newinfo->entries[cpu] = vmalloc_node(size, 6812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte cpu_to_node(cpu)); 6822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (newinfo->entries[cpu] == NULL) { 6842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte xt_free_table_info(newinfo); 6852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return NULL; 6862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 6872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 6882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return newinfo; 6902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 6912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_alloc_table_info); 6922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 6932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid xt_free_table_info(struct xt_table_info *info) 6942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 6952e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int cpu; 6962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 697f6b50824f7d85f72285c17fec66076a36907089fEric Dumazet for_each_possible_cpu(cpu) 698f6b50824f7d85f72285c17fec66076a36907089fEric Dumazet kvfree(info->entries[cpu]); 699f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 700f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (info->jumpstack != NULL) { 701f6b50824f7d85f72285c17fec66076a36907089fEric Dumazet for_each_possible_cpu(cpu) 702f6b50824f7d85f72285c17fec66076a36907089fEric Dumazet kvfree(info->jumpstack[cpu]); 703f6b50824f7d85f72285c17fec66076a36907089fEric Dumazet kvfree(info->jumpstack); 704f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt } 705f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 7067489aec8eed4f2f1eb3b4d35763bd3ea30b32ef5Eric Dumazet free_percpu(info->stackptr); 707f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 7082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte kfree(info); 7092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 7102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL(xt_free_table_info); 7112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 7122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ 71376108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtstruct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, 71476108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt const char *name) 7152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 7162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_table *t; 7172e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 7187926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[af].mutex); 7198d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan list_for_each_entry(t, &net->xt.tables[af], list) 7202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (strcmp(t->name, name) == 0 && try_module_get(t->me)) 7212e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return t; 7229e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[af].mutex); 7232e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return NULL; 7242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 7252e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_find_table_lock); 7262e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 7272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid xt_table_unlock(struct xt_table *table) 7282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 7299e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[table->af].mutex); 7302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 7312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_table_unlock); 7322e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 7332722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#ifdef CONFIG_COMPAT 73476108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtvoid xt_compat_lock(u_int8_t af) 7352722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin{ 7362722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin mutex_lock(&xt[af].compat_mutex); 7372722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin} 7382722971cbe831117686039d5c334f2c0f560be13Dmitry MishinEXPORT_SYMBOL_GPL(xt_compat_lock); 7392722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin 74076108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtvoid xt_compat_unlock(u_int8_t af) 7412722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin{ 7422722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin mutex_unlock(&xt[af].compat_mutex); 7432722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin} 7442722971cbe831117686039d5c334f2c0f560be13Dmitry MishinEXPORT_SYMBOL_GPL(xt_compat_unlock); 7452722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#endif 7462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 7477f5c6d4f665bb57a19a34ce1fb16cc708c04f219Eric DumazetDEFINE_PER_CPU(seqcount_t, xt_recseq); 7487f5c6d4f665bb57a19a34ce1fb16cc708c04f219Eric DumazetEXPORT_PER_CPU_SYMBOL_GPL(xt_recseq); 749942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 750f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardtstatic int xt_jumpstack_alloc(struct xt_table_info *i) 751f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt{ 752f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt unsigned int size; 753f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt int cpu; 754f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 7557489aec8eed4f2f1eb3b4d35763bd3ea30b32ef5Eric Dumazet i->stackptr = alloc_percpu(unsigned int); 756f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (i->stackptr == NULL) 757f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt return -ENOMEM; 758f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 759f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt size = sizeof(void **) * nr_cpu_ids; 760f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (size > PAGE_SIZE) 7613dbd4439837f2cfd2ff302897353f4b1b6263b2aJoe Perches i->jumpstack = vzalloc(size); 762f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt else 7633dbd4439837f2cfd2ff302897353f4b1b6263b2aJoe Perches i->jumpstack = kzalloc(size, GFP_KERNEL); 764f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (i->jumpstack == NULL) 765f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt return -ENOMEM; 766f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 767f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt i->stacksize *= xt_jumpstack_multiplier; 768f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt size = sizeof(void *) * i->stacksize; 769f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt for_each_possible_cpu(cpu) { 770f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (size > PAGE_SIZE) 771f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt i->jumpstack[cpu] = vmalloc_node(size, 772f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt cpu_to_node(cpu)); 773f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt else 774f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt i->jumpstack[cpu] = kmalloc_node(size, 775f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt GFP_KERNEL, cpu_to_node(cpu)); 776f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt if (i->jumpstack[cpu] == NULL) 777f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt /* 778f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt * Freeing will be done later on by the callers. The 779f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt * chain is: xt_replace_table -> __do_replace -> 780f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt * do_replace -> xt_free_table_info. 781f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt */ 782f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt return -ENOMEM; 783f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt } 784f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt 785f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt return 0; 786f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt} 787942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 7882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestruct xt_table_info * 7892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltext_replace_table(struct xt_table *table, 7902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte unsigned int num_counters, 7912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_table_info *newinfo, 7922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int *error) 7932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 794942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger struct xt_table_info *private; 795f3c5c1bfd430858d3a05436f82c51e53104feb6bJan Engelhardt int ret; 7962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 797d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt ret = xt_jumpstack_alloc(newinfo); 798d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt if (ret < 0) { 799d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt *error = ret; 800d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt return NULL; 801d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt } 802d97a9e47ba148cfc41e354c5cd241f472273207cJan Engelhardt 8032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Do the substitution. */ 804942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger local_bh_disable(); 8052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte private = table->private; 806942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 8072e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Check inside lock: is the old number correct? */ 8082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (num_counters != private->number) { 809be91fd5e323b46450ca82f6828e933e3791fb2f2Jan Engelhardt pr_debug("num_counters != table->private->number (%u/%u)\n", 8102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte num_counters, private->number); 811942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger local_bh_enable(); 8122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte *error = -EAGAIN; 8132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return NULL; 8142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 8152e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 816942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger newinfo->initial_entries = private->initial_entries; 817b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon /* 818b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon * Ensure contents of newinfo are visible before assigning to 819b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon * private. 820b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon */ 821b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon smp_wmb(); 822b416c144f46af1a30ddfa4e4319a8f077381ad63Will Deacon table->private = newinfo; 823942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 824942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger /* 825942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger * Even though table entries have now been swapped, other CPU's 826942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger * may still be using the old entries. This is okay, because 827942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger * resynchronization happens because of the locking done 828942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger * during the get_counters() routine. 829942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger */ 830942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger local_bh_enable(); 831942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 832fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf#ifdef CONFIG_AUDIT 833fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf if (audit_enabled) { 834fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf struct audit_buffer *ab; 835fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf 836fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf ab = audit_log_start(current->audit_context, GFP_KERNEL, 837fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf AUDIT_NETFILTER_CFG); 838fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf if (ab) { 839fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf audit_log_format(ab, "table=%s family=%u entries=%u", 840fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf table->name, table->af, 841fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf private->number); 842fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf audit_log_end(ab); 843fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf } 844fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf } 845fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf#endif 846fbabf31e4d482149b5e2704eb0287cf9117bdcf3Thomas Graf 847942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger return private; 8482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 8492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_replace_table); 8502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 85135aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardtstruct xt_table *xt_register_table(struct net *net, 85235aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardt const struct xt_table *input_table, 853a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyan struct xt_table_info *bootstrap, 854a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyan struct xt_table_info *newinfo) 8552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 8562e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte int ret; 8572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_table_info *private; 85835aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardt struct xt_table *t, *table; 8592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 86044d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan /* Don't add one object to multiple lists. */ 86135aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardt table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL); 86244d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan if (!table) { 86344d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan ret = -ENOMEM; 86444d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan goto out; 86544d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan } 86644d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan 8677926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayuso mutex_lock(&xt[table->af].mutex); 8682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Don't autoload: we'd eat our tail... */ 8698d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan list_for_each_entry(t, &net->xt.tables[table->af], list) { 870df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy if (strcmp(t->name, table->name) == 0) { 871df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy ret = -EEXIST; 872df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy goto unlock; 873df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy } 8742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 8752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 8762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* Simplifies replace_table code. */ 8772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte table->private = bootstrap; 878784544739a25c30637397ace5489eeb6e15d7d49Stephen Hemminger 8792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!xt_replace_table(table, 0, newinfo, &ret)) 8802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte goto unlock; 8812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 8822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte private = table->private; 883be91fd5e323b46450ca82f6828e933e3791fb2f2Jan Engelhardt pr_debug("table->private->number = %u\n", private->number); 8842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 8852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte /* save number of initial entries */ 8862e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte private->initial_entries = private->number; 8872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 8888d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan list_add(&table->list, &net->xt.tables[table->af]); 889a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyan mutex_unlock(&xt[table->af].mutex); 890a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyan return table; 8912e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 8927926dbfa4bc14e27f4e18a6184a031a1c1e077dcPablo Neira Ayusounlock: 8939e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[table->af].mutex); 89444d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan kfree(table); 895a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyanout: 896a98da11d88dbec1d5cebe2c6dbe9939ed8d13f69Alexey Dobriyan return ERR_PTR(ret); 8972e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 8982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_register_table); 8992e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 9002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltevoid *xt_unregister_table(struct xt_table *table) 9012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 9022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct xt_table_info *private; 9032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 9049e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_lock(&xt[table->af].mutex); 9052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte private = table->private; 906df0933dcb027e156cb5253570ad694b81bd52b69Patrick McHardy list_del(&table->list); 9079e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_unlock(&xt[table->af].mutex); 90844d34e721e2c81ccdfb13cf34996309247ae2981Alexey Dobriyan kfree(table); 9092e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 9102e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return private; 9112e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 9122e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_unregister_table); 9132e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 9142e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS 915715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyanstruct xt_names_priv { 916715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan struct seq_net_private p; 91776108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af; 918715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan}; 919025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic void *xt_table_seq_start(struct seq_file *seq, loff_t *pos) 9202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 921715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan struct xt_names_priv *priv = seq->private; 9221218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki struct net *net = seq_file_net(seq); 92376108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = priv->af; 9242e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 925025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan mutex_lock(&xt[af].mutex); 926715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan return seq_list_start(&net->xt.tables[af], *pos); 927025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 9282e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 929025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos) 930025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 931715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan struct xt_names_priv *priv = seq->private; 9321218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki struct net *net = seq_file_net(seq); 93376108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = priv->af; 9342e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 935715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan return seq_list_next(v, &net->xt.tables[af], pos); 9362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 9372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 938025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic void xt_table_seq_stop(struct seq_file *seq, void *v) 9392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 940715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan struct xt_names_priv *priv = seq->private; 94176108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t af = priv->af; 9422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 943025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan mutex_unlock(&xt[af].mutex); 944025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 9452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 946025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic int xt_table_seq_show(struct seq_file *seq, void *v) 947025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 948025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan struct xt_table *table = list_entry(v, struct xt_table, list); 9492e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 950025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan if (strlen(table->name)) 951025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan return seq_printf(seq, "%s\n", table->name); 952025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan else 953025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan return 0; 954025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 955601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki 956025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct seq_operations xt_table_seq_ops = { 957025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .start = xt_table_seq_start, 958025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .next = xt_table_seq_next, 959025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .stop = xt_table_seq_stop, 960025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .show = xt_table_seq_show, 961025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan}; 962025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 963025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic int xt_table_open(struct inode *inode, struct file *file) 964025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 965025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan int ret; 966715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan struct xt_names_priv *priv; 967025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 968715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan ret = seq_open_net(inode, file, &xt_table_seq_ops, 969715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan sizeof(struct xt_names_priv)); 970025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan if (!ret) { 971715cf35ac9291f31a4fea7d022695a64cac0af80Alexey Dobriyan priv = ((struct seq_file *)file->private_data)->private; 972d9dda78bad879595d8c4220a067fc029d6484a16Al Viro priv->af = (unsigned long)PDE_DATA(inode); 973025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan } 974025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan return ret; 9752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 9762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 977025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct file_operations xt_table_ops = { 978025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .owner = THIS_MODULE, 979025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .open = xt_table_open, 980025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .read = seq_read, 981025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .llseek = seq_lseek, 9820e93bb9459f56b50a2f71f2c230f4ad00ec40a73Pavel Emelyanov .release = seq_release_net, 983025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan}; 984025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 985eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt/* 986eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt * Traverse state for ip{,6}_{tables,matches} for helping crossing 987eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt * the multi-AF mutexes. 988eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt */ 989eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstruct nf_mttg_trav { 990eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct list_head *head, *curr; 991eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt uint8_t class, nfproto; 992eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt}; 993eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 994eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtenum { 995eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt MTTG_TRAV_INIT, 996eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt MTTG_TRAV_NFP_UNSPEC, 997eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt MTTG_TRAV_NFP_SPEC, 998eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt MTTG_TRAV_DONE, 999eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt}; 1000eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 1001eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, 1002eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt bool is_target) 10032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1004eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt static const uint8_t next_class[] = { 1005eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt [MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC, 1006eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt [MTTG_TRAV_NFP_SPEC] = MTTG_TRAV_DONE, 1007eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt }; 1008eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct nf_mttg_trav *trav = seq->private; 1009eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 1010eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt switch (trav->class) { 1011eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_INIT: 1012eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->class = MTTG_TRAV_NFP_UNSPEC; 1013eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt mutex_lock(&xt[NFPROTO_UNSPEC].mutex); 1014eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->head = trav->curr = is_target ? 1015eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt &xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match; 1016eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1017eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_UNSPEC: 1018eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->curr = trav->curr->next; 1019eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (trav->curr != trav->head) 1020eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1021eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); 1022eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt mutex_lock(&xt[trav->nfproto].mutex); 1023eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->head = trav->curr = is_target ? 1024eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt &xt[trav->nfproto].target : &xt[trav->nfproto].match; 1025eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->class = next_class[trav->class]; 1026eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1027eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_SPEC: 1028eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->curr = trav->curr->next; 1029eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (trav->curr != trav->head) 1030eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1031eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt /* fallthru, _stop will unlock */ 1032eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt default: 1033eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return NULL; 1034eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt } 10352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1036eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (ppos != NULL) 1037eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt ++*ppos; 1038eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return trav; 1039025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 1040601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki 1041eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos, 1042eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt bool is_target) 1043025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 1044eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct nf_mttg_trav *trav = seq->private; 1045eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt unsigned int j; 10462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1047eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt trav->class = MTTG_TRAV_INIT; 1048eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt for (j = 0; j < *pos; ++j) 1049eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL) 1050eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return NULL; 1051eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return trav; 10522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 10532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1054eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void xt_mttg_seq_stop(struct seq_file *seq, void *v) 10552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1056eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct nf_mttg_trav *trav = seq->private; 1057eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 1058eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt switch (trav->class) { 1059eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_UNSPEC: 1060eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); 1061eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1062eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_SPEC: 1063eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt mutex_unlock(&xt[trav->nfproto].mutex); 1064eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt break; 1065eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt } 1066eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt} 10672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1068eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) 1069eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt{ 1070eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return xt_mttg_seq_start(seq, pos, false); 10712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 10722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1073eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) 10742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1075eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return xt_mttg_seq_next(seq, v, ppos, false); 1076eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt} 10772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1078eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic int xt_match_seq_show(struct seq_file *seq, void *v) 1079eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt{ 1080eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt const struct nf_mttg_trav *trav = seq->private; 1081eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt const struct xt_match *match; 1082eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 1083eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt switch (trav->class) { 1084eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_UNSPEC: 1085eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_SPEC: 1086eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (trav->curr == trav->head) 1087eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 1088eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt match = list_entry(trav->curr, struct xt_match, list); 1089eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return (*match->name == '\0') ? 0 : 1090eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt seq_printf(seq, "%s\n", match->name); 1091eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt } 1092eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 10932e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 10942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1095025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct seq_operations xt_match_seq_ops = { 1096025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .start = xt_match_seq_start, 1097025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .next = xt_match_seq_next, 1098eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt .stop = xt_mttg_seq_stop, 1099025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .show = xt_match_seq_show, 11002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}; 11012e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1102025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic int xt_match_open(struct inode *inode, struct file *file) 11032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1104eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct nf_mttg_trav *trav; 1105772476df7047db87ac4174d1ed396512912d23bfRob Jones trav = __seq_open_private(file, &xt_match_seq_ops, sizeof(*trav)); 1106772476df7047db87ac4174d1ed396512912d23bfRob Jones if (!trav) 1107eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return -ENOMEM; 11082e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1109d9dda78bad879595d8c4220a067fc029d6484a16Al Viro trav->nfproto = (unsigned long)PDE_DATA(inode); 1110eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 1111025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 1112025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1113025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct file_operations xt_match_ops = { 1114025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .owner = THIS_MODULE, 1115025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .open = xt_match_open, 1116025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .read = seq_read, 1117025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .llseek = seq_lseek, 1118eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt .release = seq_release_private, 1119025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan}; 11202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1121025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) 1122025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 1123eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return xt_mttg_seq_start(seq, pos, true); 1124025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 1125025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1126eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardtstatic void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos) 1127025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 1128eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return xt_mttg_seq_next(seq, v, ppos, true); 1129025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 1130025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1131025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic int xt_target_seq_show(struct seq_file *seq, void *v) 1132025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 1133eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt const struct nf_mttg_trav *trav = seq->private; 1134eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt const struct xt_target *target; 1135eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt 1136eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt switch (trav->class) { 1137eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_UNSPEC: 1138eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt case MTTG_TRAV_NFP_SPEC: 1139eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt if (trav->curr == trav->head) 1140eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 1141eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt target = list_entry(trav->curr, struct xt_target, list); 1142eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return (*target->name == '\0') ? 0 : 1143eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt seq_printf(seq, "%s\n", target->name); 1144eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt } 1145eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 1146025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan} 1147025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1148025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct seq_operations xt_target_seq_ops = { 1149025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .start = xt_target_seq_start, 1150025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .next = xt_target_seq_next, 1151eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt .stop = xt_mttg_seq_stop, 1152025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .show = xt_target_seq_show, 1153025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan}; 1154025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1155025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic int xt_target_open(struct inode *inode, struct file *file) 1156025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan{ 1157eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt struct nf_mttg_trav *trav; 1158772476df7047db87ac4174d1ed396512912d23bfRob Jones trav = __seq_open_private(file, &xt_target_seq_ops, sizeof(*trav)); 1159772476df7047db87ac4174d1ed396512912d23bfRob Jones if (!trav) 1160eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return -ENOMEM; 1161025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan 1162d9dda78bad879595d8c4220a067fc029d6484a16Al Viro trav->nfproto = (unsigned long)PDE_DATA(inode); 1163eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt return 0; 11642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 11652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1166025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyanstatic const struct file_operations xt_target_ops = { 11672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte .owner = THIS_MODULE, 1168025d93d148d46bedb26905975f5d9c83d280b46eAlexey Dobriyan .open = xt_target_open, 11692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte .read = seq_read, 11702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte .llseek = seq_lseek, 1171eb132205ca2f7ad44d8c8c482815b6911200b6a0Jan Engelhardt .release = seq_release_private, 11722e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte}; 11732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 11742e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define FORMAT_TABLES "_tables_names" 11752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define FORMAT_MATCHES "_tables_matches" 11762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#define FORMAT_TARGETS "_tables_targets" 11772e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 11782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif /* CONFIG_PROC_FS */ 11792e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 11802b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt/** 11812b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * xt_hook_link - set up hooks for a new table 11822b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * @table: table with metadata needed to set up hooks 11832b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * @fn: Hook function 11842b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * 11852b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * This function will take care of creating and registering the necessary 11862b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * Netfilter hooks for XT tables. 11872b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt */ 11882b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardtstruct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn) 11892b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt{ 11902b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt unsigned int hook_mask = table->valid_hooks; 11912b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt uint8_t i, num_hooks = hweight32(hook_mask); 11922b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt uint8_t hooknum; 11932b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt struct nf_hook_ops *ops; 11942b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt int ret; 11952b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 11962b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); 11972b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt if (ops == NULL) 11982b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt return ERR_PTR(-ENOMEM); 11992b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 12002b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0; 12012b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt hook_mask >>= 1, ++hooknum) { 12022b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt if (!(hook_mask & 1)) 12032b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt continue; 12042b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops[i].hook = fn; 12052b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops[i].owner = table->me; 12062b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops[i].pf = table->af; 12072b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops[i].hooknum = hooknum; 12082b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ops[i].priority = table->priority; 12092b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ++i; 12102b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt } 12112b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 12122b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ret = nf_register_hooks(ops, num_hooks); 12132b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt if (ret < 0) { 12142b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt kfree(ops); 12152b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt return ERR_PTR(ret); 12162b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt } 12172b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 12182b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt return ops; 12192b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt} 12202b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan EngelhardtEXPORT_SYMBOL_GPL(xt_hook_link); 12212b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 12222b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt/** 12232b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * xt_hook_unlink - remove hooks for a table 12242b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * @ops: nf_hook_ops array as returned by nf_hook_link 12252b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt * @hook_mask: the very same mask that was passed to nf_hook_link 12262b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt */ 12272b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardtvoid xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops) 12282b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt{ 12292b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt nf_unregister_hooks(ops, hweight32(table->valid_hooks)); 12302b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt kfree(ops); 12312b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt} 12322b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan EngelhardtEXPORT_SYMBOL_GPL(xt_hook_unlink); 12332b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt 123476108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtint xt_proto_init(struct net *net, u_int8_t af) 12352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 12362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS 12372e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte char buf[XT_FUNCTION_MAXNAMELEN]; 12382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte struct proc_dir_entry *proc; 12392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif 12402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12417e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt if (af >= ARRAY_SIZE(xt_prefix)) 12422e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return -EINVAL; 12432e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12442e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS 1246ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_TABLES, sizeof(buf)); 12488b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev proc = proc_create_data(buf, 0440, net->proc_net, &xt_table_ops, 12498b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev (void *)(unsigned long)af); 12502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!proc) 12512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte goto out; 12522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1253ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_MATCHES, sizeof(buf)); 12558b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev proc = proc_create_data(buf, 0440, net->proc_net, &xt_match_ops, 12568b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev (void *)(unsigned long)af); 12572e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!proc) 12582e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte goto out_remove_tables; 12592e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1260ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12612e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_TARGETS, sizeof(buf)); 12628b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev proc = proc_create_data(buf, 0440, net->proc_net, &xt_target_ops, 12638b169240e266d7fc58d9b9077d18d50a548d9732Denis V. Lunev (void *)(unsigned long)af); 12642e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!proc) 12652e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte goto out_remove_matches; 12662e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif 12672e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12682e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return 0; 12692e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12702e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS 12712e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout_remove_matches: 1272ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12732e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_MATCHES, sizeof(buf)); 1274ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry(buf, net->proc_net); 12752e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 12762e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout_remove_tables: 1277ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12782e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_TABLES, sizeof(buf)); 1279ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry(buf, net->proc_net); 12802e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welteout: 12812e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return -1; 12822e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif 12832e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 12842e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_proto_init); 12852e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 128676108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtvoid xt_proto_fini(struct net *net, u_int8_t af) 12872e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 12882e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#ifdef CONFIG_PROC_FS 12892e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte char buf[XT_FUNCTION_MAXNAMELEN]; 12902e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1291ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12922e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_TABLES, sizeof(buf)); 1293ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry(buf, net->proc_net); 12942e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1295ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 12962e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_TARGETS, sizeof(buf)); 1297ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry(buf, net->proc_net); 12982e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1299ce18afe57bf53477f133208856dd2b7e6b5db5e3Tobias Klauser strlcpy(buf, xt_prefix[af], sizeof(buf)); 13002e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte strlcat(buf, FORMAT_MATCHES, sizeof(buf)); 1301ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry(buf, net->proc_net); 13022e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte#endif /*CONFIG_PROC_FS*/ 13032e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 13042e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteEXPORT_SYMBOL_GPL(xt_proto_fini); 13052e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13068d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyanstatic int __net_init xt_net_init(struct net *net) 13078d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan{ 13088d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan int i; 13098d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan 13107e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt for (i = 0; i < NFPROTO_NUMPROTO; i++) 13118d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan INIT_LIST_HEAD(&net->xt.tables[i]); 13128d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan return 0; 13138d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan} 13148d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan 13158d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyanstatic struct pernet_operations xt_net_ops = { 13168d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan .init = xt_net_init, 13178d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan}; 13182e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13192e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic int __init xt_init(void) 13202e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 1321942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger unsigned int i; 1322942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger int rv; 1323942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger 1324942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger for_each_possible_cpu(i) { 13257f5c6d4f665bb57a19a34ce1fb16cc708c04f219Eric Dumazet seqcount_init(&per_cpu(xt_recseq, i)); 1326942e4a2bd680c606af0211e64eb216be2e19bf61Stephen Hemminger } 13272e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13287e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); 13292e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte if (!xt) 13302e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte return -ENOMEM; 13312e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13327e9c6eeb136a46dfd941852803b3a9dd78939b69Jan Engelhardt for (i = 0; i < NFPROTO_NUMPROTO; i++) { 13339e19bb6d7a0959f5028d46e1ab99c50f0d36eda8Ingo Molnar mutex_init(&xt[i].mutex); 13342722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#ifdef CONFIG_COMPAT 13352722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin mutex_init(&xt[i].compat_mutex); 1336255d0dc34068a976550ce555e153c0bfcfec7cc6Eric Dumazet xt[i].compat_tab = NULL; 13372722971cbe831117686039d5c334f2c0f560be13Dmitry Mishin#endif 13382e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte INIT_LIST_HEAD(&xt[i].target); 13392e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte INIT_LIST_HEAD(&xt[i].match); 13402e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte } 13418d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan rv = register_pernet_subsys(&xt_net_ops); 13428d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan if (rv < 0) 13438d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan kfree(xt); 13448d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan return rv; 13452e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 13462e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13472e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltestatic void __exit xt_fini(void) 13482e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte{ 13498d870052079d255917ec4f8431f5ec102707b7afAlexey Dobriyan unregister_pernet_subsys(&xt_net_ops); 13502e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte kfree(xt); 13512e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte} 13522e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 13532e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltemodule_init(xt_init); 13542e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Weltemodule_exit(xt_fini); 13552e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte 1356