?? sf_ip.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_ip.c * 11/17/06 * * Library for managing IP addresses of either v6 or v4 families. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <math.h> /* For ceil */#include "sf_ip.h"#ifdef TESTER#define FatalError printf#endif/* Support function .. but could see some external uses */static INLINE int sfip_length(sfip_t *ip) { ARG_CHECK1(ip, 0); if(sfip_family(ip) == AF_INET) return 4; return 16;}/* Support function */static INLINE int sfip_str_to_fam(char *str) { ARG_CHECK1(str, 0); if(strchr(str,(int)':')) return AF_INET6; if(strchr(str,(int)'.')) return AF_INET; return AF_UNSPEC;}/* Place-holder allocation incase we want to do something more indepth later */static INLINE sfip_t *_sfip_alloc() { /* Note: using calloc here instead of SnortAlloc since the dynamic libs * can't presently resolve SnortAlloc */ return (sfip_t*)calloc(sizeof(sfip_t), 1); }/* Masks off 'val' bits from the IP contained within 'ip' */static INLINE int sfip_cidr_mask(sfip_t *ip, int val) { int i; unsigned int mask = 0; unsigned int *p; int index = (int)ceil(val / 32.0) - 1; ARG_CHECK1(ip, SFIP_ARG_ERR); p = ip->ip32; if( val < 0 || ((sfip_family(ip) == AF_INET6) && val > 128) || ((sfip_family(ip) == AF_INET) && val > 32) ) { return SFIP_ARG_ERR; } /* Build the netmask by converting "val" into * the corresponding number of bits that are set */ for(i = 0; i < 32- (val - (index * 32)); i++) mask = (mask<<1) + 1; p[index] = htonl((ntohl(p[index]) & ~mask)); index++; /* 0 off the rest of the IP */ for( ; index<4; index++) p[index] = 0; return SFIP_SUCCESS;}/* Allocate IP address from a character array describing the IP */sfip_t *sfip_alloc(char *ip, SFIP_RET *status) { int tmp; sfip_t *ret; if(!ip) { if(status) *status = SFIP_ARG_ERR; return NULL; } if((ret = _sfip_alloc()) == NULL) { if(status) *status = SFIP_ALLOC_ERR; return NULL; } if( (tmp = sfip_pton(ip, ret)) != SFIP_SUCCESS) { if(status) *status = tmp; sfip_free(ret); return NULL; } if(status) *status = SFIP_SUCCESS; return ret;}/* Allocate IP address from an array of 8 byte integers */sfip_t *sfip_alloc_raw(void *ip, int family, SFIP_RET *status) { sfip_t *ret; if(!ip) { if(status) *status = SFIP_ARG_ERR; return NULL; } if((ret = _sfip_alloc()) == NULL) { if(status) *status = SFIP_ALLOC_ERR; return NULL; } ret->bits = (family==AF_INET?32:128); ret->family = family; /* XXX Replace with appropriate "high speed" copy */ memcpy(ret->ip8, ip, ret->bits/8); if(status) *status = SFIP_SUCCESS; return ret;}/* Support function for _netmask_str_to_bit_count */static INLINE int _count_bits(unsigned int val) { unsigned int count; for (count = 0; val; count++) { val &= val - 1; } return count;}/* Support function for sfip_pton. Used for converting a netmask string * into a number of bits to mask off */static INLINE int _netmask_str_to_bit_count(char *mask, int family) { u_int32_t buf[4]; int bits; /* XXX * Mask not validated. * Only sfip_pton should be using this function, and using it safely. * XXX */ if(inet_pton(family, mask, buf) < 1) return -1; if(family == AF_INET) return _count_bits(buf[0]); bits = _count_bits(buf[0]); bits += _count_bits(buf[1]); bits += _count_bits(buf[2]); bits += _count_bits(buf[3]); return bits;}/* Parses "src" and stores results in "dst" */SFIP_RET sfip_pton(char *src, sfip_t *dst) { char *mask; char *sfip_buf; char *ip; int bits; if(!dst || !src) return SFIP_ARG_ERR; if((sfip_buf = strdup(src)) == NULL) return SFIP_ALLOC_ERR; ip = sfip_buf; dst->family = sfip_str_to_fam(src); /* skip whitespace or opening bracket */ while(isspace((int)*ip) || *ip == '[') ip++; /* check for and extract a mask in CIDR form */ if( (mask = strchr(ip, (int)'/')) != NULL ) { /* NULL out this character so inet_pton will see the * correct ending to the IP string */ *mask = 0; mask++; /* verify a leading digit */ if(((dst->family == AF_INET6) && !isxdigit((int)*mask)) || ((dst->family == AF_INET) && !isdigit((int)*mask))) { free(sfip_buf); return SFIP_CIDR_ERR; } /* Check if there's a netmask here instead of the number of bits */ if(strchr(mask, (int)'.') || strchr(mask, (int)':')) bits = _netmask_str_to_bit_count(mask, sfip_str_to_fam(mask)); else bits = atoi(mask); } /* We've already skipped the leading whitespace, if there is more * whitespace, then there's probably a netmask specified after it. */ else if( (mask = strchr(ip, (int)' ')) != NULL || /* If this is IPv4, ia ':' may used specified to indicate a netmask */ (dst->family == AF_INET && (mask = strchr(ip, (int)':')) != NULL) ) { *mask = 0; /* Now the IP will end at this point */ /* skip whitespace */ do { mask++; } while(isspace((int)*mask)); /* Make sure we're either looking at a valid digit, or a leading * colon, such as can be the case with IPv6 */ if((dst->family == AF_INET && isdigit((int)*mask)) || (dst->family == AF_INET6 && (isxdigit((int)*mask) || *mask == ':'))) { bits = _netmask_str_to_bit_count(mask, sfip_str_to_fam(mask)); } /* No netmask */ else { if(dst->family == AF_INET) bits = 32; else bits = 128; } } /* No netmask */ else { if(dst->family == AF_INET) bits = 32; else bits = 128; } if(inet_pton(dst->family, ip, dst->ip8) < 1) { free(sfip_buf); return SFIP_INET_PARSE_ERR; } /* Store mask */ dst->bits = bits; /* Apply mask */ if(sfip_cidr_mask(dst, bits) != SFIP_SUCCESS) { free(sfip_buf); return SFIP_INVALID_MASK; } free(sfip_buf); return SFIP_SUCCESS;}/* Sets existing IP, "dst", to be source IP, "src" */SFIP_RET sfip_set_raw(sfip_t *dst, void *src, int family) { ARG_CHECK3(dst, src, dst->ip32, SFIP_ARG_ERR); dst->family = family; if(family == AF_INET) { dst->ip32[0] = *(u_int32_t*)src; memset(&dst->ip32[1], 0, 12); dst->bits = 32; } else if(family == AF_INET6) { memcpy(dst->ip8, src, 16); dst->bits = 128; } else { return SFIP_ARG_ERR; } return SFIP_SUCCESS;}/* Sets existing IP, "dst", to be source IP, "src" */SFIP_RET sfip_set_ip(sfip_t *dst, sfip_t *src) { ARG_CHECK2(dst, src, SFIP_ARG_ERR); dst->family = src->family; dst->bits = src->bits; dst->ip32[0] = src->ip32[0]; dst->ip32[1] = src->ip32[1]; dst->ip32[2] = src->ip32[2]; dst->ip32[3] = src->ip32[3]; return SFIP_SUCCESS;}/* Obfuscates an IP * Makes 'ip': ob | (ip & mask) */void sfip_obfuscate(sfip_t *ob, sfip_t *ip) { unsigned int *ob_p, *ip_p; int index, i; unsigned int mask = 0; if(!ob || !ip) return; ob_p = ob->ip32; ip_p = ip->ip32; /* Build the netmask by converting "val" into * the corresponding number of bits that are set */ index = (int)ceil(ob->bits / 32.0) - 1; for(i = 0; i < 32- (ob->bits - (index * 32)); i++) mask = (mask<<1) + 1; /* Note: The old-Snort obfuscation code uses !mask for masking. * hence, this code uses the same algorithm as sfip_cidr_mask * except the mask below is not negated. */ ip_p[index] = htonl((ntohl(ip_p[index]) & mask)); index++; /* 0 off the rest of the IP */ for( ; index<4; index++) ip_p[index] = 0; /* OR remaining pieces */ ip_p[0] |= ob_p[0];
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -