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), u2len = strlen(needle);
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