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

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