00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifdef Linux
00013 #define __USE_GNU
00014 #endif
00015 #include <ctype.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <stdlib.h>
00019 #include <errno.h>
00020 #include <sys/types.h>
00021 #include <sys/socket.h>
00022 #include <netinet/in.h>
00023 #include <arpa/inet.h>
00024 #include <asterisk/lock.h>
00025 #include <asterisk/utils.h>
00026 #include <asterisk/logger.h>
00027
00028 static char base64[64];
00029 static char b2a[256];
00030
00031 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
00032
00033
00034 #define ERANGE 34
00035 #undef gethostbyname
00036
00037 AST_MUTEX_DEFINE_STATIC(__mutex);
00038
00039
00040 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
00041 size_t buflen, struct hostent **result,
00042 int *h_errnop)
00043 {
00044 int hsave;
00045 struct hostent *ph;
00046 ast_mutex_lock(&__mutex);
00047 hsave = h_errno;
00048
00049 ph = gethostbyname(name);
00050 *h_errnop = h_errno;
00051 if (ph == NULL) {
00052 *result = NULL;
00053 } else {
00054 char **p, **q;
00055 char *pbuf;
00056 int nbytes=0;
00057 int naddr=0, naliases=0;
00058
00059
00060
00061 for (p = ph->h_addr_list; *p != 0; p++) {
00062 nbytes += ph->h_length;
00063 nbytes += sizeof(*p);
00064 naddr++;
00065 }
00066 nbytes += sizeof(*p);
00067
00068
00069 for (p = ph->h_aliases; *p != 0; p++) {
00070 nbytes += (strlen(*p)+1);
00071 nbytes += sizeof(*p);
00072 naliases++;
00073 }
00074 nbytes += sizeof(*p);
00075
00076
00077
00078 if(nbytes > buflen) {
00079 *result = NULL;
00080 ast_mutex_unlock(&__mutex);
00081 return ERANGE;
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 *ret = *ph;
00098
00099
00100 q = (char **)buf;
00101 ret->h_addr_list = q;
00102 pbuf = buf + ((naddr+naliases+2)*sizeof(*p));
00103 for (p = ph->h_addr_list; *p != 0; p++) {
00104 memcpy(pbuf, *p, ph->h_length);
00105 *q++ = pbuf;
00106 pbuf += ph->h_length;
00107 }
00108 *q++ = NULL;
00109
00110
00111 ret->h_aliases = q;
00112 for (p = ph->h_aliases; *p != 0; p++) {
00113 strcpy(pbuf, *p);
00114 *q++ = pbuf;
00115 pbuf += strlen(*p);
00116 *pbuf++ = 0;
00117 }
00118 *q++ = NULL;
00119
00120 strcpy(pbuf, ph->h_name);
00121 ret->h_name = pbuf;
00122 pbuf += strlen(ph->h_name);
00123 *pbuf++ = 0;
00124
00125 *result = ret;
00126
00127 }
00128 h_errno = hsave;
00129 ast_mutex_unlock(&__mutex);
00130
00131 return (*result == NULL);
00132 }
00133
00134
00135 #endif
00136
00137
00138
00139
00140 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
00141 {
00142 int res;
00143 int herrno;
00144 const char *s;
00145 struct hostent *result = NULL;
00146
00147
00148
00149
00150 s = host;
00151 while(s && *s) {
00152 if (!isdigit(*s))
00153 break;
00154 s++;
00155 }
00156 if (!s || !*s)
00157 return NULL;
00158 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
00159
00160 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00161 return NULL;
00162 return &hp->hp;
00163 }
00164
00165
00166
00167
00168
00169
00170 AST_MUTEX_DEFINE_STATIC(test_lock);
00171 AST_MUTEX_DEFINE_STATIC(test_lock2);
00172 static pthread_t test_thread;
00173 static int lock_count = 0;
00174 static int test_errors = 0;
00175
00176 static void *test_thread_body(void *data)
00177 {
00178 ast_mutex_lock(&test_lock);
00179 lock_count += 10;
00180 if (lock_count != 10)
00181 test_errors++;
00182 ast_mutex_lock(&test_lock);
00183 lock_count += 10;
00184 if (lock_count != 20)
00185 test_errors++;
00186 ast_mutex_lock(&test_lock2);
00187 ast_mutex_unlock(&test_lock);
00188 lock_count -= 10;
00189 if (lock_count != 10)
00190 test_errors++;
00191 ast_mutex_unlock(&test_lock);
00192 lock_count -= 10;
00193 ast_mutex_unlock(&test_lock2);
00194 if (lock_count != 0)
00195 test_errors++;
00196 return NULL;
00197 }
00198
00199 int test_for_thread_safety(void)
00200 {
00201 ast_mutex_lock(&test_lock2);
00202 ast_mutex_lock(&test_lock);
00203 lock_count += 1;
00204 ast_mutex_lock(&test_lock);
00205 lock_count += 1;
00206 ast_pthread_create(&test_thread, NULL, test_thread_body, NULL);
00207 usleep(100);
00208 if (lock_count != 2)
00209 test_errors++;
00210 ast_mutex_unlock(&test_lock);
00211 lock_count -= 1;
00212 usleep(100);
00213 if (lock_count != 1)
00214 test_errors++;
00215 ast_mutex_unlock(&test_lock);
00216 lock_count -= 1;
00217 if (lock_count != 0)
00218 test_errors++;
00219 ast_mutex_unlock(&test_lock2);
00220 usleep(100);
00221 if (lock_count != 0)
00222 test_errors++;
00223 pthread_join(test_thread, NULL);
00224 return(test_errors);
00225 }
00226
00227 int ast_base64decode(unsigned char *dst, char *src, int max)
00228 {
00229 int cnt = 0;
00230 unsigned int byte = 0;
00231 unsigned int bits = 0;
00232 int incnt = 0;
00233 #if 0
00234 unsigned char *odst = dst;
00235 #endif
00236 while(*src && (cnt < max)) {
00237
00238 byte <<= 6;
00239 byte |= (b2a[(int)(*src)]) & 0x3f;
00240 bits += 6;
00241 #if 0
00242 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
00243 #endif
00244 src++;
00245 incnt++;
00246
00247
00248 if (bits >= 8) {
00249 bits -= 8;
00250 *dst = (byte >> bits) & 0xff;
00251 #if 0
00252 printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
00253 #endif
00254 dst++;
00255 cnt++;
00256 }
00257 }
00258 #if 0
00259 dump(odst, cnt);
00260 #endif
00261
00262 return cnt;
00263 }
00264
00265 int ast_base64encode(char *dst, unsigned char *src, int srclen, int max)
00266 {
00267 int cnt = 0;
00268 unsigned int byte = 0;
00269 int bits = 0;
00270 int index;
00271 int cntin = 0;
00272 #if 0
00273 char *odst = dst;
00274 dump(src, srclen);
00275 #endif
00276
00277 max--;
00278 while((cntin < srclen) && (cnt < max)) {
00279 byte <<= 8;
00280 #if 0
00281 printf("Add: %02x %s\n", *src, binary(*src, 8));
00282 #endif
00283 byte |= *(src++);
00284 bits += 8;
00285 cntin++;
00286 while((bits >= 6) && (cnt < max)) {
00287 bits -= 6;
00288
00289 index = (byte >> bits) & 0x3f;
00290 *dst = base64[index];
00291 #if 0
00292 printf("Remove: %c %s\n", *dst, binary(index, 6));
00293 #endif
00294 dst++;
00295 cnt++;
00296 }
00297 }
00298 if (bits && (cnt < max)) {
00299
00300
00301 byte <<= (6 - bits);
00302 index = (byte) & 0x3f;
00303 *(dst++) = base64[index];
00304 cnt++;
00305 }
00306 *dst = '\0';
00307 return cnt;
00308 }
00309
00310 static void base64_init(void)
00311 {
00312 int x;
00313 memset(b2a, -1, sizeof(b2a));
00314
00315 for (x=0;x<26;x++) {
00316
00317 base64[x] = 'A' + x;
00318 b2a['A' + x] = x;
00319
00320 base64[x + 26] = 'a' + x;
00321 b2a['a' + x] = x + 26;
00322
00323 if (x < 10) {
00324 base64[x + 52] = '0' + x;
00325 b2a['0' + x] = x + 52;
00326 }
00327 }
00328 base64[62] = '+';
00329 base64[63] = '/';
00330 b2a[(int)'+'] = 62;
00331 b2a[(int)'/'] = 63;
00332 #if 0
00333 for (x=0;x<64;x++) {
00334 if (b2a[(int)base64[x]] != x) {
00335 fprintf(stderr, "!!! %d failed\n", x);
00336 } else
00337 fprintf(stderr, "--- %d passed\n", x);
00338 }
00339 #endif
00340 }
00341
00342
00343 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
00344 {
00345 return inet_ntop(AF_INET, &ia, buf, bufsiz);
00346 }
00347
00348 int ast_utils_init(void)
00349 {
00350 base64_init();
00351 return 0;
00352 }
00353
00354
00355 #ifndef LINUX
00356 #undef pthread_create
00357 int ast_pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data)
00358 {
00359 pthread_attr_t lattr;
00360 if (!attr) {
00361 pthread_attr_init(&lattr);
00362 attr = &lattr;
00363 }
00364 errno = pthread_attr_setstacksize(attr, PTHREAD_ATTR_STACKSIZE);
00365 if (errno)
00366 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
00367 return pthread_create(thread, attr, start_routine, data);
00368 }
00369 #endif
00370
00371 static char *upper(const char *orig, char *buf, int bufsize)
00372 {
00373 int i;
00374 memset(buf, 0, bufsize);
00375 for (i=0; i<bufsize - 1; i++) {
00376 buf[i] = toupper(orig[i]);
00377 if (orig[i] == '\0') {
00378 break;
00379 }
00380 }
00381 return buf;
00382 }
00383
00384
00385 #ifndef LINUX
00386 char *ast_strcasestr(const char *haystack, const char *needle)
00387 {
00388 char *u1, *u2;
00389 int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
00390
00391 u1 = alloca(u1len);
00392 u2 = alloca(u2len);
00393 if (u1 && u2) {
00394 char *offset;
00395 if (u2len > u1len) {
00396
00397 return NULL;
00398 }
00399 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
00400 if (offset) {
00401
00402 return ((char *)((unsigned int)haystack + (unsigned int)(offset - u1)));
00403 } else {
00404 return NULL;
00405 }
00406 } else {
00407 ast_log(LOG_ERROR, "Out of memory\n");
00408 return NULL;
00409 }
00410 }
00411 #endif
00412