📄 sf_ipvar.c
字号:
free(tok); return SFIP_SUCCESS; } free(tok); return SFIP_UNMATCHED_BRACKET; } else { sfip_node_t *node; /* Skip leading commas */ for(; *str == ','; str++) ; /* Check for a negated "any" */ if(negation ^ neg_ip && !strcasecmp(tok, "any")) { free(tok); return SFIP_NOT_ANY; } /* This should be an IP address! */ /* Allocate new node for this string and add it to "ret" */ if((node = sfipnode_alloc(tok, &ret)) == NULL) { free(tok); return ret; } if(negation ^ neg_ip) { _negate_node(node); } /* Check if this is a negated, zero'ed IP (equivalent of a "!any") */ if(!sfip_is_set(node->ip) && (node->flags & SFIP_NEGATED)) { free(tok); return SFIP_NOT_ANY; } ret = sfvar_add_node(var, node, negation ^ neg_ip); if(ret != SFIP_SUCCESS ) { free(tok); return ret; } } free(tok); if(*end) str = end + 1; else break; } return SFIP_SUCCESS;}SFIP_RET sfvar_validate(sfip_var_t *var) { sfip_node_t *idx, *neg_idx; if(!var->head || !var->neg_head) return SFIP_SUCCESS; for(idx = var->head; idx; idx = idx->next) { for(neg_idx = var->neg_head; neg_idx; neg_idx = neg_idx->next) { /* A smaller netmask means "less specific" */ if(sfip_bits(neg_idx->ip) <= sfip_bits(idx->ip) && /* Verify they overlap */ (sfip_contains(neg_idx->ip, idx->ip) == SFIP_CONTAINS)) { return SFIP_CONFLICT; } } } return SFIP_SUCCESS;}/* Allocates and returns a new variable, described by "variable". */sfip_var_t *sfvar_alloc(vartable_t *table, char *variable, SFIP_RET *status) { sfip_var_t *ret; char *str, *end; if(!variable || !(*variable)) { if(status) *status = SFIP_ARG_ERR; return NULL; } if( (ret = _alloc_var()) == NULL ) { if(status) *status = SFIP_ALLOC_ERR; return NULL; } /* Extract and save the variable's name */ /* Start by skipping leading whitespace or line continuations: '\' */ for(str = variable ; *str && (isspace((int)*str) || *str == '\\'); str++) ; /* Find the end of the name */ for(end = str; *end && !isspace((int)*end) && *end != '\\'; end++) ; if(!isalpha((int)*str) && *str != '$' && *str != '!') { if(status) *status = SFIP_ARG_ERR; return NULL; } /* Set the new variable's name/key */ if((ret->name = strndup(str, end - str)) == NULL) { if(status) *status = SFIP_ALLOC_ERR; return NULL; } /* End points to the end of the name. Skip past it */ str = end; /* Everything is treated as a list, even if it's one element that's not * surrounded by brackets */ if((*status = sfvar_parse_iplist(table, ret, str, 0)) != SFIP_SUCCESS) { return NULL; } if(ret->head && (ret->head->flags & SFIP_ANY && ret->head->flags & SFIP_NEGATED)) { if(status) *status = SFIP_NOT_ANY; sfvar_free(ret); return NULL; } if(sfvar_validate(ret) == SFIP_CONFLICT) { if(status) *status = SFIP_CONFLICT; sfvar_free(ret); return NULL; } return ret;}static INLINE sfip_node_t *_sfvar_deep_copy_list(sfip_node_t *idx) { sfip_node_t *ret, *temp, *prev; ret = temp = NULL; for( ; idx; idx = idx->next) { prev = temp; if( (temp = (sfip_node_t*)calloc(1, sizeof(sfip_node_t))) == NULL ) { // XXX WALK LIST AND DELETE NODES FIRST return NULL; } if( (temp->ip = (sfip_t*)calloc(1, sizeof(sfip_t))) == NULL ) { // XXX WALK LIST AND DELETE NODES FIRST return NULL; } temp->flags = idx->flags; temp->addr_flags = idx->addr_flags; /* If it's an "any", there may be no IP object */ if(idx->ip) memcpy(temp->ip, idx->ip, sizeof(sfip_t)); if(prev) prev->next = temp; else { ret = temp; } } return ret;}sfip_var_t *sfvar_deep_copy(sfip_var_t *var) { sfip_var_t *ret; if(!var) return NULL; ret = (sfip_var_t*)SnortAlloc(sizeof(sfip_var_t)); ret->mode = var->mode; ret->head = _sfvar_deep_copy_list(var->head); ret->neg_head = _sfvar_deep_copy_list(var->neg_head); return ret;}/* Support function for sfvar_ip_in */static INLINE int _sfvar_ip_in4(sfip_var_t *var, sfip_t *ip) { int match; sfip_node_t *pos_idx, *neg_idx; match = 0; pos_idx = var->head; neg_idx = var->neg_head; if(!pos_idx) { for( ; neg_idx; neg_idx = neg_idx->next) { if(sfip_family(neg_idx->ip) != AF_INET) continue; if(sfip_fast_cont4(neg_idx->ip, ip)) { return 0; } } return 1; } while(pos_idx) { if(neg_idx) { if(sfip_family(neg_idx->ip) == AF_INET && sfip_fast_cont4(neg_idx->ip, ip)) { return 0; } neg_idx = neg_idx->next; } /* No more potential negations. Check if we've already matched. */ else if(match) { return 1; } if(!match) { if(sfip_is_set(pos_idx->ip)) { if(sfip_family(pos_idx->ip) == AF_INET && sfip_fast_cont4(pos_idx->ip, ip)) { match = 1; } else { pos_idx = pos_idx->next; } } else { match = 1; } } } return 0;}/* Support function for sfvar_ip_in */static INLINE int _sfvar_ip_in6(sfip_var_t *var, sfip_t *ip) { int match; sfip_node_t *pos_idx, *neg_idx; match = 0; pos_idx = var->head; neg_idx = var->neg_head; if(!pos_idx) { for( ; neg_idx; neg_idx = neg_idx->next) { if(sfip_family(neg_idx->ip) != AF_INET6) continue; if(sfip_fast_cont6(neg_idx->ip, ip)) { return 0; } } return 1; } while(pos_idx) { if(neg_idx) { if(sfip_family(neg_idx->ip) == AF_INET6 && sfip_fast_cont6(neg_idx->ip, ip)) { return 0; } neg_idx = neg_idx->next; } /* No more potential negations. Check if we've already matched. */ else if(match) { return 1; } if(!match) { if(sfip_is_set(pos_idx->ip)) { if(sfip_family(pos_idx->ip) == AF_INET6 && sfip_fast_cont6(pos_idx->ip, ip)) { match = 1; } else { pos_idx = pos_idx->next; } } else { match = 1; } } } return 0;}/* Returns SFIP_SUCCESS if ip is contained in 'var', SFIP_FAILURE otherwise *//* If either argument is NULL, SFIP_ARG_ERR is returned. */int sfvar_ip_in(sfip_var_t *var, sfip_t *ip) { if(!var || !ip) return 0;#if 0 if(var->mode == SFIP_TABLE) { // XXX } else {#endif /* Since this is a performance-critical function it uses different * codepaths for IPv6 and IPv4 traffic, rather than the dual-stack * functions. */ if(sfip_family(ip) == AF_INET) { return _sfvar_ip_in4(var, ip); } else { return _sfvar_ip_in6(var, ip); }#if 0 }#endif}/* Prints the variable "var" to the file descriptor 'f' */void sfvar_print(FILE *f, sfip_var_t *var) { if(!f) return; if(!var || !var->head) { fprintf(f, "[no variable]\n"); return; } fprintf(f, "Name: %s\n", var->name); if(var->mode == SFIP_LIST) { if(var->head->flags & SFIP_ANY) fprintf(f, "\t%p: <any>\n", var->head); else { sfip_set_print(f, var->head); } } else if(var->mode == SFIP_TABLE) { // XXX }}void sfip_set_print(FILE *f, sfip_node_t *p) { for(; p; p = p->next) { if(!p->ip) continue; if(p->flags & SFIP_NEGATED) fprintf(f, "\t!%s\n", sfip_to_str(p->ip)); else fprintf(f, "\t %s\n", sfip_to_str(p->ip)); }}int sfvar_flags(sfip_node_t *node) { if(node) return node->flags; return -1;}/* XXX The unit tests for this code are performed within sf_vartable.c */#if 0int main() { sfip_vtable *table; sfip_var_t *var; sfip_t *ip; /* Test parsing */ /* Allowable arguments: * { <ip>[, <ip>, ... , <ip> } * Where an IP can be in CIDR notation, or be specified with a netmask. * IPs may also be negated with '!' */ puts("********************************************************************"); puts("Testing parsing:"); var = sfvar_str(" { 1.2.3.4/8, 5.5.5.5 255.255.255.0, any} "); sfip_print_var(stdout, var); sfvar_free(var); puts(""); var = sfvar_str(" { 1.2.3.4, ffff::3/127, 0.0.0.1} "); sfip_print_var(stdout, var); ip = sfip_alloc("1.2.3.5"); printf("(need more of these) 'in': %d\n", sfip_in(var, ip)); puts("also, use 'sfip_in' for the unit tests"); puts(""); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -