1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/module.h>
25#include <asm/system.h>
26#include <linux/types.h>
27#include <linux/kernel.h>
28#include <linux/skbuff.h>
29#include <linux/in.h>
30#include <linux/ip.h>
31#include <linux/init.h>
32#include <net/protocol.h>
33#include <net/udp.h>
34#include <net/ip_masq.h>
35
36#define DEBUG_CONFIG_IP_MASQ_QUAKE 0
37
38typedef struct
39{
40 __u16 type;
41 __u16 length;
42 char message[0];
43} QUAKEHEADER;
44
45struct quake_priv_data {
46
47 char cl_connect;
48};
49
50static int
51masq_quake_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
52{
53 MOD_INC_USE_COUNT;
54 if ((ms->app_data = kmalloc(sizeof(struct quake_priv_data),
55 GFP_ATOMIC)) == NULL)
56 printk(KERN_INFO "Quake: No memory for application data\n");
57 else
58 {
59 struct quake_priv_data *priv =
60 (struct quake_priv_data *)ms->app_data;
61 priv->cl_connect = 0;
62 }
63 return 0;
64}
65
66static int
67masq_quake_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
68{
69 MOD_DEC_USE_COUNT;
70 if (ms->app_data)
71 kfree_s(ms->app_data, sizeof(struct quake_priv_data));
72 return 0;
73}
74
75int
76masq_quake_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
77{
78 struct sk_buff *skb;
79 struct iphdr *iph;
80 struct udphdr *uh;
81 QUAKEHEADER *qh;
82 __u16 udp_port;
83 char *data;
84 unsigned char code;
85 struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
86
87 if(priv->cl_connect == -1)
88 return 0;
89
90 skb = *skb_p;
91
92 iph = skb->nh.iph;
93 uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
94
95
96 if(ntohs(uh->len) < 5)
97 return 0;
98
99 qh = (QUAKEHEADER *)&uh[1];
100
101 if(qh->type != 0x0080)
102 return 0;
103
104
105 code = qh->message[0];
106
107#if DEBUG_CONFIG_IP_MASQ_QUAKE
108 printk("Quake_in: code = %d \n", (int)code);
109#endif
110
111 switch(code) {
112 case 0x01:
113
114
115 if(ntohs(qh->length) < 0x0c) {
116#if DEBUG_CONFIG_IP_MASQ_QUAKE
117 printk("Quake_in: length < 0xc \n");
118#endif
119 return 0;
120 }
121
122 data = &qh->message[1];
123
124
125 if(memcmp(data,"QUAKE\0\3",7)) {
126#if DEBUG_CONFIG_IP_MASQ_QUAKE
127 printk("Quake_out: memcmp failed \n");
128#endif
129 return 0;
130 }
131 else {
132 priv->cl_connect = 1;
133#if DEBUG_CONFIG_IP_MASQ_QUAKE
134 printk("Quake_out: memcmp ok \n");
135#endif
136 }
137 break;
138
139 case 0x81:
140
141 if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
142 return 0;
143 data = &qh->message[1];
144
145 memcpy(&udp_port, data, 2);
146
147 ms->dport = htons(udp_port);
148
149#if DEBUG_CONFIG_IP_MASQ_QUAKE
150 printk("Quake_in: in_rewrote UDP port %d \n", udp_port);
151#endif
152 priv->cl_connect = -1;
153
154 break;
155 }
156
157 return 0;
158}
159
160int
161masq_quake_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
162{
163 struct sk_buff *skb;
164 struct iphdr *iph;
165 struct udphdr *uh;
166 QUAKEHEADER *qh;
167 __u16 udp_port;
168 char *data;
169 unsigned char code;
170 struct ip_masq *n_ms;
171 struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
172
173 if(priv->cl_connect == -1)
174 return 0;
175
176 skb = *skb_p;
177
178 iph = skb->nh.iph;
179 uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
180
181
182 if(ntohs(uh->len) < 5)
183 return 0;
184
185 qh = (QUAKEHEADER *)&uh[1];
186
187#if DEBUG_CONFIG_IP_MASQ_QUAKE
188 printk("Quake_out: qh->type = %d \n", (int)qh->type);
189#endif
190
191 if(qh->type != 0x0080)
192 return 0;
193
194 code = qh->message[0];
195
196#if DEBUG_CONFIG_IP_MASQ_QUAKE
197 printk("Quake_out: code = %d \n", (int)code);
198#endif
199
200 switch(code) {
201 case 0x01:
202
203
204 if(ntohs(qh->length) < 0x0c) {
205#if DEBUG_CONFIG_IP_MASQ_QUAKE
206 printk("Quake_out: length < 0xc \n");
207#endif
208 return 0;
209 }
210
211 data = &qh->message[1];
212
213
214 if(memcmp(data,"QUAKE\0\3",7)) {
215#if DEBUG_CONFIG_IP_MASQ_QUAKE
216 printk("Quake_out: memcmp failed \n");
217#endif
218 return 0;
219 }
220 else {
221 priv->cl_connect = 1;
222#if DEBUG_CONFIG_IP_MASQ_QUAKE
223 printk("Quake_out: memcmp ok \n");
224#endif
225 }
226 break;
227
228 case 0x81:
229
230 if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
231 return 0;
232
233 data = &qh->message[1];
234
235 memcpy(&udp_port, data, 2);
236
237 n_ms = ip_masq_new(IPPROTO_UDP,
238 maddr, 0,
239 ms->saddr, htons(udp_port),
240 ms->daddr, ms->dport,
241 0);
242
243 if (n_ms==NULL)
244 return 0;
245
246#if DEBUG_CONFIG_IP_MASQ_QUAKE
247 printk("Quake_out: out_rewrote UDP port %d -> %d\n",
248 udp_port, ntohs(n_ms->mport));
249#endif
250 udp_port = ntohs(n_ms->mport);
251 memcpy(data, &udp_port, 2);
252
253 ip_masq_listen(n_ms);
254 ip_masq_control_add(n_ms, ms);
255 ip_masq_put(n_ms);
256
257 break;
258 }
259
260 return 0;
261}
262
263struct ip_masq_app ip_masq_quake = {
264 NULL,
265 "Quake_26",
266 0,
267 0,
268 masq_quake_init_1,
269 masq_quake_done_1,
270 masq_quake_out,
271 masq_quake_in
272};
273struct ip_masq_app ip_masq_quakenew = {
274 NULL,
275 "Quake_27",
276 0,
277 0,
278 masq_quake_init_1,
279 masq_quake_done_1,
280 masq_quake_out,
281 masq_quake_in
282};
283
284
285
286
287
288__initfunc(int ip_masq_quake_init(void))
289{
290 return (register_ip_masq_app(&ip_masq_quake, IPPROTO_UDP, 26000) +
291 register_ip_masq_app(&ip_masq_quakenew, IPPROTO_UDP, 27000));
292}
293
294
295
296
297
298int ip_masq_quake_done(void)
299{
300 return (unregister_ip_masq_app(&ip_masq_quake) +
301 unregister_ip_masq_app(&ip_masq_quakenew));
302}
303
304#ifdef MODULE
305EXPORT_NO_SYMBOLS;
306
307int init_module(void)
308{
309 if (ip_masq_quake_init() != 0)
310 return -EIO;
311 return 0;
312}
313
314void cleanup_module(void)
315{
316 if (ip_masq_quake_done() != 0)
317 printk("ip_masq_quake: can't remove module");
318}
319
320#endif
321
322
323