root/net/ipv4/ip_fw.c

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

DEFINITIONS

This source file includes following definitions.
  1. port_match
  2. ip_fw_chk
  3. masq_expire
  4. alloc_masq_entry
  5. revamp
  6. recalc_check
  7. ip_fw_masquerade
  8. ip_fw_demasquerade
  9. zero_fw_chain
  10. free_fw_chain
  11. add_to_chain
  12. del_from_chain
  13. check_ipfw_struct
  14. ip_acct_cnt
  15. ip_acct_ctl
  16. ip_fw_ctl
  17. ip_chain_procinfo
  18. ip_acct_procinfo
  19. ip_fw_blk_procinfo
  20. ip_fw_fwd_procinfo
  21. ip_msqhst_procinfo
  22. ip_fw_init

   1 /*
   2  *      IP firewalling code. This is taken from 4.4BSD. Please note the 
   3  *      copyright message below. As per the GPL it must be maintained
   4  *      and the licenses thus do not conflict. While this port is subject
   5  *      to the GPL I also place my modifications under the original 
   6  *      license in recognition of the original copyright. 
   7  *                              -- Alan Cox.
   8  *
   9  *      Ported from BSD to Linux,
  10  *              Alan Cox 22/Nov/1994.
  11  *      Zeroing /proc and other additions
  12  *              Jos Vos 4/Feb/1995.
  13  *      Merged and included the FreeBSD-Current changes at Ugen's request
  14  *      (but hey it's a lot cleaner now). Ugen would prefer in some ways
  15  *      we waited for his final product but since Linux 1.2.0 is about to
  16  *      appear it's not practical - Read: It works, it's not clean but please
  17  *      don't consider it to be his standard of finished work.
  18  *              Alan Cox 12/Feb/1995
  19  *      Porting bidirectional entries from BSD, fixing accounting issues,
  20  *      adding struct ip_fwpkt for checking packets with interface address
  21  *              Jos Vos 5/Mar/1995.
  22  *      Established connections (ACK check), ACK check on bidirectional rules,
  23  *      ICMP type check.
  24  *              Wilfred Mollenvanger 7/7/1995.
  25  *      TCP attack protection.
  26  *              Alan Cox 25/8/95, based on information from bugtraq.
  27  *
  28  * Masquerading functionality
  29  *
  30  * Copyright (c) 1994 Pauline Middelink
  31  *
  32  * The pieces which added masquerading functionality are totaly
  33  * my responsibility and have nothing to with the original authors
  34  * copyright or doing.
  35  *
  36  * Parts distributed under GPL.
  37  *
  38  * Fixes:
  39  *      Pauline Middelink       :       Added masquerading.
  40  *      Alan Cox                :       Fixed an error in the merge.
  41  *      Thomas Quinot           :       Fixed port spoofing.
  42  *      Alan Cox                :       Cleaned up retransmits in spoofing.
  43  *
  44  *      All the real work was done by .....
  45  *
  46  */
  47 
  48 
  49 /*
  50  * Copyright (c) 1993 Daniel Boulet
  51  * Copyright (c) 1994 Ugen J.S.Antsilevich
  52  *
  53  * Redistribution and use in source forms, with and without modification,
  54  * are permitted provided that this entire comment appears intact.
  55  *
  56  * Redistribution in binary form may occur without any restrictions.
  57  * Obviously, it would be nice if you gave credit where credit is due
  58  * but requiring it would be too onerous.
  59  *
  60  * This software is provided ``AS IS'' without any warranties of any kind.
  61  */
  62 
  63 #include <linux/config.h>
  64 #include <asm/segment.h>
  65 #include <asm/system.h>
  66 #include <linux/types.h>
  67 #include <linux/kernel.h>
  68 #include <linux/sched.h>
  69 #include <linux/string.h>
  70 #include <linux/errno.h>
  71 #include <linux/config.h>
  72 
  73 #include <linux/socket.h>
  74 #include <linux/sockios.h>
  75 #include <linux/in.h>
  76 #include <linux/inet.h>
  77 #include <linux/netdevice.h>
  78 #include <linux/icmp.h>
  79 #include <linux/udp.h>
  80 #include <net/ip.h>
  81 #include <net/protocol.h>
  82 #include <net/route.h>
  83 #include <net/tcp.h>
  84 #include <net/udp.h>
  85 #include <linux/skbuff.h>
  86 #include <net/sock.h>
  87 #include <net/icmp.h>
  88 #include <linux/ip_fw.h>
  89 #include <net/checksum.h>
  90 #include <linux/proc_fs.h>
  91 #include <linux/stat.h>
  92 
  93 /*
  94  *      Implement IP packet firewall
  95  */
  96 
  97 #ifdef CONFIG_IPFIREWALL_DEBUG 
  98 #define dprintf1(a)             printk(a)
  99 #define dprintf2(a1,a2)         printk(a1,a2)
 100 #define dprintf3(a1,a2,a3)      printk(a1,a2,a3)
 101 #define dprintf4(a1,a2,a3,a4)   printk(a1,a2,a3,a4)
 102 #else
 103 #define dprintf1(a)     
 104 #define dprintf2(a1,a2)
 105 #define dprintf3(a1,a2,a3)
 106 #define dprintf4(a1,a2,a3,a4)
 107 #endif
 108 
 109 #define print_ip(a)      printk("%ld.%ld.%ld.%ld",(ntohl(a)>>24)&0xFF,\
 110                                               (ntohl(a)>>16)&0xFF,\
 111                                               (ntohl(a)>>8)&0xFF,\
 112                                               (ntohl(a))&0xFF);
 113 
 114 #ifdef IPFIREWALL_DEBUG
 115 #define dprint_ip(a)    print_ip(a)
 116 #else
 117 #define dprint_ip(a)    
 118 #endif
 119 
 120 #ifdef CONFIG_IP_FIREWALL
 121 struct ip_fw *ip_fw_fwd_chain;
 122 struct ip_fw *ip_fw_blk_chain;
 123 int ip_fw_blk_policy=IP_FW_F_ACCEPT;
 124 int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
 125 #endif
 126 #ifdef CONFIG_IP_ACCT
 127 struct ip_fw *ip_acct_chain;
 128 #endif
 129 
 130 #define IP_INFO_BLK     0
 131 #define IP_INFO_FWD     1
 132 #define IP_INFO_ACCT    2
 133 
 134 #ifdef CONFIG_IP_MASQUERADE
 135 /*
 136  *      Implement IP packet masquerading
 137  */
 138 
 139 static unsigned short masq_port = PORT_MASQ_BEGIN;
 140 static const char *strProt[] = {"UDP","TCP"};
 141 struct ip_masq *ip_msq_hosts;
 142 
 143 #endif
 144 
 145 /*
 146  *      Returns 1 if the port is matched by the vector, 0 otherwise
 147  */
 148 
 149 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         if (!nports)
 152                 return 1;
 153         if ( range_flag ) 
 154         {
 155                 if ( portptr[0] <= port && port <= portptr[1] ) 
 156                 {
 157                         return( 1 );
 158                 }
 159                 nports -= 2;
 160                 portptr += 2;
 161         }
 162         while ( nports-- > 0 ) 
 163         {
 164                 if ( *portptr++ == port ) 
 165                 {
 166                         return( 1 );
 167                 }
 168         }
 169         return(0);
 170 }
 171 
 172 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 173 
 174 
 175 /*
 176  *      Returns 0 if packet should be dropped, 1 if it should be accepted,
 177  *      and -1 if an ICMP host unreachable packet should be sent.
 178  *      Also does accounting so you can feed it the accounting chain.
 179  *      If opt is set to 1, it means that we do this for accounting
 180  *      purposes (searches all entries and handles fragments different).
 181  *      If opt is set to 2, it doesn't count a matching packet, which
 182  *      is used when calling this for checking purposes (IP_FW_CHK_*).
 183  */
 184 
 185 
 186 int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         struct ip_fw *f;
 189         struct tcphdr           *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
 190         struct udphdr           *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
 191         struct icmphdr          *icmp=(struct icmphdr *)((unsigned long *)ip+ip->ihl);
 192         __u32                   src, dst;
 193         __u16                   src_port=0, dst_port=0, icmp_type=0;
 194         unsigned short          f_prt=0, prt;
 195         char                    notcpsyn=1, notcpack=1, match;
 196         unsigned short          f_flag;
 197         unsigned short          offset;
 198 
 199         /*
 200          *      If the chain is empty follow policy. The BSD one
 201          *      accepts anything giving you a time window while
 202          *      flushing and rebuilding the tables.
 203          */
 204          
 205         src = ip->saddr;
 206         dst = ip->daddr;
 207 
 208         /* 
 209          *      This way we handle fragmented packets.
 210          *      we ignore all fragments but the first one
 211          *      so the whole packet can't be reassembled.
 212          *      This way we relay on the full info which
 213          *      stored only in first packet.
 214          *
 215          *      Note that this theoretically allows partial packet
 216          *      spoofing. Not very dangerous but paranoid people may
 217          *      wish to play with this. It also allows the so called
 218          *      "fragment bomb" denial of service attack on some types
 219          *      of system.
 220          */
 221 
 222         offset = ntohs(ip->frag_off) & IP_OFFSET;
 223         
 224         /*
 225          *      Don't allow a fragment of TCP 8 bytes in. Nobody
 226          *      normal causes this. Its a cracker trying to break
 227          *      in by doing a flag overwrite to pass the direction
 228          *      checks.
 229          */
 230          
 231         if (offset == 1 && ip->protocol == IPPROTO_TCP)
 232                 return FW_BLOCK;
 233                 
 234         if (offset!=0 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
 235                         ip->protocol == IPPROTO_UDP))
 236                 return FW_ACCEPT;
 237                 
 238         /*
 239          *       Header fragment for TCP is too small to check the bits.
 240          */
 241          
 242         if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))
 243                 return FW_BLOCK;
 244         
 245         /*
 246          *      Too short.
 247          */
 248          
 249         else if(ntohs(ip->tot_len)<8+(ip->ihl<<2))
 250                 return FW_BLOCK;
 251                 
 252         src = ip->saddr;
 253         dst = ip->daddr;
 254 
 255         /*
 256          *      If we got interface from which packet came
 257          *      we can use the address directly. This is unlike
 258          *      4.4BSD derived systems that have an address chain
 259          *      per device. We have a device per address with dummy
 260          *      devices instead.
 261          */
 262          
 263         dprintf1("Packet ");
 264         switch(ip->protocol) 
 265         {
 266                 case IPPROTO_TCP:
 267                         dprintf1("TCP ");
 268                         /* ports stay 0 if it is not the first fragment */
 269                         if (offset!=0) {
 270                                 src_port=ntohs(tcp->source);
 271                                 dst_port=ntohs(tcp->dest);
 272                                 if(tcp->ack)
 273                                         /* We *DO* have ACK, value FALSE */
 274                                         notcpack=0;
 275                                 if(tcp->syn && notcpack)
 276                                         /* We *DO* have SYN, value FALSE */
 277                                         notcpsyn=0;
 278                         }
 279                         prt=IP_FW_F_TCP;
 280                         break;
 281                 case IPPROTO_UDP:
 282                         dprintf1("UDP ");
 283                         /* ports stay 0 if it is not the first fragment */
 284                         if (offset!=0) {
 285                                 src_port=ntohs(udp->source);
 286                                 dst_port=ntohs(udp->dest);
 287                         }
 288                         prt=IP_FW_F_UDP;
 289                         break;
 290                 case IPPROTO_ICMP:
 291                         icmp_type=(__u16)(icmp->type);
 292                         dprintf2("ICMP:%d ",icmp_type);
 293                         prt=IP_FW_F_ICMP;
 294                         break;
 295                 default:
 296                         dprintf2("p=%d ",ip->protocol);
 297                         prt=IP_FW_F_ALL;
 298                         break;
 299         }
 300 #ifdef CONFIG_IP_FIREWALL_DEBUG
 301         dprint_ip(ip->saddr);
 302         
 303         if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
 304                 /* This will print 0 when it is not the first fragment! */
 305                 dprintf2(":%d ", src_port);
 306         dprint_ip(ip->daddr);
 307         if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
 308                 /* This will print 0 when it is not the first fragment! */
 309                 dprintf2(":%d ",dst_port);
 310         dprintf1("\n");
 311 #endif  
 312 
 313         for (f=chain;f;f=f->fw_next) 
 314         {
 315                 /*
 316                  *      This is a bit simpler as we don't have to walk
 317                  *      an interface chain as you do in BSD - same logic
 318                  *      however.
 319                  */
 320 
 321                 /*
 322                  *      Match can become 0x01 (a "normal" match was found),
 323                  *      0x02 (a reverse match was found), and 0x03 (the
 324                  *      IP addresses match in both directions).
 325                  *      Now we know in which direction(s) we should look
 326                  *      for a match for the TCP/UDP ports.  Both directions
 327                  *      might match (e.g., when both addresses are on the
 328                  *      same network for which an address/mask is given), but
 329                  *      the ports might only match in one direction.
 330                  *      This was obviously wrong in the original BSD code.
 331                  */
 332                 match = 0x00;
 333 
 334                 if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
 335                 &&  (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
 336                         /* normal direction */
 337                         match |= 0x01;
 338 
 339                 if ((f->fw_flg & IP_FW_F_BIDIR) &&
 340                     (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
 341                 &&  (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
 342                         /* reverse direction */
 343                         match |= 0x02;
 344 
 345                 if (match)
 346                 {
 347                         /*
 348                          *      Look for a VIA match 
 349                          */
 350                         if(f->fw_via.s_addr && rif)
 351                         {
 352                                 if(rif->pa_addr!=f->fw_via.s_addr)
 353                                         continue;       /* Mismatch */
 354                         }
 355                         /*
 356                          *      Drop through - this is a match
 357                          */
 358                 }
 359                 else
 360                         continue;
 361 
 362                 /*
 363                  *      Ok the chain addresses match.
 364                  */
 365 
 366                 f_prt=f->fw_flg&IP_FW_F_KIND;
 367                 if (f_prt!=IP_FW_F_ALL) 
 368                 {
 369                         /*
 370                          * This is actually buggy as if you set SYN flag 
 371                          * on UDP or ICMP firewall it will never work,but 
 372                          * actually it is a concern of software which sets
 373                          * firewall entries.
 374                          */
 375                          
 376                          if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
 377                                 continue;
 378 
 379                         /*
 380                          * When a bidirectional rule is used we only check
 381                          * for ack bits on reverse matches. This way it's
 382                          * easy to set up rules which only allow connections
 383                          * initiated from "normal" match adresses.
 384                          */
 385 
 386                         if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
 387                                 if(f->fw_flg&IP_FW_F_BIDIR) {
 388                                         if(match & 0x02)
 389                                                 continue;
 390                                 } else
 391                                         continue;
 392 
 393                         /*
 394                          *      Specific firewall - packet's protocol
 395                          *      must match firewall's.
 396                          */
 397 
 398                         if(prt!=f_prt)
 399                                 continue;
 400                                 
 401                         if((prt==IP_FW_F_ICMP &&
 402                                 ! port_match(&f->fw_pts[0], f->fw_nsp,
 403                                         icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
 404                             !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
 405                                 port_match(&f->fw_pts[0], f->fw_nsp, src_port,
 406                                         f->fw_flg&IP_FW_F_SRNG) &&
 407                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
 408                                         f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
 409                                 port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
 410                                         f->fw_flg&IP_FW_F_SRNG) &&
 411                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
 412                                         f->fw_flg&IP_FW_F_DRNG))))
 413                         {
 414                                 continue;
 415                         }
 416                 }
 417 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 418                 /*
 419                  * VERY ugly piece of code which actually
 420                  * makes kernel printf for denied packets...
 421                  */
 422 
 423                 if (f->fw_flg & IP_FW_F_PRN)
 424                 {
 425                         if(opt != 1) {
 426                                 if(f->fw_flg&IP_FW_F_ACCEPT)
 427                                         printk("Accept ");
 428                                 else if(f->fw_flg&IP_FW_F_ICMPRPL)
 429                                         printk("Reject ");
 430                                 else
 431                                         printk("Deny ");
 432                         }
 433                         switch(ip->protocol)
 434                         {
 435                                 case IPPROTO_TCP:
 436                                         printk("TCP ");
 437                                         break;
 438                                 case IPPROTO_UDP:
 439                                         printk("UDP ");
 440                                 case IPPROTO_ICMP:
 441                                         printk("ICMP ");
 442                                         break;
 443                                 default:
 444                                         printk("p=%d ",ip->protocol);
 445                                         break;
 446                         }
 447                         print_ip(ip->saddr);
 448                         if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
 449                                 printk(":%d", src_port);
 450                         printk(" ");
 451                         print_ip(ip->daddr);
 452                         if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
 453                                 printk(":%d",dst_port);
 454                         printk("\n");
 455                 }
 456 #endif          
 457                 if (opt != 2) {
 458                         f->fw_bcnt+=ntohs(ip->tot_len);
 459                         f->fw_pcnt++;
 460                 }
 461                 if (opt != 1)
 462                         break;
 463         } /* Loop */
 464         
 465         if(opt == 1)
 466                 return 0;
 467 
 468         /*
 469          * We rely on policy defined in the rejecting entry or, if no match
 470          * was found, we rely on the general policy variable for this type
 471          * of firewall.
 472          */
 473 
 474         if(f!=NULL)     /* A match was found */
 475                 f_flag=f->fw_flg;
 476         else
 477                 f_flag=policy;
 478         if(f_flag&IP_FW_F_ACCEPT)
 479                 return ((f_flag&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT);
 480         if(f_flag&IP_FW_F_ICMPRPL)
 481                 return FW_REJECT;
 482         return FW_BLOCK;
 483 }
 484 
 485 #ifdef CONFIG_IP_MASQUERADE
 486 
 487 static void masq_expire(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489         struct ip_masq *ms = (struct ip_masq *)data;
 490         struct ip_masq *old,*cur;
 491         unsigned long flags;
 492 
 493 #ifdef DEBUG_MASQ
 494         printk("Masqueraded %s %lX:%X expired\n",
 495                         strProt[ms->protocol==IPPROTO_TCP],
 496                         ntohl(ms->src),ntohs(ms->sport));
 497 #endif
 498         
 499         save_flags(flags);
 500         cli();
 501 
 502         /* delete from list of hosts */
 503         old = NULL;
 504         cur = ip_msq_hosts;
 505         while (cur!=NULL) {
 506                 if (cur==ms) {
 507                         if (old==NULL) ip_msq_hosts = ms->next;
 508                         else old->next = ms->next;
 509                         kfree_s(ms,sizeof(*ms));
 510                         break;
 511                 }
 512                 old = cur;
 513                 cur=cur->next;
 514         }
 515         restore_flags(flags);
 516 }
 517 
 518 /*
 519  * Create a new masquerade list entry, also allocate an
 520  * unused mport, keeping the portnumber between the
 521  * given boundaries MASQ_BEGIN and MASQ_END.
 522  *
 523  * FIXME: possible deadlock if all free ports are exhausted! 
 524  */
 525 static struct ip_masq *alloc_masq_entry(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 526 {
 527         struct ip_masq *ms, *mst;
 528         unsigned long flags;
 529 
 530         ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
 531         if (ms==NULL) 
 532                 return NULL;
 533 
 534         memset(ms,0,sizeof(*ms));
 535         init_timer(&ms->timer);
 536         ms->timer.data     = (unsigned long)ms;
 537         ms->timer.function = masq_expire;
 538 
 539         save_flags(flags);
 540         cli();
 541         do 
 542         {
 543                 /* Try the next available port number */
 544                 ms->mport = htons(masq_port++);
 545                 if (masq_port==PORT_MASQ_END)
 546                         masq_port = PORT_MASQ_BEGIN;
 547 
 548                 /* Now hunt through the used ports to see if
 549                  * this port is in use... */
 550                 mst = ip_msq_hosts;
 551                 while (mst && mst->mport!=ms->mport)
 552                         mst = mst->next;
 553         }
 554         while (mst!=NULL); 
 555 
 556         /* add new entry in front of list to minimize lookup-time */
 557         ms->next  = ip_msq_hosts;
 558         ip_msq_hosts = ms;
 559         restore_flags(flags);
 560 
 561         return ms;
 562 }
 563 
 564 /*
 565  * When passing an FTP 'PORT' command, try to replace the IP
 566  * address with an newly assigned (masquereded) port on this
 567  * host, so the ftp-data connect FROM the site will succeed...
 568  *
 569  * Also, when the size of the packet changes, create an delta
 570  * offset, which will be added to every th->seq (and subtracted for
 571  * (th->acqseq) whose seq > init_seq.
 572  *
 573  * Not for the faint of heart!
 574  */
 575 
 576 static struct sk_buff *revamp(struct sk_buff *skb, struct device *dev, struct ip_masq *ftp)
     /* [previous][next][first][last][top][bottom][index][help] */
 577 {
 578         struct iphdr *iph = skb->h.iph;
 579         struct tcphdr *th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
 580         struct sk_buff *skb2;
 581         char *p, *data = (char *)&th[1];
 582         unsigned char p1,p2,p3,p4,p5,p6;
 583         unsigned long from;
 584         unsigned short port;
 585         struct ip_masq *ms;
 586         char buf[24];           /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
 587         int diff;
 588         
 589         /*
 590          * Adjust seq and ack_seq with delta-offset for
 591          * the packets AFTER this one...
 592          */
 593         if (ftp->delta && after(ftp->init_seq,th->seq)) 
 594         {
 595                 th->seq += ftp->delta;
 596 /*              th->ack_seq += ftp->delta;*/
 597         }
 598 
 599         while (skb->len - ((unsigned char *)data - skb->h.raw) > 18)
 600         {
 601                 if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5)) 
 602                 {
 603                         data ++;
 604                         continue;
 605                 }
 606                 p = data+5;
 607                 p1 = simple_strtoul(data+5,&data,10);
 608                 if (*data!=',')
 609                         continue;
 610                 p2 = simple_strtoul(data+1,&data,10);
 611                 if (*data!=',')
 612                         continue;
 613                 p3 = simple_strtoul(data+1,&data,10);
 614                 if (*data!=',')
 615                         continue;
 616                 p4 = simple_strtoul(data+1,&data,10);
 617                 if (*data!=',')
 618                         continue;
 619                 p5 = simple_strtoul(data+1,&data,10);
 620                 if (*data!=',')
 621                         continue;
 622                 p6 = simple_strtoul(data+1,&data,10);
 623                 if (*data!='\r' && *data!='\n')
 624                         continue;
 625 
 626                 from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
 627                 port = (p5<<8) | p6;
 628                 printk("PORT %lX:%X detected\n",from,port);
 629         
 630                 /*
 631                  * Now create an masquerade entry for it
 632                  */
 633                 ms = alloc_masq_entry();
 634                 if (ms==NULL)
 635                         return skb;
 636                 ms->protocol = IPPROTO_TCP;
 637                 ms->src      = htonl(from);     /* derived from PORT cmd */
 638                 ms->sport    = htons(port);     /* derived from PORT cmd */
 639                 ms->dst      = iph->daddr;
 640                 ms->dport    = htons(20);       /* ftp-data */
 641                 ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP_FIN;
 642                 add_timer(&ms->timer);
 643 
 644                 /*
 645                  * Replace the old PORT with the new one
 646                  */
 647                 from = ntohl(dev->pa_addr);
 648                 port = ntohs(ms->mport);
 649                 sprintf(buf,"%ld,%ld,%ld,%ld,%d,%d",
 650                         from>>24&255,from>>16&255,from>>8&255,from&255,
 651                         port>>8&255,port&255);
 652 
 653                 /*
 654                  * Calculate required delta-offset to keep TCP happy
 655                  */
 656                 
 657                 diff = strlen(buf) - (data-p);
 658                 
 659                 /*
 660                  *      No shift.
 661                  */
 662                  
 663                 if (diff==0) 
 664                 {
 665                         /*
 666                          * simple case, just replace the old PORT cmd
 667                          */
 668                         ftp->init_seq = 0;
 669                         memcpy(p,buf,strlen(buf));
 670                         return skb;
 671                 }
 672  
 673                 /*
 674                  *      If the PORT command we have fiddled is the first, or is a
 675                  *      resend don't do the delta shift again. Doesn't work for
 676                  *      pathological cases, but we would need a history for that.
 677                  *      Also fails if you send 2^31 bytes of data down the link 
 678                  *      after the first port command.
 679                  *
 680                  *      FIXME: use ftp->init_seq_valid - 0 is a valid sequence.
 681                  */
 682                  
 683                 if(!ftp->init_seq || after(ftp->init_seq,th->seq))
 684                         ftp->delta+=diff;
 685                 /*
 686                  * Sizes differ, make a copy
 687                  */
 688  printk("MASQUERADE: resizing needed for %d bytes (%ld)\n",ftp->delta, skb->len);
 689                 if (!ftp->init_seq)
 690                         ftp->init_seq = th->seq;
 691  
 692                 skb2 = alloc_skb(MAX_HEADER + skb->len+ftp->delta, GFP_ATOMIC);
 693                 if (skb2 == NULL) {
 694                         printk("MASQUERADE: No memory available\n");
 695                         return skb;
 696                 }
 697                 skb2->free = skb->free;
 698                 skb_reserve(skb2,MAX_HEADER);
 699                 skb_put(skb2,skb->len + ftp->delta);
 700 /*              skb2->h.raw = &skb2->data[skb->h.raw - skb->data];*/
 701                 skb2->h.raw = skb2->data + (skb->h.raw - skb->data);
 702                 iph=skb2->h.iph;
 703  
 704                 /*
 705                  *      Copy the packet data into the new buffer.
 706                  *      Thereby replacing the PORT cmd.
 707                  */
 708                 memcpy(skb2->data, skb->data, (p - (char *)skb->data));
 709                 memcpy(&skb2->data[(p - (char *)skb->data)], buf, strlen(buf));
 710                 memcpy(&skb2->data[(p - (char *)skb->data) + strlen(buf)], data,
 711                         skb->len - (data-(char *)skb->data));
 712 
 713                 /*
 714                  * Problem, how to replace the new skb with old one,
 715                  * preferably inplace, so all the pointers in the
 716                  * calling tree keep ok :(
 717                  */
 718                 kfree_skb(skb, FREE_WRITE);
 719                 return skb2;
 720         }
 721         return skb;
 722 }
 723 
 724 static void recalc_check(struct udphdr *uh, unsigned long saddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 725         unsigned long daddr, int len)
 726 {
 727         uh->check=0;
 728         uh->check=csum_tcpudp_magic(saddr,daddr,len,
 729                 IPPROTO_UDP, csum_partial((char *)uh,len,0));
 730         if(uh->check==0)
 731                 uh->check=0xFFFF;
 732 }
 733         
 734 void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 735 {
 736         struct sk_buff  *skb=*skb_ptr;
 737         struct iphdr    *iph = skb->h.iph;
 738         unsigned short  *portptr;
 739         struct ip_masq  *ms;
 740         int             size;
 741 
 742         /*
 743          * We can only masquerade protocols with ports...
 744          */
 745 
 746         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 747                 return;
 748  
 749         /*
 750          *      Now hunt the list to see if we have an old entry
 751          */
 752 
 753         portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
 754         ms = ip_msq_hosts;
 755 
 756 #ifdef DEBUG_MASQ
 757         printk("Outgoing %s %lX:%X -> %lX:%X\n",
 758                 strProt[iph->protocol==IPPROTO_TCP],
 759                 ntohl(iph->saddr), ntohs(portptr[0]),
 760                 ntohl(iph->daddr), ntohs(portptr[1]));
 761 #endif
 762         while (ms!=NULL) 
 763         {
 764                 if (iph->protocol == ms->protocol &&
 765                     iph->saddr == ms->src   && iph->daddr == ms->dst &&
 766                     portptr[0] == ms->sport && portptr[1] == ms->dport) 
 767                 {
 768                         del_timer(&ms->timer);
 769                         break;
 770                 }
 771                 ms = ms->next;
 772         }
 773 
 774         /*
 775          *      Nope, not found, create a new entry for it
 776          */
 777          
 778         if (ms==NULL) 
 779         {
 780                 ms = alloc_masq_entry();
 781                 if (ms==NULL) 
 782                 {
 783                         printk("MASQUERADE: no memory left !\n");
 784                         return;
 785                 }
 786                 ms->protocol = iph->protocol;
 787                 ms->src      = iph->saddr;
 788                 ms->dst      = iph->daddr;
 789                 ms->sport    = portptr[0];
 790                 ms->dport    = portptr[1];
 791         }
 792  
 793         /*
 794          *      Change the fragments origin
 795          */
 796          
 797         size = skb->len - ((unsigned char *)portptr - skb->h.raw);
 798         iph->saddr = dev->pa_addr; /* my own address */
 799         portptr[0] = ms->mport;
 800  
 801         /*
 802          *      Adjust packet accordingly to protocol
 803          */
 804          
 805         if (iph->protocol==IPPROTO_UDP) 
 806         {
 807                 ms->timer.expires = jiffies+MASQUERADE_EXPIRE_UDP;
 808                 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 809         }
 810         else 
 811         {
 812                 struct tcphdr *th;
 813                 if (portptr[1]==htons(21)) 
 814                 {
 815                         skb = revamp(*skb_ptr, dev, ms);
 816                         *skb_ptr = skb;
 817                         iph = skb->h.iph;
 818                         portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
 819                         size = skb->len - ((unsigned char *)portptr-skb->h.raw);
 820                 }
 821                 th = (struct tcphdr *)portptr;
 822  
 823                 /*
 824                  *      Timeout depends if FIN packet was seen
 825                  */
 826                 if (ms->sawfin || th->fin) 
 827                 {
 828                         ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP_FIN;
 829                         ms->sawfin = 1;
 830                 }
 831                 else ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP;
 832  
 833                 tcp_send_check(th,iph->saddr,iph->daddr,size,skb->sk);
 834         }
 835         add_timer(&ms->timer);
 836         ip_send_check(iph);
 837  
 838  #ifdef DEBUG_MASQ
 839         printk("O-routed from %lX:%X over %s\n",ntohl(dev->pa_addr),ntohs(ms->mport),dev->name);
 840  #endif
 841  }
 842  
 843  /*
 844   *     Check if it's an masqueraded port, look it up,
 845   *     and send it on it's way...
 846   *
 847   *     Better not have many hosts using the designated portrange
 848   *     as 'normal' ports, or you'll be spending lots of time in
 849   *     this function.
 850   */
 851 
 852 int ip_fw_demasquerade(struct sk_buff *skb_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         struct iphdr    *iph = skb_ptr->h.iph;
 855         unsigned short  *portptr;
 856         struct ip_masq  *ms;
 857         struct tcphdr   *th = (struct tcphdr *)(skb_ptr->h.raw+(iph->ihl<<2));
 858  
 859         if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
 860                 return 0;
 861  
 862         portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
 863         if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
 864             ntohs(portptr[1]) > PORT_MASQ_END)
 865                 return 0;
 866  
 867 #ifdef DEBUG_MASQ
 868         printk("Incoming %s %lX:%X -> %lX:%X\n",
 869                 strProt[iph->protocol==IPPROTO_TCP],
 870                 ntohl(iph->saddr), ntohs(portptr[0]),
 871                 ntohl(iph->daddr), ntohs(portptr[1]));
 872 #endif
 873         /*
 874          * reroute to original host:port if found...
 875          *
 876          * NB. Cannot check destination address, just for the incoming port.
 877          * reason: archie.doc.ac.uk has 6 interfaces, you send to
 878          * phoenix and get a reply from any other interface(==dst)!
 879          *
 880          * [Only for UDP] - AC
 881          */
 882         ms = ip_msq_hosts;
 883         while (ms!=NULL) 
 884         {
 885                 if (iph->protocol==ms->protocol &&
 886                     (iph->saddr==ms->dst || iph->protocol==IPPROTO_UDP) && 
 887                     portptr[0]==ms->dport &&
 888                     portptr[1]==ms->mport)
 889                 {
 890                         int size = skb_ptr->len - ((unsigned char *)portptr - skb_ptr->h.raw);
 891                         iph->daddr = ms->src;
 892                         portptr[1] = ms->sport;
 893                         
 894                         /*
 895                          * Yug! adjust UDP/TCP and IP checksums
 896                          */
 897                         if (iph->protocol==IPPROTO_UDP)
 898                                 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
 899                         else
 900                         {
 901                                 /*
 902                                  * Adjust seq and ack_seq with delta-offset for
 903                                  * the packets AFTER this one...
 904                                  */
 905                                 if (ms->delta && after(ms->init_seq,th->ack_seq)) 
 906                                 {
 907 /*                                      th->seq += ms->delta;*/
 908                                         th->ack_seq -= ms->delta;
 909                                 }
 910                                 tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb_ptr->sk);
 911                         }
 912                         ip_send_check(iph);
 913 #ifdef DEBUG_MASQ
 914                         printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
 915 #endif
 916                         return 1;
 917                 }
 918                 ms = ms->next;
 919         }
 920  
 921         /* sorry, all this trouble for a no-hit :) */
 922         return 0;
 923 }
 924 #endif
 925   
 926 
 927 
 928 static void zero_fw_chain(struct ip_fw *chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 929 {
 930         struct ip_fw *ctmp=chainptr;
 931         while(ctmp) 
 932         {
 933                 ctmp->fw_pcnt=0L;
 934                 ctmp->fw_bcnt=0L;
 935                 ctmp=ctmp->fw_next;
 936         }
 937 }
 938 
 939 static void free_fw_chain(struct ip_fw *volatile* chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 940 {
 941         unsigned long flags;
 942         save_flags(flags);
 943         cli();
 944         while ( *chainptr != NULL ) 
 945         {
 946                 struct ip_fw *ftmp;
 947                 ftmp = *chainptr;
 948                 *chainptr = ftmp->fw_next;
 949                 kfree_s(ftmp,sizeof(*ftmp));
 950         }
 951         restore_flags(flags);
 952 }
 953 
 954 /* Volatiles to keep some of the compiler versions amused */
 955 
 956 static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 957 {
 958         struct ip_fw *ftmp;
 959         struct ip_fw *chtmp=NULL;
 960         struct ip_fw *volatile chtmp_prev=NULL;
 961         unsigned long flags;
 962         unsigned long m_src_mask,m_dst_mask;
 963         unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
 964         unsigned short n_sr,n_dr,o_sr,o_dr; 
 965         unsigned short oldkind,newkind;
 966         int addb4=0;
 967         int n_o,n_n;
 968 
 969         save_flags(flags);
 970 
 971         ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
 972         if ( ftmp == NULL ) 
 973         {
 974 #ifdef DEBUG_CONFIG_IP_FIREWALL
 975                 printk("ip_fw_ctl:  malloc said no\n");
 976 #endif
 977                 return( ENOMEM );
 978         }
 979 
 980         memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
 981 
 982         ftmp->fw_pcnt=0L;
 983         ftmp->fw_bcnt=0L;
 984 
 985         ftmp->fw_next = NULL;
 986 
 987         cli();
 988 
 989         if (*chainptr==NULL)
 990         {
 991                 *chainptr=ftmp;
 992         }
 993         else
 994         {
 995                 chtmp_prev=NULL;
 996                 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next) 
 997                 {
 998                         addb4=0;
 999                         newkind=ftmp->fw_flg & IP_FW_F_KIND;
1000                         oldkind=chtmp->fw_flg & IP_FW_F_KIND;
1001         
1002                         if (newkind!=IP_FW_F_ALL 
1003                                 &&  oldkind!=IP_FW_F_ALL
1004                                 &&  oldkind!=newkind) 
1005                         {
1006                                 chtmp_prev=chtmp;
1007                                 continue;
1008                         }
1009 
1010                         /*
1011                          *      Very very *UGLY* code...
1012                          *      Sorry,but i had to do this....
1013                          */
1014 
1015                         n_sa=ntohl(ftmp->fw_src.s_addr);
1016                         n_da=ntohl(ftmp->fw_dst.s_addr);
1017                         n_sm=ntohl(ftmp->fw_smsk.s_addr);
1018                         n_dm=ntohl(ftmp->fw_dmsk.s_addr);
1019 
1020                         o_sa=ntohl(chtmp->fw_src.s_addr);
1021                         o_da=ntohl(chtmp->fw_dst.s_addr);
1022                         o_sm=ntohl(chtmp->fw_smsk.s_addr);
1023                         o_dm=ntohl(chtmp->fw_dmsk.s_addr);
1024 
1025                         m_src_mask = o_sm & n_sm;
1026                         m_dst_mask = o_dm & n_dm;
1027 
1028                         if ((o_sa & m_src_mask) == (n_sa & m_src_mask)) 
1029                         {
1030                                 if (n_sm > o_sm) 
1031                                         addb4++;
1032                                 if (n_sm < o_sm) 
1033                                         addb4--;
1034                         }
1035 
1036                         if ((o_da & m_dst_mask) == (n_da & m_dst_mask)) 
1037                         {
1038                                 if (n_dm > o_dm)
1039                                         addb4++;
1040                                 if (n_dm < o_dm)
1041                                         addb4--;
1042                         }
1043 
1044                         if (((o_da & o_dm) == (n_da & n_dm))
1045                                 &&((o_sa & o_sm) == (n_sa & n_sm)))
1046                         {
1047                                 if (newkind!=IP_FW_F_ALL &&
1048                                         oldkind==IP_FW_F_ALL)
1049                                         addb4++;
1050                                 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
1051                                         ||  oldkind==IP_FW_F_UDP)) 
1052                                 {
1053 
1054                                         /*
1055                                          *      Here the main idea is to check the size
1056                                          *      of port range which the frwl covers
1057                                          *      We actually don't check their values but
1058                                          *      just the wideness of range they have
1059                                          *      so that less wide ranges or single ports
1060                                          *      go first and wide ranges go later. No ports
1061                                          *      at all treated as a range of maximum number
1062                                          *      of ports.
1063                                          */
1064 
1065                                         if (ftmp->fw_flg & IP_FW_F_SRNG) 
1066                                                 n_sr=ftmp->fw_pts[1]-ftmp->fw_pts[0];
1067                                         else 
1068                                                 n_sr=(ftmp->fw_nsp)?
1069                                                         ftmp->fw_nsp : 0xFFFF;
1070                                                 
1071                                         if (chtmp->fw_flg & IP_FW_F_SRNG) 
1072                                                 o_sr=chtmp->fw_pts[1]-chtmp->fw_pts[0];
1073                                         else 
1074                                                 o_sr=(chtmp->fw_nsp)?chtmp->fw_nsp : 0xFFFF;
1075 
1076                                         if (n_sr<o_sr)
1077                                                 addb4++;
1078                                         if (n_sr>o_sr)
1079                                                 addb4--;
1080                                         
1081                                         n_n=ftmp->fw_nsp;
1082                                         n_o=chtmp->fw_nsp;
1083         
1084                                         /*
1085                                          * Actually this cannot happen as the frwl control
1086                                          * procedure checks for number of ports in source and
1087                                          * destination range but we will try to be more safe.
1088                                          */
1089                                          
1090                                         if ((n_n>(IP_FW_MAX_PORTS-2)) ||
1091                                                 (n_o>(IP_FW_MAX_PORTS-2)))
1092                                                 goto skip_check;
1093 
1094                                         if (ftmp->fw_flg & IP_FW_F_DRNG) 
1095                                                n_dr=ftmp->fw_pts[n_n+1]-ftmp->fw_pts[n_n];
1096                                         else 
1097                                                n_dr=(ftmp->fw_ndp)? ftmp->fw_ndp : 0xFFFF;
1098 
1099                                         if (chtmp->fw_flg & IP_FW_F_DRNG) 
1100                                                 o_dr=chtmp->fw_pts[n_o+1]-chtmp->fw_pts[n_o];
1101                                         else 
1102                                                 o_dr=(chtmp->fw_ndp)? chtmp->fw_ndp : 0xFFFF;
1103                                         if (n_dr<o_dr)
1104                                                 addb4++;
1105                                         if (n_dr>o_dr)
1106                                                 addb4--;
1107 skip_check:
1108                                 }
1109                                 /* finally look at the interface address */
1110                                 if ((addb4 == 0) && ftmp->fw_via.s_addr &&
1111                                                 !(chtmp->fw_via.s_addr))
1112                                         addb4++;
1113                         }
1114                         if (addb4>0) 
1115                         {
1116                                 if (chtmp_prev) 
1117                                 {
1118                                         chtmp_prev->fw_next=ftmp; 
1119                                         ftmp->fw_next=chtmp;
1120                                 } 
1121                                 else 
1122                                 {
1123                                         *chainptr=ftmp;
1124                                         ftmp->fw_next=chtmp;
1125                                 }
1126                                 restore_flags(flags);
1127                                 return 0;
1128                         }
1129                         chtmp_prev=chtmp;
1130                 }
1131         }
1132         
1133         if (chtmp_prev)
1134                 chtmp_prev->fw_next=ftmp;
1135         else
1136                 *chainptr=ftmp;
1137         restore_flags(flags);
1138         return(0);
1139 }
1140 
1141 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
1142 {
1143         struct ip_fw    *ftmp,*ltmp;
1144         unsigned short  tport1,tport2,tmpnum;
1145         char            matches,was_found;
1146         unsigned long   flags;
1147 
1148         save_flags(flags);
1149         cli();
1150 
1151         ftmp=*chainptr;
1152 
1153         if ( ftmp == NULL ) 
1154         {
1155 #ifdef DEBUG_CONFIG_IP_FIREWALL
1156                 printk("ip_fw_ctl:  chain is empty\n");
1157 #endif
1158                 restore_flags(flags);
1159                 return( EINVAL );
1160         }
1161 
1162         ltmp=NULL;
1163         was_found=0;
1164 
1165         while( ftmp != NULL )
1166         {
1167                 matches=1;
1168              if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr 
1169                      ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
1170                      ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
1171                      ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
1172                      ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
1173                      ||  ftmp->fw_flg!=frwl->fw_flg)
1174                         matches=0;
1175 
1176                 tport1=ftmp->fw_nsp+ftmp->fw_ndp;
1177                 tport2=frwl->fw_nsp+frwl->fw_ndp;
1178                 if (tport1!=tport2)
1179                         matches=0;
1180                 else if (tport1!=0)
1181                 {
1182                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
1183                         if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
1184                                 matches=0;
1185                 }
1186                 if(matches)
1187                 {
1188                         was_found=1;
1189                         if (ltmp)
1190                         {
1191                                 ltmp->fw_next=ftmp->fw_next;
1192                                 kfree_s(ftmp,sizeof(*ftmp));
1193                                 ftmp=ltmp->fw_next;
1194                         }
1195                         else
1196                         {
1197                                 *chainptr=ftmp->fw_next; 
1198                                 kfree_s(ftmp,sizeof(*ftmp));
1199                                 ftmp=*chainptr;
1200                         }       
1201                 }
1202                 else
1203                 {
1204                         ltmp = ftmp;
1205                         ftmp = ftmp->fw_next;
1206                  }
1207         }
1208         restore_flags(flags);
1209         if (was_found)
1210                 return 0;
1211         else
1212                 return(EINVAL);
1213 }
1214 
1215 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
1216 
1217 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
1218 {
1219 
1220         if ( len != sizeof(struct ip_fw) )
1221         {
1222 #ifdef DEBUG_CONFIG_IP_FIREWALL
1223                 printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
1224 #endif
1225                 return(NULL);
1226         }
1227 
1228         if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
1229         {
1230 #ifdef DEBUG_CONFIG_IP_FIREWALL
1231                 printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
1232                         frwl->fw_flg);
1233 #endif
1234                 return(NULL);
1235         }
1236 
1237         if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 ) 
1238         {
1239 #ifdef DEBUG_CONFIG_IP_FIREWALL
1240                 printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
1241                         frwl->fw_nsp);
1242 #endif
1243                 return(NULL);
1244         }
1245 
1246         if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 ) 
1247         {
1248 #ifdef DEBUG_CONFIG_IP_FIREWALL
1249                 printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
1250                         frwl->fw_ndp);
1251 #endif
1252                 return(NULL);
1253         }
1254 
1255         if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS ) 
1256         {
1257 #ifdef DEBUG_CONFIG_IP_FIREWALL
1258                 printk("ip_fw_ctl: too many ports (%d+%d)\n",
1259                         frwl->fw_nsp,frwl->fw_ndp);
1260 #endif
1261                 return(NULL);
1262         }
1263 
1264         return frwl;
1265 }
1266 
1267 
1268 
1269 
1270 #ifdef CONFIG_IP_ACCT
1271 
1272 #if 0
1273 void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
     /* [previous][next][first][last][top][bottom][index][help] */
1274 {
1275         (void) ip_fw_chk(iph, dev, f, 0, 1);
1276         return;
1277 }
1278 #endif
1279 
1280 int ip_acct_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
1281 {
1282         if ( stage == IP_ACCT_FLUSH )
1283         {
1284                 free_fw_chain(&ip_acct_chain);
1285                 return(0);
1286         }  
1287         if ( stage == IP_ACCT_ZERO )
1288         {
1289                 zero_fw_chain(ip_acct_chain);
1290                 return(0);
1291         }
1292         if ( stage == IP_ACCT_ADD
1293           || stage == IP_ACCT_DEL
1294            )
1295         {
1296                 struct ip_fw *frwl;
1297 
1298                 if (!(frwl=check_ipfw_struct(m,len)))
1299                         return (EINVAL);
1300 
1301                 switch (stage) 
1302                 {
1303                         case IP_ACCT_ADD:
1304                                 return( add_to_chain(&ip_acct_chain,frwl));
1305                         case IP_ACCT_DEL:
1306                                 return( del_from_chain(&ip_acct_chain,frwl));
1307                         default:
1308                                 /*
1309                                  *      Should be panic but... (Why ??? - AC)
1310                                  */
1311 #ifdef DEBUG_CONFIG_IP_FIREWALL
1312                                 printk("ip_acct_ctl:  unknown request %d\n",stage);
1313 #endif
1314                                 return(EINVAL);
1315                 }
1316         }
1317 #ifdef DEBUG_CONFIG_IP_FIREWALL
1318         printk("ip_acct_ctl:  unknown request %d\n",stage);
1319 #endif
1320         return(EINVAL);
1321 }
1322 #endif
1323 
1324 #ifdef CONFIG_IP_FIREWALL
1325 int ip_fw_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
1326 {
1327         int ret;
1328 
1329         if ( stage == IP_FW_FLUSH_BLK )
1330         {
1331                 free_fw_chain(&ip_fw_blk_chain);
1332                 return(0);
1333         }  
1334 
1335         if ( stage == IP_FW_FLUSH_FWD )
1336         {
1337                 free_fw_chain(&ip_fw_fwd_chain);
1338                 return(0);
1339         }  
1340 
1341         if ( stage == IP_FW_ZERO_BLK )
1342         {
1343                 zero_fw_chain(ip_fw_blk_chain);
1344                 return(0);
1345         }  
1346 
1347         if ( stage == IP_FW_ZERO_FWD )
1348         {
1349                 zero_fw_chain(ip_fw_fwd_chain);
1350                 return(0);
1351         }  
1352 
1353         if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
1354         {
1355                 int *tmp_policy_ptr;
1356                 tmp_policy_ptr=(int *)m;
1357                 if ( stage == IP_FW_POLICY_BLK )
1358                         ip_fw_blk_policy=*tmp_policy_ptr;
1359                 else
1360                         ip_fw_fwd_policy=*tmp_policy_ptr;
1361                 return 0;
1362         }
1363 
1364         if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
1365         {
1366                 struct device viadev;
1367                 struct ip_fwpkt *ipfwp;
1368                 struct iphdr *ip;
1369 
1370                 if ( len < sizeof(struct ip_fwpkt) )
1371                 {
1372 #ifdef DEBUG_CONFIG_IP_FIREWALL
1373                         printk("ip_fw_ctl: length=%d, expected %d\n",
1374                                 len, sizeof(struct ip_fwpkt));
1375 #endif
1376                         return( EINVAL );
1377                 }
1378 
1379                 ipfwp = (struct ip_fwpkt *)m;
1380                 ip = &(ipfwp->fwp_iph);
1381 
1382                 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
1383                 {
1384 #ifdef DEBUG_CONFIG_IP_FIREWALL
1385                         printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
1386                                         sizeof(struct iphdr)/sizeof(int));
1387 #endif
1388                         return(EINVAL);
1389                 }
1390 
1391                 viadev.pa_addr = ipfwp->fwp_via.s_addr;
1392 
1393                 if ((ret = ip_fw_chk(ip, &viadev,
1394                         stage == IP_FW_CHK_BLK ?
1395                         ip_fw_blk_chain : ip_fw_fwd_chain,
1396                         stage == IP_FW_CHK_BLK ?
1397                         ip_fw_blk_policy : ip_fw_fwd_policy, 2 )) > 0
1398                    )
1399                         return(0);
1400                 else if (ret == -1)     
1401                         return(ECONNREFUSED);
1402                 else
1403                         return(ETIMEDOUT);
1404         }
1405 
1406 /*
1407  *      Here we really working hard-adding new elements
1408  *      to blocking/forwarding chains or deleting 'em
1409  */
1410 
1411         if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
1412                 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
1413                 )
1414         {
1415                 struct ip_fw *frwl;
1416                 frwl=check_ipfw_struct(m,len);
1417                 if (frwl==NULL)
1418                         return (EINVAL);
1419                 
1420                 switch (stage) 
1421                 {
1422                         case IP_FW_ADD_BLK:
1423                                 return(add_to_chain(&ip_fw_blk_chain,frwl));
1424                         case IP_FW_ADD_FWD:
1425                                 return(add_to_chain(&ip_fw_fwd_chain,frwl));
1426                         case IP_FW_DEL_BLK:
1427                                 return(del_from_chain(&ip_fw_blk_chain,frwl));
1428                         case IP_FW_DEL_FWD: 
1429                                 return(del_from_chain(&ip_fw_fwd_chain,frwl));
1430                         default:
1431                         /*
1432                          *      Should be panic but... (Why are BSD people panic obsessed ??)
1433                          */
1434 #ifdef DEBUG_CONFIG_IP_FIREWALL
1435                                 printk("ip_fw_ctl:  unknown request %d\n",stage);
1436 #endif
1437                                 return(EINVAL);
1438                 }
1439         } 
1440 
1441 #ifdef DEBUG_CONFIG_IP_FIREWALL
1442         printk("ip_fw_ctl:  unknown request %d\n",stage);
1443 #endif
1444         return(EINVAL);
1445 }
1446 #endif /* CONFIG_IP_FIREWALL */
1447 
1448 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
1449 
1450 static int ip_chain_procinfo(int stage, char *buffer, char **start,
     /* [previous][next][first][last][top][bottom][index][help] */
1451                              off_t offset, int length, int reset)
1452 {
1453         off_t pos=0, begin=0;
1454         struct ip_fw *i;
1455         unsigned long flags;
1456         int len, p;
1457         
1458 
1459         switch(stage)
1460         {
1461 #ifdef CONFIG_IP_FIREWALL
1462                 case IP_INFO_BLK:
1463                         i = ip_fw_blk_chain;
1464                         len=sprintf(buffer, "IP firewall block rules, default %d\n",
1465                                 ip_fw_blk_policy);
1466                         break;
1467                 case IP_INFO_FWD:
1468                         i = ip_fw_fwd_chain;
1469                         len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1470                                 ip_fw_fwd_policy);
1471                         break;
1472 #endif
1473 #ifdef CONFIG_IP_ACCT
1474                 case IP_INFO_ACCT:
1475                         i = ip_acct_chain;
1476                         len=sprintf(buffer,"IP accounting rules\n");
1477                         break;
1478 #endif
1479                 default:
1480                         /* this should never be reached, but safety first... */
1481                         i = NULL;
1482                         len=0;
1483                         break;
1484         }
1485 
1486         save_flags(flags);
1487         cli();
1488         
1489         while(i!=NULL)
1490         {
1491                 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
1492                         ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
1493                         ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
1494                         ntohl(i->fw_via.s_addr),i->fw_flg);
1495                 len+=sprintf(buffer+len,"%u %u %-9lu %-9lu",
1496                         i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
1497                 for (p = 0; p < IP_FW_MAX_PORTS; p++)
1498                         len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
1499                 buffer[len++]='\n';
1500                 buffer[len]='\0';
1501                 pos=begin+len;
1502                 if(pos<offset)
1503                 {
1504                         len=0;
1505                         begin=pos;
1506                 }
1507                 else if(reset)
1508                 {
1509                         /* This needs to be done at this specific place! */
1510                         i->fw_pcnt=0L;
1511                         i->fw_bcnt=0L;
1512                 }
1513                 if(pos>offset+length)
1514                         break;
1515                 i=i->fw_next;
1516         }
1517         restore_flags(flags);
1518         *start=buffer+(offset-begin);
1519         len-=(offset-begin);
1520         if(len>length)
1521                 len=length;     
1522         return len;
1523 }
1524 #endif
1525 
1526 #ifdef CONFIG_IP_ACCT
1527 
1528 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
1529                             int length, int reset)
1530 {
1531         return ip_chain_procinfo(IP_INFO_ACCT, buffer,start, offset,length,
1532                                  reset);
1533 }
1534 
1535 #endif
1536 
1537 #ifdef CONFIG_IP_FIREWALL
1538 
1539 static int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
1540                               int length, int reset)
1541 {
1542         return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,
1543                                  reset);
1544 }
1545 
1546 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
1547                               int length, int reset)
1548 {
1549         return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,
1550                                  reset);
1551 }
1552 #endif
1553 
1554 #ifdef CONFIG_IP_MASQUERADE
1555 
1556 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
1557                               int length, int unused)
1558 {
1559         off_t pos=0, begin=0;
1560         struct ip_masq *ms;
1561         unsigned long flags;
1562         int len=0;
1563         
1564         len=sprintf(buffer,"Prc FromIP   FPrt ToIP     TPrt Masq Init-seq Delta Expires\n"); 
1565         save_flags(flags);
1566         cli();
1567         
1568         ms=ip_msq_hosts;
1569         while (ms!=NULL) 
1570         {
1571                 int timer_active = del_timer(&ms->timer);
1572                 if (!timer_active)
1573                         ms->timer.expires = jiffies;
1574                 len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08X %5d %lu\n",
1575                         strProt[ms->protocol==IPPROTO_TCP],
1576                         ntohl(ms->src),ntohs(ms->sport),
1577                         ntohl(ms->dst),ntohs(ms->dport),
1578                         ntohs(ms->mport),
1579                         ms->init_seq,ms->delta,ms->timer.expires-jiffies);
1580                 if (timer_active)
1581                         add_timer(&ms->timer);
1582 
1583                 pos=begin+len;
1584                 if(pos<offset) 
1585                 {
1586                         len=0;
1587                         begin=pos;
1588                 }
1589                 if(pos>offset+length)
1590                         break;
1591                 ms=ms->next;
1592         }
1593         restore_flags(flags);
1594         *start=buffer+(offset-begin);
1595         len-=(offset-begin);
1596         if(len>length)
1597                 len=length;
1598         return len;
1599 }
1600   
1601 #endif
1602 
1603 void ip_fw_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1604 {
1605 #ifdef CONFIG_IP_ACCT
1606         proc_net_register(&(struct proc_dir_entry) {
1607                 PROC_NET_IPACCT, 7, "ip_acct",
1608                 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1609                 0, &proc_net_inode_operations,
1610                 ip_acct_procinfo
1611         });
1612 #endif
1613 #ifdef CONFIG_IP_FIREWALL
1614         proc_net_register(&(struct proc_dir_entry) {
1615                 PROC_NET_IPFWBLK, 8, "ip_block",
1616                 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1617                 0, &proc_net_inode_operations,
1618                 ip_fw_blk_procinfo
1619         });
1620         proc_net_register(&(struct proc_dir_entry) {
1621                 PROC_NET_IPFWFWD, 10, "ip_forward",
1622                 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1623                 0, &proc_net_inode_operations,
1624                 ip_fw_fwd_procinfo
1625         });
1626 #endif
1627 #ifdef CONFIG_IP_MASQUERADE
1628         proc_net_register(&(struct proc_dir_entry) {
1629                 PROC_NET_IPMSQHST, 13, "ip_masquerade",
1630                 S_IFREG | S_IRUGO, 1, 0, 0,
1631                 0, &proc_net_inode_operations,
1632                 ip_msqhst_procinfo
1633         });
1634 #endif
1635 }

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