1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/config.h>
44#include <linux/module.h>
45
46#include <linux/types.h>
47#include <linux/kernel.h>
48#include <asm/system.h>
49#include <linux/skbuff.h>
50#include <linux/in.h>
51#include <linux/ip.h>
52#include <linux/init.h>
53#include <net/protocol.h>
54#include <net/tcp.h>
55#include <net/ip_masq.h>
56
57
58
59
60
61
62int ports[MAX_MASQ_APP_PORTS] = {6667};
63struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
64
65
66
67#ifdef CONFIG_IP_MASQ_DEBUG
68static int debug=0;
69MODULE_PARM(debug, "i");
70#endif
71
72MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
73
74
75
76
77
78
79#define NUM_DCCPROTO 5
80
81struct dccproto
82{
83 char *match;
84 int matchlen;
85 int xtra_args;
86};
87
88struct dccproto dccprotos[NUM_DCCPROTO] = {
89 { "SEND ", 5, 1 },
90 { "CHAT ", 5, 0, },
91 { "MOVE ", 5, 1 },
92 { "TSEND ", 6, 1, },
93 { "SCHAT ", 6, 0, }
94};
95#define MAXMATCHLEN 6
96
97static int
98masq_irc_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
99{
100 MOD_INC_USE_COUNT;
101 return 0;
102}
103
104static int
105masq_irc_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
106{
107 MOD_DEC_USE_COUNT;
108 return 0;
109}
110
111int
112masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
113{
114 struct sk_buff *skb;
115 struct iphdr *iph;
116 struct tcphdr *th;
117 char *data, *data_limit;
118 __u32 s_addr;
119 __u16 s_port;
120 struct ip_masq *n_ms;
121 char buf[20];
122 unsigned buf_len;
123 int diff;
124 int xtra_args = 0;
125 char *dcc_p, *addr_beg_p, *addr_end_p;
126
127 skb = *skb_p;
128 iph = skb->nh.iph;
129 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
130 data = (char *)&th[1];
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 data_limit = skb->h.raw + skb->len;
149
150 while (data < (data_limit - ( 21 + MAXMATCHLEN ) ) )
151 {
152 int i;
153 if (memcmp(data,"DCC ",4)) {
154 data ++;
155 continue;
156 }
157
158 dcc_p = data;
159 data += 4;
160
161 for(i=0; i<NUM_DCCPROTO; i++)
162 {
163
164
165
166
167 if( memcmp(data, dccprotos[i].match, dccprotos[i].matchlen ) == 0 )
168 {
169 xtra_args = dccprotos[i].xtra_args;
170 data += dccprotos[i].matchlen;
171
172
173
174
175
176 while( *data++ != ' ')
177
178
179
180
181
182 if (data > (data_limit-12)) return 0;
183
184
185 addr_beg_p = data;
186
187
188
189
190
191 s_addr = simple_strtoul(data,&data,10);
192 if (*data++ !=' ')
193 continue;
194
195
196
197
198
199 s_port = simple_strtoul(data,&data,10);
200 addr_end_p = data;
201
202
203
204
205
206 while(xtra_args) {
207 if (*data != ' ')
208 break;
209 data++;
210 simple_strtoul(data,&data,10);
211 xtra_args--;
212 }
213
214 if (xtra_args != 0) continue;
215
216
217
218
219
220 if (data[0] != 0x01)
221 continue;
222 if (data[1]!='\r' && data[1]!='\n')
223 continue;
224
225
226
227
228
229
230
231 n_ms = ip_masq_new(IPPROTO_TCP,
232 maddr, 0,
233 htonl(s_addr),htons(s_port),
234 0, 0,
235 IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
236 if (n_ms==NULL)
237 return 0;
238
239
240
241
242
243 buf_len = sprintf(buf,"%lu %u",
244 ntohl(n_ms->maddr),ntohs(n_ms->mport));
245
246
247
248
249
250 diff = buf_len - (addr_end_p-addr_beg_p);
251
252 *addr_beg_p = '\0';
253 IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
254
255
256
257
258
259 if (diff==0) {
260
261
262
263 memcpy(addr_beg_p,buf,buf_len);
264 } else {
265
266 *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
267 addr_beg_p, addr_end_p-addr_beg_p,
268 buf, buf_len);
269 }
270 ip_masq_listen(n_ms);
271 ip_masq_put(n_ms);
272 return diff;
273 }
274 }
275 }
276 return 0;
277
278}
279
280
281
282
283
284
285
286
287
288struct ip_masq_app ip_masq_irc = {
289 NULL,
290 "irc",
291 0,
292 0,
293 masq_irc_init_1,
294 masq_irc_done_1,
295 masq_irc_out,
296 NULL
297};
298
299
300
301
302
303__initfunc(int ip_masq_irc_init(void))
304{
305 int i, j;
306
307 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
308 if (ports[i]) {
309 if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
310 GFP_KERNEL)) == NULL)
311 return -ENOMEM;
312 memcpy(masq_incarnations[i], &ip_masq_irc, sizeof(struct ip_masq_app));
313 if ((j = register_ip_masq_app(masq_incarnations[i],
314 IPPROTO_TCP,
315 ports[i]))) {
316 return j;
317 }
318 IP_MASQ_DEBUG(1-debug,
319 "Irc: loaded support on port[%d] = %d\n",
320 i, ports[i]);
321 } else {
322
323 masq_incarnations[i] = NULL;
324 }
325 }
326 return 0;
327}
328
329
330
331
332
333int ip_masq_irc_done(void)
334{
335 int i, j, k;
336
337 k=0;
338 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
339 if (masq_incarnations[i]) {
340 if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
341 k = j;
342 } else {
343 kfree(masq_incarnations[i]);
344 masq_incarnations[i] = NULL;
345 IP_MASQ_DEBUG(1-debug, "Irc: unloaded support on port[%d] = %d\n",
346 i, ports[i]);
347 }
348 }
349 }
350 return k;
351}
352
353
354#ifdef MODULE
355EXPORT_NO_SYMBOLS;
356
357int init_module(void)
358{
359 if (ip_masq_irc_init() != 0)
360 return -EIO;
361 return 0;
362}
363
364void cleanup_module(void)
365{
366 if (ip_masq_irc_done() != 0)
367 printk(KERN_INFO "ip_masq_irc: can't remove module");
368}
369
370#endif
371