summaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_masq_irc.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-03 01:22:27 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-03 01:22:27 +0000
commitf9bbe9da79dbc8557c74efeb158b431cd67ace52 (patch)
tree3220d014a35f9d88a48668a1468524e988daebff /net/ipv4/ip_masq_irc.c
parent3d697109c1ff85ef563aec3d5e113ef225ed2792 (diff)
Upgrade to 2.1.73.
Diffstat (limited to 'net/ipv4/ip_masq_irc.c')
-rw-r--r--net/ipv4/ip_masq_irc.c366
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;