ipchains_core.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:49k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Minor modifications to fit on compatibility framework:
  2.    Rusty.Russell@rustcorp.com.au
  3. */
  4. /*
  5.  * This code is heavily based on the code on the old ip_fw.c code; see below for
  6.  * copyrights and attributions of the old code.  This code is basically GPL.
  7.  *
  8.  * 15-Aug-1997: Major changes to allow graphs for firewall rules.
  9.  *              Paul Russell <Paul.Russell@rustcorp.com.au> and
  10.  * Michael Neuling <Michael.Neuling@rustcorp.com.au>
  11.  * 24-Aug-1997: Generalised protocol handling (not just TCP/UDP/ICMP).
  12.  *              Added explicit RETURN from chains.
  13.  *              Removed TOS mangling (done in ipchains 1.0.1).
  14.  *              Fixed read & reset bug by reworking proc handling.
  15.  *              Paul Russell <Paul.Russell@rustcorp.com.au>
  16.  * 28-Sep-1997: Added packet marking for net sched code.
  17.  *              Removed fw_via comparisons: all done on device name now,
  18.  *              similar to changes in ip_fw.c in DaveM's CVS970924 tree.
  19.  *              Paul Russell <Paul.Russell@rustcorp.com.au>
  20.  * 2-Nov-1997:  Moved types across to __u16, etc.
  21.  *              Added inverse flags.
  22.  *              Fixed fragment bug (in args to port_match).
  23.  *              Changed mark to only one flag (MARKABS).
  24.  * 21-Nov-1997: Added ability to test ICMP code.
  25.  * 19-Jan-1998: Added wildcard interfaces.
  26.  * 6-Feb-1998:  Merged 2.0 and 2.1 versions.
  27.  *              Initialised ip_masq for 2.0.x version.
  28.  *              Added explicit NETLINK option for 2.1.x version.
  29.  *              Added packet and byte counters for policy matches.
  30.  * 26-Feb-1998: Fixed race conditions, added SMP support.
  31.  * 18-Mar-1998: Fix SMP, fix race condition fix.
  32.  * 1-May-1998:  Remove caching of device pointer.
  33.  * 12-May-1998: Allow tiny fragment case for TCP/UDP.
  34.  * 15-May-1998: Treat short packets as fragments, don't just block.
  35.  * 3-Jan-1999:  Fixed serious procfs security hole -- users should never
  36.  *              be allowed to view the chains!
  37.  *              Marc Santoro <ultima@snicker.emoti.com>
  38.  * 29-Jan-1999: Locally generated bogus IPs dealt with, rather than crash
  39.  *              during dump_packet. --RR.
  40.  * 19-May-1999: Star Wars: The Phantom Menace opened.  Rule num
  41.  * printed in log (modified from Michael Hasenstein's patch).
  42.  * Added SYN in log message. --RR
  43.  * 23-Jul-1999: Fixed small fragment security exposure opened on 15-May-1998.
  44.  *              John McDonald <jm@dataprotect.com>
  45.  *              Thomas Lopatic <tl@dataprotect.com>
  46.  */
  47. /*
  48.  *
  49.  * The origina Linux port was done Alan Cox, with changes/fixes from
  50.  * Pauline Middlelink, Jos Vos, Thomas Quinot, Wouter Gadeyne, Juan
  51.  * Jose Ciarlante, Bernd Eckenfels, Keith Owens and others.
  52.  *
  53.  * Copyright from the original FreeBSD version follows:
  54.  *
  55.  * Copyright (c) 1993 Daniel Boulet
  56.  * Copyright (c) 1994 Ugen J.S.Antsilevich
  57.  *
  58.  * Redistribution and use in source forms, with and without modification,
  59.  * are permitted provided that this entire comment appears intact.
  60.  *
  61.  * Redistribution in binary form may occur without any restrictions.
  62.  * Obviously, it would be nice if you gave credit where credit is due
  63.  * but requiring it would be too onerous.
  64.  *
  65.  * This software is provided ``AS IS'' without any warranties of any kind.  */
  66. #include <linux/config.h>
  67. #include <asm/uaccess.h>
  68. #include <asm/system.h>
  69. #include <linux/types.h>
  70. #include <linux/sched.h>
  71. #include <linux/string.h>
  72. #include <linux/errno.h>
  73. #include <linux/module.h>
  74. #include <linux/socket.h>
  75. #include <linux/sockios.h>
  76. #include <linux/in.h>
  77. #include <linux/inet.h>
  78. #include <linux/netdevice.h>
  79. #include <linux/icmp.h>
  80. #include <linux/udp.h>
  81. #include <net/ip.h>
  82. #include <net/protocol.h>
  83. #include <net/route.h>
  84. #include <net/tcp.h>
  85. #include <net/udp.h>
  86. #include <net/sock.h>
  87. #include <net/icmp.h>
  88. #include <linux/netlink.h>
  89. #include <linux/netfilter.h>
  90. #include <linux/netfilter_ipv4/compat_firewall.h>
  91. #include <linux/netfilter_ipv4/ipchains_core.h>
  92. #include <net/checksum.h>
  93. #include <linux/proc_fs.h>
  94. #include <linux/stat.h>
  95. /* Understanding locking in this code: (thanks to Alan Cox for using
  96.  * little words to explain this to me). -- PR
  97.  *
  98.  * In UP, there can be two packets traversing the chains:
  99.  * 1) A packet from the current userspace context
  100.  * 2) A packet off the bh handlers (timer or net).
  101.  *
  102.  * For SMP (kernel v2.1+), multiply this by # CPUs.
  103.  *
  104.  * [Note that this in not correct for 2.2 - because the socket code always
  105.  *  uses lock_kernel() to serialize, and bottom halves (timers and net_bhs)
  106.  *  only run on one CPU at a time.  This will probably change for 2.3.
  107.  *  It is still good to use spinlocks because that avoids the global cli()
  108.  *  for updating the tables, which is rather costly in SMP kernels -AK]
  109.  *
  110.  * This means counters and backchains can get corrupted if no precautions
  111.  * are taken.
  112.  *
  113.  * To actually alter a chain on UP, we need only do a cli(), as this will
  114.  * stop a bh handler firing, as we are in the current userspace context
  115.  * (coming from a setsockopt()).
  116.  *
  117.  * On SMP, we need a write_lock_irqsave(), which is a simple cli() in
  118.  * UP.
  119.  *
  120.  * For backchains and counters, we use an array, indexed by
  121.  * [cpu_number_map[smp_processor_id()]*2 + !in_interrupt()]; the array is of
  122.  * size [smp_num_cpus*2].  For v2.0, smp_num_cpus is effectively 1.  So,
  123.  * confident of uniqueness, we modify counters even though we only
  124.  * have a read lock (to read the counters, you need a write lock,
  125.  * though).  */
  126. /* Why I didn't use straight locking... -- PR
  127.  *
  128.  * The backchains can be separated out of the ip_chains structure, and
  129.  * allocated as needed inside ip_fw_check().
  130.  *
  131.  * The counters, however, can't.  Trying to lock these means blocking
  132.  * interrupts every time we want to access them.  This would suck HARD
  133.  * performance-wise.  Not locking them leads to possible corruption,
  134.  * made worse on 32-bit machines (counters are 64-bit).  */
  135. /*#define DEBUG_IP_FIREWALL*/
  136. /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
  137. /*#define DEBUG_IP_FIREWALL_USER*/
  138. /*#define DEBUG_IP_FIREWALL_LOCKING*/
  139. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  140. static struct sock *ipfwsk;
  141. #endif
  142. #ifdef CONFIG_SMP
  143. #define SLOT_NUMBER() (cpu_number_map(smp_processor_id())*2 + !in_interrupt())
  144. #else /* !SMP */
  145. #define SLOT_NUMBER() (!in_interrupt())
  146. #endif /* CONFIG_SMP */
  147. #define NUM_SLOTS (smp_num_cpus*2)
  148. #define SIZEOF_STRUCT_IP_CHAIN (sizeof(struct ip_chain) 
  149. + NUM_SLOTS*sizeof(struct ip_reent))
  150. #define SIZEOF_STRUCT_IP_FW_KERNEL (sizeof(struct ip_fwkernel) 
  151.     + NUM_SLOTS*sizeof(struct ip_counters))
  152. #ifdef DEBUG_IP_FIREWALL_LOCKING
  153. static unsigned int fwc_rlocks, fwc_wlocks;
  154. #define FWC_DEBUG_LOCK(d)
  155. do {
  156. FWC_DONT_HAVE_LOCK(d);
  157. d |= (1 << SLOT_NUMBER());
  158. } while (0)
  159. #define FWC_DEBUG_UNLOCK(d)
  160. do {
  161. FWC_HAVE_LOCK(d);
  162. d &= ~(1 << SLOT_NUMBER());
  163. } while (0)
  164. #define FWC_DONT_HAVE_LOCK(d)
  165. do {
  166. if ((d) & (1 << SLOT_NUMBER()))
  167. printk("%s:%i: Got lock on %i already!n", 
  168.        __FILE__, __LINE__, SLOT_NUMBER());
  169. } while(0)
  170. #define FWC_HAVE_LOCK(d)
  171. do {
  172. if (!((d) & (1 << SLOT_NUMBER())))
  173. printk("%s:%i:No lock on %i!n", 
  174.        __FILE__, __LINE__, SLOT_NUMBER());
  175. } while (0)
  176. #else
  177. #define FWC_DEBUG_LOCK(d) do { } while(0)
  178. #define FWC_DEBUG_UNLOCK(d) do { } while(0)
  179. #define FWC_DONT_HAVE_LOCK(d) do { } while(0)
  180. #define FWC_HAVE_LOCK(d) do { } while(0)
  181. #endif /*DEBUG_IP_FIRWALL_LOCKING*/
  182. #define FWC_READ_LOCK(l) do { FWC_DEBUG_LOCK(fwc_rlocks); read_lock(l); } while (0)
  183. #define FWC_WRITE_LOCK(l) do { FWC_DEBUG_LOCK(fwc_wlocks); write_lock(l); } while (0)
  184. #define FWC_READ_LOCK_IRQ(l,f) do { FWC_DEBUG_LOCK(fwc_rlocks); read_lock_irqsave(l,f); } while (0)
  185. #define FWC_WRITE_LOCK_IRQ(l,f) do { FWC_DEBUG_LOCK(fwc_wlocks); write_lock_irqsave(l,f); } while (0)
  186. #define FWC_READ_UNLOCK(l) do { FWC_DEBUG_UNLOCK(fwc_rlocks); read_unlock(l); } while (0)
  187. #define FWC_WRITE_UNLOCK(l) do { FWC_DEBUG_UNLOCK(fwc_wlocks); write_unlock(l); } while (0)
  188. #define FWC_READ_UNLOCK_IRQ(l,f) do { FWC_DEBUG_UNLOCK(fwc_rlocks); read_unlock_irqrestore(l,f); } while (0)
  189. #define FWC_WRITE_UNLOCK_IRQ(l,f) do { FWC_DEBUG_UNLOCK(fwc_wlocks); write_unlock_irqrestore(l,f); } while (0)
  190. struct ip_chain;
  191. struct ip_counters
  192. {
  193. __u64 pcnt, bcnt; /* Packet and byte counters */
  194. };
  195. struct ip_fwkernel
  196. {
  197. struct ip_fw ipfw;
  198. struct ip_fwkernel *next; /* where to go next if current
  199.  * rule doesn't match */
  200. struct ip_chain *branch; /* which branch to jump to if
  201.  * current rule matches */
  202. int simplebranch; /* Use this if branch == NULL */
  203. struct ip_counters counters[0]; /* Actually several of these */
  204. };
  205. struct ip_reent
  206. {
  207. struct ip_chain *prevchain; /* Pointer to referencing chain */
  208. struct ip_fwkernel *prevrule; /* Pointer to referencing rule */
  209. struct ip_counters counters;
  210. };
  211. struct ip_chain
  212. {
  213. ip_chainlabel label;     /* Defines the label for each block */
  214.   struct ip_chain *next;     /* Pointer to next block */
  215. struct ip_fwkernel *chain;  /* Pointer to first rule in block */
  216. __u32 refcount;      /* Number of refernces to block */
  217. int policy;     /* Default rule for chain.  Only *
  218.      * used in built in chains */
  219. struct ip_reent reent[0];   /* Actually several of these */
  220. };
  221. /*
  222.  * Implement IP packet firewall
  223.  */
  224. #ifdef DEBUG_IP_FIREWALL
  225. #define dprintf(format, args...)  printk(format , ## args)
  226. #else
  227. #define dprintf(format, args...)
  228. #endif
  229. #ifdef DEBUG_IP_FIREWALL_USER
  230. #define duprintf(format, args...) printk(format , ## args)
  231. #else
  232. #define duprintf(format, args...)
  233. #endif
  234. /* Lock around ip_fw_chains linked list structure */
  235. rwlock_t ip_fw_lock = RW_LOCK_UNLOCKED;
  236. /* Head of linked list of fw rules */
  237. static struct ip_chain *ip_fw_chains;
  238. #define IP_FW_INPUT_CHAIN ip_fw_chains
  239. #define IP_FW_FORWARD_CHAIN (ip_fw_chains->next)
  240. #define IP_FW_OUTPUT_CHAIN (ip_fw_chains->next->next)
  241. /* Returns 1 if the port is matched by the range, 0 otherwise */
  242. extern inline int port_match(__u16 min, __u16 max, __u16 port,
  243.      int frag, int invert)
  244. {
  245. if (frag) /* Fragments fail ANY port test. */
  246. return (min == 0 && max == 0xFFFF);
  247. else return (port >= min && port <= max) ^ invert;
  248. }
  249. /* Returns whether matches rule or not. */
  250. static int ip_rule_match(struct ip_fwkernel *f,
  251.  const char *ifname,
  252.  struct iphdr *ip,
  253.  char tcpsyn,
  254.  __u16 src_port, __u16 dst_port,
  255.  char isfrag)
  256. {
  257. #define FWINV(bool,invflg) ((bool) ^ !!(f->ipfw.fw_invflg & invflg))
  258. /*
  259.  * This is a bit simpler as we don't have to walk
  260.  * an interface chain as you do in BSD - same logic
  261.  * however.
  262.  */
  263. if (FWINV((ip->saddr&f->ipfw.fw_smsk.s_addr) != f->ipfw.fw_src.s_addr,
  264.   IP_FW_INV_SRCIP)
  265.     || FWINV((ip->daddr&f->ipfw.fw_dmsk.s_addr)!=f->ipfw.fw_dst.s_addr,
  266.      IP_FW_INV_DSTIP)) {
  267. dprintf("Source or dest mismatch.n");
  268. dprintf("SRC: %u. Mask: %u. Target: %u.%sn", ip->saddr,
  269. f->ipfw.fw_smsk.s_addr, f->ipfw.fw_src.s_addr,
  270. f->ipfw.fw_invflg & IP_FW_INV_SRCIP ? " (INV)" : "");
  271. dprintf("DST: %u. Mask: %u. Target: %u.%sn", ip->daddr,
  272. f->ipfw.fw_dmsk.s_addr, f->ipfw.fw_dst.s_addr,
  273. f->ipfw.fw_invflg & IP_FW_INV_DSTIP ? " (INV)" : "");
  274. return 0;
  275. }
  276. /*
  277.  * Look for a VIA device match
  278.  */
  279. if (f->ipfw.fw_flg & IP_FW_F_WILDIF) {
  280.     if (FWINV(strncmp(ifname, f->ipfw.fw_vianame,
  281.       strlen(f->ipfw.fw_vianame)) != 0,
  282.       IP_FW_INV_VIA)) {
  283. dprintf("Wildcard interface mismatch.%sn",
  284. f->ipfw.fw_invflg & IP_FW_INV_VIA ? " (INV)" : "");
  285. return 0; /* Mismatch */
  286.     }
  287. }
  288. else if (FWINV(strcmp(ifname, f->ipfw.fw_vianame) != 0,
  289.        IP_FW_INV_VIA)) {
  290.     dprintf("Interface name does not match.%sn",
  291.     f->ipfw.fw_invflg & IP_FW_INV_VIA
  292.     ? " (INV)" : "");
  293.     return 0; /* Mismatch */
  294. }
  295. /*
  296.  * Ok the chain addresses match.
  297.  */
  298. /* If we have a fragment rule but the packet is not a fragment
  299.  * the we return zero */
  300. if (FWINV((f->ipfw.fw_flg&IP_FW_F_FRAG) && !isfrag, IP_FW_INV_FRAG)) {
  301. dprintf("Fragment rule but not fragment.%sn",
  302. f->ipfw.fw_invflg & IP_FW_INV_FRAG ? " (INV)" : "");
  303. return 0;
  304. }
  305. /* Fragment NEVER passes a SYN test, even an inverted one. */
  306. if (FWINV((f->ipfw.fw_flg&IP_FW_F_TCPSYN) && !tcpsyn, IP_FW_INV_SYN)
  307.     || (isfrag && (f->ipfw.fw_flg&IP_FW_F_TCPSYN))) {
  308. dprintf("Rule requires SYN and packet has no SYN.%sn",
  309. f->ipfw.fw_invflg & IP_FW_INV_SYN ? " (INV)" : "");
  310. return 0;
  311. }
  312. if (f->ipfw.fw_proto) {
  313. /*
  314.  * Specific firewall - packet's protocol
  315.  * must match firewall's.
  316.  */
  317. if (FWINV(ip->protocol!=f->ipfw.fw_proto, IP_FW_INV_PROTO)) {
  318. dprintf("Packet protocol %hi does not match %hi.%sn",
  319. ip->protocol, f->ipfw.fw_proto,
  320. f->ipfw.fw_invflg&IP_FW_INV_PROTO ? " (INV)":"");
  321. return 0;
  322. }
  323. /* For non TCP/UDP/ICMP, port range is max anyway. */
  324. if (!port_match(f->ipfw.fw_spts[0],
  325. f->ipfw.fw_spts[1],
  326. src_port, isfrag,
  327. !!(f->ipfw.fw_invflg&IP_FW_INV_SRCPT))
  328.     || !port_match(f->ipfw.fw_dpts[0],
  329.    f->ipfw.fw_dpts[1],
  330.    dst_port, isfrag,
  331.    !!(f->ipfw.fw_invflg
  332.       &IP_FW_INV_DSTPT))) {
  333.     dprintf("Port match failed.n");
  334.     return 0;
  335. }
  336. }
  337. dprintf("Match succeeded.n");
  338. return 1;
  339. }
  340. static const char *branchname(struct ip_chain *branch,int simplebranch)
  341. {
  342. if (branch)
  343. return branch->label;
  344. switch (simplebranch)
  345. {
  346. case FW_BLOCK: return IP_FW_LABEL_BLOCK;
  347. case FW_ACCEPT: return IP_FW_LABEL_ACCEPT;
  348. case FW_REJECT: return IP_FW_LABEL_REJECT;
  349. case FW_REDIRECT: return IP_FW_LABEL_REDIRECT;
  350. case FW_MASQUERADE: return IP_FW_LABEL_MASQUERADE;
  351. case FW_SKIP: return "-";
  352. case FW_SKIP+1: return IP_FW_LABEL_RETURN;
  353. default:
  354. return "UNKNOWN";
  355. }
  356. }
  357. /*
  358.  * VERY ugly piece of code which actually
  359.  * makes kernel printf for matching packets...
  360.  */
  361. static void dump_packet(const struct iphdr *ip,
  362. const char *ifname,
  363. struct ip_fwkernel *f,
  364. const ip_chainlabel chainlabel,
  365. __u16 src_port,
  366. __u16 dst_port,
  367. unsigned int count,
  368. int syn)
  369. {
  370. __u32 *opt = (__u32 *) (ip + 1);
  371. int opti;
  372. if (f) {
  373. printk(KERN_INFO "Packet log: %s ",chainlabel);
  374. printk("%s ",branchname(f->branch,f->simplebranch));
  375. if (f->simplebranch==FW_REDIRECT)
  376. printk("%d ",f->ipfw.fw_redirpt);
  377. }
  378. printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
  379.        " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
  380.        ifname, ip->protocol, NIPQUAD(ip->saddr),
  381.        src_port, NIPQUAD(ip->daddr),
  382.        dst_port,
  383.        ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
  384.        ntohs(ip->frag_off), ip->ttl);
  385. for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
  386. printk(" O=0x%8.8X", *opt++);
  387. printk(" %s(#%d)n", syn ? "SYN " : /* "PENANCE" */ "", count);
  388. }
  389. /* function for checking chain labels for user space. */
  390. static int check_label(ip_chainlabel label)
  391. {
  392. unsigned int i;
  393. /* strlen must be < IP_FW_MAX_LABEL_LENGTH. */
  394. for (i = 0; i < IP_FW_MAX_LABEL_LENGTH + 1; i++)
  395. if (label[i] == '') return 1;
  396. return 0;
  397. }
  398. /* This function returns a pointer to the first chain with a label
  399.  * that matches the one given. */
  400. static struct ip_chain *find_label(ip_chainlabel label)
  401. {
  402. struct ip_chain *tmp;
  403. FWC_HAVE_LOCK(fwc_rlocks | fwc_wlocks);
  404. for (tmp = ip_fw_chains; tmp; tmp = tmp->next)
  405. if (strcmp(tmp->label,label) == 0)
  406. break;
  407. return tmp;
  408. }
  409. /* This function returns a boolean which when true sets answer to one
  410.    of the FW_*. */
  411. static int find_special(ip_chainlabel label, int *answer)
  412. {
  413. if (label[0] == '') {
  414. *answer = FW_SKIP; /* => pass-through rule */
  415. return 1;
  416. } else if (strcmp(label,IP_FW_LABEL_ACCEPT) == 0) {
  417. *answer = FW_ACCEPT;
  418. return 1;
  419. } else if (strcmp(label,IP_FW_LABEL_BLOCK) == 0) {
  420. *answer = FW_BLOCK;
  421. return 1;
  422. } else if (strcmp(label,IP_FW_LABEL_REJECT) == 0) {
  423. *answer = FW_REJECT;
  424. return 1;
  425. } else if (strcmp(label,IP_FW_LABEL_REDIRECT) == 0) {
  426. *answer = FW_REDIRECT;
  427. return 1;
  428. } else if (strcmp(label,IP_FW_LABEL_MASQUERADE) == 0) {
  429. *answer = FW_MASQUERADE;
  430. return 1;
  431. } else if (strcmp(label, IP_FW_LABEL_RETURN) == 0) {
  432. *answer = FW_SKIP+1;
  433. return 1;
  434. } else {
  435. return 0;
  436. }
  437. }
  438. /* This function cleans up the prevchain and prevrule.  If the verbose
  439.  * flag is set then he names of the chains will be printed as it
  440.  * cleans up.  */
  441. static void cleanup(struct ip_chain *chain,
  442.     const int verbose,
  443.     unsigned int slot)
  444. {
  445. struct ip_chain *tmpchain = chain->reent[slot].prevchain;
  446. if (verbose)
  447. printk(KERN_ERR "Chain backtrace: ");
  448. while (tmpchain) {
  449. if (verbose)
  450. printk("%s<-",chain->label);
  451. chain->reent[slot].prevchain = NULL;
  452. chain = tmpchain;
  453. tmpchain = chain->reent[slot].prevchain;
  454. }
  455. if (verbose)
  456. printk("%sn",chain->label);
  457. }
  458. static inline int
  459. ip_fw_domatch(struct ip_fwkernel *f,
  460.       struct iphdr *ip,
  461.       const char *rif,
  462.       const ip_chainlabel label,
  463.       struct sk_buff *skb,
  464.       unsigned int slot,
  465.       __u16 src_port, __u16 dst_port,
  466.       unsigned int count,
  467.       int tcpsyn)
  468. {
  469. f->counters[slot].bcnt+=ntohs(ip->tot_len);
  470. f->counters[slot].pcnt++;
  471. if (f->ipfw.fw_flg & IP_FW_F_PRN) {
  472. dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn);
  473. }
  474. ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;
  475. /* This functionality is useless in stock 2.0.x series, but we don't
  476.  * discard the mark thing altogether, to avoid breaking ipchains (and,
  477.  * more importantly, the ipfwadm wrapper) --PR */
  478. if (f->ipfw.fw_flg & IP_FW_F_MARKABS) {
  479. skb->nfmark = f->ipfw.fw_mark;
  480. } else {
  481. skb->nfmark += f->ipfw.fw_mark;
  482. }
  483. if (f->ipfw.fw_flg & IP_FW_F_NETLINK) {
  484. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  485. size_t len = min_t(unsigned int, f->ipfw.fw_outputsize, ntohs(ip->tot_len))
  486. + sizeof(__u32) + sizeof(skb->nfmark) + IFNAMSIZ;
  487. struct sk_buff *outskb=alloc_skb(len, GFP_ATOMIC);
  488. duprintf("Sending packet out NETLINK (length = %u).n",
  489.  (unsigned int)len);
  490. if (outskb) {
  491. /* Prepend length, mark & interface */
  492. skb_put(outskb, len);
  493. *((__u32 *)outskb->data) = (__u32)len;
  494. *((__u32 *)(outskb->data+sizeof(__u32))) = skb->nfmark;
  495. strcpy(outskb->data+sizeof(__u32)*2, rif);
  496. memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip,
  497.        len-(sizeof(__u32)*2+IFNAMSIZ));
  498. netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
  499. }
  500. else {
  501. #endif
  502. if (net_ratelimit())
  503. printk(KERN_WARNING "ip_fw: packet drop due to "
  504.        "netlink failuren");
  505. return 0;
  506. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  507. }
  508. #endif
  509. }
  510. return 1;
  511. }
  512. /*
  513.  * Returns one of the generic firewall policies, like FW_ACCEPT.
  514.  *
  515.  * The testing is either false for normal firewall mode or true for
  516.  * user checking mode (counters are not updated, TOS & mark not done).
  517.  */
  518. static int
  519. ip_fw_check(struct iphdr *ip,
  520.     const char *rif,
  521.     __u16 *redirport,
  522.     struct ip_chain *chain,
  523.     struct sk_buff *skb,
  524.     unsigned int slot,
  525.     int testing)
  526. {
  527. struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
  528. struct udphdr *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
  529. struct icmphdr *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl);
  530. __u32 src, dst;
  531. __u16 src_port = 0xFFFF, dst_port = 0xFFFF;
  532. char tcpsyn=0;
  533. __u16 offset;
  534. unsigned char oldtos;
  535. struct ip_fwkernel *f;
  536. int ret = FW_SKIP+2;
  537. unsigned int count;
  538. /* We handle fragments by dealing with the first fragment as
  539.  * if it was a normal packet.  All other fragments are treated
  540.  * normally, except that they will NEVER match rules that ask
  541.  * things we don't know, ie. tcp syn flag or ports).  If the
  542.  * rule is also a fragment-specific rule, non-fragments won't
  543.  * match it. */
  544. offset = ntohs(ip->frag_off) & IP_OFFSET;
  545. /*
  546.  * Don't allow a fragment of TCP 8 bytes in. Nobody
  547.  * normal causes this. Its a cracker trying to break
  548.  * in by doing a flag overwrite to pass the direction
  549.  * checks.
  550.  */
  551. if (offset == 1 && ip->protocol == IPPROTO_TCP) {
  552. if (!testing && net_ratelimit()) {
  553. printk("Suspect TCP fragment.n");
  554. dump_packet(ip,rif,NULL,NULL,0,0,0,0);
  555. }
  556. return FW_BLOCK;
  557. }
  558. /* If we can't investigate ports, treat as fragment.  It's
  559.  * either a trucated whole packet, or a truncated first
  560.  * fragment, or a TCP first fragment of length 8-15, in which
  561.  * case the above rule stops reassembly.
  562.  */
  563. if (offset == 0) {
  564. unsigned int size_req;
  565. switch (ip->protocol) {
  566. case IPPROTO_TCP:
  567. /* Don't care about things past flags word */
  568. size_req = 16;
  569. break;
  570. case IPPROTO_UDP:
  571. case IPPROTO_ICMP:
  572. size_req = 8;
  573. break;
  574. default:
  575. size_req = 0;
  576. }
  577. /* If it is a truncated first fragment then it can be
  578.  * used to rewrite port information, and thus should
  579.  * be blocked.
  580.  */
  581. if (ntohs(ip->tot_len) < (ip->ihl<<2)+size_req) {
  582. if (!testing && net_ratelimit()) {
  583. printk("Suspect short first fragment.n");
  584. dump_packet(ip,rif,NULL,NULL,0,0,0,0);
  585. }
  586. return FW_BLOCK;
  587. }
  588. }
  589. src = ip->saddr;
  590. dst = ip->daddr;
  591. oldtos = ip->tos;
  592. /*
  593.  * If we got interface from which packet came
  594.  * we can use the address directly. Linux 2.1 now uses address
  595.  * chains per device too, but unlike BSD we first check if the
  596.  * incoming packet matches a device address and the routing
  597.  * table before calling the firewall.
  598.  */
  599. dprintf("Packet ");
  600. switch(ip->protocol)
  601. {
  602. case IPPROTO_TCP:
  603. dprintf("TCP ");
  604. if (!offset) {
  605. src_port=ntohs(tcp->source);
  606. dst_port=ntohs(tcp->dest);
  607. /* Connection initilisation can only
  608.  * be made when the syn bit is set and
  609.  * neither of the ack or reset is
  610.  * set. */
  611. if(tcp->syn && !(tcp->ack || tcp->rst))
  612. tcpsyn=1;
  613. }
  614. break;
  615. case IPPROTO_UDP:
  616. dprintf("UDP ");
  617. if (!offset) {
  618. src_port=ntohs(udp->source);
  619. dst_port=ntohs(udp->dest);
  620. }
  621. break;
  622. case IPPROTO_ICMP:
  623. if (!offset) {
  624. src_port=(__u16)icmp->type;
  625. dst_port=(__u16)icmp->code;
  626. }
  627. dprintf("ICMP ");
  628. break;
  629. default:
  630. dprintf("p=%d ",ip->protocol);
  631. break;
  632. }
  633. #ifdef DEBUG_IP_FIREWALL
  634. print_ip(ip->saddr);
  635. if (offset)
  636. dprintf(":fragment (%i) ", ((int)offset)<<2);
  637. else if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP
  638.  || ip->protocol==IPPROTO_ICMP)
  639. dprintf(":%hu:%hu", src_port, dst_port);
  640. dprintf("n");
  641. #endif
  642. if (!testing) FWC_READ_LOCK(&ip_fw_lock);
  643. else FWC_HAVE_LOCK(fwc_rlocks);
  644. f = chain->chain;
  645. do {
  646. count = 0;
  647. for (; f; f = f->next) {
  648. count++;
  649. if (ip_rule_match(f,rif,ip,
  650.   tcpsyn,src_port,dst_port,offset)) {
  651. if (!testing
  652.     && !ip_fw_domatch(f, ip, rif, chain->label,
  653.       skb, slot,
  654.       src_port, dst_port,
  655.       count, tcpsyn)) {
  656. ret = FW_BLOCK;
  657. goto out;
  658. }
  659. break;
  660. }
  661. }
  662. if (f) {
  663. if (f->branch) {
  664. /* Do sanity check to see if we have
  665.                                  * already set prevchain and if so we
  666.                                  * must be in a loop */
  667. if (f->branch->reent[slot].prevchain) {
  668. if (!testing) {
  669. printk(KERN_ERR
  670.        "IP firewall: "
  671.        "Loop detected "
  672.        "at `%s'.n",
  673.        f->branch->label);
  674. cleanup(chain, 1, slot);
  675. ret = FW_BLOCK;
  676. } else {
  677. cleanup(chain, 0, slot);
  678. ret = FW_SKIP+1;
  679. }
  680. }
  681. else {
  682. f->branch->reent[slot].prevchain
  683. = chain;
  684. f->branch->reent[slot].prevrule
  685. = f->next;
  686. chain = f->branch;
  687. f = chain->chain;
  688. }
  689. }
  690. else if (f->simplebranch == FW_SKIP)
  691. f = f->next;
  692. else if (f->simplebranch == FW_SKIP+1) {
  693. /* Just like falling off the chain */
  694. goto fall_off_chain;
  695. } else {
  696. cleanup(chain, 0, slot);
  697. ret = f->simplebranch;
  698. }
  699. } /* f == NULL */
  700. else {
  701. fall_off_chain:
  702. if (chain->reent[slot].prevchain) {
  703. struct ip_chain *tmp = chain;
  704. f = chain->reent[slot].prevrule;
  705. chain = chain->reent[slot].prevchain;
  706. tmp->reent[slot].prevchain = NULL;
  707. }
  708. else {
  709. ret = chain->policy;
  710. if (!testing) {
  711. chain->reent[slot].counters.pcnt++;
  712. chain->reent[slot].counters.bcnt
  713. += ntohs(ip->tot_len);
  714. }
  715. }
  716. }
  717. } while (ret == FW_SKIP+2);
  718.  out:
  719. if (!testing) FWC_READ_UNLOCK(&ip_fw_lock);
  720. /* Recalculate checksum if not going to reject, and TOS changed. */
  721. if (ip->tos != oldtos
  722.     && ret != FW_REJECT && ret != FW_BLOCK
  723.     && !testing)
  724. ip_send_check(ip);
  725. if (ret == FW_REDIRECT && redirport) {
  726. if ((*redirport = htons(f->ipfw.fw_redirpt)) == 0) {
  727. /* Wildcard redirection.
  728.  * Note that redirport will become
  729.  * 0xFFFF for non-TCP/UDP packets.
  730.  */
  731. *redirport = htons(dst_port);
  732. }
  733. }
  734. #ifdef DEBUG_ALLOW_ALL
  735. return (testing ? ret : FW_ACCEPT);
  736. #else
  737. return ret;
  738. #endif
  739. }
  740. /* Must have write lock & interrupts off for any of these */
  741. /* This function sets all the byte counters in a chain to zero.  The
  742.  * input is a pointer to the chain required for zeroing */
  743. static int zero_fw_chain(struct ip_chain *chainptr)
  744. {
  745. struct ip_fwkernel *i;
  746. FWC_HAVE_LOCK(fwc_wlocks);
  747. for (i = chainptr->chain; i; i = i->next)
  748. memset(i->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS);
  749. return 0;
  750. }
  751. static int clear_fw_chain(struct ip_chain *chainptr)
  752. {
  753. struct ip_fwkernel *i= chainptr->chain;
  754. FWC_HAVE_LOCK(fwc_wlocks);
  755. chainptr->chain=NULL;
  756. while (i) {
  757. struct ip_fwkernel *tmp = i->next;
  758. if (i->branch)
  759. i->branch->refcount--;
  760. kfree(i);
  761. i = tmp;
  762. MOD_DEC_USE_COUNT;
  763. }
  764. return 0;
  765. }
  766. static int replace_in_chain(struct ip_chain *chainptr,
  767.     struct ip_fwkernel *frwl,
  768.     __u32 position)
  769. {
  770. struct ip_fwkernel *f = chainptr->chain;
  771. FWC_HAVE_LOCK(fwc_wlocks);
  772. while (--position && f != NULL) f = f->next;
  773. if (f == NULL)
  774. return EINVAL;
  775. if (f->branch) f->branch->refcount--;
  776. if (frwl->branch) frwl->branch->refcount++;
  777. frwl->next = f->next;
  778. memcpy(f,frwl,sizeof(struct ip_fwkernel));
  779. kfree(frwl);
  780. return 0;
  781. }
  782. static int append_to_chain(struct ip_chain *chainptr, struct ip_fwkernel *rule)
  783. {
  784. struct ip_fwkernel *i;
  785. FWC_HAVE_LOCK(fwc_wlocks);
  786. /* Special case if no rules already present */
  787. if (chainptr->chain == NULL) {
  788. /* If pointer writes are atomic then turning off
  789.  * interrupts is not necessary. */
  790. chainptr->chain = rule;
  791. if (rule->branch) rule->branch->refcount++;
  792. goto append_successful;
  793. }
  794. /* Find the rule before the end of the chain */
  795. for (i = chainptr->chain; i->next; i = i->next);
  796. i->next = rule;
  797. if (rule->branch) rule->branch->refcount++;
  798. append_successful:
  799. MOD_INC_USE_COUNT;
  800. return 0;
  801. }
  802. /* This function inserts a rule at the position of position in the
  803.  * chain refenced by chainptr.  If position is 1 then this rule will
  804.  * become the new rule one. */
  805. static int insert_in_chain(struct ip_chain *chainptr,
  806.    struct ip_fwkernel *frwl,
  807.    __u32 position)
  808. {
  809. struct ip_fwkernel *f = chainptr->chain;
  810. FWC_HAVE_LOCK(fwc_wlocks);
  811. /* special case if the position is number 1 */
  812. if (position == 1) {
  813. frwl->next = chainptr->chain;
  814. if (frwl->branch) frwl->branch->refcount++;
  815. chainptr->chain = frwl;
  816. goto insert_successful;
  817. }
  818. position--;
  819. while (--position && f != NULL) f = f->next;
  820. if (f == NULL)
  821. return EINVAL;
  822. if (frwl->branch) frwl->branch->refcount++;
  823. frwl->next = f->next;
  824. f->next = frwl;
  825. insert_successful:
  826. MOD_INC_USE_COUNT;
  827. return 0;
  828. }
  829. /* This function deletes the a rule from a given rulenum and chain.
  830.  * With rulenum = 1 is the first rule is deleted. */
  831. static int del_num_from_chain(struct ip_chain *chainptr, __u32 rulenum)
  832. {
  833. struct ip_fwkernel *i=chainptr->chain,*tmp;
  834. FWC_HAVE_LOCK(fwc_wlocks);
  835. if (!chainptr->chain)
  836. return ENOENT;
  837. /* Need a special case for the first rule */
  838. if (rulenum == 1) {
  839. /* store temp to allow for freeing up of memory */
  840. tmp = chainptr->chain;
  841.         if (chainptr->chain->branch) chainptr->chain->branch->refcount--;
  842. chainptr->chain = chainptr->chain->next;
  843. kfree(tmp); /* free memory that is now unused */
  844. } else {
  845. rulenum--;
  846. while (--rulenum && i->next ) i = i->next;
  847. if (!i->next)
  848. return ENOENT;
  849. tmp = i->next;
  850. if (i->next->branch)
  851. i->next->branch->refcount--;
  852. i->next = i->next->next;
  853. kfree(tmp);
  854. }
  855. MOD_DEC_USE_COUNT;
  856. return 0;
  857. }
  858. /* This function deletes the a rule from a given rule and chain.
  859.  * The rule that is deleted is the first occursance of that rule. */
  860. static int del_rule_from_chain(struct ip_chain *chainptr,
  861.        struct ip_fwkernel *frwl)
  862. {
  863. struct ip_fwkernel *ltmp,*ftmp = chainptr->chain ;
  864. int was_found;
  865. FWC_HAVE_LOCK(fwc_wlocks);
  866. /* Sure, we should compare marks, but since the `ipfwadm'
  867.  * script uses it for an unholy hack... well, life is easier
  868.  * this way.  We also mask it out of the flags word. --PR */
  869. for (ltmp=NULL, was_found=0;
  870.      !was_found && ftmp != NULL;
  871.      ltmp = ftmp,ftmp = ftmp->next) {
  872. if (ftmp->ipfw.fw_src.s_addr!=frwl->ipfw.fw_src.s_addr
  873.     || ftmp->ipfw.fw_dst.s_addr!=frwl->ipfw.fw_dst.s_addr
  874.     || ftmp->ipfw.fw_smsk.s_addr!=frwl->ipfw.fw_smsk.s_addr
  875.     || ftmp->ipfw.fw_dmsk.s_addr!=frwl->ipfw.fw_dmsk.s_addr
  876. #if 0
  877.     || ftmp->ipfw.fw_flg!=frwl->ipfw.fw_flg
  878. #else
  879.     || ((ftmp->ipfw.fw_flg & ~IP_FW_F_MARKABS)
  880. != (frwl->ipfw.fw_flg & ~IP_FW_F_MARKABS))
  881. #endif
  882.     || ftmp->ipfw.fw_invflg!=frwl->ipfw.fw_invflg
  883.     || ftmp->ipfw.fw_proto!=frwl->ipfw.fw_proto
  884. #if 0
  885.     || ftmp->ipfw.fw_mark!=frwl->ipfw.fw_mark
  886. #endif
  887.     || ftmp->ipfw.fw_redirpt!=frwl->ipfw.fw_redirpt
  888.     || ftmp->ipfw.fw_spts[0]!=frwl->ipfw.fw_spts[0]
  889.     || ftmp->ipfw.fw_spts[1]!=frwl->ipfw.fw_spts[1]
  890.     || ftmp->ipfw.fw_dpts[0]!=frwl->ipfw.fw_dpts[0]
  891.     || ftmp->ipfw.fw_dpts[1]!=frwl->ipfw.fw_dpts[1]
  892.     || ftmp->ipfw.fw_outputsize!=frwl->ipfw.fw_outputsize) {
  893. duprintf("del_rule_from_chain: mismatch:"
  894.  "src:%u/%u dst:%u/%u smsk:%u/%u dmsk:%u/%u "
  895.  "flg:%hX/%hX invflg:%hX/%hX proto:%u/%u "
  896.  "mark:%u/%u "
  897.  "ports:%hu-%hu/%hu-%hu %hu-%hu/%hu-%hu "
  898.  "outputsize:%hu-%hun",
  899.  ftmp->ipfw.fw_src.s_addr,
  900.  frwl->ipfw.fw_src.s_addr,
  901.  ftmp->ipfw.fw_dst.s_addr,
  902.  frwl->ipfw.fw_dst.s_addr,
  903.  ftmp->ipfw.fw_smsk.s_addr,
  904.  frwl->ipfw.fw_smsk.s_addr,
  905.  ftmp->ipfw.fw_dmsk.s_addr,
  906.  frwl->ipfw.fw_dmsk.s_addr,
  907.  ftmp->ipfw.fw_flg,
  908.  frwl->ipfw.fw_flg,
  909.  ftmp->ipfw.fw_invflg,
  910.  frwl->ipfw.fw_invflg,
  911.  ftmp->ipfw.fw_proto,
  912.  frwl->ipfw.fw_proto,
  913.  ftmp->ipfw.fw_mark,
  914.  frwl->ipfw.fw_mark,
  915.  ftmp->ipfw.fw_spts[0],
  916.  frwl->ipfw.fw_spts[0],
  917.  ftmp->ipfw.fw_spts[1],
  918.  frwl->ipfw.fw_spts[1],
  919.  ftmp->ipfw.fw_dpts[0],
  920.  frwl->ipfw.fw_dpts[0],
  921.  ftmp->ipfw.fw_dpts[1],
  922.  frwl->ipfw.fw_dpts[1],
  923.  ftmp->ipfw.fw_outputsize,
  924.  frwl->ipfw.fw_outputsize);
  925. continue;
  926. }
  927. if (strncmp(ftmp->ipfw.fw_vianame,
  928.     frwl->ipfw.fw_vianame,
  929.     IFNAMSIZ)) {
  930. duprintf("del_rule_from_chain: if mismatch: %s/%sn",
  931.  ftmp->ipfw.fw_vianame,
  932.  frwl->ipfw.fw_vianame);
  933.         continue;
  934. }
  935. if (ftmp->branch != frwl->branch) {
  936. duprintf("del_rule_from_chain: branch mismatch: "
  937.  "%s/%sn",
  938.  ftmp->branch?ftmp->branch->label:"(null)",
  939.  frwl->branch?frwl->branch->label:"(null)");
  940. continue;
  941. }
  942. if (ftmp->branch == NULL
  943.     && ftmp->simplebranch != frwl->simplebranch) {
  944. duprintf("del_rule_from_chain: simplebranch mismatch: "
  945.  "%i/%in",
  946.  ftmp->simplebranch, frwl->simplebranch);
  947. continue;
  948. }
  949. was_found = 1;
  950. if (ftmp->branch)
  951. ftmp->branch->refcount--;
  952. if (ltmp)
  953. ltmp->next = ftmp->next;
  954. else
  955. chainptr->chain = ftmp->next;
  956. kfree(ftmp);
  957. MOD_DEC_USE_COUNT;
  958. break;
  959. }
  960. if (was_found)
  961. return 0;
  962. else {
  963. duprintf("del_rule_from_chain: no matching rule foundn");
  964. return EINVAL;
  965. }
  966. }
  967. /* This function takes the label of a chain and deletes the first
  968.  * chain with that name.  No special cases required for the built in
  969.  * chains as they have their refcount initilised to 1 so that they are
  970.  * never deleted.  */
  971. static int del_chain(ip_chainlabel label)
  972. {
  973. struct ip_chain *tmp,*tmp2;
  974. FWC_HAVE_LOCK(fwc_wlocks);
  975. /* Corner case: return EBUSY not ENOENT for first elem ("input") */
  976. if (strcmp(label, ip_fw_chains->label) == 0)
  977. return EBUSY;
  978. for (tmp = ip_fw_chains; tmp->next; tmp = tmp->next)
  979. if(strcmp(tmp->next->label,label) == 0)
  980. break;
  981. tmp2 = tmp->next;
  982. if (!tmp2)
  983. return ENOENT;
  984. if (tmp2->refcount)
  985. return EBUSY;
  986. if (tmp2->chain)
  987. return ENOTEMPTY;
  988. tmp->next = tmp2->next;
  989. kfree(tmp2);
  990. MOD_DEC_USE_COUNT;
  991. return 0;
  992. }
  993. /* This is a function to initilise a chain.  Built in rules start with
  994.  * refcount = 1 so that they cannot be deleted.  User defined rules
  995.  * start with refcount = 0 so they can be deleted. */
  996. static struct ip_chain *ip_init_chain(ip_chainlabel name,
  997.       __u32 ref,
  998.       int policy)
  999. {
  1000. unsigned int i;
  1001. struct ip_chain *label
  1002. = kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_KERNEL);
  1003. if (label == NULL)
  1004. panic("Can't kmalloc for firewall chains.n");
  1005. strcpy(label->label,name);
  1006. label->next = NULL;
  1007. label->chain = NULL;
  1008. label->refcount = ref;
  1009. label->policy = policy;
  1010. for (i = 0; i < smp_num_cpus*2; i++) {
  1011. label->reent[i].counters.pcnt = label->reent[i].counters.bcnt
  1012. = 0;
  1013. label->reent[i].prevchain = NULL;
  1014. label->reent[i].prevrule = NULL;
  1015. }
  1016. return label;
  1017. }
  1018. /* This is a function for reating a new chain.  The chains is not
  1019.  * created if a chain of the same name already exists */
  1020. static int create_chain(ip_chainlabel label)
  1021. {
  1022. struct ip_chain *tmp;
  1023. if (!check_label(label))
  1024. return EINVAL;
  1025. FWC_HAVE_LOCK(fwc_wlocks);
  1026. for (tmp = ip_fw_chains; tmp->next; tmp = tmp->next)
  1027. if (strcmp(tmp->label,label) == 0)
  1028. return EEXIST;
  1029. if (strcmp(tmp->label,label) == 0)
  1030. return EEXIST;
  1031. tmp->next = ip_init_chain(label, 0, FW_SKIP); /* refcount is
  1032.       * zero since this is a
  1033.       * user defined chain *
  1034.       * and therefore can be
  1035.       * deleted */
  1036. MOD_INC_USE_COUNT;
  1037. return 0;
  1038. }
  1039. /* This function simply changes the policy on one of the built in
  1040.  * chains.  checking must be done before this is call to ensure that
  1041.  * chainptr is pointing to one of the three possible chains */
  1042. static int change_policy(struct ip_chain *chainptr, int policy)
  1043. {
  1044. FWC_HAVE_LOCK(fwc_wlocks);
  1045. chainptr->policy = policy;
  1046. return 0;
  1047. }
  1048. /* This function takes an ip_fwuser and converts it to a ip_fwkernel.  It also
  1049.  * performs some checks in the structure. */
  1050. static struct ip_fwkernel *convert_ipfw(struct ip_fwuser *fwuser, int *errno)
  1051. {
  1052. struct ip_fwkernel *fwkern;
  1053. if ( (fwuser->ipfw.fw_flg & ~IP_FW_F_MASK) != 0 ) {
  1054. duprintf("convert_ipfw: undefined flag bits set (flags=%x)n",
  1055.  fwuser->ipfw.fw_flg);
  1056. *errno = EINVAL;
  1057. return NULL;
  1058. }
  1059. #ifdef DEBUG_IP_FIREWALL_USER
  1060. /* These are sanity checks that don't really matter.
  1061.  * We can get rid of these once testing is complete.
  1062.  */
  1063. if ((fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN)
  1064.     && ((fwuser->ipfw.fw_invflg & IP_FW_INV_PROTO)
  1065. || fwuser->ipfw.fw_proto != IPPROTO_TCP)) {
  1066. duprintf("convert_ipfw: TCP SYN flag set but proto != TCP!n");
  1067. *errno = EINVAL;
  1068. return NULL;
  1069. }
  1070. if (strcmp(fwuser->label, IP_FW_LABEL_REDIRECT) != 0
  1071.     && fwuser->ipfw.fw_redirpt != 0) {
  1072. duprintf("convert_ipfw: Target not REDIR but redirpt != 0!n");
  1073. *errno = EINVAL;
  1074. return NULL;
  1075. }
  1076. if ((!(fwuser->ipfw.fw_flg & IP_FW_F_FRAG)
  1077.      && (fwuser->ipfw.fw_invflg & IP_FW_INV_FRAG))
  1078.     || (!(fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN)
  1079. && (fwuser->ipfw.fw_invflg & IP_FW_INV_SYN))) {
  1080. duprintf("convert_ipfw: Can't have INV flag if flag unset!n");
  1081. *errno = EINVAL;
  1082. return NULL;
  1083. }
  1084. if (((fwuser->ipfw.fw_invflg & IP_FW_INV_SRCPT)
  1085.      && fwuser->ipfw.fw_spts[0] == 0
  1086.      && fwuser->ipfw.fw_spts[1] == 0xFFFF)
  1087.     || ((fwuser->ipfw.fw_invflg & IP_FW_INV_DSTPT)
  1088. && fwuser->ipfw.fw_dpts[0] == 0
  1089. && fwuser->ipfw.fw_dpts[1] == 0xFFFF)
  1090.     || ((fwuser->ipfw.fw_invflg & IP_FW_INV_VIA)
  1091. && (fwuser->ipfw.fw_vianame)[0] == '')
  1092.     || ((fwuser->ipfw.fw_invflg & IP_FW_INV_SRCIP)
  1093. && fwuser->ipfw.fw_smsk.s_addr == 0)
  1094.     || ((fwuser->ipfw.fw_invflg & IP_FW_INV_DSTIP)
  1095. && fwuser->ipfw.fw_dmsk.s_addr == 0)) {
  1096. duprintf("convert_ipfw: INV flag makes rule unmatchable!n");
  1097. *errno = EINVAL;
  1098. return NULL;
  1099. }
  1100. if ((fwuser->ipfw.fw_flg & IP_FW_F_FRAG)
  1101.     && !(fwuser->ipfw.fw_invflg & IP_FW_INV_FRAG)
  1102.     && (fwuser->ipfw.fw_spts[0] != 0
  1103. || fwuser->ipfw.fw_spts[1] != 0xFFFF
  1104. || fwuser->ipfw.fw_dpts[0] != 0
  1105. || fwuser->ipfw.fw_dpts[1] != 0xFFFF
  1106. || (fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN))) {
  1107. duprintf("convert_ipfw: Can't test ports or SYN with frag!n");
  1108. *errno = EINVAL;
  1109. return NULL;
  1110. }
  1111. #endif
  1112. if ((fwuser->ipfw.fw_spts[0] != 0
  1113.      || fwuser->ipfw.fw_spts[1] != 0xFFFF
  1114.      || fwuser->ipfw.fw_dpts[0] != 0
  1115.      || fwuser->ipfw.fw_dpts[1] != 0xFFFF)
  1116.     && ((fwuser->ipfw.fw_invflg & IP_FW_INV_PROTO)
  1117. || (fwuser->ipfw.fw_proto != IPPROTO_TCP
  1118.     && fwuser->ipfw.fw_proto != IPPROTO_UDP
  1119.     && fwuser->ipfw.fw_proto != IPPROTO_ICMP))) {
  1120. duprintf("convert_ipfw: Can only test ports for TCP/UDP/ICMP!n");
  1121. *errno = EINVAL;
  1122. return NULL;
  1123. }
  1124. fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_KERNEL);
  1125. if (!fwkern) {
  1126. duprintf("convert_ipfw: kmalloc failed!n");
  1127. *errno = ENOMEM;
  1128. return NULL;
  1129. }
  1130. memcpy(&fwkern->ipfw,&fwuser->ipfw,sizeof(struct ip_fw));
  1131. if (!find_special(fwuser->label, &fwkern->simplebranch)) {
  1132. fwkern->branch = find_label(fwuser->label);
  1133. if (!fwkern->branch) {
  1134. duprintf("convert_ipfw: chain doesn't exist `%s'.n",
  1135.  fwuser->label);
  1136. kfree(fwkern);
  1137. *errno = ENOENT;
  1138. return NULL;
  1139. } else if (fwkern->branch == IP_FW_INPUT_CHAIN
  1140.    || fwkern->branch == IP_FW_FORWARD_CHAIN
  1141.    || fwkern->branch == IP_FW_OUTPUT_CHAIN) {
  1142. duprintf("convert_ipfw: Can't branch to builtin chain `%s'.n",
  1143.  fwuser->label);
  1144. kfree(fwkern);
  1145. *errno = ENOENT;
  1146. return NULL;
  1147. }
  1148. } else
  1149. fwkern->branch = NULL;
  1150. memset(fwkern->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS);
  1151. /* Handle empty vianame by making it a wildcard */
  1152. if ((fwkern->ipfw.fw_vianame)[0] == '')
  1153.     fwkern->ipfw.fw_flg |= IP_FW_F_WILDIF;
  1154. fwkern->next = NULL;
  1155. return fwkern;
  1156. }
  1157. int ip_fw_ctl(int cmd, void *m, int len)
  1158. {
  1159. int ret;
  1160. struct ip_chain *chain;
  1161. unsigned long flags;
  1162. FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
  1163. switch (cmd) {
  1164. case IP_FW_FLUSH:
  1165. if (len != sizeof(ip_chainlabel) || !check_label(m))
  1166. ret = EINVAL;
  1167. else if ((chain = find_label(m)) == NULL)
  1168. ret = ENOENT;
  1169. else ret = clear_fw_chain(chain);
  1170. break;
  1171. case IP_FW_ZERO:
  1172. if (len != sizeof(ip_chainlabel) || !check_label(m))
  1173. ret = EINVAL;
  1174. else if ((chain = find_label(m)) == NULL)
  1175. ret = ENOENT;
  1176. else ret = zero_fw_chain(chain);
  1177. break;
  1178. case IP_FW_CHECK: {
  1179. struct ip_fwtest *new = m;
  1180. struct iphdr *ip;
  1181. /* Don't need write lock. */
  1182. FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
  1183. if (len != sizeof(struct ip_fwtest) || !check_label(m))
  1184. return EINVAL;
  1185. /* Need readlock to do find_label */
  1186. FWC_READ_LOCK(&ip_fw_lock);
  1187. if ((chain = find_label(new->fwt_label)) == NULL)
  1188. ret = ENOENT;
  1189. else {
  1190. ip = &(new->fwt_packet.fwp_iph);
  1191. if (ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
  1192.     duprintf("ip_fw_ctl: ip->ihl=%d, want %dn",
  1193.      ip->ihl,
  1194.      sizeof(struct iphdr) / sizeof(int));
  1195.     ret = EINVAL;
  1196. }
  1197. else {
  1198. ret = ip_fw_check(ip, new->fwt_packet.fwp_vianame,
  1199.   NULL, chain,
  1200.   NULL, SLOT_NUMBER(), 1);
  1201. switch (ret) {
  1202. case FW_ACCEPT:
  1203. ret = 0; break;
  1204. case FW_REDIRECT:
  1205. ret = ECONNABORTED; break;
  1206. case FW_MASQUERADE:
  1207. ret = ECONNRESET; break;
  1208. case FW_REJECT:
  1209. ret = ECONNREFUSED; break;
  1210. /* Hack to help diag; these only get
  1211.    returned when testing. */
  1212. case FW_SKIP+1:
  1213. ret = ELOOP; break;
  1214. case FW_SKIP:
  1215. ret = ENFILE; break;
  1216. default: /* FW_BLOCK */
  1217. ret = ETIMEDOUT; break;
  1218. }
  1219. }
  1220. }
  1221. FWC_READ_UNLOCK(&ip_fw_lock);
  1222. return ret;
  1223. }
  1224. case IP_FW_MASQ_TIMEOUTS: {
  1225. ret = ip_fw_masq_timeouts(m, len);
  1226. }
  1227. break;
  1228. case IP_FW_REPLACE: {
  1229. struct ip_fwkernel *ip_fwkern;
  1230. struct ip_fwnew *new = m;
  1231. if (len != sizeof(struct ip_fwnew)
  1232.     || !check_label(new->fwn_label))
  1233. ret = EINVAL;
  1234. else if ((chain = find_label(new->fwn_label)) == NULL)
  1235. ret = ENOENT;
  1236. else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret))
  1237.  != NULL)
  1238. ret = replace_in_chain(chain, ip_fwkern,
  1239.        new->fwn_rulenum);
  1240. }
  1241. break;
  1242. case IP_FW_APPEND: {
  1243. struct ip_fwchange *new = m;
  1244. struct ip_fwkernel *ip_fwkern;
  1245. if (len != sizeof(struct ip_fwchange)
  1246.     || !check_label(new->fwc_label))
  1247. ret = EINVAL;
  1248. else if ((chain = find_label(new->fwc_label)) == NULL)
  1249. ret = ENOENT;
  1250. else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret))
  1251.  != NULL)
  1252. ret = append_to_chain(chain, ip_fwkern);
  1253. }
  1254. break;
  1255. case IP_FW_INSERT: {
  1256. struct ip_fwkernel *ip_fwkern;
  1257. struct ip_fwnew *new = m;
  1258. if (len != sizeof(struct ip_fwnew)
  1259.     || !check_label(new->fwn_label))
  1260. ret = EINVAL;
  1261. else if ((chain = find_label(new->fwn_label)) == NULL)
  1262. ret = ENOENT;
  1263. else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret))
  1264.  != NULL)
  1265. ret = insert_in_chain(chain, ip_fwkern,
  1266.       new->fwn_rulenum);
  1267. }
  1268. break;
  1269. case IP_FW_DELETE: {
  1270. struct ip_fwchange *new = m;
  1271. struct ip_fwkernel *ip_fwkern;
  1272. if (len != sizeof(struct ip_fwchange)
  1273.     || !check_label(new->fwc_label))
  1274. ret = EINVAL;
  1275. else if ((chain = find_label(new->fwc_label)) == NULL)
  1276. ret = ENOENT;
  1277. else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret))
  1278.  != NULL) {
  1279. ret = del_rule_from_chain(chain, ip_fwkern);
  1280. kfree(ip_fwkern);
  1281. }
  1282. }
  1283. break;
  1284. case IP_FW_DELETE_NUM: {
  1285. struct ip_fwdelnum *new = m;
  1286. if (len != sizeof(struct ip_fwdelnum)
  1287.     || !check_label(new->fwd_label))
  1288. ret = EINVAL;
  1289. else if ((chain = find_label(new->fwd_label)) == NULL)
  1290. ret = ENOENT;
  1291. else ret = del_num_from_chain(chain, new->fwd_rulenum);
  1292. }
  1293. break;
  1294. case IP_FW_CREATECHAIN: {
  1295. if (len != sizeof(ip_chainlabel)) {
  1296. duprintf("create_chain: bad size %in", len);
  1297. ret = EINVAL;
  1298. }
  1299. else ret = create_chain(m);
  1300. }
  1301. break;
  1302. case IP_FW_DELETECHAIN: {
  1303. if (len != sizeof(ip_chainlabel)) {
  1304. duprintf("delete_chain: bad size %in", len);
  1305. ret = EINVAL;
  1306. }
  1307. else ret = del_chain(m);
  1308. }
  1309. break;
  1310. case IP_FW_POLICY: {
  1311. struct ip_fwpolicy *new = m;
  1312. if (len != sizeof(struct ip_fwpolicy)
  1313.     || !check_label(new->fwp_label))
  1314. ret = EINVAL;
  1315. else if ((chain = find_label(new->fwp_label)) == NULL)
  1316. ret = ENOENT;
  1317. else if (chain != IP_FW_INPUT_CHAIN
  1318.  && chain != IP_FW_FORWARD_CHAIN
  1319.  && chain != IP_FW_OUTPUT_CHAIN) {
  1320. duprintf("change_policy: can't change policy on user"
  1321.  " defined chain.n");
  1322. ret = EINVAL;
  1323. }
  1324. else {
  1325.         int pol = FW_SKIP;
  1326. find_special(new->fwp_policy, &pol);
  1327. switch(pol) {
  1328. case FW_MASQUERADE:
  1329. if (chain != IP_FW_FORWARD_CHAIN) {
  1330. ret = EINVAL;
  1331. break;
  1332. }
  1333. /* Fall thru... */
  1334. case FW_BLOCK:
  1335. case FW_ACCEPT:
  1336. case FW_REJECT:
  1337. ret = change_policy(chain, pol);
  1338. break;
  1339. default:
  1340.         duprintf("change_policy: bad policy `%s'n",
  1341.  new->fwp_policy);
  1342. ret = EINVAL;
  1343. }
  1344. }
  1345. break;
  1346. }
  1347. default:
  1348. duprintf("ip_fw_ctl:  unknown request %dn",cmd);
  1349. ret = ENOPROTOOPT;
  1350. }
  1351. FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
  1352. return ret;
  1353. }
  1354. /* Returns bytes used - doesn't NUL terminate */
  1355. static int dump_rule(char *buffer,
  1356.      const char *chainlabel,
  1357.      const struct ip_fwkernel *rule)
  1358. {
  1359. int len;
  1360. unsigned int i;
  1361. __u64 packets = 0, bytes = 0;
  1362. FWC_HAVE_LOCK(fwc_wlocks);
  1363. for (i = 0; i < NUM_SLOTS; i++) {
  1364. packets += rule->counters[i].pcnt;
  1365. bytes += rule->counters[i].bcnt;
  1366. }
  1367. len=sprintf(buffer,
  1368.     "%9s " /* Chain name */
  1369.     "%08X/%08X->%08X/%08X " /* Source & Destination IPs */
  1370.     "%.16s " /* Interface */
  1371.     "%X %X " /* fw_flg and fw_invflg fields */
  1372.     "%u " /* Protocol */
  1373.     "%-9u %-9u %-9u %-9u " /* Packet & byte counters */
  1374.     "%u-%u %u-%u " /* Source & Dest port ranges */
  1375.     "A%02X X%02X " /* TOS and and xor masks */
  1376.     "%08X " /* Redirection port */
  1377.     "%u " /* fw_mark field */
  1378.     "%u " /* output size */
  1379.     "%9sn", /* Target */
  1380.     chainlabel,
  1381.     ntohl(rule->ipfw.fw_src.s_addr),
  1382.     ntohl(rule->ipfw.fw_smsk.s_addr),
  1383.     ntohl(rule->ipfw.fw_dst.s_addr),
  1384.     ntohl(rule->ipfw.fw_dmsk.s_addr),
  1385.     (rule->ipfw.fw_vianame)[0] ? rule->ipfw.fw_vianame : "-",
  1386.     rule->ipfw.fw_flg,
  1387.     rule->ipfw.fw_invflg,
  1388.     rule->ipfw.fw_proto,
  1389.     (__u32)(packets >> 32), (__u32)packets,
  1390.     (__u32)(bytes >> 32), (__u32)bytes,
  1391.     rule->ipfw.fw_spts[0], rule->ipfw.fw_spts[1],
  1392.     rule->ipfw.fw_dpts[0], rule->ipfw.fw_dpts[1],
  1393.     rule->ipfw.fw_tosand, rule->ipfw.fw_tosxor,
  1394.     rule->ipfw.fw_redirpt,
  1395.     rule->ipfw.fw_mark,
  1396.     rule->ipfw.fw_outputsize,
  1397.     branchname(rule->branch,rule->simplebranch));
  1398. duprintf("dump_rule: %i bytes done.n", len);
  1399. return len;
  1400. }
  1401. /* File offset is actually in records, not bytes. */
  1402. static int ip_chain_procinfo(char *buffer, char **start,
  1403.      off_t offset, int length
  1404. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
  1405.      , int reset
  1406. #endif
  1407. )
  1408. {
  1409. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
  1410. /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
  1411. int reset = 0;
  1412. #endif
  1413. struct ip_chain *i;
  1414. struct ip_fwkernel *j = ip_fw_chains->chain;
  1415. unsigned long flags;
  1416. int len = 0;
  1417. int last_len = 0;
  1418. off_t upto = 0;
  1419. duprintf("Offset starts at %lun", offset);
  1420. duprintf("ip_fw_chains is 0x%0lXn", (unsigned long int)ip_fw_chains);
  1421. /* Need a write lock to lock out ``readers'' which update counters. */
  1422. FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
  1423. for (i = ip_fw_chains; i; i = i->next) {
  1424.     for (j = i->chain; j; j = j->next) {
  1425. if (upto == offset) break;
  1426. duprintf("Skipping rule in chain `%s'n",
  1427.  i->label);
  1428. upto++;
  1429.     }
  1430.     if (upto == offset) break;
  1431. }
  1432. /* Don't init j first time, or once i = NULL */
  1433. for (; i; (void)((i = i->next) && (j = i->chain))) {
  1434. duprintf("Dumping chain `%s'n", i->label);
  1435. for (; j; j = j->next, upto++, last_len = len)
  1436. {
  1437. len += dump_rule(buffer+len, i->label, j);
  1438. if (len > length) {
  1439. duprintf("Dumped to %i (past %i).  "
  1440.  "Moving back to %i.n",
  1441.  len, length, last_len);
  1442. len = last_len;
  1443. goto outside;
  1444. }
  1445. else if (reset)
  1446. memset(j->counters, 0,
  1447.        sizeof(struct ip_counters)*NUM_SLOTS);
  1448. }
  1449. }
  1450. outside:
  1451. FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
  1452. buffer[len] = '';
  1453. duprintf("ip_chain_procinfo: Length = %i (of %i).  Offset = %li.n",
  1454.  len, length, upto);
  1455. /* `start' hack - see fs/proc/generic.c line ~165 */
  1456. *start=(char *)((unsigned int)upto-offset);
  1457. return len;
  1458. }
  1459. static int ip_chain_name_procinfo(char *buffer, char **start,
  1460.   off_t offset, int length)
  1461. {
  1462. struct ip_chain *i;
  1463. int len = 0,last_len = 0;
  1464. off_t pos = 0,begin = 0;
  1465. unsigned long flags;
  1466. /* Need a write lock to lock out ``readers'' which update counters. */
  1467. FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
  1468. for (i = ip_fw_chains; i; i = i->next)
  1469. {
  1470. unsigned int j;
  1471. __u32 packetsHi = 0, packetsLo = 0, bytesHi = 0, bytesLo = 0;
  1472. for (j = 0; j < NUM_SLOTS; j++) {
  1473. packetsLo += i->reent[j].counters.pcnt & 0xFFFFFFFF;
  1474. packetsHi += ((i->reent[j].counters.pcnt >> 32)
  1475.       & 0xFFFFFFFF);
  1476. bytesLo += i->reent[j].counters.bcnt & 0xFFFFFFFF;
  1477. bytesHi += ((i->reent[j].counters.bcnt >> 32)
  1478.     & 0xFFFFFFFF);
  1479. }
  1480. /* print the label and the policy */
  1481. len+=sprintf(buffer+len,"%s %s %i %u %u %u %un",
  1482.      i->label,branchname(NULL, i->policy),i->refcount,
  1483.      packetsHi, packetsLo, bytesHi, bytesLo);
  1484. pos=begin+len;
  1485. if(pos<offset) {
  1486. len=0;
  1487. begin=pos;
  1488. }
  1489. else if(pos>offset+length) {
  1490. len = last_len;
  1491. break;
  1492. }
  1493. last_len = len;
  1494. }
  1495. FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
  1496. *start = buffer+(offset-begin);
  1497. len-=(offset-begin);
  1498. if(len>length)
  1499. len=length;
  1500. return len;
  1501. }
  1502. /*
  1503.  * Interface to the generic firewall chains.
  1504.  */
  1505. int ipfw_input_check(struct firewall_ops *this, int pf,
  1506.      struct net_device *dev, void *phdr, void *arg,
  1507.      struct sk_buff **pskb)
  1508. {
  1509. return ip_fw_check(phdr, dev->name,
  1510.    arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
  1511. }
  1512. int ipfw_output_check(struct firewall_ops *this, int pf,
  1513.       struct net_device *dev, void *phdr, void *arg,
  1514.       struct sk_buff **pskb)
  1515. {
  1516. /* Locally generated bogus packets by root. <SIGH>. */
  1517. if (((struct iphdr *)phdr)->ihl * 4 < sizeof(struct iphdr)
  1518.     || (*pskb)->len < sizeof(struct iphdr))
  1519. return FW_ACCEPT;
  1520. return ip_fw_check(phdr, dev->name,
  1521.    arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
  1522. }
  1523. int ipfw_forward_check(struct firewall_ops *this, int pf,
  1524.        struct net_device *dev, void *phdr, void *arg,
  1525.        struct sk_buff **pskb)
  1526. {
  1527. return ip_fw_check(phdr, dev->name,
  1528.    arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0);
  1529. }
  1530. struct firewall_ops ipfw_ops=
  1531. {
  1532. NULL,
  1533. ipfw_forward_check,
  1534. ipfw_input_check,
  1535. ipfw_output_check,
  1536. NULL,
  1537. NULL
  1538. };
  1539. int ipfw_init_or_cleanup(int init)
  1540. {
  1541. struct proc_dir_entry *proc;
  1542. int ret = 0;
  1543. unsigned long flags;
  1544. if (!init) goto cleanup;
  1545. #ifdef DEBUG_IP_FIREWALL_LOCKING
  1546. fwc_wlocks = fwc_rlocks = 0;
  1547. #endif
  1548. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  1549. ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
  1550. if (ipfwsk == NULL)
  1551. goto cleanup_nothing;
  1552. #endif
  1553. ret = register_firewall(PF_INET, &ipfw_ops);
  1554. if (ret < 0)
  1555. goto cleanup_netlink;
  1556. proc = proc_net_create(IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR,
  1557.        ip_chain_procinfo);
  1558. if (proc) proc->owner = THIS_MODULE;
  1559. proc = proc_net_create(IP_FW_PROC_CHAIN_NAMES,
  1560.        S_IFREG | S_IRUSR | S_IWUSR,
  1561.        ip_chain_name_procinfo);
  1562. if (proc) proc->owner = THIS_MODULE;
  1563. IP_FW_INPUT_CHAIN = ip_init_chain(IP_FW_LABEL_INPUT, 1, FW_ACCEPT);
  1564. IP_FW_FORWARD_CHAIN = ip_init_chain(IP_FW_LABEL_FORWARD, 1, FW_ACCEPT);
  1565. IP_FW_OUTPUT_CHAIN = ip_init_chain(IP_FW_LABEL_OUTPUT, 1, FW_ACCEPT);
  1566. return ret;
  1567.  cleanup:
  1568. unregister_firewall(PF_INET, &ipfw_ops);
  1569. FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
  1570. while (ip_fw_chains) {
  1571. struct ip_chain *next = ip_fw_chains->next;
  1572. clear_fw_chain(ip_fw_chains);
  1573. kfree(ip_fw_chains);
  1574. ip_fw_chains = next;
  1575. }
  1576. FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
  1577. proc_net_remove(IP_FW_PROC_CHAINS);
  1578. proc_net_remove(IP_FW_PROC_CHAIN_NAMES);
  1579.  cleanup_netlink:
  1580. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  1581. sock_release(ipfwsk->socket);
  1582.  cleanup_nothing:
  1583. #endif
  1584. return ret;
  1585. }
  1586. MODULE_LICENSE("BSD without advertisement clause");