Files
m241Neelima/components/ip_net2-6.9/ipfirewall/src/ipfirewall_userdef_http.c
T
2026-07-30 11:19:44 +05:30

1556 lines
54 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipfirewall_userdef_http.c,v $ $Revision: 1.30.10.2 $
* $Source: /home/interpeak/CVSRoot/ipfirewall/src/ipfirewall_userdef_http.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Markus Carlstedt <markus@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* This library provides a rudimentary content filter for the HTTP packet.It
* performs the URL filtering, proxy filtering, cookie blocking, Java applet and
* ActiveX control filtering actions. The URL filtering is done based on the
* user specified URL database. Each entry of the database can specify either a
* URL path or a URL keyword to match. The proxy filtering matches all the packets
* which have absolute URI in its request line, i.e. the URI has the form:
* http://xxx.xxx.xxx/xxx. The cookie filtering replaces the cookie with the same
* length of the meaningless data in the request packet. It does not prevent the
* cookie from being set to your host. It simply prevents the cookie from being
* transmitted back to the server. Java applet and ActiveX control filterings
* simply block the requests for the files with extension .zip, .class, .jar;
* and .ocx,.cab respectively. It does not inspect the HTML OBJECT or APPLET tags
* or the signature of the object binary content.
* This content filter utilizes the firewall extension handler service
* registration mechanism to allow user add/remove the filtering functions
* described above dynamically. The content filter operates in the context of
* the firewall extension handler installed on a firewall rule intercepting the
* outbound HTTP traffic.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_list.h>
#include <ipcom_syslog.h>
#include <ipcom_err.h>
#define IPFIREWALL_C
#include "ipfirewall.h"
#include "ipfirewall_h.h"
#ifdef IPFIREWALL_USE_HTTP_FILTER
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
*===========================================================================
* HTTP Filter identifier length
*===========================================================================
*/
#define IPFIREWALL_HTTP_FILTER_MAX_ID 32
/*
*===========================================================================
* URL filter type
*===========================================================================
*/
#define IPFIREWALL_CLASS_INDIVIDUAL 1 /* filter specific URLs */
#define IPFIREWALL_CLASS_ABS_URI 2 /* filter absolute URI URLs */
/*
*===========================================================================
* URL match type
*===========================================================================
*/
#define IPFIREWALL_URL_SPECIFIC_PATH 1 /* URL path match */
#define IPFIREWALL_URL_KEYWORD 2 /* URL keyword match */
/*
*===========================================================================
* Object filter type
*===========================================================================
*/
#define IPFIREWALL_OBJ_FILTER_JAVA 1 /* Java object filter type */
#define IPFIREWALL_OBJ_FILTER_ACTIVEX 2 /* ActiveX control filter type */
/*
*===========================================================================
* Constants
*===========================================================================
*/
#define IPFIREWALL_ONE_SPACE 1
#define IPFIREWALL_TOKEN_GET "GET"
#define IPFIREWALL_TOKEN_HTTP "http"
#define IPFIREWALL_TOKEN_HOST "Host"
#define IPFIREWALL_HTTP_S2H_LEN 7
#define IPFIREWALL_TMNATOR_TYPE_SPECIFIC 1
#define IPFIREWALL_TMNATOR_TYPE_GENERIC 2
#define IPFIREWALL_LOOSE_MATCH 0x10
#define IPFIREWALL_STRICT_MATCH 0x20
#define IPFIREWALL_FILE_EXT_MAXLEN 10
#define IPFIREWALL_SMALL_PATTERN_SIZE 5
#define IPFIREWALL_UCHAR_MAX 255
/*
*===========================================================================
* Macros
*===========================================================================
*/
#define IPFIREWALL_IS_STRING_SAME(str,strid) (ipcom_memcmp(str,strid,ipcom_strlen(strid)) == 0)
#define IPFIREWALL_NEXT_FIELD_POS(curToken) (ipcom_strlen(curToken) + IPFIREWALL_ONE_SPACE)
#define IPFIREWALL_TMNATOR_TYPE(t) ((t) & 0xff)
#define IPFIREWALL_TMNATOR_MATCH(t) (((t) >> 8) & 0xff)
#define IPFIREWALL_STR_GENERIC_TMNATOR(ch) ((ch) == '/' || (ch) == '\r' || (ch) == 0)
#define IPFIREWALL_ALIGNED(x, align) (((unsigned long)(x) & (align - 1)) == 0)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipfirewall_url
*===========================================================================
*/
typedef struct Ipfirewall_url_struct
{
Ipcom_list list_url;
char *url; /* URL string */
Ip_u16 len; /* the host length of URL, or entire length if keyword */
Ip_u16 attr; /* path or keyword type */
}
Ipfirewall_url;
/*
*===========================================================================
* Ipfirewall_http
*===========================================================================
*/
typedef struct Ipfirewall_http_struct
{
Ipcom_list list_http;
Ipcom_list head_url;
Ip_bool proxy;
Ip_bool cookie;
Ip_bool java;
Ip_bool activex;
char identifier[IPFIREWALL_HTTP_FILTER_MAX_ID];
}
Ipfirewall_http;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_GLOBAL Ipcom_list head_http;
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipfirewall_http_bms_str_search
*===========================================================================
* Description: Search using the Boyer-Moore-Sunday (Quick Search) algorithm
* The Boyer-Moore-Sunday algorithm is a more efficient simplification of
* the Boyer-Moore algorithm. It performs comparisons between a character
* in the pattern and a character in the text buffer from left to right.
* After each mismatch it uses bad character heuristic to shift the
* pattern to the right. For more details on the algorithm, refer to
* "A Very Fast Substring Search Algorithm", Daniel M. Sunday, Communications
* of the ACM, Vol. 33 No. 8, August 1990, pp. 132-142.
* It has a O(Pattern Length x Text Buffer Length) worst-case time complexity.
* But empirical results have shown that this algorithm is one of the
* fastest in practice.
* Parameters: pattern - pattern to search for
* pattern_len - length of the pattern
* buffer - text buffer to search in
* buffer_len - length of the text buffer
* case_sensitive - case-sensitive search
* Returns: A pointer to the located pattern, or a IP_NULL pointer if the
* pattern is not found
*/
IP_STATIC char *
ipfirewall_http_bms_str_search(char *pattern,
int pattern_len,
char *buffer,
int buffer_len,
Ip_bool case_sensitive)
{
int skip_table[IPFIREWALL_UCHAR_MAX + 1];
int i;
int b;
char *p_pattern;
char *p_buffer;
char *p_buffer_compare;
char *p_pattern_end = pattern + pattern_len;
char *p_buffer_end = buffer + buffer_len - pattern_len + 1;
/* Validation check */
if ((pattern == IP_NULL) || (pattern_len == 0) ||
(buffer == IP_NULL) || (buffer_len == 0) ||
(pattern_len > buffer_len))
{
return IP_NULL;
}
/* Setup the skip table for the pattern */
for (i = 0; i < IPFIREWALL_UCHAR_MAX + 1; i++)
skip_table[(Ip_u8)i] = pattern_len + 1;
for (p_pattern = pattern; p_pattern < p_pattern_end; p_pattern++)
{
if (case_sensitive == IP_TRUE)
skip_table[(Ip_u8)*p_pattern] = (int)(p_pattern_end - p_pattern);
else
{
b = ipcom_tolower((int)*p_pattern);
skip_table[b] = (int)(p_pattern_end - p_pattern);
b = ipcom_toupper((int)*p_pattern);
skip_table[b] = (int)(p_pattern_end - p_pattern);
}
}
/* Main loop is the fast skip loop */
for (p_buffer = buffer; p_buffer < p_buffer_end;
p_buffer += skip_table[(Ip_u8)*(p_buffer + pattern_len)])
{
/* Comparison loop */
if (case_sensitive == IP_TRUE)
{
for (p_pattern = pattern, p_buffer_compare = p_buffer;
(p_pattern < p_pattern_end) && (*p_pattern == *p_buffer_compare);
p_pattern++, p_buffer_compare++)
;
}
else
{
for (p_pattern = pattern, p_buffer_compare = p_buffer;
(p_pattern < p_pattern_end) &&
(toupper((int)*p_pattern) == toupper((int)*p_buffer_compare));
p_pattern++, p_buffer_compare++)
;
}
if (p_pattern == p_pattern_end)
return p_buffer; /* match */
}
/* no match */
return IP_NULL;
}
/*
*===========================================================================
* ipfirewall_http_bf_str_search
*===========================================================================
* Description: Search using the Brute Force algorithm
* The Brute Force algorithm is the simplest string search
* algorithm. It performs comparisons between a character in
* the pattern and a character in the text buffer from left to
* right. After each attempt it shifts the pattern by one position
* to the right. The Brute Force algorithm requires no
* pre-processing and no extra space. It has a O(Pattern Length
* x Text Buffer Length) worst-case time complexity.
* Parameters: pattern - pattern to search for
* pattern_len - length of the pattern
* buffer - text buffer to search in
* buffer_len - length of the text buffer
* case_sensitive - case-sensitive search
* Returns: A pointer to the located pattern, or a IP_NULL pointer if the
* pattern is not found
*/
IP_STATIC char *
ipfirewall_http_bf_str_search(char *pattern,
int pattern_len,
char *buffer,
int buffer_len,
Ip_bool case_sensitive)
{
char *p_pattern;
char *p_buffer;
char *p_buffer_compare;
char *p_pattern_end = pattern + pattern_len;
char *p_buffer_end = buffer + buffer_len - pattern_len + 1;
/* Validation check */
if ((pattern == IP_NULL) || (pattern_len == 0) ||
(buffer == IP_NULL) || (buffer_len == 0) ||
(pattern_len > buffer_len))
{
return IP_NULL;
}
for (p_buffer = buffer; p_buffer < p_buffer_end; p_buffer++)
{
if (case_sensitive == IP_TRUE)
{
for (p_pattern = pattern, p_buffer_compare = p_buffer;
(p_pattern < p_pattern_end) && (*p_pattern == *p_buffer_compare);
p_pattern++, p_buffer_compare++)
;
}
else
{
for (p_pattern = pattern, p_buffer_compare = p_buffer;
(p_pattern < p_pattern_end) &&
(toupper((int)*p_pattern) == toupper((int)*p_buffer_compare));
p_pattern++, p_buffer_compare++)
;
}
if (p_pattern == p_pattern_end)
return p_buffer; /* match */
}
/* no match */
return IP_NULL;
}
/*
*===========================================================================
* ipfirewall_http_fast_str_search
*===========================================================================
* Description: Search by optimally choosing the search algorithm.
* Depending on the pattern size, this function uses either the
* Boyer-Moore-Sunday algorithm or the Brute Force algorithm. The
* Boyer-Moore-Sunday algorithm requires pre-processing,
* therefore for small patterns it is better to use the Brute
* Force algorithm.
* Parameters: pattern - pattern to search for
* pattern_len - length of the pattern
* buffer - text buffer to search in
* buffer_len - length of the text buffer
* case_sensitive - case-sensitive search
* Returns: A pointer to the located pattern, or a IP_NULL pointer if the
* pattern is not found
*/
IP_STATIC char *
ipfirewall_http_fast_str_search(char *pattern,
int pattern_len,
char *buffer,
int buffer_len,
Ip_bool case_sensitive)
{
if (pattern_len >= IPFIREWALL_SMALL_PATTERN_SIZE)
return ipfirewall_http_bms_str_search(pattern, pattern_len, buffer,
buffer_len, case_sensitive);
else
return ipfirewall_http_bf_str_search(pattern, pattern_len, buffer,
buffer_len, case_sensitive);
}
/*
*===========================================================================
* ipfirewall_http_str_st_len
*===========================================================================
* Description: Returns the length of a string with specific terminator
* Parameters: str - pointer to the string
* terminator - terminating character
* maxlen - maximum length to search
* Returns: length of string
*/
IP_STATIC int
ipfirewall_http_str_st_len(char *str, char terminator, int maxlen)
{
int i;
for (i = 0; i < maxlen; i++)
{
if (str[i] == terminator)
return i;
}
return 0;
}
/*
*===========================================================================
* ipfirewall_http_is_ci_string_same
*===========================================================================
* Description: Compare two case insensitive strings
* Parameters: str - pointer to string one.
* id_str - pointer to string two.
* Returns: IP_TRUE if strings are the same or IP_FALSE if not.
*/
IP_STATIC Ip_bool
ipfirewall_http_is_ci_string_same(char *str, char *id_str)
{
Ip_u32 len, i;
len = (Ip_u32)ipcom_strlen(id_str);
for (i = 0; i < len; i++)
if (ipcom_tolower((Ip_u8)str[i]) != ipcom_tolower((Ip_u8)id_str[i]))
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipfirewall_http_str_ci_cmp
*===========================================================================
* Description: Compare two case insensitive strings with specific
* terminators.
* Parameters: str1 - pointer to string one.
* str2 - pointer to string two.
* typematch - compare type.
* Returns: IP_TRUE if strings are the same or IP_FALSE if not.
*/
IP_STATIC Ip_bool
ipfirewall_http_str_ci_cmp(char *str1, char *str2, int typematch, char term1, char term2)
{
int cnt = 0;
Ip_bool cond1;
Ip_bool cond2;
for(;;)
{
if (IPFIREWALL_TMNATOR_TYPE(typematch) == IPFIREWALL_TMNATOR_TYPE_SPECIFIC)
{
cond1 = (str1[cnt] == term1);
cond2 = (str2[cnt] == term2);
}
else /* TMNATOR_TYPE_GENERIC */
{
cond1 = IPFIREWALL_STR_GENERIC_TMNATOR(str1[cnt]);
cond2 = IPFIREWALL_STR_GENERIC_TMNATOR(str2[cnt]);
}
if (cond1 && cond2)
return IP_TRUE;
else if (cond1 || cond2)
{
if (IPFIREWALL_TMNATOR_MATCH(typematch) == IPFIREWALL_LOOSE_MATCH)
return IP_TRUE;
else
return IP_FALSE;
}
if (ipcom_tolower((Ip_u8)str1[cnt]) != ipcom_tolower((Ip_u8)str2[cnt]))
return IP_FALSE;
cnt++;
}
}
/*
*===========================================================================
* ipfirewall_http_find
*===========================================================================
* Description: This function searches for a HTTP filter.
* Parameters: id - identifier
* Returns: Pointer to the HTTP filter defined structure or IP_NULL if not found.
*/
IP_STATIC Ipfirewall_http *
ipfirewall_http_find(const char *id)
{
Ipfirewall_http *fw_http;
/* Check input */
if(id == IP_NULL)
return IP_NULL;
fw_http = IPCOM_LIST_FIRST(&head_http);
while(fw_http != IP_NULL)
{
if(ipcom_strcmp(fw_http->identifier, id) == 0)
return fw_http;
fw_http = IPCOM_LIST_NEXT(&fw_http->list_http);
}
return IP_NULL;
}
/*
*===========================================================================
* ipfirewall_field_name_find
*===========================================================================
* Description: This routine searches a string in a structured message.
* It assumes the searched string always starts at the begining
* of each line of data terminated by \r\n characters. A message
* should be terminated by \r\n preceded by the line terminator
* \r\n.
* Parameters: buf - pointer to the message.
* id - string to search for.
* len - length of the HTTP payload.
* pos - offset where the string was found
* Returns: IP_TRUE = string found
* IP_FALSE = string not found
*/
IP_STATIC Ip_bool
ipfirewall_field_name_find(char *buf, char *id, int len, int *pos)
{
int search_len;
char *start = buf;
if (id == IP_NULL)
return IP_FALSE;
search_len = len;
while (1)
{
/* skip all space */
while (search_len > 0 && buf[0] == ' ')
{
buf++;
search_len--;
}
if (search_len < (int)ipcom_strlen(id))
{
IPCOM_LOG1(DEBUG, "ipfirewall_field_name_find() :: string not '%s' found - reached end of message", id);
return IP_FALSE;
}
if (IPFIREWALL_IS_STRING_SAME(buf, id))
{
IPCOM_LOG2(DEBUG, "ipfirewall_field_name_find() :: found string '%s' att offset %d",
id, buf - start);
break; /* Breaks out of outer loop */
}
/* advance to next line */
while (search_len > 1)
{
if (buf[0] == '\r' && buf[1] == '\n')
break; /* Breaks out of inner loop */
buf++;
search_len--;
}
if (search_len <= 1)
{
IPCOM_LOG1(DEBUG, "ipfirewall_field_name_find() :: string '%s' not found - line end not found", id);
return IP_FALSE;
}
buf += 2;
search_len -= 2;
if (search_len > 1)
{
if (buf[0] == '\r' && buf[1] == '\n')
{
/* reach the end mark \r\n\r\n */
IPCOM_LOG1(DEBUG, "ipfirewall_field_name_find() :: string '%s' not found - reached end mark", id);
return IP_FALSE;
}
}
}
*pos = (int)(buf - start);
return IP_TRUE;
}
/*
*===========================================================================
* ipfirewall_http_checksum_adjust
*===========================================================================
* Description: Adjust the TCP checksum for modified packet. Assume data
* starts at even boundary with even length.
* Parameters: cksum - original checksum.
* buf - pointer to modified data.
* len - modified data length.
* is_adding_data - IP_TRUE if data is added. IP_TRUE if data is
* removed.
* Returns: The new checksum.
*/
IP_STATIC Ip_u32
ipfirewall_http_checksum_adjust(Ip_u32 cksum, Ip_u16 *buf, int len,
Ip_bool is_adding_data)
{
cksum = (~cksum & 0x0000FFFF);
if (is_adding_data == IP_FALSE)
{
/* removing data */
while (len > 0)
{
cksum = cksum - ((*buf++) & 0x0000FFFF);
if ((Ip_s32) cksum <= 0x00000000L)
{
--cksum;
cksum = cksum & 0x0000FFFF;
}
len -= 2;
}
}
else
{
/* adding data */
while (len > 0)
{
cksum = cksum + ((*buf++) & 0x0000FFFF);
if (cksum & 0x00010000)
{
++cksum;
cksum = cksum & 0x0000FFFF;
}
len -= 2;
}
}
cksum = ~cksum;
return cksum;
}
/*
*===========================================================================
* ipfirewall_http_match_cookie
*===========================================================================
* Description: This function prevent a cookie from being sent back to
* the web server by overwritting the cookie in the client's
* request message header. It must therefore recalculate the
* TCP checksum.
* Parameters: buf - pointer to the HTTP payload.
* len - length of the HTTP payload.
* tcp - pointer to tcp header
* Returns: 1 = object found
* 0 = object not found;
*/
IP_STATIC int
ipfirewall_http_match_cookie(Ip_u8 *buf, int len, Ipcom_tcp_header *tcp)
{
Ip_u16 *chksum_start;
int ret, offset, cookielen, cslen, cstokenlen;
Ip_u32 new_checksum = 0;
ret = 0;
if (ipfirewall_field_name_find((char *)buf, "Cookie", len, &offset) == IP_TRUE)
{
buf += offset;
len -= offset;
cookielen = ipfirewall_http_str_st_len((char *)buf, '\r', len);
if (!IPFIREWALL_ALIGNED(buf, 2))
{
chksum_start = (Ip_u16 *)(buf - 1);
cslen = (cookielen & 0x1) ? cookielen + 1 : cookielen + 2;
}
else
{
chksum_start = (Ip_u16 *)buf;
cslen = (cookielen & 0x1) ? cookielen + 1 : cookielen;
}
/* subtract the cookie checksum data from TCP checksum */
new_checksum = ipfirewall_http_checksum_adjust(tcp->checksum, chksum_start, cslen, IP_FALSE);
/* remove the Cookie information by filling some junk data */
cstokenlen = ipfirewall_http_str_st_len((char *)buf, ':', len);
ipcom_memset(buf, 'd', (Ip_size_t)cstokenlen);
/* not to overwrite the : and space */
ipcom_memset(buf + cstokenlen + 2, 'x', (Ip_size_t)(cookielen - (cstokenlen + 2)));
/* add the new Cookie data to the adjusted TCP checksum */
tcp->checksum = (Ip_u16)ipfirewall_http_checksum_adjust(new_checksum, chksum_start, cslen, IP_TRUE);
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_cookie() :: hiding cookie");
ret = 1;
}
return ret;
}
/*
*===========================================================================
* ipfirewall_http_match_object
*===========================================================================
* Description: This function matches binary objects in HTTP GET requests.
* It prevents certain executable files from running in the web
* browser by blocking the requests to the corresponding type
* of files. Currently it blocks the Java Applet by blocking
* the files with extension .class, .jar and .zip; and ActiveX
* control by blocking the files with extension .ocx and .cab.
* Parameters: buf - pointer to the HTTP payload.
* len - length of the HTTP payload.
* type - type of object
* Returns: 1 = object found
* 0 = object not found;
*/
IP_STATIC int
ipfirewall_http_match_object(Ip_u8 *buf, int len, int type)
{
int cnt, ret;
ret = 0;
if (IPFIREWALL_IS_STRING_SAME(buf, IPFIREWALL_TOKEN_GET))
{
/* advance pass GET token and space */
buf += IPFIREWALL_NEXT_FIELD_POS(IPFIREWALL_TOKEN_GET);
len = len - (int)IPFIREWALL_NEXT_FIELD_POS(IPFIREWALL_TOKEN_GET);
cnt = ipfirewall_http_str_st_len((char *)buf, ' ' , len);
buf += cnt;
len -= cnt;
/* search for file extension seperator */
for (cnt=0; (cnt < IPFIREWALL_FILE_EXT_MAXLEN) && (*buf-- != '.'); cnt++);
if (cnt < IPFIREWALL_FILE_EXT_MAXLEN)
{
buf += 2;
if (type == IPFIREWALL_OBJ_FILTER_ACTIVEX)
{
if (ipfirewall_http_is_ci_string_same((char *)buf,"ocx") ||
ipfirewall_http_is_ci_string_same((char *)buf,"cab") )
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_object() :: found activex object");
ret = 1;
}
}
else if (type == IPFIREWALL_OBJ_FILTER_JAVA)
{
if (ipfirewall_http_is_ci_string_same((char *)buf,"class") ||
ipfirewall_http_is_ci_string_same((char *)buf,"jar") ||
ipfirewall_http_is_ci_string_same((char *)buf,"zip") )
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_object() :: found java object");
ret = 1;
}
}
}
}
return ret;
}
/*
*===========================================================================
* ipfirewall_http_match_url
*===========================================================================
* Description: Performs the URL filtering for the HTTP packets.
* This routine filters the HTTP request packets based on the
* given URL database. It performs two match actions: the path
* match and keyword match. The path match means both the host
* name and the file path of the provided URL string matches the
* packet's ones. However, the given file path just needs to
* match the beginning portion of the packet's path. The keyword
* match means thegiven string matches any part of the packet's URL.
* Parameters: buf - pointer to the HTTP payload.
* len - length of the HTTP payload.
* type - URL filter type.
* Returns: 1 = object found
* 0 = object not found;
*/
IP_STATIC int
ipfirewall_http_match_url(Ip_u8 *buf, int len, int type, Ipfirewall_http *fw_http)
{
Ipfirewall_url *fw_url;
int cnt, pathlen, hostlen;
Ip_u8 *host, *path;
/* skip the method token, advance to URI */
cnt = ipfirewall_http_str_st_len((char *)buf, ' ', len);
buf += cnt + 1;
len -= cnt + 1;
/* Request-URI = "*" | absoluteURI | abs_path | authority
* "*" and authority forms are used by OPTION and CONNECT methods
* absoluteURI = scheme ":" ( hier_part | opaque_part )
* hier_part = ( net_path | abs_path ) [ "?" query ]
* net_path = "//" authority [ abs_path ]
* abs_path = "/" path_segments
*
* Host name case insensitive, scheme case insensitive
*/
/* consider absoluteURI and abs_path */
if (ipfirewall_http_str_ci_cmp((char *)buf, IPFIREWALL_TOKEN_HTTP, IPFIREWALL_TMNATOR_TYPE_SPECIFIC, ':', 0) == IP_TRUE)
{
/* absoluteURI
* HTTP/1.1 clients only generates absoluteURI in requests to
* proxies(RFC2616, 5.1.2).
*/
if (type == IPFIREWALL_CLASS_ABS_URI)
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_url() :: Found absolute URI");
return 1;
}
buf += IPFIREWALL_HTTP_S2H_LEN;
len -= IPFIREWALL_HTTP_S2H_LEN;
host = buf;
hostlen = ipfirewall_http_str_st_len((char *)host, '/', len);
path = buf + hostlen;
pathlen = ipfirewall_http_str_st_len((char *)path, ' ', len - hostlen); /* terminated by space */
}
else
{
/* not absolute URI */
if (type == IPFIREWALL_CLASS_ABS_URI)
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_url() :: Not an absolute URI");
return 0;
}
/* abs_path */
path = buf;
pathlen = ipfirewall_http_str_st_len((char *)path, ' ', len);
if (ipfirewall_field_name_find((char *)buf, IPFIREWALL_TOKEN_HOST, len, &cnt) == IP_FALSE)
{
IPCOM_LOG0(INFO, "ipfirewall_http_match_url() :: No 'Host:' token in request");
return 0;
}
buf += cnt;
len -= cnt;
buf += IPFIREWALL_NEXT_FIELD_POS(IPFIREWALL_TOKEN_HOST);
len = len - (int)IPFIREWALL_NEXT_FIELD_POS(IPFIREWALL_TOKEN_HOST);
while (*(char *)(buf) == ' ')
{
buf++;
len--;
}
host = buf;
hostlen = ipfirewall_http_str_st_len((char *)host, '\r', len);
}
ip_assert(fw_http != IP_NULL);
for (fw_url = IPCOM_LIST_FIRST(&fw_http->head_url);
fw_url != IP_NULL;
fw_url = IPCOM_LIST_NEXT(&fw_url->list_url))
{
if (fw_url->attr == IPFIREWALL_URL_SPECIFIC_PATH)
{
if (ipfirewall_http_str_ci_cmp((char *)fw_url->url, (char *)host, IPFIREWALL_TMNATOR_TYPE_GENERIC, 0, 0))
{
if (fw_url->url[fw_url->len] == 0 ||
IPFIREWALL_IS_STRING_SAME(path, fw_url->url + fw_url->len))
{
IPCOM_LOG1(DEBUG, "ipfirewall_http_match_url() :: Matched path: '%s'", fw_url->url);
break;
}
}
}
else
{
/* IPFIREWALL_URL_KEYWORD */
if (ipfirewall_http_fast_str_search((char *)fw_url->url, fw_url->len, (char *)host, hostlen, IP_FALSE) ||
ipfirewall_http_fast_str_search((char *)fw_url->url, fw_url->len, (char *)path, pathlen, IP_TRUE))
{
IPCOM_LOG1(DEBUG, "ipfirewall_http_match_url() :: Matched keyword: '%s'", fw_url->url);
break;
}
}
}
/* check if matches */
if (fw_url != IP_NULL)
{
return 1;
}
else
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match_url() :: No keyword or path matched.");
return 0;
}
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipfirewall_http_match
*===========================================================================
* Description: HTTP filter match function.
* Parameters: pkt - pointer to the ipcom packet
* cookie - a cookie set at registration.
* info - user defined info buffer
* Returns: 1 = rule matched.
* 0 = rule did not match.
*/
IP_PUBLIC int
ipfirewall_http_match(Ipcom_pkt *pkt, void *cookie, void *info)
{
Ipfirewall_http *fw_http;
Ipcom_tcp_header *tcp;
Ip_u8 ver, protocol = 0, is_frag = 0, first_frag = 0, *http_pkt;
Ip_u16 hlen;
int http_len, tcp_hlen, ret;
(void)cookie;
fw_http = *(Ipfirewall_http **)info;
ret = 0;
ip_assert(fw_http != IP_NULL);
/* Check version */
ver = (Ip_u8)(pkt->data[pkt->ipstart] >> 4);
if (ver == 4)
hlen = (Ip_u16)((pkt->data[pkt->ipstart] & 0x0f) << 2);
else if (ver == 6)
hlen = IPCOM_IP6_HEADER_LENGTH;
else
{
IPCOM_LOG0(ERR, "ipfirewall_http_match() :: Unknown version.");
return 0;
}
/* Check that the packet is long enough for the IP header */
if(pkt->end - pkt->ipstart < (int)hlen)
{
IPCOM_LOG0(ERR, "ipfirewall_http_match() :: Packet too short for IP header.");
return 0;
}
#ifdef IPCOM_USE_INET
if (ver == 4)
{
Ipcom_ip_header *ip4;
ip4 = (Ipcom_ip_header *)&pkt->data[pkt->ipstart];
protocol = ip4->protocol;
/* Set MTU to MAX_ULONG */
ipfirewall_get_frag4_info(ip4, pkt, 0xffffffff, &is_frag, &first_frag);
}
#endif
#ifdef IPCOM_USE_INET6
if (ver == 6)
{
Ipcom_ip6_header *ip6;
ip6 = (Ipcom_ip6_header *)&pkt->data[pkt->ipstart];
/* Set MTU to MAX_ULONG */
if (ipfirewall_get_frag6_info(ip6, pkt, 0xffffffff, &is_frag, &first_frag, &protocol, &hlen) < 0)
{
IPCOM_LOG0(ERR, "ipfirewall_http_match() :: Failed to parse IPv6 extension headers.");
return 0;
}
}
#endif
/* Cannot match fragments other than the first */
if (is_frag == 1 && first_frag == 0)
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match() :: Skipped fragment.");
return 0;
}
/* Verify that protocol is TCP */
if (protocol != IP_IPPROTO_TCP)
{
IPCOM_LOG0(DEBUG, "ipfirewall_http_match() :: Skipped non-TCP packet.");
return 0;
}
/* Check that the packet is long enough for mandatory TCP header */
if(pkt->end - pkt->ipstart - (int)hlen < IPCOM_TCP_HEADER_LENGTH)
{
IPCOM_LOG0(ERR, "ipfirewall_http_match() :: Packet too short for mandatory TCP header.");
return 0;
}
/* Store pointer to TCP header */
tcp = (Ipcom_tcp_header *)&pkt->data[pkt->ipstart + (int)hlen];
tcp_hlen = ip_ntohs(tcp->offset_flags)>>10;
/* Check that the packet is long enough for the TCP header */
if(pkt->end - pkt->ipstart - (int)hlen < tcp_hlen)
{
IPCOM_LOG0(ERR, "ipfirewall_http_match() :: Packet too short for TCP header.");
return 0;
}
/* Store pointer to HTTP packet */
http_pkt = (Ip_u8 *)tcp + tcp_hlen;
http_len = pkt->end - pkt->ipstart - (int)hlen - tcp_hlen;
/* Check that HTTP data is long enough to contain at least "GET / HTTP/1.0\r\n\r\n" */
if (http_len >= 18)
{
/* Match URL filter if at least one URL is inserted */
if (ret == 0 && fw_http->head_url.size > 0)
ret = ipfirewall_http_match_url(http_pkt, http_len, IPFIREWALL_CLASS_INDIVIDUAL, fw_http);
/* Match proxy filter if enabled */
if (ret == 0 && fw_http->proxy == IP_TRUE)
ret = ipfirewall_http_match_url(http_pkt, http_len, IPFIREWALL_CLASS_ABS_URI, IP_NULL);
/* Match java filter if enabled */
if (ret == 0 && fw_http->java == IP_TRUE)
ret = ipfirewall_http_match_object(http_pkt, http_len, IPFIREWALL_OBJ_FILTER_JAVA);
/* Match activex filter if enabled */
if (ret == 0 && fw_http->activex == IP_TRUE)
ret = ipfirewall_http_match_object(http_pkt, http_len, IPFIREWALL_OBJ_FILTER_ACTIVEX);
/* Remove cookies if cookie filter is enabled */
if (fw_http->cookie == IP_TRUE)
{
ipfirewall_http_match_cookie(http_pkt, http_len, tcp);
}
}
return ret;
}
/*
*===========================================================================
* ipfirewall_http_check
*===========================================================================
* Description: HTTP filter check function.
* cookie - a cookie set at registration.
* info - parameter string specified in the rule syntax
* infolen - length of user defined info buffer
* Returns: 1 = rule parameters accepted
* 0 = rule parameters not accepted
*/
IP_PUBLIC int
ipfirewall_http_check(void *cookie, void *info, unsigned int infolen)
{
Ipfirewall_http *fw_http;
(void)cookie;
/* Verify that there is a HTTP filter matching the rule parameter string */
fw_http = ipfirewall_http_find(info);
if (fw_http == IP_NULL)
{
IPCOM_LOG1(ERR, "ipfirewall_http_check() :: HTTP filter '%s' not found", info);
return 0;
}
/* Store pointer to filter for faster access in match function */
if (infolen < (int)sizeof(fw_http))
return 0;
ipcom_memcpy(info, &fw_http, sizeof(fw_http));
return 1;
}
/*
*===========================================================================
* ipfirewall_http_destroy
*===========================================================================
* Description: HTTP filter destroy function.
* cookie - a cookie set at registration.
* info - parameter string specified in the rule syntax
* infolen - length of user defined info buffer
*/
IP_PUBLIC void
ipfirewall_http_destroy(void *cookie, void *info, unsigned int infolen)
{
(void)cookie;
(void)info;
(void)infolen;
}
/*
*===========================================================================
* ipfirewall_http_insert_url_filter
*===========================================================================
* Description: Add a URL path or keyword to a HTTP filter.
* Parameters: id - filter identifier.
* url - keyword or URL path.
* keyword - IP_TRUE for keyword match or IP_FALSE for URL path.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_insert_url_filter(const char *id, const char *url, Ip_bool keyword)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ipfirewall_url *fw_url;
Ip_err ret = IPCOM_SUCCESS;
/* Find HTTP filter */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_url() :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http == IP_NULL)
{
IPCOM_LOG1(ERR, "ipfirewall_http_insert_url() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
goto out;
}
/* Allocate the URL structure */
fw_url = ipcom_malloc(sizeof(*fw_url));
if(fw_url == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_url() :: Could not allocate memory for URL match entry");
ret = IPCOM_ERR_NO_MEMORY;
goto out;
}
/* Populate the URL structure */
ipcom_memset(fw_url, 0, sizeof(*fw_url));
fw_url->url = ipcom_malloc(ipcom_strlen(url) + 1);
if (fw_url->url == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_url() :: Could not allocate memory for URL string");
ipcom_free(fw_url);
ret = IPCOM_ERR_NO_MEMORY;
goto out;
}
/* Skip leading "http://" */
if (ipfirewall_http_str_ci_cmp((char *)url, IPFIREWALL_TOKEN_HTTP, IPFIREWALL_TMNATOR_TYPE_SPECIFIC, ':', 0) == IP_TRUE)
if (IPFIREWALL_IS_STRING_SAME((url + ipcom_strlen(IPFIREWALL_TOKEN_HTTP)),"://"))
url += IPFIREWALL_HTTP_S2H_LEN;
ipcom_strcpy(fw_url->url, url);
if (keyword == IP_FALSE)
{
fw_url->len = (Ip_u16)ipfirewall_http_str_st_len(fw_url->url, '/', (int)ipcom_strlen(fw_url->url));
if (!fw_url->len)
fw_url->len = (Ip_u16)ipcom_strlen(fw_url->url);
fw_url->attr = IPFIREWALL_URL_SPECIFIC_PATH;
}
else
{
fw_url->len = (Ip_u16)ipcom_strlen(fw_url->url);
fw_url->attr = IPFIREWALL_URL_KEYWORD;
}
ipcom_list_insert_last(&fw_http->head_url, &fw_url->list_url);
out:
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_insert_proxy_filter
*===========================================================================
* Description: Enable proxy filter in a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_insert_proxy_filter(const char *id)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ip_err ret = IPCOM_SUCCESS;
/* Find HTTP filter */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_proxy_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
fw_http->proxy = IP_TRUE;
}
else
{
IPCOM_LOG1(ERR, "ipfirewall_http_insert_proxy_filter() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
}
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_insert_cookie_filter
*===========================================================================
* Description: Enable cookie filter in a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_insert_cookie_filter(const char *id)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ip_err ret = IPCOM_SUCCESS;
/* Find HTTP filter */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_cookie_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
fw_http->cookie = IP_TRUE;
}
else
{
IPCOM_LOG1(ERR, "ipfirewall_http_insert_cookie_filter() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
}
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_insert_java_filter
*===========================================================================
* Description: Enable java filter in a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_insert_java_filter(const char *id)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ip_err ret = IPCOM_SUCCESS;
/* Find HTTP filter */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_java_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
fw_http->java= IP_TRUE;
}
else
{
IPCOM_LOG1(ERR, "ipfirewall_http_insert_java_filter() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
}
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_insert_activex_filter
*===========================================================================
* Description: Enable active filter in a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_insert_activex_filter(const char *id)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ip_err ret = IPCOM_SUCCESS;
/* Find HTTP filter */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_insert_activex_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
fw_http->activex = IP_TRUE;
}
else
{
IPCOM_LOG1(ERR, "ipfirewall_http_insert_activex_filter() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
}
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_add_filter
*===========================================================================
* Description: Add a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_add_filter(const char *id)
{
void *suspend_handle;
Ipfirewall_http *fw_http;
Ip_err ret = IPCOM_SUCCESS;
/* Check for duplicate */
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_add_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
IPCOM_LOG1(ERR, "ipfirewall_http_add_filter() :: HTTP filter '%s' already exists", id);
ret = IPCOM_ERR_DUPLICATE;
goto out;
}
if(ipcom_strlen(id) >= sizeof(fw_http->identifier))
{
ret = IPCOM_ERR_FAILED;
goto out;
}
/* Allocate the HTTP filter structure */
fw_http = ipcom_malloc(sizeof(*fw_http));
if(fw_http == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_add_filter() :: Could not allocate memory for HTTP filter entry");
ret = IPCOM_ERR_NO_MEMORY;
goto out;
}
/* Populate the HTTP filter structure */
ipcom_memset(fw_http, 0, sizeof(*fw_http));
ipcom_strcpy(fw_http->identifier, id);
ipcom_list_init(&fw_http->head_url);
/* Insert the HTTP filter structure in list */
ipcom_list_insert_last(&head_http, &fw_http->list_http);
out:
ipnet_resume_stack(suspend_handle);
return ret;
}
/*
*===========================================================================
* ipfirewall_http_remove_filter
*===========================================================================
* Description: Remove a HTTP filter.
* Parameters: id - filter identifier.
* Returns: IPCOM_SUCCESS or error code.
*/
IP_PUBLIC Ip_err
ipfirewall_http_remove_filter(const char *id)
{
void *suspend_handle;
#ifdef IPFIREWALL_USE_IP_STATEFUL
Ipfirewall_state *fw_state;
#endif
Ipfirewall_rule *fw_rule;
Ipfirewall_http *fw_http;
Ipfirewall_url *fw_url;
Ip_err ret = IPCOM_SUCCESS;
suspend_handle = ipnet_suspend_stack();
if (suspend_handle == IP_NULL)
{
IPCOM_LOG0(ERR, "ipfirewall_http_remove_filter :: Could not suspend stack");
return IPCOM_ERR_FAILED;
}
/* Verify that there are no rules that refer this HTTP filter */
#ifdef IPFIREWALL_USE_MAC_FILTER
if (ret == IPCOM_SUCCESS)
{
for (fw_rule = IPCOM_LIST_FIRST(&ipfirewall->mac_head_rule_input);
fw_rule != IP_NULL;
fw_rule = IPCOM_LIST_NEXT(&fw_rule->list_rule))
{
if (fw_rule->inner.userdef == 1
&& ipcom_strcmp((char *)fw_rule->inner.userdef_id, IPFIREWALL_HTTP_FILTER_ID) == 0
&& ipcom_strcmp(fw_rule->inner.userdef_param, id) == 0)
{
IPCOM_LOG3(ERR, "ipfirewall_unregister_userdef() :: "
"Cannot remove HTTP filter '%s' since MAC filter rule @%d:%d "
"refers to it.",
fw_rule->inner.userdef_param, fw_rule->inner.group_no, fw_rule->inner.rule_no);
ret = IPCOM_ERR_FAILED;
break;
}
}
}
if (ret == IPCOM_SUCCESS)
{
for (fw_rule = IPCOM_LIST_FIRST(&ipfirewall->mac_head_rule_output);
fw_rule != IP_NULL;
fw_rule = IPCOM_LIST_NEXT(&fw_rule->list_rule))
{
if (fw_rule->inner.userdef == 1
&& ipcom_strcmp((char *)fw_rule->inner.userdef_id, IPFIREWALL_HTTP_FILTER_ID) == 0
&& ipcom_strcmp(fw_rule->inner.userdef_param, id) == 0)
{
IPCOM_LOG3(ERR, "ipfirewall_unregister_userdef() :: "
"Cannot remove HTTP filter '%s' since MAC filter rule @%d:%d "
"refers to it.",
fw_rule->inner.userdef_param, fw_rule->inner.group_no, fw_rule->inner.rule_no);
ret = IPCOM_ERR_FAILED;
break;
}
}
}
#endif /* #ifdef IPFIREWALL_USE_MAC_FILTER */
#ifdef IPFIREWALL_USE_IP_FILTER
if (ret == IPCOM_SUCCESS)
{
for (fw_rule = IPCOM_LIST_FIRST(&ipfirewall->head_rule_input);
fw_rule != IP_NULL;
fw_rule = IPCOM_LIST_NEXT(&fw_rule->list_rule))
{
if (fw_rule->inner.userdef == 1
&& ipcom_strcmp((char *)fw_rule->inner.userdef_id, IPFIREWALL_HTTP_FILTER_ID) == 0
&& ipcom_strcmp(fw_rule->inner.userdef_param, id) == 0)
{
IPCOM_LOG3(ERR, "ipfirewall_unregister_userdef() :: "
"Cannot remove HTTP filter '%s' since IP filter rule @%d:%d "
"refers to it.",
fw_rule->inner.userdef_param, fw_rule->inner.group_no, fw_rule->inner.rule_no);
ret = IPCOM_ERR_FAILED;
break;
}
}
}
if (ret == IPCOM_SUCCESS)
{
for (fw_rule = IPCOM_LIST_FIRST(&ipfirewall->head_rule_output);
fw_rule != IP_NULL;
fw_rule = IPCOM_LIST_NEXT(&fw_rule->list_rule))
{
if (fw_rule->inner.userdef == 1
&& ipcom_strcmp((char *)fw_rule->inner.userdef_id, IPFIREWALL_HTTP_FILTER_ID) == 0
&& ipcom_strcmp(fw_rule->inner.userdef_param, id) == 0)
{
IPCOM_LOG3(ERR, "ipfirewall_unregister_userdef() :: "
"Cannot remove HTTP filter '%s' since IP filter rule @%d:%d "
"refers to it.",
fw_rule->inner.userdef_param, fw_rule->inner.group_no, fw_rule->inner.rule_no);
ret = IPCOM_ERR_FAILED;
break;
}
}
}
#endif /* #ifdef IPFIREWALL_USE_IP_FILTER */
#ifdef IPFIREWALL_USE_IP_STATEFUL
if (ret == IPCOM_SUCCESS)
{
for (fw_state = IPCOM_LIST_FIRST(&ipfirewall->head_state);
fw_state != IP_NULL;
fw_state = IPCOM_LIST_NEXT(&ipfirewall->head_state))
{
fw_rule=(Ipfirewall_rule *)fw_state->fw_rule;
if ((fw_rule!=IP_NULL)&&(fw_rule->inner.userdef==1)
&&(ipcom_strcmp((char *)fw_rule->inner.userdef_id,IPFIREWALL_HTTP_FILTER_ID)==0)
&&(ipcom_strcmp(fw_rule->inner.userdef_param, id)==0))
{
ipfirewall_clean_state(fw_state);
}
}
}
#endif /* IPFIREWALL_USE_IP_STATEFUL */
/* Find HTTP filter */
if (ret == IPCOM_SUCCESS)
{
fw_http = ipfirewall_http_find(id);
if (fw_http != IP_NULL)
{
/* Clear URL list */
while((fw_url = IPCOM_LIST_LAST(&fw_http->head_url)) != IP_NULL)
{
ipcom_list_remove(&fw_url->list_url);
if (fw_url->url != IP_NULL)
ipcom_free(fw_url->url); /* Clear URL string */
ipcom_free(fw_url);
}
/* Remove from HTTP filter list */
ipcom_list_remove(&fw_http->list_http);
ipcom_free(fw_http);
}
else
{
IPCOM_LOG1(ERR, "ipfirewall_http_add() :: HTTP filter '%s' not found", id);
ret = IPCOM_ERR_NOT_FOUND;
}
}
ipnet_resume_stack(suspend_handle);
return ret;
}
#else
int ipfirewall_userdef_http_empty_file;
#endif /* #ifdef IPFIREWALL_USE_HTTP_FILTER */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/