www.pudn.com > Firewall_PNE_3_3.zip > usrFwHomegwRules.c, change:2009-03-16,size:68579b


/* usrFwHomegwRules.c  - Sample firewall rules for Home/SOHO Gateway */

/* Copyright 2004-2005 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01l,28sep05,zhu  Added rate limit with host tracking and HTTP content filter
                 Removed rule for website blocking by keyword
01k,17jun05,svk  Fix compilation warnings
01j,27may05,svk  Replace fwStringSearch() with fastStrSearch()
01i,26apr05,zhu  Removed deprecated header files
01i,05apr05,myz  added fwExtIpOptsCheck
01h,29mar05,svk  Replace usage of Tornado with Workbench
01g,06apr04,svk  Send TCP RST for unsolicited SYN-ACK packets
01f,01apr04,svk  Add rules for basic DoS protection
01e,19mar04,svk  add MAC address filtering
01d,18mar04,svk  reorganize, add rules to allow inbound services
01c,17mar04,svk  add rules for spoofing protection
01b,15mar04,svk  add rule for website blocking by keyword
01a,06mar04,svk  created
*/

/* 
DESCRIPTION


This file supplies sample firewall rules for a Home/SOHO Gateway. The 
filtering policy is described below:

- All hosts on private network are trusted; all hosts on public network
  are untrusted.

- All services are available on hosts in the public network. 

- Only specifically configured services (FTP, HTTP, TELNET, SMTP, POP3)
  can be offered by hosts in the private network. Other than these 
  services, hosts on the public network can not initiate new connections 
  to the hosts on the private network.

- No services are available on the Gateway. That means hosts on the public
  network can not initiate new connections to the Gateway.

- Allow FTP clients in Normal (Active) mode on the private network to 
  talk to FTP servers on the public network.
  
- Block anonymous pings from the public network.

- Allow only specified list of private host MAC Addresses to access 
  the Gateway.

- In addition, protect the Gateway and private network from some 
  Denial of Service (DoS) attacks from the untrusted public network by:

  1. Rejecting packets with spoofed source IP addresses (protects
     against LAND attack, and others that use reserved/private source 
     IP addresses).

  2. Rejecting IP Directed Broadcast packets (protects against Smurf 
     and Fraggle type flooding attacks).

  3. Rejecting packets with illegal TCP flag combinations (protects
     against Xmas scan, NULL scan, and similar types of port scanning).

  4. Rejecting or Reassembling fragmented packets (protects against
     fragmentation based attacks such as Ping of death, Jolt, sPing,
     Teardrop, Newtear, Bonk, Boink, etc.).


ASSUMPTION:
It is assumed that the Firewall has been already been initialized and 
configured to:
- Initialize the logging facility.
- Enable logging for IP Filter.
- Initialize the Stateful inspection.
- Install RX MAC Filter on the Gateway private interface.
- Enable logging for MAC Filter.
You can use the Workbench Kernel Editor to initialize and configure 
the Firewall. Alternately, for a sample Firewall initialization and 
configuration code, refer to:
  target/src/wrn/firewall/sample/usrFwStartup.c

*/

/* includes */

#include <vxWorks.h>
#include <netconf.h>

#include <stdio.h>
#include <string.h>
#include <strSearchLib.h>
#include "wrn/firewall/fwLib.h"
#include "netinet/ip.h"
#include "netinet/tcp.h"
#include "netinet/ip_icmp.h"

/* defines */

#define MACADDR_LEN      6  /* number of bytes in MAC address */
#define MACADDRSTR_MAX  17  /* max length of MAC address string */

#define FRAG_ACCEPT      0  /* allow fragments from public network */
#define FRAG_REJECT      1  /* reject fragments from public network */
#define FRAG_REASSEMBLE  2  /* reassemble fragments from public network */

#define TCP_FLAGS_ALL    (TH_FIN | TH_SYN | TH_RST | TH_PUSH | \
                          TH_ACK | TH_URG)  /* all TCP flags */
                          
#define FTPS_PORT       21  /* FTP service port */
#define HTTPS_PORT      80  /* HTTP service port */
#define TELNETS_PORT    23  /* TELNET service port */
#define SMTPS_PORT      25  /* SMTP service port */
#define POPS_PORT      110  /* POP3 service port */

#define OPT_LEN_MAX     40  /* maximum IP option length */
#define OPT_TYPE_INX     0  /* index to IP option type */
#define OPT_LEN_INX      1  /* index to IP option length */

#define INVALID_PACKET_ACTION  (FW_REJECT)  /* action on invalid packets */ 

/* locals */

/****************** Configuration Section Start ***************************/
/*
 * This is the only part of this file you need to edit to configure the
 * firewall rules for your environment.
 */

/* Network interfaces */

LOCAL char * publicIfName  = "motfcc";  /* public interface name */
LOCAL int    publicIfUnit  = 1;         /* public interface unit number */
LOCAL char * privateIfName = "motscc";  /* private interface name */
LOCAL int    privateIfUnit = 0;         /* private interface unit number */
LOCAL char * loIfName      = "lo";      /* loopback interface name */
LOCAL int    loIfUnit      = 0;         /* loopback interface unit number */

/* Gateway IP address */

LOCAL char * publicGwAddr   = "147.11.1.254"; /* gateway public IP address */

/* Public network Broadcast address */

LOCAL char * publicBcastAddr = "147.11.1.255"; /* public net broadcast addr */

/* IP address range of private network */

LOCAL char * privateStartAddr = "192.124.127.1";   /* private net start addr */
LOCAL char * privateEndAddr   = "192.124.127.254"; /* private net end addr   */

/* Block Spoofed packets from public network */

LOCAL BOOL spoofingBlock = TRUE;   /* block packets with spoofed source IP */
                                   /* addresses from public network        */

/* Block IP Directed Broadcast from public network */
                                    
LOCAL BOOL directedBcastBlock = TRUE; /* block directed broadcast packets */
                                       /* from public network              */

/* How to handle fragmented packets from public network */

LOCAL BOOL fragmentsAction = FRAG_REJECT; /* reject/reassemble/accept      */
                                          /* fragments from public network */

/* Block packets with illegal TCP flags from public network */

LOCAL BOOL badTcpFlagsBlock = TRUE;  /* block packets with illegal TCP */
                                     /* flag combinations              */

/* Block source routed packets from public network */

LOCAL BOOL sourceRouteBlock = TRUE; /* block source routed packets from */
		                    /* public network */

/* HTTP Content filter */

LOCAL BOOL httpContentFilter = FALSE; /* set to TRUE to enable HTTP */
                                      /* content filtering          */

LOCAL BOOL urlBlock = FALSE; /* set to TRUE to block HTTP URLs based on */
                             /* the two lists below */ 
                             
/* List of specific URLs to be blocked */

LOCAL char * urlBlockList[] =
    {
    "www.badwebsite.com",
    "www.somewebsite.com/badpage",
    NULL    /* last entry _must_ be NULL */
    };
    
/* List of keywords in URLs to be blocked */

LOCAL char * keywordsInUrlBlockList[] =
    {
    "bad",
    "sleaz",
    NULL    /* last entry _must_ be NULL */
    };            
                   
/* Block access to Web Proxy Servers in public network */

LOCAL BOOL proxyBlock = FALSE; /* block hosts in private network from        */
			       /* accessing proxy servers in public network. */
			       /* Prevents users in private network from     */
			       /* circumventing Firewall's content filtering */

/* Block Java Applets */

LOCAL BOOL javaAppletBlock = FALSE; /* block access to pubic web sites */
				    /* containing Java Applets         */

/* Block Active X Controls */

LOCAL BOOL activeXBlock = FALSE; /* block access to public web sites */
				 /* containing Active X controls     */

/* Block Cookies */

LOCAL BOOL cookieBlock = FALSE; /* block cookies from being sent to public */
				/* web servers                             */

/*
 * Services offered from private network for hosts in public network
 *
 * NOTE! For security reasons, typically this is used only with NAT so
 * that externally the services appear to be available from the Gateway.
 */

LOCAL BOOL inFtpsAllow    = FALSE; /* allow FTP service inside private net */
LOCAL BOOL inHttpsAllow   = FALSE; /* allow HTTP service inside private net */
LOCAL BOOL inTelnetsAllow = FALSE; /* allow Telnet service inside private net */
LOCAL BOOL inSmtpsAllow   = FALSE; /* allow SMTP service inside private net */
LOCAL BOOL inPopsAllow    = FALSE; /* allow POP service inside private net */

/* Private host offering the above services */

LOCAL char * privateServerAddr = NULL; /* private host offering services */

/*
 * MAC Address Filter
 */
 
LOCAL BOOL listedMacsAllow = FALSE; /* allow only MAC Addresses listed below */
                                    /* to access Gateway private interface   */
                                   
/* List of private host MAC Addresses allowed to access the Gateway */

LOCAL char * macsAllow[] =
    {
    "00:01:02:03:04:05",
    "0a:0b:0c:d0:e0:f0",
    NULL    /* last entry _must_ be NULL */
    };

/* DoS Flood Protection */

LOCAL BOOL synFloodProtect = TRUE; /* enable TCP SYN flood protection */
LOCAL UINT32 synFloodRate = 200; /* packets/sec - drop SYN packets arriving */
                                 /* from public network faster than this rate*/

LOCAL BOOL udpFloodProtect = TRUE; /* enable UDP flood protection */
LOCAL UINT32 udpFloodRate = 200;  /* packets/sec - drop UDP packets arriving  */
                                  /* from public network faster than this rate*/

LOCAL BOOL pingFloodProtect = TRUE; /* enable PING flood protection */
LOCAL UINT32 pingFloodRate = 200; /* packets/sec - drop Ping packets arriving */
                                  /* from public network faster than this rate*/

/* Logging */

LOCAL UINT32 pktLogLen = 40; /* number of bytes in packet to log */
/****************** Configuration Section End ****************************/


/* forward declarations */

LOCAL STATUS listedMacsAllowRulesSet();
LOCAL STATUS protectionRulesSet();
LOCAL STATUS spoofingRulesSet();
LOCAL STATUS directedBcastRulesSet();
LOCAL STATUS fragmentsRulesSet();
LOCAL STATUS badTcpFlagsRulesSet();
LOCAL STATUS forwardRulesSet();
LOCAL STATUS inGatewayRulesSet();
LOCAL STATUS outRulesSet();
LOCAL STATUS inFtpsAllowRulesSet();
LOCAL STATUS inHttpsAllowRulesSet();
LOCAL STATUS inTelnetsAllowRulesSet();
LOCAL STATUS inSmtpsAllowRulesSet();
LOCAL STATUS inPopsAllowRulesSet();    
LOCAL STATUS sourceRouteBlockRulesSet();
LOCAL UINT32 sourceRouteBlocker (FW_LOC_TYPE, void *, struct mbuf *, void *);
LOCAL STATUS contentFilterRulesSet(void *); 
LOCAL STATUS floodProtectRulesSet();
    
/***************************************************************************
*
* usrFwHomegwRules - Set firewall rules for Home Gateway
*
* RETURNS: OK (success), or ERROR (failure)
*/

STATUS usrFwHomegwRules()
    {
    
    /* Sanity check */

    if ((privateIfName == NULL) || (publicIfName == NULL))
        {
        printf("Must specify private and public interface to continue!\n");
        return ERROR;
        }

    /*
     * Rules to allow only listed private host MAC Addresses to access 
     * the Gateway 
     */
    
    if (listedMacsAllow == TRUE)
        {
        if (listedMacsAllowRulesSet() == ERROR)
            return ERROR;
        }

    /*
     * Rules to protect both gateway and private network from 
     * bad/invalid IP packets incoming from public network
     */

    if ((spoofingBlock == TRUE) || (directedBcastBlock == TRUE) ||
        (fragmentsAction != FRAG_ACCEPT) || (badTcpFlagsBlock == TRUE))
        {     
        if (protectionRulesSet() == ERROR)    
            return ERROR;
        }

    /*
     * Rules for forwarded IP packets
     * i.e., Public network <---> Private network
     */
         
    if (forwardRulesSet() == ERROR)
        return ERROR;

    /*
     * Rules for incoming IP packets to gateway itself
     * i.e., Public/Private network ---> Gateway
     */    
    
    if (inGatewayRulesSet() == ERROR)
        return ERROR;
        
    /*
     * Rules for all outgoing IP packets
     */
     
    if (outRulesSet() == ERROR)
        return ERROR;        
         
    return OK;
    }


/***************************************************************************
*
* listedMacsAllowRulesSet - Set firewall rules to allow only listed private
* host MAC Addresses access the Gateway
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS listedMacsAllowRulesSet()
    {
    char ** pMacsAllow;
    char macBuf[MACADDRSTR_MAX + 1];
    char * token;
    UINT8 mac[MACADDR_LEN];
    int i;

    /*
     * Set the default action of the MAC RX Filter to reject. Only
     * listed MAC addresses are allowed.
     */
    
    if (fwMacFilterDefaultSet(FW_MAC_FILTER_RX, FW_REJECT | FW_LOG,
                              NULL, NULL) == ERROR)
        {
        printf("MAC: Failed to set default action\n");
        return ERROR;
        }
     
    /* Add each listed MAC Address to the MAC Filter cache */
        
    for (pMacsAllow = macsAllow; *pMacsAllow != NULL; pMacsAllow++)
        {
        /* Convert the MAC Address from string to binary format */
         
        if (strlen(*pMacsAllow) > MACADDRSTR_MAX)
            {
            printf("MAC: Invalid MAC Address string %s\n", *pMacsAllow);
            return ERROR;
            }            
        strcpy(macBuf, *pMacsAllow);
        for (token = strtok(macBuf, ":"), i = 0; 
             (token != NULL) && (i < MACADDR_LEN); 
             token = strtok(NULL, ":"), i++)
            {
            mac[i] = (UINT8) strtol(token, (char **)NULL, 16);
            }
        if (i != MACADDR_LEN)
            {
            printf("MAC: Invalid MAC Address string %s\n", macBuf);
            return ERROR;            
            }
            
        /* Add the MAC Address to the cache */
        
        if (fwMacCacheAdd(FW_MAC_FILTER_RX, mac, TRUE) == ERROR)
            {
            printf("MAC: Failed to add Mac Addr to cache\n");
            return ERROR;
            }
        }
    
    return OK;
    }
    
        
/***************************************************************************
*
* protectionRulesSet - Set firewall rules to protect both gateway and 
* private network from bad/invalid IP packets incoming from public network
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS protectionRulesSet()
    {
    void * groupId;
    
    /*
     * The pre-input filter location sees ALL packets (local/forwarded)
     * incoming to any network interface. Therefore, this filter
     * location is ideal for setting rules to protect both the
     * gateway and private network from bad/illegal packets incoming 
     * from public network.
     *
     * Set the default action for pre-input filter location to accept.
     * The input and forward filter location will be responsible for
     * dropping all unwanted incoming packets.
     */
    
    if (fwRuleFilterInstall(FW_PREIN_LOC, FW_ACCEPT, NULL, NULL, NULL, 0)
        == ERROR)
        {
        printf("PRE-IN: Failed to install Rule Filter!\n");
        return ERROR;
        }

    /* Group to accept ALL packets from private network (it is trusted) */
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                                "Trusted Packets from Private Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:PRI: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId, FW_FIELD_NETIF, 
                       (UINT32) privateIfName, privateIfUnit, 0, 0) == ERROR)
        {
        printf("PRE:PRI: Failed to set netif\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("PRE:PRI: Failed to set action\n");
        return ERROR;
        }
        
        

    /*
     * Since all the packets incoming from private network have been
     * accepted, all the rules below apply to packets incoming from
     * public network.
     */

    if (spoofingBlock == TRUE)
        {
        /* Reject packets with spoofed source IP addresses */
    
        if (spoofingRulesSet() == ERROR)
            return ERROR;
        }
        
    if (directedBcastBlock == TRUE)
        {
        /* Reject IP Directed Broadcast */
    
        if (directedBcastRulesSet() == ERROR)
            return ERROR;
        }

    if (badTcpFlagsBlock == TRUE)
        {
        /* Reject packets with illegal TCP flag combinations */

        if (badTcpFlagsRulesSet() == ERROR)
            return ERROR;
        }

    if (synFloodProtect == TRUE || udpFloodProtect == TRUE ||
        pingFloodProtect == TRUE)
        {
        /* Reject TCP SYN or UDP or Ping flood packets */

        if (floodProtectRulesSet() == ERROR)
            return ERROR;
        }

    if (fragmentsAction != FRAG_ACCEPT)
        {
        /* Reject or Reassemble fragments */

        if (fragmentsRulesSet() == ERROR)
            return ERROR;
        }

    if (sourceRouteBlock == TRUE)
        {
        /* Reject packets with IP source routing option */

        if (sourceRouteBlockRulesSet() == ERROR)
            return ERROR;
        }
          
    return OK;
    }


/***************************************************************************
*
* spoofingRulesSet - Set firewall rules to reject packets with spoofed
* source IP addresses.
*
* RETURNS: OK (success), or ERROR (failure)
*/    

LOCAL STATUS spoofingRulesSet()
    {
    void * groupId;
    void * ruleId;
    
    /* Group to reject packets with spoofed source IP addresses */

    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                                "Spoofed packets from Public Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:SPOOF: Can't create rule group\n");
        return ERROR;
        }

    /* Rule to block packets from Historical Broadcast addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF1: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "0.0.0.0", (UINT32) "0.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF1: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF1: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from RFC 1918 Class A private addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF2: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "10.0.0.0", (UINT32) "10.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF2: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF2: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from loopback addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF3: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "127.0.0.0", (UINT32) "127.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF3: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF3: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from Link Local addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF4: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "169.254.0.0", (UINT32) "169.254.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF4: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF4: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from RFC 1918 Class B private addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF5: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "172.16.0.0", (UINT32) "172.31.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF5: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF5: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from TEST-NET addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF6: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "192.0.2.0", (UINT32) "192.0.2.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF6: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF6: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from RFC 1918 Class C private addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF7: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "192.168.0.0", (UINT32) "192.168.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF7: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF7: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from Class D Multicast addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF8: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "224.0.0.0", (UINT32) "239.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF8: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF8: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from Class E Reserved addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF9: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "240.0.0.0", (UINT32) "247.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF9: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF9: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets from Unallocated and Broadcast addresses */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF10: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) "248.0.0.0", (UINT32) "255.255.255.255",
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF10: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF10: Failed to set action\n");
        return ERROR;
        }                  

    /* Rule to block packets claiming to be from our own private network */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF11: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) privateStartAddr, (UINT32) privateEndAddr,
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF11: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF11: Failed to set action\n");
        return ERROR;
        }       
        
    /* Rule to block packets claiming to be from gateway's public address */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:SPOOF12: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) publicGwAddr, (UINT32) publicGwAddr,
                       (UINT32) NULL, (UINT32) NULL) == ERROR)
        {
        printf("PRE:SPOOF12: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:SPOOF12: Failed to set action\n");
        return ERROR;
        }
                     
    return OK;
    }

/***************************************************************************
*
* directedBcastRulesSet - Set firewall rules to reject IP Directed 
* Broadcast. 
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS directedBcastRulesSet()
    {
    void * groupId;
    void * ruleId;

    /*
     * Reject IP Directed Broadcast. This ensures your network can not
     * be used as a Broadcast Amplification site to flood other networks
     * with DoS attacks such as the Smurf/Fraggle.
     */
     
    /* Group to reject Directed Broadcast */
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                         "Directed Broadcast packets from Public Network",
                         pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:BCAST: Can't create rule group\n");
        return ERROR;
        }  
    
    /* Rule to block packets to limited broadcast address */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:BCAST1: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) "255.255.255.255", (UINT32) "255.255.255.255")
        == ERROR)
        {
        printf("PRE:BCAST1: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:BCAST1: Failed to set action\n");
        return ERROR;
        }

    /* Rule to block packets to public network broadcast address */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:BCAST2: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                       (UINT32) NULL, (UINT32) NULL,
                       (UINT32) publicBcastAddr, (UINT32) publicBcastAddr)
        == ERROR)
        {
        printf("PRE:BCAST2: Failed to set IP addr\n");
        return ERROR;
        }                          
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:BCAST2: Failed to set action\n");
        return ERROR;
        }   

    return OK;    
    }

/***************************************************************************
*
* fragmentsRulesSet - Set firewall rules for rejecting or reassembling
* fragmented packets
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS fragmentsRulesSet()
    {
    void * groupId;

    /* Group to reject or reassemble fragments */
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                                "Fragments from Public Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:FRAG: Can't create rule group\n");
        return ERROR;
        }  

    if (fwRuleFieldSet(groupId, FW_FIELD_FRAG, TRUE) == ERROR)
        {
        printf("PRE:FRAG: Failed set frag field\n");
        return ERROR;
        }           
    if (fwRuleFieldSet(groupId, FW_FIELD_ACTION,
                       (fragmentsAction == FRAG_REASSEMBLE)?
                       FW_FRAG_REASSEMBLE : FW_REJECT | FW_LOG) == ERROR)
        {
        printf("PRE:FRAG: Failed set action\n");
        return ERROR;
        }
                
    return OK;
    }

/***************************************************************************
*
* badTcpFlagsRulesSet - Set firewall rules to reject TCP packets with
* illegal TCP flag combinations
*
* RETURNS: OK (success), or ERROR (failure)
*/
    
LOCAL STATUS badTcpFlagsRulesSet()
    {
    void * groupId;
    void * ruleId;
    
    /* Group to reject packets with illegal TCP flag combinations */
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                      "Illegal TCP flag combinations from Public Network",
                      pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:FLAG: Can't create rule group\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(groupId, FW_FIELD_TCP, 0,0,0,0,0,0,0) == ERROR)
        {
        printf("PRE:FLAG: Can't set TCP field\n");
        return ERROR;        
        }
        
    /* Rule to block packets with all flags set - XMAS Scan */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG1: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TCP_FLAGS_ALL, 
                       TCP_FLAGS_ALL, 
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG1: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG1: Failed to set action\n");
        return ERROR;
        }           

    /* Rule to block packets with no flags set - NULL Scan */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG2: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       0, 
                       TCP_FLAGS_ALL, 
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG2: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG2: Failed to set action\n");
        return ERROR;
        }         
        
    /* Rule to block packets with SYN and FIN set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG3: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_SYN | TH_FIN, 
                       TH_SYN | TH_FIN,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG3: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG3: Failed to set action\n");
        return ERROR;
        }                 

    /* Rule to block packets with SYN and RST set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG4: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_SYN | TH_RST, 
                       TH_SYN | TH_RST,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG4: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG4: Failed to set action\n");
        return ERROR;
        }         
        
    /* Rule to block packets with FIN and RST set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG5: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_RST | TH_FIN, 
                       TH_RST | TH_FIN,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG5: Can't set TCP field\n");
        return ERROR;                
        }  
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG5: Failed to set action\n");
        return ERROR;
        }                 
        
    /* Rule to block packets with FIN set, but ACK not set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG6: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_FIN, 
                       TH_FIN | TH_ACK,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG6: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG6: Failed to set action\n");
        return ERROR;
        }                 

    /* Rule to block packets with PUSH set, but ACK not set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG7: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_PUSH, 
                       TH_PUSH | TH_ACK,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG7: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG7: Failed to set action\n");
        return ERROR;
        }                 
        
    /* Rule to block packets with URG set, but ACK not set */
    
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG8: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_URG, 
                       TH_URG | TH_ACK,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG8: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
        {
        printf("PRE:FLAG8: Failed to set action\n");
        return ERROR;
        }                 

    /* Rule to send TCP Reset to unsolicited SYN-ACK packets */

    /*
     * NOTE: In a TCP SYN Flood attack, the attacker sends the server
     * a SYN packet from a spoofed IP address. The server replies with
     * a SYN-ACK and waits for the final SYN-ACK-ACK. If the spoofed IP
     * address is our gateway public address or our private network
     * address, stateful inspection rules would silently drop the  
     * unsolicited SYN-ACK packet from the server. Therefore, the server 
     * will never get the SYN-ACK-ACK and it will typically wait and  
     * retransmit, thereby consuming resources. If the attacker floods 
     * the server with spoofed SYN packets, it can crash/hang the server.
     *
     * To avoid this, do the right thing and sent a RST back.
     */

    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("PRE:FLAG9: Can't create rule\n");
        return ERROR;
        }          
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                       TH_SYN | TH_ACK, 
                       TH_SYN | TH_ACK,
                       FW_AND_OP) == ERROR)
        {
        printf("PRE:FLAG9: Can't set TCP field\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_STATE, FW_CONN_RESPONDER,
                       FW_CONN_STATE_NEW) == ERROR)
        {
        printf("PRE:FLAG9: Can't set state\n");
        return ERROR;                
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION,
                       FW_REJECT | FW_TCP_RESET) == ERROR)
        {
        printf("PRE:FLAG9: Can't set action\n");
        return ERROR;                
        }        
                      
    return OK;
    }
            
/***************************************************************************
*
* floodProtectRulesSet - Set firewall rules for flood protection
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS floodProtectRulesSet()
    {
    void * groupId;
    void * ruleId;    
    
    /* Group for flood protection*/
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC,
                                "Flood Protection from Public Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:FLOOD: Can't create rule group\n");
        return ERROR;
        }

    if (synFloodProtect == TRUE)
        {                    
        /* Rule to block TCP SYN flood */
    
        ruleId = fwRuleCreate(groupId);
        if (ruleId == NULL)
            {
            printf("PRE:FLOOD1: Can't create rule\n");
            return ERROR;
            }          
        if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 0, 0,
                           TH_SYN, TCP_FLAGS_ALL, FW_AND_OP) == ERROR)
            {
            printf("PRE:FLOOD1: Can't set TCP field\n");
            return ERROR;                
            }
        
        /* Rate limit per host up to 57 hosts */  
            
        if (fwRuleFieldSet(ruleId, FW_FIELD_RATELIMIT, FW_GT_OP, synFloodRate, 
                           1, FW_SRC_TRK_ON, 57) == ERROR)
            {
            printf("PRE:FLOOD1: Failed to set rate limit rule\n");
            return ERROR;
            }
        if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
            {
            printf("PRE:FLOOD1: Failed to set action\n");
            return ERROR;
            }                 
        }

    if (udpFloodProtect == TRUE)
        {    
        /* Rule to block UDP flood */
    
        ruleId = fwRuleCreate(groupId);
        if (ruleId == NULL)
            {
            printf("PRE:FLOOD2: Can't create rule\n");
            return ERROR;
            }          
        if (fwRuleFieldSet(ruleId, FW_FIELD_UDP, 0, 0, 0, 0) == ERROR)
            {
            printf("PRE:FLOOD2: Can't set UDP field\n");
            return ERROR;                
            }
        
        /* Rate limit per host up to 57 hosts */  
            
        if (fwRuleFieldSet(ruleId, FW_FIELD_RATELIMIT, FW_GT_OP, udpFloodRate, 
                           1, FW_SRC_TRK_ON, 57) == ERROR)
            {
            printf("PRE:FLOOD2: Failed to set rate limit rule\n");
            return ERROR;
            }
        if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
            {
            printf("PRE:FLOOD2: Failed to set action\n");
            return ERROR;
            }
        }
    
    if (pingFloodProtect == TRUE)
        {    
        /* Rule to block ping flood */
    
        ruleId = fwRuleCreate(groupId);
        if (ruleId == NULL)
            {
            printf("PRE:FLOOD3: Can't create rule\n");
            return ERROR;
            }          
        if (fwRuleFieldSet(ruleId, FW_FIELD_ICMP, ICMP_ECHO, 0)
	    == ERROR)
        {
        printf("PRE:FLOOD3: Can't set ICMP field\n");
        return ERROR;                
        }
        
        /* Rate limit per host up to 57 hosts */  
            
        if (fwRuleFieldSet(ruleId, FW_FIELD_RATELIMIT, FW_GT_OP, pingFloodRate, 
                           1, FW_SRC_TRK_ON, 57) == ERROR)
            {
            printf("PRE:FLOOD3: Failed to set rate limit rule\n");
            return ERROR;
            }
        if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_REJECT) == ERROR)
            {
            printf("PRE:FLOOD3: Failed to set action\n");
            return ERROR;
            }  
        }
        
    return OK;                
    }                   
                    
/***************************************************************************
*
* forwardRulesSet - Set firewall rules for forwarded packets
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS forwardRulesSet()
    {
    void * groupId1;
    void * groupId2;
    void * groupId3;    
    void * ruleId;
    FW_SERVICE_DESC extServiceDesc;
    
    /*
     * Set the default action for ALL forwarded packets (from any
     * network interface) to reject 
     */
    
    if (fwRuleFilterInstall(FW_FORW_LOC, FW_REJECT, NULL, NULL, NULL, 0)
        == ERROR)
        {
        printf("FWD: Failed to install Rule Filter!\n");
        return ERROR;
        } 

    /*
     * Packets forwarded from Public network to Private network
     */
     
    /* Group for Public --> Private packets */
    
    groupId1 = fwRuleGroupCreate(FW_FORW_LOC, 
                                 "Packets Forwarded from Public to Private",
                                 pktLogLen);
    if (groupId1 == NULL)
        {
        printf("FWD-PUB: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId1, FW_FIELD_NETIF, 
                       (UINT32) publicIfName, publicIfUnit,
                       (UINT32) privateIfName, privateIfUnit) == ERROR)
        {
        printf("FWD-PUB: Failed to set netif\n");
        return ERROR;
        }    

    /* Rule to allow packets that are part of established connections */
        
    ruleId = fwRuleCreate(groupId1);
    if (ruleId == NULL)
        {
        printf("FWD-PUB: Can't create rule\n");
        return ERROR;
        }           
    if (fwRuleFieldSet(ruleId, FW_FIELD_STATE, FW_CONN_RESPONDER,
                       FW_CONN_STATE_ESTABLISHED) == ERROR)
        {
        printf("FWD-PUB: Failed to set state\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) 
        == ERROR)
        {
        printf("FWD-PUB: Failed to set action\n");
        return ERROR;
        }    
       
    /* Rule(s) to allow FTP Service on the private network */
    
    if (inFtpsAllow == TRUE)
        {
        if (inFtpsAllowRulesSet(groupId1) == ERROR)
            return ERROR;        
        }
        
    /* Rule(s) to allow HTTP Service on the private network */
    
    if (inHttpsAllow == TRUE)
        {
        if (inHttpsAllowRulesSet(groupId1) == ERROR)
            return ERROR;                
        }
        
    /* Rule(s) to allow Telnet Service on the private network */
    
    if (inTelnetsAllow == TRUE)
        {
        if (inTelnetsAllowRulesSet(groupId1) == ERROR)
            return ERROR;                
        }
        
    /* Rule(s) to allow SMTP Service on the private network */
    
    if (inSmtpsAllow == TRUE)
        {
        if (inSmtpsAllowRulesSet(groupId1) == ERROR)
            return ERROR;                
        }
            
    /* Rule(s) to allow POP Service on the private network */
    
    if (inPopsAllow == TRUE)
        {
        if (inPopsAllowRulesSet(groupId1) == ERROR)
            return ERROR;                
        }

                                            
    /*
     * Packets forwarded from Private network to Public network
     */
         
    /* Group for Private --> Public packets */
    
    groupId2 = fwRuleGroupCreate(FW_FORW_LOC, 
                                 "Packets Forwarded from Private to Public",
                                 pktLogLen);
    if (groupId2 == NULL)
        {
        printf("FWD-PRI: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId2, FW_FIELD_NETIF, 
                       (UINT32) privateIfName, privateIfUnit,
                       (UINT32) publicIfName, publicIfUnit) == ERROR)
        {
        printf("FWD-PRI: Failed to set netif\n");
        return ERROR;
        }    
        
    /* Rule to block HTTP traffic based on content */
    
    if (httpContentFilter == TRUE)
        {
        if (contentFilterRulesSet(groupId2) == ERROR)
            return ERROR;
        }        

    /* Rule to accept all other packets */
    
    ruleId = fwRuleCreate(groupId2);
    if (ruleId == NULL)
        {
        printf("FWD-PRI: Can't create rule\n");
        return ERROR;
        }       
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("FWD-PRI: Failed to set action\n");
        return ERROR;
        }  
         
    /*
     * For FTP Client on Private Network to talk to FTP Server on Public
     * Network in NORMAL (Active) mode, attach an extension handler
     * to the above rule to:
     *
     * a) inspect payload of FTP control channel to look for PORT command
     * b) get the client port of the FTP data channel
     * c) create rules to allow the incoming FTP data channel connection
     */
    extServiceDesc.proto = IPPROTO_TCP;
    extServiceDesc.srcPort = 0;
    extServiceDesc.dstPort = FTPS_PORT;
    if (fwExtHandlerInstall(ruleId, &extServiceDesc, fwExtFtpHandler, 
                            NULL, NULL) == ERROR)
        {
        printf("FWD-PRI: Failed to install FTP ext handler for Client\n");
        return ERROR;
        }

    if (inFtpsAllow == TRUE)
        {
        /*
         * For FTP Server on Private Network to talk to FTP Client on Public
         * Network in Passive mode, attach an extension handler to the
         * above rule to:
         *
         * a) inspect payload of FTP control channel to look for PASV command
         * b) get the server port of the FTP data channel
         * c) create rules to allow the incoming FTP data channel connection
         */ 
                        
        extServiceDesc.proto = IPPROTO_TCP;
        extServiceDesc.srcPort = FTPS_PORT;
        extServiceDesc.dstPort = 0;
        if (fwExtHandlerInstall(ruleId, &extServiceDesc, fwExtFtpHandler, 
                                NULL, NULL) == ERROR)
            {
            printf("FWD-PRI: Failed to install FTP ext handler for Server\n");
            return ERROR;
            }         
        }           

    /*
     * Packets sent in response to rejected packets at Public interface.
     *
     * At pre-input filter location, in addition to rejecting packets you
     * can also choose to send a TCP Reset or an ICMP packet in response
     * to the rejected packet. These packets will go through the
     * Forward filter location, and need to be allowed.
     */
     
    /* Group to allow response to rejected packets from public interface */
   
    groupId3 = fwRuleGroupCreate(FW_FORW_LOC,
                         "Response to Rejected packets from Public Interface",
                         pktLogLen);
    if (groupId3 == NULL)
        {
        printf("FWD-RESP: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId3, FW_FIELD_NETIF,
                       (UINT32) publicIfName, publicIfUnit,
                       (UINT32) publicIfName, publicIfUnit) == ERROR)
        {
        printf("FWD-RESP: Failed to set netif\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId3, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("FWD-RESP: Failed to set action\n");
        return ERROR;
        }
                    
    return OK;   
    }
    
/***************************************************************************
*
* inGatewayRulesSet - Set firewall rules for packets incoming to
* gateway itself
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS inGatewayRulesSet()
    {
    void * groupId1;
    void * groupId2;
    void * groupId3;
    
    /*
     * Set the default action for ALL incoming packets to Gateway 
     * (from any network interface) to reject 
     */
    
    if (fwRuleFilterInstall(FW_IN_LOC, FW_REJECT, NULL, NULL, NULL, 0)
        == ERROR)
        {
        printf("IN: Failed to install Rule Filter!\n");
        return ERROR;
        }

    /* Group to allow packets ONLY if they are part of established connection */

    groupId1 = fwRuleGroupCreate(FW_IN_LOC, 
                                 "Packets from Public to Gateway",
                                  pktLogLen);
    if (groupId1 == NULL)
        {
        printf("IN-PUB: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId1, FW_FIELD_NETIF, 
                       (UINT32) publicIfName, publicIfUnit, 0, 0) == ERROR)
        {
        printf("IN-PUB: Failed to set netif\n");
        return ERROR;
        }     
    if (fwRuleFieldSet(groupId1, FW_FIELD_STATE, FW_CONN_RESPONDER,
                       FW_CONN_STATE_ESTABLISHED) == ERROR)
        {
        printf("IN-PUB: Failed to set state\n");
        return ERROR;
        }

    if (fwRuleFieldSet(groupId1, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) 
        == ERROR)
        {
        printf("IN-PUB: Failed to set action\n");
        return ERROR;
        }
    
    /* Group to allow ALL packets from private network */
    
    groupId2 = fwRuleGroupCreate(FW_IN_LOC, 
                                 "Packets from Private to Gateway",
                                  pktLogLen);
    if (groupId2 == NULL)
        {
        printf("IN-PRI: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId2, FW_FIELD_NETIF, 
                       (UINT32) privateIfName, privateIfUnit, 0, 0) == ERROR)
        {
        printf("IN-PRI: Failed to set netif\n");
        return ERROR;
        } 
    if (fwRuleFieldSet(groupId2, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("IN-PRI: Failed to set action\n");
        return ERROR;
        }
                        
    /* Group to allow ALL packets from Loopback interface */  
    
    groupId3 = fwRuleGroupCreate(FW_IN_LOC, 
                                 "Packets from Loopback Interface",
                                 pktLogLen);
    if (groupId3 == NULL)
        {
        printf("IN-LO: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId3, FW_FIELD_NETIF, 
                       (UINT32) loIfName, loIfUnit, 0, 0) == ERROR)
        {
        printf("IN-LO: Failed to set netif\n");
        return ERROR;
        } 
    if (fwRuleFieldSet(groupId3, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("IN-LO: Failed to set action\n");
        return ERROR;
        }          
            
    return OK;
    }
    

/***************************************************************************
*
* outRulesSet - Set firewall rules for all outgoing packets 
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS outRulesSet()
    {
    void * groupId;
    
    /*
     * Set the default action for ALL outgoing packets (to any
     * network interface) to accept for performance 
     */
    
    if (fwRuleFilterInstall(FW_OUT_LOC, FW_ACCEPT, NULL, NULL, NULL, 0)
        == ERROR)
        {
        printf("OUT: Failed to install Rule Filter!\n");
        return ERROR;
        }

    /*
     * Group to allow ALL packets outgoing to the public network 
     * and keep state
     */

    groupId = fwRuleGroupCreate(FW_OUT_LOC, 
                                "Outgoing Packets to Public Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("OUT-PUB: Can't create rule group\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId, FW_FIELD_NETIF, 0, 0, 
                       (UINT32) publicIfName, publicIfUnit) == ERROR)
        {
        printf("OUT-PUB: Failed to set netif\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId, FW_FIELD_STATE, FW_CONN_INITIATOR,
                       FW_CONN_STATE_ALL) == ERROR)
        {
        printf("OUT-PUB: Failed to set state\n");
        return ERROR;
        }
    if (fwRuleFieldSet(groupId, FW_FIELD_ACTION, FW_ACCEPT) == ERROR)
        {
        printf("OUT-PUB: Failed to set action\n");
        return ERROR;
        }   
            
    return OK;
    }

/***************************************************************************
*
* contentFilterRulesSet - Set rule to block HTTP traffic based on content
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS contentFilterRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;
    static void * svcHdl;
    static void * pUrlDesc;    
    char ** pUrls = (char **) urlBlockList;
    char ** pKeywords = (char **) keywordsInUrlBlockList;
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("WEB: Can't create rule\n");
        return ERROR;
        }
        
    /* Create a firewall rule to intercept the outbound HTTP traffic. */
    
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, HTTPS_PORT, HTTPS_PORT, 
                       0, 0, 0) == ERROR)
        {
        printf("WEB: Failed to set TCP fields\n");
        return ERROR;
        }
         
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_USER_ACTION) == ERROR)
        {
        printf("WEB: Failed to set action\n");
        return ERROR;
        }  
        
    /* create a service container */

    svcHdl = fwExtSvcCreate();

    /* create a empty URL database */

    pUrlDesc = fwUrlListCreate();

    /* add URL pathes and keywords */
    
    if ((urlBlock == TRUE) && (pUrls != NULL))
        {
        for (; *pUrls != NULL; pUrls++)
            {
            fwUrlAdd(pUrlDesc,*pUrls,FW_URL_SPECIFIC_PATH);            
            }
        }   

    if ((urlBlock == TRUE) && (pKeywords != NULL))
        {
        for (; *pKeywords != NULL; pKeywords++)
            {
            fwUrlAdd(pUrlDesc,*pKeywords,FW_URL_KEYWORD);            
            }
        }  

    /* 
     * Register the URL filter, proxy filter, Java Applet filter,
     * activeX control filter and the cookie filter
     */
    if (urlBlock == TRUE)
        fwExtSvcReg(svcHdl,"URL filter",fwUrlFilter,(void *)pUrlDesc,
		    FW_REJECT);
    if (proxyBlock == TRUE)        
        fwExtSvcReg(svcHdl,"Filter Proxy",fwProxyFilter,NULL,FW_REJECT);
    if (javaAppletBlock == TRUE)        
        fwExtSvcReg(svcHdl,"Block Java Applet",fwJavaAppletFilter,NULL,
                    FW_REJECT);
    if (activeXBlock == TRUE)                    
        fwExtSvcReg(svcHdl,"Block ActiveX",fwActiveXFilter,NULL,
                    FW_REJECT);
    if (cookieBlock == TRUE)                    
        fwExtSvcReg(svcHdl,"Cookie Block",fwCookieFilter,NULL,0);

    /* Install the service process function to the given firewall rule */

    if (fwExtHandlerInstall(ruleId, NULL, fwExtSvcProcess, svcHdl, NULL) 
        == ERROR)
        {
        printf("Content: Failed to install extension handler\n");
        return ERROR;
        }    

    return OK;              
    }
		
/***************************************************************************
*
* inFtpsAllowRulesSet - Set firewall rule(s) allow FTP service offered
* by a private host.
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS inFtpsAllowRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;
    
    /* Sanity check */
    
    if (privateServerAddr == NULL)
        {
        printf("Address of private host offering service not specified!n");
        return ERROR;
        }

    /* Rule to allow FTP traffic to the private host offering service */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("FTPS: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) privateServerAddr, (UINT32) privateServerAddr)
        == ERROR)
        {
        printf("FTPS: Failed to set IP addr\n");
        return ERROR;
        }                   
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, FTPS_PORT, FTPS_PORT, 
                       0, 0, 0) == ERROR)
        {
        printf("FTPS: Failed to set TCP fields\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) == ERROR)
        {
        printf("FTPS: Failed to set action\n");
        return ERROR;
        }  
        
    return OK;
    }

/***************************************************************************
*
* inHttpsAllowRulesSet - Set firewall rule(s) allow HTTP service offered
* by a private host.
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS inHttpsAllowRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;

    /* Sanity check */
    
    if (privateServerAddr == NULL)
        {
        printf("Address of private host offering service not specified!n");
        return ERROR;
        }

    /* Rule to allow HTTP traffic to the private host offering service */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("HTTPS: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) privateServerAddr, (UINT32) privateServerAddr)
        == ERROR)
        {
        printf("HTTPS: Failed to set IP addr\n");
        return ERROR;
        }                   
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, HTTPS_PORT, HTTPS_PORT, 
                       0, 0, 0) == ERROR)
        {
        printf("HTTPS: Failed to set TCP fields\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) == ERROR)
        {
        printf("HTTPS: Failed to set action\n");
        return ERROR;
        }  
            
    return OK;
    }

/***************************************************************************
*
* inTelnetsAllowRulesSet - Set firewall rule(s) allow TELNET service offered
* by a private host.
*
* RETURNS: OK (success), or ERROR (failure)
*/
    
LOCAL STATUS inTelnetsAllowRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;

    /* Sanity check */
    
    if (privateServerAddr == NULL)
        {
        printf("Address of private host offering service not specified!n");
        return ERROR;
        }

    /* Rule to allow TELNET traffic to the private host offering service */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("TELS: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) privateServerAddr, (UINT32) privateServerAddr)
        == ERROR)
        {
        printf("TELS: Failed to set IP addr\n");
        return ERROR;
        }                   
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, 
               TELNETS_PORT, TELNETS_PORT, 0, 0, 0) == ERROR)
        {
        printf("TELS: Failed to set TCP fields\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) == ERROR)
        {
        printf("TELS: Failed to set action\n");
        return ERROR;
        }  
            
    return OK;
    }

/***************************************************************************
*
* inSmtpsAllowRulesSet - Set firewall rule(s) allow SMTP service offered
* by a private host.
*
* RETURNS: OK (success), or ERROR (failure)
*/
    
LOCAL STATUS inSmtpsAllowRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;

    /* Sanity check */
    
    if (privateServerAddr == NULL)
        {
        printf("Address of private host offering service not specified!n");
        return ERROR;
        }

    /* Rule to allow SMTP traffic to the private host offering service */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("SMTPS: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) privateServerAddr, (UINT32) privateServerAddr)
        == ERROR)
        {
        printf("SMTPS: Failed to set IP addr\n");
        return ERROR;
        }                   
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, SMTPS_PORT, SMTPS_PORT, 
               0, 0, 0) == ERROR)
        {
        printf("SMTPS: Failed to set TCP fields\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) == ERROR)
        {
        printf("SMTPS: Failed to set action\n");
        return ERROR;
        }  
            
    return OK;
    }

/***************************************************************************
*
* inPopsAllowRulesSet - Set firewall rule(s) allow POP3 service offered
* by a private host.
*
* RETURNS: OK (success), or ERROR (failure)
*/
    
LOCAL STATUS inPopsAllowRulesSet
    (
    void * groupId
    )
    {
    void * ruleId;

    /* Sanity check */
    
    if (privateServerAddr == NULL)
        {
        printf("Address of private host offering service not specified!n");
        return ERROR;
        }

    /* Rule to allow POP3 traffic to the private host offering service */
        
    ruleId = fwRuleCreate(groupId);
    if (ruleId == NULL)
        {
        printf("POPS: Can't create rule\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_IPADDRSTR, 
                   (UINT32) NULL, (UINT32) NULL,
                   (UINT32) privateServerAddr, (UINT32) privateServerAddr)
        == ERROR)
        {
        printf("POPS: Failed to set IP addr\n");
        return ERROR;
        }                   
    if (fwRuleFieldSet(ruleId, FW_FIELD_TCP, 0, 0, POPS_PORT, POPS_PORT, 
                       0, 0, 0) == ERROR)
        {
        printf("POPS: Failed to set TCP fields\n");
        return ERROR;
        }
    if (fwRuleFieldSet(ruleId, FW_FIELD_ACTION, FW_ACCEPT | FW_LOG) == ERROR)
        {
        printf("POPS: Failed to set action\n");
        return ERROR;
        }  
            
    return OK;
    }

/***************************************************************************
*
* sourceRouteBlockRulesSet - Set firewall rule to block packets with the
* IP source routing option.
*
* IP source routing can be used to specify a direct route to a destination
* and a return path back to the sender. The route could involve the use of
* other routers or hosts that normally would not be used to forward packets
* to the destination. This option can be used to trick Firewalls into
* allowing connections from hosts that otherwise would not be allowed. It
* can lead to breakins and intruder activity.
*
* RETURNS: OK (success), or ERROR (failure)
*/

LOCAL STATUS sourceRouteBlockRulesSet()
    {
    void * groupId;

    /* Group to reject IP source routed packets */
    
    groupId = fwRuleGroupCreate(FW_PREIN_LOC, 
                                "Source Routed packets from Public Network",
                                pktLogLen);
    if (groupId == NULL)
        {
        printf("PRE:SRCRT: Can't create rule group\n");
        return ERROR;
        }  
        
    /* Applies only if IP options are present - i.e., IP header len > 20 */
    
    if (fwRuleFieldSet(groupId, FW_FIELD_HDRLEN, 20, FW_GT_OP) == ERROR)
        {
        printf("PRE:SRCRT Failed to set IP header length field\n");
        return ERROR;
        }
        
    /* 
     * Install an extension handler to deep-inspect the packet to
     * look for IP source routing option.
     */
     
    if (fwRuleFieldSet(groupId, FW_FIELD_ACTION, FW_USER_ACTION) == ERROR)
        {
        printf("PRE:SRCRT: Failed to set action\n");
        return ERROR;
        }  
    if (fwExtHandlerInstall(groupId, NULL, sourceRouteBlocker, 
                            NULL, NULL) == ERROR)
        {
        printf("PRE:SRCRT: Failed to install extension handler\n");
        return ERROR;
        }
        
    return OK;   
    }
    
/*****************************************************************************
*
* sourceRouteBlocker - Reject packets with IP source routing option
*
* This function validates option length field as it parses through and
* checks for either a loosely or strictly source routing option. If so,
* it returns a reject action code. Otherwise, it returns the action code to
* evaluate the next rule.
*
* RETURNS: Firewall action code
*/

LOCAL UINT32 sourceRouteBlocker
    (
    FW_LOC_TYPE loc,
    void * groupId,
    struct mbuf * m,
    void * arg
    )
    {
    struct ip * pIp = mtod(m,struct ip *);
    UINT8 * pOption;
    UINT8 * pOptStart;
    int optLen;
    UINT8 tmpHolder[OPT_LEN_MAX];

    optLen = ((pIp->ip_hl) << 2) - sizeof(struct ip);
    
    /* Packets with invalid option length */
    
    if (optLen < 0 || optLen > OPT_LEN_MAX)
        return INVALID_PACKET_ACTION;

    /* 
     * First make sure the IP option data is in the same mbuf, otherwise
     * copy to temp buf to operate.
     */

    if (m->m_len < (optLen + sizeof(struct ip)))
        {
        /* Option data not in a single mbuf */

        if (!netMblkOffsetToBufCopy(m,sizeof(struct ip),(char *)tmpHolder,
                                    optLen,NULL))
            return INVALID_PACKET_ACTION;

        pOptStart = tmpHolder;
        }
    else
        pOptStart = (UINT8 *)(pIp + 1);

    /* Init current option pointer */

    pOption = pOptStart;

    while ((pOption - pOptStart) < optLen)
        {
        if (pOption[OPT_TYPE_INX] == IPOPT_EOL)
            break;
        if (pOption[OPT_TYPE_INX] == IPOPT_NOP)
            pOption++;
        else
            {
            if ((pOption[OPT_TYPE_INX] == IPOPT_LSRR) ||
                (pOption[OPT_TYPE_INX] == IPOPT_SSRR) )
                {
                /* Loosely or strictly routed packet */

                return (FW_REJECT | FW_LOG);
                }

            /* Invalid option length, less than minimum */

            if (pOption[OPT_LEN_INX] < IPOPT_OFFSET)
                return INVALID_PACKET_ACTION; 
                
            pOption += pOption[OPT_LEN_INX];

            /* Invalid option length, greater than maximum */

            if ((pOption - pOptStart) > optLen)
                return INVALID_PACKET_ACTION; 
            }
        }

    /* Not a source routed packet; evaluate the next rule */
   
    return FW_NEXT_RULE;        
    }