--- /dev/null
+/* 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;i<len;i++){ /* word-wise bit compare would be faster */
+ if(((char*)one)[i] != ((char*)two)[i]){
+ return(false);
+ }
+ }
+ return(true);
+}
+
+/* pass in something at least 20 bytes long */
+void ip_from_bytes(uint32_t addr, char *buf){
+ int i;
+ unsigned char *caddr = (unsigned char*) &addr;
+ if (am_big_endian()){
+ i = sprintf(buf,"%d.%d.%d.%d",caddr[0],caddr[1],caddr[2],caddr[3]);
+ } else {
+ i = sprintf(buf,"%d.%d.%d.%d",caddr[3],caddr[2],caddr[1],caddr[0]);
+ }
+ return;
+}
+
+
+void init_hashing(void){
+ util_salt = getpid() ^ time(NULL); // same as ulogd_drl
+}
+
+/* some stupid generic hash function things */
+/* just return a map_handle */
+map_handle allocate_map(void) {
+ map_handle map;
+ map = (map_handle) malloc(sizeof(struct map));
+ if (map == NULL) {
+ printlog(LOG_WARN, "allocate_map failed.");
+ return NULL;
+ }
+
+ memset(map,0,sizeof(struct map));
+ map->iterator = 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;i<GENERIC_HASH_SIZE;i++){
+ nxt_me = (struct map_entry*) (map->table[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;i<keylen;i++){
+ printf("[%x]",((char*)key)[i]);
+ }
+ printf(" Hashes to index (%d)\n", index);
+#endif
+
+ nxt_me = (struct map_entry*) map->table[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;i<map->size;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):");
+ }
+}