patch-2.3.99-pre2 linux/net/ipv4/netfilter/ip_fw_compat.c
Next file: linux/net/ipv4/netfilter/ip_fw_compat_masq.c
Previous file: linux/net/ipv4/netfilter/ip_conntrack_standalone.c
Back to the patch index
Back to the overall index
- Lines: 239
- Date:
Sat Mar 18 16:51:35 2000
- Orig file:
v2.3.99-pre1/linux/net/ipv4/netfilter/ip_fw_compat.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.99-pre1/linux/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c
@@ -0,0 +1,238 @@
+/* Compatibility framework for ipchains and ipfwadm support; designed
+ to look as much like the 2.2 infrastructure as possible. */
+struct notifier_block;
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/ip.h>
+#include <net/icmp.h>
+#include <linux/if.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <linux/netfilter_ipv4/compat_firewall.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+
+EXPORT_NO_SYMBOLS;
+
+static struct firewall_ops *fwops;
+
+/* From ip_fw_compat_redir.c */
+extern unsigned int
+do_redirect(struct sk_buff *skb,
+ const struct net_device *dev,
+ u_int16_t redirpt);
+
+extern void
+check_for_redirect(struct sk_buff *skb);
+
+extern void
+check_for_unredirect(struct sk_buff *skb);
+
+/* From ip_fw_compat_masq.c */
+extern unsigned int
+do_masquerade(struct sk_buff **pskb, const struct net_device *dev);
+
+extern unsigned int
+check_for_demasq(struct sk_buff **pskb);
+
+extern int __init masq_init(void);
+extern void masq_cleanup(void);
+
+/* They call these; we do what they want. */
+int register_firewall(int pf, struct firewall_ops *fw)
+{
+ if (pf != PF_INET) {
+ printk("Attempt to register non-IP firewall module.\n");
+ return -EINVAL;
+ }
+ if (fwops) {
+ printk("Attempt to register multiple firewall modules.\n");
+ return -EBUSY;
+ }
+
+ fwops = fw;
+ return 0;
+}
+
+int unregister_firewall(int pf, struct firewall_ops *fw)
+{
+ fwops = NULL;
+ return 0;
+}
+
+static unsigned int
+fw_in(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ int ret = FW_BLOCK;
+ u_int16_t redirpt;
+
+ (*pskb)->nfcache |= NFC_UNKNOWN;
+ (*pskb)->ip_summed = CHECKSUM_NONE;
+
+ switch (hooknum) {
+ case NF_IP_PRE_ROUTING:
+ if (fwops->fw_acct_in)
+ fwops->fw_acct_in(fwops, PF_INET,
+ (struct net_device *)in,
+ (*pskb)->nh.raw, &redirpt, pskb);
+
+ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+ *pskb = ip_ct_gather_frags(*pskb);
+
+ if (!*pskb)
+ return NF_STOLEN;
+ }
+
+ ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in,
+ (*pskb)->nh.raw, &redirpt, pskb);
+ break;
+
+ case NF_IP_FORWARD:
+ /* Connection will only be set if it was
+ demasqueraded: if so, skip forward chain. */
+ if ((*pskb)->nfct)
+ ret = FW_ACCEPT;
+ else ret = fwops->fw_forward(fwops, PF_INET,
+ (struct net_device *)out,
+ (*pskb)->nh.raw, &redirpt, pskb);
+ break;
+
+ case NF_IP_POST_ROUTING:
+ ret = fwops->fw_output(fwops, PF_INET,
+ (struct net_device *)out,
+ (*pskb)->nh.raw, &redirpt, pskb);
+ if (fwops->fw_acct_out && (ret == FW_ACCEPT || ret == FW_SKIP))
+ fwops->fw_acct_out(fwops, PF_INET,
+ (struct net_device *)in,
+ (*pskb)->nh.raw, &redirpt, pskb);
+ break;
+ }
+
+ switch (ret) {
+ case FW_REJECT: {
+ /* Alexey says:
+ *
+ * Generally, routing is THE FIRST thing to make, when
+ * packet enters IP stack. Before packet is routed you
+ * cannot call any service routines from IP stack. */
+ struct iphdr *iph = (*pskb)->nh.iph;
+
+ if ((*pskb)->dst != NULL
+ || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos,
+ (struct net_device *)in) == 0)
+ icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
+ 0);
+ return NF_DROP;
+ }
+
+ case FW_ACCEPT:
+ case FW_SKIP:
+ if (hooknum == NF_IP_PRE_ROUTING) {
+ check_for_demasq(pskb);
+ check_for_redirect(*pskb);
+ } else if (hooknum == NF_IP_POST_ROUTING)
+ check_for_unredirect(*pskb);
+
+ return NF_ACCEPT;
+
+ case FW_MASQUERADE:
+ if (hooknum == NF_IP_FORWARD)
+ return do_masquerade(pskb, out);
+ else return NF_ACCEPT;
+
+ case FW_REDIRECT:
+ if (hooknum == NF_IP_PRE_ROUTING)
+ return do_redirect(*pskb, in, redirpt);
+ else return NF_ACCEPT;
+
+ default:
+ /* FW_BLOCK */
+ return NF_DROP;
+ }
+}
+
+extern int ip_fw_ctl(int optval, void *user, unsigned int len);
+
+static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len)
+{
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ return -ip_fw_ctl(optval, user, len);
+}
+
+static struct nf_hook_ops preroute_ops
+= { { NULL, NULL }, fw_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER };
+
+static struct nf_hook_ops postroute_ops
+= { { NULL, NULL }, fw_in, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FILTER };
+
+static struct nf_hook_ops forward_ops
+= { { NULL, NULL }, fw_in, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER };
+
+static struct nf_sockopt_ops sock_ops
+= { { NULL, NULL }, PF_INET, 64, 64 + 1024 + 1, &sock_fn, 0, 0, NULL,
+ 0, NULL };
+
+extern int ipfw_init_or_cleanup(int init);
+
+static int init_or_cleanup(int init)
+{
+ int ret = 0;
+
+ if (!init) goto cleanup;
+
+ ret = nf_register_sockopt(&sock_ops);
+
+ if (ret < 0)
+ goto cleanup_nothing;
+
+ ret = ipfw_init_or_cleanup(1);
+ if (ret < 0)
+ goto cleanup_sockopt;
+
+ ret = masq_init();
+ if (ret < 0)
+ goto cleanup_ipfw;
+
+ nf_register_hook(&preroute_ops);
+ nf_register_hook(&postroute_ops);
+ nf_register_hook(&forward_ops);
+
+ return ret;
+
+ cleanup:
+ nf_unregister_hook(&preroute_ops);
+ nf_unregister_hook(&postroute_ops);
+ nf_unregister_hook(&forward_ops);
+
+ masq_cleanup();
+
+ cleanup_ipfw:
+ ipfw_init_or_cleanup(0);
+
+ cleanup_sockopt:
+ nf_unregister_sockopt(&sock_ops);
+
+ cleanup_nothing:
+ return ret;
+}
+
+static int __init init(void)
+{
+ return init_or_cleanup(1);
+}
+
+static void __exit fini(void)
+{
+ init_or_cleanup(0);
+}
+
+module_init(init);
+module_exit(fini);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)