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 int ip_fw_blk_policy=1;
  59 int ip_fw_fwd_policy=1;
  60 #endif
  61 #ifdef CONFIG_IP_ACCT
  62 struct ip_fw *ip_acct_chain;
  63 #endif
  64 
  65 #define IP_INFO_BLK     0
  66 #define IP_INFO_FWD     1
  67 #define IP_INFO_ACCT    2
  68 
  69 
  70 extern inline void print_ip(unsigned long xaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         unsigned long addr = ntohl(xaddr);
  73         printk("%ld.%ld.%ld.%ld",(addr>>24) & 0xff,
  74                          (addr>>16)&0xff,
  75                          (addr>>8)&0xff,
  76                          addr&0xFF);
  77 }                  
  78 
  79 
  80 /*
  81  *      Returns 1 if the port is matched by the vector, 0 otherwise
  82  */
  83 
  84 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         if (!nports)
  87                 return 1;
  88         if ( range_flag ) 
  89         {
  90                 if ( portptr[0] <= port && port <= portptr[1] ) 
  91                 {
  92                         return( 1 );
  93                 }
  94                 nports -= 2;
  95                 portptr += 2;
  96         }
  97         while ( nports-- > 0 ) 
  98         {
  99                 if ( *portptr++ == port ) 
 100                 {
 101                         return( 1 );
 102                 }
 103         }
 104         return(0);
 105 }
 106 
 107 
 108 /*
 109  *      Returns 0 if packet should be dropped, 1 or more if it should be accepted
 110  */
 111 
 112 #ifdef CONFIG_IP_FIREWALL
 113 
 114 int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain, int policy)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         unsigned long src, dst;
 117         char got_proto=0;
 118         int frwl_proto, proto=0;
 119         struct ip_fw *f;
 120         unsigned short src_port=0, dst_port=0;
 121         unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
 122 
 123         if (!chain) 
 124                 return(policy);  /* If no chain, use your policy. */
 125 
 126         src = ip->saddr;
 127         dst = ip->daddr;
 128 
 129 #ifdef DEBUG_CONFIG_IP_FIREWALL
 130         {
 131                 printk("packet ");
 132                 switch(ip->protocol) 
 133                 {
 134                         case IPPROTO_TCP:
 135                                 printf("TCP ");
 136                                 break;
 137                         case IPPROTO_UDP:
 138                                 printf("UDP ");
 139                                 break;
 140                         case IPPROTO_ICMP:
 141                                 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
 142                                 break;
 143                         default:
 144                                 printf("p=%d ",ip->protocol);
 145                                 break;
 146                 }
 147                 print_ip(ip->saddr);
 148                 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 149                 {
 150                         printf(":%d ",ntohs(portptr[0]));
 151                 }
 152                 print_ip(ip->daddr);
 153                 if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 154                 {
 155                         printf(":%d ",ntohs(portptr[1]));
 156                 }
 157                 printf("\n");
 158         }
 159 #endif
 160 
 161         for (f=chain;f;f=f->next) 
 162         {
 163                 if ((src&f->src_mask.s_addr)==f->src.s_addr
 164                         &&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
 165                 {
 166                         frwl_proto=f->flags&IP_FW_F_KIND;
 167                         if (frwl_proto==IP_FW_F_ALL) 
 168                         {
 169                                 /* Universal frwl - we've got a match! */
 170 
 171 #ifdef DEBUG_CONFIG_IP_FIREWALL
 172                                 printf("universal frwl match\n");
 173 #endif
 174                                 f->p_cnt++;
 175                                 f->b_cnt+=ntohs(ip->tot_len);
 176 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 177                                 if (!(f->flags & IP_FW_F_ACCEPT))
 178                                         goto bad_packet;
 179                                 return 1;
 180 #else
 181                                 return( f->flags & IP_FW_F_ACCEPT );
 182 #endif
 183                         }
 184                         else
 185                         {
 186                                 /*
 187                                  *      Specific firewall - packet's protocol must match firewall's
 188                                  */
 189                                 if (!got_proto) 
 190                                 {
 191                                         /*
 192                                          * We still had not determined the protocol
 193                                          * of this packet,now the time to do so.
 194                                          */
 195                                         switch(ip->protocol) 
 196                                         {
 197                                                 case IPPROTO_TCP:
 198                                                         /*
 199                                                          *      First two shorts in TCP are src/dst ports
 200                                                          */
 201                                                         proto=IP_FW_F_TCP;
 202                                                         src_port=ntohs(portptr[0]);
 203                                                         dst_port=ntohs(portptr[1]);
 204                                                         break;
 205                                                 case IPPROTO_UDP:
 206                                                         /*
 207                                                          *      First two shorts in UDP are src/dst ports
 208                                                          */
 209                                                         proto = IP_FW_F_UDP;
 210                                                         src_port = ntohs(portptr[0]);
 211                                                         dst_port = ntohs(portptr[1]);
 212                                                         break;
 213                                                 case IPPROTO_ICMP:
 214                                                         proto=IP_FW_F_ICMP;
 215                                                         break;
 216                                                 default:
 217                                                         proto=IP_FW_F_ALL;
 218 #ifdef DEBUG_CONFIG_IP_FIREWALL
 219                                                         printf("non TCP/UDP packet\n");
 220 #endif
 221                                         }
 222                                         got_proto=1;
 223                                 } 
 224                                 /*
 225                                  * At this moment we surely know the protocol of this
 226                                  * packet and we'll check if it matches,then proceed further..
 227                                  */
 228                                 if (proto==frwl_proto) 
 229                                 {
 230         
 231                                         if (proto==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port,
 232                                                 f->flags&IP_FW_F_SRNG) &&
 233                                                 port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
 234                                                 f->flags&IP_FW_F_DRNG))) 
 235                                         {
 236                                         /* We've got a match! */
 237                                         f->p_cnt++;
 238                                         f->b_cnt+=ntohs(ip->tot_len);
 239 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 240                                                 if (!(f->flags & IP_FW_F_ACCEPT))
 241                                                         goto bad_packet;
 242                                                 return 1;
 243 #else
 244                                                 return( f->flags & IP_FW_F_ACCEPT);
 245 #endif
 246                                         } /* Ports match */
 247                                 } /* Proto matches */
 248                         }  /* ALL/Specific */
 249                 } /* IP addr/mask matches */
 250         } /* Loop */
 251         
 252         /*
 253          * If we get here then none of the firewalls matched.
 254          * So now we relay on policy defined by user-unmatched packet can
 255          * be ever accepted or rejected...
 256          */
 257 
 258 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 259         if (!(policy))
 260                 goto bad_packet;
 261         return 1;
 262 #else
 263         return(policy);
 264 #endif
 265 
 266 #ifdef CONFIG_IP_FIREWALL_VERBOSE
 267 bad_packet:
 268         /*
 269          * VERY ugly piece of code which actually
 270          * makes kernel printf for denied packets...
 271          */
 272         if (f->flags&IP_FW_F_PRN) 
 273         {
 274                 printf("ip_fw_chk says no to ");
 275                 switch(ip->protocol) 
 276                 {
 277                         case IPPROTO_TCP:
 278                                 printf("TCP ");
 279                                 break;
 280                         case IPPROTO_UDP:
 281                                 printf("UDP ");
 282                                 break;
 283                         case IPPROTO_ICMP:
 284                                 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
 285                                 break;
 286                         default:
 287                                 printf("p=%d ",ip->protocol);
 288                                 break;
 289                 }
 290                 print_ip(ip->saddr);
 291                 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
 292                 {
 293                         printf(":%d ",ntohs(portptr[0]));
 294                 }
 295                 else
 296                 {
 297                         printf("\n");
 298                 }
 299                 print_ip(ip->daddr);
 300                 if ( ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ) 
 301                 {
 302                         printf(":%d ",ntohs(portptr[1]));
 303                 }
 304                 printf("\n");
 305         }
 306         return(0);
 307 #endif
 308 }
 309 #endif /* CONFIG_IP_FIREWALL */
 310 
 311 
 312 
 313 
 314 #ifdef CONFIG_IP_ACCT
 315 void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain)
     /* [previous][next][first][last][top][bottom][index][help] */
 316 {
 317         unsigned long src, dst;
 318         char got_proto=0,rev=0;
 319         int frwl_proto, proto=0;
 320         struct ip_fw *f;
 321         unsigned short src_port=0, dst_port=0;
 322         unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
 323 
 324         if (!chain) 
 325                 return;     
 326 
 327         src = ip->saddr;
 328         dst = ip->daddr;
 329 
 330         for (f=chain;f;f=f->next) 
 331         {
 332                 if ((src&f->src_mask.s_addr)==f->src.s_addr
 333                         &&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
 334                 {
 335                         rev=0;
 336                         goto addr_match;
 337                 }
 338                 if  ((f->flags&IP_FW_F_BIDIR) &&
 339                     ((src&f->src_mask.s_addr)==f->dst.s_addr
 340                 &&  (dst&f->dst_mask.s_addr)==f->src.s_addr)) 
 341                 { 
 342                         rev=1;
 343                         goto addr_match;
 344                 }
 345                 continue;
 346 addr_match:
 347                 frwl_proto=f->flags&IP_FW_F_KIND;
 348                 if (frwl_proto==IP_FW_F_ALL) 
 349                 {
 350                         /*      Universal frwl - we've got a match! */
 351                         f->p_cnt++;     /*      Rise packet count */
 352 
 353                         /*
 354                          *      Rise byte count, convert from host to network byte order.
 355                          */
 356                          
 357                         f->b_cnt+=ntohs(ip->tot_len);
 358                 }
 359                 else
 360                 {
 361                         /*
 362                          *      Specific firewall - packet's protocol must match firewall's
 363                          */
 364                          
 365                         if (!got_proto) 
 366                         {
 367                                 /*
 368                                  *      We still had not determined the protocol
 369                                  *      of this packet,now the time to do so.
 370                                  */
 371                                 switch(ip->protocol) 
 372                                 {
 373                                         case IPPROTO_TCP:
 374                                                 /*
 375                                                  *      First two shorts in TCP are src/dst ports
 376                                                  */
 377                                                 proto=IP_FW_F_TCP;
 378                                                 src_port=ntohs(portptr[0]);
 379                                                 dst_port=ntohs(portptr[1]);
 380                                                 break;
 381                                         case IPPROTO_UDP:
 382                                                 /*
 383                                                  * First two shorts in UDP are src/dst ports
 384                                                  */
 385                                                 proto = IP_FW_F_UDP;
 386                                                 src_port = ntohs(portptr[0]);
 387                                                 dst_port = ntohs(portptr[1]);
 388                                                 break;
 389                                         case IPPROTO_ICMP:
 390                                                 proto=IP_FW_F_ICMP;
 391                                                 break;
 392                                         default:
 393                                                 proto=IP_FW_F_ALL;
 394                                 }
 395                                 got_proto=1;
 396                         } 
 397                         /*
 398                          * At this moment we surely know the protocol of this
 399                          * packet and we'll check if it matches,then proceed further..
 400                          */
 401                         if (proto==frwl_proto) 
 402                         {
 403 
 404                                 if ((proto==IP_FW_F_ICMP ||
 405                                         (port_match(&f->ports[0],f->n_src_p,src_port,
 406                                         f->flags&IP_FW_F_SRNG) &&
 407                                         port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
 408                                         f->flags&IP_FW_F_DRNG)))
 409                                         || ((rev)   
 410                                                 && (port_match(&f->ports[0],f->n_src_p,dst_port,
 411                                                 f->flags&IP_FW_F_SRNG)
 412                                                 && port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port,
 413                                                 f->flags&IP_FW_F_DRNG))))
 414                                 {
 415                                         f->p_cnt++;                   /* Rise packet count */
 416                                         /*
 417                                          * Rise byte count, convert from host to network byte order.
 418                                          */
 419                                         f->b_cnt+=ntohs(ip->tot_len);
 420                                 } /* Ports match */
 421                         } /* Proto matches */
 422                 }  /* ALL/Specific */
 423         } /* IP addr/mask matches */
 424 } /* End of whole function */
 425 #endif /* CONFIG_IP_ACCT */
 426 
 427 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 428 
 429 static void zero_fw_chain(struct ip_fw *chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 430 {
 431         struct ip_fw *ctmp=chainptr;
 432         while(ctmp) 
 433         {
 434                 ctmp->p_cnt=0l;
 435                 ctmp->b_cnt=0l;
 436                 ctmp=ctmp->next;
 437         }
 438 }
 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_BLK )
 815         {
 816                 free_fw_chain(&ip_fw_blk_chain);
 817                 return(0);
 818         }  
 819 
 820         if ( stage == IP_FW_FLUSH_FWD )
 821         {
 822                 free_fw_chain(&ip_fw_fwd_chain);
 823                 return(0);
 824         }  
 825 
 826         if ( stage == IP_FW_ZERO_BLK )
 827         {
 828                 zero_fw_chain(ip_fw_blk_chain);
 829                 return(0);
 830         }  
 831 
 832         if ( stage == IP_FW_ZERO_FWD )
 833         {
 834                 zero_fw_chain(ip_fw_fwd_chain);
 835                 return(0);
 836         }  
 837 
 838         if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
 839         {
 840                 int *tmp_policy_ptr;
 841                 tmp_policy_ptr=(int *)m;
 842                 if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
 843                         return (EINVAL);
 844                 if ( stage == IP_FW_POLICY_BLK )
 845                         ip_fw_blk_policy=*tmp_policy_ptr;
 846                 else
 847                         ip_fw_fwd_policy=*tmp_policy_ptr;
 848                 return 0;
 849         }
 850 
 851         if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
 852         {
 853                 struct iphdr *ip;
 854 
 855                 if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) )
 856                 {
 857 #ifdef DEBUG_CONFIG_IP_FIREWALL
 858                         printf("ip_fw_ctl: len=%d, want at least %d\n",
 859                                 len,sizeof(struct ip) + 2 * sizeof(unsigned short));
 860 #endif
 861                         return( EINVAL );
 862                 }
 863 
 864                 ip = (struct iphdr *)m;
 865 
 866                 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
 867                 {
 868 #ifdef DEBUG_CONFIG_IP_FIREWALL
 869                         printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
 870                                         sizeof(struct ip)/sizeof(int));
 871 #endif
 872                         return(EINVAL);
 873                 }
 874 
 875                 if ( ip_fw_chk(ip,
 876                         stage == IP_FW_CHK_BLK ?
 877                         ip_fw_blk_chain : ip_fw_fwd_chain,
 878                         stage == IP_FW_CHK_BLK ?
 879                         ip_fw_blk_policy : ip_fw_fwd_policy )
 880                        ) 
 881                         return(0);
 882                 else    
 883                         return(EACCES);
 884         }
 885 
 886 /*
 887  *      Here we really working hard-adding new elements
 888  *      to blocking/forwarding chains or deleting 'em
 889  */
 890 
 891         if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
 892                 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
 893                 )
 894         {
 895                 struct ip_fw *frwl;
 896                 frwl=check_ipfw_struct(m,len);
 897                 if (frwl==NULL)
 898                         return (EINVAL);
 899                 
 900                 switch (stage) 
 901                 {
 902                         case IP_FW_ADD_BLK:
 903                                 return(add_to_chain(&ip_fw_blk_chain,frwl));
 904                         case IP_FW_ADD_FWD:
 905                                 return(add_to_chain(&ip_fw_fwd_chain,frwl));
 906                         case IP_FW_DEL_BLK:
 907                                 return(del_from_chain(&ip_fw_blk_chain,frwl));
 908                         case IP_FW_DEL_FWD: 
 909                                 return(del_from_chain(&ip_fw_fwd_chain,frwl));
 910                         default:
 911                         /*
 912                          *      Should be panic but... (Why are BSD people panic obsessed ??)
 913                          */
 914 #ifdef DEBUG_CONFIG_IP_FIREWALL
 915                                 printf("ip_fw_ctl:  unknown request %d\n",stage);
 916 #endif
 917                                 return(EINVAL);
 918                 }
 919         } 
 920 
 921 #ifdef DEBUG_CONFIG_IP_FIREWALL
 922         printf("ip_fw_ctl:  unknown request %d\n",stage);
 923 #endif
 924         return(EINVAL);
 925 }
 926 #endif /* CONFIG_IP_FIREWALL */
 927 
 928 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
 929 
 930 static int ip_chain_procinfo(int stage, char *buffer, char **start,
     /* [previous][next][first][last][top][bottom][index][help] */
 931                 off_t offset, int length, int reset)
 932 {
 933         off_t pos=0, begin=0;
 934         struct ip_fw *i;
 935         unsigned long flags;
 936         int len;
 937         
 938 
 939         switch(stage)
 940         {
 941 #ifdef CONFIG_IP_FIREWALL
 942                 case IP_INFO_BLK:
 943                         i = ip_fw_blk_chain;
 944                         len=sprintf(buffer, "IP firewall block rules, policy = %d\n",
 945                                 ip_fw_blk_policy);
 946                         break;
 947                 case IP_INFO_FWD:
 948                         i = ip_fw_fwd_chain;
 949                         len=sprintf(buffer, "IP firewall forward rules, policy = %d\n",
 950                                 ip_fw_fwd_policy);
 951                         break;
 952 #endif
 953 #ifdef CONFIG_IP_ACCT
 954                 case IP_INFO_ACCT:
 955                         i = ip_acct_chain;
 956                         len=sprintf(buffer,"IP accounting rules\n");
 957                         break;
 958 #endif
 959                 default:
 960                         /* this should never be reached, but safety first... */
 961                         i = NULL;
 962                         len=0;
 963                         break;
 964         }
 965 
 966         save_flags(flags);
 967         cli();
 968         
 969         while(i!=NULL)
 970         {
 971                 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
 972                         ntohl(i->src.s_addr),ntohl(i->src_mask.s_addr),
 973                         ntohl(i->dst.s_addr),ntohl(i->dst_mask.s_addr),
 974                         i->flags);
 975                 len+=sprintf(buffer+len,"%u %u %lu %lu ",
 976                         i->n_src_p,i->n_dst_p, i->p_cnt,i->b_cnt);
 977                 len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n",
 978                         i->ports[0],i->ports[1],i->ports[2],i->ports[3],        
 979                         i->ports[4],i->ports[5],i->ports[6],i->ports[7],        
 980                         i->ports[8],i->ports[9]);       
 981                 pos=begin+len;
 982                 if(pos<offset)
 983                 {
 984                         len=0;
 985                         begin=pos;
 986                 }
 987                 else if(reset)
 988                 {
 989                         /* This needs to be done at this specific place! */
 990                         i->p_cnt=0L;
 991                         i->b_cnt=0L;
 992                 }
 993                 if(pos>offset+length)
 994                         break;
 995                 i=i->next;
 996         }
 997         restore_flags(flags);
 998         *start=buffer+(offset-begin);
 999         len-=(offset-begin);
1000         if(len>length)
1001                 len=length;     
1002         return len;
1003 }
1004 #endif
1005 
1006 #ifdef CONFIG_IP_ACCT
1007 
1008 int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
     /* [previous][next][first][last][top][bottom][index][help] */
1009 {
1010         return ip_chain_procinfo(IP_INFO_ACCT,buffer,start,offset,length,reset);
1011 }
1012 
1013 #endif
1014 
1015 #ifdef CONFIG_IP_FIREWALL
1016 
1017 int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
     /* [previous][next][first][last][top][bottom][index][help] */
1018 {
1019         return ip_chain_procinfo(IP_INFO_BLK,buffer,start,offset,length,reset);
1020 }
1021 
1022 int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
     /* [previous][next][first][last][top][bottom][index][help] */
1023 {
1024         return ip_chain_procinfo(IP_INFO_FWD,buffer,start,offset,length,reset);
1025 }
1026 
1027 #endif

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