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/* Some 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) (void)0 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 const char *randfile = RANDFILE; 44 45 if (! been_seeded) 46 { 47 int fd, n = 0; 48 unsigned int c = 0, seed = 0, badseed; 49 char sbuf[sizeof(seed)]; 50 char *s; 51 struct timeval now; 52 53 /* get the bad seed as a backup */ 54 /* (but we'd rather have something more random) */ 55 gettimeofday(&now, NULL); 56 badseed = now.tv_sec ^ now.tv_usec ^ (getpid() << 16); 57 58 fd = open(randfile, O_RDONLY); 59 if (fd < 0) 60 seed = badseed; 61 else 62 { 63 s = (char *) &seed; 64 while ((c < sizeof(seed)) && 65 ((n = read(fd, sbuf, sizeof(seed)) > 0))) 66 { 67 memcpy(s, sbuf, n); 68 s += n; 69 c += n; 70 } 71 if (n < 0) 72 seed = badseed; 73 close(fd); 74 } 75 76 srand(seed); 77 been_seeded = 1; 78 } 79 80 /* Some rand() implementations have less randomness in low bits 81 * than in high bits, so we only pay attention to the high ones. 82 * But most implementations don't touch the high bit, so we 83 * ignore that one. 84 */ 85 return( (unsigned short) (rand() >> 15) ); 86} 87 88int atoi_check(char *a, int *res) 89{ 90 char *p; 91 92 for (p = a; *p; p++) 93 if (*p < '0' || *p > '9') 94 return 0; 95 96 *res = atoi(a); 97 return 1; 98} 99 100int legal_char(char c) 101{ 102 /* check for legal char a-z A-Z 0-9 - 103 (also / , used for RFC2317 and _ used in windows queries) */ 104 if ((c >= 'A' && c <= 'Z') || 105 (c >= 'a' && c <= 'z') || 106 (c >= '0' && c <= '9') || 107 c == '-' || c == '/' || c == '_') 108 return 1; 109 110 return 0; 111} 112 113int canonicalise(char *s) 114{ 115 /* check for legal chars and remove trailing . 116 also fail empty string. */ 117 int l = strlen(s); 118 char c; 119 120 if (l == 0) return 0; 121 122 if (s[l-1] == '.') 123 { 124 if (l == 1) return 0; 125 s[l-1] = 0; 126 } 127 128 while ((c = *s++)) 129 if (c != '.' && !legal_char(c)) 130 return 0; 131 132 return 1; 133} 134 135/* for use during startup */ 136void *safe_malloc(int size) 137{ 138 void *ret = malloc(size); 139 140 if (!ret) 141 die("could not get memory", NULL); 142 143 return ret; 144} 145 146char *safe_string_alloc(char *cp) 147{ 148 char *ret = NULL; 149 150 if (cp && strlen(cp) != 0) 151 { 152 ret = safe_malloc(strlen(cp)+1); 153 strcpy(ret, cp); 154 } 155 156 return ret; 157} 158 159void complain(char *message, char *arg1) 160{ 161 char *errmess = strerror(errno); 162 163 if (!arg1) 164 arg1 = errmess; 165 166 fprintf(stderr, "dnsmasq: "); 167 fprintf(stderr, message, arg1, errmess); 168 fprintf(stderr, "\n"); 169 170#ifdef USE_SYSLOG /* foxconn wklin added, 08/13/2007 */ 171 syslog(LOG_CRIT, message, arg1, errmess); 172#endif 173} 174 175void die(char *message, char *arg1) 176{ 177 complain(message, arg1); 178#ifdef USE_SYSLOG /* foxconn wklin added, 08/13/2007 */ 179 syslog(LOG_CRIT, "FAILED to start up"); 180#endif 181 exit(1); 182} 183 184int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2) 185{ 186 if (s1->sa.sa_family == s2->sa.sa_family) 187 { 188 if (s1->sa.sa_family == AF_INET && 189 s1->in.sin_port == s2->in.sin_port && 190 memcmp(&s1->in.sin_addr, &s2->in.sin_addr, sizeof(struct in_addr)) == 0) 191 return 1; 192#ifdef HAVE_IPV6 193 if (s1->sa.sa_family == AF_INET6 && 194 s1->in6.sin6_port == s2->in6.sin6_port && 195 s1->in6.sin6_flowinfo == s2->in6.sin6_flowinfo && 196 memcmp(&s1->in6.sin6_addr, &s2->in6.sin6_addr, sizeof(struct in6_addr)) == 0) 197 return 1; 198#endif 199 } 200 return 0; 201} 202 203int sa_len(union mysockaddr *addr) 204{ 205#ifdef HAVE_SOCKADDR_SA_LEN 206 return addr->sa.sa_len; 207#else 208#ifdef HAVE_IPV6 209 if (addr->sa.sa_family == AF_INET6) 210 return sizeof(addr->in6); 211 else 212#endif 213 return sizeof(addr->in); 214#endif 215} 216 217/* don't use strcasecmp and friends here - they may be messed up by LOCALE */ 218int hostname_isequal(unsigned char *a, unsigned char *b) 219{ 220 unsigned int c1, c2; 221 222 do { 223 c1 = *a++; 224 c2 = *b++; 225 226 if (c1 >= 'A' && c1 <= 'Z') 227 c1 += 'a' - 'A'; 228 if (c2 >= 'A' && c2 <= 'Z') 229 c2 += 'a' - 'A'; 230 231 if (c1 != c2) 232 return 0; 233 } while (c1); 234 235 return 1; 236} 237 238time_t dnsmasq_time(int fd) 239{ 240#ifdef HAVE_BROKEN_RTC 241 /* we use uptime as a time-base, rather than epoch time 242 because epoch time can break when a machine contacts 243 a nameserver and updates it. */ 244 char buf[30]; 245 lseek(fd, 0, SEEK_SET); 246 read(fd, buf, 30); 247 return (time_t)atol(buf); 248#else 249 fd = 0; /* stop warning */ 250 return time(NULL); 251#endif 252} 253 254int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) 255{ 256 return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); 257}