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 {
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
24 +#ifndef _IP_CONNTRACK_TALK_H
25 +#define _IP_CONNTRACK_TALK_H
29 +#include <linux/in.h>
30 +#include <linux/netfilter_ipv4/lockhelp.h>
32 +/* Protects talk part of conntracks */
33 +DECLARE_LOCK_EXTERN(ip_talk_lock);
37 +#define TALK_PORT 517
38 +#define NTALK_PORT 518
40 +/* talk structures and constants from <protocols/talkd.h> */
43 + * 4.3BSD struct sockaddr
46 + u_int16_t ta_family;
53 +#define TALK_OLD_NSIZE 9
54 +#define TALK_NSIZE 12
55 +#define TALK_TTY_NSIZE 16
58 + * Client->server request message formats.
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 */
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 */
73 + u_char vers; /* protocol version */
74 + u_char type; /* request type, see below */
75 + u_char answer; /* not used */
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 */
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 */
101 + * Server->client response message formats.
103 +struct talk_response {
104 + u_char type; /* type of request message, see below */
105 + u_char answer; /* response to request message, see below */
107 + u_int32_t id_num; /* message id */
108 + struct talk_addr addr; /* address for establishing conversation */
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 */
116 + u_int32_t id_num; /* message id */
117 + struct talk_addr addr; /* address for establishing conversation */
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 */
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)
135 +#define TALK_VERSION 0 /* protocol versions */
136 +#define NTALK_VERSION 1
137 +#define NTALK2_VERSION 2
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 */
145 +#define REPLY_QUERY 4 /* request reply data from local daemon */
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 */
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 */
163 +/* This structure exists only once per master */
164 +struct ip_ct_talk_master
168 +struct ip_conntrack;
169 +struct ip_conntrack_expect;
171 +extern unsigned int (*ip_nat_talk_resp_hook)(struct sk_buff **pskb,
172 + struct ip_conntrack_expect *exp,
175 + struct talk_addr *addr);
177 +extern unsigned int (*ip_nat_talk_msg_hook)(struct sk_buff **pskb,
178 + struct ip_conntrack *ct,
180 + struct talk_addr *addr,
181 + struct talk_addr *ctl_addr);
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'.
194 +config IP_NF_NAT_TALK
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
201 + tristate 'talk protocol support'
202 + depends on IP_NF_CONNTRACK
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.
214 + If you want to compile it as a module, say 'M' here and read
215 + Documentation/modules.txt. If unsure, say 'N'.
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
225 # connection tracking helpers
226 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
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
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
243 + * talk extension for IP connection tracking.
244 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
251 + * Module load syntax:
252 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
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
258 + * The default is talk=1 ntalk=1 ntalk2=1
260 + * The helper does not support simultaneous talk requests.
263 + * ASCII art on talk protocols
266 + * caller server callee server
273 + * caller client ----------- callee client
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
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)
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
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>
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>
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");
320 +static char talk_buffer[65536];
321 +static DECLARE_LOCK(talk_buffer_lock);
323 +unsigned int (*ip_nat_talk_resp_hook)(struct sk_buff **pskb,
324 + struct ip_conntrack_expect *exp,
327 + struct talk_addr *addr);
328 +EXPORT_SYMBOL_GPL(ip_nat_talk_resp_hook);
330 +unsigned int (*ip_nat_talk_msg_hook)(struct sk_buff **pskb,
331 + struct ip_conntrack *ct,
333 + struct talk_addr *addr,
334 + struct talk_addr *ctl_addr);
335 +EXPORT_SYMBOL_GPL(ip_nat_talk_msg_hook);
338 +#define DEBUGP printk
340 +#define DEBUGP(format, args...)
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);
348 +static void (*talk_expectfn[2])(struct ip_conntrack *ct,
349 + struct ip_conntrack_expect *exp) = {
351 + ip_ct_ntalk_expect };
353 +static int talk_help_response(struct sk_buff **pskb,
354 + struct ip_conntrack *ct,
355 + enum ip_conntrack_info ctinfo,
360 + struct talk_addr *addr)
363 + int dir = CTINFO2DIR(ctinfo);
364 + struct ip_conntrack_expect *exp;
365 + u_int16_t exp_talk_port;
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),
371 + if (!(answer == SUCCESS && type == mode))
374 + exp = ip_conntrack_expect_alloc();
379 + if (type == ANNOUNCE) {
381 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
383 + /* update the talk info */
384 + exp_talk_port = htons(talk_port);
386 + /* expect callee client -> caller server message */
387 + exp->tuple = ((struct ip_conntrack_tuple)
388 + { { ct->tuplehash[dir].tuple.src.ip,
390 + { ct->tuplehash[dir].tuple.dst.ip,
391 + { .udp = { htons(talk_port) } },
393 + exp->mask = ((struct ip_conntrack_tuple)
394 + { { 0xFFFFFFFF, { 0 } },
395 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
397 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
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));
407 + if (ip_nat_talk_resp_hook)
408 + ret = ip_nat_talk_resp_hook(pskb, exp, type, answer,
410 + else if (ip_conntrack_expect_related(exp) != 0) {
411 + ip_conntrack_expect_free(exp);
414 + } else if (type == LOOK_UP) {
416 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
418 + /* update the talk info */
419 + exp_talk_port = addr->ta_port;
421 + /* expect callee client -> caller client connection */
422 + exp->tuple = ((struct ip_conntrack_tuple)
423 + { { ct->tuplehash[!dir].tuple.src.ip,
428 + exp->mask = ((struct ip_conntrack_tuple)
429 + { { 0xFFFFFFFF, { 0 } },
430 + { 0xFFFFFFFF, { 0xFFFF }, 0xFF }});
431 + exp->expectfn = NULL;
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));
441 + if (ip_nat_talk_resp_hook)
442 + ret = ip_nat_talk_resp_hook(pskb, exp, type, answer,
444 + else if (ip_conntrack_expect_related(exp) != 0) {
445 + ip_conntrack_expect_free(exp);
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,
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);
469 + DEBUGP("ip_ct_talk_help: help entered\n");
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);
478 + /* Not whole UDP header? */
479 + uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
480 + sizeof(_udph), &_udph);
482 + DEBUGP("ip_ct_talk_help: short for udph\n");
486 + udplen = (*pskb)->len - (*pskb)->nh.iph->ihl*4;
487 + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(_udph);
488 + if (dataoff >= (*pskb)->len)
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);
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));
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);
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);
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
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
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));
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));
561 + UNLOCK_BH(&talk_buffer_lock);
565 +static int lookup_help(struct sk_buff **pskb,
566 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
568 + return talk_help(pskb, ct, ctinfo, TALK_PORT, LOOK_UP);
571 +static int lookup_nhelp(struct sk_buff **pskb,
572 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
574 + return talk_help(pskb, ct, ctinfo, NTALK_PORT, LOOK_UP);
577 +static struct ip_conntrack_helper lookup_helpers[2] = {
579 + .name = "talk-lookup",
583 + .src.u.udp.port = __constant_htons(TALK_PORT),
584 + .dst.protonum = IPPROTO_UDP,
587 + .src.u.udp.port = 0xffff,
588 + .dst.protonum = 0xff,
590 + .help = &lookup_help,
593 + .name = "ntalk-lookup",
597 + .src.u.udp.port = __constant_htons(NTALK_PORT),
598 + .dst.protonum = IPPROTO_UDP,
601 + .src.u.udp.port = 0xffff,
602 + .dst.protonum = 0xff,
604 + .help = &lookup_nhelp,
608 +void ip_ct_talk_expect(struct ip_conntrack *ct,
609 + struct ip_conntrack_expect *exp)
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);
617 +void ip_ct_ntalk_expect(struct ip_conntrack *ct,
618 + struct ip_conntrack_expect *exp)
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);
626 +static int help(struct sk_buff **pskb,
627 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
629 + return talk_help(pskb, ct, ctinfo, TALK_PORT, ANNOUNCE);
632 +static int nhelp(struct sk_buff **pskb,
633 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
635 + return talk_help(pskb, ct, ctinfo, NTALK_PORT, ANNOUNCE);
638 +static struct ip_conntrack_helper talk_helpers[2] = {
644 + .timeout = 4 * 60, /* 4 minutes */
646 + .src.u.udp.port = __constant_htons(TALK_PORT),
647 + .dst.protonum = IPPROTO_UDP,
650 + .src.u.udp.port = 0xffff,
651 + .dst.protonum = 0xff,
659 + .timeout = 4 * 60, /* 4 minutes */
661 + .src.u.udp.port = __constant_htons(NTALK_PORT),
662 + .dst.protonum = IPPROTO_UDP,
665 + .src.u.udp.port = 0xffff,
666 + .dst.protonum = IPPROTO_UDP,
671 +static int __init init(void)
674 + ip_conntrack_helper_register(&talk_helpers[0]);
675 + if (ntalk > 0 || ntalk2 > 0)
676 + ip_conntrack_helper_register(&talk_helpers[1]);
681 +static void __exit fini(void)
684 + ip_conntrack_helper_unregister(&talk_helpers[0]);
685 + if (ntalk > 0 || ntalk2 > 0)
686 + ip_conntrack_helper_unregister(&talk_helpers[1]);
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
696 + * talk extension for UDP NAT alteration.
697 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
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
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>
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>
726 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
727 +MODULE_DESCRIPTION("talk network address translation module");
730 +#define DEBUGP printk
731 +#define IP_NAT_TALK_DEBUG
733 +#define DEBUGP(format, args...)
737 +nat_talk_expect(struct ip_conntrack *ct,
738 + struct ip_conntrack_expect *exp)
740 + ip_nat_follow_master(ct, exp);
741 + ip_ct_talk_expect(ct, exp);
745 +nat_ntalk_expect(struct ip_conntrack *ct,
746 + struct ip_conntrack_expect *exp)
748 + ip_nat_follow_master(ct, exp);
749 + ip_ct_ntalk_expect(ct, exp);
753 +mangle_packet(struct sk_buff **pskb,
754 + struct ip_conntrack *ct,
757 + struct talk_addr *addr,
758 + struct talk_addr *ctl_addr)
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;
764 + /* Fortunately talk sends a structure with the address and
765 + port in it. The size of the packet won't change. */
767 + if (ctl_addr == NULL) {
769 + if (addr->ta_addr == INADDR_ANY)
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;
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;
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;
797 + /* Fix checksums */
798 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
800 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
801 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
803 + ip_send_check(iph);
807 +static unsigned int talk_help_msg(struct sk_buff **pskb,
808 + struct ip_conntrack *ct,
810 + struct talk_addr *addr,
811 + struct talk_addr *ctl_addr)
816 + unsigned int verdict = NF_ACCEPT;
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),
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));
830 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
836 +static unsigned int talk_help_response(struct sk_buff **pskb,
837 + struct ip_conntrack_expect *exp,
840 + struct talk_addr *addr)
842 + struct ip_conntrack *ct = exp->master;
844 + u_int16_t port, *pport, *tport;
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);
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");
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
861 + if (type == LOOK_UP) {
862 + pport = &exp->saved_proto.tcp.port;
863 + tport = &exp->tuple.dst.u.tcp.port;
865 + pport = &exp->saved_proto.udp.port;
866 + tport = &exp->tuple.dst.u.udp.port;
871 + exp->tuple.dst.ip = newip;
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;
880 + /* Try to get same port: if not, try to change it. */
881 + for (port = ntohs(*pport); port != 0; port++) {
882 + *tport = htons(port);
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);
891 + ip_conntrack_expect_free(exp);
895 + if (!mangle_packet(pskb, ct, newip, htons(port), addr, NULL)) {
896 + ip_conntrack_unexpect_related(exp);
902 +static int __init init(void)
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;
911 +static void __exit fini(void)
913 + ip_nat_talk_resp_hook = NULL;
914 + ip_nat_talk_msg_hook = NULL;
915 + /* Make sure noone calls it, meanwhile */