]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-talk-conntrack-nat-20061213.patch
- disbaled B43_PCMCIA and SSB_PCMCIAHOST, kills pcmcia dependency in ssb.ko
[packages/kernel.git] / pom-ng-talk-conntrack-nat-20061213.patch
1 diff -NurpP --minimal linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack.h
2 --- linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack.h     2006-12-14 11:38:12.000000000 +0100
3 +++ linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack.h    2006-12-14 11:40:54.000000000 +0100
4 @@ -28,6 +28,7 @@ union ip_conntrack_expect_proto {
5  };
6  
7  /* Add protocol helper include file here */
8 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
9  #include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
10  #include <linux/netfilter_ipv4/ip_conntrack_mms.h>
11  #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
12 @@ -39,6 +40,7 @@ union ip_conntrack_expect_proto {
13  /* per conntrack: application helper private data */
14  union ip_conntrack_help {
15         /* insert conntrack helper private data (master) here */
16 +       struct ip_ct_talk_master ct_talk_info;
17         struct ip_ct_rsh_master ct_rsh_info;
18         struct ip_ct_mms_master ct_mms_info;
19         struct ip_ct_h323_master ct_h323_info;
20 diff -NurpP --minimal linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack_talk.h
21 --- linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
22 +++ linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack_talk.h       2006-12-14 11:40:54.000000000 +0100
23 @@ -0,0 +1,163 @@
24 +#ifndef _IP_CONNTRACK_TALK_H
25 +#define _IP_CONNTRACK_TALK_H
26 +/* TALK tracking. */
27 +
28 +#ifdef __KERNEL__
29 +#include <linux/in.h>
30 +#include <linux/netfilter_ipv4/lockhelp.h>
31 +
32 +/* Protects talk part of conntracks */
33 +DECLARE_LOCK_EXTERN(ip_talk_lock);
34 +#endif
35 +
36 +
37 +#define TALK_PORT      517
38 +#define NTALK_PORT     518
39 +
40 +/* talk structures and constants from <protocols/talkd.h> */
41 +
42 +/*
43 + * 4.3BSD struct sockaddr
44 + */
45 +struct talk_addr {
46 +       u_int16_t ta_family;
47 +       u_int16_t ta_port;
48 +       u_int32_t ta_addr;
49 +       u_int32_t ta_junk1;
50 +       u_int32_t ta_junk2;
51 +};
52 +
53 +#define        TALK_OLD_NSIZE  9
54 +#define        TALK_NSIZE      12
55 +#define        TALK_TTY_NSIZE  16
56 +
57 +/*
58 + * Client->server request message formats.
59 + */
60 +struct talk_msg {
61 +       u_char  type;           /* request type, see below */
62 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
63 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
64 +       u_char  pad;
65 +       u_int32_t id_num;       /* message id */
66 +       int32_t pid;            /* caller's process id */
67 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
68 +       struct  talk_addr addr;         /* old (4.3) style */
69 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
70 +};
71 +
72 +struct ntalk_msg {
73 +       u_char  vers;           /* protocol version */
74 +       u_char  type;           /* request type, see below */
75 +       u_char  answer;         /* not used */
76 +       u_char  pad;
77 +       u_int32_t id_num;       /* message id */
78 +       struct  talk_addr addr;         /* old (4.3) style */
79 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
80 +       int32_t pid;            /* caller's process id */
81 +       char    l_name[TALK_NSIZE];/* caller's name */
82 +       char    r_name[TALK_NSIZE];/* callee's name */
83 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
84 +};
85 +
86 +struct ntalk2_msg {
87 +       u_char  vers;           /* talk protocol version    */
88 +       u_char  type;           /* request type             */
89 +       u_char  answer;         /*  */
90 +       u_char  extended;       /* !0 if additional parts   */
91 +       u_int32_t id_num;       /* message id number (dels) */
92 +       struct  talk_addr addr;         /* target address   */
93 +       struct  talk_addr ctl_addr;     /* reply to address */
94 +       int32_t pid;            /* caller's process id */
95 +       char    l_name[TALK_NSIZE];  /* caller's name */
96 +       char    r_name[TALK_NSIZE];  /* callee's name */
97 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
98 +};
99 +
100 +/*
101 + * Server->client response message formats.
102 + */
103 +struct talk_response {
104 +       u_char  type;           /* type of request message, see below */
105 +       u_char  answer;         /* response to request message, see below */
106 +       u_char  pad[2];
107 +       u_int32_t id_num;       /* message id */
108 +       struct  talk_addr addr; /* address for establishing conversation */
109 +};
110 +
111 +struct ntalk_response {
112 +       u_char  vers;           /* protocol version */
113 +       u_char  type;           /* type of request message, see below */
114 +       u_char  answer;         /* response to request message, see below */
115 +       u_char  pad;
116 +       u_int32_t id_num;       /* message id */
117 +       struct  talk_addr addr; /* address for establishing conversation */
118 +};
119 +
120 +struct ntalk2_response {
121 +       u_char  vers;           /* protocol version         */
122 +       u_char  type;           /* type of request message  */
123 +       u_char  answer;         /* response to request      */
124 +       u_char  rvers;          /* Version of answering vers*/
125 +       u_int32_t id_num;       /* message id number        */
126 +       struct  talk_addr addr; /* address for connection   */
127 +       /* This is at the end to compatiblize this with NTALK version.   */
128 +       char    r_name[TALK_NSIZE]; /* callee's name            */
129 +};
130 +
131 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
132 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
133 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
134 +
135 +#define        TALK_VERSION    0               /* protocol versions */
136 +#define        NTALK_VERSION   1
137 +#define        NTALK2_VERSION  2
138 +
139 +/* message type values */
140 +#define LEAVE_INVITE   0       /* leave invitation with server */
141 +#define LOOK_UP                1       /* check for invitation by callee */
142 +#define DELETE         2       /* delete invitation by caller */
143 +#define ANNOUNCE       3       /* announce invitation by caller */
144 +/* NTALK2 */
145 +#define REPLY_QUERY    4       /* request reply data from local daemon */
146 +
147 +/* answer values */
148 +#define SUCCESS                0       /* operation completed properly */
149 +#define NOT_HERE       1       /* callee not logged in */
150 +#define FAILED         2       /* operation failed for unexplained reason */
151 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
152 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
153 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
154 +#define        BADVERSION      6       /* request has invalid protocol version */
155 +#define        BADADDR         7       /* request has invalid addr value */
156 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
157 +/* NTALK2 */
158 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
159 +#define TRY_HERE       10      /* Not on this machine, try this      */
160 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
161 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
162 +
163 +/* This structure exists only once per master */
164 +struct ip_ct_talk_master
165 +{
166 +};
167 +
168 +struct ip_conntrack;
169 +struct ip_conntrack_expect;
170 +
171 +extern unsigned int (*ip_nat_talk_resp_hook)(struct sk_buff **pskb,
172 +                                     struct ip_conntrack_expect *exp,
173 +                                     u_char type,
174 +                                     u_char answer,
175 +                                     struct talk_addr *addr);
176 +
177 +extern unsigned int (*ip_nat_talk_msg_hook)(struct sk_buff **pskb,
178 +                                    struct ip_conntrack *ct,
179 +                                    u_char type,
180 +                                    struct talk_addr *addr,
181 +                                    struct talk_addr *ctl_addr);
182 +
183 +
184 +void ip_ct_talk_expect(struct ip_conntrack *ct, struct ip_conntrack_expect *exp);
185 +void ip_ct_ntalk_expect(struct ip_conntrack *ct, struct ip_conntrack_expect *exp);
186 +#endif /* _IP_CONNTRACK_TALK_H */
187 diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/Kconfig linux-2.6.19/net/ipv4/netfilter/Kconfig
188 --- linux-2.6.19-pom-ng/net/ipv4/netfilter/Kconfig      2006-12-14 11:40:32.000000000 +0100
189 +++ linux-2.6.19/net/ipv4/netfilter/Kconfig     2006-12-14 11:40:54.000000000 +0100
190 @@ -909,5 +909,28 @@ config IP_NF_RTSP
191           If you want to compile it as a module, say 'M' here and read
192           Documentation/modules.txt.  If unsure, say 'Y'.
193  
194 +config IP_NF_NAT_TALK
195 +       tristate
196 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
197 +       default IP_NF_NAT if IP_NF_TALK=y
198 +       default m if IP_NF_TALK=m
199 +
200 +config IP_NF_TALK
201 +       tristate  'talk protocol support'
202 +       depends on IP_NF_CONNTRACK
203 +       help
204 +         The talk protocols (both otalk/talk - or talk/ntalk, to confuse
205 +         you by the different namings about which is old or which is new :-)
206 +         use an additional channel to setup the talk session and a separated
207 +         data channel for the actual conversation (like in FTP). Both the 
208 +         initiating and the setup channels are over UDP, while the data channel 
209 +         is over TCP, on a random port. The conntrack part of this extension
210 +         will enable you to let in/out talk sessions easily by matching these
211 +         connections as RELATED by the state match, while the NAT part helps
212 +         you to let talk sessions trough a NAT machine.
213 +       
214 +         If you want to compile it as a module, say 'M' here and read
215 +         Documentation/modules.txt.  If unsure, say 'N'.
216 +
217  endmenu
218  
219 diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/Makefile linux-2.6.19/net/ipv4/netfilter/Makefile
220 --- linux-2.6.19-pom-ng/net/ipv4/netfilter/Makefile     2006-12-14 11:40:32.000000000 +0100
221 +++ linux-2.6.19/net/ipv4/netfilter/Makefile    2006-12-14 11:40:54.000000000 +0100
222 @@ -25,6 +25,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) +=
223  obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
224  
225  # connection tracking helpers
226 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
227  
228  # rtsp protocol support
229  obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
230 @@ -43,6 +44,7 @@ obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_
231  obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
232  
233  # NAT helpers 
234 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
235  obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
236  obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
237  obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
238 diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_talk.c
239 --- linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
240 +++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_talk.c 2006-12-14 11:40:54.000000000 +0100
241 @@ -0,0 +1,449 @@
242 +/* 
243 + * talk extension for IP connection tracking. 
244 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
245 + *
246 + *      This program is free software; you can redistribute it and/or
247 + *      modify it under the terms of the GNU General Public License
248 + *      as published by the Free Software Foundation; either version
249 + *      2 of the License, or (at your option) any later version.
250 + **
251 + *     Module load syntax:
252 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
253 + *
254 + *             talk=[0|1]      disable|enable old talk support
255 + *            ntalk=[0|1]      disable|enable ntalk support
256 + *           ntalk2=[0|1]      disable|enable ntalk2 support
257 + *
258 + *     The default is talk=1 ntalk=1 ntalk2=1
259 + *
260 + *     The helper does not support simultaneous talk requests.
261 + **
262 + *
263 + *             ASCII art on talk protocols
264 + *     
265 + *     
266 + *     caller server               callee server
267 + *             |     \           /
268 + *             |       \       /
269 + *             |         \   /
270 + *             |           /  
271 + *             |         /   \
272 + *           2 |     1 /       \ 3
273 + *     caller client  ----------- callee client
274 + *                              4
275 + *
276 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
277 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
278 + *     3. callee client <-> caller server: LOOK_UP invitation
279 + *     4. callee client <-> caller client: talk data channel
280 + *
281 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
282 + *      draft-hunter-talk-00.txt
283 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
284 + *
285 + * Modifications:
286 + * 2005-02-13 Harald Welte <laforge@netfilter.org>
287 + *     - update to 2.6.x API
288 + *     - update to post 2.6.11 helper infrastructure
289 + *     - use c99 structure initializers
290 + *     - explicitly allocate expectation
291 + *
292 + */
293 +#include <linux/config.h>
294 +#include <linux/module.h>
295 +#include <linux/netfilter.h>
296 +#include <linux/ip.h>
297 +#include <net/checksum.h>
298 +#include <net/udp.h>
299 +
300 +#include <linux/netfilter_ipv4/lockhelp.h>
301 +#include <linux/netfilter_ipv4/ip_conntrack.h>
302 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
303 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
304 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
305 +
306 +/* Default all talk protocols are supported */
307 +static int talk = 1;
308 +static int ntalk = 1;
309 +static int ntalk2 = 1;
310 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
311 +MODULE_DESCRIPTION("talk connection tracking module");
312 +MODULE_LICENSE("GPL");
313 +module_param(talk, int, 0400);
314 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
315 +module_param(ntalk, int, 0400);
316 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
317 +module_param(ntalk2, int, 0400);
318 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
319 +
320 +static char talk_buffer[65536];
321 +static DECLARE_LOCK(talk_buffer_lock);
322 +
323 +unsigned int (*ip_nat_talk_resp_hook)(struct sk_buff **pskb,
324 +                                     struct ip_conntrack_expect *exp,
325 +                                     u_char type,
326 +                                     u_char answer,
327 +                                     struct talk_addr *addr);
328 +EXPORT_SYMBOL_GPL(ip_nat_talk_resp_hook);
329 +
330 +unsigned int (*ip_nat_talk_msg_hook)(struct sk_buff **pskb,
331 +                                    struct ip_conntrack *ct,
332 +                                    u_char type,
333 +                                    struct talk_addr *addr,
334 +                                    struct talk_addr *ctl_addr);
335 +EXPORT_SYMBOL_GPL(ip_nat_talk_msg_hook);
336 +
337 +#if 0
338 +#define DEBUGP printk
339 +#else
340 +#define DEBUGP(format, args...)
341 +#endif
342 +
343 +void ip_ct_talk_expect(struct ip_conntrack *ct,
344 +                      struct ip_conntrack_expect *exp);
345 +void ip_ct_ntalk_expect(struct ip_conntrack *ct,
346 +                       struct ip_conntrack_expect *exp);
347 +
348 +static void (*talk_expectfn[2])(struct ip_conntrack *ct,
349 +                               struct ip_conntrack_expect *exp) = {
350 +                                       ip_ct_talk_expect,
351 +                                       ip_ct_ntalk_expect };
352 +
353 +static int talk_help_response(struct sk_buff **pskb,
354 +                             struct ip_conntrack *ct,
355 +                             enum ip_conntrack_info ctinfo,
356 +                             int talk_port,
357 +                             u_char mode,
358 +                             u_char type,
359 +                             u_char answer,
360 +                             struct talk_addr *addr)
361 +{
362 +       int ret;
363 +       int dir = CTINFO2DIR(ctinfo);
364 +       struct ip_conntrack_expect *exp;
365 +       u_int16_t exp_talk_port;
366 +
367 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
368 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
369 +               type, answer);
370 +
371 +       if (!(answer == SUCCESS && type == mode))
372 +               return NF_ACCEPT;
373 +       
374 +       exp = ip_conntrack_expect_alloc();
375 +       if (exp == NULL) {
376 +               return NF_DROP;
377 +       }
378 +       
379 +       if (type == ANNOUNCE) {
380 +
381 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
382 +
383 +               /* update the talk info */
384 +               exp_talk_port = htons(talk_port);
385 +
386 +               /* expect callee client -> caller server message */
387 +               exp->tuple = ((struct ip_conntrack_tuple)
388 +                       { { ct->tuplehash[dir].tuple.src.ip,
389 +                           { 0 } },
390 +                         { ct->tuplehash[dir].tuple.dst.ip,
391 +                           { .udp = { htons(talk_port) } },
392 +                           IPPROTO_UDP }});
393 +               exp->mask = ((struct ip_conntrack_tuple)
394 +                       { { 0xFFFFFFFF, { 0 } },
395 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
396 +               
397 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
398 +               exp->master = ct;
399 +
400 +               DEBUGP("ip_ct_talk_help_response: callee client "
401 +                      "%u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
402 +                      NIPQUAD(exp->tuple.src.ip), 
403 +                      ntohs(exp->tuple.src.u.udp.port),
404 +                      NIPQUAD(exp->tuple.dst.ip), 
405 +                      ntohs(exp->tuple.dst.u.udp.port));
406 +
407 +               if (ip_nat_talk_resp_hook)
408 +                       ret = ip_nat_talk_resp_hook(pskb, exp, type, answer, 
409 +                                                   addr);
410 +               else if (ip_conntrack_expect_related(exp) != 0) {
411 +                       ip_conntrack_expect_free(exp);
412 +                       ret = NF_DROP;
413 +               }
414 +       } else if (type == LOOK_UP) {
415 +
416 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
417 +
418 +               /* update the talk info */
419 +               exp_talk_port = addr->ta_port;
420 +
421 +               /* expect callee client -> caller client connection */
422 +               exp->tuple = ((struct ip_conntrack_tuple)
423 +                       { { ct->tuplehash[!dir].tuple.src.ip,
424 +                           { 0 } },
425 +                         { addr->ta_addr,
426 +                           { addr->ta_port },
427 +                           IPPROTO_TCP }});
428 +               exp->mask = ((struct ip_conntrack_tuple)
429 +                       { { 0xFFFFFFFF, { 0 } },
430 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFF }});
431 +               exp->expectfn = NULL;
432 +               exp->master = ct;
433 +
434 +               DEBUGP("ip_ct_talk_help_response: callee client "
435 +                      "%u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
436 +                      NIPQUAD(exp->tuple.src.ip),
437 +                      ntohs(exp->tuple.src.u.tcp.port),
438 +                      NIPQUAD(exp->tuple.dst.ip),
439 +                      ntohs(exp->tuple.dst.u.tcp.port));
440 +
441 +               if (ip_nat_talk_resp_hook)
442 +                       ret = ip_nat_talk_resp_hook(pskb, exp, type, answer, 
443 +                                                   addr);
444 +               else if (ip_conntrack_expect_related(exp) != 0) {
445 +                       ip_conntrack_expect_free(exp);
446 +                       ret = NF_DROP;
447 +               }
448 +       }
449 +                   
450 +       return NF_ACCEPT;
451 +}
452 +
453 +/* FIXME: This should be in userspace.  Later. */
454 +static int talk_help(struct sk_buff **pskb,
455 +                    struct ip_conntrack *ct,
456 +                    enum ip_conntrack_info ctinfo,
457 +                    int talk_port,
458 +                    u_char mode)
459 +{
460 +       int ret;
461 +       unsigned int dataoff;
462 +       struct udphdr _udph, *uh;
463 +       char *tb_ptr, *data;
464 +       //struct udphdr *udph = (void *)iph + iph->ihl * 4;
465 +       //const char *data = (const char *)udph + sizeof(struct udphdr);
466 +       int dir = CTINFO2DIR(ctinfo);
467 +       size_t udplen;
468 +
469 +       DEBUGP("ip_ct_talk_help: help entered\n");
470 +
471 +       /* Until there's been traffic both ways, don't look in packets. */
472 +       if (ctinfo != IP_CT_ESTABLISHED
473 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
474 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
475 +               return NF_ACCEPT;
476 +       }
477 +
478 +       /* Not whole UDP header? */
479 +       uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
480 +                               sizeof(_udph), &_udph);
481 +       if (uh == NULL) {
482 +               DEBUGP("ip_ct_talk_help: short for udph\n");
483 +               return NF_ACCEPT;
484 +       }
485 +
486 +       udplen = (*pskb)->len - (*pskb)->nh.iph->ihl*4;
487 +       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(_udph);
488 +       if (dataoff >= (*pskb)->len)
489 +               return NF_ACCEPT;
490 +
491 +       LOCK_BH(&talk_buffer_lock);
492 +       tb_ptr = skb_header_pointer(*pskb, dataoff,
493 +                                   (*pskb)->len - dataoff, talk_buffer);
494 +       BUG_ON(tb_ptr == NULL);
495 +
496 +       data = tb_ptr;
497 +       
498 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
499 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
500 +
501 +       if (dir == IP_CT_DIR_ORIGINAL && ip_nat_talk_msg_hook) {
502 +               if (talk_port == TALK_PORT) {
503 +                       if (udplen == sizeof(struct udphdr) + 
504 +                                       sizeof(struct talk_msg)) {
505 +                               struct talk_msg *tm = (struct talk_msg *)data;
506 +                               return ip_nat_talk_msg_hook(pskb, ct, tm->type,
507 +                                               &tm->addr, &tm->ctl_addr);
508 +                       }
509 +               } else {
510 +                       if (ntalk &&
511 +                           udplen == sizeof(struct udphdr) +
512 +                                       sizeof(struct ntalk_msg) &&
513 +                           ((struct ntalk_msg *)data)->vers == NTALK_VERSION){
514 +                               struct ntalk_msg *tm = (struct ntalk_msg *)data;
515 +                               return ip_nat_talk_msg_hook(pskb, ct, tm->type,
516 +                                               &tm->addr, &tm->ctl_addr);
517 +                       } else if (ntalk2 &&
518 +                                  udplen >= sizeof(struct udphdr) +
519 +                                               sizeof(struct ntalk2_msg) &&
520 +                                  ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION &&
521 +                                  udplen == sizeof(struct udphdr)
522 +                                            + sizeof(struct ntalk2_msg)
523 +                                            + ((struct ntalk2_msg *)data)->extended) {
524 +                               struct ntalk2_msg *tm = (struct ntalk2_msg *)data;
525 +                               return ip_nat_talk_msg_hook(pskb, ct, tm->type,
526 +                                               &tm->addr, &tm->ctl_addr);
527 +                       }
528 +               }
529 +               return NF_ACCEPT;
530 +       }
531 +               
532 +       /* only DIR_REPLY */
533 +       if (talk_port == TALK_PORT
534 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
535 +               ret = talk_help_response(pskb, ct, ctinfo, talk_port, mode,
536 +                                         ((struct talk_response *)data)->type, 
537 +                                         ((struct talk_response *)data)->answer,
538 +                                         &(((struct talk_response *)data)->addr));
539 +       else if (talk_port == NTALK_PORT
540 +                 && ntalk
541 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
542 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
543 +               ret = talk_help_response(pskb, ct, ctinfo, talk_port, mode,
544 +                                         ((struct ntalk_response *)data)->type, 
545 +                                         ((struct ntalk_response *)data)->answer,
546 +                                         &(((struct ntalk_response *)data)->addr));
547 +       else if (talk_port == NTALK_PORT
548 +                && ntalk2
549 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
550 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
551 +               ret = talk_help_response(pskb, ct, ctinfo, talk_port, mode,
552 +                                         ((struct ntalk2_response *)data)->type, 
553 +                                         ((struct ntalk2_response *)data)->answer,
554 +                                         &(((struct ntalk2_response *)data)->addr));
555 +       else {
556 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
557 +                      (unsigned)udplen - sizeof(struct udphdr), 
558 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
559 +               ret = NF_ACCEPT;
560 +       }
561 +       UNLOCK_BH(&talk_buffer_lock);
562 +       return ret;
563 +}
564 +
565 +static int lookup_help(struct sk_buff **pskb,
566 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
567 +{
568 +       return talk_help(pskb, ct, ctinfo, TALK_PORT, LOOK_UP);
569 +}
570 +
571 +static int lookup_nhelp(struct sk_buff **pskb,
572 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
573 +{
574 +       return talk_help(pskb, ct, ctinfo, NTALK_PORT, LOOK_UP);
575 +}
576 +
577 +static struct ip_conntrack_helper lookup_helpers[2] = { 
578 +       { 
579 +               .name           = "talk-lookup",
580 +               .max_expected   = 1,
581 +               .timeout        = 4 * 60,
582 +               .tuple          = {
583 +                               .src.u.udp.port = __constant_htons(TALK_PORT),
584 +                               .dst.protonum   = IPPROTO_UDP,
585 +                       },
586 +               .mask           = {
587 +                               .src.u.udp.port = 0xffff,
588 +                               .dst.protonum   = 0xff,
589 +                       },
590 +               .help           = &lookup_help,
591 +       },
592 +       {
593 +               .name           = "ntalk-lookup",
594 +               .max_expected   = 1,
595 +               .timeout        = 4 * 60,
596 +               .tuple          = {
597 +                               .src.u.udp.port = __constant_htons(NTALK_PORT),
598 +                               .dst.protonum   = IPPROTO_UDP,
599 +                       },
600 +               .mask           = {
601 +                               .src.u.udp.port = 0xffff,
602 +                               .dst.protonum   = 0xff,
603 +                       },
604 +               .help           = &lookup_nhelp,
605 +       },
606 +};
607 +
608 +void ip_ct_talk_expect(struct ip_conntrack *ct,
609 +                      struct ip_conntrack_expect *exp)
610 +{
611 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
612 +       WRITE_LOCK(&ip_conntrack_lock);
613 +       ct->helper = &lookup_helpers[0];
614 +       WRITE_UNLOCK(&ip_conntrack_lock);
615 +}
616 +
617 +void ip_ct_ntalk_expect(struct ip_conntrack *ct,
618 +                       struct ip_conntrack_expect *exp)
619 +{
620 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
621 +       WRITE_LOCK(&ip_conntrack_lock);
622 +       ct->helper = &lookup_helpers[1];
623 +       WRITE_UNLOCK(&ip_conntrack_lock);
624 +}
625 +
626 +static int help(struct sk_buff **pskb,
627 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
628 +{
629 +       return talk_help(pskb, ct, ctinfo, TALK_PORT, ANNOUNCE);
630 +}
631 +
632 +static int nhelp(struct sk_buff **pskb,
633 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
634 +{
635 +       return talk_help(pskb, ct, ctinfo, NTALK_PORT, ANNOUNCE);
636 +}
637 +
638 +static struct ip_conntrack_helper talk_helpers[2] = { 
639 +       { 
640 +               .name           = "talk",
641 +               .help           = &help,
642 +               .me             = THIS_MODULE,
643 +               .max_expected   = 1,
644 +               .timeout        = 4 * 60,       /* 4 minutes */
645 +               .tuple          = {
646 +                               .src.u.udp.port = __constant_htons(TALK_PORT),
647 +                               .dst.protonum   = IPPROTO_UDP,
648 +                       },
649 +               .mask           = {
650 +                               .src.u.udp.port = 0xffff,
651 +                               .dst.protonum   = 0xff,
652 +                       },
653 +       },
654 +       {
655 +               .name           = "ntalk",
656 +               .help           = &nhelp,
657 +               .me             = THIS_MODULE,
658 +               .max_expected   = 1,
659 +               .timeout        = 4 * 60,       /* 4 minutes */
660 +               .tuple          = {
661 +                               .src.u.udp.port = __constant_htons(NTALK_PORT),
662 +                               .dst.protonum   = IPPROTO_UDP,
663 +                       },
664 +               .mask           = {
665 +                               .src.u.udp.port = 0xffff,
666 +                               .dst.protonum   = IPPROTO_UDP,
667 +                       },
668 +       },
669 +};
670 +
671 +static int __init init(void)
672 +{
673 +       if (talk > 0)
674 +               ip_conntrack_helper_register(&talk_helpers[0]);
675 +       if (ntalk > 0 || ntalk2 > 0)
676 +               ip_conntrack_helper_register(&talk_helpers[1]);
677 +               
678 +       return 0;
679 +}
680 +
681 +static void __exit fini(void)
682 +{
683 +       if (talk > 0)
684 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
685 +       if (ntalk > 0 || ntalk2 > 0)
686 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
687 +}
688 +
689 +module_init(init);
690 +module_exit(fini);
691 diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.19/net/ipv4/netfilter/ip_nat_talk.c
692 --- linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
693 +++ linux-2.6.19/net/ipv4/netfilter/ip_nat_talk.c       2006-12-14 11:40:54.000000000 +0100
694 @@ -0,0 +1,226 @@
695 +/* 
696 + * talk extension for UDP NAT alteration. 
697 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
698 + *
699 + *      This program is free software; you can redistribute it and/or
700 + *      modify it under the terms of the GNU General Public License
701 + *      as published by the Free Software Foundation; either version
702 + *      2 of the License, or (at your option) any later version.
703 + **
704 + *
705 + * Modifications:
706 + * 2005-02-13 Harald Welte <laforge@netfilter.org>
707 + *     - update to 2.6.x API
708 + *     - update to post 2.6.11 helper infrastructure
709 + *     - use c99 structure initializers
710 + *  
711 + */
712 +#include <linux/module.h>
713 +#include <linux/netfilter_ipv4.h>
714 +#include <linux/ip.h>
715 +#include <linux/udp.h>
716 +#include <linux/kernel.h>
717 +#include <net/tcp.h>
718 +#include <net/udp.h>
719 +
720 +#include <linux/netfilter_ipv4/ip_nat.h>
721 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
722 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
723 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
724 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
725 +
726 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
727 +MODULE_DESCRIPTION("talk network address translation module");
728 +
729 +#if 0
730 +#define DEBUGP printk
731 +#define IP_NAT_TALK_DEBUG
732 +#else
733 +#define DEBUGP(format, args...)
734 +#endif
735 +
736 +static void
737 +nat_talk_expect(struct ip_conntrack *ct,
738 +               struct ip_conntrack_expect *exp)
739 +{
740 +       ip_nat_follow_master(ct, exp);
741 +       ip_ct_talk_expect(ct, exp);
742 +}
743 +
744 +static void
745 +nat_ntalk_expect(struct ip_conntrack *ct,
746 +                struct ip_conntrack_expect *exp)
747 +{
748 +       ip_nat_follow_master(ct, exp);
749 +       ip_ct_ntalk_expect(ct, exp);
750 +}
751 +
752 +static int
753 +mangle_packet(struct sk_buff **pskb,
754 +             struct ip_conntrack *ct,
755 +             u_int32_t newip,
756 +             u_int16_t port,
757 +             struct talk_addr *addr,
758 +             struct talk_addr *ctl_addr)
759 +{
760 +       struct iphdr *iph = (*pskb)->nh.iph;
761 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
762 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
763 +
764 +       /* Fortunately talk sends a structure with the address and
765 +          port in it. The size of the packet won't change. */
766 +
767 +       if (ctl_addr == NULL) {
768 +               /* response */
769 +               if (addr->ta_addr == INADDR_ANY)
770 +                       return 1;
771 +               DEBUGP("ip_nat_talk_mangle_packet: response orig "
772 +                      "%u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
773 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
774 +                      NIPQUAD(newip), ntohs(port));
775 +               addr->ta_addr = newip;
776 +               addr->ta_port = port;
777 +       } else {
778 +               /* message */
779 +               if (addr->ta_addr != INADDR_ANY) {
780 +                       /* Change address inside packet to match way we're
781 +                        * mapping this connection. */
782 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr "
783 +                              "%u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
784 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
785 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
786 +                              ntohs(addr->ta_port));
787 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
788 +               }
789 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr "
790 +                      "%u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
791 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
792 +                      NIPQUAD(newip), ntohs(port));
793 +               ctl_addr->ta_addr = newip;
794 +               ctl_addr->ta_port = port;
795 +       }
796 +
797 +       /* Fix checksums */
798 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
799 +       udph->check = 0;
800 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
801 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
802 +               
803 +       ip_send_check(iph);
804 +       return 1;
805 +}
806 +
807 +static unsigned int talk_help_msg(struct sk_buff **pskb,
808 +                        struct ip_conntrack *ct,
809 +                        u_char type,
810 +                        struct talk_addr *addr,
811 +                        struct talk_addr *ctl_addr)
812 +{
813 +       u_int32_t newip;
814 +       u_int16_t port;
815 +       
816 +       unsigned int verdict = NF_ACCEPT;
817 +
818 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
819 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
820 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
821 +               type);
822 +
823 +       /* Change address inside packet to match way we're mapping
824 +          this connection. */
825 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
826 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
827 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
828 +               NIPQUAD(newip), ntohs(port));
829 +
830 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
831 +               verdict = NF_DROP;
832 +
833 +       return verdict;
834 +}
835 +
836 +static unsigned int talk_help_response(struct sk_buff **pskb,
837 +                             struct ip_conntrack_expect *exp,
838 +                             u_char type,
839 +                             u_char answer,
840 +                             struct talk_addr *addr)
841 +{
842 +       struct ip_conntrack *ct = exp->master;
843 +       u_int32_t newip;
844 +       u_int16_t port, *pport, *tport;
845 +
846 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, "
847 +              "type %d answer %d\n", NIPQUAD(addr->ta_addr),
848 +              ntohs(addr->ta_port), type, answer);
849 +       
850 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
851 +               ntohs(exp->tuple.dst.u.tcp.port),
852 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
853 +
854 +       /* Change address inside packet to match way we're mapping
855 +          this connection. */
856 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
857 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
858 +       /* We can read expect here without conntrack lock, since it's
859 +          only set in ip_conntrack_talk , with ip_talk_lock held
860 +          writable */ 
861 +       if (type == LOOK_UP) {
862 +               pport = &exp->saved_proto.tcp.port;
863 +               tport = &exp->tuple.dst.u.tcp.port;
864 +       } else {
865 +               pport = &exp->saved_proto.udp.port;
866 +               tport = &exp->tuple.dst.u.udp.port;
867 +       }
868 +
869 +       *pport = *tport;
870 +
871 +       exp->tuple.dst.ip = newip;
872 +
873 +       if (exp->expectfn == ip_ct_talk_expect)
874 +               exp->expectfn = nat_talk_expect;
875 +       else if (exp->expectfn == ip_ct_ntalk_expect)
876 +               exp->expectfn = nat_ntalk_expect;
877 +       else
878 +               BUG();
879 +
880 +       /* Try to get same port: if not, try to change it. */
881 +       for (port = ntohs(*pport); port != 0; port++) {
882 +               *tport = htons(port);
883 +
884 +               if (ip_conntrack_expect_related(exp) == 0) {
885 +                       DEBUGP("ip_nat_talk_help_response: using "
886 +                              "%u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
887 +                       break;
888 +               }
889 +       }
890 +       if (port == 0) {
891 +               ip_conntrack_expect_free(exp);
892 +               return NF_DROP;
893 +       }
894 +
895 +       if (!mangle_packet(pskb, ct, newip, htons(port), addr, NULL)) {
896 +               ip_conntrack_unexpect_related(exp);
897 +               return NF_DROP;
898 +       }
899 +       return NF_ACCEPT;
900 +}
901 +
902 +static int __init init(void)
903 +{
904 +       BUG_ON(ip_nat_talk_msg_hook);
905 +       BUG_ON(ip_nat_talk_resp_hook);
906 +       ip_nat_talk_msg_hook = &talk_help_msg;
907 +       ip_nat_talk_resp_hook = &talk_help_response;
908 +       return 0;
909 +}
910 +
911 +static void __exit fini(void)
912 +{
913 +       ip_nat_talk_resp_hook = NULL;
914 +       ip_nat_talk_msg_hook = NULL;
915 +       /* Make sure noone calls it, meanwhile */
916 +       synchronize_net();
917 +}
918 +
919 +module_init(init);
920 +module_exit(fini);
This page took 0.129648 seconds and 3 git commands to generate.