• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/ipv4/netfilter/
1/*
2 * Packet matching code.
3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
6 *
7 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
8 * 	- increase module usage count as soon as we have rules inside
9 * 	  a table
10 */
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>
17#include <linux/ip.h>
18#include <linux/tcp.h>
19#include <net/route.h>
20#include <net/ip.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>
29
30#define LFP_DEBUG 0
31
32#if LFP_DEBUG
33#define DEBUGP(format, args...) printk(KERN_DEBUG format, ##args)
34#else
35#define DEBUGP(format, args...)
36#endif
37
38unsigned int  lfp_ip=0;
39
40struct lfp_port_s {
41	unsigned int port;
42};
43
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)
47static struct lfp_port_s lfp_ports[NR_ALL_LFP_PORTS] = {
48	[0] = { 445 },
49	[1] = {  20 },
50};
51static int next_slot = NR_STATIC_LFP_PORTS;
52
53typedef int (*lfpHitHook)(int pf, unsigned int hook, struct sk_buff *skb);
54lfpHitHook lfp_hit_hook = NULL;
55
56static inline int lfp_hit_hook_func(lfpHitHook hook_func)
57{
58	lfp_hit_hook = hook_func;
59	return 0;
60}
61
62static inline int lfp_func(int pf, unsigned int hook, struct sk_buff *skb)
63{
64	int i, ret = 0;
65	struct iphdr *iph;
66	struct tcphdr *tcph;
67	struct lfp_port_s *p;
68	__u32 ipaddr=0, r_ipaddr=0;
69	__u16 port=0;
70
71	if(lfp_ip == 0 || pf != AF_INET) return 0;
72	if(skb->nfcache & NFC_LFP_ENABLE) return 1;
73
74	iph = ip_hdr(skb);
75	if (unlikely(iph->protocol != IPPROTO_TCP))
76		return 0;
77
78	if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_LOCAL_IN) {
79		tcph = (struct tcphdr *)(skb->data+(iph->ihl<<2));
80
81		ipaddr = iph->daddr;
82		r_ipaddr = iph->saddr;
83		port = ntohs(tcph->dest);
84	} else if (hook == NF_INET_LOCAL_OUT || hook == NF_INET_POST_ROUTING) {
85		tcph = (struct tcphdr *)(skb->data+(iph->ihl<<2));
86
87		ipaddr = iph->saddr;
88		r_ipaddr = iph->daddr;
89		port = ntohs(tcph->source);
90	}
91
92	if (likely(ipaddr != lfp_ip || !ipaddr))
93		return 0;
94
95	DEBUGP("ip match: %x %x %x %x\n", hook, ipaddr, r_ipaddr, lfp_ip);
96	for (i = 0, p = &lfp_ports[0]; i < NR_ALL_LFP_PORTS; ++i, ++p) {
97		if (!p->port)
98			continue;
99
100		if (port == p->port) {
101			skb->nfcache |= NFC_LFP_ENABLE;
102			ret = 1;
103			break;
104		}
105	}
106
107	return ret;
108}
109
110#ifdef CONFIG_PROC_FS
111static int lfp_ctrl(struct file *file, const char *buffer, unsigned long length, void *data)
112{
113	char s[10];
114
115	if ((length > 0) && (length < 10)) {
116		memcpy(s, buffer, length);
117		s[length] = 0;
118		lfp_ip = simple_strtoul(s, NULL, 16);
119	}
120	else lfp_ip=0;
121
122	if(lfp_ip==0) lfp_hit_hook_func (NULL);
123	else lfp_hit_hook_func(lfp_func);
124
125	return length;
126}
127
128static int lfp_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
129{
130	sprintf(page, "%x,%p,%d\n", lfp_ip, lfp_hit_hook, LFP_DEBUG);
131	*eof = 1;
132        return strlen(page);
133}
134
135/* Add port to LFP ports list
136 * @return:
137 *  0:		Add port to empty slot success.
138 *  1:		Override port to an exist port.
139 *  2:		Same port exist
140 *  -1:		Invalid port number.
141 */
142int lfp_add_port(unsigned int port)
143{
144	int i, ret = 0;
145	struct lfp_port_s *p;
146
147	if (!port || port > 65535)
148		return -1;
149
150	for (i = 0, p = &lfp_ports[0]; i < NR_ALL_LFP_PORTS; ++i, ++p) {
151		if (!p->port || p->port != port)
152			continue;
153
154		return 2;
155	}
156
157	/* find empty slot */
158	for (i = 0, p = &lfp_ports[NR_STATIC_LFP_PORTS]; i < NR_DYNAMIC_LFP_PORTS; ++i, ++p) {
159		if (p->port)
160			continue;
161
162		p->port = port;
163		DEBUGP("Add port %d to LFP port list\n", port);
164		return 0;
165	}
166
167	if (next_slot < NR_STATIC_LFP_PORTS || next_slot >= NR_ALL_LFP_PORTS)
168		next_slot = NR_STATIC_LFP_PORTS;
169
170	p = &lfp_ports[next_slot];
171	if (p->port) {
172		DEBUGP("Override port %d with %d\n", p->port, port);
173		ret = 1;
174	}
175	p->port = port;
176	next_slot++;
177
178	return ret;
179}
180
181/* Remove port from dynamic LFP ports list.
182 * @return:
183 *  0:		Remove port success.
184 *  1:		Port not found.
185 *  -1:		Invalid port number.
186 */
187int lfp_del_port(unsigned int port)
188{
189	int i;
190	struct lfp_port_s *p;
191
192	if (!port || port > 65535)
193		return -1;
194
195	for (i = 0, p = &lfp_ports[NR_STATIC_LFP_PORTS]; i < NR_DYNAMIC_LFP_PORTS; ++i, ++p) {
196		if (!p->port || p->port != port)
197			continue;
198
199		p->port = 0;
200		DEBUGP("Remove port %d from LFP port list\n", port);
201		return 0;
202	}
203
204	return 1;
205}
206
207/* Query port in LFP ports list
208 * @return:
209 *  0:		Not found
210 *  1:		found
211 *  -1:		Invalid port number.
212 */
213int lfp_query_port(unsigned int port)
214{
215	int i;
216	struct lfp_port_s *p;
217
218	if (!port || port > 65535)
219		return -1;
220
221	for (i = 0, p = &lfp_ports[NR_STATIC_LFP_PORTS]; i < NR_DYNAMIC_LFP_PORTS; ++i, ++p) {
222		if (port != p->port)
223			continue;
224
225		DEBUGP("Port %d found in LFP port list\n", port);
226		return 1;
227	}
228
229	return 0;
230}
231
232static int lfp_port_write_proc(struct file *file, const char *buffer, unsigned long length, void *data)
233{
234	unsigned int port = 0;
235
236	port = simple_strtoul(buffer, NULL, 10);
237	lfp_add_port(port);
238
239	return length;
240}
241
242static int lfp_port_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
243{
244	int i, len = 0, c = 0;
245	struct lfp_port_s *p;
246
247	if (next_slot < NR_STATIC_LFP_PORTS || next_slot >= NR_ALL_LFP_PORTS)
248		next_slot = NR_STATIC_LFP_PORTS;
249
250	for (i = 0, p = &lfp_ports[NR_STATIC_LFP_PORTS]; !c && i < NR_DYNAMIC_LFP_PORTS; ++i, ++p) {
251		if (!p->port)
252			c++;
253	}
254
255	for (i = NR_STATIC_LFP_PORTS, p = &lfp_ports[NR_STATIC_LFP_PORTS]; i < NR_ALL_LFP_PORTS; ++i, ++p) {
256		if (!p->port)
257			continue;
258
259		len += sprintf(page + len, "%d%c\n", p->port, (c || i != next_slot)?' ':'*');
260	}
261
262	*eof = 1;
263        return len;
264}
265#endif	/* CONFIG_PROC_FS */
266
267static int __init init(void)
268{
269#ifdef CONFIG_PROC_FS
270	struct proc_dir_entry *p;
271
272	p = create_proc_entry("lfpctrl", 0600, init_net.proc_net);
273
274	if (p) {
275		p->read_proc = lfp_read_proc;
276		p->write_proc = lfp_ctrl;
277	}
278
279	p = create_proc_entry("lfp_ports_ctrl", 0600, init_net.proc_net);
280	if (p) {
281		p->read_proc = lfp_port_read_proc;
282		p->write_proc = lfp_port_write_proc;
283	}
284#endif
285	// it will be enabled later
286	lfp_hit_hook_func (NULL);
287	return 0;
288}
289
290static void __exit fini(void)
291{
292	lfp_hit_hook_func (NULL);
293
294#ifdef CONFIG_PROC_FS
295	remove_proc_entry("lfp_ports_ctrl", init_net.proc_net);
296	remove_proc_entry("lfpctrl", init_net.proc_net);
297#endif
298}
299
300module_init(init);
301module_exit(fini);
302MODULE_LICENSE("Proprietary");
303