root/net/inet/ip_fw.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_ip
  2. port_match
  3. ip_fw_chk
  4. ip_acct_cnt
  5. zero_fw_chain
  6. free_fw_chain
  7. add_to_chain
  8. del_from_chain
  9. check_ipfw_struct
  10. ip_acct_ctl
  11. ip_fw_ctl
  12. ip_chain_procinfo
  13. ip_acct_procinfo
  14. ip_fw_blk_procinfo
  15. ip_fw_fwd_procinfo

   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  *
   8  *      Ported from BSD to Linux,
   9  *              Alan Cox 22/Nov/1994.
  10  *
  11  *      All the real work was done by .....
  12  */
  13 
  14 /*
  15  * Copyright (c) 1993 Daniel Boulet
  16  * Copyright (c) 1994 Ugen J.S.Antsilevich
  17  *
  18  * Redistribution and use in source forms, with and without modification,
  19  * are permitted provided that this entire comment appears intact.
  20  *
  21  * Redistribution in binary form may occur without any restrictions.
  22  * Obviously, it would be nice if you gave credit where credit is due
  23  * but requiring it would be too onerous.
  24  *
  25  * This software is provided ``AS IS'' without any warranties of any kind.
  26  */
  27 
  28 #include <asm/segment.h>
  29 #include <asm/system.h>
  30 #include <linux/types.h>
  31 #include <linux/kernel.h>
  32 #include <linux/sched.h>
  33 #include <linux/string.h>
  34 #include <linux/errno.h>
  35 #include <linux/socket.h>
  36 #include <linux/sockios.h>
  37 #include <linux/in.h>
  38 #include <linux/inet.h>
  39 #include <linux/netdevice.h>
  40 #include "ip.h"
  41 #include "protocol.h"
  42 #include "route.h"
  43 #include "tcp.h"
  44 #include <linux/skbuff.h>
  45 #include "sock.h"
  46 #include "icmp.h"
  47 #include <linux/ip_fw.h>
  48 
  49 /*
  50  *      Implement IP packet firewall
  51  */
  52 
  53 #ifdef CONFIG_IP_FIREWALL
  54 struct ip_fw *ip_fw_fwd_chain;
  55 struct ip_fw *ip_fw_blk_chain;
  56 static int ip_fw_policy=1;
  57 #endif
  58 #ifdef CONFIG_IP_ACCT
  59 struct ip_fw *ip_acct_chain;
  60 #endif
  61 
  62 
  63 extern inline void print_ip(unsigned long xaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         unsigned long addr = ntohl(xaddr);
  66         printk("%ld.%ld.%ld.%ld",(addr>>24) & 0xff,
  67                          (addr>>16)&0xff,
  68                          (addr>>8)&0xff,
  69                          addr&0xFF);
  70 }                  
  71 
  72 
  73 /*
  74  *      Returns 1 if the port is matched by the vector, 0 otherwise
  75  */
  76 
  77 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         if (!nports)
  80                 return 1;
  81         if ( range_flag ) 
  82         {
  83                 if ( portptr[0] <= port && port <= portptr[1] ) 
  84                 {
  85                         return( 1 );
  86                 }
  87                 nports -= 2;
  88                 portptr += 2;
  89         }
  90         while ( nports-- > 0 ) 
  91         {
  92                 if ( *portptr++ == port ) 
  93                 {
  94                         return( 1 );
  95                 }
  96         }
  97         return(0);
  98 }
  99 
 100 
 101 /*
 102  *      Returns 0 if packet should be dropped, 1 or more if it should be accepted
 103  */
 104 
 105 #ifdef CONFIG_IP_FIREWALL
 106 
 107 int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         unsigned long src, dst;
 110         char got_proto=0;
 111         int frwl_proto, proto=0;
 112         struct ip_fw *f;
 113         unsigned short src_port=0, dst_port=0;
 114         unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
 115 
 116         if (!chain) 
 117                 return(1);     /* If no chain , always say Ok to packet */
 118 
 119         src = ip->saddr;
 120         dst = ip->daddr;
 121 
 122 #ifdef DEBUG_CONFIG_IP_FIREWALL
 123         {
 124                 printk("packet ");
 125                 switch(ip->protocol) 
 126                 {
 127                         case IPPROTO_TCP:
 128                                 printf("TCP ");
 129                                 break;
 130                         case IPPROTO_UDP:
 131                                 printf("UDP ");
 132                                 break;
 133                         case IPPROTO_ICMP:
 134                                 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
 135                                 break;
 136                         default:
 137                                 printf("p=%d ",ip->protocol);
 138                                 break;
 139                 }
 140                 print_ip(ip->saddr);
 141                 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 142                 {
 143                         printf(":%d ",ntohs(portptr[0]));
 144                 }
 145                 print_ip(ip->daddr);
 146                 if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 147                 {
 148                         printf(":%d ",ntohs(portptr[1]));
 149                 }
 150                 printf("\n");
 151         }
 152 #endif
 153 
 154         for (f=chain;f;f=f->next) 
 155         {
 156                 if ((src&f->src_mask.s_addr)==f->src.s_addr
 157                         &&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
 158                 {
 159                         frwl_proto=f->flags&IP_FW_F_KIND;
 160                         if (frwl_proto==IP_FW_F_ALL) 
 161                         {
 162                                 /* Universal frwl - we've got a match! */
 163 
 164 #ifdef DEBUG_CONFIG_IP_FIREWALL
 165                                 printf("universal frwl match\n");
 166 #endif
 167 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 168                                 if (!(f->flags & IP_FW_F_ACCEPT))
 169                                         goto bad_packet;
 170                                 return 1;
 171 #else
 172                                 return( f->flags & IP_FW_F_ACCEPT );
 173 #endif
 174                         }
 175                         else
 176                         {
 177                                 /*
 178                                  *      Specific firewall - packet's protocol must match firewall's
 179                                  */
 180                                 if (!got_proto) 
 181                                 {
 182                                         /*
 183                                          * We still had not determined the protocol
 184                                          * of this packet,now the time to do so.
 185                                          */
 186                                         switch(ip->protocol) 
 187                                         {
 188                                                 case IPPROTO_TCP:
 189                                                         /*
 190                                                          *      First two shorts in TCP are src/dst ports
 191                                                          */
 192                                                         proto=IP_FW_F_TCP;
 193                                                         src_port=ntohs(portptr[0]);
 194                                                         dst_port=ntohs(portptr[1]);
 195                                                         break;
 196                                                 case IPPROTO_UDP:
 197                                                         /*
 198                                                          *      First two shorts in UDP are src/dst ports
 199                                                          */
 200                                                         proto = IP_FW_F_UDP;
 201                                                         src_port = ntohs(portptr[0]);
 202                                                         dst_port = ntohs(portptr[1]);
 203                                                         break;
 204                                                 case IPPROTO_ICMP:
 205                                                         proto=IP_FW_F_ICMP;
 206                                                         break;
 207                                                 default:
 208                                                         proto=IP_FW_F_ALL;
 209 #ifdef DEBUG_CONFIG_IP_FIREWALL
 210                                                         printf("non TCP/UDP packet\n");
 211 #endif
 212                                         }
 213                                         got_proto=1;
 214                                 } 
 215                                 /*
 216                                  * At this moment we surely know the protocol of this
 217                                  * packet and we'll check if it matches,then proceed further..
 218                                  */
 219                                 if (proto==frwl_proto) 
 220                                 {
 221         
 222                                         if (proto==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port,
 223                                                 f->flags&IP_FW_F_SRNG) &&
 224                                                 port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
 225                                                 f->flags&IP_FW_F_DRNG))) 
 226                                         {
 227 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 228                                                 if (!(f->flags & IP_FW_F_ACCEPT))
 229                                                         goto bad_packet;
 230                                                 return 1;
 231 #else
 232                                                 return( f->flags & IP_FW_F_ACCEPT);
 233 #endif
 234                                         } /* Ports match */
 235                                 } /* Proto matches */
 236                         }  /* ALL/Specific */
 237                 } /* IP addr/mask matches */
 238         } /* Loop */
 239         
 240         /*
 241          * If we get here then none of the firewalls matched.
 242          * So now we relay on policy defined by user-unmatched packet can
 243          * be ever accepted or rejected...
 244          */
 245 
 246 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 247         if (!(ip_fw_policy))
 248                 goto bad_packet;
 249         return 1;
 250 #else
 251         return(ip_fw_policy);
 252 #endif
 253 
 254 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 255 bad_packet:
 256         /*
 257          * VERY ugly piece of code which actually
 258          * makes kernel printf for denied packets...
 259          */
 260         if (f->flags&IP_FW_F_PRN) 
 261         {
 262                 printf("ip_fw_chk says no to ");
 263                 switch(ip->protocol) 
 264                 {
 265                         case IPPROTO_TCP:
 266                                 printf("TCP ");
 267                                 break;
 268                         case IPPROTO_UDP:
 269                                 printf("UDP ");
 270                                 break;
 271                         case IPPROTO_ICMP:
 272                                 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
 273                                 break;
 274                         default:
 275                                 printf("p=%d ",ip->protocol);
 276                                 break;
 277                 }
 278                 print_ip(ip->saddr);
 279                 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 280                 {
 281                         printf(":%d ",ntohs(portptr[0]));
 282                 }
 283                 else
 284                 {
 285                         printf("\n");
 286                 }
 287                 print_ip(ip->daddr);
 288                 if ( ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ) 
 289                 {
 290                         printf(":%d ",ntohs(portptr[1]));
 291                 }
 292                 printf("\n");
 293         }
 294         return(0);
 295 #endif
 296 }
 297 #endif /* CONFIG_IP_FIREWALL */
 298 
 299 
 300 
 301 
 302 #ifdef CONFIG_IP_ACCT
 303 void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain,int nh_conv)
     /* [previous][next][first][last][top][bottom][index][help] */
 304 {
 305         unsigned long src, dst;
 306         char got_proto=0,rev=0;
 307         int frwl_proto, proto=0;
 308         struct ip_fw *f;
 309         unsigned short src_port=0, dst_port=0;
 310         unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
 311 
 312         if (!chain) 
 313                 return;     
 314 
 315         src = ip->saddr;
 316         dst = ip->daddr;
 317 
 318         for (f=chain;f;f=f->next) 
 319         {
 320                 if ((src&f->src_mask.s_addr)==f->src.s_addr
 321                         &&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
 322                 {
 323                         rev=0;
 324                         goto addr_match;
 325                 }
 326                 if  ((f->flags&IP_FW_F_BIDIR) &&
 327                     ((src&f->src_mask.s_addr)==f->dst.s_addr
 328                 &&  (dst&f->dst_mask.s_addr)==f->src.s_addr)) 
 329                 { 
 330                         rev=1;
 331                         goto addr_match;
 332                 }
 333                 continue;
 334 addr_match:
 335                 frwl_proto=f->flags&IP_FW_F_KIND;
 336                 if (frwl_proto==IP_FW_F_ALL) 
 337                 {
 338                         /*      Universal frwl - we've got a match! */
 339                         f->p_cnt++;     /*      Rise packet count */
 340 
 341                         /*
 342                          *      Rise byte count, if need to convert from host to network byte order,do it.
 343                          */
 344                          
 345                         if (nh_conv)                
 346                                 f->b_cnt+=ntohs(ip->tot_len);
 347                         else
 348                                 f->b_cnt+=ip->tot_len;
 349                 }
 350                 else
 351                 {
 352                         /*
 353                          *      Specific firewall - packet's protocol must match firewall's
 354                          */
 355                          
 356                         if (!got_proto) 
 357                         {
 358                                 /*
 359                                  *      We still had not determined the protocol
 360                                  *      of this packet,now the time to do so.
 361                                  */
 362                                 switch(ip->protocol) 
 363                                 {
 364                                         case IPPROTO_TCP:
 365                                                 /*
 366                                                  *      First two shorts in TCP are src/dst ports
 367                                                  */
 368                                                 proto=IP_FW_F_TCP;
 369                                                 src_port=ntohs(portptr[0]);
 370                                                 dst_port=ntohs(portptr[1]);
 371                                                 break;
 372                                         case IPPROTO_UDP:
 373                                                 /*
 374                                                  * First two shorts in UDP are src/dst ports
 375                                                  */
 376                                                 proto = IP_FW_F_UDP;
 377                                                 src_port = ntohs(portptr[0]);
 378                                                 dst_port = ntohs(portptr[1]);
 379                                                 break;
 380                                         case IPPROTO_ICMP:
 381                                                 proto=IP_FW_F_ICMP;
 382                                                 break;
 383                                         default:
 384                                                 proto=IP_FW_F_ALL;
 385                                 }
 386                                 got_proto=1;
 387                         } 
 388                         /*
 389                          * At this moment we surely know the protocol of this
 390                          * packet and we'll check if it matches,then proceed further..
 391                          */
 392                         if (proto==frwl_proto) 
 393                         {
 394 
 395                                 if ((proto==IP_FW_F_ICMP ||
 396                                         (port_match(&f->ports[0],f->n_src_p,src_port,
 397                                         f->flags&IP_FW_F_SRNG) &&
 398                                         port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
 399                                         f->flags&IP_FW_F_DRNG)))
 400                                         || ((rev)   
 401                                                 && (port_match(&f->ports[0],f->n_src_p,dst_port,
 402                                                 f->flags&IP_FW_F_SRNG)
 403                                                 && port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port,
 404                                                 f->flags&IP_FW_F_DRNG))))
 405                                 {
 406                                         f->p_cnt++;                   /* Rise packet count */
 407                                         /*
 408                                          * Rise byte count, if need to convert from host to network byte order,do it.
 409                                          */
 410                                         if (nh_conv)                
 411                                                 f->b_cnt+=ntohs(ip->tot_len);
 412                                         else
 413                                                 f->b_cnt+=ip->tot_len;
 414                                 } /* Ports match */
 415                         } /* Proto matches */
 416                 }  /* ALL/Specific */
 417         } /* IP addr/mask matches */
 418 } /* End of whole function */
 419 #endif /* CONFIG_IP_ACCT */
 420 
 421 #ifdef CONFIG_IP_ACCT
 422 
 423 static void zero_fw_chain(struct ip_fw *chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 424 {
 425         struct ip_fw *ctmp=chainptr;
 426         while(ctmp) 
 427         {
 428                 ctmp->p_cnt=0l;
 429                 ctmp->b_cnt=0l;
 430                 ctmp=ctmp->next;
 431         }
 432 }
 433 
 434 #endif
 435 
 436 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 437 
 438 static void free_fw_chain(struct ip_fw **chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 439 {
 440         unsigned long flags;
 441         save_flags(flags);
 442         cli();
 443         while ( *chainptr != NULL ) 
 444         {
 445                 struct ip_fw *ftmp;
 446                 ftmp = *chainptr;
 447                 *chainptr = ftmp->next;
 448                 kfree_s(ftmp,sizeof(*ftmp));
 449         }
 450         restore_flags(flags);
 451 }
 452 
 453 static int add_to_chain(struct ip_fw **chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 454 {
 455         struct ip_fw *ftmp;
 456         struct ip_fw *chtmp=NULL;
 457         struct ip_fw *chtmp_prev=NULL;
 458         unsigned long flags;
 459         unsigned long m_src_mask,m_dst_mask;
 460         unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
 461         unsigned short n_sr,n_dr,o_sr,o_dr; 
 462         unsigned short oldkind,newkind;
 463         int addb4=0;
 464         int n_o,n_n;
 465         
 466         save_flags(flags);
 467         
 468         ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
 469         if ( ftmp == NULL ) 
 470         {
 471 #ifdef DEBUG_CONFIG_IP_FIREWALL
 472                 printf("ip_fw_ctl:  malloc said no\n");
 473 #endif
 474                 return( ENOSPC );
 475         }
 476 
 477         memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
 478         ftmp->p_cnt=0L;
 479         ftmp->b_cnt=0L;
 480 
 481         ftmp->next = NULL;
 482 
 483         cli();
 484         
 485         if (*chainptr==NULL)
 486         {
 487                 *chainptr=ftmp;
 488         }
 489         else
 490         {
 491                 chtmp_prev=NULL;
 492                 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->next) 
 493                 {
 494                         addb4=0;
 495                         newkind=ftmp->flags & IP_FW_F_KIND;
 496                         oldkind=chtmp->flags & IP_FW_F_KIND;
 497         
 498                         if (newkind!=IP_FW_F_ALL 
 499                                 &&  oldkind!=IP_FW_F_ALL
 500                                 &&  oldkind!=newkind) 
 501                         {
 502                                 chtmp_prev=chtmp;
 503                                 continue;
 504                         }
 505 
 506                         /*
 507                          *      Very very *UGLY* code...
 508                          *      Sorry,but i had to do this....
 509                          */
 510 
 511                         n_sa=ntohl(ftmp->src.s_addr);
 512                         n_da=ntohl(ftmp->dst.s_addr);
 513                         n_sm=ntohl(ftmp->src_mask.s_addr);
 514                         n_dm=ntohl(ftmp->dst_mask.s_addr);
 515 
 516                         o_sa=ntohl(chtmp->src.s_addr);
 517                         o_da=ntohl(chtmp->dst.s_addr);
 518                         o_sm=ntohl(chtmp->src_mask.s_addr);
 519                         o_dm=ntohl(chtmp->dst_mask.s_addr);
 520 
 521                         m_src_mask = o_sm & n_sm;
 522                         m_dst_mask = o_dm & n_dm;
 523 
 524                         if ((o_sa & m_src_mask) == (n_sa & m_src_mask)) 
 525                         {
 526                                 if (n_sm > o_sm) 
 527                                         addb4++;
 528                                 if (n_sm < o_sm) 
 529                                         addb4--;
 530                         }
 531                 
 532                         if ((o_da & m_dst_mask) == (n_da & m_dst_mask)) 
 533                         {
 534                                 if (n_dm > o_dm)
 535                                         addb4++;
 536                                 if (n_dm < o_dm)
 537                                         addb4--;
 538                         }
 539 
 540                         if (((o_da & o_dm) == (n_da & n_dm))
 541                                 &&((o_sa & o_sm) == (n_sa & n_sm)))
 542                         {
 543                                 if (newkind!=IP_FW_F_ALL &&
 544                                         oldkind==IP_FW_F_ALL)
 545                                         addb4++;
 546                                 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
 547                                         ||  oldkind==IP_FW_F_UDP)) 
 548                                 {
 549         
 550                                         /*
 551                                          *      Here the main idea is to check the size
 552                                          *      of port range which the frwl covers
 553                                          *      We actually don't check their values but
 554                                          *      just the wideness of range they have
 555                                          *      so that less wide ranges or single ports
 556                                          *      go first and wide ranges go later. No ports
 557                                          *      at all treated as a range of maximum number
 558                                          *      of ports.
 559                                          */
 560 
 561                                         if (ftmp->flags & IP_FW_F_SRNG) 
 562                                                 n_sr=ftmp->ports[1]-ftmp->ports[0];
 563                                         else 
 564                                                 n_sr=(ftmp->n_src_p)?ftmp->n_src_p : 0xFFFF;
 565                                                 
 566                                         if (chtmp->flags & IP_FW_F_SRNG) 
 567                                                 o_sr=chtmp->ports[1]-chtmp->ports[0];
 568                                         else 
 569                                                 o_sr=(chtmp->n_src_p)?chtmp->n_src_p : 0xFFFF;
 570 
 571                                         if (n_sr<o_sr)
 572                                                 addb4++;
 573                                         if (n_sr>o_sr)
 574                                                 addb4--;
 575                                         
 576                                         n_n=ftmp->n_src_p;
 577                                         n_o=chtmp->n_src_p;
 578         
 579                                         /*
 580                                          * Actually this cannot happen as the frwl control
 581                                          * procedure checks for number of ports in source and
 582                                          * destination range but we will try to be more safe.
 583                                          */
 584                                          
 585                                         if ((n_n>(IP_FW_MAX_PORTS-2)) ||
 586                                                 (n_o>(IP_FW_MAX_PORTS-2)))
 587                                                 goto skip_check;
 588 
 589                                         if (ftmp->flags & IP_FW_F_DRNG) 
 590                                                n_dr=ftmp->ports[n_n+1]-ftmp->ports[n_n];
 591                                         else 
 592                                                n_dr=(ftmp->n_dst_p)? ftmp->n_dst_p : 0xFFFF;
 593 
 594                                         if (chtmp->flags & IP_FW_F_DRNG) 
 595                                                 o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o];
 596                                         else 
 597                                                 o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : 0xFFFF;
 598                                         if (n_dr<o_dr)
 599                                                 addb4++;
 600                                         if (n_dr>o_dr)
 601                                                 addb4--;
 602 skip_check:
 603                                 }
 604                         }
 605                         if (addb4>0) 
 606                         {
 607                                 if (chtmp_prev) 
 608                                 {
 609                                         chtmp_prev->next=ftmp; 
 610                                         ftmp->next=chtmp;
 611                                 } 
 612                                 else 
 613                                 {
 614                                         *chainptr=ftmp;
 615                                         ftmp->next=chtmp;
 616                                 }
 617                                 restore_flags(flags);
 618                                 return 0;
 619                         }
 620                         chtmp_prev=chtmp;
 621                 }
 622         }
 623         
 624         if (chtmp_prev)
 625                 chtmp_prev->next=ftmp;
 626         else
 627                 *chainptr=ftmp;
 628         restore_flags(flags);
 629         return(0);
 630 }
 631 
 632 static int del_from_chain(struct ip_fw **chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         struct ip_fw    *ftmp,*ltmp;
 635         unsigned short  tport1,tport2,tmpnum;
 636         char            matches,was_found;
 637         unsigned long   flags;
 638 
 639         save_flags(flags);
 640         cli();
 641         
 642         ftmp=*chainptr;
 643 
 644         if ( ftmp == NULL ) 
 645         {
 646 #ifdef DEBUG_CONFIG_IP_FIREWALL
 647                 printf("ip_fw_ctl:  chain is empty\n");
 648 #endif
 649                 restore_flags(flags);
 650                 return( EINVAL );
 651         }
 652 
 653         ltmp=NULL;
 654         was_found=0;
 655 
 656         while( ftmp != NULL )
 657         {
 658                 matches=1;
 659                 if ((memcmp(&ftmp->src,&frwl->src,sizeof(struct in_addr))) 
 660                         || (memcmp(&ftmp->src_mask,&frwl->src_mask,sizeof(struct in_addr)))
 661                         || (memcmp(&ftmp->dst,&frwl->dst,sizeof(struct in_addr)))
 662                         || (memcmp(&ftmp->dst_mask,&frwl->dst_mask,sizeof(struct in_addr)))
 663                         || (ftmp->flags!=frwl->flags))
 664                         matches=0;
 665 
 666                 tport1=ftmp->n_src_p+ftmp->n_dst_p;
 667                 tport2=frwl->n_src_p+frwl->n_dst_p;
 668                 if (tport1!=tport2)
 669                         matches=0;
 670                 else if (tport1!=0)
 671                 {
 672                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
 673                         if (ftmp->ports[tmpnum]!=frwl->ports[tmpnum])
 674                                 matches=0;
 675                 }
 676                 if(matches)
 677                 {
 678                         was_found=1;
 679                         if (ltmp)
 680                         {
 681                                 ltmp->next=ftmp->next;
 682                                 kfree_s(ftmp,sizeof(*ftmp));
 683                                 ftmp=ltmp->next;
 684                         }
 685                         else
 686                         {
 687                                 *chainptr=ftmp->next; 
 688                                 kfree_s(ftmp,sizeof(*ftmp));
 689                                 ftmp=*chainptr;
 690                         }       
 691                 }
 692                 else
 693                 {
 694                         ltmp = ftmp;
 695                         ftmp = ftmp->next;
 696                  }
 697         }
 698         restore_flags(flags);
 699         if (was_found)
 700                 return 0;
 701         else
 702                 return(EINVAL);
 703 }
 704 
 705 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
 706 
 707 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 708 {
 709 
 710         if ( len != sizeof(struct ip_fw) )
 711         {
 712 #ifdef DEBUG_CONFIG_IP_FIREWALL
 713                 printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,
 714                                         sizeof(struct ip_fw));
 715 #endif
 716                 return(NULL);
 717         }
 718 
 719         if ( (frwl->flags & ~IP_FW_F_MASK) != 0 )
 720         {
 721 #ifdef DEBUG_CONFIG_IP_FIREWALL
 722                 printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
 723                         frwl->flags);
 724 #endif
 725                 return(NULL);
 726         }
 727 
 728         if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) 
 729         {
 730 #ifdef DEBUG_CONFIG_IP_FIREWALL
 731                 printf("ip_fw_ctl: src range set but n_src_p=%d\n",
 732                         frwl->n_src_p);
 733 #endif
 734                 return(NULL);
 735         }
 736 
 737         if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) 
 738         {
 739 #ifdef DEBUG_CONFIG_IP_FIREWALL
 740                 printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",
 741                         frwl->n_dst_p);
 742 #endif
 743                 return(NULL);
 744         }
 745 
 746         if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) 
 747         {
 748 #ifdef DEBUG_CONFIG_IP_FIREWALL
 749                 printf("ip_fw_ctl: too many ports (%d+%d)\n",
 750                         frwl->n_src_p,frwl->n_dst_p);
 751 #endif
 752                 return(NULL);
 753         }
 754 
 755         return frwl;
 756 }
 757 
 758 
 759 
 760 
 761 #ifdef CONFIG_IP_ACCT
 762 int ip_acct_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 763 {
 764         if ( stage == IP_ACCT_FLUSH )
 765         {
 766                 free_fw_chain(&ip_acct_chain);
 767                 return(0);
 768         }  
 769         if ( stage == IP_ACCT_ZERO )
 770         {
 771                 zero_fw_chain(ip_acct_chain);
 772                 return(0);
 773         }
 774         if ( stage == IP_ACCT_ADD
 775           || stage == IP_ACCT_DEL
 776            )
 777         {
 778                 struct ip_fw *frwl;
 779 
 780                 if (!(frwl=check_ipfw_struct(m,len)))
 781                         return (EINVAL);
 782 
 783                 switch (stage) 
 784                 {
 785                         case IP_ACCT_ADD:
 786                                 return( add_to_chain(&ip_acct_chain,frwl));
 787                         case IP_ACCT_DEL:
 788                                 return( del_from_chain(&ip_acct_chain,frwl));
 789                         default:
 790                                 /*
 791                                  *      Should be panic but... (Why ??? - AC)
 792                                  */
 793 #ifdef DEBUG_CONFIG_IP_FIREWALL
 794                                 printf("ip_acct_ctl:  unknown request %d\n",stage);
 795 #endif
 796                                 return(EINVAL);
 797                 }
 798         }
 799 #ifdef DEBUG_CONFIG_IP_FIREWALL
 800         printf("ip_acct_ctl:  unknown request %d\n",stage);
 801 #endif
 802         return(EINVAL);
 803 }
 804 #endif
 805 
 806 #ifdef CONFIG_IP_FIREWALL
 807 int ip_fw_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 808 {
 809         if ( stage == IP_FW_FLUSH )
 810         {
 811                 free_fw_chain(&ip_fw_blk_chain);
 812                 free_fw_chain(&ip_fw_fwd_chain);
 813                 return(0);
 814         }  
 815 
 816         if ( stage == IP_FW_POLICY )
 817         {
 818                 int *tmp_policy_ptr;
 819                 tmp_policy_ptr=(int *)m;
 820                 if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
 821                         return (EINVAL);
 822                 ip_fw_policy=*tmp_policy_ptr;
 823                 return 0;
 824         }
 825 
 826         if ( stage == IP_FW_CHK_BLK 
 827                 || stage == IP_FW_CHK_FWD )
 828         {
 829                 struct iphdr *ip;
 830 
 831                 if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) )
 832                 {
 833 #ifdef DEBUG_CONFIG_IP_FIREWALL
 834                         printf("ip_fw_ctl: len=%d, want at least %d\n",
 835                                 len,sizeof(struct ip) + 2 * sizeof(unsigned short));
 836 #endif
 837                         return( EINVAL );
 838                 }
 839 
 840                 ip = (struct iphdr *)m;
 841 
 842                 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
 843                 {
 844 #ifdef DEBUG_CONFIG_IP_FIREWALL
 845                         printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
 846                                         sizeof(struct ip)/sizeof(int));
 847 #endif
 848                         return(EINVAL);
 849                 }
 850 
 851                 if ( ip_fw_chk(ip,
 852                         stage == IP_FW_CHK_BLK ?
 853                         ip_fw_blk_chain : ip_fw_fwd_chain )
 854                        ) 
 855                         return(0);
 856                 else    
 857                         return(EACCES);
 858         }
 859 
 860 /*
 861  *      Here we really working hard-adding new elements
 862  *      to blocking/forwarding chains or deleting 'em
 863  */
 864 
 865         if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
 866                 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
 867                 )
 868         {
 869                 struct ip_fw *frwl;
 870                 frwl=check_ipfw_struct(m,len);
 871                 if (frwl==NULL)
 872                         return (EINVAL);
 873                 
 874                 switch (stage) 
 875                 {
 876                         case IP_FW_ADD_BLK:
 877                                 return(add_to_chain(&ip_fw_blk_chain,frwl));
 878                         case IP_FW_ADD_FWD:
 879                                 return(add_to_chain(&ip_fw_fwd_chain,frwl));
 880                         case IP_FW_DEL_BLK:
 881                                 return(del_from_chain(&ip_fw_blk_chain,frwl));
 882                         case IP_FW_DEL_FWD: 
 883                                 return(del_from_chain(&ip_fw_fwd_chain,frwl));
 884                         default:
 885                         /*
 886                          *      Should be panic but... (Why are BSD people panic obsessed ??)
 887                          */
 888 #ifdef DEBUG_CONFIG_IP_FIREWALL
 889                                 printf("ip_fw_ctl:  unknown request %d\n",stage);
 890 #endif
 891                                 return(EINVAL);
 892                 }
 893         } 
 894 
 895 #ifdef DEBUG_CONFIG_IP_FIREWALL
 896         printf("ip_fw_ctl:  unknown request %d\n",stage);
 897 #endif
 898         return(EINVAL);
 899 }
 900 #endif /* CONFIG_IP_FIREWALL */
 901 
 902 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
 903 
 904 static int ip_chain_procinfo(struct ip_fw *chain, char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 905 {
 906         off_t pos=0, begin=0;
 907         struct ip_fw *i;
 908         unsigned long flags;
 909         int len=0;
 910         
 911         
 912         len=sprintf(buffer,"Firewall Rules\n");  
 913         save_flags(flags);
 914         cli();
 915         
 916         i=chain;
 917         
 918         while(i!=NULL)
 919         {
 920                 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
 921                         ntohl(i->src.s_addr),ntohl(i->src_mask.s_addr),
 922                         ntohl(i->dst.s_addr),ntohl(i->dst_mask.s_addr),
 923                         i->flags);
 924                 len+=sprintf(buffer+len,"%u %u %lu %lu ",
 925                         i->n_src_p,i->n_dst_p, i->p_cnt,i->b_cnt);
 926                 len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n",
 927                         i->ports[0],i->ports[1],i->ports[2],i->ports[3],        
 928                         i->ports[4],i->ports[5],i->ports[6],i->ports[7],        
 929                         i->ports[8],i->ports[9]);       
 930                 pos=begin+len;
 931                 if(pos<offset)
 932                 {
 933                         len=0;
 934                         begin=pos;
 935                 }
 936                 if(pos>offset+length)
 937                         break;
 938                 i=i->next;
 939         }
 940         restore_flags(flags);
 941         *start=buffer+(offset-begin);
 942         len-=(offset-begin);
 943         if(len>length)
 944                 len=length;     
 945         return len;
 946 }
 947 #endif
 948 
 949 #ifdef CONFIG_IP_ACCT
 950 
 951 int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 952 {
 953         return ip_chain_procinfo(ip_acct_chain, buffer,start,offset,length);
 954 }
 955 
 956 #endif
 957 
 958 #ifdef CONFIG_IP_FIREWALL
 959 
 960 int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 961 {
 962         return ip_chain_procinfo(ip_fw_blk_chain, buffer,start,offset,length);
 963 }
 964 
 965 int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 966 {
 967         return ip_chain_procinfo(ip_fw_fwd_chain, buffer,start,offset,length);
 968 }
 969 
 970 #endif

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