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

   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 futher..
 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 futher..
 391                          */
 392                         if (proto==frwl_proto) 
 393                         {
 394 
 395                                 if ((proto==IP_FW_F_ICMP ||
 396                                         (port_match(&f->ports[0],f->n_src_p,src_port,
 397                                         f->flags&IP_FW_F_SRNG) &&
 398                                         port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
 399                                         f->flags&IP_FW_F_DRNG)))
 400                                         || ((rev)   
 401                                                 && (port_match(&f->ports[0],f->n_src_p,dst_port,
 402                                                 f->flags&IP_FW_F_SRNG)
 403                                                 && port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port,
 404                                                 f->flags&IP_FW_F_DRNG))))
 405                                 {
 406                                         f->p_cnt++;                   /* Rise packet count */
 407                                         /*
 408                                          * Rise byte count, if need to convert from host to network byte order,do it.
 409                                          */
 410                                         if (nh_conv)                
 411                                                 f->b_cnt+=ntohs(ip->tot_len);
 412                                         else
 413                                                 f->b_cnt+=ip->tot_len;
 414                                 } /* Ports match */
 415                         } /* Proto matches */
 416                 }  /* ALL/Specific */
 417         } /* IP addr/mask matches */
 418 } /* End of whole function */
 419 #endif /* CONFIG_IP_ACCT */
 420 
 421 #ifdef CONFIG_IP_ACCT
 422 
 423 static void zero_fw_chain(struct ip_fw *chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 424 {
 425         struct ip_fw *ctmp=chainptr;
 426         while(ctmp) 
 427         {
 428                 ctmp->p_cnt=0l;
 429                 ctmp->b_cnt=0l;
 430                 ctmp=ctmp->next;
 431         }
 432 }
 433 
 434 #endif
 435 
 436 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 437 
 438 static void free_fw_chain(struct ip_fw **chainptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 439 {
 440         unsigned long flags;
 441         save_flags(flags);
 442         cli();
 443         while ( *chainptr != NULL ) 
 444         {
 445                 struct ip_fw *ftmp;
 446                 ftmp = *chainptr;
 447                 *chainptr = ftmp->next;
 448                 kfree_s(ftmp,sizeof(*ftmp));
 449         }
 450         restore_flags(flags);
 451 }
 452 
 453 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
 454 
 455 #ifdef CONFIG_IP_FIREWALL
 456 
 457 static int add_to_chain(struct ip_fw **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 *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         ftmp->p_cnt=0L;
 483         ftmp->b_cnt=0L;
 484 
 485         ftmp->next = NULL;
 486 
 487         cli();
 488         
 489         if (*chainptr==NULL)
 490         {
 491                 *chainptr=ftmp;
 492         }
 493         else
 494         {
 495                 chtmp_prev=NULL;
 496                 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->next) 
 497                 {
 498                         addb4=0;
 499                         newkind=ftmp->flags & IP_FW_F_KIND;
 500                         oldkind=chtmp->flags & IP_FW_F_KIND;
 501         
 502                         if (newkind!=IP_FW_F_ALL 
 503                                 &&  oldkind!=IP_FW_F_ALL
 504                                 &&  oldkind!=newkind) 
 505                         {
 506                                 chtmp_prev=chtmp;
 507                                 continue;
 508                         }
 509 
 510                         /*
 511                          *      Very very *UGLY* code...
 512                          *      Sorry,but i had to do this....
 513                          */
 514 
 515                         n_sa=ntohl(ftmp->src.s_addr);
 516                         n_da=ntohl(ftmp->dst.s_addr);
 517                         n_sm=ntohl(ftmp->src_mask.s_addr);
 518                         n_dm=ntohl(ftmp->dst_mask.s_addr);
 519 
 520                         o_sa=ntohl(chtmp->src.s_addr);
 521                         o_da=ntohl(chtmp->dst.s_addr);
 522                         o_sm=ntohl(chtmp->src_mask.s_addr);
 523                         o_dm=ntohl(chtmp->dst_mask.s_addr);
 524 
 525                         m_src_mask = o_sm & n_sm;
 526                         m_dst_mask = o_dm & n_dm;
 527 
 528                         if ((o_sa & m_src_mask) == (n_sa & m_src_mask)) 
 529                         {
 530                                 if (n_sm > o_sm) 
 531                                         addb4++;
 532                                 if (n_sm < o_sm) 
 533                                         addb4--;
 534                         }
 535                 
 536                         if ((o_da & m_dst_mask) == (n_da & m_dst_mask)) 
 537                         {
 538                                 if (n_dm > o_dm)
 539                                         addb4++;
 540                                 if (n_dm < o_dm)
 541                                         addb4--;
 542                         }
 543 
 544                         if (((o_da & o_dm) == (n_da & n_dm))
 545                                 &&((o_sa & o_sm) == (n_sa & n_sm)))
 546                         {
 547                                 if (newkind!=IP_FW_F_ALL &&
 548                                         oldkind==IP_FW_F_ALL)
 549                                         addb4++;
 550                                 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
 551                                         ||  oldkind==IP_FW_F_UDP)) 
 552                                 {
 553         
 554                                         /*
 555                                          *      Here the main idea is to check the size
 556                                          *      of port range which the frwl covers
 557                                          *      We actually don't check their values but
 558                                          *      just the wideness of range they have
 559                                          *      so that less wide ranges or single ports
 560                                          *      go first and wide ranges go later. No ports
 561                                          *      at all treated as a range of maximum number
 562                                          *      of ports.
 563                                          */
 564 
 565                                         if (ftmp->flags & IP_FW_F_SRNG) 
 566                                                 n_sr=ftmp->ports[1]-ftmp->ports[0];
 567                                         else 
 568                                                 n_sr=(ftmp->n_src_p)?ftmp->n_src_p : 0xFFFF;
 569                                                 
 570                                         if (chtmp->flags & IP_FW_F_SRNG) 
 571                                                 o_sr=chtmp->ports[1]-chtmp->ports[0];
 572                                         else 
 573                                                 o_sr=(chtmp->n_src_p)?chtmp->n_src_p : 0xFFFF;
 574 
 575                                         if (n_sr<o_sr)
 576                                                 addb4++;
 577                                         if (n_sr>o_sr)
 578                                                 addb4--;
 579                                         
 580                                         n_n=ftmp->n_src_p;
 581                                         n_o=chtmp->n_src_p;
 582         
 583                                         /*
 584                                          * Actually this cannot happen as the frwl control
 585                                          * procedure checks for number of ports in source and
 586                                          * destination range but we will try to be more safe.
 587                                          */
 588                                          
 589                                         if ((n_n>(IP_FW_MAX_PORTS-2)) ||
 590                                                 (n_o>(IP_FW_MAX_PORTS-2)))
 591                                                 goto skip_check;
 592 
 593                                         if (ftmp->flags & IP_FW_F_DRNG) 
 594                                                n_dr=ftmp->ports[n_n+1]-ftmp->ports[n_n];
 595                                         else 
 596                                                n_dr=(ftmp->n_dst_p)? ftmp->n_dst_p : 0xFFFF;
 597 
 598                                         if (chtmp->flags & IP_FW_F_DRNG) 
 599                                                 o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o];
 600                                         else 
 601                                                 o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : 0xFFFF;
 602                                         if (n_dr<o_dr)
 603                                                 addb4++;
 604                                         if (n_dr>o_dr)
 605                                                 addb4--;
 606 skip_check:
 607                                 }
 608                         }
 609                         if (addb4>0) 
 610                         {
 611                                 if (chtmp_prev) 
 612                                 {
 613                                         chtmp_prev->next=ftmp; 
 614                                         ftmp->next=chtmp;
 615                                 } 
 616                                 else 
 617                                 {
 618                                         *chainptr=ftmp;
 619                                         ftmp->next=chtmp;
 620                                 }
 621                                 restore_flags(flags);
 622                                 return 0;
 623                         }
 624                         chtmp_prev=chtmp;
 625                 }
 626         }
 627         
 628         if (chtmp_prev)
 629                 chtmp_prev->next=ftmp;
 630         else
 631         {
 632                 *chainptr=ftmp;
 633                 printk("ip_fw: add_to_chain: Can't happen");
 634         }
 635         restore_flags(flags);
 636         return(0);
 637 }
 638 
 639 static int del_from_chain(struct ip_fw **chainptr, struct ip_fw *frwl)
     /* [previous][next][first][last][top][bottom][index][help] */
 640 {
 641         struct ip_fw    *ftmp,*ltmp;
 642         unsigned short  tport1,tport2,tmpnum;
 643         char            matches,was_found;
 644         unsigned long   flags;
 645 
 646         save_flags(flags);
 647         cli();
 648         
 649         ftmp=*chainptr;
 650 
 651         if ( ftmp == NULL ) 
 652         {
 653 #ifdef DEBUG_CONFIG_IP_FIREWALL
 654                 printf("ip_fw_ctl:  chain is empty\n");
 655 #endif
 656                 restore_flags(flags);
 657                 return( EINVAL );
 658         }
 659 
 660         ltmp=NULL;
 661         was_found=0;
 662 
 663         while( ftmp != NULL )
 664         {
 665                 matches=1;
 666                 if ((memcmp(&ftmp->src,&frwl->src,sizeof(struct in_addr))) 
 667                         || (memcmp(&ftmp->src_mask,&frwl->src_mask,sizeof(struct in_addr)))
 668                         || (memcmp(&ftmp->dst,&frwl->dst,sizeof(struct in_addr)))
 669                         || (memcmp(&ftmp->dst_mask,&frwl->dst_mask,sizeof(struct in_addr)))
 670                         || (ftmp->flags!=frwl->flags))
 671                         matches=0;
 672 
 673                 tport1=ftmp->n_src_p+ftmp->n_dst_p;
 674                 tport2=frwl->n_src_p+frwl->n_dst_p;
 675                 if (tport1!=tport2)
 676                         matches=0;
 677                 else if (tport1!=0)
 678                 {
 679                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
 680                         if (ftmp->ports[tmpnum]!=frwl->ports[tmpnum])
 681                                 matches=0;
 682                 }
 683                 if(matches)
 684                 {
 685                         was_found=1;
 686                         if (ltmp)
 687                         {
 688                                 ltmp->next=ftmp->next;
 689                                 kfree_s(ftmp,sizeof(*ftmp));
 690                                 ftmp=ltmp->next;
 691                         }
 692                         else
 693                         {
 694                                 *chainptr=ftmp->next; 
 695                                 kfree_s(ftmp,sizeof(*ftmp));
 696                                 ftmp=*chainptr;
 697                         }       
 698                 }
 699                 else
 700                 {
 701                         ltmp = ftmp;
 702                         ftmp = ftmp->next;
 703                  }
 704         }
 705         restore_flags(flags);
 706         if (was_found)
 707                 return 0;
 708         else
 709                 return(EINVAL);
 710 }
 711 
 712 #endif /* CONFIG_IP_FIREWALL */
 713 
 714 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 715 {
 716 
 717         if ( len != sizeof(struct ip_fw) )
 718         {
 719 #ifdef DEBUG_CONFIG_IP_FIREWALL
 720                 printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,
 721                                         sizeof(struct ip_fw));
 722 #endif
 723                 return(NULL);
 724         }
 725 
 726         if ( (frwl->flags & ~IP_FW_F_MASK) != 0 )
 727         {
 728 #ifdef DEBUG_CONFIG_IP_FIREWALL
 729                 printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
 730                         frwl->flags);
 731 #endif
 732                 return(NULL);
 733         }
 734 
 735         if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) 
 736         {
 737 #ifdef DEBUG_CONFIG_IP_FIREWALL
 738                 printf("ip_fw_ctl: src range set but n_src_p=%d\n",
 739                         frwl->n_src_p);
 740 #endif
 741                 return(NULL);
 742         }
 743 
 744         if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) 
 745         {
 746 #ifdef DEBUG_CONFIG_IP_FIREWALL
 747                 printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",
 748                         frwl->n_dst_p);
 749 #endif
 750                 return(NULL);
 751         }
 752 
 753         if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) 
 754         {
 755 #ifdef DEBUG_CONFIG_IP_FIREWALL
 756                 printf("ip_fw_ctl: too many ports (%d+%d)\n",
 757                         frwl->n_src_p,frwl->n_dst_p);
 758 #endif
 759                 return(NULL);
 760         }
 761 
 762         return frwl;
 763 }
 764 
 765 
 766 
 767 
 768 #ifdef CONFIG_IP_ACCT
 769 int ip_acct_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 770 {
 771         if ( stage == IP_ACCT_FLUSH )
 772         {
 773                 free_fw_chain(&ip_acct_chain);
 774                 return(0);
 775         }  
 776         if ( stage == IP_ACCT_ZERO )
 777         {
 778                 zero_fw_chain(ip_acct_chain);
 779                 return(0);
 780         }
 781         if ( stage == IP_ACCT_ADD
 782           || stage == IP_ACCT_DEL
 783            )
 784         {
 785                 struct ip_fw *frwl;
 786 
 787                 if (!(frwl=check_ipfw_struct(m,len)))
 788                         return (EINVAL);
 789 
 790                 switch (stage) 
 791                 {
 792                         case IP_ACCT_ADD:
 793                                 return( add_to_chain(&ip_acct_chain,frwl));
 794                         case IP_ACCT_DEL:
 795                                 return( del_from_chain(&ip_acct_chain,frwl));
 796                         default:
 797                                 /*
 798                                  *      Should be panic but... (Why ??? - AC)
 799                                  */
 800 #ifdef DEBUG_CONFIG_IP_FIREWALL
 801                                 printf("ip_acct_ctl:  unknown request %d\n",stage);
 802 #endif
 803                                 return(EINVAL);
 804                 }
 805         }
 806 #ifdef DEBUG_CONFIG_IP_FIREWALL
 807         printf("ip_acct_ctl:  unknown request %d\n",stage);
 808 #endif
 809         return(EINVAL);
 810 }
 811 #endif
 812 
 813 #ifdef CONFIG_IP_FIREWALL
 814 int ip_fw_ctl(int stage, void *m, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 815 {
 816         if ( stage == IP_FW_FLUSH )
 817         {
 818                 free_fw_chain(&ip_fw_blk_chain);
 819                 free_fw_chain(&ip_fw_fwd_chain);
 820                 return(0);
 821         }  
 822 
 823         if ( stage == IP_FW_POLICY )
 824         {
 825                 int *tmp_policy_ptr;
 826                 tmp_policy_ptr=(int *)m;
 827                 if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
 828                         return (EINVAL);
 829                 ip_fw_policy=*tmp_policy_ptr;
 830                 return 0;
 831         }
 832 
 833         if ( stage == IP_FW_CHK_BLK 
 834                 || stage == IP_FW_CHK_FWD )
 835         {
 836                 struct iphdr *ip;
 837 
 838                 if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) )
 839                 {
 840 #ifdef DEBUG_CONFIG_IP_FIREWALL
 841                         printf("ip_fw_ctl: len=%d, want at least %d\n",
 842                                 len,sizeof(struct ip) + 2 * sizeof(unsigned short));
 843 #endif
 844                         return( EINVAL );
 845                 }
 846 
 847                 ip = (struct iphdr *)m;
 848 
 849                 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
 850                 {
 851 #ifdef DEBUG_CONFIG_IP_FIREWALL
 852                         printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
 853                                         sizeof(struct ip)/sizeof(int));
 854 #endif
 855                         return(EINVAL);
 856                 }
 857 
 858                 if ( ip_fw_chk(ip,
 859                         stage == IP_FW_CHK_BLK ?
 860                         ip_fw_blk_chain : ip_fw_fwd_chain )
 861                        ) 
 862                         return(0);
 863                 else    
 864                         return(EACCES);
 865         }
 866 
 867 /*
 868  *      Here we really working hard-adding new elements
 869  *      to blocking/forwarding chains or deleting'em
 870  */
 871 
 872         if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
 873                 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
 874                 )
 875         {
 876                 struct ip_fw *frwl;
 877                 frwl=check_ipfw_struct(m,len);
 878                 if (frwl==NULL)
 879                         return (EINVAL);
 880                 
 881                 switch (stage) 
 882                 {
 883                         case IP_FW_ADD_BLK:
 884                                 return(add_to_chain(&ip_fw_blk_chain,frwl));
 885                         case IP_FW_ADD_FWD:
 886                                 return(add_to_chain(&ip_fw_fwd_chain,frwl));
 887                         case IP_FW_DEL_BLK:
 888                                 return(del_from_chain(&ip_fw_blk_chain,frwl));
 889                         case IP_FW_DEL_FWD: 
 890                                 return(del_from_chain(&ip_fw_fwd_chain,frwl));
 891                         default:
 892                         /*
 893                          *      Should be panic but... (Why are BSD people panic obsessed ??)
 894                          */
 895 #ifdef DEBUG_CONFIG_IP_FIREWALL
 896                                 printf("ip_fw_ctl:  unknown request %d\n",stage);
 897 #endif
 898                                 return(EINVAL);
 899                 }
 900         } 
 901 
 902 #ifdef DEBUG_CONFIG_IP_FIREWALL
 903         printf("ip_fw_ctl:  unknown request %d\n",stage);
 904 #endif
 905         return(EINVAL);
 906 }
 907 #endif /* CONFIG_IP_FIREWALL */

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