nf_conntrack_irc.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /* IRC extension for IP connection tracking, Version 1.21
  2. * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
  3. * based on RR's ip_conntrack_ftp.c
  4. * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/moduleparam.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/in.h>
  15. #include <linux/ip.h>
  16. #include <linux/tcp.h>
  17. #include <linux/netfilter.h>
  18. #include <linux/slab.h>
  19. #include <net/netfilter/nf_conntrack.h>
  20. #include <net/netfilter/nf_conntrack_expect.h>
  21. #include <net/netfilter/nf_conntrack_helper.h>
  22. #include <linux/netfilter/nf_conntrack_irc.h>
  23. #define MAX_PORTS 8
  24. static unsigned short ports[MAX_PORTS];
  25. static unsigned int ports_c;
  26. static unsigned int max_dcc_channels = 8;
  27. static unsigned int dcc_timeout __read_mostly = 300;
  28. /* This is slow, but it's simple. --RR */
  29. static char *irc_buffer;
  30. static DEFINE_SPINLOCK(irc_buffer_lock);
  31. unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
  32. enum ip_conntrack_info ctinfo,
  33. unsigned int protoff,
  34. unsigned int matchoff,
  35. unsigned int matchlen,
  36. struct nf_conntrack_expect *exp) __read_mostly;
  37. EXPORT_SYMBOL_GPL(nf_nat_irc_hook);
  38. MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  39. MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
  40. MODULE_LICENSE("GPL");
  41. MODULE_ALIAS("ip_conntrack_irc");
  42. MODULE_ALIAS_NFCT_HELPER("irc");
  43. module_param_array(ports, ushort, &ports_c, 0400);
  44. MODULE_PARM_DESC(ports, "port numbers of IRC servers");
  45. module_param(max_dcc_channels, uint, 0400);
  46. MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
  47. "IRC session");
  48. module_param(dcc_timeout, uint, 0400);
  49. MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
  50. static const char *const dccprotos[] = {
  51. "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
  52. };
  53. #define MINMATCHLEN 5
  54. /* tries to get the ip_addr and port out of a dcc command
  55. * return value: -1 on failure, 0 on success
  56. * data pointer to first byte of DCC command data
  57. * data_end pointer to last byte of dcc command data
  58. * ip returns parsed ip of dcc command
  59. * port returns parsed port of dcc command
  60. * ad_beg_p returns pointer to first byte of addr data
  61. * ad_end_p returns pointer to last byte of addr data
  62. */
  63. static int parse_dcc(char *data, const char *data_end, __be32 *ip,
  64. u_int16_t *port, char **ad_beg_p, char **ad_end_p)
  65. {
  66. char *tmp;
  67. /* at least 12: "AAAAAAAA P\1\n" */
  68. while (*data++ != ' ')
  69. if (data > data_end - 12)
  70. return -1;
  71. /* Make sure we have a newline character within the packet boundaries
  72. * because simple_strtoul parses until the first invalid character. */
  73. for (tmp = data; tmp <= data_end; tmp++)
  74. if (*tmp == '\n')
  75. break;
  76. if (tmp > data_end || *tmp != '\n')
  77. return -1;
  78. *ad_beg_p = data;
  79. *ip = cpu_to_be32(simple_strtoul(data, &data, 10));
  80. /* skip blanks between ip and port */
  81. while (*data == ' ') {
  82. if (data >= data_end)
  83. return -1;
  84. data++;
  85. }
  86. *port = simple_strtoul(data, &data, 10);
  87. *ad_end_p = data;
  88. return 0;
  89. }
  90. static int help(struct sk_buff *skb, unsigned int protoff,
  91. struct nf_conn *ct, enum ip_conntrack_info ctinfo)
  92. {
  93. unsigned int dataoff;
  94. const struct iphdr *iph;
  95. const struct tcphdr *th;
  96. struct tcphdr _tcph;
  97. const char *data_limit;
  98. char *data, *ib_ptr;
  99. int dir = CTINFO2DIR(ctinfo);
  100. struct nf_conntrack_expect *exp;
  101. struct nf_conntrack_tuple *tuple;
  102. __be32 dcc_ip;
  103. u_int16_t dcc_port;
  104. __be16 port;
  105. int i, ret = NF_ACCEPT;
  106. char *addr_beg_p, *addr_end_p;
  107. typeof(nf_nat_irc_hook) nf_nat_irc;
  108. /* If packet is coming from IRC server */
  109. if (dir == IP_CT_DIR_REPLY)
  110. return NF_ACCEPT;
  111. /* Until there's been traffic both ways, don't look in packets. */
  112. if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
  113. return NF_ACCEPT;
  114. /* Not a full tcp header? */
  115. th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
  116. if (th == NULL)
  117. return NF_ACCEPT;
  118. /* No data? */
  119. dataoff = protoff + th->doff*4;
  120. if (dataoff >= skb->len)
  121. return NF_ACCEPT;
  122. spin_lock_bh(&irc_buffer_lock);
  123. ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff,
  124. irc_buffer);
  125. BUG_ON(ib_ptr == NULL);
  126. data = ib_ptr;
  127. data_limit = ib_ptr + skb->len - dataoff;
  128. /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
  129. * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
  130. while (data < data_limit - (19 + MINMATCHLEN)) {
  131. if (memcmp(data, "\1DCC ", 5)) {
  132. data++;
  133. continue;
  134. }
  135. data += 5;
  136. /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
  137. iph = ip_hdr(skb);
  138. pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
  139. &iph->saddr, ntohs(th->source),
  140. &iph->daddr, ntohs(th->dest));
  141. for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
  142. if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
  143. /* no match */
  144. continue;
  145. }
  146. data += strlen(dccprotos[i]);
  147. pr_debug("DCC %s detected\n", dccprotos[i]);
  148. /* we have at least
  149. * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
  150. * data left (== 14/13 bytes) */
  151. if (parse_dcc(data, data_limit, &dcc_ip,
  152. &dcc_port, &addr_beg_p, &addr_end_p)) {
  153. pr_debug("unable to parse dcc command\n");
  154. continue;
  155. }
  156. pr_debug("DCC bound ip/port: %pI4:%u\n",
  157. &dcc_ip, dcc_port);
  158. /* dcc_ip can be the internal OR external (NAT'ed) IP */
  159. tuple = &ct->tuplehash[dir].tuple;
  160. if (tuple->src.u3.ip != dcc_ip &&
  161. tuple->dst.u3.ip != dcc_ip) {
  162. net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
  163. &tuple->src.u3.ip,
  164. &dcc_ip, dcc_port);
  165. continue;
  166. }
  167. exp = nf_ct_expect_alloc(ct);
  168. if (exp == NULL) {
  169. nf_ct_helper_log(skb, ct,
  170. "cannot alloc expectation");
  171. ret = NF_DROP;
  172. goto out;
  173. }
  174. tuple = &ct->tuplehash[!dir].tuple;
  175. port = htons(dcc_port);
  176. nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
  177. tuple->src.l3num,
  178. NULL, &tuple->dst.u3,
  179. IPPROTO_TCP, NULL, &port);
  180. nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
  181. if (nf_nat_irc && ct->status & IPS_NAT_MASK)
  182. ret = nf_nat_irc(skb, ctinfo, protoff,
  183. addr_beg_p - ib_ptr,
  184. addr_end_p - addr_beg_p,
  185. exp);
  186. else if (nf_ct_expect_related(exp) != 0) {
  187. nf_ct_helper_log(skb, ct,
  188. "cannot add expectation");
  189. ret = NF_DROP;
  190. }
  191. nf_ct_expect_put(exp);
  192. goto out;
  193. }
  194. }
  195. out:
  196. spin_unlock_bh(&irc_buffer_lock);
  197. return ret;
  198. }
  199. static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
  200. static struct nf_conntrack_expect_policy irc_exp_policy;
  201. static void nf_conntrack_irc_fini(void);
  202. static int __init nf_conntrack_irc_init(void)
  203. {
  204. int i, ret;
  205. if (max_dcc_channels < 1) {
  206. printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n");
  207. return -EINVAL;
  208. }
  209. irc_exp_policy.max_expected = max_dcc_channels;
  210. irc_exp_policy.timeout = dcc_timeout;
  211. irc_buffer = kmalloc(65536, GFP_KERNEL);
  212. if (!irc_buffer)
  213. return -ENOMEM;
  214. /* If no port given, default to standard irc port */
  215. if (ports_c == 0)
  216. ports[ports_c++] = IRC_PORT;
  217. for (i = 0; i < ports_c; i++) {
  218. irc[i].tuple.src.l3num = AF_INET;
  219. irc[i].tuple.src.u.tcp.port = htons(ports[i]);
  220. irc[i].tuple.dst.protonum = IPPROTO_TCP;
  221. irc[i].expect_policy = &irc_exp_policy;
  222. irc[i].me = THIS_MODULE;
  223. irc[i].help = help;
  224. if (ports[i] == IRC_PORT)
  225. sprintf(irc[i].name, "irc");
  226. else
  227. sprintf(irc[i].name, "irc-%u", i);
  228. ret = nf_conntrack_helper_register(&irc[i]);
  229. if (ret) {
  230. printk(KERN_ERR "nf_ct_irc: failed to register helper "
  231. "for pf: %u port: %u\n",
  232. irc[i].tuple.src.l3num, ports[i]);
  233. nf_conntrack_irc_fini();
  234. return ret;
  235. }
  236. }
  237. return 0;
  238. }
  239. /* This function is intentionally _NOT_ defined as __exit, because
  240. * it is needed by the init function */
  241. static void nf_conntrack_irc_fini(void)
  242. {
  243. int i;
  244. for (i = 0; i < ports_c; i++)
  245. nf_conntrack_helper_unregister(&irc[i]);
  246. kfree(irc_buffer);
  247. }
  248. module_init(nf_conntrack_irc_init);
  249. module_exit(nf_conntrack_irc_fini);