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