NETFILTER: remove unnecessary goto statement for error recovery
[tomato.git] / release / src-rt / linux / linux-2.6 / net / ipv4 / netfilter / dnsmq.c
blob52bb8e0bc053770b7b1dcb3abb116fb69870347b
1 /*
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
9 * a table
11 #include <linux/config.h>
12 #include <linux/cache.h>
13 #include <linux/skbuff.h>
14 #include <linux/kmod.h>
15 #include <linux/vmalloc.h>
16 #include <linux/netdevice.h>
17 #include <linux/module.h>
18 #include <linux/ip.h>
19 #include <linux/tcp.h>
20 #include <linux/udp.h>
21 #include <linux/in.h>
22 #include <linux/if_vlan.h>
23 #include <net/route.h>
24 #include <net/ip.h>
25 #include <linux/netfilter.h>
26 #include <linux/netfilter_ipv4.h>
27 #include <net/netfilter/nf_nat_core.h>
28 #include <net/netfilter/nf_conntrack.h>
29 #include <net/netfilter/nf_conntrack_core.h>
30 #include <linux/netfilter/nf_conntrack_common.h>
31 #include <linux/netfilter_ipv4/ip_tables.h>
32 #include <linux/proc_fs.h>
33 #include <bcmnvram.h>
35 #define DEBUGP(format, args...)
37 unsigned int dnsmq_ip=0;
38 char dnsmq_name[32];
39 unsigned char dnsmq_mac[ETH_ALEN] = { 0x00, 0xe0, 0x11, 0x22, 0x33, 0x44 };
40 typedef int (*dnsmqHitHook)(struct sk_buff *skb);
41 dnsmqHitHook dnsmq_hit_hook = NULL;
43 static inline void dnsmq_hit_hook_func(dnsmqHitHook hook_func)
45 dnsmq_hit_hook = hook_func;
48 void dump_packet(struct sk_buff *skb, char *title)
50 int i;
52 if(nvram_match("dnsmq_debug", "1")) {
53 printk("dump packet[%s] %x %x %x", title, skb->len, skb->mac_len, skb->data_len);
54 if(skb->dev) printk("%s\n", skb->dev->name);
55 else printk("\n");
57 if(skb && skb->data) {
58 for(i=0;i<skb->len&&i<120;i++) {
59 if(i%16==0) printk("\n");
60 printk("%x ", skb->data[i]);
63 printk("\n\n\n");
67 EXPORT_SYMBOL(dump_packet);
69 #define MAXDNSNAME 256
70 #pragma pack(1) // let struct be neat by byte
72 typedef struct Flags_Pack {
73 uint16_t reply_1:4,
74 non_auth_ok:1,
75 answer_auth:1,
76 reserved:1,
77 recur_avail:1,
78 recur_desired:1,
79 truncated:1,
80 authori:1,
81 opcode:4,
82 response:1;
83 } flag_pack;
85 typedef struct DNS_HEADER {
86 uint16_t tid;
87 union {
88 uint16_t flag_num;
89 flag_pack flags;
90 } flag_set;
91 uint16_t questions;
92 uint16_t answer_rrs;
93 uint16_t auth_rrs;
94 uint16_t additional_rss;
95 } dns_header;
97 typedef struct DNS_QUERIES {
98 char name[MAXDNSNAME];
99 uint16_t type;
100 uint16_t ip_class;
101 } dns_queries;
103 typedef struct DNS_REQUEST {
104 dns_header header;
105 dns_queries queries;
106 } dns_query_packet;
108 static inline int dnschar_cmp(char a, char b)
110 char a1;
112 if(a==b) return 0;
114 if(a>='a'&&a<='z') a1 = 'A' + a - 'a';
115 else if(a>='A'&&a<='Z') a1 = 'a' + a - 'A';
116 else return 1;
118 if(a1==b) return 0;
120 return 1;
123 static inline int dnsmq_hit(struct udphdr *udph)
125 dns_query_packet *dns_query;
126 int i, j;
128 dns_query = (dns_query_packet *)((unsigned char *)udph + sizeof(struct udphdr));
130 j = 0;
131 //printk("dns hit\n");
132 for(i=0;dns_query->queries.name[i]!=0;i++) {
133 //printk("%x %x %x\n", i, dns_query->queries.name[i], dnsmq_name[i]);
134 if(dnschar_cmp(dns_query->queries.name[i],dnsmq_name[j])) return 0;
135 j++;
137 return 1;
140 static inline int dnsmq_func(struct sk_buff *skb)
142 struct ethhdr *ethh;
143 struct vlan_ethhdr *vethh;
144 struct iphdr *iph;
145 struct udphdr *udph;
146 struct tcphdr *tcph;
147 u32 hlen;
148 u16 proto;
150 if(dnsmq_ip==0) return 0;
152 if(!skb || !skb->data) return 0;
154 ethh = (struct ethhdr *)skb->data;
156 proto = ntohs(ethh->h_proto);
158 if(proto == ETH_P_IP) hlen = ETH_HLEN;
159 else if (proto == ETH_P_8021Q) {
160 vethh = (struct vlan_ethhdr *)skb->data;
161 if(vethh->h_vlan_encapsulated_proto == htons(ETH_P_IP))
162 hlen = VLAN_ETH_HLEN;
163 else return 0;
165 else return 0;
167 iph = (struct iphdr *)(skb->data+hlen);
169 // IP & DNS & Looking for my host name
170 if(iph->protocol==IPPROTO_UDP) {
171 udph = (struct udphdr *)(skb->data+hlen+(iph->ihl<<2));
172 if(ntohs(udph->dest)==53) {
173 if(dnsmq_hit(udph)) {
174 memcpy(ethh->h_dest, dnsmq_mac, ETH_ALEN);
175 //dump_packet(skb, "dnshit");
176 return 1;
180 // IP & HTTP & Original Locol IP & Looking for my host name
181 else if(iph->protocol==IPPROTO_TCP) {
182 tcph = (struct tcphdr *)(skb->data+hlen+(iph->ihl<<2));
183 if(iph->daddr==dnsmq_ip && ntohs(tcph->dest)==80) {
184 memcpy(ethh->h_dest, dnsmq_mac, ETH_ALEN);
185 //dump_packet(skb, "httphit");
186 return 1;
189 return 0;
192 static int dnsmq_ctrl(struct file *file, const char *buffer, unsigned long length, void *data)
194 char s[32];
195 char str[32];
196 char *ptr;
197 int i, j;
199 // "[dnsmq ip] [dnsmq name]
200 if ((length > 0) && (length < 32)) {
201 memcpy(s, buffer, length);
202 s[length] = 0;
203 for(i=0;i<length;i++) {
204 if(s[i]==' ') break;
206 if(i<length) {
207 s[i] = 0;
208 ptr = s + i + 1;
209 dnsmq_ip = simple_strtoul(s, NULL, 16);
211 // convert to dnsname format
212 j=0;
213 for(;i<length;i++) {
214 if(s[i]=='.') {
215 s[i]=0;
216 dnsmq_name[j]=strlen(ptr);
217 memcpy(dnsmq_name+j+1, ptr, strlen(ptr));
218 j += strlen(ptr) + 1;
219 ptr = s + i + 1;
222 dnsmq_name[j]=strlen(ptr);
223 memcpy(dnsmq_name+j+1, ptr, strlen(ptr));
224 dnsmq_name[j+1+strlen(ptr)]=0;
227 else dnsmq_ip=0;
229 printk("dnsmq ctrl: %x %s\n", dnsmq_ip, dnsmq_name);
231 if(dnsmq_ip==0) dnsmq_hit_hook_func (NULL);
232 else dnsmq_hit_hook_func(dnsmq_func);
234 return length;
237 static int __init init(void)
239 #ifdef CONFIG_PROC_FS
240 struct proc_dir_entry *p;
242 p = create_proc_entry("dnsmqctrl", 0200, proc_net);
244 if(p) {
245 p->owner = THIS_MODULE;
246 p->write_proc = dnsmq_ctrl;
248 #endif
249 // it will be enabled later
250 dnsmq_hit_hook_func (NULL);
251 return 0;
254 static void __exit fini(void)
256 dnsmq_hit_hook_func (NULL);
259 EXPORT_SYMBOL(dnsmq_hit_hook);
261 module_init(init);
262 module_exit(fini);
263 MODULE_LICENSE("Proprietary");