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

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