linux-old/net/ipv4/ip_masq_quake.c
<<
>>
Prefs
   1/*
   2 *              IP_MASQ_QUAKE quake masquerading module
   3 *
   4 *
   5 * Version:     @(#)ip_masq_quake.c 0.02   22/02/97
   6 *
   7 * Author:      Harald Hoyer mailto:HarryH@Royal.Net
   8 *              
   9 *
  10 * Fixes: 
  11 *      Harald Hoyer            :       Unofficial Quake Specs found at 
  12 *                                 http://www.gamers.org/dEngine/quake/spec/ 
  13 *      Harald Hoyer            :       Check for QUAKE-STRING
  14 *      Juan Jose Ciarlante     :  litl bits for 2.1
  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
  24#include <linux/module.h>
  25#include <asm/system.h>
  26#include <linux/types.h>
  27#include <linux/kernel.h>
  28#include <linux/skbuff.h>
  29#include <linux/in.h>
  30#include <linux/ip.h>
  31#include <linux/init.h>
  32#include <net/protocol.h>
  33#include <net/udp.h>
  34#include <net/ip_masq.h>
  35
  36#define DEBUG_CONFIG_IP_MASQ_QUAKE 0
  37
  38typedef struct
  39{ 
  40        __u16 type;     // (Little Endian) Type of message.
  41        __u16 length;   // (Little Endian) Length of message, header included. 
  42        char  message[0];  // The contents of the message.
  43} QUAKEHEADER;
  44
  45struct quake_priv_data {
  46        /* Have we seen a client connect message */
  47        char    cl_connect;
  48};
  49
  50static int
  51masq_quake_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
  52{
  53        MOD_INC_USE_COUNT;
  54        if ((ms->app_data = kmalloc(sizeof(struct quake_priv_data),
  55                                    GFP_ATOMIC)) == NULL) 
  56                printk(KERN_INFO "Quake: No memory for application data\n");
  57        else 
  58        {
  59                struct quake_priv_data *priv = 
  60                        (struct quake_priv_data *)ms->app_data;
  61                priv->cl_connect = 0;
  62        }
  63        return 0;
  64}
  65
  66static int
  67masq_quake_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
  68{
  69        MOD_DEC_USE_COUNT;
  70        if (ms->app_data)
  71                kfree_s(ms->app_data, sizeof(struct quake_priv_data));
  72        return 0;
  73}
  74
  75int
  76masq_quake_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
  77{
  78        struct sk_buff *skb;
  79        struct iphdr *iph;
  80        struct udphdr *uh;
  81        QUAKEHEADER *qh;
  82        __u16 udp_port;
  83        char *data;
  84        unsigned char code;
  85        struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
  86        
  87        if(priv->cl_connect == -1)
  88          return 0;
  89
  90        skb = *skb_p;
  91
  92        iph = skb->nh.iph;
  93        uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
  94
  95        /* Check for lenght */
  96        if(ntohs(uh->len) < 5)
  97          return 0;
  98        
  99        qh = (QUAKEHEADER *)&uh[1];
 100
 101        if(qh->type != 0x0080)
 102          return 0;
 103
 104        
 105        code = qh->message[0];
 106
 107#if DEBUG_CONFIG_IP_MASQ_QUAKE
 108          printk("Quake_in: code = %d \n", (int)code);
 109#endif
 110
 111        switch(code) {
 112        case 0x01:
 113          /* Connection Request */
 114
 115          if(ntohs(qh->length) < 0x0c) {
 116#if DEBUG_CONFIG_IP_MASQ_QUAKE
 117            printk("Quake_in: length < 0xc \n");
 118#endif
 119            return 0;
 120          }
 121
 122          data = &qh->message[1];
 123
 124          /* Check for stomping string */
 125          if(memcmp(data,"QUAKE\0\3",7)) {
 126#if DEBUG_CONFIG_IP_MASQ_QUAKE
 127            printk("Quake_out: memcmp failed \n");
 128#endif
 129            return 0;
 130          }
 131          else {
 132            priv->cl_connect = 1;
 133#if DEBUG_CONFIG_IP_MASQ_QUAKE
 134            printk("Quake_out: memcmp ok \n");
 135#endif
 136          }
 137          break;
 138
 139        case 0x81:
 140          /* Accept Connection */
 141          if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
 142            return 0;
 143          data = &qh->message[1];
 144
 145          memcpy(&udp_port, data, 2);
 146
 147          ms->dport = htons(udp_port);
 148
 149#if DEBUG_CONFIG_IP_MASQ_QUAKE
 150          printk("Quake_in: in_rewrote UDP port %d \n", udp_port);
 151#endif
 152          priv->cl_connect = -1;
 153
 154          break;
 155        }
 156         
 157        return 0;
 158}
 159
 160int
 161masq_quake_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
 162{
 163        struct sk_buff *skb;
 164        struct iphdr *iph;
 165        struct udphdr *uh;
 166        QUAKEHEADER *qh;
 167        __u16 udp_port;
 168        char *data;
 169        unsigned char code;
 170        struct ip_masq *n_ms;
 171        struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
 172
 173        if(priv->cl_connect == -1)
 174          return 0;
 175        
 176        skb = *skb_p;
 177
 178        iph = skb->nh.iph;
 179        uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
 180
 181        /* Check for lenght */
 182        if(ntohs(uh->len) < 5)
 183          return 0;
 184        
 185        qh = (QUAKEHEADER *)&uh[1];
 186
 187#if DEBUG_CONFIG_IP_MASQ_QUAKE
 188          printk("Quake_out: qh->type = %d \n", (int)qh->type);
 189#endif
 190
 191        if(qh->type != 0x0080)
 192          return 0;
 193        
 194        code = qh->message[0];
 195
 196#if DEBUG_CONFIG_IP_MASQ_QUAKE
 197          printk("Quake_out: code = %d \n", (int)code);
 198#endif
 199
 200        switch(code) {
 201        case 0x01:
 202          /* Connection Request */
 203
 204          if(ntohs(qh->length) < 0x0c) {
 205#if DEBUG_CONFIG_IP_MASQ_QUAKE
 206            printk("Quake_out: length < 0xc \n");
 207#endif
 208            return 0;
 209          }
 210
 211          data = &qh->message[1];
 212
 213          /* Check for stomping string */
 214          if(memcmp(data,"QUAKE\0\3",7)) {
 215#if DEBUG_CONFIG_IP_MASQ_QUAKE
 216            printk("Quake_out: memcmp failed \n");
 217#endif
 218            return 0;
 219          }
 220          else {
 221            priv->cl_connect = 1;
 222#if DEBUG_CONFIG_IP_MASQ_QUAKE
 223            printk("Quake_out: memcmp ok \n");
 224#endif
 225          }
 226          break;
 227
 228        case 0x81:
 229          /* Accept Connection */
 230          if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
 231            return 0;
 232
 233          data = &qh->message[1];
 234
 235          memcpy(&udp_port, data, 2);
 236          
 237          n_ms = ip_masq_new(IPPROTO_UDP,
 238                             maddr, 0,
 239                             ms->saddr, htons(udp_port),
 240                             ms->daddr, ms->dport,
 241                             0);
 242
 243          if (n_ms==NULL)
 244            return 0;
 245
 246#if DEBUG_CONFIG_IP_MASQ_QUAKE
 247          printk("Quake_out: out_rewrote UDP port %d -> %d\n",
 248                 udp_port, ntohs(n_ms->mport));
 249#endif
 250          udp_port = ntohs(n_ms->mport);
 251          memcpy(data, &udp_port, 2);
 252
 253          ip_masq_listen(n_ms);
 254          ip_masq_control_add(n_ms, ms);
 255          ip_masq_put(n_ms);
 256
 257          break;
 258        }
 259         
 260        return 0;
 261}
 262
 263struct ip_masq_app ip_masq_quake = {
 264        NULL,                   /* next */
 265        "Quake_26",             /* name */
 266        0,                      /* type */
 267        0,                      /* n_attach */
 268        masq_quake_init_1,      /* ip_masq_init_1 */
 269        masq_quake_done_1,      /* ip_masq_done_1 */
 270        masq_quake_out,         /* pkt_out */
 271        masq_quake_in           /* pkt_in */
 272};
 273struct ip_masq_app ip_masq_quakenew = {
 274        NULL,                   /* next */
 275        "Quake_27",             /* name */
 276        0,                      /* type */
 277        0,                      /* n_attach */
 278        masq_quake_init_1,      /* ip_masq_init_1 */
 279        masq_quake_done_1,      /* ip_masq_done_1 */
 280        masq_quake_out,         /* pkt_out */
 281        masq_quake_in           /* pkt_in */
 282};
 283
 284/*
 285 *      ip_masq_quake initialization
 286 */
 287
 288__initfunc(int ip_masq_quake_init(void))
 289{
 290        return (register_ip_masq_app(&ip_masq_quake, IPPROTO_UDP, 26000) +
 291                register_ip_masq_app(&ip_masq_quakenew, IPPROTO_UDP, 27000));
 292}
 293
 294/*
 295 *      ip_masq_quake fin.
 296 */
 297
 298int ip_masq_quake_done(void)
 299{
 300        return (unregister_ip_masq_app(&ip_masq_quake) +
 301                unregister_ip_masq_app(&ip_masq_quakenew));
 302}
 303
 304#ifdef MODULE
 305EXPORT_NO_SYMBOLS;
 306
 307int init_module(void)
 308{
 309        if (ip_masq_quake_init() != 0)
 310                return -EIO;
 311        return 0;
 312}
 313
 314void cleanup_module(void)
 315{
 316        if (ip_masq_quake_done() != 0)
 317                printk("ip_masq_quake: can't remove module");
 318}
 319
 320#endif /* MODULE */
 321
 322
 323
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.