iptable_filter.c revision c9bdd4b5257406b0608385d19c40b5511decf4f6
1/* 2 * This is the 1999 rewrite of IP Firewalling, aiming for kernel 2.3.x. 3 * 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 */ 12 13#include <linux/module.h> 14#include <linux/moduleparam.h> 15#include <linux/netfilter_ipv4/ip_tables.h> 16#include <net/ip.h> 17 18MODULE_LICENSE("GPL"); 19MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 20MODULE_DESCRIPTION("iptables filter table"); 21 22#define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)) 23 24static struct 25{ 26 struct ipt_replace repl; 27 struct ipt_standard entries[3]; 28 struct ipt_error term; 29} initial_table __initdata 30= { { "filter", FILTER_VALID_HOOKS, 4, 31 sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), 32 { [NF_IP_LOCAL_IN] = 0, 33 [NF_IP_FORWARD] = sizeof(struct ipt_standard), 34 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 35 { [NF_IP_LOCAL_IN] = 0, 36 [NF_IP_FORWARD] = sizeof(struct ipt_standard), 37 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 38 0, NULL, { } }, 39 { 40 /* LOCAL_IN */ 41 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 42 0, 43 sizeof(struct ipt_entry), 44 sizeof(struct ipt_standard), 45 0, { 0, 0 }, { } }, 46 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 47 -NF_ACCEPT - 1 } }, 48 /* FORWARD */ 49 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 50 0, 51 sizeof(struct ipt_entry), 52 sizeof(struct ipt_standard), 53 0, { 0, 0 }, { } }, 54 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 55 -NF_ACCEPT - 1 } }, 56 /* LOCAL_OUT */ 57 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 58 0, 59 sizeof(struct ipt_entry), 60 sizeof(struct ipt_standard), 61 0, { 0, 0 }, { } }, 62 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 63 -NF_ACCEPT - 1 } } 64 }, 65 /* ERROR */ 66 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 67 0, 68 sizeof(struct ipt_entry), 69 sizeof(struct ipt_error), 70 0, { 0, 0 }, { } }, 71 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, 72 { } }, 73 "ERROR" 74 } 75 } 76}; 77 78static struct xt_table packet_filter = { 79 .name = "filter", 80 .valid_hooks = FILTER_VALID_HOOKS, 81 .lock = RW_LOCK_UNLOCKED, 82 .me = THIS_MODULE, 83 .af = AF_INET, 84}; 85 86/* The work comes in here from netfilter.c. */ 87static unsigned int 88ipt_hook(unsigned int hook, 89 struct sk_buff **pskb, 90 const struct net_device *in, 91 const struct net_device *out, 92 int (*okfn)(struct sk_buff *)) 93{ 94 return ipt_do_table(pskb, hook, in, out, &packet_filter); 95} 96 97static unsigned int 98ipt_local_out_hook(unsigned int hook, 99 struct sk_buff **pskb, 100 const struct net_device *in, 101 const struct net_device *out, 102 int (*okfn)(struct sk_buff *)) 103{ 104 /* root is playing with raw sockets. */ 105 if ((*pskb)->len < sizeof(struct iphdr) 106 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { 107 if (net_ratelimit()) 108 printk("ipt_hook: happy cracking.\n"); 109 return NF_ACCEPT; 110 } 111 112 return ipt_do_table(pskb, hook, in, out, &packet_filter); 113} 114 115static struct nf_hook_ops ipt_ops[] = { 116 { 117 .hook = ipt_hook, 118 .owner = THIS_MODULE, 119 .pf = PF_INET, 120 .hooknum = NF_IP_LOCAL_IN, 121 .priority = NF_IP_PRI_FILTER, 122 }, 123 { 124 .hook = ipt_hook, 125 .owner = THIS_MODULE, 126 .pf = PF_INET, 127 .hooknum = NF_IP_FORWARD, 128 .priority = NF_IP_PRI_FILTER, 129 }, 130 { 131 .hook = ipt_local_out_hook, 132 .owner = THIS_MODULE, 133 .pf = PF_INET, 134 .hooknum = NF_IP_LOCAL_OUT, 135 .priority = NF_IP_PRI_FILTER, 136 }, 137}; 138 139/* Default to forward because I got too much mail already. */ 140static int forward = NF_ACCEPT; 141module_param(forward, bool, 0000); 142 143static int __init iptable_filter_init(void) 144{ 145 int ret; 146 147 if (forward < 0 || forward > NF_MAX_VERDICT) { 148 printk("iptables forward must be 0 or 1\n"); 149 return -EINVAL; 150 } 151 152 /* Entry 1 is the FORWARD hook */ 153 initial_table.entries[1].target.verdict = -forward - 1; 154 155 /* Register table */ 156 ret = ipt_register_table(&packet_filter, &initial_table.repl); 157 if (ret < 0) 158 return ret; 159 160 /* Register hooks */ 161 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 162 if (ret < 0) 163 goto cleanup_table; 164 165 return ret; 166 167 cleanup_table: 168 ipt_unregister_table(&packet_filter); 169 return ret; 170} 171 172static void __exit iptable_filter_fini(void) 173{ 174 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 175 ipt_unregister_table(&packet_filter); 176} 177 178module_init(iptable_filter_init); 179module_exit(iptable_filter_fini); 180