nf_nat_irc.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* IRC extension for TCP NAT alteration.
  2. *
  3. * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
  4. * (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
  5. * based on a copy of RR's ip_nat_ftp.c
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version
  10. * 2 of the License, or (at your option) any later version.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/moduleparam.h>
  14. #include <linux/tcp.h>
  15. #include <linux/kernel.h>
  16. #include <net/netfilter/nf_nat.h>
  17. #include <net/netfilter/nf_nat_helper.h>
  18. #include <net/netfilter/nf_nat_rule.h>
  19. #include <net/netfilter/nf_conntrack_helper.h>
  20. #include <net/netfilter/nf_conntrack_expect.h>
  21. #include <linux/netfilter/nf_conntrack_irc.h>
  22. #if 0
  23. #define DEBUGP printk
  24. #else
  25. #define DEBUGP(format, args...)
  26. #endif
  27. MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
  28. MODULE_DESCRIPTION("IRC (DCC) NAT helper");
  29. MODULE_LICENSE("GPL");
  30. MODULE_ALIAS("ip_nat_irc");
  31. static unsigned int help(struct sk_buff **pskb,
  32. enum ip_conntrack_info ctinfo,
  33. unsigned int matchoff,
  34. unsigned int matchlen,
  35. struct nf_conntrack_expect *exp)
  36. {
  37. char buffer[sizeof("4294967296 65635")];
  38. u_int32_t ip;
  39. u_int16_t port;
  40. unsigned int ret;
  41. DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
  42. expect->seq, exp_irc_info->len, ntohl(tcph->seq));
  43. /* Reply comes from server. */
  44. exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  45. exp->dir = IP_CT_DIR_REPLY;
  46. exp->expectfn = nf_nat_follow_master;
  47. /* Try to get same port: if not, try to change it. */
  48. for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
  49. exp->tuple.dst.u.tcp.port = htons(port);
  50. if (nf_conntrack_expect_related(exp) == 0)
  51. break;
  52. }
  53. if (port == 0)
  54. return NF_DROP;
  55. ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
  56. sprintf(buffer, "%u %u", ip, port);
  57. DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
  58. buffer, NIPQUAD(ip), port);
  59. ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
  60. matchoff, matchlen, buffer,
  61. strlen(buffer));
  62. if (ret != NF_ACCEPT)
  63. nf_conntrack_unexpect_related(exp);
  64. return ret;
  65. }
  66. static void __exit nf_nat_irc_fini(void)
  67. {
  68. rcu_assign_pointer(nf_nat_irc_hook, NULL);
  69. synchronize_rcu();
  70. }
  71. static int __init nf_nat_irc_init(void)
  72. {
  73. BUG_ON(rcu_dereference(nf_nat_irc_hook));
  74. rcu_assign_pointer(nf_nat_irc_hook, help);
  75. return 0;
  76. }
  77. /* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
  78. static int warn_set(const char *val, struct kernel_param *kp)
  79. {
  80. printk(KERN_INFO KBUILD_MODNAME
  81. ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
  82. return 0;
  83. }
  84. module_param_call(ports, warn_set, NULL, NULL, 0);
  85. module_init(nf_nat_irc_init);
  86. module_exit(nf_nat_irc_fini);