1 /* Compatibility framework for ipchains and ipfwadm support; designed
2 to look as much like the 2.2 infrastructure as possible. */
4 /* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
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.
12 struct notifier_block;
14 #include <linux/netfilter_ipv4.h>
18 #include <linux/inetdevice.h>
19 #include <linux/netdevice.h>
20 #include <linux/module.h>
21 #include <asm/uaccess.h>
23 #include <net/route.h>
24 #include <linux/netfilter_ipv4/compat_firewall.h>
25 #include <linux/netfilter_ipv4/ip_conntrack.h>
26 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
27 #include "ip_fw_compat.h"
29 static struct firewall_ops *fwops;
32 /* From ip_vs_core.c */
34 check_for_ip_vs_out(struct sk_buff **skb_p, int (*okfn)(struct sk_buff *));
37 /* They call these; we do what they want. */
38 int register_firewall(int pf, struct firewall_ops *fw)
41 printk("Attempt to register non-IP firewall module.\n");
45 printk("Attempt to register multiple firewall modules.\n");
53 int unregister_firewall(int pf, struct firewall_ops *fw)
60 fw_in(unsigned int hooknum,
61 struct sk_buff **pskb,
62 const struct net_device *in,
63 const struct net_device *out,
64 int (*okfn)(struct sk_buff *))
69 /* Assume worse case: any hook could change packet */
70 (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
71 if ((*pskb)->ip_summed == CHECKSUM_HW)
72 if (skb_checksum_help(pskb, (out == NULL)))
76 case NF_IP_PRE_ROUTING:
77 if (fwops->fw_acct_in)
78 fwops->fw_acct_in(fwops, PF_INET,
79 (struct net_device *)in,
82 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
83 *pskb = ip_ct_gather_frags(*pskb);
89 ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in,
94 /* Connection will only be set if it was
95 demasqueraded: if so, skip forward chain. */
98 else ret = fwops->fw_forward(fwops, PF_INET,
99 (struct net_device *)out,
103 case NF_IP_POST_ROUTING:
104 ret = fwops->fw_output(fwops, PF_INET,
105 (struct net_device *)out,
107 if (ret == FW_ACCEPT || ret == FW_SKIP) {
108 if (fwops->fw_acct_out)
109 fwops->fw_acct_out(fwops, PF_INET,
110 (struct net_device *)out,
114 /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */
115 if (ip_conntrack_confirm(*pskb) == NF_DROP)
125 * Generally, routing is THE FIRST thing to make, when
126 * packet enters IP stack. Before packet is routed you
127 * cannot call any service routines from IP stack. */
128 struct iphdr *iph = (*pskb)->nh.iph;
130 if ((*pskb)->dst != NULL
131 || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos,
132 (struct net_device *)in) == 0)
133 icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
140 if (hooknum == NF_IP_PRE_ROUTING) {
141 check_for_demasq(pskb);
142 check_for_redirect(*pskb);
143 } else if (hooknum == NF_IP_POST_ROUTING) {
144 check_for_unredirect(*pskb);
145 /* Handle ICMP errors from client here */
146 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
148 check_for_masq_error(pskb);
153 if (hooknum == NF_IP_FORWARD) {
155 /* check if it is for ip_vs */
156 if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN)
159 return do_masquerade(pskb, out);
161 else return NF_ACCEPT;
164 if (hooknum == NF_IP_PRE_ROUTING)
165 return do_redirect(*pskb, in, redirpt);
166 else return NF_ACCEPT;
174 static unsigned int fw_confirm(unsigned int hooknum,
175 struct sk_buff **pskb,
176 const struct net_device *in,
177 const struct net_device *out,
178 int (*okfn)(struct sk_buff *))
180 return ip_conntrack_confirm(*pskb);
183 extern int ip_fw_ctl(int optval, void *m, unsigned int len);
185 static int sock_fn(struct sock *sk, int optval, void __user *user, unsigned int len)
188 2.2: sizeof(struct ip_fwtest) (~14x4 + 3x4 = 17x4)
189 2.2: sizeof(struct ip_fwnew) (~1x4 + 15x4 + 3x4 + 3x4 = 22x4)
190 2.0: sizeof(struct ip_fw) (~25x4)
192 We can't include both 2.0 and 2.2 headers, they conflict.
193 Hence, 200 is a good number. --RR */
195 if (!capable(CAP_NET_ADMIN))
198 if (len > sizeof(tmp_fw) || len < 1)
201 if (copy_from_user(&tmp_fw, user, len))
204 return -ip_fw_ctl(optval, &tmp_fw, len);
207 static struct nf_hook_ops preroute_ops = {
209 .owner = THIS_MODULE,
211 .hooknum = NF_IP_PRE_ROUTING,
212 .priority = NF_IP_PRI_FILTER,
215 static struct nf_hook_ops postroute_ops = {
217 .owner = THIS_MODULE,
219 .hooknum = NF_IP_POST_ROUTING,
220 .priority = NF_IP_PRI_FILTER,
223 static struct nf_hook_ops forward_ops = {
225 .owner = THIS_MODULE,
227 .hooknum = NF_IP_FORWARD,
228 .priority = NF_IP_PRI_FILTER,
231 static struct nf_hook_ops local_in_ops = {
233 .owner = THIS_MODULE,
235 .hooknum = NF_IP_LOCAL_IN,
236 .priority = NF_IP_PRI_LAST - 1,
239 static struct nf_sockopt_ops sock_ops = {
242 .set_optmax = 64 + 1024 + 1,
246 extern int ipfw_init_or_cleanup(int init);
248 static int init_or_cleanup(int init)
252 if (!init) goto cleanup;
254 ret = nf_register_sockopt(&sock_ops);
257 goto cleanup_nothing;
259 ret = ipfw_init_or_cleanup(1);
261 goto cleanup_sockopt;
267 nf_register_hook(&preroute_ops);
268 nf_register_hook(&postroute_ops);
269 nf_register_hook(&forward_ops);
270 nf_register_hook(&local_in_ops);
275 nf_unregister_hook(&preroute_ops);
276 nf_unregister_hook(&postroute_ops);
277 nf_unregister_hook(&forward_ops);
278 nf_unregister_hook(&local_in_ops);
283 ipfw_init_or_cleanup(0);
286 nf_unregister_sockopt(&sock_ops);
292 static int __init init(void)
294 return init_or_cleanup(1);
297 static void __exit fini(void)