diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-03 01:22:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-03 01:22:27 +0000 |
commit | f9bbe9da79dbc8557c74efeb158b431cd67ace52 (patch) | |
tree | 3220d014a35f9d88a48668a1468524e988daebff /net/ipv4/ip_masq_irc.c | |
parent | 3d697109c1ff85ef563aec3d5e113ef225ed2792 (diff) |
Upgrade to 2.1.73.
Diffstat (limited to 'net/ipv4/ip_masq_irc.c')
-rw-r--r-- | net/ipv4/ip_masq_irc.c | 366 |
1 files changed, 231 insertions, 135 deletions
diff --git a/net/ipv4/ip_masq_irc.c b/net/ipv4/ip_masq_irc.c index b2e325ce6..6668efdaf 100644 --- a/net/ipv4/ip_masq_irc.c +++ b/net/ipv4/ip_masq_irc.c @@ -2,13 +2,22 @@ * IP_MASQ_IRC irc masquerading module * * - * Version: @(#)ip_masq_irc.c 0.01 03/20/96 + * Version: @(#)ip_masq_irc.c 0.03 97/11/30 * * Author: Juan Jose Ciarlante - * - * + * + * Additions: + * - recognize a few non-irc-II DCC requests (Oliver Wagner) + * DCC MOVE (AmIRC/DCC.MOVE; SEND with resuming) + * DCC SCHAT (AmIRC IDEA encrypted CHAT) + * DCC TSEND (AmIRC/PIRCH SEND without ACKs) * Fixes: - * - set NO_DADDR flag in ip_masq_new(). + * Juan Jose Ciarlante : set NO_DADDR flag in ip_masq_new() + * Nigel Metheringham : Added multiple port support + * Juan Jose Ciarlante : litl bits for 2.1 + * Oliver Wagner : more IRC cmds processing + * <winmute@lucifer.gv.kotnet.org> + * Juan Jose Ciarlante : put new ms entry to listen() * * FIXME: * - detect also previous "PRIVMSG" string ?. @@ -17,7 +26,18 @@ * 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. - * + * + * Multiple Port Support + * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12) + * with the port numbers being defined at module load time. The module + * uses the symbol "ports" to define a list of monitored ports, which can + * be specified on the insmod command line as + * ports=x1,x2,x3... + * where x[n] are integer port numbers. This option can be put into + * /etc/conf.modules (or /etc/modules.conf depending on your config) + * where modload will pick it up should you use modload to load your + * modules. + * */ #include <linux/config.h> @@ -34,7 +54,43 @@ #include <net/tcp.h> #include <net/ip_masq.h> -#define DEBUG_CONFIG_IP_MASQ_IRC 0 + +/* + * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper + * First port is set to the default port. + */ +int ports[MAX_MASQ_APP_PORTS] = {6667}; /* I rely on the trailing items being set to zero */ +struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS]; +/* + * Debug level + */ +static int debug=0; + +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i"); +MODULE_PARM(debug, "i"); + + +/* + * List of supported DCC protocols + */ + +#define NUM_DCCPROTO 5 + +struct dccproto +{ + char *match; + int matchlen; + int xtra_args; +}; + +struct dccproto dccprotos[NUM_DCCPROTO] = { + { "SEND ", 5, 1 }, + { "CHAT ", 5, 0, }, + { "MOVE ", 5, 1 }, + { "TSEND ", 6, 1, }, + { "SCHAT ", 6, 0, } +}; +#define MAXMATCHLEN 6 static int masq_irc_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms) @@ -72,145 +128,148 @@ masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb data = (char *)&th[1]; /* - * Hunt irc DCC string, the _shortest_: - * - * strlen("DCC CHAT chat AAAAAAAA P\x01\n")=26 - * strlen("DCC SEND F AAAAAAAA P S\x01\n")=25 - * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits) - * P: bound port (min 1 d ) - * F: filename (min 1 d ) - * S: size (min 1 d ) - * 0x01, \n: terminators + * Hunt irc DCC string, the _shortest_: + * + * strlen("DCC CHAT chat AAAAAAAA P\x01\n")=26 + * strlen("DCC SCHAT chat AAAAAAAA P\x01\n")=27 + * strlen("DCC SEND F AAAAAAAA P S\x01\n")=25 + * strlen("DCC MOVE F AAAAAAAA P S\x01\n")=25 + * strlen("DCC TSEND F AAAAAAAA P S\x01\n")=26 + * strlen("DCC MOVE F AAAAAAAA P S\x01\n")=25 + * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits) + * P: bound port (min 1 d ) + * F: filename (min 1 d ) + * S: size (min 1 d ) + * 0x01, \n: terminators */ data_limit = skb->h.raw + skb->len; - - while (data < (data_limit - 25) ) + + while (data < (data_limit - ( 21 + MAXMATCHLEN ) ) ) { + int i; if (memcmp(data,"DCC ",4)) { data ++; continue; } - dcc_p = data; + dcc_p = data; data += 4; /* point to DCC cmd */ - if (memcmp(data, "CHAT ", 5) == 0 || - memcmp(data, "SEND ", 5) == 0) - { - /* - * extra arg (file_size) req. for "SEND" - */ - - if (*data == 'S') xtra_args++; - data += 5; - } - else - continue; - - /* - * skip next string. - */ - - while( *data++ != ' ') - - /* - * must still parse, at least, "AAAAAAAA P\x01\n", - * 12 bytes left. - */ - if (data > (data_limit-12)) return 0; - - - addr_beg_p = data; - - /* - * client bound address in dec base - */ - - s_addr = simple_strtoul(data,&data,10); - if (*data++ !=' ') - continue; - - /* - * client bound port in dec base - */ - - s_port = simple_strtoul(data,&data,10); - addr_end_p = data; - - /* - * should check args consistency? - */ - - while(xtra_args) { - if (*data != ' ') - break; - data++; - simple_strtoul(data,&data,10); - xtra_args--; - } - - if (xtra_args != 0) continue; - - /* - * terminators. - */ - - if (data[0] != 0x01) - continue; - if (data[1]!='\r' && data[1]!='\n') - continue; - - /* - * Now create an masquerade entry for it - * must set NO_DPORT and NO_DADDR because - * connection is requested by another client. - */ - - n_ms = ip_masq_new(maddr, IPPROTO_TCP, - htonl(s_addr),htons(s_port), - 0, 0, - IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR - ); - if (n_ms==NULL) - return 0; - - ip_masq_set_expire(n_ms, ip_masq_expire->tcp_fin_timeout); - - /* - * Replace the old "address port" with the new one - */ - - buf_len = sprintf(buf,"%lu %u", - ntohl(n_ms->maddr),ntohs(n_ms->mport)); - - /* - * Calculate required delta-offset to keep TCP happy - */ - - diff = buf_len - (addr_end_p-addr_beg_p); - -#if DEBUG_CONFIG_IP_MASQ_IRC - *addr_beg_p = '\0'; - printk("masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff); -#endif - /* - * No shift. - */ - - if (diff==0) + for(i=0; i<NUM_DCCPROTO; i++) { /* - * simple case, just copy. - */ - memcpy(addr_beg_p,buf,buf_len); - return 0; - } - - *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, - addr_beg_p, addr_end_p-addr_beg_p, - buf, buf_len); - return diff; + * go through the table and hunt a match string + */ + + if( memcmp(data, dccprotos[i].match, dccprotos[i].matchlen ) == 0 ) + { + xtra_args = dccprotos[i].xtra_args; + data += dccprotos[i].matchlen; + + /* + * skip next string. + */ + + while( *data++ != ' ') + + /* + * must still parse, at least, "AAAAAAAA P\x01\n", + * 12 bytes left. + */ + if (data > (data_limit-12)) return 0; + + + addr_beg_p = data; + + /* + * client bound address in dec base + */ + + s_addr = simple_strtoul(data,&data,10); + if (*data++ !=' ') + continue; + + /* + * client bound port in dec base + */ + + s_port = simple_strtoul(data,&data,10); + addr_end_p = data; + + /* + * should check args consistency? + */ + + while(xtra_args) { + if (*data != ' ') + break; + data++; + simple_strtoul(data,&data,10); + xtra_args--; + } + + if (xtra_args != 0) continue; + + /* + * terminators. + */ + + if (data[0] != 0x01) + continue; + if (data[1]!='\r' && data[1]!='\n') + continue; + + /* + * Now create an masquerade entry for it + * must set NO_DPORT and NO_DADDR because + * connection is requested by another client. + */ + + n_ms = ip_masq_new(IPPROTO_TCP, + maddr, 0, + htonl(s_addr),htons(s_port), + 0, 0, + IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR); + if (n_ms==NULL) + return 0; + + /* + * Replace the old "address port" with the new one + */ + + buf_len = sprintf(buf,"%lu %u", + ntohl(n_ms->maddr),ntohs(n_ms->mport)); + + /* + * Calculate required delta-offset to keep TCP happy + */ + + diff = buf_len - (addr_end_p-addr_beg_p); + + *addr_beg_p = '\0'; + IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff); + + /* + * No shift. + */ + + if (diff==0) { + /* + * simple case, just copy. + */ + memcpy(addr_beg_p,buf,buf_len); + } else { + + *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, + addr_beg_p, addr_end_p-addr_beg_p, + buf, buf_len); + } + ip_masq_listen(n_ms); + ip_masq_put(n_ms); + return diff; + } + } } return 0; @@ -221,7 +280,7 @@ masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb * You need 1 object per port in case you need * to offer also other used irc ports (6665,6666,etc), * they will share methods but they need own space for - * data. + * data. */ struct ip_masq_app ip_masq_irc = { @@ -241,7 +300,28 @@ struct ip_masq_app ip_masq_irc = { __initfunc(int ip_masq_irc_init(void)) { - return register_ip_masq_app(&ip_masq_irc, IPPROTO_TCP, 6667); + int i, j; + + for (i=0; (i<MAX_MASQ_APP_PORTS); i++) { + if (ports[i]) { + if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app), + GFP_KERNEL)) == NULL) + return -ENOMEM; + memcpy(masq_incarnations[i], &ip_masq_irc, sizeof(struct ip_masq_app)); + if ((j = register_ip_masq_app(masq_incarnations[i], + IPPROTO_TCP, + ports[i]))) { + return j; + } + IP_MASQ_DEBUG(1-debug, + "Irc: loaded support on port[%d] = %d\n", + i, ports[i]); + } else { + /* To be safe, force the incarnation table entry to NULL */ + masq_incarnations[i] = NULL; + } + } + return 0; } /* @@ -250,9 +330,25 @@ __initfunc(int ip_masq_irc_init(void)) int ip_masq_irc_done(void) { - return unregister_ip_masq_app(&ip_masq_irc); + int i, j, k; + + k=0; + for (i=0; (i<MAX_MASQ_APP_PORTS); i++) { + if (masq_incarnations[i]) { + if ((j = unregister_ip_masq_app(masq_incarnations[i]))) { + k = j; + } else { + kfree(masq_incarnations[i]); + masq_incarnations[i] = NULL; + IP_MASQ_DEBUG(1-debug, "Irc: unloaded support on port[%d] = %d\n", + i, ports[i]); + } + } + } + return k; } + #ifdef MODULE EXPORT_NO_SYMBOLS; |