123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /* IRC extension for TCP NAT alteration.
- *
- * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
- * (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
- * based on a copy of RR's ip_nat_ftp.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/tcp.h>
- #include <linux/kernel.h>
- #include <net/netfilter/nf_nat.h>
- #include <net/netfilter/nf_nat_helper.h>
- #include <net/netfilter/nf_nat_rule.h>
- #include <net/netfilter/nf_conntrack_helper.h>
- #include <net/netfilter/nf_conntrack_expect.h>
- #include <linux/netfilter/nf_conntrack_irc.h>
- #if 0
- #define DEBUGP printk
- #else
- #define DEBUGP(format, args...)
- #endif
- MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
- MODULE_DESCRIPTION("IRC (DCC) NAT helper");
- MODULE_LICENSE("GPL");
- MODULE_ALIAS("ip_nat_irc");
- static unsigned int help(struct sk_buff **pskb,
- enum ip_conntrack_info ctinfo,
- unsigned int matchoff,
- unsigned int matchlen,
- struct nf_conntrack_expect *exp)
- {
- char buffer[sizeof("4294967296 65635")];
- u_int32_t ip;
- u_int16_t port;
- unsigned int ret;
- DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
- expect->seq, exp_irc_info->len, ntohl(tcph->seq));
- /* Reply comes from server. */
- exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
- exp->dir = IP_CT_DIR_REPLY;
- exp->expectfn = nf_nat_follow_master;
- /* Try to get same port: if not, try to change it. */
- for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
- exp->tuple.dst.u.tcp.port = htons(port);
- if (nf_conntrack_expect_related(exp) == 0)
- break;
- }
- if (port == 0)
- return NF_DROP;
- ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
- sprintf(buffer, "%u %u", ip, port);
- DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
- buffer, NIPQUAD(ip), port);
- ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
- matchoff, matchlen, buffer,
- strlen(buffer));
- if (ret != NF_ACCEPT)
- nf_conntrack_unexpect_related(exp);
- return ret;
- }
- static void __exit nf_nat_irc_fini(void)
- {
- rcu_assign_pointer(nf_nat_irc_hook, NULL);
- synchronize_rcu();
- }
- static int __init nf_nat_irc_init(void)
- {
- BUG_ON(rcu_dereference(nf_nat_irc_hook));
- rcu_assign_pointer(nf_nat_irc_hook, help);
- return 0;
- }
- /* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
- static int warn_set(const char *val, struct kernel_param *kp)
- {
- printk(KERN_INFO KBUILD_MODNAME
- ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
- return 0;
- }
- module_param_call(ports, warn_set, NULL, NULL, 0);
- module_init(nf_nat_irc_init);
- module_exit(nf_nat_irc_fini);
|