add MD5 and CHECK_MD5 functions, deprecate MD5 and MD5Check apps (bug #4123)
[asterisk/asterisk.git] / utils.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Utility functions
5  *
6  * Copyright (C)  2004 - 2005, Digium, Inc.
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #ifdef Linux    /* For strcasestr */
13 #define __USE_GNU
14 #endif
15 #include <ctype.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25
26 #include "asterisk/lock.h"
27 #include "asterisk/utils.h"
28 #include "asterisk/io.h"
29 #include "asterisk/logger.h"
30 #include "asterisk/md5.h"
31
32 static char base64[64];
33 static char b2a[256];
34
35 char *ast_strip(char *buf)
36 {
37         char *start;
38         /* Strip off trailing whitespace, returns, etc */
39         while (!ast_strlen_zero(buf) && (buf[strlen(buf)-1]<33))
40                 buf[strlen(buf)-1] = '\0';
41         start = buf;
42         /* Strip off leading whitespace, returns, etc */
43         while (*start && (*start < 33))
44                 *start++ = '\0';
45         return start;
46 }
47
48 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
49
50 /* duh? ERANGE value copied from web... */
51 #define ERANGE 34
52 #undef gethostbyname
53
54 AST_MUTEX_DEFINE_STATIC(__mutex);
55
56 /* Recursive replacement for gethostbyname for BSD-based systems */
57 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
58                                 size_t buflen, struct hostent **result, 
59                                 int *h_errnop) 
60 {
61         int hsave;
62         struct hostent *ph;
63         ast_mutex_lock(&__mutex); /* begin critical area */
64         hsave = h_errno;
65
66         ph = gethostbyname(name);
67         *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
68         if (ph == NULL) {
69                 *result = NULL;
70         } else {
71                 char **p, **q;
72                 char *pbuf;
73                 int nbytes=0;
74                 int naddr=0, naliases=0;
75                 /* determine if we have enough space in buf */
76
77                 /* count how many addresses */
78                 for (p = ph->h_addr_list; *p != 0; p++) {
79                         nbytes += ph->h_length; /* addresses */
80                         nbytes += sizeof(*p); /* pointers */
81                         naddr++;
82                 }
83                 nbytes += sizeof(*p); /* one more for the terminating NULL */
84
85                 /* count how many aliases, and total length of strings */
86                 for (p = ph->h_aliases; *p != 0; p++) {
87                         nbytes += (strlen(*p)+1); /* aliases */
88                         nbytes += sizeof(*p);  /* pointers */
89                         naliases++;
90                 }
91                 nbytes += sizeof(*p); /* one more for the terminating NULL */
92
93                 /* here nbytes is the number of bytes required in buffer */
94                 /* as a terminator must be there, the minimum value is ph->h_length */
95                 if(nbytes > buflen) {
96                         *result = NULL;
97                         ast_mutex_unlock(&__mutex); /* end critical area */
98                         return ERANGE; /* not enough space in buf!! */
99                 }
100
101                 /* There is enough space. Now we need to do a deep copy! */
102                 /* Allocation in buffer:
103                         from [0] to [(naddr-1) * sizeof(*p)]:
104                         pointers to addresses
105                         at [naddr * sizeof(*p)]:
106                         NULL
107                         from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
108                         pointers to aliases
109                         at [(naddr+naliases+1) * sizeof(*p)]:
110                         NULL
111                         then naddr addresses (fixed length), and naliases aliases (asciiz).
112                 */
113
114                 *ret = *ph;   /* copy whole structure (not its address!) */
115
116                 /* copy addresses */
117                 q = (char **)buf; /* pointer to pointers area (type: char **) */
118                 ret->h_addr_list = q; /* update pointer to address list */
119                 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
120                 for (p = ph->h_addr_list; *p != 0; p++) {
121                         memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
122                         *q++ = pbuf; /* the pointer is the one inside buf... */
123                         pbuf += ph->h_length; /* advance pbuf */
124                 }
125                 *q++ = NULL; /* address list terminator */
126
127                 /* copy aliases */
128                 ret->h_aliases = q; /* update pointer to aliases list */
129                 for (p = ph->h_aliases; *p != 0; p++) {
130                         strcpy(pbuf, *p); /* copy alias strings */
131                         *q++ = pbuf; /* the pointer is the one inside buf... */
132                         pbuf += strlen(*p); /* advance pbuf */
133                         *pbuf++ = 0; /* string terminator */
134                 }
135                 *q++ = NULL; /* terminator */
136
137                 strcpy(pbuf, ph->h_name); /* copy alias strings */
138                 ret->h_name = pbuf;
139                 pbuf += strlen(ph->h_name); /* advance pbuf */
140                 *pbuf++ = 0; /* string terminator */
141
142                 *result = ret;  /* and let *result point to structure */
143
144         }
145         h_errno = hsave;  /* restore h_errno */
146         ast_mutex_unlock(&__mutex); /* end critical area */
147
148         return (*result == NULL); /* return 0 on success, non-zero on error */
149 }
150
151
152 #endif
153
154 /* Re-entrant (thread safe) version of gethostbyname that replaces the 
155    standard gethostbyname (which is not thread safe)
156 */
157 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
158 {
159         int res;
160         int herrno;
161         const char *s;
162         struct hostent *result = NULL;
163         /* Although it is perfectly legitimate to lookup a pure integer, for
164            the sake of the sanity of people who like to name their peers as
165            integers, we break with tradition and refuse to look up a
166            pure integer */
167         s = host;
168         res = 0;
169         while(s && *s) {
170                 if (!isdigit(*s))
171                         break;
172                 s++;
173         }
174         if (!s || !*s)
175                 return NULL;
176 #ifdef SOLARIS
177         result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
178
179         if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
180                 return NULL;
181 #else
182         res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
183
184         if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
185                 return NULL;
186 #endif
187         return &hp->hp;
188 }
189
190
191 /* This is a regression test for recursive mutexes.
192    test_for_thread_safety() will return 0 if recursive mutex locks are
193    working properly, and non-zero if they are not working properly. */
194
195 AST_MUTEX_DEFINE_STATIC(test_lock);
196 AST_MUTEX_DEFINE_STATIC(test_lock2);
197 static pthread_t test_thread; 
198 static int lock_count = 0;
199 static int test_errors = 0;
200
201 static void *test_thread_body(void *data) 
202
203         ast_mutex_lock(&test_lock);
204         lock_count += 10;
205         if (lock_count != 10) 
206                 test_errors++;
207         ast_mutex_lock(&test_lock);
208         lock_count += 10;
209         if (lock_count != 20) 
210                 test_errors++;
211         ast_mutex_lock(&test_lock2);
212         ast_mutex_unlock(&test_lock);
213         lock_count -= 10;
214         if (lock_count != 10) 
215                 test_errors++;
216         ast_mutex_unlock(&test_lock);
217         lock_count -= 10;
218         ast_mutex_unlock(&test_lock2);
219         if (lock_count != 0) 
220                 test_errors++;
221         return NULL;
222
223
224 int test_for_thread_safety(void)
225
226         ast_mutex_lock(&test_lock2);
227         ast_mutex_lock(&test_lock);
228         lock_count += 1;
229         ast_mutex_lock(&test_lock);
230         lock_count += 1;
231         ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
232         usleep(100);
233         if (lock_count != 2) 
234                 test_errors++;
235         ast_mutex_unlock(&test_lock);
236         lock_count -= 1;
237         usleep(100); 
238         if (lock_count != 1) 
239                 test_errors++;
240         ast_mutex_unlock(&test_lock);
241         lock_count -= 1;
242         if (lock_count != 0) 
243                 test_errors++;
244         ast_mutex_unlock(&test_lock2);
245         usleep(100);
246         if (lock_count != 0) 
247                 test_errors++;
248         pthread_join(test_thread, NULL);
249         return(test_errors);          /* return 0 on success. */
250 }
251
252 /*--- ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
253 void ast_md5_hash(char *output, char *input)
254 {
255         struct MD5Context md5;
256         unsigned char digest[16];
257         char *ptr;
258         int x;
259
260         MD5Init(&md5);
261         MD5Update(&md5, input, strlen(input));
262         MD5Final(digest, &md5);
263         ptr = output;
264         for (x=0; x<16; x++)
265                 ptr += sprintf(ptr, "%2.2x", digest[x]);
266 }
267
268 int ast_base64decode(unsigned char *dst, char *src, int max)
269 {
270         int cnt = 0;
271         unsigned int byte = 0;
272         unsigned int bits = 0;
273         int incnt = 0;
274 #if 0
275         unsigned char *odst = dst;
276 #endif
277         while(*src && (cnt < max)) {
278                 /* Shift in 6 bits of input */
279                 byte <<= 6;
280                 byte |= (b2a[(int)(*src)]) & 0x3f;
281                 bits += 6;
282 #if 0
283                 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
284 #endif
285                 src++;
286                 incnt++;
287                 /* If we have at least 8 bits left over, take that character 
288                    off the top */
289                 if (bits >= 8)  {
290                         bits -= 8;
291                         *dst = (byte >> bits) & 0xff;
292 #if 0
293                         printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
294 #endif
295                         dst++;
296                         cnt++;
297                 }
298         }
299 #if 0
300         dump(odst, cnt);
301 #endif
302         /* Dont worry about left over bits, they're extra anyway */
303         return cnt;
304 }
305
306 int ast_base64encode(char *dst, unsigned char *src, int srclen, int max)
307 {
308         int cnt = 0;
309         unsigned int byte = 0;
310         int bits = 0;
311         int index;
312         int cntin = 0;
313 #if 0
314         char *odst = dst;
315         dump(src, srclen);
316 #endif
317         /* Reserve one bit for end */
318         max--;
319         while((cntin < srclen) && (cnt < max)) {
320                 byte <<= 8;
321 #if 0
322                 printf("Add: %02x %s\n", *src, binary(*src, 8));
323 #endif
324                 byte |= *(src++);
325                 bits += 8;
326                 cntin++;
327                 while((bits >= 6) && (cnt < max)) {
328                         bits -= 6;
329                         /* We want only the top */
330                         index = (byte >> bits) & 0x3f;
331                         *dst = base64[index];
332 #if 0
333                         printf("Remove: %c %s\n", *dst, binary(index, 6));
334 #endif
335                         dst++;
336                         cnt++;
337                 }
338         }
339         if (bits && (cnt < max)) {
340                 /* Add one last character for the remaining bits, 
341                    padding the rest with 0 */
342                 byte <<= (6 - bits);
343                 index = (byte) & 0x3f;
344                 *(dst++) = base64[index];
345                 cnt++;
346         }
347         *dst = '\0';
348         return cnt;
349 }
350
351 static void base64_init(void)
352 {
353         int x;
354         memset(b2a, -1, sizeof(b2a));
355         /* Initialize base-64 Conversion table */
356         for (x=0;x<26;x++) {
357                 /* A-Z */
358                 base64[x] = 'A' + x;
359                 b2a['A' + x] = x;
360                 /* a-z */
361                 base64[x + 26] = 'a' + x;
362                 b2a['a' + x] = x + 26;
363                 /* 0-9 */
364                 if (x < 10) {
365                         base64[x + 52] = '0' + x;
366                         b2a['0' + x] = x + 52;
367                 }
368         }
369         base64[62] = '+';
370         base64[63] = '/';
371         b2a[(int)'+'] = 62;
372         b2a[(int)'/'] = 63;
373 #if 0
374         for (x=0;x<64;x++) {
375                 if (b2a[(int)base64[x]] != x) {
376                         fprintf(stderr, "!!! %d failed\n", x);
377                 } else
378                         fprintf(stderr, "--- %d passed\n", x);
379         }
380 #endif
381 }
382
383 /* Recursive thread safe replacement of inet_ntoa */
384 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
385 {
386         return inet_ntop(AF_INET, &ia, buf, bufsiz);
387 }
388
389 int ast_utils_init(void)
390 {
391         base64_init();
392         return 0;
393 }
394
395 #ifndef __linux__
396 #undef pthread_create /* For ast_pthread_create function only */
397 #endif /* ! LINUX */
398 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
399 {
400         pthread_attr_t lattr;
401         if (!attr) {
402                 pthread_attr_init(&lattr);
403                 attr = &lattr;
404         }
405         if (!stacksize)
406                 stacksize = AST_STACKSIZE;
407         errno = pthread_attr_setstacksize(attr, stacksize);
408         if (errno)
409                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
410         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
411 }
412
413 int ast_wait_for_input(int fd, int ms)
414 {
415         struct pollfd pfd[1];
416         memset(pfd, 0, sizeof(pfd));
417         pfd[0].fd = fd;
418         pfd[0].events = POLLIN|POLLPRI;
419         return poll(pfd, 1, ms);
420 }
421
422 void ast_copy_string(char *dst, const char *src, size_t size)
423 {
424         while (*src && size) {
425                 *dst++ = *src++;
426                 size--;
427         }
428         if (__builtin_expect(!size, 0))
429                 dst--;
430         *dst = '\0';
431 }
432
433 /* Case-insensitive substring matching */
434 #ifndef LINUX
435 static char *upper(const char *orig, char *buf, int bufsize)
436 {
437         int i;
438         memset(buf, 0, bufsize);
439         for (i=0; i<bufsize - 1; i++) {
440                 buf[i] = toupper(orig[i]);
441                 if (orig[i] == '\0') {
442                         break;
443                 }
444         }
445         return buf;
446 }
447
448 char *ast_strcasestr(const char *haystack, const char *needle)
449 {
450         char *u1, *u2;
451         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
452
453         u1 = alloca(u1len);
454         u2 = alloca(u2len);
455         if (u1 && u2) {
456                 char *offset;
457                 if (u2len > u1len) {
458                         /* Needle bigger than haystack */
459                         return NULL;
460                 }
461                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
462                 if (offset) {
463                         /* Return the offset into the original string */
464                         return ((char *)((unsigned int)haystack + (unsigned int)(offset - u1)));
465                 } else {
466                         return NULL;
467                 }
468         } else {
469                 ast_log(LOG_ERROR, "Out of memory\n");
470                 return NULL;
471         }
472 }
473 #endif /* LINUX */