?? sf_ipvar.c
字號:
/*** Copyright (C) 1998-2006 Sourcefire, Inc.**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License Version 2 as** published by the Free Software Foundation. You may not use, modify or** distribute this program under any other version of the GNU General** Public License.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * Adam Keeton * sf_ipvar.c * 11/17/06 * * Library for IP variables.*/#include <stdlib.h>#include <string.h>#include <ctype.h>#include <stdio.h>#include "util.h"#include "sf_ipvar.h"#include "sf_vartable.h"#define LIST_OPEN '['#define LIST_CLOSE ']'static INLINE sfip_var_t *_alloc_var() { return (sfip_var_t*)calloc(1, sizeof(sfip_var_t));}void sfvar_free(sfip_var_t *var) { sfip_node_t *p, *next; if(!var) return; if(var->name) free(var->name); if(var->mode == SFIP_LIST) { for(p=var->head; p; p=next) { next = p->next; if(p->ip) sfip_free(p->ip); free(p); } } else if(var->mode == SFIP_TABLE) { // XXX } free(var);}sfip_node_t *sfipnode_alloc(char *str, SFIP_RET *status) { sfip_node_t *ret; if(!str) { if(status) *status = SFIP_ARG_ERR; return NULL; } if( (ret = (sfip_node_t*)calloc(1, sizeof(sfip_node_t))) == NULL ) { if(status) *status = SFIP_ALLOC_ERR; return NULL; } /* Check if this string starts with a '!', if so, * then the node needs to be negated */ if(*str == '!') { str++; ret->flags |= SFIP_NEGATED; } /* Check if this is an "any" */ if(!strncasecmp(str, "any", 3)) { /* Make sure they're not doing !any, which is meaningless */ if(ret->flags & SFIP_NEGATED) { if(status) *status = SFIP_ARG_ERR; free(ret); return NULL; } ret->flags |= SFIP_ANY; if( (ret->ip = sfip_alloc("0.0.0.0", status)) == NULL ) { /* Failed to parse this string, so free and return */ if(status) *status = SFIP_ALLOC_ERR; free(ret); return NULL; } if(status) *status = SFIP_SUCCESS; if( !(ret->ip = sfip_alloc("0.0.0.0", NULL)) ) { if(status) *status = SFIP_FAILURE; free(ret); return NULL; } } else if( (ret->ip = sfip_alloc(str, status)) == NULL ) { /* Failed to parse this string, so free and return */ if(status) *status = SFIP_INET_PARSE_ERR; free(ret); return NULL; } /* Check if this is a negated, zero'ed IP (equivalent of a "!any") */ if(!sfip_is_set(ret->ip) && (ret->flags & SFIP_NEGATED)) { if(status) *status = SFIP_NOT_ANY; free(ret); return NULL; } return ret;}/* Deep copy of src added to dst *//* Ordering is not necessarily preserved */SFIP_RET sfvar_add(sfip_var_t *dst, sfip_var_t *src) { sfip_node_t *oldhead, *oldneg, *idx; sfip_var_t *copiedvar; if(!dst || !src) return SFIP_ARG_ERR; oldhead = dst->head; oldneg = dst->neg_head; if((copiedvar = sfvar_deep_copy(src)) == NULL) { return SFIP_ALLOC_ERR; } dst->head = copiedvar->head; dst->neg_head = copiedvar->neg_head; free(copiedvar); if(dst->head) { for(idx = dst->head; idx->next; idx = idx->next) ; idx->next = oldhead; } else { dst->head = oldhead; } if(dst->neg_head) { for(idx = dst->neg_head; idx->next; idx = idx->next) ; idx->next = oldneg; } else { dst->neg_head = oldneg; } return SFIP_SUCCESS;}SFIP_RET sfvar_add_node(sfip_var_t *var, sfip_node_t *node, int negated) { sfip_node_t *p; sfip_node_t *swp; sfip_node_t **head; if(!var || !node) return SFIP_ARG_ERR; /* XXX */ /* As of this writing, 11/20/06, nodes are always added to * the list, regardless of the mode (list or table). */ if(negated) head = &var->neg_head; else head = &var->head; if(!(*head)) { *head = node; return SFIP_SUCCESS; } /* "Anys" should always be inserted first */ /* Otherwise, check if this IP is less than the head's IP */ if((node->flags & SFIP_ANY) || (sfip_cmp(node->ip, (*head)->ip) == SFIP_LESSER)) { node->next = *head; *head = node; return SFIP_SUCCESS; } /* If we're here, the head node was lesser than the new node */ /* Before searching the list, verify there is atleast two nodes. * (This saves an extra check during the loop below) */ if(!(*head)->next) { (*head)->next = node; return SFIP_SUCCESS; } /* Insertion sort */ for(p = *head; p->next; p=p->next) { if(sfip_cmp(node->ip, p->next->ip) == SFIP_LESSER) { swp = p->next; p->next = node; node->next = swp; return SFIP_SUCCESS; } } p->next = node; return SFIP_SUCCESS; /* XXX Insert new node into routing table */// sfrt_add(node->ip, }/* Check's if two variables have the same nodes */SFIP_RET sfvar_compare(sfip_var_t *one, sfip_var_t *two) { sfip_node_t *idx1, *idx2; int i, match; int total1 = 0; int total2 = 0; char *usage; /* Walk first list. For each node, check if there is an equal * counterpart in the second list. This method breaks down of there are * duplicated nodes. For instance, if one = {a, b} and two = {a, a}. * Therefore, need additional data structure[s] ('usage') to check off * which nodes have been accounted for already. * * Also, the lists are not necessarily ordered, so comparing * node-for-node won't work */ if(!one && !two) return 1; if((one && !two) || (!one && two)) return 0; for(idx1 = one->head; idx1; idx1 = idx1->next) total1++; for(idx2 = two->head; idx2; idx2 = idx2->next) total2++; if(total1 != total2) return 0; usage = (char*)SnortAlloc(total1); for(idx1 = one->head; idx1; idx1 = idx1->next) { match = 0; for(idx2 = two->head, i = 0; idx2; idx2 = idx2->next, i++) { if((sfip_cmp(idx1->ip, idx2->ip) == SFIP_EQUAL) && !usage[i]) { match = 1; usage[i] = 1; break; } } if(!match) { free(usage); return 0; } } free(usage); return 1; return SFIP_SUCCESS;}/* Support function for sfvar_parse_iplist. Used to * correctly match up end brackets. * (Can't just do strchr(str, ']') because of the * [a, [b], c] case, and can't do strrchr because * of the [a, [b], [c]] case) */char *_find_end_token(char *str) { int stack = 0; for(; *str; str++) { if(*str == LIST_OPEN) stack++; else if(*str == LIST_CLOSE) stack--; if(!stack) { return str; } } return NULL;}/* Support function for sfvar_parse_iplist. * Negates a node */static void _negate_node(sfip_node_t *node) { if(node->addr_flags & SFIP_NEGATED) { node->addr_flags &= ~SFIP_NEGATED; node->flags &= ~SFIP_NEGATED; } else { node->addr_flags |= SFIP_NEGATED; node->flags |= SFIP_NEGATED; }}/* Support function for sfvar_parse_iplist. * Negates a variable */static void _negate_lists(sfip_var_t *var) { sfip_node_t *node; sfip_node_t *temp; for(node = var->head; node; node=node->next) _negate_node(node); for(node = var->neg_head; node; node=node->next) _negate_node(node); /* Swap lists */ temp = var->head; var->head = var->neg_head; var->neg_head = temp;}SFIP_RET sfvar_parse_iplist(vartable_t *table, sfip_var_t *var, char *str, int negation) { char *end, *tok; SFIP_RET ret; int neg_ip; if(!var || !table || !str) return SFIP_ARG_ERR; while(*str) { /* Skip whitespace and leading commas */ if(isspace((int)*str) || *str == ',') { str++; continue; } neg_ip = 0; /* Handle multiple negations */ for(; *str == '!'; str++) neg_ip = !neg_ip; /* Find end of this token */ for(end = str+1; *end && !isspace((int)*end) && *end != LIST_CLOSE && *end != ','; end++) ; tok = SnortStrndup(str, end - str); if(*str == LIST_OPEN) { char *list_tok; /* Find end of this list */ if((end = _find_end_token(str)) == NULL) { /* No trailing bracket found */ return SFIP_UNMATCHED_BRACKET; } str++; list_tok = SnortStrndup(str, end - str); if((ret = sfvar_parse_iplist(table, var, list_tok, negation ^ neg_ip)) != SFIP_SUCCESS) { free(list_tok); free(tok); return ret; } free(list_tok); } else if(*str == '$') { sfip_var_t *tmp_var; if((tmp_var = sfvt_lookup_var(table, tok)) == NULL) { free(tok); return SFIP_LOOKUP_FAILURE; } sfvar_add(var, tmp_var); /* Apply the negation */ if(negation ^ neg_ip) { /* Check for a negated "any" */ if(var->head && var->head->flags & SFIP_ANY) { free(tok); return SFIP_NOT_ANY; } /* Check if this is a negated, zero'ed IP (equivalent of a "!any") */ if(!sfip_is_set(var->head->ip)) { free(tok); return SFIP_NOT_ANY; } _negate_lists(var); } } else if(*str == LIST_CLOSE) { /* This should be the last character, if not, then this is an * invalid extra closing bracket */ if(!(*(str+1))) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -