X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drl%2Futil.c;fp=drl%2Futil.c;h=9f5706af52af41b5a90446d0e492795d1f3d9288;hb=0be9704d6b24d09ebd55beedec52758cb88c570b;hp=0000000000000000000000000000000000000000;hpb=6747e89080a8265aa73320bd9f40a0fa6e1c161e;p=distributedratelimiting.git diff --git a/drl/util.c b/drl/util.c new file mode 100644 index 0000000..9f5706a --- /dev/null +++ b/drl/util.c @@ -0,0 +1,360 @@ +/* See the DRL-LICENSE file for this file's software license. */ + +/* util.c + * + * Mainly a hash table implementation, but other sundry items for + * ulogd_DRL as well. + * Ken Yocum 2007/08 + */ + +#include "raterouter.h" +#include "util.h" +#include "ratetypes.h" +#include "logging.h" + +static int util_salt = 0; + +/* stupidity BE:MSB first, LE: MSB last*/ +static int am_big_endian(void){ + long one = 1; + return !(*((char*)(&one))); /* looking for 1 in the big end */ +} + +static int compare_key(void *one, void *two, int len){ + int i; + for (i=0;iiterator = map->table[0]; + map->size = 0; + return(map); +} + +/* de-allocates the map, if true, de-allocates crud in map as well */ +void free_map(map_handle map, int dealloc){ + int i; + struct map_entry *nxt_me,*tmp; + for (i=0;itable[i]); + while(nxt_me) { + if (dealloc && (nxt_me->value != NULL)){ + free(nxt_me->value); + nxt_me->value=NULL; + } + tmp = nxt_me->nxt; + free(nxt_me); + map->size--; + nxt_me= tmp; + } + } + free(map); +} + +/* internal_search + * + * prior_me points to a pointer for the space holding the next map + * entry + * If you find the first entry of the linked list, it points to the + * memory in the table holding the pointer to the first map entry. + * Otherwise it points to the memory in the previous map_entry that + * holds the next pointer. + * A triple pointer here, b/c we need to save the value. + */ +static struct map_entry* internal_search(map_handle map, void *key, int keylen, struct map_entry*** prior_me){ + uint32_t index; + struct map_entry *nxt_me; + + index = jhash(key,keylen,util_salt) & (GENERIC_HASH_SIZE - 1); + +#if 0 + printf("IS: KEY:"); + for(i=0;itable[index]; + *prior_me = (struct map_entry**) &(map->table[index]); + + while(nxt_me){ + if (compare_key(nxt_me->key,key,keylen)){ + return(nxt_me); + } + *prior_me = &(nxt_me->nxt); + nxt_me = nxt_me->nxt; + } + return(NULL); + +} + +void* map_next(map_handle map){ + void *val; + + if (map->iterator_row == GENERIC_HASH_SIZE){ + return(NULL); /* empty, call reset */ + } + /* iterator points to current one to return */ + if (map->iterator != NULL){ + val = map->iterator->value; + map->iterator = map->iterator->nxt; + return(val); + } + /* if null, go to next row */ + while (map->iterator == NULL){ + map->iterator_row++; + if (map->iterator_row < GENERIC_HASH_SIZE) { + map->iterator = map->table[map->iterator_row]; + } else { + return(NULL); + } + } + val = map->iterator->value; + map->iterator = map->iterator->nxt; + return(val); +} + +void map_reset_iterate(map_handle map){ + map->iterator = map->table[0]; + map->iterator_row = 0; +} + +int map_size(map_handle map){ + return(map->size); +} + +void** map_to_array(map_handle map, int *length){ + void** array = (void**)malloc(sizeof(void*)*(map->size + 1)); + int i; + + *length = map->size; + map_reset_iterate(map); + for(i=0;isize;i++){ + array[i] = map_next(map); + } + array[i] = NULL; /* just in case */ + return(array); +} + +void* map_search(map_handle map,void *key, int keylen){ + struct map_entry *me,**pme; + me = internal_search(map,key,keylen,&pme); + if (me!=NULL) { + return(me->value); + } else { + return(NULL); + } +} + +void* map_remove(map_handle map,void *key, int keylen){ + struct map_entry *me,**pme; + void *rtn_val; + me = internal_search(map,key,keylen,&pme); + if (me!=NULL){ + (*pme) = me->nxt; + rtn_val = me->value; + free (me); + map->size--; + return(rtn_val); + } else { + return(NULL); + } +} + +/* the key is a void *, but we also need the length */ +void map_insert(map_handle map, void *key, int keylen, void *value) { + struct map_entry *me,**pme; + + me = internal_search(map,key,keylen,&pme); + if (me != NULL){ + printlog(LOG_WARN, "util.c: insert failed, key already present."); + return; + } + /* now pme is at the end of the list on that index */ + me = (struct map_entry*) malloc(sizeof(struct map_entry)); + if (me == NULL) { + printlog(LOG_WARN, "util.c: insert failed, malloc failure"); + return; + } + if ((*pme) == NULL) + (*pme) = me; /* pointer now points to this new entry */ + else { + printlog(LOG_WARN, "util.c: insert failed. pme should always be NULL."); + free(me); + return; + } + me->nxt = NULL; + me->key = key; + me->value = value; + map->size++; + return; +} + +/* get_local_ip + * + * go through the available interfaces and find the first + * with a routable IP (not 10.*, 192.*, or 172.*) + * Ignore inet6 addrs for now. + * return the string. + */ +char* get_local_ip(){ + char *ip; + struct ifaddrs *ifa = NULL, *ifp = NULL; + struct sockaddr *addr; + uint32_t ho_addr; + socklen_t salen; + int shift; + unsigned char addrbyte; + + + if (getifaddrs(&ifp) < 0) { + perror("getifaddrs"); + return 0; + } + + if (am_big_endian()){ + shift = 0; + } else { + shift = 3; + } + +#define STRINGSIZE 200 + ip = (char *)malloc(STRINGSIZE); + + + for (ifa = ifp; ifa; ifa=ifa->ifa_next){ + if (ifa->ifa_addr->sa_family == AF_INET){ + salen = sizeof(struct sockaddr_in); + } else if( ifa->ifa_addr->sa_family == AF_INET6){ + salen = sizeof(struct sockaddr_in6); + } else { + continue; + } + + + if (getnameinfo(ifa->ifa_addr,salen, ip, STRINGSIZE, NULL, 0, NI_NUMERICHOST) < 0){ + perror("getnameinfo"); + continue; + } + /* return the first public IP match */ + + addr = ifa->ifa_addr; /* a sockaddr */ + struct in_addr *sin_addr = & (((struct sockaddr_in*)addr)->sin_addr); + ho_addr = ntohl((uint32_t)(sin_addr->s_addr)); + addrbyte = ((char*)&ho_addr)[shift]; + //printf("get_local_ip found %s and sin_addr 0x%x addrbyte %d\n",ip,ho_addr,(uint32_t)addrbyte); + + /* is it MSB first? */ + + if ( (addrbyte != 192) && (addrbyte != 172) + && (addrbyte != 10) && (addrbyte != 127) ){ + printlog(LOG_WARN, " Using ip: %s\n",ip); + freeifaddrs(ifp); +#if 0 + return (ifa->ifa_addr->sin_addr); +#else + return(ip); /* for now return the IP address */ +#endif + } + } + freeifaddrs(ifp); + free(ip); + return(NULL); +} + +static FILE *urandfd = NULL; + +static void myrand_init() { + if (urandfd == NULL) { + urandfd = fopen("/dev/urandom", "rb"); + if (urandfd == NULL) { + perror("myrand_init: fopen"); + } + setvbuf(urandfd, NULL, _IOFBF, 1 << 16); + } +} + +/* returns an unsigned int between 0 and UINT_MAX */ +unsigned int myrand() { + int successful; + + /* my new rand code */ + myrand_init(); + + unsigned int r; + successful = fread(&r, sizeof(unsigned int), 1, urandfd); + + return r; +} + +/* returns a random bool */ +int myrand_boolean() { + int successful; + + myrand_init(); + + uint8_t r; + successful = fread(&r, sizeof(uint8_t), 1, urandfd); + + return (r%2); +} + +/* returns a random double between 0 and 1 */ +double myrand_double() { + return (double) myrand() / (double) UINT_MAX; +} + +/* takes the log_2 of x */ +int my_lg(int x) { + int c = 0; + while (x > 0) { + c++; + x = x >> 1; + } + + return c; +} + +/* print out some error information if a system call failes */ +void print_system_error(int ret){ + if (WIFSIGNALED(ret) && + (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)){ + /* received some kind of signal during program execution */ + printf("enforce received signal during program execution."); + } else { + perror("enforce failed (ret==-1):"); + } +}