root/net/ipv4/ip_masq.c

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

DEFINITIONS

This source file includes following definitions.
  1. masq_proto_name
  2. ip_masq_hash_key
  3. ip_masq_hash
  4. ip_masq_unhash
  5. ip_masq_in_get
  6. ip_masq_out_get
  7. ip_masq_out_get_2
  8. ip_masq_getbym
  9. masq_expire
  10. ip_masq_new
  11. ip_masq_set_expire
  12. recalc_check
  13. ip_fw_masquerade
  14. ip_fw_demasquerade
  15. ip_msqhst_procinfo
  16. ip_masq_init

   1 /*
   2  *
   3  *      Masquerading functionality
   4  *
   5  *      Copyright (c) 1994 Pauline Middelink
   6  *
   7  *      See ip_fw.c for original log
   8  *
   9  * Fixes:
  10  *      Juan Jose Ciarlante     :       Modularized application masquerading (see ip_masq_app.c)
  11  *      Juan Jose Ciarlante     :       New struct ip_masq_seq that holds output/input delta seq.
  12  *      Juan Jose Ciarlante     :       Added hashed lookup by proto,maddr,mport and proto,saddr,sport
  13  *      Juan Jose Ciarlante     :       Fixed deadlock if free ports get exhausted
  14  *      Juan Jose Ciarlante     :       Added NO_ADDR status flag.
  15  *
  16  *      
  17  */
  18 
  19 #include <linux/module.h>
  20 #include <linux/types.h>
  21 #include <linux/kernel.h>
  22 #include <linux/errno.h>
  23 #include <linux/skbuff.h>
  24 #include <asm/system.h>
  25 #include <linux/stat.h>
  26 #include <linux/proc_fs.h>
  27 #include <linux/in.h>
  28 #include <linux/ip.h>
  29 #include <net/protocol.h>
  30 #include <net/tcp.h>
  31 #include <net/udp.h>
  32 #include <net/ip_masq.h>
  33 
  34 #define IP_MASQ_TAB_SIZE 256    /* must be power of 2 */
  35 
  36 /*
  37  *      Implement IP packet masquerading
  38  */
  39 
  40 static const char *strProt[] = {"UDP","TCP"};
  41 
  42 static __inline__ const char * masq_proto_name(unsigned proto)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         return strProt[proto==IPPROTO_TCP];
  45 }
  46 
  47 /*
  48  *      Last masq_port number in use.
  49  *      Will cycle in MASQ_PORT boundaries.
  50  */
  51 static __u16 masq_port = PORT_MASQ_BEGIN;
  52 
  53 /*
  54  *      free ports counters (UDP & TCP)
  55  *
  56  *      Their value is _less_ or _equal_ to actual free ports:
  57  *      same masq port, diff masq addr (firewall iface address) allocated
  58  *      entries are accounted but their actually don't eat a more than 1 port.
  59  *
  60  *      Greater values could lower MASQ_EXPIRATION setting as a way to
  61  *      manage 'masq_entries resource'.
  62  *      
  63  */
  64 
  65 int ip_masq_free_ports[2] = {
  66         PORT_MASQ_END - PORT_MASQ_BEGIN,        /* UDP */
  67         PORT_MASQ_END - PORT_MASQ_BEGIN         /* TCP */
  68 };
  69 
  70 static struct symbol_table ip_masq_syms = {
  71 #include <linux/symtab_begin.h>
  72         X(ip_masq_new),
  73         X(ip_masq_set_expire),
  74         X(ip_masq_free_ports),
  75         X(ip_masq_expire),
  76         X(ip_masq_out_get_2),
  77 #include <linux/symtab_end.h>
  78 };
  79 
  80 /*
  81  *      2 ip_masq hash tables: for input and output pkts lookups.
  82  */
  83 
  84 struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
  85 struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
  86 
  87 /*
  88  * timeouts
  89  */
  90 
  91 static struct ip_fw_masq ip_masq_dummy = {
  92         MASQUERADE_EXPIRE_TCP,
  93         MASQUERADE_EXPIRE_TCP_FIN,
  94         MASQUERADE_EXPIRE_UDP
  95 };
  96 
  97 struct ip_fw_masq *ip_masq_expire = &ip_masq_dummy;
  98 
  99 /*
 100  *      Returns hash value
 101  */
 102 
 103 static __inline__ unsigned
 104 
 105 ip_masq_hash_key(unsigned proto, __u32 addr, __u16 port)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107         return (proto^ntohl(addr)^ntohs(port)) & (IP_MASQ_TAB_SIZE-1);
 108 }
 109 
 110 /*
 111  *      Hashes ip_masq by its proto,addrs,ports.
 112  *      should be called with masked interrupts.
 113  *      returns bool success.
 114  */
 115 
 116 static __inline__ int
 117 ip_masq_hash(struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         unsigned hash;
 120 
 121         if (ms->flags & IP_MASQ_F_HASHED) {
 122                 printk("ip_masq_hash(): request for already hashed\n");
 123                 return 0;
 124         }
 125         /*
 126          *      Hash by proto,m{addr,port}
 127          */
 128         hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
 129         ms->m_link = ip_masq_m_tab[hash];
 130         ip_masq_m_tab[hash] = ms;
 131 
 132         /*
 133          *      Hash by proto,s{addr,port}
 134          */
 135         hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
 136         ms->s_link = ip_masq_s_tab[hash];
 137         ip_masq_s_tab[hash] = ms;
 138 
 139 
 140         ms->flags |= IP_MASQ_F_HASHED;
 141         return 1;
 142 }
 143 
 144 /*
 145  *      UNhashes ip_masq from ip_masq_[ms]_tables.
 146  *      should be called with masked interrupts.
 147  *      returns bool success.
 148  */
 149 
 150 static __inline__ int ip_masq_unhash(struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         unsigned hash;
 153         struct ip_masq ** ms_p;
 154         if (!(ms->flags & IP_MASQ_F_HASHED)) {
 155                 printk("ip_masq_unhash(): request for unhash flagged\n");
 156                 return 0;
 157         }
 158         /*
 159          *      UNhash by m{addr,port}
 160          */
 161         hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
 162         for (ms_p = &ip_masq_m_tab[hash]; *ms_p ; ms_p = &(*ms_p)->m_link)
 163                 if (ms == (*ms_p))  {
 164                         *ms_p = ms->m_link;
 165                         break;
 166                 }
 167         /*
 168          *      UNhash by s{addr,port}
 169          */
 170         hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
 171         for (ms_p = &ip_masq_s_tab[hash]; *ms_p ; ms_p = &(*ms_p)->s_link)
 172                 if (ms == (*ms_p))  {
 173                         *ms_p = ms->s_link;
 174                         break;
 175                 }
 176 
 177         ms->flags &= ~IP_MASQ_F_HASHED;
 178         return 1;
 179 }
 180 
 181 /*
 182  *      Returns ip_masq associated with addresses found in iph.
 183  *      called for pkts coming from outside-to-INside the firewall
 184  *
 185  *      NB. Cannot check destination address, just for the incoming port.
 186  *      reason: archie.doc.ac.uk has 6 interfaces, you send to
 187  *      phoenix and get a reply from any other interface(==dst)!
 188  *
 189  *      [Only for UDP] - AC
 190  */
 191 
 192 struct ip_masq *
 193 ip_masq_in_get(struct iphdr *iph)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195         unsigned hash;
 196         struct ip_masq *ms;
 197         __u16 *portptr;
 198         int protocol;
 199         __u32 s_addr, d_addr;
 200         __u16 s_port, d_port;
 201 
 202         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 203         protocol = iph->protocol;
 204         s_addr = iph->saddr;
 205         s_port = portptr[0];
 206         d_addr = iph->daddr;
 207         d_port = portptr[1];
 208 
 209         hash = ip_masq_hash_key(protocol, d_addr, d_port);
 210         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
 211                 if ( protocol==ms->protocol &&
 212                     (s_addr==ms->daddr || ms->flags & IP_MASQ_F_NO_DADDR) &&
 213                     (s_port==ms->dport || ms->flags & IP_MASQ_F_NO_DPORT) &&
 214                     (d_addr==ms->maddr && d_port==ms->mport))
 215                         return ms;
 216         }
 217         return NULL;
 218 }
 219 
 220 /*
 221  *      Returns ip_masq associated with addresses found in iph.
 222  *      called for pkts coming from inside-to-OUTside the firewall.
 223  */
 224 
 225 struct ip_masq *
 226 ip_masq_out_get(struct iphdr *iph)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         __u16 *portptr;
 229         int protocol;
 230         __u32 s_addr, d_addr;
 231         __u16 s_port, d_port;
 232 
 233         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 234         protocol = iph->protocol;
 235         s_addr = iph->saddr;
 236         s_port = portptr[0];
 237         d_addr = iph->daddr;
 238         d_port = portptr[1];
 239 
 240         return ip_masq_out_get_2(protocol, s_addr, s_port, d_addr, d_port);
 241 }
 242 
 243 /*
 244  *      Returns ip_masq associated with supplied parameters, either
 245  *      broken out of the ip/tcp headers or directly supplied for those
 246  *      pathological protocols with address/port in the data stream
 247  *      (ftp, irc).  addresses and ports are in network order.
 248  *      called for pkts coming from inside-to-OUTside the firewall.
 249  */
 250 
 251 struct ip_masq *
 252 ip_masq_out_get_2(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254         unsigned hash;
 255         struct ip_masq *ms;
 256 
 257         hash = ip_masq_hash_key(protocol, s_addr, s_port);
 258         for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) {
 259                 if (protocol == ms->protocol &&
 260                     s_addr == ms->saddr && s_port == ms->sport &&
 261                     d_addr == ms->daddr && d_port == ms->dport )
 262                         return ms;
 263         }
 264 
 265         return NULL;
 266 }
 267 
 268 /*
 269  *      Returns ip_masq for given proto,m_addr,m_port.
 270  *      called by allocation routine to find an unused m_port.
 271  */
 272 
 273 struct ip_masq *
 274 ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port)
     /* [previous][next][first][last][top][bottom][index][help] */
 275 {
 276         unsigned hash;
 277         struct ip_masq *ms;
 278 
 279         hash = ip_masq_hash_key(protocol, m_addr, m_port);
 280         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
 281                 if ( protocol==ms->protocol &&
 282                     (m_addr==ms->maddr && m_port==ms->mport))
 283                         return ms;
 284         }
 285         return NULL;
 286 }
 287 
 288 static void masq_expire(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         struct ip_masq *ms = (struct ip_masq *)data;
 291         unsigned long flags;
 292 
 293 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 294         printk("Masqueraded %s %lX:%X expired\n",
 295                         masq_proto_name(ms->protocol),
 296                         ntohl(ms->src),ntohs(ms->sport));
 297 #endif
 298         
 299         save_flags(flags);
 300         cli();
 301 
 302         if (ip_masq_unhash(ms)) {
 303                 ip_masq_free_ports[ms->protocol==IPPROTO_TCP]++;
 304                 ip_masq_unbind_app(ms);
 305                 kfree_s(ms,sizeof(*ms));
 306         }
 307 
 308         restore_flags(flags);
 309 }
 310 
 311 /*
 312  *      Create a new masquerade list entry, also allocate an
 313  *      unused mport, keeping the portnumber between the
 314  *      given boundaries MASQ_BEGIN and MASQ_END.
 315  */
 316 
 317 struct ip_masq * ip_masq_new(struct device *dev, int proto, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags)
     /* [previous][next][first][last][top][bottom][index][help] */
 318 {
 319         struct ip_masq *ms, *mst;
 320         int ports_tried, *free_ports_p;
 321         unsigned long flags;
 322         static int n_fails = 0;
 323 
 324         free_ports_p = &ip_masq_free_ports[proto==IPPROTO_TCP];
 325 
 326         if (*free_ports_p == 0) {
 327                 if (++n_fails < 5)
 328                         printk("ip_masq_new(proto=%s): no free ports.\n",
 329                                masq_proto_name(proto));
 330                 return NULL;
 331         }
 332         ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
 333         if (ms == NULL) {
 334                 if (++n_fails < 5)
 335                         printk("ip_masq_new(proto=%s): no memory available.\n",
 336                                masq_proto_name(proto));
 337                 return NULL;
 338         }
 339         memset(ms, 0, sizeof(*ms));
 340         init_timer(&ms->timer);
 341         ms->timer.data     = (unsigned long)ms;
 342         ms->timer.function = masq_expire;
 343         ms->protocol       = proto;
 344         ms->saddr          = saddr;
 345         ms->sport          = sport;
 346         ms->daddr          = daddr;
 347         ms->dport          = dport;
 348         ms->flags          = mflags;
 349         ms->app_data       = NULL;
 350 
 351         if (proto == IPPROTO_UDP)
 352                 ms->flags |= IP_MASQ_F_NO_DADDR;
 353         
 354         /* get masq address from rif */
 355         ms->maddr          = dev->pa_addr;
 356 
 357         for (ports_tried = 0; ports_tried < *free_ports_p; ports_tried++){
 358                 save_flags(flags);
 359                 cli();
 360                 
 361                 /*
 362                  *      Try the next available port number
 363                  */
 364                 
 365                 ms->mport = htons(masq_port++);
 366                 if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
 367                 
 368                 restore_flags(flags);
 369                 
 370                 /*
 371                  *      lookup to find out if this port is used.
 372                  */
 373                 
 374                 mst = ip_masq_getbym(proto, ms->maddr, ms->mport);
 375                 if (mst == NULL) {
 376                         save_flags(flags);
 377                         cli();
 378                 
 379                         if (*free_ports_p == 0) {
 380                                 restore_flags(flags);
 381                                 break;
 382                         }
 383                         (*free_ports_p)--;
 384                         ip_masq_hash(ms);
 385                         
 386                         restore_flags(flags);
 387                         
 388                         ip_masq_bind_app(ms);
 389                         n_fails = 0;
 390                         return ms;
 391                 }
 392         }
 393         
 394         if (++n_fails < 5)
 395                 printk("ip_masq_new(proto=%s): could not get free masq entry (free=%d).\n",
 396                        masq_proto_name(ms->protocol), *free_ports_p);
 397         kfree_s(ms, sizeof(*ms));
 398         return NULL;
 399 }
 400 
 401 /*
 402  *      Set masq expiration (deletion) and adds timer,
 403  *      if timeout==0 cancel expiration.
 404  *      Warning: it does not check/delete previous timer!
 405  */
 406 
 407 void ip_masq_set_expire(struct ip_masq *ms, unsigned long tout)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409         if (tout) {
 410                 ms->timer.expires = jiffies+tout;
 411                 add_timer(&ms->timer);
 412         } else {
 413                 del_timer(&ms->timer);
 414         }
 415 }
 416 
 417 static void recalc_check(struct udphdr *uh, __u32 saddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 418         __u32 daddr, int len)
 419 {
 420         uh->check=0;
 421         uh->check=csum_tcpudp_magic(saddr,daddr,len,
 422                 IPPROTO_UDP, csum_partial((char *)uh,len,0));
 423         if(uh->check==0)
 424                 uh->check=0xFFFF;
 425 }
 426         
 427 void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429         struct sk_buff  *skb=*skb_ptr;
 430         struct iphdr    *iph = skb->h.iph;
 431         __u16   *portptr;
 432         struct ip_masq  *ms;
 433         int             size;
 434         unsigned long   timeout;
 435 
 436         /*
 437          * We can only masquerade protocols with ports...
 438          */
 439 
 440         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 441                 return;
 442 
 443         /*
 444          *      Now hunt the list to see if we have an old entry
 445          */
 446 
 447         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 448 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 449         printk("Outgoing %s %lX:%X -> %lX:%X\n",
 450                 masq_proto_name(iph->protocol),
 451                 ntohl(iph->saddr), ntohs(portptr[0]),
 452                 ntohl(iph->daddr), ntohs(portptr[1]));
 453 #endif
 454 
 455         ms = ip_masq_out_get(iph);
 456         if (ms!=NULL)
 457                 ip_masq_set_expire(ms,0);
 458 
 459         /*
 460          *      Nope, not found, create a new entry for it
 461          */
 462         
 463         if (ms==NULL)
 464         {
 465                 ms = ip_masq_new(dev, iph->protocol,
 466                                  iph->saddr, portptr[0],
 467                                  iph->daddr, portptr[1],
 468                                  0);
 469                 if (ms == NULL)
 470                         return;
 471         }
 472 
 473         /*
 474          *      Change the fragments origin
 475          */
 476         
 477         size = skb->len - ((unsigned char *)portptr - skb->h.raw);
 478         /*
 479          *      Set iph addr and port from ip_masq obj.
 480          */
 481         iph->saddr = ms->maddr;
 482         portptr[0] = ms->mport;
 483 
 484         /*
 485          *      Attempt ip_masq_app call.
 486          *      will fix ip_masq and iph seq stuff
 487          */
 488         if (ip_masq_app_pkt_out(ms, skb_ptr, dev) != 0)
 489         {
 490                 /*
 491                  *      skb has possibly changed, update pointers.
 492                  */
 493                 skb = *skb_ptr;
 494                 iph = skb->h.iph;
 495                 portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 496                 size = skb->len - ((unsigned char *)portptr-skb->h.raw);
 497         }
 498 
 499         /*
 500          *      Adjust packet accordingly to protocol
 501          */
 502         
 503         if (iph->protocol==IPPROTO_UDP)
 504         {
 505                 timeout = ip_masq_expire->udp_timeout;
 506                 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 507         }
 508         else
 509         {
 510                 struct tcphdr *th;
 511                 th = (struct tcphdr *)portptr;
 512 
 513                 /*
 514                  *      Timeout depends if FIN packet was seen
 515                  *      Very short timeout if RST packet seen.
 516                  */
 517                 if (ms->flags & IP_MASQ_F_SAW_RST || th->rst)
 518                 {
 519                         timeout = 1;
 520                         ms->flags |= IP_MASQ_F_SAW_RST;
 521                 }
 522                 else if (ms->flags & IP_MASQ_F_SAW_FIN || th->fin)
 523                 {
 524                         timeout = ip_masq_expire->tcp_fin_timeout;
 525                         ms->flags |= IP_MASQ_F_SAW_FIN;
 526                 }
 527                 else timeout = ip_masq_expire->tcp_timeout;
 528 
 529                 skb->csum = csum_partial((void *)(th + 1), size - sizeof(*th), 0);
 530                 tcp_send_check(th,iph->saddr,iph->daddr,size,skb);
 531         }
 532         ip_masq_set_expire(ms, timeout);
 533         ip_send_check(iph);
 534 
 535  #ifdef DEBUG_CONFIG_IP_MASQUERADE
 536         printk("O-routed from %lX:%X over %s\n",ntohl(ms->maddr),ntohs(ms->mport),dev->name);
 537  #endif
 538  }
 539 
 540  /*
 541   *     Check if it's an masqueraded port, look it up,
 542   *     and send it on it's way...
 543   *
 544   *     Better not have many hosts using the designated portrange
 545   *     as 'normal' ports, or you'll be spending many time in
 546   *     this function.
 547   */
 548 
 549 int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 550 {
 551         struct sk_buff  *skb = *skb_p;
 552         struct iphdr    *iph = skb->h.iph;
 553         __u16   *portptr;
 554         struct ip_masq  *ms;
 555         unsigned short  frag;
 556 
 557         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 558                 return 0;
 559 
 560         /*
 561          * Toss fragments, since we handle them in ip_rcv()
 562          */
 563 
 564         frag = ntohs(iph->frag_off);
 565 
 566         if ((frag & IP_MF) != 0 || (frag & IP_OFFSET) != 0)
 567         {
 568                 return 0;
 569         }
 570 
 571         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 572         if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
 573             ntohs(portptr[1]) > PORT_MASQ_END)
 574                 return 0;
 575 
 576 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 577         printk("Incoming %s %lX:%X -> %lX:%X\n",
 578                 masq_proto_name(iph->protocol),
 579                 ntohl(iph->saddr), ntohs(portptr[0]),
 580                 ntohl(iph->daddr), ntohs(portptr[1]));
 581 #endif
 582         /*
 583          * reroute to original host:port if found...
 584          */
 585 
 586         ms = ip_masq_in_get(iph);
 587 
 588         if (ms != NULL)
 589         {
 590                 int size;
 591 
 592                 /*
 593                  *      Set dport if not defined yet.
 594                  */
 595 
 596                 if ( ms->flags & IP_MASQ_F_NO_DPORT && ms->protocol == IPPROTO_TCP ) {
 597                         ms->flags &= ~IP_MASQ_F_NO_DPORT;
 598                         ms->dport = portptr[0];
 599 #if DEBUG_CONFIG_IP_MASQUERADE
 600                         printk("ip_fw_demasquerade(): filled dport=%d\n",
 601                                ntohs(ms->dport));
 602 #endif
 603                 }
 604                 if (ms->flags & IP_MASQ_F_NO_DADDR && ms->protocol == IPPROTO_TCP)  {
 605                         ms->flags &= ~IP_MASQ_F_NO_DADDR;
 606                         ms->daddr = iph->saddr;
 607 #if DEBUG_CONFIG_IP_MASQUERADE
 608                         printk("ip_fw_demasquerade(): filled daddr=%X\n",
 609                                ntohs(ms->daddr));
 610 #endif
 611                 }
 612                 size = skb->len - ((unsigned char *)portptr - skb->h.raw);
 613                 iph->daddr = ms->saddr;
 614                 portptr[1] = ms->sport;
 615 
 616                 /*
 617                  *      Attempt ip_masq_app call.
 618                  *      will fix ip_masq and iph ack_seq stuff
 619                  */
 620 
 621                 if (ip_masq_app_pkt_in(ms, skb_p, dev) != 0)
 622                 {
 623                         /*
 624                          *      skb has changed, update pointers.
 625                          */
 626 
 627                         skb = *skb_p;
 628                         iph = skb->h.iph;
 629                         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 630                         size = skb->len - ((unsigned char *)portptr-skb->h.raw);
 631                 }
 632 
 633                 /*
 634                  * Yug! adjust UDP/TCP and IP checksums, also update
 635                  * UDP timeouts since you cannot depend on traffic
 636                  * going through the other way to hold the timeout open.
 637                  * (With TCP the ACK packets hold the tunnel open).
 638                  * If a TCP RST is seen collapse the tunnel!
 639                  */
 640                 if (iph->protocol==IPPROTO_UDP)
 641                 {
 642                         unsigned long   timeout;
 643                         recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 644                         ip_masq_set_expire(ms, 0);
 645                         ip_masq_set_expire(ms, ip_masq_expire->udp_timeout);
 646                 }
 647                 else
 648                 {
 649                         struct tcphdr *th;
 650                         skb->csum = csum_partial((void *)(((struct tcphdr *)portptr) + 1),
 651                                                  size - sizeof(struct tcphdr), 0);
 652                         tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb);
 653                         /* Check if TCP RST */
 654                         th = (struct tcphdr *)portptr;
 655                         if (th->rst)
 656                         {
 657                                 ip_masq_set_expire(ms, 0);
 658                                 ms->flags |= IP_MASQ_F_SAW_RST;
 659                                 ip_masq_set_expire(ms, 1);
 660                         }
 661 
 662                 }
 663                 ip_send_check(iph);
 664 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 665                 printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
 666 #endif
 667                 return 1;
 668         }
 669 
 670         /* sorry, all this trouble for a no-hit :) */
 671         return 0;
 672 }
 673 
 674 /*
 675  *      /proc/net entry
 676  */
 677 
 678 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
 679                               int length, int unused)
 680 {
 681         off_t pos=0, begin;
 682         struct ip_masq *ms;
 683         unsigned long flags;
 684         char temp[129];
 685         int idx = 0;
 686         int len=0;
 687         
 688         if (offset < 128) 
 689         {
 690                 sprintf(temp,
 691                         "Prc FromIP   FPrt ToIP     TPrt Masq Init-seq  Delta PDelta Expires (free=%d,%d)",
 692                         ip_masq_free_ports[0], ip_masq_free_ports[1]); 
 693                 len = sprintf(buffer, "%-127s\n", temp);
 694         }
 695         pos = 128;
 696         save_flags(flags);
 697         cli();
 698         
 699         for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
 700         for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
 701         {
 702                 int timer_active;
 703                 pos += 128;
 704                 if (pos <= offset)
 705                         continue;
 706 
 707                 timer_active = del_timer(&ms->timer);
 708                 if (!timer_active)
 709                         ms->timer.expires = jiffies;
 710                 sprintf(temp,"%s %08lX:%04X %08lX:%04X %04X %08X %6d %6d %7lu",
 711                         masq_proto_name(ms->protocol),
 712                         ntohl(ms->saddr), ntohs(ms->sport),
 713                         ntohl(ms->daddr), ntohs(ms->dport),
 714                         ntohs(ms->mport),
 715                         ms->out_seq.init_seq,
 716                         ms->out_seq.delta,
 717                         ms->out_seq.previous_delta,
 718                         ms->timer.expires-jiffies);
 719                 if (timer_active)
 720                         add_timer(&ms->timer);
 721                 len += sprintf(buffer+len, "%-127s\n", temp);
 722 
 723                 if(len >= length)
 724                         goto done;
 725         }
 726 done:
 727         restore_flags(flags);
 728         begin = len - (pos - offset);
 729         *start = buffer + begin;
 730         len -= begin;
 731         if(len>length)
 732                 len = length;
 733         return len;
 734 }
 735 
 736 /*
 737  *      Initialize ip masquerading
 738  */
 739 int ip_masq_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         register_symtab (&ip_masq_syms);
 742         proc_net_register(&(struct proc_dir_entry) {
 743                 PROC_NET_IPMSQHST, 13, "ip_masquerade",
 744                 S_IFREG | S_IRUGO, 1, 0, 0,
 745                 0, &proc_net_inode_operations,
 746                 ip_msqhst_procinfo
 747         });
 748         ip_masq_app_init();
 749 
 750         return 0;
 751 }

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