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_getbym
  8. masq_expire
  9. ip_masq_new
  10. ip_masq_set_expire
  11. recalc_check
  12. ip_fw_masquerade
  13. ip_fw_demasquerade
  14. ip_msqhst_procinfo
  15. 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 #include <linux/symtab_end.h>
  76 };
  77 
  78 /*
  79  *      2 ip_masq hash tables: for input and output pkts lookups.
  80  */
  81 
  82 struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
  83 struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
  84 
  85 /*
  86  *      Returns hash value
  87  */
  88 
  89 static __inline__ unsigned
  90 
  91 ip_masq_hash_key(unsigned proto, __u32 addr, __u16 port)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93         return (proto^ntohl(addr)^ntohs(port)) & (IP_MASQ_TAB_SIZE-1);
  94 }
  95 
  96 /*
  97  *      Hashes ip_masq by its proto,addrs,ports.
  98  *      should be called with masked interrupts.
  99  *      returns bool success.
 100  */
 101 
 102 static __inline__ int
 103 ip_masq_hash(struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         unsigned hash;
 106 
 107         if (ms->flags & IP_MASQ_F_HASHED) {
 108                 printk("ip_masq_hash(): request for already hashed\n");
 109                 return 0;
 110         }
 111         /*
 112          *      Hash by proto,m{addr,port}
 113          */
 114         hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
 115         ms->m_link = ip_masq_m_tab[hash];
 116         ip_masq_m_tab[hash] = ms;
 117         
 118         /*
 119          *      Hash by proto,s{addr,port}
 120          */
 121         hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
 122         ms->s_link = ip_masq_s_tab[hash];
 123         ip_masq_s_tab[hash] = ms;
 124         
 125 
 126         ms->flags |= IP_MASQ_F_HASHED;
 127         return 1;
 128 }
 129 
 130 /*
 131  *      UNhashes ip_masq from ip_masq_[ms]_tables.
 132  *      should be called with masked interrupts.
 133  *      returns bool success.
 134  */
 135 
 136 static __inline__ int ip_masq_unhash(struct ip_masq *ms)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         unsigned hash;
 139         struct ip_masq ** ms_p;
 140         if (!(ms->flags & IP_MASQ_F_HASHED)) {
 141                 printk("ip_masq_unhash(): request for unhash flagged\n");
 142                 return 0;
 143         }
 144         /*
 145          *      UNhash by m{addr,port}
 146          */
 147         hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
 148         for (ms_p = &ip_masq_m_tab[hash]; *ms_p ; ms_p = &(*ms_p)->m_link)
 149                 if (ms == (*ms_p))  {
 150                         *ms_p = ms->m_link;
 151                         break;
 152                 }
 153         /*
 154          *      UNhash by s{addr,port}
 155          */
 156         hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
 157         for (ms_p = &ip_masq_s_tab[hash]; *ms_p ; ms_p = &(*ms_p)->s_link)
 158                 if (ms == (*ms_p))  {
 159                         *ms_p = ms->s_link;
 160                         break;
 161                 }
 162        
 163         ms->flags &= ~IP_MASQ_F_HASHED;
 164         return 1;
 165 }
 166 
 167 /*
 168  *      Returns ip_masq associated with addresses found in iph.
 169  *      called for pkts coming from outside-to-INside the firewall
 170  *
 171  *      NB. Cannot check destination address, just for the incoming port.
 172  *      reason: archie.doc.ac.uk has 6 interfaces, you send to
 173  *      phoenix and get a reply from any other interface(==dst)!
 174  *
 175  *      [Only for UDP] - AC
 176  */
 177 
 178 struct ip_masq *
 179 ip_masq_in_get(struct iphdr *iph)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         unsigned hash;
 182         struct ip_masq *ms;
 183         __u16 *portptr;
 184         int protocol;
 185         __u32 s_addr, d_addr;
 186         __u16 s_port, d_port;
 187 
 188         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 189         protocol = iph->protocol;
 190         s_addr = iph->saddr;
 191         s_port = portptr[0];
 192         d_addr = iph->daddr;
 193         d_port = portptr[1];
 194         
 195         hash = ip_masq_hash_key(protocol, d_addr, d_port);
 196         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
 197                 if ( protocol==ms->protocol &&
 198                     (s_addr==ms->daddr || ms->flags & IP_MASQ_F_NO_DADDR) &&
 199                     (s_port==ms->dport || ms->flags & IP_MASQ_F_NO_DPORT) &&
 200                     (d_addr==ms->maddr && d_port==ms->mport))
 201                         return ms;
 202         }
 203         return NULL;
 204 }
 205 
 206 /*
 207  *      Returns ip_masq associated with addresses found in iph.
 208  *      called for pkts coming from inside-to-OUTside the firewall.
 209  */
 210 
 211 struct ip_masq *
 212 ip_masq_out_get(struct iphdr *iph)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         unsigned hash;
 215         struct ip_masq *ms;
 216         __u16 *portptr;
 217         int protocol;
 218         __u32 s_addr, d_addr;
 219         __u16 s_port, d_port;
 220 
 221         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 222         protocol = iph->protocol;
 223         s_addr = iph->saddr;
 224         s_port = portptr[0];
 225         d_addr = iph->daddr;
 226         d_port = portptr[1];
 227         
 228         hash = ip_masq_hash_key(protocol, s_addr, s_port);
 229         for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) {
 230                 if (protocol == ms->protocol &&
 231                     s_addr == ms->saddr && s_port == ms->sport &&
 232                     d_addr == ms->daddr && d_port == ms->dport )
 233                         return ms;
 234         }
 235         
 236         return NULL;
 237 }
 238 
 239 /*
 240  *      Returns ip_masq for given proto,m_addr,m_port.
 241  *      called by allocation routine to find an unused m_port.
 242  */
 243 
 244 struct ip_masq *
 245 ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247         unsigned hash;
 248         struct ip_masq *ms;
 249         
 250         hash = ip_masq_hash_key(protocol, m_addr, m_port);
 251         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
 252                 if ( protocol==ms->protocol &&
 253                     (m_addr==ms->maddr && m_port==ms->mport))
 254                         return ms;
 255         }
 256         return NULL;
 257 }
 258 
 259 static void masq_expire(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         struct ip_masq *ms = (struct ip_masq *)data;
 262         unsigned long flags;
 263 
 264 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 265         printk("Masqueraded %s %lX:%X expired\n",
 266                         masq_proto_name(ms->protocol),
 267                         ntohl(ms->src),ntohs(ms->sport));
 268 #endif
 269         
 270         save_flags(flags);
 271         cli();
 272 
 273         if (ip_masq_unhash(ms)) {
 274                 ip_masq_free_ports[ms->protocol==IPPROTO_TCP]++;
 275                 ip_masq_unbind_app(ms);
 276                 kfree_s(ms,sizeof(*ms));
 277         }
 278         
 279         restore_flags(flags);
 280 }
 281 
 282 /*
 283  *      Create a new masquerade list entry, also allocate an
 284  *      unused mport, keeping the portnumber between the
 285  *      given boundaries MASQ_BEGIN and MASQ_END.
 286  */
 287 
 288 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] */
 289 {
 290         struct ip_masq *ms, *mst;
 291         int ports_tried, *free_ports_p;
 292         unsigned long flags;
 293         static int n_fails = 0;
 294         
 295         free_ports_p = &ip_masq_free_ports[proto==IPPROTO_TCP];
 296         
 297         if (*free_ports_p == 0) {
 298                 if (++n_fails < 5)
 299                         printk("ip_masq_new(proto=%s): no free ports.\n",
 300                                masq_proto_name(proto));
 301                 return NULL;
 302         }
 303         ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
 304         if (ms == NULL) {
 305                 if (++n_fails < 5)
 306                         printk("ip_masq_new(proto=%s): no memory available.\n",
 307                                masq_proto_name(proto));
 308                 return NULL;
 309         }
 310         memset(ms, 0, sizeof(*ms));
 311         init_timer(&ms->timer);
 312         ms->timer.data     = (unsigned long)ms;
 313         ms->timer.function = masq_expire;
 314         ms->protocol       = proto;
 315         ms->saddr          = saddr;
 316         ms->sport          = sport;
 317         ms->daddr          = daddr;
 318         ms->dport          = dport;
 319         ms->flags          = mflags;
 320         
 321         if (proto == IPPROTO_UDP)
 322                 ms->flags |= IP_MASQ_F_NO_DADDR;
 323         
 324         /* get masq address from rif */
 325         ms->maddr          = dev->pa_addr;
 326 
 327         for (ports_tried = 0; ports_tried < *free_ports_p; ports_tried++){
 328                 save_flags(flags);
 329                 cli();
 330                 
 331                 /*
 332                  *      Try the next available port number
 333                  */
 334                 
 335                 ms->mport = htons(masq_port++);
 336                 if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
 337                 
 338                 restore_flags(flags);
 339                 
 340                 /*
 341                  *      lookup to find out if this port is used.
 342                  */
 343                 
 344                 mst = ip_masq_getbym(proto, ms->maddr, ms->mport);
 345                 if (mst == NULL) {
 346                         save_flags(flags);
 347                         cli();
 348                 
 349                         if (*free_ports_p == 0) {
 350                                 restore_flags(flags);
 351                                 break;
 352                         }
 353                         (*free_ports_p)--;
 354                         ip_masq_hash(ms);
 355                         
 356                         restore_flags(flags);
 357                         
 358                         ip_masq_bind_app(ms);
 359                         n_fails = 0;
 360                         return ms;
 361                 }
 362         }
 363         
 364         if (++n_fails < 5)
 365                 printk("ip_masq_new(proto=%s): could not get free masq entry (free=%d).\n",
 366                        masq_proto_name(ms->protocol), *free_ports_p);
 367         kfree_s(ms, sizeof(*ms));
 368         return NULL;
 369 }
 370 
 371 /*
 372  *      Set masq expiration (deletion) and adds timer,
 373  *      if timeout==0 cancel expiration.
 374  *      Warning: it does not check/delete previous timer!
 375  */
 376 
 377 void ip_masq_set_expire(struct ip_masq *ms, unsigned long tout)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379         if (tout) {
 380                 ms->timer.expires = jiffies+tout;
 381                 add_timer(&ms->timer);
 382         } else {
 383                 del_timer(&ms->timer);
 384         }
 385 }
 386 
 387 static void recalc_check(struct udphdr *uh, __u32 saddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 388         __u32 daddr, int len)
 389 {
 390         uh->check=0;
 391         uh->check=csum_tcpudp_magic(saddr,daddr,len,
 392                 IPPROTO_UDP, csum_partial((char *)uh,len,0));
 393         if(uh->check==0)
 394                 uh->check=0xFFFF;
 395 }
 396         
 397 void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 398 {
 399         struct sk_buff  *skb=*skb_ptr;
 400         struct iphdr    *iph = skb->h.iph;
 401         __u16   *portptr;
 402         struct ip_masq  *ms;
 403         int             size;
 404         unsigned long   timeout;
 405 
 406         /*
 407          * We can only masquerade protocols with ports...
 408          */
 409 
 410         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 411                 return;
 412  
 413         /*
 414          *      Now hunt the list to see if we have an old entry
 415          */
 416 
 417         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 418 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 419         printk("Outgoing %s %lX:%X -> %lX:%X\n",
 420                 masq_proto_name(iph->protocol),
 421                 ntohl(iph->saddr), ntohs(portptr[0]),
 422                 ntohl(iph->daddr), ntohs(portptr[1]));
 423 #endif
 424         
 425         ms = ip_masq_out_get(iph);
 426         if (ms!=NULL)
 427                 ip_masq_set_expire(ms,0);
 428 
 429         /*
 430          *      Nope, not found, create a new entry for it
 431          */
 432          
 433         if (ms==NULL) 
 434         {
 435                 ms = ip_masq_new(dev, iph->protocol,
 436                                  iph->saddr, portptr[0],
 437                                  iph->daddr, portptr[1],
 438                                  0);
 439                 if (ms == NULL)
 440                         return;
 441         }
 442  
 443         /*
 444          *      Change the fragments origin
 445          */
 446          
 447         size = skb->len - ((unsigned char *)portptr - skb->h.raw);
 448         /*
 449          *      Set iph addr and port from ip_masq obj.
 450          */
 451         iph->saddr = ms->maddr;
 452         portptr[0] = ms->mport;
 453  
 454         /*
 455          *      Attempt ip_masq_app call.
 456          *      will fix ip_masq and iph seq stuff
 457          */
 458         if (ip_masq_app_pkt_out(ms, skb_ptr, dev) != 0)
 459         {
 460                 /*
 461                  *      skb has possibly changed, update pointers.
 462                  */
 463                 skb = *skb_ptr;
 464                 iph = skb->h.iph;
 465                 portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 466                 size = skb->len - ((unsigned char *)portptr-skb->h.raw);
 467         }
 468         
 469         /*
 470          *      Adjust packet accordingly to protocol
 471          */
 472          
 473         if (iph->protocol==IPPROTO_UDP) 
 474         {
 475                 timeout = MASQUERADE_EXPIRE_UDP;
 476                 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 477         }
 478         else 
 479         {
 480                 struct tcphdr *th;
 481                 th = (struct tcphdr *)portptr;
 482  
 483                 /*
 484                  *      Timeout depends if FIN packet was seen
 485                  */
 486                 if (ms->flags & IP_MASQ_F_SAW_FIN || th->fin)
 487                 {
 488                         timeout = MASQUERADE_EXPIRE_TCP_FIN;
 489                         ms->flags |= IP_MASQ_F_SAW_FIN;
 490                 }
 491                 else timeout = MASQUERADE_EXPIRE_TCP;
 492  
 493                 skb->csum = csum_partial((void *)(th + 1), size - sizeof(*th), 0);
 494                 tcp_send_check(th,iph->saddr,iph->daddr,size,skb);
 495         }
 496         ip_masq_set_expire(ms, timeout);
 497         ip_send_check(iph);
 498  
 499  #ifdef DEBUG_CONFIG_IP_MASQUERADE
 500         printk("O-routed from %lX:%X over %s\n",ntohl(ms->maddr),ntohs(ms->mport),dev->name);
 501  #endif
 502  }
 503  
 504  /*
 505   *     Check if it's an masqueraded port, look it up,
 506   *     and send it on it's way...
 507   *
 508   *     Better not have many hosts using the designated portrange
 509   *     as 'normal' ports, or you'll be spending many time in
 510   *     this function.
 511   */
 512 
 513 int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 514 {
 515         struct sk_buff  *skb = *skb_p;
 516         struct iphdr    *iph = skb->h.iph;
 517         __u16   *portptr;
 518         struct ip_masq  *ms;
 519  
 520         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 521                 return 0;
 522  
 523         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 524         if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
 525             ntohs(portptr[1]) > PORT_MASQ_END)
 526                 return 0;
 527  
 528 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 529         printk("Incoming %s %lX:%X -> %lX:%X\n",
 530                 masq_proto_name(iph->protocol),
 531                 ntohl(iph->saddr), ntohs(portptr[0]),
 532                 ntohl(iph->daddr), ntohs(portptr[1]));
 533 #endif
 534         /*
 535          * reroute to original host:port if found...
 536          */
 537         
 538         ms = ip_masq_in_get(iph);
 539         
 540         if (ms != NULL)
 541         {
 542                 int size;
 543         
 544                 /*
 545                  *      Set dport if not defined yet.
 546                  */
 547                 
 548                 if ( ms->flags & IP_MASQ_F_NO_DPORT && ms->protocol == IPPROTO_TCP ) {
 549                         ms->flags &= ~IP_MASQ_F_NO_DPORT;
 550                         ms->dport = portptr[0];
 551 #if DEBUG_CONFIG_IP_MASQUERADE
 552                         printk("ip_fw_demasquerade(): filled dport=%d\n",
 553                                ntohs(ms->dport));
 554 #endif
 555                 }
 556                 if (ms->flags & IP_MASQ_F_NO_DADDR && ms->protocol == IPPROTO_TCP)  {
 557                         ms->flags &= ~IP_MASQ_F_NO_DADDR;
 558                         ms->daddr = iph->saddr;
 559 #if DEBUG_CONFIG_IP_MASQUERADE
 560                         printk("ip_fw_demasquerade(): filled daddr=%X\n",
 561                                ntohs(ms->daddr));
 562 #endif
 563                 }
 564                 size = skb->len - ((unsigned char *)portptr - skb->h.raw);
 565                 iph->daddr = ms->saddr;
 566                 portptr[1] = ms->sport;
 567                 
 568                 /*
 569                  *      Attempt ip_masq_app call.
 570                  *      will fix ip_masq and iph ack_seq stuff
 571                  */
 572                 
 573                 if (ip_masq_app_pkt_in(ms, skb_p, dev) != 0)
 574                 {
 575                         /*
 576                          *      skb has changed, update pointers.
 577                          */
 578                         
 579                         skb = *skb_p;
 580                         iph = skb->h.iph;
 581                         portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 582                         size = skb->len - ((unsigned char *)portptr-skb->h.raw);
 583                 }
 584                 
 585                 /*
 586                  * Yug! adjust UDP/TCP and IP checksums
 587                  */
 588                 if (iph->protocol==IPPROTO_UDP)
 589                         recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 590                 else
 591                 {
 592                         skb->csum = csum_partial((void *)(((struct tcphdr *)portptr) + 1),
 593                                                  size - sizeof(struct tcphdr), 0);
 594                         tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb);
 595                 }
 596                 ip_send_check(iph);
 597 #ifdef DEBUG_CONFIG_IP_MASQUERADE
 598                 printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
 599 #endif
 600                 return 1;
 601         }
 602         
 603         /* sorry, all this trouble for a no-hit :) */
 604         return 0;
 605 }
 606 
 607 /*
 608  *      /proc/net entry
 609  */
 610 
 611 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
 612                               int length, int unused)
 613 {
 614         off_t pos=0, begin=0;
 615         struct ip_masq *ms;
 616         unsigned long flags;
 617         int idx = 0;
 618         int len=0;
 619         
 620         len=sprintf(buffer,"Prc FromIP   FPrt ToIP     TPrt Masq Init-seq  Delta PDelta Expires (free=%d,%d)\n",
 621                     ip_masq_free_ports[0], ip_masq_free_ports[1]); 
 622         save_flags(flags);
 623         cli();
 624         
 625         for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
 626         for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
 627         {
 628                 int timer_active = del_timer(&ms->timer);
 629                 if (!timer_active)
 630                         ms->timer.expires = jiffies;
 631                 len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08X %6d %6d %lu\n",
 632                         masq_proto_name(ms->protocol),
 633                         ntohl(ms->saddr),ntohs(ms->sport),
 634                         ntohl(ms->daddr),ntohs(ms->dport),
 635                         ntohs(ms->mport),
 636                         ms->out_seq.init_seq,ms->out_seq.delta,ms->out_seq.previous_delta,ms->timer.expires-jiffies);
 637                 if (timer_active)
 638                         add_timer(&ms->timer);
 639 
 640                 pos=begin+len;
 641                 if(pos<offset) 
 642                 {
 643                         len=0;
 644                         begin=pos;
 645                 }
 646                 if(pos>offset+length)
 647                         break;
 648         }
 649         restore_flags(flags);
 650         *start=buffer+(offset-begin);
 651         len-=(offset-begin);
 652         if(len>length)
 653                 len=length;
 654         return len;
 655 }
 656 
 657 /*
 658  *      Initialize ip masquerading
 659  */
 660 int ip_masq_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 661 {  
 662         register_symtab (&ip_masq_syms);
 663         proc_net_register(&(struct proc_dir_entry) {
 664                 PROC_NET_IPMSQHST, 13, "ip_masquerade",
 665                 S_IFREG | S_IRUGO, 1, 0, 0,
 666                 0, &proc_net_inode_operations,
 667                 ip_msqhst_procinfo
 668         });
 669         ip_masq_app_init();
 670         
 671         return 0;
 672 }

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