2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
7 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
8 * - increase module usage count as soon as we have rules inside
11 #include <linux/cache.h>
12 #include <linux/skbuff.h>
13 #include <linux/kmod.h>
14 #include <linux/vmalloc.h>
15 #include <linux/netdevice.h>
16 #include <linux/module.h>
18 #include <linux/tcp.h>
19 #include <net/route.h>
21 #include <linux/netfilter.h>
22 #include <linux/netfilter_ipv4.h>
23 #include <net/netfilter/nf_nat_core.h>
24 #include <net/netfilter/nf_conntrack.h>
25 #include <net/netfilter/nf_conntrack_core.h>
26 #include <linux/netfilter/nf_conntrack_common.h>
27 #include <linux/netfilter_ipv4/ip_tables.h>
28 #include <linux/proc_fs.h>
33 #define DEBUGP(format, args...) printk(KERN_DEBUG format, ##args)
35 #define DEBUGP(format, args...)
38 unsigned int lfp_ip
=0;
44 #define NR_STATIC_LFP_PORTS 2
45 #define NR_DYNAMIC_LFP_PORTS 5
46 #define NR_ALL_LFP_PORTS (NR_STATIC_LFP_PORTS + NR_DYNAMIC_LFP_PORTS)
47 static struct lfp_port_s lfp_ports
[NR_ALL_LFP_PORTS
] = {
51 static int next_slot
= NR_STATIC_LFP_PORTS
;
53 #define NFC_LFP_ENABLE (1<<29)
55 typedef int (*lfpHitHook
)(int pf
, unsigned int hook
, struct sk_buff
*skb
);
56 lfpHitHook lfp_hit_hook
= NULL
;
58 static inline int lfp_hit_hook_func(lfpHitHook hook_func
)
60 lfp_hit_hook
= hook_func
;
64 static inline int lfp_func(int pf
, unsigned int hook
, struct sk_buff
*skb
)
70 __u32 ipaddr
=0, r_ipaddr
=0;
73 if(lfp_ip
== 0 || pf
!= AF_INET
) return 0;
74 if(skb
->nfcache
& NFC_LFP_ENABLE
) return 1;
77 if (unlikely(iph
->protocol
!= IPPROTO_TCP
))
80 if (hook
== NF_INET_PRE_ROUTING
|| hook
== NF_INET_LOCAL_IN
) {
81 tcph
= (struct tcphdr
*)(skb
->data
+(iph
->ihl
<<2));
84 r_ipaddr
= iph
->saddr
;
85 port
= ntohs(tcph
->dest
);
86 } else if (hook
== NF_INET_LOCAL_OUT
|| hook
== NF_INET_POST_ROUTING
) {
87 tcph
= (struct tcphdr
*)(skb
->data
+(iph
->ihl
<<2));
90 r_ipaddr
= iph
->daddr
;
91 port
= ntohs(tcph
->source
);
94 if (likely(ipaddr
!= lfp_ip
|| !ipaddr
))
97 DEBUGP("ip match: %x %x %x %x\n", hook
, ipaddr
, r_ipaddr
, lfp_ip
);
98 for (i
= 0, p
= &lfp_ports
[0]; i
< NR_ALL_LFP_PORTS
; ++i
, ++p
) {
102 if (port
== p
->port
) {
103 skb
->nfcache
|= NFC_LFP_ENABLE
;
112 #ifdef CONFIG_PROC_FS
113 static int lfp_ctrl(struct file
*file
, const char *buffer
, unsigned long length
, void *data
)
117 if ((length
> 0) && (length
< 10)) {
118 memcpy(s
, buffer
, length
);
120 lfp_ip
= simple_strtoul(s
, NULL
, 16);
124 if(lfp_ip
==0) lfp_hit_hook_func (NULL
);
125 else lfp_hit_hook_func(lfp_func
);
130 static int lfp_read_proc(char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
)
132 sprintf(page
, "%x,%p,%d\n", lfp_ip
, lfp_hit_hook
, LFP_DEBUG
);
137 /* Add port to LFP ports list
139 * 0: Add port to empty slot success.
140 * 1: Override port to an exist port.
142 * -1: Invalid port number.
144 int lfp_add_port(unsigned int port
)
147 struct lfp_port_s
*p
;
149 if (!port
|| port
> 65535)
152 for (i
= 0, p
= &lfp_ports
[0]; i
< NR_ALL_LFP_PORTS
; ++i
, ++p
) {
153 if (!p
->port
|| p
->port
!= port
)
159 /* find empty slot */
160 for (i
= 0, p
= &lfp_ports
[NR_STATIC_LFP_PORTS
]; i
< NR_DYNAMIC_LFP_PORTS
; ++i
, ++p
) {
165 DEBUGP("Add port %d to LFP port list\n", port
);
169 if (next_slot
< NR_STATIC_LFP_PORTS
|| next_slot
>= NR_ALL_LFP_PORTS
)
170 next_slot
= NR_STATIC_LFP_PORTS
;
172 p
= &lfp_ports
[next_slot
];
174 DEBUGP("Override port %d with %d\n", p
->port
, port
);
183 /* Remove port from dynamic LFP ports list.
185 * 0: Remove port success.
187 * -1: Invalid port number.
189 int lfp_del_port(unsigned int port
)
192 struct lfp_port_s
*p
;
194 if (!port
|| port
> 65535)
197 for (i
= 0, p
= &lfp_ports
[NR_STATIC_LFP_PORTS
]; i
< NR_DYNAMIC_LFP_PORTS
; ++i
, ++p
) {
198 if (!p
->port
|| p
->port
!= port
)
202 DEBUGP("Remove port %d from LFP port list\n", port
);
209 /* Query port in LFP ports list
213 * -1: Invalid port number.
215 int lfp_query_port(unsigned int port
)
218 struct lfp_port_s
*p
;
220 if (!port
|| port
> 65535)
223 for (i
= 0, p
= &lfp_ports
[NR_STATIC_LFP_PORTS
]; i
< NR_DYNAMIC_LFP_PORTS
; ++i
, ++p
) {
227 DEBUGP("Port %d found in LFP port list\n", port
);
234 static int lfp_port_write_proc(struct file
*file
, const char *buffer
, unsigned long length
, void *data
)
236 unsigned int port
= 0;
238 port
= simple_strtoul(buffer
, NULL
, 10);
244 static int lfp_port_read_proc(char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
)
246 int i
, len
= 0, c
= 0;
247 struct lfp_port_s
*p
;
249 if (next_slot
< NR_STATIC_LFP_PORTS
|| next_slot
>= NR_ALL_LFP_PORTS
)
250 next_slot
= NR_STATIC_LFP_PORTS
;
252 for (i
= 0, p
= &lfp_ports
[NR_STATIC_LFP_PORTS
]; !c
&& i
< NR_DYNAMIC_LFP_PORTS
; ++i
, ++p
) {
257 for (i
= NR_STATIC_LFP_PORTS
, p
= &lfp_ports
[NR_STATIC_LFP_PORTS
]; i
< NR_ALL_LFP_PORTS
; ++i
, ++p
) {
261 len
+= sprintf(page
+ len
, "%d%c\n", p
->port
, (c
|| i
!= next_slot
)?' ':'*');
267 #endif /* CONFIG_PROC_FS */
269 static int __init
init(void)
271 #ifdef CONFIG_PROC_FS
272 struct proc_dir_entry
*p
;
274 p
= create_proc_entry("lfpctrl", 0600, init_net
.proc_net
);
277 p
->read_proc
= lfp_read_proc
;
278 p
->write_proc
= lfp_ctrl
;
281 p
= create_proc_entry("lfp_ports_ctrl", 0600, init_net
.proc_net
);
283 p
->read_proc
= lfp_port_read_proc
;
284 p
->write_proc
= lfp_port_write_proc
;
287 // it will be enabled later
288 lfp_hit_hook_func (NULL
);
292 static void __exit
fini(void)
294 lfp_hit_hook_func (NULL
);
296 #ifdef CONFIG_PROC_FS
297 remove_proc_entry("lfp_ports_ctrl", init_net
.proc_net
);
298 remove_proc_entry("lfpctrl", init_net
.proc_net
);
304 MODULE_LICENSE("Proprietary");