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 *volatile* 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 /* Volatiles to keep some of the compiler versions amused */
 454 
 455 static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 456 {
 457         struct ip_fw *ftmp;
 458         struct ip_fw *chtmp=NULL;
 459         struct ip_fw *volatile chtmp_prev=NULL;
 460         unsigned long flags;
 461         unsigned long m_src_mask,m_dst_mask;
 462         unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
 463         unsigned short n_sr,n_dr,o_sr,o_dr; 
 464         unsigned short oldkind,newkind;
 465         int addb4=0;
 466         int n_o,n_n;
 467         
 468         save_flags(flags);
 469         
 470         ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
 471         if ( ftmp == NULL ) 
 472         {
 473 #ifdef DEBUG_CONFIG_IP_FIREWALL
 474                 printf("ip_fw_ctl:  malloc said no\n");
 475 #endif
 476                 return( ENOSPC );
 477         }
 478 
 479         memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
 480         
 481         ftmp->p_cnt=0L;
 482         ftmp->b_cnt=0L;
 483 
 484         ftmp->next = NULL;
 485 
 486         cli();
 487         
 488         if (*chainptr==NULL)
 489         {
 490                 *chainptr=ftmp;
 491         }
 492         else
 493         {
 494                 chtmp_prev=NULL;
 495                 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->next) 
 496                 {
 497                         addb4=0;
 498                         newkind=ftmp->flags & IP_FW_F_KIND;
 499                         oldkind=chtmp->flags & IP_FW_F_KIND;
 500         
 501                         if (newkind!=IP_FW_F_ALL 
 502                                 &&  oldkind!=IP_FW_F_ALL
 503                                 &&  oldkind!=newkind) 
 504                         {
 505                                 chtmp_prev=chtmp;
 506                                 continue;
 507                         }
 508 
 509                         /*
 510                          *      Very very *UGLY* code...
 511                          *      Sorry,but i had to do this....
 512                          */
 513 
 514                         n_sa=ntohl(ftmp->src.s_addr);
 515                         n_da=ntohl(ftmp->dst.s_addr);
 516                         n_sm=ntohl(ftmp->src_mask.s_addr);
 517                         n_dm=ntohl(ftmp->dst_mask.s_addr);
 518 
 519                         o_sa=ntohl(chtmp->src.s_addr);
 520                         o_da=ntohl(chtmp->dst.s_addr);
 521                         o_sm=ntohl(chtmp->src_mask.s_addr);
 522                         o_dm=ntohl(chtmp->dst_mask.s_addr);
 523 
 524                         m_src_mask = o_sm & n_sm;
 525                         m_dst_mask = o_dm & n_dm;
 526 
 527                         if ((o_sa & m_src_mask) == (n_sa & m_src_mask)) 
 528                         {
 529                                 if (n_sm > o_sm) 
 530                                         addb4++;
 531                                 if (n_sm < o_sm) 
 532                                         addb4--;
 533                         }
 534                 
 535                         if ((o_da & m_dst_mask) == (n_da & m_dst_mask)) 
 536                         {
 537                                 if (n_dm > o_dm)
 538                                         addb4++;
 539                                 if (n_dm < o_dm)
 540                                         addb4--;
 541                         }
 542 
 543                         if (((o_da & o_dm) == (n_da & n_dm))
 544                                 &&((o_sa & o_sm) == (n_sa & n_sm)))
 545                         {
 546                                 if (newkind!=IP_FW_F_ALL &&
 547                                         oldkind==IP_FW_F_ALL)
 548                                         addb4++;
 549                                 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
 550                                         ||  oldkind==IP_FW_F_UDP)) 
 551                                 {
 552         
 553                                         /*
 554                                          *      Here the main idea is to check the size
 555                                          *      of port range which the frwl covers
 556                                          *      We actually don't check their values but
 557                                          *      just the wideness of range they have
 558                                          *      so that less wide ranges or single ports
 559                                          *      go first and wide ranges go later. No ports
 560                                          *      at all treated as a range of maximum number
 561                                          *      of ports.
 562                                          */
 563 
 564                                         if (ftmp->flags & IP_FW_F_SRNG) 
 565                                                 n_sr=ftmp->ports[1]-ftmp->ports[0];
 566                                         else 
 567                                                 n_sr=(ftmp->n_src_p)?ftmp->n_src_p : 0xFFFF;
 568                                                 
 569                                         if (chtmp->flags & IP_FW_F_SRNG) 
 570                                                 o_sr=chtmp->ports[1]-chtmp->ports[0];
 571                                         else 
 572                                                 o_sr=(chtmp->n_src_p)?chtmp->n_src_p : 0xFFFF;
 573 
 574                                         if (n_sr<o_sr)
 575                                                 addb4++;
 576                                         if (n_sr>o_sr)
 577                                                 addb4--;
 578                                         
 579                                         n_n=ftmp->n_src_p;
 580                                         n_o=chtmp->n_src_p;
 581         
 582                                         /*
 583                                          * Actually this cannot happen as the frwl control
 584                                          * procedure checks for number of ports in source and
 585                                          * destination range but we will try to be more safe.
 586                                          */
 587                                          
 588                                         if ((n_n>(IP_FW_MAX_PORTS-2)) ||
 589                                                 (n_o>(IP_FW_MAX_PORTS-2)))
 590                                                 goto skip_check;
 591 
 592                                         if (ftmp->flags & IP_FW_F_DRNG) 
 593                                                n_dr=ftmp->ports[n_n+1]-ftmp->ports[n_n];
 594                                         else 
 595                                                n_dr=(ftmp->n_dst_p)? ftmp->n_dst_p : 0xFFFF;
 596 
 597                                         if (chtmp->flags & IP_FW_F_DRNG) 
 598                                                 o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o];
 599                                         else 
 600                                                 o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : 0xFFFF;
 601                                         if (n_dr<o_dr)
 602                                                 addb4++;
 603                                         if (n_dr>o_dr)
 604                                                 addb4--;
 605 skip_check:
 606                                 }
 607                         }
 608                         if (addb4>0) 
 609                         {
 610                                 if (chtmp_prev) 
 611                                 {
 612                                         chtmp_prev->next=ftmp; 
 613                                         ftmp->next=chtmp;
 614                                 } 
 615                                 else 
 616                                 {
 617                                         *chainptr=ftmp;
 618                                         ftmp->next=chtmp;
 619                                 }
 620                                 restore_flags(flags);
 621                                 return 0;
 622                         }
 623                         chtmp_prev=chtmp;
 624                 }
 625         }
 626         
 627         if (chtmp_prev)
 628                 chtmp_prev->next=ftmp;
 629         else
 630                 *chainptr=ftmp;
 631         restore_flags(flags);
 632         return(0);
 633 }
 634 
 635 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 636 {
 637         struct ip_fw    *ftmp,*ltmp;
 638         unsigned short  tport1,tport2,tmpnum;
 639         char            matches,was_found;
 640         unsigned long   flags;
 641 
 642         save_flags(flags);
 643         cli();
 644         
 645         ftmp=*chainptr;
 646 
 647         if ( ftmp == NULL ) 
 648         {
 649 #ifdef DEBUG_CONFIG_IP_FIREWALL
 650                 printf("ip_fw_ctl:  chain is empty\n");
 651 #endif
 652                 restore_flags(flags);
 653                 return( EINVAL );
 654         }
 655 
 656         ltmp=NULL;
 657         was_found=0;
 658 
 659         while( ftmp != NULL )
 660         {
 661                 matches=1;
 662                 if ((memcmp(&ftmp->src,&frwl->src,sizeof(struct in_addr))) 
 663                         || (memcmp(&ftmp->src_mask,&frwl->src_mask,sizeof(struct in_addr)))
 664                         || (memcmp(&ftmp->dst,&frwl->dst,sizeof(struct in_addr)))
 665                         || (memcmp(&ftmp->dst_mask,&frwl->dst_mask,sizeof(struct in_addr)))
 666                         || (ftmp->flags!=frwl->flags))
 667                         matches=0;
 668 
 669                 tport1=ftmp->n_src_p+ftmp->n_dst_p;
 670                 tport2=frwl->n_src_p+frwl->n_dst_p;
 671                 if (tport1!=tport2)
 672                         matches=0;
 673                 else if (tport1!=0)
 674                 {
 675                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
 676                         if (ftmp->ports[tmpnum]!=frwl->ports[tmpnum])
 677                                 matches=0;
 678                 }
 679                 if(matches)
 680                 {
 681                         was_found=1;
 682                         if (ltmp)
 683                         {
 684                                 ltmp->next=ftmp->next;
 685                                 kfree_s(ftmp,sizeof(*ftmp));
 686                                 ftmp=ltmp->next;
 687                         }
 688                         else
 689                         {
 690                                 *chainptr=ftmp->next; 
 691                                 kfree_s(ftmp,sizeof(*ftmp));
 692                                 ftmp=*chainptr;
 693                         }       
 694                 }
 695                 else
 696                 {
 697                         ltmp = ftmp;
 698                         ftmp = ftmp->next;
 699                  }
 700         }
 701         restore_flags(flags);
 702         if (was_found)
 703                 return 0;
 704         else
 705                 return(EINVAL);
 706 }
 707 
 708 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
 709 
 710 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 711 {
 712 
 713         if ( len != sizeof(struct ip_fw) )
 714         {
 715 #ifdef DEBUG_CONFIG_IP_FIREWALL
 716                 printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,
 717                                         sizeof(struct ip_fw));
 718 #endif
 719                 return(NULL);
 720         }
 721 
 722         if ( (frwl->flags & ~IP_FW_F_MASK) != 0 )
 723         {
 724 #ifdef DEBUG_CONFIG_IP_FIREWALL
 725                 printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
 726                         frwl->flags);
 727 #endif
 728                 return(NULL);
 729         }
 730 
 731         if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) 
 732         {
 733 #ifdef DEBUG_CONFIG_IP_FIREWALL
 734                 printf("ip_fw_ctl: src range set but n_src_p=%d\n",
 735                         frwl->n_src_p);
 736 #endif
 737                 return(NULL);
 738         }
 739 
 740         if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) 
 741         {
 742 #ifdef DEBUG_CONFIG_IP_FIREWALL
 743                 printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",
 744                         frwl->n_dst_p);
 745 #endif
 746                 return(NULL);
 747         }
 748 
 749         if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) 
 750         {
 751 #ifdef DEBUG_CONFIG_IP_FIREWALL
 752                 printf("ip_fw_ctl: too many ports (%d+%d)\n",
 753                         frwl->n_src_p,frwl->n_dst_p);
 754 #endif
 755                 return(NULL);
 756         }
 757 
 758         return frwl;
 759 }
 760 
 761 
 762 
 763 
 764 #ifdef CONFIG_IP_ACCT
 765 int ip_acct_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767         if ( stage == IP_ACCT_FLUSH )
 768         {
 769                 free_fw_chain(&ip_acct_chain);
 770                 return(0);
 771         }  
 772         if ( stage == IP_ACCT_ZERO )
 773         {
 774                 zero_fw_chain(ip_acct_chain);
 775                 return(0);
 776         }
 777         if ( stage == IP_ACCT_ADD
 778           || stage == IP_ACCT_DEL
 779            )
 780         {
 781                 struct ip_fw *frwl;
 782 
 783                 if (!(frwl=check_ipfw_struct(m,len)))
 784                         return (EINVAL);
 785 
 786                 switch (stage) 
 787                 {
 788                         case IP_ACCT_ADD:
 789                                 return( add_to_chain(&ip_acct_chain,frwl));
 790                         case IP_ACCT_DEL:
 791                                 return( del_from_chain(&ip_acct_chain,frwl));
 792                         default:
 793                                 /*
 794                                  *      Should be panic but... (Why ??? - AC)
 795                                  */
 796 #ifdef DEBUG_CONFIG_IP_FIREWALL
 797                                 printf("ip_acct_ctl:  unknown request %d\n",stage);
 798 #endif
 799                                 return(EINVAL);
 800                 }
 801         }
 802 #ifdef DEBUG_CONFIG_IP_FIREWALL
 803         printf("ip_acct_ctl:  unknown request %d\n",stage);
 804 #endif
 805         return(EINVAL);
 806 }
 807 #endif
 808 
 809 #ifdef CONFIG_IP_FIREWALL
 810 int ip_fw_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 811 {
 812         if ( stage == IP_FW_FLUSH )
 813         {
 814                 free_fw_chain(&ip_fw_blk_chain);
 815                 free_fw_chain(&ip_fw_fwd_chain);
 816                 return(0);
 817         }  
 818 
 819         if ( stage == IP_FW_POLICY )
 820         {
 821                 int *tmp_policy_ptr;
 822                 tmp_policy_ptr=(int *)m;
 823                 if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
 824                         return (EINVAL);
 825                 ip_fw_policy=*tmp_policy_ptr;
 826                 return 0;
 827         }
 828 
 829         if ( stage == IP_FW_CHK_BLK 
 830                 || stage == IP_FW_CHK_FWD )
 831         {
 832                 struct iphdr *ip;
 833 
 834                 if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) )
 835                 {
 836 #ifdef DEBUG_CONFIG_IP_FIREWALL
 837                         printf("ip_fw_ctl: len=%d, want at least %d\n",
 838                                 len,sizeof(struct ip) + 2 * sizeof(unsigned short));
 839 #endif
 840                         return( EINVAL );
 841                 }
 842 
 843                 ip = (struct iphdr *)m;
 844 
 845                 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
 846                 {
 847 #ifdef DEBUG_CONFIG_IP_FIREWALL
 848                         printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
 849                                         sizeof(struct ip)/sizeof(int));
 850 #endif
 851                         return(EINVAL);
 852                 }
 853 
 854                 if ( ip_fw_chk(ip,
 855                         stage == IP_FW_CHK_BLK ?
 856                         ip_fw_blk_chain : ip_fw_fwd_chain )
 857                        ) 
 858                         return(0);
 859                 else    
 860                         return(EACCES);
 861         }
 862 
 863 /*
 864  *      Here we really working hard-adding new elements
 865  *      to blocking/forwarding chains or deleting 'em
 866  */
 867 
 868         if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
 869                 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
 870                 )
 871         {
 872                 struct ip_fw *frwl;
 873                 frwl=check_ipfw_struct(m,len);
 874                 if (frwl==NULL)
 875                         return (EINVAL);
 876                 
 877                 switch (stage) 
 878                 {
 879                         case IP_FW_ADD_BLK:
 880                                 return(add_to_chain(&ip_fw_blk_chain,frwl));
 881                         case IP_FW_ADD_FWD:
 882                                 return(add_to_chain(&ip_fw_fwd_chain,frwl));
 883                         case IP_FW_DEL_BLK:
 884                                 return(del_from_chain(&ip_fw_blk_chain,frwl));
 885                         case IP_FW_DEL_FWD: 
 886                                 return(del_from_chain(&ip_fw_fwd_chain,frwl));
 887                         default:
 888                         /*
 889                          *      Should be panic but... (Why are BSD people panic obsessed ??)
 890                          */
 891 #ifdef DEBUG_CONFIG_IP_FIREWALL
 892                                 printf("ip_fw_ctl:  unknown request %d\n",stage);
 893 #endif
 894                                 return(EINVAL);
 895                 }
 896         } 
 897 
 898 #ifdef DEBUG_CONFIG_IP_FIREWALL
 899         printf("ip_fw_ctl:  unknown request %d\n",stage);
 900 #endif
 901         return(EINVAL);
 902 }
 903 #endif /* CONFIG_IP_FIREWALL */
 904 
 905 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
 906 
 907 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] */
 908 {
 909         off_t pos=0, begin=0;
 910         struct ip_fw *i;
 911         unsigned long flags;
 912         int len=0;
 913         
 914         
 915         len=sprintf(buffer,"Firewall Rules\n");  
 916         save_flags(flags);
 917         cli();
 918         
 919         i=chain;
 920         
 921         while(i!=NULL)
 922         {
 923                 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
 924                         ntohl(i->src.s_addr),ntohl(i->src_mask.s_addr),
 925                         ntohl(i->dst.s_addr),ntohl(i->dst_mask.s_addr),
 926                         i->flags);
 927                 len+=sprintf(buffer+len,"%u %u %lu %lu ",
 928                         i->n_src_p,i->n_dst_p, i->p_cnt,i->b_cnt);
 929                 len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n",
 930                         i->ports[0],i->ports[1],i->ports[2],i->ports[3],        
 931                         i->ports[4],i->ports[5],i->ports[6],i->ports[7],        
 932                         i->ports[8],i->ports[9]);       
 933                 pos=begin+len;
 934                 if(pos<offset)
 935                 {
 936                         len=0;
 937                         begin=pos;
 938                 }
 939                 if(pos>offset+length)
 940                         break;
 941                 i=i->next;
 942         }
 943         restore_flags(flags);
 944         *start=buffer+(offset-begin);
 945         len-=(offset-begin);
 946         if(len>length)
 947                 len=length;     
 948         return len;
 949 }
 950 #endif
 951 
 952 #ifdef CONFIG_IP_ACCT
 953 
 954 int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 955 {
 956         return ip_chain_procinfo(ip_acct_chain, buffer,start,offset,length);
 957 }
 958 
 959 #endif
 960 
 961 #ifdef CONFIG_IP_FIREWALL
 962 
 963 int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 964 {
 965         return ip_chain_procinfo(ip_fw_blk_chain, buffer,start,offset,length);
 966 }
 967 
 968 int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 969 {
 970         return ip_chain_procinfo(ip_fw_fwd_chain, buffer,start,offset,length);
 971 }
 972 
 973 #endif

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