35 #include <sys/syscall.h>
37 #if defined(__APPLE__)
38 #include <mach/mach.h>
39 #elif defined(__NetBSD__)
41 #elif defined(HAVE_SYS_THR_H)
48 #define AST_API_MODULE
57 #define AST_API_MODULE
60 #define AST_API_MODULE
63 #define AST_API_MODULE
66 #define AST_API_MODULE
69 #define AST_API_MODULE
72 #define AST_API_MODULE
87 #if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
99 static int gethostbyname_r (
const char *
name,
struct hostent *ret,
char *
buf,
100 size_t buflen,
struct hostent **
result,
116 int naddr = 0, naliases = 0;
120 for (p = ph->h_addr_list; *p != 0; p++) {
121 nbytes += ph->h_length;
122 nbytes +=
sizeof(*p);
125 nbytes +=
sizeof(*p);
128 for (p = ph->h_aliases; *p != 0; p++) {
129 nbytes += (strlen(*p)+1);
130 nbytes +=
sizeof(*p);
133 nbytes +=
sizeof(*p);
137 if (nbytes > buflen) {
160 ret->h_addr_list = q;
161 pbuf =
buf + ((naddr + naliases + 2) *
sizeof(*p));
162 for (p = ph->h_addr_list; *p != 0; p++) {
163 memcpy(pbuf, *p, ph->h_length);
165 pbuf += ph->h_length;
171 for (p = ph->h_aliases; *p != 0; p++) {
179 strcpy(pbuf, ph->h_name);
181 pbuf += strlen(ph->h_name);
201 #ifndef HAVE_GETHOSTBYNAME_R_5
216 else if (!isdigit(*s))
225 hp->
hp.h_addrtype = AF_INET;
226 hp->
hp.h_addr_list = (
void *) hp->
buf;
227 hp->
hp.h_addr = hp->
buf +
sizeof(
void *);
230 if (inet_pton(AF_INET, host, hp->
hp.h_addr) > 0)
235 #ifdef HAVE_GETHOSTBYNAME_R_5
236 result = gethostbyname_r(host, &hp->
hp, hp->
buf,
sizeof(hp->
buf), &herrno);
238 if (!
result || !hp->
hp.h_addr_list || !hp->
hp.h_addr_list[0])
241 res = gethostbyname_r(host, &hp->
hp, hp->
buf,
sizeof(hp->
buf), &
result, &herrno);
243 if (res || !
result || !hp->
hp.h_addr_list || !hp->
hp.h_addr_list[0])
253 unsigned char digest[16];
261 for (x = 0; x < 16; x++)
262 ptr += sprintf(ptr,
"%02hhx", digest[x]);
271 uint8_t Message_Digest[20];
279 for (x = 0; x < 20; x++)
280 ptr += sprintf(ptr,
"%02hhx", Message_Digest[x]);
299 unsigned int byte = 0;
300 unsigned int bits = 0;
302 while(*src && *src !=
'=' && (cnt <
max)) {
305 byte |= (
b2a[(int)(*src)]) & 0x3f;
313 *dst = (
byte >> bits) & 0xff;
328 unsigned char *decoded_string;
334 encoded_len = strlen(src);
335 if (encoded_len > 2 && src[encoded_len - 1] ==
'=') {
337 if (src[encoded_len - 2] ==
'=') {
342 decoded_len = (encoded_len / 4 * 3) - padding;
344 if (!decoded_string) {
349 decoded_string[decoded_len] =
'\0';
351 return (
char *)decoded_string;
359 unsigned int byte = 0;
364 while ((cntin < srclen) && (cnt <
max)) {
369 if ((bits == 24) && (cnt + 4 <=
max)) {
370 *dst++ =
base64[(
byte >> 18) & 0x3f];
371 *dst++ =
base64[(
byte >> 12) & 0x3f];
372 *dst++ =
base64[(
byte >> 6) & 0x3f];
373 *dst++ =
base64[
byte & 0x3f];
379 if (linebreaks && (cnt <
max) && (col == 64)) {
385 if (bits && (cnt + 4 <=
max)) {
389 *dst++ =
base64[(
byte >> 18) & 0x3f];
390 *dst++ =
base64[(
byte >> 12) & 0x3f];
392 *dst++ =
base64[(
byte >> 6) & 0x3f];
398 if (linebreaks && (cnt <
max)) {
415 char *encoded_string;
421 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
424 ast_base64encode(encoded_string, (
const unsigned char *)src, strlen(src), encoded_len);
426 return encoded_string;
432 unsigned int byte = 0;
433 unsigned int bits = 0;
435 while (*src && (cnt <
max)) {
437 byte |= (
b2a_url[(int)(*src)]) & 0x3f;
442 *dst = (
byte >> bits) & 0xff;
453 unsigned char *decoded_string;
459 decoded_len = strlen(src) * 3 / 4;
461 if (!decoded_string) {
466 decoded_string[decoded_len] =
'\0';
468 return (
char *)decoded_string;
475 unsigned int byte = 0;
480 while ((cntin < srclen) && (cnt <
max)) {
485 if ((bits == 24) && (cnt + 4 <=
max)) {
495 if (linebreaks && (cnt <
max) && (col == 64)) {
501 if (bits && (cnt + 4 <=
max)) {
510 if (linebreaks && (cnt <
max)) {
526 char *encoded_string;
532 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
537 return encoded_string;
543 memset(
b2a, -1,
sizeof(
b2a));
546 for (x = 0; x < 26; x++) {
555 b2a[
'a' + x] = x + 26;
561 b2a[
'0' + x] = x + 52;
575 #define BASELINELEN 72
576 #define BASEMAXINLINE 256
618 if (!
inbuf(bio, fi)) {
629 static int ochar(
struct baseio *bio,
int c, FILE *so,
const char *endl)
632 if (fputs(endl, so) == EOF) {
639 if (putc(((
unsigned char)
c), so) == EOF) {
650 static const unsigned char dtable[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
651 'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
652 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
653 '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
657 memset(&bio, 0,
sizeof(bio));
661 unsigned char igroup[3], ogroup[4];
664 memset(igroup, 0,
sizeof(igroup));
666 for (n = 0; n < 3; n++) {
667 if ((
c =
inchar(&bio, inputfile)) == EOF) {
672 igroup[n] = (
unsigned char)
c;
676 ogroup[0]= dtable[igroup[0] >> 2];
677 ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
678 ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
679 ogroup[3]= dtable[igroup[2] & 0x3F];
689 for (i = 0; i < 4; i++) {
690 ochar(&bio, ogroup[i], outputfile, endl);
695 if (fputs(endl, outputfile) == EOF) {
707 if (!(fi = fopen(filename,
"rb"))) {
727 const char *mark =
"-_.!~*'()";
728 const char *user_unreserved =
"&=+$,;?/";
730 while (*ptr &&
out - outbuf < buflen - 1) {
736 && strchr(mark, *ptr))
738 && ((*ptr >=
'0' && *ptr <=
'9')
739 || (*ptr >=
'A' && *ptr <=
'Z')
740 || (*ptr >=
'a' && *ptr <=
'z')))
742 && strchr(user_unreserved, *ptr))) {
744 if (
out - outbuf >= buflen - 3) {
747 out += sprintf(
out,
"%%%02hhX", (
unsigned char) *ptr);
767 for (o = s; *s; s++, o++) {
771 }
else if (*s ==
'%' && s[1] !=
'\0' && s[2] !=
'\0' && sscanf(s + 1,
"%2x", &
tmp) == 1) {
785 char *allow =
"\t\v !";
787 while (*ptr &&
out - outbuf < buflen - 1) {
788 if (!(strchr(allow, *ptr))
789 && !(*ptr >=
'#' && *ptr <=
'[')
790 && !(*ptr >=
']' && *ptr <=
'~')
791 && !((
unsigned char) *ptr > 0x7f)) {
793 if (
out - outbuf >= buflen - 2) {
796 out += sprintf(
out,
"\\%c", (
unsigned char) *ptr);
816 if (
string ==
NULL || outbuf ==
NULL) {
821 while (*ptr &&
out - outbuf < buflen - 1) {
823 if (
out - outbuf >= buflen - 2) {
846 int quote_str_len = strlen(quote_str);
848 for (esc_pos = 0, unesc_pos = 0;
849 esc_pos < quote_str_len;
850 esc_pos++, unesc_pos++) {
851 if (quote_str[esc_pos] ==
'\\') {
854 if (esc_pos >= quote_str_len) {
859 quote_str[unesc_pos] = quote_str[esc_pos];
861 quote_str[unesc_pos] =
'\0';
867 char *
end = outbuf + buflen - 1;
876 while (*
string && dst <
end) {
877 const char *entity =
NULL;
924 return *
string ==
'\0' ? 0 : -1;
935 return inet_ntop(AF_INET, &ia,
buf, INET_ADDRSTRLEN);
941 #undef pthread_create
946 #if !defined(LOW_MEMORY)
948 #define AST_MAX_LOCKS 64
951 #undef pthread_mutex_t
952 #undef pthread_mutex_lock
953 #undef pthread_mutex_unlock
954 #undef pthread_mutex_init
955 #undef pthread_mutex_destroy
962 struct thr_lock_info {
966 const char *thread_name;
971 const char *lock_name;
983 } locks[AST_MAX_LOCKS];
987 unsigned int num_locks;
1010 static void lock_info_destroy(
void *data)
1020 for (i = 0; i <
lock_info->num_locks; i++) {
1021 if (
lock_info->locks[i].pending == -1) {
1028 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
1052 int line_num,
const char *func,
const char *lock_name,
void *lock_addr,
struct ast_bt *bt)
1054 #if !defined(LOW_MEMORY)
1063 for (i = 0; i <
lock_info->num_locks; i++) {
1064 if (
lock_info->locks[i].lock_addr == lock_addr) {
1074 if (
lock_info->num_locks == AST_MAX_LOCKS) {
1076 fprintf(stderr,
"XXX ERROR XXX A thread holds more locks than '%d'."
1077 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
1082 if (i &&
lock_info->locks[i - 1].pending == -1) {
1092 lock_info->locks[i].line_num = line_num;
1094 lock_info->locks[i].lock_name = lock_name;
1095 lock_info->locks[i].lock_addr = lock_addr;
1108 void ast_mark_lock_acquired(
void *lock_addr)
1110 #if !defined(LOW_MEMORY)
1126 #if !defined(LOW_MEMORY)
1141 int ast_find_lock_info(
void *lock_addr,
char *filename,
size_t filename_size,
int *lineno,
char *func,
size_t func_size,
char *mutex_name,
size_t mutex_name_size)
1143 #if !defined(LOW_MEMORY)
1152 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1153 if (
lock_info->locks[i].lock_addr == lock_addr)
1176 void ast_suspend_lock_info(
void *lock_addr)
1178 #if !defined(LOW_MEMORY)
1188 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1189 if (
lock_info->locks[i].lock_addr == lock_addr)
1205 void ast_restore_lock_info(
void *lock_addr)
1207 #if !defined(LOW_MEMORY)
1216 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1217 if (
lock_info->locks[i].lock_addr == lock_addr)
1234 void ast_remove_lock_info(
void *lock_addr,
struct ast_bt *bt)
1236 #if !defined(LOW_MEMORY)
1245 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1246 if (
lock_info->locks[i].lock_addr == lock_addr)
1256 if (
lock_info->locks[i].times_locked > 1) {
1265 if (i < lock_info->num_locks - 1) {
1277 #if !defined(LOW_MEMORY)
1293 static void append_backtrace_information(
struct ast_str **
str,
struct ast_bt *bt)
1309 for (frame_iterator = 1; frame_iterator <
AST_VECTOR_SIZE(symbols); ++frame_iterator) {
1320 static void append_lock_information(
struct ast_str **
str,
struct thr_lock_info *
lock_info,
int i)
1327 lock_info->locks[i].pending > 0 ?
"Waiting for " :
1328 lock_info->locks[i].pending < 0 ?
"Tried and failed to get " :
"", i,
1335 lock_info->locks[i].suspended ?
" - suspended" :
"");
1337 append_backtrace_information(
str,
lock_info->locks[i].backtrace);
1349 ast_reentrancy_lock(lt);
1354 ast_reentrancy_unlock(lt);
1377 void ast_log_show_lock(
void *this_lock_addr)
1379 #if !defined(LOW_MEMORY)
1396 if (
lock_info->locks[i].lock_addr == this_lock_addr) {
1410 struct ast_str *ast_dump_locks(
void)
1412 #if !defined(LOW_MEMORY)
1421 "=======================================================================\n"
1423 "=== Currently Held Locks\n"
1424 "=======================================================================\n"
1426 "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
1436 int header_printed = 0;
1444 if (!header_printed) {
1461 if (header_printed) {
1462 ast_str_append(&
str, 0,
"=== -------------------------------------------------------------------\n"
1475 ast_str_append(&
str, 0,
"=======================================================================\n"
1484 #if !defined(LOW_MEMORY)
1491 e->
command =
"core show locks";
1493 "Usage: core show locks\n"
1494 " This command is for lock debugging. It prints out which locks\n"
1495 "are owned by each active thread.\n";
1503 str = ast_dump_locks();
1516 AST_CLI_DEFINE(handle_show_locks,
"Show which locks are held by which thread"),
1521 #if !defined(LOW_MEMORY)
1528 void *(*start_routine)(
void *);
1544 #ifdef DEBUG_THREADS
1546 pthread_mutexattr_t mutex_attr;
1555 pthread_mutexattr_init(&mutex_attr);
1558 pthread_mutexattr_destroy(&mutex_attr);
1574 ret =
a.start_routine(
a.data);
1576 pthread_cleanup_pop(1);
1585 #if !defined(LOW_MEMORY)
1593 void *data,
size_t stacksize,
const char *
file,
const char *caller,
1594 int line,
const char *start_fn)
1596 #if !defined(LOW_MEMORY)
1602 pthread_attr_init(attr);
1605 #if defined(__linux__) || defined(__FreeBSD__)
1613 if ((
errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1620 if ((
errno = pthread_attr_setstacksize(attr, stacksize ? stacksize :
AST_STACKSIZE)))
1623 #if !defined(LOW_MEMORY)
1629 start_fn, line,
file, caller) < 0) {
1641 void *
data,
size_t stacksize,
const char *
file,
const char *caller,
1642 int line,
const char *start_fn)
1644 unsigned char attr_destroy = 0;
1649 pthread_attr_init(attr);
1653 if ((
errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1657 stacksize,
file, caller, line, start_fn);
1660 pthread_attr_destroy(attr);
1667 struct pollfd pfd[1];
1669 memset(pfd, 0,
sizeof(pfd));
1671 pfd[0].events = POLLIN | POLLPRI;
1677 struct pollfd pfd[1];
1679 memset(pfd, 0,
sizeof(pfd));
1681 pfd[0].events = POLLOUT;
1687 struct pollfd pfd = {
1696 while ((res =
ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1700 ast_debug(1,
"Timed out trying to write\n");
1703 }
else if (res == -1) {
1708 if (elapsed >= timeoutms) {
1721 if (elapsed >= timeoutms) {
1749 res = write(fd, s,
len);
1751 if (res < 0 &&
errno != EAGAIN &&
errno != EINTR) {
1753 if (
errno == EPIPE) {
1755 ast_debug(1,
"write() failed due to reading end being closed: %s\n", strerror(
errno));
1774 if (elapsed >= timeoutms) {
1791 if ((q = strchr(beg_quotes, *s)) && *q !=
'\0') {
1792 e = s + strlen(s) - 1;
1793 if (*e == *(end_quotes + (q - beg_quotes))) {
1814 memset(stack, 0,
sizeof(stack));
1816 for(is = st; *is; is++) {
1818 if (*++is !=
'\0') {
1825 if (*is ==
'\'' || *is ==
'"') {
1826 if (*is == stack[inquote]) {
1827 stack[inquote--] =
'\0';
1829 if (++inquote >=
sizeof(stack)) {
1832 stack[inquote] = *is;
1836 if (*is == sep && !inquote) {
1867 while ((e = strchr(work,
';'))) {
1868 if ((e > work) && (*(e-1) ==
'\\')) {
1869 memmove(e - 1, e, strlen(e) + 1);
1887 for (ret = dst = src; (
c = *src++); *dst++ =
c ) {
1890 switch ((
c = *src++)) {
1921 '\a',
'\b',
'\f',
'\n',
'\r',
'\t',
'\v',
'\\',
'\'',
'\"',
'\?',
'\0'
1929 'a',
'b',
'f',
'n',
'r',
't',
'v',
'\\',
'\'',
'"',
'?',
'\0'
1932 char *
ast_escape(
char *dest,
const char *s,
size_t size,
const char *to_escape)
1937 if (!dest || !size) {
1950 for (p = dest; *s && --size; ++s, ++p) {
1952 if (strchr(to_escape, *s)) {
1985 if (!dest || !size) {
1993 for (p = dest; *s && --size; ++s, ++p) {
2026 *size = strlen(s) * 2 + 1;
2050 if (!buffer || !*buffer || !space || !*space)
2053 result = vsnprintf(*buffer, *space, fmt, ap);
2057 else if (
result > *space)
2079 int regex_len = strlen(regex_string);
2083 if ((regex_len >= 1) && (regex_string[0] ==
'/')) {
2084 ast_str_set(regex_pattern, 0,
"%s", regex_string + 1);
2089 if ((regex_len > 1) && (regex_string[regex_len - 1] ==
'/')) {
2103 if (!strcasecmp(s,
"yes") ||
2104 !strcasecmp(s,
"true") ||
2105 !strcasecmp(s,
"y") ||
2106 !strcasecmp(s,
"t") ||
2107 !strcasecmp(s,
"1") ||
2108 !strcasecmp(s,
"on"))
2120 if (!strcasecmp(s,
"no") ||
2121 !strcasecmp(s,
"false") ||
2122 !strcasecmp(s,
"n") ||
2123 !strcasecmp(s,
"f") ||
2124 !strcasecmp(s,
"0") ||
2125 !strcasecmp(s,
"off"))
2131 #define ONE_MILLION 1000000
2136 static struct timeval
tvfix(struct timeval
a)
2140 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2143 }
else if (
a.tv_usec < 0) {
2145 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2151 struct timeval
ast_tvadd(struct timeval
a, struct timeval
b)
2156 a.tv_sec +=
b.tv_sec;
2157 a.tv_usec +=
b.tv_usec;
2165 struct timeval
ast_tvsub(struct timeval
a, struct timeval
b)
2170 a.tv_sec -=
b.tv_sec;
2171 a.tv_usec -=
b.tv_usec;
2172 if (
a.tv_usec < 0) {
2197 int durh, durm, durs;
2198 durh = duration / 3600;
2199 durm = (duration % 3600) / 60;
2200 durs = duration % 60;
2201 snprintf(
buf, length,
"%02d:%02d:%02d", durh, durm, durs);
2217 long int rm = RAND_MAX;
2218 res = res < 0 ? ~res : res;
2252 char *dataPut = start;
2256 for (; *start; start++) {
2258 *dataPut++ = *start;
2261 if (*start ==
'\\') {
2263 }
else if (*start ==
'\'') {
2264 inQuotes = 1 - inQuotes;
2267 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2271 if (start != dataPut)
2284 for (x = 0; ofs <
len && x < size && w[x] ; x++) {
2287 for (src = w[x]; *src && ofs <
len; src++)
2298 char *front, *back, *
buf = res;
2301 front = strtok_r(
buf, delim, &back);
2304 size = strlen(front);
2305 *front = toupper(*front);
2308 front = strtok_r(
NULL, delim, &back);
2317 int ast_get_timeval(
const char *src,
struct timeval *dst,
struct timeval _default,
int *consumed)
2319 long double dtv = 0.0;
2331 if (sscanf(src,
"%30Lf%n", &dtv, &scanned) > 0) {
2333 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2335 *consumed = scanned;
2358 if (sscanf(src,
"%30ld%n", &t, &scanned) == 1) {
2361 *consumed = scanned;
2369 #if defined(HAVE_IP_MTU_DISCOVER)
2370 int val = IP_PMTUDISC_DONT;
2372 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &
val,
sizeof(
val)))
2373 ast_log(
LOG_WARNING,
"Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
2380 int len = strlen(path), count = 0, x, piececount = 0;
2386 for (ptr =
tmp; *ptr; ptr++) {
2392 pieces =
ast_alloca(count *
sizeof(*pieces));
2393 for (ptr =
tmp; *ptr; ptr++) {
2396 pieces[piececount++] = ptr + 1;
2401 for (x = 0; x < piececount; x++) {
2403 strcat(fullpath,
"/");
2404 strcat(fullpath, pieces[x]);
2405 res = mkdir(fullpath, mode);
2406 if (res &&
errno != EEXIST)
2412 static int safe_mkdir(
const char *base_path,
char *path,
int mode)
2416 absolute_path = realpath(path,
NULL);
2418 if (absolute_path) {
2430 char *path_term = strchr(path,
'/');
2432 int parent_is_safe = 0;
2439 char c = *(path_term + 1);
2440 *(path_term + 1) =
'\0';
2441 absolute_subpath = realpath(path,
NULL);
2443 if (absolute_subpath) {
2446 absolute_subpath, base_path);
2447 }
else if (parent_is_safe) {
2450 res = mkdir(path, mode);
2462 *(path_term + 1) =
c;
2464 path_term = strchr(path_term + 1,
'/');
2468 if (!parent_is_safe) {
2473 res = mkdir(path, mode);
2474 if (res != 0 &&
errno != EEXIST) {
2487 if (base_path ==
NULL || path ==
NULL) {
2498 absolute_base_path = realpath(base_path,
NULL);
2499 if (absolute_base_path ==
NULL) {
2503 return safe_mkdir(absolute_base_path, p, mode);
2510 #if defined(DEBUG_THREADS) && !defined(LOW_MEMORY)
2519 #ifdef DEBUG_THREADS
2520 #if !defined(LOW_MEMORY)
2545 {
"username=", &
d->username },
2546 {
"realm=", &
d->realm },
2547 {
"nonce=", &
d->nonce },
2548 {
"uri=", &
d->uri },
2549 {
"domain=", &
d->domain },
2550 {
"response=", &
d->response },
2551 {
"cnonce=", &
d->cnonce },
2552 {
"opaque=", &
d->opaque },
2554 {
"algorithm=",
NULL },
2569 if (strncasecmp(
c,
"Digest ", strlen(
"Digest "))) {
2574 c += strlen(
"Digest ");
2579 for (i =
keys; i->key !=
NULL; i++) {
2580 char *src, *separator;
2582 if (strncasecmp(
c, i->key, strlen(i->key)) != 0) {
2587 c += strlen(i->key);
2604 if (!strcasecmp(i->key,
"algorithm=")) {
2605 if (strcasecmp(src,
"MD5")) {
2610 }
else if (!strcasecmp(i->key,
"qop=") && !strcasecmp(src,
"auth")) {
2612 }
else if (!strcasecmp(i->key,
"nc=")) {
2614 if (sscanf(src,
"%30lx", &u) != 1) {
2624 if (i->key ==
NULL) {
2653 #if defined (__linux) && defined(SYS_gettid)
2654 ret = syscall(SYS_gettid);
2655 #elif defined(__sun)
2656 ret = pthread_self();
2657 #elif defined(__APPLE__)
2658 ret = mach_thread_self();
2659 mach_port_deallocate(mach_task_self(), ret);
2660 #elif defined(__FreeBSD__) && defined(HAVE_SYS_THR_H)
2664 #elif defined(__NetBSD__)
2672 const char *envPATH = getenv(
"PATH");
2679 while ((path =
strsep(&tpath,
":"))) {
2680 snprintf(fullpath, fullpath_size,
"%s/%s", path, binary);
2681 if (!stat(fullpath, &unused)) {
2690 int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
2692 if (udp6_socket < 0) {
2702 #if defined(DO_CRASH)
2718 fprintf(stderr,
"FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
2719 condition_str, condition, line,
function,
file);
2721 condition_str, condition);
2740 if (s && (maxlen > 0)) {
2744 for (x = 0; x < 5; x++) {
2745 sprintf(s,
"%02hhx:", eid->
eid[x]);
2748 sprintf(s,
"%02hhx", eid->
eid[5]);
2753 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Darwin__)
2754 #include <ifaddrs.h>
2755 #include <net/if_dl.h>
2759 struct ifaddrs *ifap, *ifaphead;
2761 const struct sockaddr_dl *sdl;
2765 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2766 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2768 rtnerr = getifaddrs(&ifaphead);
2771 "You will have to set it manually.\n");
2777 "You will have to set it manually.\n");
2781 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
2782 if (ifap->ifa_addr->sa_family != AF_LINK) {
2786 sdl = (
const struct sockaddr_dl *) ifap->ifa_addr;
2787 ap = ((caddr_t) ((sdl)->sdl_data + (sdl)->sdl_nlen));
2788 alen = sdl->sdl_alen;
2789 if (alen != 6 || !(memcmp(ap, &empty_mac, 6) && memcmp(ap, &full_mac, 6))) {
2793 memcpy(eid, ap,
sizeof(*eid));
2794 ast_debug(1,
"Seeding global EID '%s'\n",
2796 freeifaddrs(ifaphead);
2801 "You will have to set it manually.\n");
2802 freeifaddrs(ifaphead);
2807 #elif defined(SOLARIS)
2808 #include <sys/sockio.h>
2809 #include <net/if_arp.h>
2815 struct lifreq *ifr =
NULL;
2819 struct sockaddr_in *sa, *sa2;
2823 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2824 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2826 s = socket(AF_INET, SOCK_STREAM, 0);
2829 " You will have to set it manually.\n");
2834 ifn.lifn_family = AF_UNSPEC;
2837 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
2839 " You will have to set it manually.\n");
2844 bufsz = ifn.lifn_count *
sizeof(
struct lifreq);
2847 "You will have to set it manually.\n");
2851 memset(
buf, 0, bufsz);
2854 ifc.lifc_len = bufsz;
2856 ifc.lifc_family = AF_UNSPEC;
2858 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
2860 "You will have to set it manually.\n");
2866 for (ifr = (
struct lifreq *)
buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
2869 sa = (
struct sockaddr_in *)&(ifr->lifr_addr);
2870 sa2 = (
struct sockaddr_in *)&(ar.arp_pa);
2873 if(ioctl(s, SIOCGARP, &ar) >= 0) {
2874 p = (
unsigned char *)&(ar.arp_ha.sa_data);
2875 if (!(memcmp(p, &empty_mac, 6) && memcmp(p, &full_mac, 6))) {
2879 memcpy(eid, p,
sizeof(*eid));
2880 ast_debug(1,
"Seeding global EID '%s'\n",
2889 "You will have to set it manually.\n");
2906 int bufsz, num_interfaces;
2907 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2908 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2910 s = socket(AF_INET, SOCK_STREAM, 0);
2913 "You will have to set it manually.\n");
2919 if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
2921 "You will have to set it manually.\n");
2925 bufsz = ifc.ifc_len;
2929 "You will have to set it manually.\n");
2935 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
2936 ast_log(
LOG_WARNING,
"Unable to retrieve ethernet interfaces for seeding global EID. "
2937 "You will have to set it manually.\n");
2944 num_interfaces = ifc.ifc_len /
sizeof(*ifr);
2946 for (i = 0; i < num_interfaces; i++) {
2948 if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
2949 unsigned char *hwaddr = (
unsigned char *) ifr->ifr_hwaddr.sa_data;
2951 if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
2955 memcpy(eid, hwaddr,
sizeof(*eid));
2956 ast_debug(1,
"Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
2965 "You will have to set it manually.\n");
2975 unsigned int eid_int[6];
2978 if (sscanf(s,
"%2x:%2x:%2x:%2x:%2x:%2x", &eid_int[0], &eid_int[1], &eid_int[2],
2979 &eid_int[3], &eid_int[4], &eid_int[5]) != 6) {
2983 for (x = 0; x < 6; x++) {
2984 eid->
eid[x] = eid_int[x];
2992 return memcmp(eid1, eid2,
sizeof(*eid1));
3005 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3006 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3007 #define eaccess euidaccess
3009 return eaccess(filename, R_OK) == 0;
3011 int fd = open(filename, O_RDONLY | O_NONBLOCK);
3022 unsigned int major[2] = { 0 };
3023 unsigned int minor[2] = { 0 };
3024 unsigned int patch[2] = { 0 };
3025 unsigned int extra[2] = { 0 };
3028 sscanf(version1,
"%u.%u.%u.%u", &major[0], &minor[0], &patch[0], &extra[0]);
3029 sscanf(version2,
"%u.%u.%u.%u", &major[1], &minor[1], &patch[1], &extra[1]);
3031 res = major[0] - major[1];
3035 res = minor[0] - minor[1];
3039 res = patch[0] - patch[1];
3043 return extra[0] - extra[1];
3047 const char *
file,
int lineno,
const char *
function)
3051 f = fcntl(fd, F_GETFL);
3054 "Failed to get fcntl() flags for file descriptor: %s\n", strerror(
errno));
3060 if ((f & flags) == flags) {
3078 f = fcntl(fd, F_SETFL, f);
3081 "Failed to set fcntl() flags for file descriptor: %s\n", strerror(
errno));
3088 #ifndef HAVE_SOCK_NONBLOCK
3108 int p = pipe(filedes);
3131 int *thread_user_interface;
3135 if (thread_user_interface ==
NULL) {
3136 ast_log(
LOG_ERROR,
"Error setting user interface status for current thread\n");
3140 *thread_user_interface = !!is_user_interface;
3146 int *thread_user_interface;
3150 if (thread_user_interface ==
NULL) {
3156 return *thread_user_interface;
static int input(yyscan_t yyscanner)
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
void ast_std_free(void *ptr)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ast_bt_free_symbols(string_vector)
#define ast_bt_get_symbols(addresses, num_frames)
static int request(void *obj)
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_mark_lock_failed(void *lock_addr)
static const struct ast_datastore_info lock_info
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
I/O Management (derived from Cheops-NG)
A set of macros to manage forward-linked lists.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Asterisk locking-related definitions:
#define pthread_mutex_lock
#define ast_mutex_unlock(a)
#define pthread_mutex_unlock
#define pthread_mutex_destroy
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
#define pthread_mutex_init
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
int ast_base64url_encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
Same as ast_base64encode_full but for base64 URL.
int ast_base64_encode_file(FILE *inputfile, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
int ast_base64decode(unsigned char *dst, const char *src, int max)
decode BASE64 encoded text
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
char * ast_unescape_semicolon(char *s)
Strip backslash for "escaped" semicolons, the string to be stripped (will be modified).
static char base64url[64]
char * ast_escape_alloc(const char *s, const char *to_escape)
Escape the 'to_escape' characters in the given string.
static int dev_urandom_fd
int ast_xml_escape(const char *string, char *const outbuf, const size_t buflen)
Escape reserved characters for use in XML.
static struct ast_threadstorage thread_user_interface_tl
char * ast_unescape_c(char *src)
Convert some C escape sequences.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
char * ast_process_quotes_and_slashes(char *start, char find, char replace_with)
Process a string to find and replace characters.
char * ast_escape_c(char *dest, const char *s, size_t size)
Escape standard 'C' sequences in the given string.
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, const char *file, int lineno, const char *function)
int ast_background_stacksize(void)
char * ast_base64url_decode_string(const char *src)
Decode string from base64 URL.
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
void ast_set_default_eid(struct ast_eid *eid)
Fill in an ast_eid with the default eid of this machine.
int ast_thread_user_interface_set(int is_user_interface)
Set the current thread's user interface status.
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
const char * ast_inet_ntoa(struct in_addr ia)
ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
int ast_wait_for_input(int fd, int ms)
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
static void utils_shutdown(void)
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
get values from config variables.
char * ast_escape_semicolons(const char *string, char *outbuf, int buflen)
Escape semicolons found in a string.
char * ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
Escape the 'to_escape' characters in the given string.
static void * dummy_start(void *data)
int ast_get_tid(void)
Get current thread ID.
long int ast_random(void)
static void base64_init(void)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
Build a string in a buffer, designed to be called repeatedly.
const struct ast_flags ast_uri_http
int ast_wait_for_output(int fd, int ms)
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
int ast_base64url_decode(unsigned char *dst, const char *src, int max)
Decode data from base64 URL.
int ast_compare_versions(const char *version1, const char *version2)
Compare 2 major.minor.patch.extra version strings.
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64 URL.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
static char * escape_alloc(const char *s, size_t *size)
char * ast_base64url_encode_string(const char *src)
Encode string in base64 URL.
static int safe_mkdir(const char *base_path, char *path, int mode)
char * ast_to_camel_case_delim(const char *s, const char *delim)
Attempts to convert the given string to camel case using the specified delimiter.
int ast_false(const char *s)
Make sure something is false. Determine if a string containing a boolean value is "false"....
static char escape_sequences_map[]
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
encode text to BASE64 coding
char * ast_base64encode_string(const char *src)
Encode to BASE64 and return encoded string.
int ast_true(const char *s)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static struct ast_threadstorage inet_ntoa_buf
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
Produce a 20 byte SHA1 hash of value.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static int ochar(struct baseio *bio, int c, FILE *so, const char *endl)
utility used by base_encode()
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Re-entrant (thread safe) version of gethostbyname that replaces the standard gethostbyname (which is ...
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
char * ast_base64decode_string(const char *src)
Decode BASE64 encoded text and return the string.
static struct timeval tvfix(struct timeval a)
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
char * ast_strsep(char **iss, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
const struct ast_flags ast_uri_sip_user
void ast_md5_hash(char *output, const char *input)
Produce 32 char MD5 hash of value.
int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
void ast_sha1_hash(char *output, const char *input)
Produce 40 char SHA1 hash of value.
int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
Given a string regex_string in the form of "/regex/", convert it into the form of "regex".
const struct ast_flags ast_uri_http_legacy
char * ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
Resolve a binary to a full pathname.
static int wait_for_output(int fd, int timeoutms)
void ast_join_delim(char *s, size_t len, const char *const w[], unsigned int size, char delim)
Join an array of strings into a single string.
static ast_mutex_t randomlock
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
void MD5Init(struct MD5Context *context)
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Wrapper for network related headers, masking differences between various operating systems....
static dundi_eid empty_eid
#define ast_poll(a, b, c)
int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
SHA1Result Returns the resulting 160-bit digest.
int SHA1Input(SHA1Context *, const uint8_t *bytes, unsigned int bytecount)
int SHA1Reset(SHA1Context *)
SHA1Reset.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
const char * ast_string_field
#define ast_string_field_ptr_set(x, ptr, data)
Set a field to a simple string value.
String manipulation functions.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
void * addresses[AST_MAX_BT_FRAMES]
descriptor for a cli entry.
An Entity ID is essentially a MAC address, brief and unique.
Structure used to handle boolean flags.
Lock tracking information.
int lineno[AST_MAX_REENTRANCY]
const char * file[AST_MAX_REENTRANCY]
const char * func[AST_MAX_REENTRANCY]
Structure for mutex and tracking information.
Support for dynamic strings.
String vector definitions.
Structure used for base64 encoding.
unsigned char iobuf[BASEMAXINLINE]
void *(* start_routine)(void *)
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Time-related functions and macros.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_test_flag(p, flag)
#define AST_URI_LEGACY_SPACE
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_URI_SIP_USER_UNRESERVED
#define DO_CRASH_NORETURN
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
#define AST_URI_UNRESERVED
#define AST_STACKSIZE_LOW
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
void ast_register_thread(char *name)
void ast_unregister_thread(void *id)
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.