43 #include <sys/ioctl.h> 49 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__) 50 #include <net/if_dl.h> 153 #define MAX_RESULTS 64 155 #define MAX_PACKET_SIZE 8192 157 #define MAX_WEIGHT 59999 159 #define DUNDI_MODEL_INBOUND (1 << 0) 160 #define DUNDI_MODEL_OUTBOUND (1 << 1) 161 #define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND) 164 #define DUNDI_TIMING_HISTORY 10 176 #define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17) 179 #define DUNDI_SECRET_TIME 15 181 #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME 191 static unsigned int tos = 0;
228 unsigned char data[0];
247 struct timeval start;
316 unsigned char txenckey[256];
317 unsigned char rxenckey[256];
337 struct timeval qualtx;
373 if (!strcasecmp(perm->
name,
"all") || !strcasecmp(perm->
name, cont))
398 if (!strcasecmp(str,
"IAX") || !strcasecmp(str,
"IAX2"))
400 else if (!strcasecmp(str,
"SIP"))
402 else if (!strcasecmp(str,
"H323"))
408 static int dundi_lookup_internal(
struct dundi_result *
result,
int maxret,
struct ast_channel *chan,
const char *dcontext,
const char *
number,
int ttl,
int blockempty,
struct dundi_hint_metadata *md,
int *expiration,
int cybpass,
int modeselect,
dundi_eid *skip,
dundi_eid *avoid[],
int direct[]);
465 memset(&tmp, 0,
sizeof(tmp));
466 memset(&trans, 0,
sizeof(trans));
468 tmp.hdr.strans = h->
dtrans;
469 tmp.hdr.dtrans = h->
strans;
470 tmp.hdr.iseqno = h->
oseqno;
471 tmp.hdr.oseqno = h->
iseqno;
473 tmp.hdr.cmdflags = 0;
474 tmp.pack.h = (
struct dundi_hdr *)tmp.pack.data;
475 tmp.pack.datalen =
sizeof(
struct dundi_hdr);
476 tmp.pack.parent = &trans;
493 tid = (tid % 32766) + 1;
494 }
while (tid != stid);
527 if (!cur && any_peer)
536 unsigned int *fluffy;
538 fluffy = (
unsigned int *)(iv);
571 if (sscanf(buf,
"%30d", &map->
_weight) != 1)
608 dr[anscnt].
eid = *us_eid;
609 ast_eid_to_str(dr[anscnt].eid_str,
sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
629 dr[anscnt].
dest[0] =
'\0';
637 for (x = 0; x < (
sizeof(
tmp) - 1); x++) {
638 tmp[x] = called_number[x];
644 if (strlen(tmp) > strlen(hmd->
exten)) {
671 memset(&ied, 0,
sizeof(ied));
672 memset(&dr, 0,
sizeof(dr));
673 memset(&hmd, 0,
sizeof(hmd));
680 for (x=0;x<ouranswers;x++) {
687 res =
dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers,
NULL, st->
called_context, st->
called_number, st->
ttl, 1, &hmd, &expiration, st->
nocache, 0,
NULL, st->
eids, st->
directs);
692 if ((res < -1) && (!ouranswers))
701 ast_debug(1,
"Our transaction went away!\n");
705 for (x=0;x<ouranswers;x++) {
707 if (dr[x].expiration && (expiration > dr[x].expiration))
730 memset(&ied, 0,
sizeof(ied));
740 ast_debug(1,
"Our transaction went away!\n");
765 memset(&ied, 0,
sizeof(ied));
766 memset(&dei, 0,
sizeof(dei));
767 memset(&hmd, 0,
sizeof(hmd));
770 ast_debug(1,
"Neat, someone look for us!\n");
785 ast_debug(1,
"Our transaction went away!\n");
817 pthread_t lookupthread;
838 for (x=skipfirst;ies->
eids[x];x++) {
840 *st->
eids[x-skipfirst] = *ies->
eids[x];
869 char eidpeer_str[20];
870 char eidroot_str[20];
885 snprintf(key1,
sizeof(key1),
"hint/%s/%s/%s/e%08x", eidpeer_str, hint->
data, req->
dcontext, unaffected ? 0 : req->
crc32);
886 snprintf(key2,
sizeof(key2),
"hint/%s/%s/%s/r%s", eidpeer_str, hint->
data, req->
dcontext, eidroot_str);
889 timeout += expiration;
890 snprintf(data,
sizeof(data),
"%ld|", (
long)(timeout));
893 ast_debug(1,
"Caching hint at '%s'\n", key1);
895 ast_debug(1,
"Caching hint at '%s'\n", key2);
905 char eidpeer_str[20];
906 char eidroot_str[20];
921 snprintf(key1,
sizeof(key1),
"%s/%s/%s/e%08x", eidpeer_str, req->
number, req->
dcontext, unaffected ? 0 : req->
crc32);
922 snprintf(key2,
sizeof(key2),
"%s/%s/%s/r%s", eidpeer_str, req->
number, req->
dcontext, eidroot_str);
925 timeout += expiration;
926 snprintf(data,
sizeof(data),
"%ld|", (
long)(timeout));
929 if (strchr(req->
dr[x].
dest,
'|'))
931 snprintf(data + strlen(data),
sizeof(data) - strlen(data),
"%u/%d/%d/%s/%s|",
955 pthread_t lookupthread;
957 memset(&dr2, 0,
sizeof(dr2));
958 memset(&dr, 0,
sizeof(dr));
959 memset(&hmd, 0,
sizeof(hmd));
1017 if (!strcasecmp(cur->
dcontext, ccontext))
1047 for (x=skipfirst;ies->
eids[x];x++) {
1049 *st->
eids[x-skipfirst] = *ies->
eids[x];
1057 if (!strcasecmp(cur->
dcontext, ccontext)) {
1072 memset(&ied, 0,
sizeof(ied));
1079 memset(&ied, 0,
sizeof(ied));
1098 pthread_t lookupthread;
1102 if (!strcasecmp(cur->
dcontext, ccontext))
1130 for (x=skipfirst;ies->
eids[x];x++) {
1132 *st->
eids[x-skipfirst] = *ies->
eids[x];
1140 if (!strcasecmp(cur->
dcontext, ccontext)) {
1155 memset(&ied, 0,
sizeof(ied));
1162 memset(&ied, 0,
sizeof(ied));
1173 char *ptr, *term, *src;
1182 if (!
ast_db_get(
"dundi/cache", key, data,
sizeof(data))) {
1186 int expiration = timeout - now;
1187 if (expiration > 0) {
1188 ast_debug(1,
"Found cache expiring in %d seconds!\n", expiration);
1190 while((sscanf(ptr,
"%30d/%30d/%30d/%n", (
int *)&(flags.
flags), &weight, &tech, &length) == 3)) {
1192 term = strchr(ptr,
'|');
1195 src = strrchr(ptr,
'/');
1201 ast_debug(1,
"Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
1206 !strcmp(req->
dr[z].
dest, ptr))
1224 }
else if (req->
dr[z].
weight > weight)
1230 if (expiration < *lowexpiration)
1231 *lowexpiration = expiration;
1245 char eidroot_str[20];
1249 char eid_str_full[20];
1252 char key[
sizeof(eid_str) +
sizeof(tmp) +
sizeof(req->
dcontext) +
sizeof(eidroot_str) +
sizeof(
"hint////r")];
1259 snprintf(key,
sizeof(key),
"%s/%s/%s/e%08x", eid_str, req->
number, req->
dcontext, crc);
1261 snprintf(key,
sizeof(key),
"%s/%s/%s/e%08x", eid_str, req->
number, req->
dcontext, (
unsigned)0);
1263 snprintf(key,
sizeof(key),
"%s/%s/%s/r%s", eid_str, req->
number, req->
dcontext, eidroot_str);
1270 if (!(tmp[x] = req->
number[x]))
1274 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/e%08x", eid_str, tmp, req->
dcontext, crc);
1276 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/e%08x", eid_str, tmp, req->
dcontext, (
unsigned)0);
1278 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/r%s", eid_str, tmp, req->
dcontext, eidroot_str);
1281 if (strlen(tmp) > strlen(req->
hmd->
exten)) {
1336 unsigned char key[16];
1346 ast_log(
LOG_NOTICE,
"No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
1352 ast_log(
LOG_NOTICE,
"No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
1375 unsigned char curblock[16];
1377 memcpy(curblock, iv,
sizeof(curblock));
1380 curblock[x] ^= src[x];
1382 memcpy(curblock, dst,
sizeof(curblock));
1391 unsigned char lastblock[16];
1393 memcpy(lastblock, iv,
sizeof(lastblock));
1397 dst[x] ^= lastblock[x];
1398 memcpy(lastblock, src,
sizeof(lastblock));
1408 int space = *dstlen;
1409 unsigned long bytes;
1411 unsigned char *decrypt_space;
1418 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
1419 ast_debug(1,
"Ouch, uncompress failed :(\n");
1423 *dstlen = bytes + 6;
1430 unsigned char *compress_space;
1433 unsigned long bytes;
1436 unsigned char iv[16];
1439 memset(compress_space, 0, len);
1442 res = compress(compress_space, &bytes, pack->
data + 6, pack->
datalen - 6);
1444 ast_debug(1,
"Ouch, compression failed!\n");
1447 memset(&ied, 0,
sizeof(ied));
1477 if ((ied.
pos + bytes) >=
sizeof(ied.
buf)) {
1482 ied.
pos += ((bytes + 15) / 16) * 16;
1492 static int check_key(
struct dundi_peer *peer,
unsigned char *newkey,
unsigned char *newsig, uint32_t keycrc32)
1494 unsigned char dst[128];
1502 }
else if (!newkey || !newsig)
1504 if (!memcmp(peer->
rxenckey, newkey, 128) &&
1505 !memcmp(peer->
rxenckey + 128, newsig, 128)) {
1536 ast_debug(1,
"Wow, new key combo passed signature and decrypt!\n");
1537 memcpy(peer->
rxenckey, newkey, 128);
1538 memcpy(peer->
rxenckey + 128, newsig, 128);
1549 *peer_dst = *peer_src;
1562 memset(&peer_dst->
permit, 0,
sizeof(peer_dst->
permit));
1566 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(cur->
name) + 1)))
1576 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(cur->
name) + 1)))
1589 int final = hdr->
cmdresp & 0x80;
1590 int cmd = hdr->
cmdresp & 0x7f;
1595 unsigned char *bufcpy;
1619 memcpy(bufcpy, hdr->
ies, datalen);
1620 ast_debug(1,
"Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->
oseqno, datalen,
final ?
" (Final)" :
"");
1623 goto return_cleanup;
1644 if (strlen(peer->
inkey)) {
1645 hasauth = encrypted;
1695 if (any_peer && peer == any_peer) {
1710 if (!peer || !peer->
dynamic) {
1717 hasauth = encrypted;
1729 ast_verb(3,
"Registered DUNDi peer '%s' at '%s'\n",
1745 if (ies.
cause < 1) {
1749 authpass = encrypted;
1829 if (ies.
cause < 1) {
1831 ast_debug(1,
"Looks like success of some sort (%d)\n", ies.
cause);
1833 authpass = encrypted;
1882 if (ies.
cause < 1) {
1886 hasauth = encrypted;
1934 memset(&ies, 0,
sizeof(ies));
1937 memset(ied, 0,
sizeof(*ied));
1970 ddatalen =
sizeof(decoded);
1981 ast_debug(1,
"Ouch, decrypt failed :(\n");
2027 if ((pack->
h->
oseqno + 1) % 255 == iseqno) {
2078 ast_debug(1,
"Dropping packet out of window!\n");
2090 res =
ast_recvfrom(*((
int *)sock), buf,
sizeof(buf), 0, &sin);
2092 if (
errno != ECONNREFUSED)
2112 unsigned char tmp[16];
2118 while((s = strchr(secret,
';'))) *s =
'+';
2119 while((s = strchr(secret,
'/'))) *s =
'+';
2120 while((s = strchr(secret,
':'))) *s =
'+';
2121 while((s = strchr(secret,
'@'))) *s =
'+';
2129 snprintf(tmp,
sizeof(tmp),
"%s;%s", oldkey, newkey);
2131 snprintf(tmp,
sizeof(tmp),
"%s", newkey);
2134 snprintf(tmp,
sizeof(tmp),
"%d", (
int)rotatetime);
2145 ast_db_get(secretpath,
"secretexpiry", tmp,
sizeof(tmp));
2147 ast_db_get(secretpath,
"secret", tmp,
sizeof(tmp));
2148 current = strchr(tmp,
';');
2155 if ((time(
NULL) - expired) < 0) {
2169 rotatetime = expired;
2184 printf(
"%ld/%ld\n", now, rotatetime);
2186 if ((now - rotatetime) >= 0) {
2201 int *socket_read_id2 =
NULL;
2202 if (netsocket2 >= 0) {
2206 while (!dundi_shutdown) {
2208 if ((res > 1000) || (res < 0))
2221 if (socket_read_id2) {
2231 int striplen =
sizeof(
"/dundi/cache");
2234 while (!dundi_shutdown) {
2235 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
NULL);
2240 for (; db_entry; db_entry = db_entry->
next) {
2245 ast_debug(1,
"clearing expired DUNDI cache entry: %s\n", db_entry->
key);
2252 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,
NULL);
2253 pthread_testcancel();
2255 pthread_testcancel();
2269 while (!dundi_shutdown) {
2308 e->
command =
"dundi set debug {on|off}";
2310 "Usage: dundi set debug {on|off}\n" 2311 " Enables/Disables dumping of DUNDi packets for debugging purposes\n";
2320 if (!strncasecmp(a->
argv[e->
args -1],
"on", 2)) {
2322 ast_cli(a->
fd,
"DUNDi Debugging Enabled\n");
2325 ast_cli(a->
fd,
"DUNDi Debugging Disabled\n");
2334 e->
command =
"dundi store history {on|off}";
2336 "Usage: dundi store history {on|off}\n" 2337 " Enables/Disables storing of DUNDi requests and times for debugging\n" 2347 if (!strncasecmp(a->
argv[e->
args -1],
"on", 2)) {
2348 global_storehistory = 1;
2349 ast_cli(a->
fd,
"DUNDi History Storage Enabled\n");
2351 global_storehistory = 0;
2352 ast_cli(a->
fd,
"DUNDi History Storage Disabled\n");
2362 e->
command =
"dundi flush [stats]";
2364 "Usage: dundi flush [stats]\n" 2365 " Flushes DUNDi answer cache, used primarily for debug. If\n" 2366 "'stats' is present, clears timer statistics instead of normal\n" 2372 if ((a->
argc < 2) || (a->
argc > 3)) {
2376 if (!strcasecmp(a->
argv[2],
"stats")) {
2398 ast_cli(a->
fd,
"DUNDi Cache Flushed\n");
2430 if (!strncasecmp(word, s,
len) && ++which > state) {
2453 qsort(results, count,
sizeof(results[0]),
rescomp);
2465 struct timeval start;
2470 "Usage: dundi lookup <number>[@context] [bypass]\n" 2471 " Lookup the given number within the given DUNDi context\n" 2472 "(or e164 if none is specified). Bypasses cache if 'bypass'\n" 2473 "keyword is specified.\n";
2479 if ((a->
argc < 3) || (a->
argc > 4)) {
2483 if (!strcasecmp(a->
argv[3],
"bypass")) {
2490 context = strchr(tmp,
'@');
2499 ast_cli(a->
fd,
"DUNDi lookup returned error.\n");
2501 ast_cli(a->
fd,
"DUNDi lookup returned no results.\n");
2504 for (x=0;x<res;x++) {
2517 struct timeval start;
2520 e->
command =
"dundi precache";
2522 "Usage: dundi precache <number>[@context]\n" 2523 " Lookup the given number within the given DUNDi context\n" 2524 "(or e164 if none is specified) and precaches the results to any\n" 2525 "upstream DUNDi push servers.\n";
2530 if ((a->
argc < 3) || (a->
argc > 3)) {
2534 context = strchr(tmp,
'@');
2543 ast_cli(a->
fd,
"DUNDi precache returned error.\n");
2545 ast_cli(a->
fd,
"DUNDi precache returned no error.\n");
2561 "Usage: dundi query <entity>[@context]\n" 2562 " Attempts to retrieve contact information for a specific\n" 2563 "DUNDi entity identifier (EID) within a given DUNDi context (or\n" 2564 "e164 if none is specified).\n";
2569 if ((a->
argc < 3) || (a->
argc > 3)) {
2577 context = strchr(tmp,
'@');
2584 ast_cli(a->
fd,
"DUNDi Query EID returned error.\n");
2586 ast_cli(a->
fd,
"DUNDi Query EID returned no results.\n");
2588 ast_cli(a->
fd,
"DUNDi Query EID succeeded:\n");
2604 return "(Unspecified)";
2630 e->
command =
"dundi show peer";
2632 "Usage: dundi show peer [peer]\n" 2633 " Provide a detailed description of a specifid DUNDi peer.\n";
2647 switch(peer->
order) {
2652 order =
"Secondary";
2658 order =
"Quartiary";
2684 ast_cli(a->
fd,
"Last few query times:\n");
2699 #define FORMAT2 "%-20.20s %-41s %-6.6s %-10.10s %-8.8s %-15.15s\n" 2700 #define FORMAT "%-20.20s %-41s %s %-6d %-10.10s %-8.8s %-15.15s\n" 2702 int registeredonly=0;
2705 int online_peers = 0;
2706 int offline_peers = 0;
2707 int unmonitored_peers = 0;
2708 int total_peers = 0;
2711 e->
command =
"dundi show peers [registered|include|exclude|begin]";
2713 "Usage: dundi show peers [registered|include|exclude|begin]\n" 2714 " Lists all known DUNDi peers.\n" 2715 " If 'registered' is present, only registered peers are shown.\n";
2721 if ((a->
argc != 3) && (a->
argc != 4) && (a->
argc != 5)) {
2724 if ((a->
argc == 4)) {
2725 if (!strcasecmp(a->
argv[3],
"registered")) {
2732 ast_cli(a->
fd,
FORMAT2,
"EID",
"Host",
"Port",
"Model",
"AvgTime",
"Status");
2735 int print_line = -1;
2744 strcpy(status,
"UNREACHABLE");
2748 snprintf(status,
sizeof(status),
"LAGGED (%d ms)", peer->
lastms);
2752 snprintf(status,
sizeof(status),
"OK (%d ms)", peer->
lastms);
2756 strcpy(status,
"UNKNOWN");
2760 strcpy(status,
"Unmonitored");
2761 unmonitored_peers++;
2764 snprintf(avgms,
sizeof(avgms),
"%d ms", peer->
avgms);
2766 strcpy(avgms,
"Unavail");
2772 if (!strcasecmp(a->
argv[3],
"include") && strstr(srch,a->
argv[4])) {
2774 }
else if (!strcasecmp(a->
argv[3],
"exclude") && !strstr(srch,a->
argv[4])) {
2776 }
else if (!strcasecmp(a->
argv[3],
"begin") && !strncasecmp(srch,a->
argv[4],strlen(a->
argv[4]))) {
2789 ast_cli(a->
fd,
"%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
2798 #define FORMAT2 "%-47s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" 2799 #define FORMAT "%-41s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" 2803 e->
command =
"dundi show trans";
2805 "Usage: dundi show trans\n" 2806 " Lists all known DUNDi transactions.\n";
2832 e->
command =
"dundi show entityid";
2834 "Usage: dundi show entityid\n" 2835 " Displays the global entityid for this host.\n";
2846 ast_cli(a->
fd,
"Global EID for this system is '%s'\n", eid_str);
2852 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" 2853 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" 2858 e->
command =
"dundi show requests";
2860 "Usage: dundi show requests\n" 2861 " Lists all known pending DUNDi requests.\n";
2885 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 2886 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 2892 e->
command =
"dundi show mappings";
2894 "Usage: dundi show mappings\n" 2895 " Lists all known DUNDi mappings.\n";
2904 ast_cli(a->
fd,
FORMAT2,
"DUNDi Cntxt",
"Weight",
"Local Cntxt",
"Options",
"Tech",
"Destination");
2919 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" 2920 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" 2926 e->
command =
"dundi show precache";
2928 "Usage: dundi show precache\n" 2929 " Lists all known DUNDi scheduled precache updates.\n";
2957 #define FORMAT2 "%-12.12s %-16.16s %-10.10s %-18s %-7s %s\n" 2958 #define FORMAT "%-12.12s %-16.16s %6d sec %-18s %-7d %s/%s (%s)\n" 2963 char src_eid_str[20];
2964 int expiry, tech,
weight;
2968 char *ptr, *term, *src, *number, *
context, *dst;
2972 e->
command =
"dundi show cache";
2974 "Usage: dundi show cache\n" 2975 " Lists all DUNDi cache entries.\n";
2987 ast_cli(a->
fd,
FORMAT2,
"Number",
"Context",
"Expiration",
"From",
"Weight",
"Destination (Flags)");
2988 for (db_entry = db_tree; db_entry; db_entry = db_entry->
next) {
2991 if ((strncmp(db_entry->
key,
"/dundi/cache/hint/", 18) == 0) ||
ast_get_time_t(db_entry->
data, &ts, 0, &length)) {
3001 ptr = db_entry->
key +
sizeof(
"/dundi/cache");
3002 strtok_r(ptr,
"/", &rest);
3003 number = strtok_r(
NULL,
"/", &rest);
3004 context = strtok_r(
NULL,
"/", &rest);
3005 ptr = strtok_r(
NULL,
"/", &rest);
3011 ptr = db_entry->
data + length + 1;
3013 if ((sscanf(ptr,
"%30u/%30d/%30d/%n", &(flags.
flags), &weight, &tech, &length) != 3)) {
3019 term = strchr(ptr,
'|');
3029 src = strrchr(ptr,
'/');
3039 ast_cli(a->
fd,
FORMAT, number, context, expiry, src_eid_str, weight,
tech2str(tech), dst,
dundi_flags2str(fs,
sizeof(fs), flags.
flags));
3042 ast_cli(a->
fd,
"Number of entries: %d\n", cnt);
3052 #define FORMAT2 "%-12.12s %-16.16s %-10.10s %-18s\n" 3053 #define FORMAT "%-12.12s %-16.16s %6d sec %-18s\n" 3058 char src_eid_str[20];
3061 char *ptr, *src, *number, *
context;
3065 e->
command =
"dundi show hints";
3067 "Usage: dundi show hints\n" 3068 " Lists all DUNDi 'DONTASK' hints in the cache.\n";
3082 for (db_entry = db_tree; db_entry; db_entry = db_entry->
next) {
3095 ptr = db_entry->
key +
sizeof(
"/dundi/cache/hint");
3096 src = strtok_r(ptr,
"/", &rest);
3097 number = strtok_r(
NULL,
"/", &rest);
3098 context = strtok_r(
NULL,
"/", &rest);
3099 ptr = strtok_r(
NULL,
"/", &rest);
3111 ast_cli(a->
fd,
"Number of entries: %d\n", cnt);
3149 if (!(trans =
ast_calloc(1,
sizeof(*trans))))
3152 if (global_storehistory) {
3175 if (netsocket2 < 0) {
3223 if (ms < peer->
maxms) {
3267 if (write(trans->
parent->
pfds[1],
"killa!", 6) < 0) {
3314 len =
sizeof(
struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
3316 if (ast_test_flag(trans, FLAG_ENCRYPT))
3320 pack->
h = (
struct dundi_hdr *)(pack->
data);
3333 pack->
datalen =
sizeof(
struct dundi_hdr);
3335 memcpy(pack->
h->
ies, ied->buf, ied->pos);
3421 memset(&ied, 0,
sizeof(ied));
3445 int direct[1] = { 0, };
3452 memset(&hmd, 0,
sizeof(hmd));
3453 memset(&dr, 0,
sizeof(dr));
3455 for (x=0;x<mapcount;x++)
3459 for (x=0;x<ouranswers;x++) {
3465 res =
dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers,
NULL, trans->
parent->
dcontext, trans->
parent->
number, trans->
ttl, 1, &hmd, &expiration, 0, 1, &trans->
them_eid, avoid, direct);
3472 if (ouranswers > 0) {
3473 *foundanswers += ouranswers;
3474 memset(&ied, 0,
sizeof(ied));
3483 for (x=0;x<ouranswers;x++) {
3485 if (dr[x].expiration && (expiration > dr[x].expiration))
3493 if (expiration < *minexp)
3494 *minexp = expiration;
3511 memset(&ied, 0,
sizeof(ied));
3559 ast_debug(1,
"Our transaction went away!\n");
3610 (peer->
order <= order)) {
3667 trans->
eids[x] = *avoid[x];
3700 static void build_transactions(
struct dundi_request *
dr,
int ttl,
int order,
int *foundcache,
int *skipped,
int blockempty,
int nocache,
int modeselect,
dundi_eid *skip,
dundi_eid *avoid[],
int directs[])
3710 if (modeselect == 1) {
3724 if (p->
order <= order) {
3732 for (x=0;avoid[x];x++) {
3735 if (directs && !directs[x])
3751 }
else if (!*skipped || (p->
order < *skipped))
3752 *skipped = p->
order;
3770 ast_debug(1,
"Found existing query for '%s@%s' for '%s' crc '%08x'\n",
3778 ast_debug(1,
"Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n",
3813 uint32_t acrc32 = 0;
3815 for (x=0;avoid[x];x++) {
3818 acrc32 ^=
crc32(0L, (
unsigned char *)avoid[x],
sizeof(
dundi_eid));
3824 static int dundi_lookup_internal(
struct dundi_result *result,
int maxret,
struct ast_channel *chan,
const char *dcontext,
const char *number,
int ttl,
int blockempty,
struct dundi_hint_metadata *hmd,
int *expiration,
int cbypass,
int modeselect,
dundi_eid *skip,
dundi_eid *avoid[],
int direct[])
3836 struct timeval start;
3844 for (x=0;avoid[x];x++)
3847 memset(&dr, 0,
sizeof(dr));
3848 if (pipe(dr.
pfds)) {
3868 ast_debug(1,
"Oooh, duplicate request for '%s@%s' for '%s'\n",
3875 ast_debug(1,
"Waiting for similar request for '%s@%s' for '%s'\n",
3891 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
3930 int direct[1] = { 0, };
3932 memset(&hmd, 0,
sizeof(hmd));
3934 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0,
NULL, avoid, direct);
3943 if (!strcmp(number, qe->
number) && !strcasecmp(context, qe->
context)) {
3950 int len =
sizeof(*qe);
3951 int num_len = strlen(number) + 1;
3952 int context_len = strlen(context) + 1;
3953 if (!(qe =
ast_calloc(1, len + num_len + context_len))) {
3957 strcpy(qe->
number, number);
4001 struct timeval start;
4005 int foundcache, skipped, ttlms, ms;
4008 ast_debug(1,
"Precache internal (%s@%s)!\n", number, context);
4012 if (!strcasecmp(cur->dcontext, context))
4019 if (!strcasecmp(cur->dcontext, context))
4020 maps[nummaps++] = *cur;
4028 memset(&dr2, 0,
sizeof(dr2));
4029 memset(&dr, 0,
sizeof(dr));
4030 memset(&hmd, 0,
sizeof(hmd));
4038 if (pipe(dr.
pfds) < 0) {
4042 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1,
NULL, avoids,
NULL);
4054 if (dr.
pfds[0] > -1) {
4061 if (dr.
pfds[0] > -1) {
4083 struct timeval start;
4087 for (x=0;avoid[x];x++)
4090 memset(&dr, 0,
sizeof(dr));
4099 build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0,
NULL, avoid,
NULL);
4125 memset(&hmd, 0,
sizeof(hmd));
4165 args.context =
"e164";
4171 for (x = 0; x < results; x++) {
4173 snprintf(buf, len,
"%s/%s", dr[x].tech, dr[x].dest);
4187 .
name =
"DUNDILOOKUP",
4211 .
type =
"DUNDIQUERY",
4245 args.context =
"e164";
4247 if (!(drds =
ast_calloc(1,
sizeof(*drds)))) {
4252 snprintf(buf, len,
"%u", drds->
id);
4259 datastore->
data = drds;
4275 .
name =
"DUNDIQUERY",
4324 drds = datastore->
data;
4326 if (!strcasecmp(
args.resultnum,
"getnum")) {
4332 if (sscanf(
args.resultnum,
"%30u", &num) != 1) {
4338 if (num && drds->
num_results > 0 && num <= drds->num_results) {
4342 ast_log(
LOG_WARNING,
"Result number %u is not valid for DUNDi query results for ID %s!\n", num,
args.id);
4349 .
name =
"DUNDIRESULT",
4446 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(s) + 1)))
4449 strcpy(perm->
name, s);
4455 #define MAX_OPTS 128 4468 if (!strcasecmp(map->
dcontext, name) &&
4471 (value[strlen(map->
lcontext)] ==
','))))
4481 memset(fields, 0,
sizeof(fields));
4495 }
else if (x >= 4) {
4502 }
else if (!strncmp(fields[1],
"${", 2) && fields[1][strlen(fields[1]) - 1] ==
'}') {
4510 for (y = 4;y < x; y++) {
4511 if (!strcasecmp(fields[y],
"nounsolicited"))
4513 else if (!strcasecmp(fields[y],
"nocomunsolicit"))
4515 else if (!strcasecmp(fields[y],
"residential"))
4517 else if (!strcasecmp(fields[y],
"commercial"))
4519 else if (!strcasecmp(fields[y],
"mobile"))
4521 else if (!strcasecmp(fields[y],
"nopartial"))
4527 ast_log(
LOG_WARNING,
"Expected at least %d arguments in map, but got only %d\n", 4, x);
4545 memset(&ied, 0,
sizeof(ied));
4572 if (peer->
maxms > 0) {
4595 if (!
ast_db_get(
"dundi/dpeers", eid_str, data,
sizeof(data))) {
4612 if (sscanf(c,
"%5d:%30d", &port, &expire) == 2) {
4644 if (!(peer =
ast_calloc(1,
sizeof(*peer)))) {
4660 for (; v; v = v->
next) {
4661 if (!strcasecmp(v->
name,
"inkey")) {
4663 }
else if (!strcasecmp(v->
name,
"outkey")) {
4665 }
else if (!strcasecmp(v->
name,
"port")) {
4666 port = atoi(v->
value);
4667 }
else if (!strcasecmp(v->
name,
"host")) {
4668 if (!strcasecmp(v->
value,
"dynamic")) {
4682 }
else if (!strcasecmp(v->
name,
"ustothem")) {
4687 }
else if (!strcasecmp(v->
name,
"include")) {
4689 }
else if (!strcasecmp(v->
name,
"permit")) {
4691 }
else if (!strcasecmp(v->
name,
"noinclude")) {
4693 }
else if (!strcasecmp(v->
name,
"deny")) {
4695 }
else if (!strcasecmp(v->
name,
"register")) {
4697 }
else if (!strcasecmp(v->
name,
"order")) {
4698 if (!strcasecmp(v->
value,
"primary"))
4700 else if (!strcasecmp(v->
value,
"secondary"))
4702 else if (!strcasecmp(v->
value,
"tertiary"))
4704 else if (!strcasecmp(v->
value,
"quartiary"))
4709 }
else if (!strcasecmp(v->
name,
"qualify")) {
4710 if (!strcasecmp(v->
value,
"no")) {
4712 }
else if (!strcasecmp(v->
value,
"yes")) {
4714 }
else if (sscanf(v->
value,
"%30d", &peer->
maxms) != 1) {
4715 ast_log(
LOG_WARNING,
"Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4719 }
else if (!strcasecmp(v->
name,
"model")) {
4720 if (!strcasecmp(v->
value,
"inbound"))
4722 else if (!strcasecmp(v->
value,
"outbound"))
4724 else if (!strcasecmp(v->
value,
"symmetric"))
4726 else if (!strcasecmp(v->
value,
"none"))
4729 ast_log(
LOG_WARNING,
"Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4732 }
else if (!strcasecmp(v->
name,
"precache")) {
4733 if (!strcasecmp(v->
value,
"inbound"))
4735 else if (!strcasecmp(v->
value,
"outbound"))
4737 else if (!strcasecmp(v->
value,
"symmetric"))
4739 else if (!strcasecmp(v->
value,
"none"))
4742 ast_log(
LOG_WARNING,
"Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4752 (*globalpcmode) |= peer->
pcmodel;
4758 ast_log(
LOG_WARNING,
"Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4762 ast_log(
LOG_WARNING,
"Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4766 ast_log(
LOG_WARNING,
"Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4769 ast_log(
LOG_WARNING,
"Peer '%s' is supposed to have permission for some inbound searches but isn't an inbound peer or outbound precache!\n",
4789 if (!strncasecmp(context,
"macro-", 6)) {
4795 if (!strcasecmp(exten,
"s")) {
4812 res =
dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4813 for (x=0;x<res;x++) {
4817 if (found >= priority)
4838 const char *dundiargs;
4841 if (!strncasecmp(context,
"macro-", 6)) {
4847 if (!strcasecmp(exten,
"s")) {
4864 res =
dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4867 for (x=0;x<res;x++) {
4877 snprintf(req,
sizeof(req),
"%s/%s,,%s", results[x].tech, results[x].dest,
4878 S_OR(dundiargs,
""));
4894 .description =
"DUNDi Discovered Dialplan Switch",
4918 struct addrinfo hints;
4921 memset(&hints, 0,
sizeof(hints));
4929 if (gethostname(hn,
sizeof(hn) - 1) < 0) {
4944 static int last_port = 0;
4946 int globalpcmodel = 0;
4948 char bind_addr[80]={0,};
4949 char bind_addr2[80]={0,};
4967 global_storehistory = 0;
4971 if (!strcasecmp(v->
name,
"port")){
4972 port = atoi(v->
value);
4973 }
else if (!strcasecmp(v->
name,
"bindaddr")) {
4979 }
else if (!strcasecmp(v->
name,
"bindaddr2")) {
4985 }
else if (!strcasecmp(v->
name,
"authdebug")) {
4987 }
else if (!strcasecmp(v->
name,
"ttl")) {
4991 ast_log(
LOG_WARNING,
"'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
4994 }
else if (!strcasecmp(v->
name,
"autokill")) {
4995 if (sscanf(v->
value,
"%30d", &x) == 1) {
4997 global_autokilltimeout = x;
5003 global_autokilltimeout = 0;
5005 }
else if (!strcasecmp(v->
name,
"entityid")) {
5007 global_eid = testeid;
5010 }
else if (!strcasecmp(v->
name,
"tos")) {
5013 }
else if (!strcasecmp(v->
name,
"department")) {
5015 }
else if (!strcasecmp(v->
name,
"organization")) {
5017 }
else if (!strcasecmp(v->
name,
"locality")) {
5019 }
else if (!strcasecmp(v->
name,
"stateprov")) {
5021 }
else if (!strcasecmp(v->
name,
"country")) {
5023 }
else if (!strcasecmp(v->
name,
"email")) {
5025 }
else if (!strcasecmp(v->
name,
"phone")) {
5027 }
else if (!strcasecmp(v->
name,
"storehistory")) {
5029 }
else if (!strcasecmp(v->
name,
"cachetime")) {
5030 if ((sscanf(v->
value,
"%30d", &x) == 1)) {
5031 dundi_cache_time = x;
5033 ast_log(
LOG_WARNING,
"'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
5045 sprintf(bind_addr,
"0.0.0.0:%d", port);
5051 if (last_port == 0) {
5053 }
else if (last_port != port) {
5078 if (strcasecmp(cat,
"general") && strcasecmp(cat,
"mappings")) {
5082 else if (!strcasecmp(cat,
"*")) {
5110 pthread_kill(netthreadid, SIGURG);
5111 pthread_join(netthreadid,
NULL);
5115 pthread_kill(precachethreadid, SIGURG);
5116 pthread_join(precachethreadid,
NULL);
5120 pthread_cancel(clearcachethreadid);
5121 pthread_join(clearcachethreadid,
NULL);
5125 if (netsocket >= 0) {
5129 if (netsocket2 >= 0) {
5138 if (-1 < netsocket) {
5163 if (
set_config(
"dundi.conf", &sin, 1, &sin2))
5181 if (!io || !sched) {
5188 if (
set_config(
"dundi.conf", &sin, 0, &sin2)) {
5194 ast_log(
LOG_ERROR,
"bindaddr & bindaddr2 should be different IP protocols.\n");
5200 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5201 netsocket2 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5202 if (netsocket < 0 || netsocket2 < 0) {
5233 netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5235 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5237 if (netsocket < 0) {
5277 .optional_modules =
"res_crypto",
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
static void dundi_precache_full(void)
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
struct ast_variable * next
static int discover_transactions(struct dundi_request *dr)
int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
Retrieve information on a specific EID.
int ast_unlock_context(struct ast_context *con)
static char * dundi_sockaddr_stringify_host(const struct ast_sockaddr *addr)
#define DUNDI_IE_EXPIRATION
#define ast_channel_lock(chan)
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
#define AST_CLI_DEFINE(fn, txt,...)
static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspec...
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
#define DUNDI_DEFAULT_RETRANS
static char * complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos)
#define AST_LIST_LOCK(head)
Locks a list.
#define DUNDI_IE_EID_DIRECT
Asterisk locking-related definitions:
static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
static const char config_file[]
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define DUNDI_MODEL_SYMMETRIC
char dcontext[AST_MAX_EXTENSION]
Distributed Universal Number Discovery (DUNDi) See also.
static char * dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
char * lookups[DUNDI_TIMING_HISTORY]
const char * ast_get_context_name(struct ast_context *con)
static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
static int reset_transaction(struct dundi_transaction *trans)
static int register_request(struct dundi_request *dr, struct dundi_request **pending)
static struct ast_sched_context * sched
char called_number[AST_MAX_EXTENSION]
static char * dundi_show_requests(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
static void prune_mappings(void)
struct dundi_request * parent
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
static int get_ipaddress(char *ip, size_t size, const char *str, int family)
static char * dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define DUNDI_IE_CACHEBYPASS
static pthread_t precachethreadid
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
char lcontext[AST_MAX_EXTENSION]
#define ast_pthread_create_detached(a, b, c, d)
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
static int dundi_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static void sort_results(struct dundi_result *results, int count)
static char * dundi_show_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static int dundi_cache_time
#define DUNDI_COMMAND_ENCREJ
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
static int do_register_expire(const void *data)
static dundi_eid global_eid
#define ast_test_flag(p, flag)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
struct dundi_entity_info * dei
static void * process_precache(void *ign)
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
static void * dundi_lookup_thread(void *data)
static void destroy_map(struct dundi_mapping *map)
#define ast_clear_flag_nonstd(p, flag)
static void * network_thread(void *ignore)
#define DUNDI_TIMING_HISTORY
static void set_host_ipaddr(struct ast_sockaddr *sin)
dundi_eid eids[DUNDI_MAX_STACK+1]
#define ast_set_flag(p, flag)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
struct dundi_answer * answers[DUNDI_MAX_ANSWERS+1]
static char * tech2str(int tech)
descriptor for a cli entry.
#define DUNDI_DEFAULT_CACHE_TIME
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
dundi_eid * eids[DUNDI_MAX_STACK+1]
#define DUNDI_IE_SHAREDKEY
static int dundi_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Provide cryptographic signature routines.
#define CONFIG_STATUS_FILEINVALID
static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx)
struct dundi_mapping * maps
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
struct dundi_transaction * trans
void dundi_set_error(void(*func)(const char *))
static int start_network_thread(void)
static struct io_context * io
Structure for variables, used for configurations and for channel variables.
unsigned char rxenckey[256]
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
static void cancel_request(struct dundi_request *dr)
static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc, int *lowexpiration)
struct ast_context * ast_walk_contexts(struct ast_context *con)
static void destroy_permissions(struct permissionlist *permlist)
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Structure for a data store type.
static char * dundi_do_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
static const struct adsi_event events[]
static void deep_copy_peer(struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
static char * dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
int ast_rdlock_contexts(void)
Read locks the context list.
#define DUNDI_COMMAND_ENCRYPT
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
int eid_direct[DUNDI_MAX_STACK+1]
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
static void qualify_peer(struct dundi_peer *peer, int schedonly)
#define ast_copy_flags(dest, src, flagz)
static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
void ast_verbose(const char *fmt,...)
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
int lookuptimes[DUNDI_TIMING_HISTORY]
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
static struct dundi_hdr * dundi_decrypt(struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen)
static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[])
struct packetlist lasttrans
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
static void load_password(void)
I/O Management (derived from Cheops-NG)
char dcontext[AST_MAX_EXTENSION]
static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
void ast_cli(int fd, const char *fmt,...)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
static char * dundi_do_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct dundi_transaction::@439 all
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
#define DUNDI_IE_DEPARTMENT
struct dundi_mapping::@442 list
dundi_eid * eids[DUNDI_MAX_STACK+1]
static int do_register(const void *data)
#define DUNDI_COMMAND_ACK
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
Socket address structure.
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
An Entity ID is essentially a MAC address, brief and unique.
#define ast_verb(level,...)
ast_aes_decrypt_key them_dcx
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
static int query_transactions(struct dundi_request *dr)
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
static char secretpath[80]
static int decrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx)
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
#define AST_LIST_INSERT_AFTER(head, listelm, elm, field)
Inserts a list entry after a given entry.
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
struct dundi_mapping * next
int args
This gets set in ast_cli_register()
static int has_permission(struct permissionlist *permlist, char *cont)
#define ast_strlen_zero(foo)
static pthread_t netthreadid
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define ast_pthread_create_background(a, b, c, d)
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Configuration File Parser.
static char * dundi_flush(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
AES_KEY ast_aes_encrypt_key
static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
#define ast_debug(level,...)
Log a DEBUG message.
#define DUNDI_COMMAND_DPRESPONSE
#define DUNDI_IE_LOCALITY
struct ast_db_entry * next
#define ast_config_load(filename, flags)
Load a config file.
#define DUNDI_IE_KEYCRC32
static int dundi_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
#define DUNDI_IE_SIGNATURE
static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
static void save_secret(const char *newkey, const char *oldkey)
static struct dundi_peer * any_peer
Wildcard peer.
General Asterisk PBX channel definitions.
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
#define DUNDI_DEFAULT_TTL
void io_context_destroy(struct io_context *ioc)
Destroys a context.
struct dundi_encblock * encblock
ast_aes_decrypt_key us_dcx
void dundi_set_output(void(*func)(const char *))
#define DUNDI_DEFAULT_RETRANS_TIMER
#define AST_PTHREADT_NULL
#define DUNDI_MODEL_INBOUND
struct sla_ringing_trunk * last
Data structure associated with a custom dialplan function.
Access Control of various sorts.
Global IO variables are now in a struct in order to be made threadsafe.
#define AST_MAX_EXTENSION
Scheduler Routines (derived from cheops)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Asterisk internal frame definitions.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
struct dundi_transaction::@438 parentlist
long int ast_random(void)
static int global_storehistory
static void build_iv(unsigned char *iv)
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
static uint16_t dundi_sockaddr_port(const struct ast_sockaddr *addr)
#define ast_strdupa(s)
duplicate a string in memory from the stack
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
static int get_trans_id(void)
static dundi_eid empty_eid
void AST_OPTIONAL_API_NAME() ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
static int dundi_discover(struct dundi_transaction *trans)
#define ast_malloc(len)
A wrapper for malloc()
#define DUNDI_SECRET_TIME
static int do_autokill(const void *data)
static void destroy_peer(struct dundi_peer *peer)
static int default_expiration
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
struct dundi_transaction::packetlist packets
static char * dundi_store_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static int dundi_query(struct dundi_transaction *trans)
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
static void dundi_debug_output(const char *data)
unsigned char * encsharedkey
const char * ast_channel_exten(const struct ast_channel *chan)
static struct ast_custom_function dundi_function
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
ast_aes_encrypt_key them_ecx
Wrapper for network related headers, masking differences between various operating systems...
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
static char * dundi_show_mappings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dundi_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void reschedule_precache(const char *number, const char *context, int expiration)
static void destroy_packet(struct dundi_packet *pack, int needfree)
static int dundifunc_read(struct ast_channel *chan, const char *cmd, char *num, char *buf, size_t len)
static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
static unsigned long avoid_crc32(dundi_eid *avoid[])
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define DUNDI_COMMAND_UNKNOWN
static unsigned int dundi_result_id
static int dundi_rexmit(const void *data)
static char * dundi_show_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static const struct ast_datastore_info dundi_result_datastore_info
static void unregister_request(struct dundi_request *dr)
static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
char number[AST_MAX_EXTENSION]
static struct dundi_peer * find_peer(dundi_eid *eid)
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static pthread_t clearcachethreadid
static int global_autokilltimeout
int AST_OPTIONAL_API_NAME() ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
encrypt a message
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
int ast_unlock_contexts(void)
Unlocks contexts.
static void check_password(void)
void ast_var_delete(struct ast_var_t *var)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct dundi_transaction * qualtrans
static int load_module(void)
#define DUNDI_IE_CALLED_CONTEXT
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
def ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags, struct ast_sockaddr *src_addr)
Wrapper around recvfrom(2) that uses struct ast_sockaddr.
#define DUNDI_IE_ORGANIZATION
const char * ast_get_extension_name(struct ast_exten *exten)
#define DUNDI_DEFAULT_KEY_EXPIRE
int dundi_precache(const char *context, const char *number)
Pre-cache to push upstream peers.
#define DUNDI_DEFAULT_VERSION
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static int get_mapping_weight(struct dundi_mapping *map, struct varshead *headp)
static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32)
static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[])
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define ast_channel_unlock(chan)
static void parse(struct mgcp_request *req)
static void drds_destroy_cb(void *data)
int directs[DUNDI_MAX_STACK+1]
static void * dundi_precache_thread(void *data)
#define ast_calloc(num, len)
A wrapper for calloc()
static void * dundi_query_thread(void *data)
AES_KEY ast_aes_decrypt_key
struct ast_var_t::@249 entries
int AST_OPTIONAL_API_NAME() ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
signs outgoing message with public key
#define ast_var_assign(name, value)
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
static void abort_request(struct dundi_request *dr)
struct dundi_hint_metadata * hmd
static void build_secret(char *secret, int seclen)
Module could not be loaded properly.
int AST_OPTIONAL_API_NAME() ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
check signature of a message
struct dundi_request::@440 trans
Module has failed to load, may be in an inconsistent state.
static struct ast_cli_entry cli_dundi[]
struct dundi_peer::permissionlist permit
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
static int dundi_shutdown
Structure used to handle boolean flags.
#define ast_clear_flag(p, flag)
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
#define DUNDI_IE_CALLED_NUMBER
#define DUNDI_COMMAND_PRECACHERQ
#define DUNDI_COMMAND_PRECACHERP
static int dundi_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
struct ast_eid ast_eid_default
Global EID.
ast_aes_encrypt_key us_ecx
struct permissionlist include
#define DUNDI_COMMAND_REGREQ
#define DUNDI_COMMAND_FINAL
static void destroy_packets(struct packetlist *p)
static void dundi_reject(struct dundi_hdr *h, struct ast_sockaddr *sin)
static void dundi_error_output(const char *data)
static int update_key(struct dundi_peer *peer)
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
unsigned char txenckey[256]
static int check_request(struct dundi_request *dr)
#define DUNDI_COMMAND_EIDRESPONSE
static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *pack)
static void mark_peers(void)
Standard Command Line Interface.
#define DUNDI_IE_STATE_PROV
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
ast_app: A registered application
const char * ast_channel_name(const struct ast_channel *chan)
int dundi_eid_zero(dundi_eid *eid)
static int str2tech(char *str)
struct dundi_result results[MAX_RESULTS]
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
#define DUNDI_COMMAND_EIDQUERY
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
static int unload_module(void)
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
static void mark_mappings(void)
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
static int ack_trans(struct dundi_transaction *trans, int iseqno)
static int do_qualify(const void *data)
static int socket_read(int *id, int fd, short events, void *sock)
#define DUNDI_COMMAND_INVALID
struct ast_key *AST_OPTIONAL_API_NAME() ast_key_get(const char *kname, int ktype)
return the ast_key structure for name
struct dundi_transaction * regtrans
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
static char cursecret[80]
#define ast_datastore_alloc(info, uid)
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define DUNDI_COMMAND_DPDISCOVER
static void build_mapping(const char *name, const char *value)
static char * dundi_do_lookup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
static int dundi_ack(struct dundi_transaction *trans, int final)
static const struct ast_app_option dundi_query_opts[128]
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
static char context[AST_MAX_CONTEXT]
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
static struct ast_custom_function dundi_query_function
struct dundi_transaction * parent
static struct dundi_transaction * find_transaction(struct dundi_hdr *hdr, struct ast_sockaddr *sin)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
#define ast_set_flag_nonstd(p, flag)
#define ASTERISK_GPL_KEY
The text the key() function should return.
static int optimize_transactions(struct dundi_request *dr, int order)
int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
Asterisk module definitions.
static int dundi_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
static char * dundi_show_entityid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void build_transactions(struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[])
int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Persistant data storage (akin to *doze registry)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
ast_context: An extension context - must remain in sync with fake_context
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
#define ast_custom_function_register(acf)
Register a custom function.
#define DUNDI_COMMAND_NULL
#define DUNDI_MODEL_OUTBOUND
const char * ast_channel_macroexten(const struct ast_channel *chan)
void AST_OPTIONAL_API_NAME() ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
static struct ast_switch dundi_switch
#define ast_test_flag_nonstd(p, flag)
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
static int rescomp(const void *a, const void *b)
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
static void * process_clearcache(void *ignore)
char * dundi_flags2str(char *buf, int bufsiz, int flags)
#define DUNDI_COMMAND_REGRESPONSE
int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
char called_context[AST_MAX_EXTENSION]
static char * model2str(int model)
struct permission::@435 list
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
static void prune_peers(void)
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
static struct ast_custom_function dundi_result_function
static int handle_frame(struct dundi_hdr *h, struct ast_sockaddr *sin, int datalen)
#define AST_APP_ARG(name)
Define an application argument.
int AST_OPTIONAL_API_NAME() ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
decrypt a message
#define DUNDI_COMMAND_CANCEL
static char stateprov[80]
static char * dundi_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dundi_xmit(struct dundi_packet *pack)
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
static void drds_destroy(struct dundi_result_datastore *drds)