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

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