root/net/ipv4/ip_masq_irc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. masq_irc_init_1
  2. masq_irc_done_1
  3. masq_irc_out
  4. ip_masq_irc_init
  5. ip_masq_irc_done
  6. init_module
  7. cleanup_module

   1 /*
   2  *              IP_MASQ_IRC irc masquerading module
   3  *
   4  *
   5  * Version:     @(#)ip_masq_irc.c 0.01   03/20/96
   6  *
   7  * Author:      Juan Jose Ciarlante
   8  *              
   9  *
  10  * Fixes:
  11  *      - set NO_DADDR flag in ip_masq_new().
  12  *
  13  * FIXME:
  14  *      - detect also previous "PRIVMSG" string ?.
  15  *
  16  *      This program is free software; you can redistribute it and/or
  17  *      modify it under the terms of the GNU General Public License
  18  *      as published by the Free Software Foundation; either version
  19  *      2 of the License, or (at your option) any later version.
  20  *      
  21  */
  22 
  23 #include <linux/module.h>
  24 
  25 #include <linux/types.h>
  26 #include <linux/kernel.h>
  27 #include <asm/system.h>
  28 #include <linux/skbuff.h>
  29 #include <linux/in.h>
  30 #include <linux/ip.h>
  31 #include <net/protocol.h>
  32 #include <net/tcp.h>
  33 #include <net/ip_masq.h>
  34 
  35 #define DEBUG_CONFIG_IP_MASQ_IRC 0
  36 
  37 static int
  38 masq_irc_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40         MOD_INC_USE_COUNT;
  41         return 0;
  42 }
  43 
  44 static int
  45 masq_irc_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47         MOD_DEC_USE_COUNT;
  48         return 0;
  49 }
  50 
  51 int
  52 masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         struct sk_buff *skb;
  55         struct iphdr *iph;
  56         struct tcphdr *th;
  57         char *data, *data_limit;
  58         __u32 s_addr;
  59         __u16 s_port;
  60         struct ip_masq *n_ms;
  61         char buf[20];           /* "m_addr m_port" (dec base)*/
  62         unsigned buf_len;
  63         int diff;
  64         int xtra_args = 0;      /* extra int args wanted after addr */
  65         char *dcc_p, *addr_beg_p, *addr_end_p;
  66 
  67         skb = *skb_p;
  68         iph = skb->h.iph;
  69         th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
  70         data = (char *)&th[1];
  71 
  72         /*
  73          *      Hunt irc DCC string, the _shortest_:
  74          *
  75          *      strlen("DCC CHAT chat AAAAAAAA P\x01\n")=26
  76          *      strlen("DCC SEND F AAAAAAAA P S\x01\n")=25
  77          *              AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits)
  78          *              P:         bound port (min 1 d )
  79          *              F:         filename   (min 1 d )
  80          *              S:         size       (min 1 d ) 
  81          *              0x01, \n:  terminators
  82          */
  83 
  84         data_limit = skb->h.raw + skb->len;
  85         
  86         while (data < (data_limit - 25) )
  87         {
  88                 if (memcmp(data,"DCC ",4))  {
  89                         data ++;
  90                         continue;
  91                 }
  92                 
  93                 dcc_p = data;
  94                 data += 4;     /* point to DCC cmd */
  95                 
  96                 if (memcmp(data, "CHAT ", 5) == 0 ||
  97                     memcmp(data, "SEND ", 5) == 0)
  98                 {
  99                         /*
 100                          *      extra arg (file_size) req. for "SEND"
 101                          */
 102                         
 103                         if (*data == 'S') xtra_args++;
 104                         data += 5;
 105                 }
 106                 else
 107                         continue;
 108 
 109                 /*
 110                  *      skip next string.
 111                  */
 112                 
 113                 while( *data++ != ' ')
 114                         
 115                         /*
 116                          *      must still parse, at least, "AAAAAAAA P\x01\n",
 117                          *      12 bytes left.
 118                          */
 119                         if (data > (data_limit-12)) return 0;
 120 
 121                 
 122                 addr_beg_p = data;
 123                 
 124                 /*
 125                  *      client bound address in dec base
 126                  */
 127                 
 128                 s_addr = simple_strtoul(data,&data,10);
 129                 if (*data++ !=' ')
 130                         continue;
 131 
 132                 /*
 133                  *      client bound port in dec base
 134                  */
 135                 
 136                 s_port = simple_strtoul(data,&data,10);
 137                 addr_end_p = data;
 138                 
 139                 /*
 140                  *      should check args consistency?
 141                  */
 142                 
 143                 while(xtra_args) {
 144                         if (*data != ' ')
 145                                 break;
 146                         data++;
 147                         simple_strtoul(data,&data,10);
 148                         xtra_args--;
 149                 }
 150                 
 151                 if (xtra_args != 0) continue;
 152                 
 153                 /*
 154                  *      terminators.
 155                  */
 156                 
 157                 if (data[0] != 0x01)
 158                         continue;
 159                 if (data[1]!='\r' && data[1]!='\n')
 160                         continue;
 161                 
 162                 /*
 163                  *      Now create an masquerade entry for it
 164                  *      must set NO_DPORT and NO_DADDR because
 165                  *      connection is requested by another client.
 166                  */
 167                 
 168                 n_ms = ip_masq_new(dev, IPPROTO_TCP,
 169                                    htonl(s_addr),htons(s_port),
 170                                    0, 0,
 171                                    IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR
 172                                    );
 173                 if (n_ms==NULL)
 174                         return 0;
 175 
 176                 ip_masq_set_expire(n_ms, ip_masq_expire->tcp_fin_timeout);
 177                 
 178                 /*
 179                  * Replace the old "address port" with the new one
 180                  */
 181                 
 182                 buf_len = sprintf(buf,"%lu %u",
 183                         ntohl(n_ms->maddr),ntohs(n_ms->mport));
 184                 
 185                 /*
 186                  * Calculate required delta-offset to keep TCP happy
 187                  */
 188                 
 189                 diff = buf_len - (addr_end_p-addr_beg_p);
 190 
 191 #if DEBUG_CONFIG_IP_MASQ_IRC
 192                 *addr_beg_p = '\0';
 193                 printk("masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
 194 #endif  
 195                 /*
 196                  *      No shift.
 197                  */
 198                  
 199                 if (diff==0) 
 200                 {
 201                         /*
 202                          * simple case, just copy.
 203                          */
 204                         memcpy(addr_beg_p,buf,buf_len);
 205                         return 0;
 206                 }
 207 
 208                 *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
 209                                              addr_beg_p, addr_end_p-addr_beg_p,
 210                                              buf, buf_len);
 211                 return diff;
 212         }
 213         return 0;
 214 
 215 }
 216 
 217 /*
 218  *      Main irc object
 219  *      You need 1 object per port in case you need
 220  *      to offer also other used irc ports (6665,6666,etc),
 221  *      they will share methods but they need own space for
 222  *      data. 
 223  */
 224 
 225 struct ip_masq_app ip_masq_irc = {
 226         NULL,                   /* next */
 227         "irc",                  /* name */
 228         0,                      /* type */
 229         0,                      /* n_attach */
 230         masq_irc_init_1,        /* init_1 */
 231         masq_irc_done_1,        /* done_1 */
 232         masq_irc_out,           /* pkt_out */
 233         NULL                    /* pkt_in */
 234 };
 235 
 236 /*
 237  *      ip_masq_irc initialization
 238  */
 239 
 240 int ip_masq_irc_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         return register_ip_masq_app(&ip_masq_irc, IPPROTO_TCP, 6667);
 243 }
 244 
 245 /*
 246  *      ip_masq_irc fin.
 247  */
 248 
 249 int ip_masq_irc_done(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 250 {
 251         return unregister_ip_masq_app(&ip_masq_irc);
 252 }
 253 
 254 #ifdef MODULE
 255 
 256 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258         if (ip_masq_irc_init() != 0)
 259                 return -EIO;
 260         register_symtab(NULL);
 261         return 0;
 262 }
 263 
 264 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 265 {
 266         if (ip_masq_irc_done() != 0)
 267                 printk("ip_masq_irc: can't remove module");
 268 }
 269 
 270 #endif /* MODULE */

/* [previous][next][first][last][top][bottom][index][help] */