1/* dnsmasq is Copyright (c) 2000 Simon Kelley 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 dated June, 1991. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11*/ 12 13 14/* Code in this file contributed by Rob Funk. */ 15 16#include "dnsmasq.h" 17 18/* Prefer arc4random(3) over random(3) over rand(3) */ 19/* Also prefer /dev/urandom over /dev/random, to preserve the entropy pool */ 20#ifdef HAVE_ARC4RANDOM 21# define rand() arc4random() 22# define srand(s) (NULL) 23# define RANDFILE (NULL) 24#else 25# ifdef HAVE_RANDOM 26# define rand() random() 27# define srand(s) srandom(s) 28# endif 29# ifdef HAVE_DEV_URANDOM 30# define RANDFILE "/dev/urandom" 31# else 32# ifdef HAVE_DEV_RANDOM 33# define RANDFILE "/dev/random" 34# else 35# define RANDFILE (NULL) 36# endif 37# endif 38#endif 39 40unsigned short rand16(void) 41{ 42 static int been_seeded = 0; 43#ifdef HAVE_FILE_SYSTEM 44 const char *randfile = RANDFILE; 45#endif 46 47 if (! been_seeded) 48 { 49#ifdef HAVE_FILE_SYSTEM 50 int fd, n = 0; 51#endif 52 unsigned int c = 0, seed = 0, badseed; 53#ifdef HAVE_FILE_SYSTEM 54 char sbuf[sizeof(seed)]; 55 char *s; 56#endif 57 struct timeval now; 58 59 /* get the bad seed as a backup */ 60 /* (but we'd rather have something more random) */ 61 gettimeofday(&now, NULL); 62 badseed = now.tv_sec ^ now.tv_usec ^ (getpid() << 16); 63 64#ifdef HAVE_FILE_SYSTEM 65 fd = open(randfile, O_RDONLY); 66 if (fd < 0) 67 seed = badseed; 68 else 69 { 70 s = (char *) &seed; 71 while ( (c < sizeof(seed)) && 72 ((n = read(fd, sbuf, sizeof(seed)) > 0)) ) 73 { 74 memcpy(s, sbuf, n); 75 s += n; 76 c += n; 77 } 78 if (n < 0) 79 { 80 seed = badseed; 81 } 82 } 83 if (seed != badseed) 84 close(fd); 85#else 86 seed = badseed; 87#endif 88 89 srand(seed); 90 been_seeded = 1; 91 } 92 93 /* Some rand() implementations have less randomness in low bits 94 * than in high bits, so we only pay attention to the high ones. 95 * But most implementations don't touch the high bit, so we 96 * ignore that one. 97 */ 98 return( (unsigned short) (rand() >> 15) ); 99} 100 101void canonicalise(char *s) 102{ 103 char *p; 104 int l = strlen(s); 105 106 for (p=s; *p; p++) 107 *p = tolower(*p); 108 109 if (l>0 && s[l-1] == '.') 110 s[l-1] = 0; 111} 112 113/* 114* memory counters - debugging only 115*/ 116#if defined(DEBUG_MEMORY) 117static unsigned int allocated_memory_count = 0; 118void dnsr_mem_used(void) 119{ 120 printf("Total memory used: %u bytes\n", allocated_memory_count); 121} 122#endif 123 124void safe_free(void *mem) 125{ 126#if defined(DEBUG_MEMORY) 127 unsigned int size; 128 char *ptr = mem; 129 if (ptr == NULL) 130 { 131 printf("safe_free: NULL pointer!\n"); 132 return; 133 } 134 else if (((unsigned int)ptr)&3) 135 { 136 printf("safe_free: Memory at 0x%08x not aligned!\n", mem); 137 } 138 else 139 { 140 if (*(--(unsigned int *)ptr) != 0xDEADBEEF) 141 { 142 printf("safe_free: Memory at 0x%08x untagged!\n", mem); 143 } 144 else 145 { 146 size = *(--(unsigned int *)ptr); 147 allocated_memory_count -= size; 148 mem = ptr; 149 } 150 } 151#endif 152 free(mem); 153} 154 155/* for use during startup */ 156void *safe_malloc(int size) 157{ 158#if defined(DEBUG_MEMORY) 159 char *ret = memalign(4, ((size+3)&~3)+3*sizeof(unsigned int)); 160#else 161 void *ret = malloc(size); 162#endif 163 164 if (!ret) 165 die("could not get memory", NULL); 166 167#if defined(DEBUG_MEMORY) 168 *(unsigned int *)ret = size; 169 ret += sizeof(unsigned int); 170 *(unsigned int *)ret = 0xDEADBEEF; 171 ret += sizeof(unsigned int); 172 memset(ret, 0, size); 173 *(unsigned int *)(ret+((size+3)&~3)) = 0xDEADBEEF; 174 allocated_memory_count += size; 175#endif 176 177 return ret; 178} 179 180char *safe_string_alloc(char *cp) 181{ 182 char *ret = NULL; 183 184 if (cp && strlen(cp) != 0) 185 { 186 ret = safe_malloc(strlen(cp)+1); 187 strcpy(ret, cp); 188 } 189 190 return ret; 191} 192 193void die(char *message, char *arg1) 194{ 195 char *errmess = strerror(errno); 196 197 if (!arg1) 198 arg1 = errmess; 199 200 fprintf(stderr, "dnsmasq: "); 201 fprintf(stderr, message, arg1, errmess); 202 fprintf(stderr, "\n"); 203 204 syslog(LOG_CRIT, message, arg1, errmess); 205 syslog(LOG_CRIT, "FAILED to start up"); 206 exit(1); 207} 208 209int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2) 210{ 211 if (s1->sa.sa_family == s2->sa.sa_family) 212 { 213 if (s1->sa.sa_family == AF_INET && 214 s1->in.sin_port == s2->in.sin_port && 215 memcmp(&s1->in.sin_addr, &s2->in.sin_addr, sizeof(struct in_addr)) == 0) 216 return 1; 217#ifdef HAVE_IPV6 218 if (s1->sa.sa_family == AF_INET6 && 219 s1->in6.sin6_port == s2->in6.sin6_port && 220 s1->in6.sin6_flowinfo == s2->in6.sin6_flowinfo && 221 memcmp(&s1->in6.sin6_addr, &s2->in6.sin6_addr, sizeof(struct in6_addr)) == 0) 222 return 1; 223#endif 224 } 225 return 0; 226} 227 228int sa_len(union mysockaddr *addr) 229{ 230#ifdef HAVE_SOCKADDR_SA_LEN 231 return addr->sa.sa_len; 232#else 233#ifdef HAVE_IPV6 234 if (addr->sa.sa_family == AF_INET6) 235 return sizeof(addr->in6); 236 else 237#endif 238 return sizeof(addr->in); 239#endif 240} 241