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 */ 6#include <linux/module.h> 7#include <linux/netfilter_ipv4/ip_tables.h> 8 9#define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)) 10 11/* Standard entry. */ 12struct ipt_standard 13{ 14 struct ipt_entry entry; 15 struct ipt_standard_target target; 16}; 17 18struct ipt_error_target 19{ 20 struct ipt_entry_target target; 21 char errorname[IPT_FUNCTION_MAXNAMELEN]; 22}; 23 24struct ipt_error 25{ 26 struct ipt_entry entry; 27 struct ipt_error_target target; 28}; 29 30static struct 31{ 32 struct ipt_replace repl; 33 struct ipt_standard entries[3]; 34 struct ipt_error term; 35} initial_table __initdata 36= { { "filter", FILTER_VALID_HOOKS, 4, 37 sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), 38 { [NF_IP_LOCAL_IN] 0, 39 [NF_IP_FORWARD] sizeof(struct ipt_standard), 40 [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 }, 41 { [NF_IP_LOCAL_IN] 0, 42 [NF_IP_FORWARD] sizeof(struct ipt_standard), 43 [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 }, 44 0, NULL, { } }, 45 { 46 /* LOCAL_IN */ 47 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 48 0, 49 sizeof(struct ipt_entry), 50 sizeof(struct ipt_standard), 51 0, { 0, 0 }, { } }, 52 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 53 -NF_ACCEPT - 1 } }, 54 /* FORWARD */ 55 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 56 0, 57 sizeof(struct ipt_entry), 58 sizeof(struct ipt_standard), 59 0, { 0, 0 }, { } }, 60 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 61 -NF_ACCEPT - 1 } }, 62 /* LOCAL_OUT */ 63 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 64 0, 65 sizeof(struct ipt_entry), 66 sizeof(struct ipt_standard), 67 0, { 0, 0 }, { } }, 68 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 69 -NF_ACCEPT - 1 } } 70 }, 71 /* ERROR */ 72 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 73 0, 74 sizeof(struct ipt_entry), 75 sizeof(struct ipt_error), 76 0, { 0, 0 }, { } }, 77 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, 78 { } }, 79 "ERROR" 80 } 81 } 82}; 83 84static struct ipt_table packet_filter 85= { { NULL, NULL }, "filter", &initial_table.repl, 86 FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE }; 87 88/* The work comes in here from netfilter.c. */ 89static unsigned int 90ipt_hook(unsigned int hook, 91 struct sk_buff **pskb, 92 const struct net_device *in, 93 const struct net_device *out, 94 int (*okfn)(struct sk_buff *)) 95{ 96 return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL); 97} 98 99static unsigned int 100ipt_local_out_hook(unsigned int hook, 101 struct sk_buff **pskb, 102 const struct net_device *in, 103 const struct net_device *out, 104 int (*okfn)(struct sk_buff *)) 105{ 106 /* root is playing with raw sockets. */ 107 if ((*pskb)->len < sizeof(struct iphdr) 108 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { 109 if (net_ratelimit()) 110 printk("ipt_hook: happy cracking.\n"); 111 return NF_ACCEPT; 112 } 113 114 return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL); 115} 116 117static struct nf_hook_ops ipt_ops[] 118= { { { NULL, NULL }, ipt_hook, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_FILTER }, 119 { { NULL, NULL }, ipt_hook, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER }, 120 { { NULL, NULL }, ipt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT, 121 NF_IP_PRI_FILTER } 122}; 123 124/* Default to forward because I got too much mail already. */ 125static int forward = NF_ACCEPT; 126MODULE_PARM(forward, "i"); 127 128static int __init init(void) 129{ 130 int ret; 131 132 if (forward < 0 || forward > NF_MAX_VERDICT) { 133 printk("iptables forward must be 0 or 1\n"); 134 return -EINVAL; 135 } 136 137 /* Entry 1 is the FORWARD hook */ 138 initial_table.entries[1].target.verdict = -forward - 1; 139 140 /* Register table */ 141 ret = ipt_register_table(&packet_filter); 142 if (ret < 0) 143 return ret; 144 145 /* Register hooks */ 146 ret = nf_register_hook(&ipt_ops[0]); 147 if (ret < 0) 148 goto cleanup_table; 149 150 ret = nf_register_hook(&ipt_ops[1]); 151 if (ret < 0) 152 goto cleanup_hook0; 153 154 ret = nf_register_hook(&ipt_ops[2]); 155 if (ret < 0) 156 goto cleanup_hook1; 157 158 return ret; 159 160 cleanup_hook1: 161 nf_unregister_hook(&ipt_ops[1]); 162 cleanup_hook0: 163 nf_unregister_hook(&ipt_ops[0]); 164 cleanup_table: 165 ipt_unregister_table(&packet_filter); 166 167 return ret; 168} 169 170static void __exit fini(void) 171{ 172 unsigned int i; 173 174 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) 175 nf_unregister_hook(&ipt_ops[i]); 176 177 ipt_unregister_table(&packet_filter); 178} 179 180module_init(init); 181module_exit(fini); 182MODULE_LICENSE("GPL"); 183