34 #include "asterisk/network.h"
35 #include <sys/ioctl.h>
37 #include <sys/signal.h>
41 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__)
42 #include <net/if_dl.h>
145 #define MAX_RESULTS 64
147 #define MAX_PACKET_SIZE 8192
149 #define MAX_WEIGHT 59999
151 #define DUNDI_MODEL_INBOUND (1 << 0)
152 #define DUNDI_MODEL_OUTBOUND (1 << 1)
153 #define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
156 #define DUNDI_TIMING_HISTORY 10
168 #define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17)
171 #define DUNDI_SECRET_TIME 15
173 #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME
182 static unsigned int tos = 0;
219 unsigned char data[0];
237 struct sockaddr_in addr;
238 struct timeval start;
259 struct dundi_request *parent;
264 struct dundi_request {
296 struct sockaddr_in addr;
307 unsigned char txenckey[256];
308 unsigned char rxenckey[256];
309 uint32_t us_keycrc32;
312 uint32_t them_keycrc32;
318 char *lookups[DUNDI_TIMING_HISTORY];
320 struct dundi_transaction *regtrans;
321 struct dundi_transaction *qualtrans;
325 unsigned int dynamic:1;
328 struct timeval qualtx;
345 static
int dundi_xmit(struct dundi_packet *pack);
364 if (!strcasecmp(perm->
name,
"all") || !strcasecmp(perm->
name, cont))
389 if (!strcasecmp(str,
"IAX") || !strcasecmp(str,
"IAX2"))
391 else if (!strcasecmp(str,
"SIP"))
393 else if (!strcasecmp(str,
"H323"))
399 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[]);
404 struct dundi_transaction *trans;
429 memcpy(&trans->
addr, sin,
sizeof(trans->
addr));
438 static int dundi_send(
struct dundi_transaction *trans,
int cmdresp,
int flags,
int final,
struct dundi_ie_data *ied);
440 static int dundi_ack(
struct dundi_transaction *trans,
int final)
447 struct dundi_packet pack;
450 struct dundi_transaction trans;
454 memset(&tmp, 0,
sizeof(tmp));
455 memset(&trans, 0,
sizeof(trans));
456 memcpy(&trans.
addr, sin,
sizeof(trans.
addr));
457 tmp.hdr.strans = h->
dtrans;
458 tmp.hdr.dtrans = h->
strans;
459 tmp.hdr.iseqno = h->
oseqno;
460 tmp.hdr.oseqno = h->
iseqno;
462 tmp.hdr.cmdflags = 0;
463 tmp.pack.h = (
struct dundi_hdr *)tmp.pack.data;
464 tmp.pack.datalen =
sizeof(
struct dundi_hdr);
465 tmp.pack.parent = &trans;
471 struct dundi_transaction *t;
482 tid = (tid % 32766) + 1;
483 }
while (tid != stid);
506 struct dundi_peer *cur = NULL;
525 unsigned int *fluffy;
527 fluffy = (
unsigned int *)(iv);
555 if (sscanf(buf,
"%30d", &map->
_weight) != 1)
593 dr[anscnt].
eid = *us_eid;
594 ast_eid_to_str(dr[anscnt].eid_str,
sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
613 dr[anscnt].
dest[0] =
'\0';
619 for (x = 0; x < (
sizeof(tmp) - 1); x++) {
620 tmp[x] = called_number[x];
626 if (strlen(tmp) > strlen(hmd->
exten)) {
637 static void destroy_trans(
struct dundi_transaction *trans,
int fromtimeout);
653 memset(&ied, 0,
sizeof(ied));
654 memset(&dr, 0,
sizeof(dr));
655 memset(&hmd, 0,
sizeof(hmd));
662 for (x=0;x<ouranswers;x++) {
663 if (dr[x].weight < max)
669 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);
674 if ((res < -1) && (!ouranswers))
683 ast_debug(1,
"Our transaction went away!\n");
687 for (x=0;x<ouranswers;x++) {
689 if (dr[x].expiration && (expiration > dr[x].expiration))
712 memset(&ied, 0,
sizeof(ied));
722 ast_debug(1,
"Our transaction went away!\n");
747 memset(&ied, 0,
sizeof(ied));
748 memset(&dei, 0,
sizeof(dei));
749 memset(&hmd, 0,
sizeof(hmd));
752 ast_debug(1,
"Neat, someone look for us!\n");
767 ast_debug(1,
"Our transaction went away!\n");
799 pthread_t lookupthread;
820 for (x=skipfirst;ies->
eids[x];x++) {
822 *st->
eids[x-skipfirst] = *ies->
eids[x];
851 char eidpeer_str[20];
852 char eidroot_str[20];
867 snprintf(key1,
sizeof(key1),
"hint/%s/%s/%s/e%08x", eidpeer_str, hint->
data, req->
dcontext, unaffected ? 0 : req->
crc32);
868 snprintf(key2,
sizeof(key2),
"hint/%s/%s/%s/r%s", eidpeer_str, hint->
data, req->
dcontext, eidroot_str);
871 timeout += expiration;
872 snprintf(data,
sizeof(data),
"%ld|", (
long)(timeout));
875 ast_debug(1,
"Caching hint at '%s'\n", key1);
877 ast_debug(1,
"Caching hint at '%s'\n", key2);
881 static int cache_save(
dundi_eid *eidpeer,
struct dundi_request *req,
int start,
int unaffected,
int expiration,
int push)
887 char eidpeer_str[20];
888 char eidroot_str[20];
903 snprintf(key1,
sizeof(key1),
"%s/%s/%s/e%08x", eidpeer_str, req->
number, req->
dcontext, unaffected ? 0 : req->
crc32);
904 snprintf(key2,
sizeof(key2),
"%s/%s/%s/r%s", eidpeer_str, req->
number, req->
dcontext, eidroot_str);
907 timeout += expiration;
908 snprintf(data,
sizeof(data),
"%ld|", (
long)(timeout));
911 if (strchr(req->
dr[x].
dest,
'|'))
913 snprintf(data + strlen(data),
sizeof(data) - strlen(data),
"%u/%d/%d/%s/%s|",
930 struct dundi_request dr;
933 struct dundi_mapping *cur;
937 pthread_t lookupthread;
939 memset(&dr2, 0,
sizeof(dr2));
940 memset(&dr, 0,
sizeof(dr));
941 memset(&hmd, 0,
sizeof(hmd));
999 if (!strcasecmp(cur->
dcontext, ccontext))
1017 totallen += mapcount *
sizeof(
struct dundi_mapping);
1029 for (x=skipfirst;ies->
eids[x];x++) {
1031 *st->
eids[x-skipfirst] = *ies->
eids[x];
1037 st->
maps = (
struct dundi_mapping *)s;
1039 if (!strcasecmp(cur->
dcontext, ccontext)) {
1054 memset(&ied, 0,
sizeof(ied));
1061 memset(&ied, 0,
sizeof(ied));
1076 struct dundi_mapping *cur;
1080 pthread_t lookupthread;
1084 if (!strcasecmp(cur->
dcontext, ccontext))
1100 totallen += mapcount *
sizeof(
struct dundi_mapping);
1112 for (x=skipfirst;ies->
eids[x];x++) {
1114 *st->
eids[x-skipfirst] = *ies->
eids[x];
1120 st->
maps = (
struct dundi_mapping *)s;
1122 if (!strcasecmp(cur->
dcontext, ccontext)) {
1137 memset(&ied, 0,
sizeof(ied));
1144 memset(&ied, 0,
sizeof(ied));
1152 static int cache_lookup_internal(time_t now,
struct dundi_request *req,
char *key,
char *eid_str_full,
int *lowexpiration)
1155 char *ptr, *term, *src;
1164 if (!
ast_db_get(
"dundi/cache", key, data,
sizeof(data))) {
1168 int expiration = timeout - now;
1169 if (expiration > 0) {
1170 ast_debug(1,
"Found cache expiring in %d seconds!\n", expiration);
1172 while((sscanf(ptr,
"%30d/%30d/%30d/%n", (
int *)&(flags.
flags), &weight, &tech, &length) == 3)) {
1174 term = strchr(ptr,
'|');
1177 src = strrchr(ptr,
'/');
1183 ast_debug(1,
"Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
1188 !strcmp(req->
dr[z].
dest, ptr))
1206 }
else if (req->
dr[z].
weight > weight)
1212 if (expiration < *lowexpiration)
1213 *lowexpiration = expiration;
1228 char eidroot_str[20];
1232 char eid_str_full[20];
1240 snprintf(key,
sizeof(key),
"%s/%s/%s/e%08x", eid_str, req->
number, req->
dcontext, crc32);
1242 snprintf(key,
sizeof(key),
"%s/%s/%s/e%08x", eid_str, req->
number, req->
dcontext, (
unsigned)0);
1244 snprintf(key,
sizeof(key),
"%s/%s/%s/r%s", eid_str, req->
number, req->
dcontext, eidroot_str);
1251 if (!(tmp[x] = req->
number[x]))
1255 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/e%08x", eid_str, tmp, req->
dcontext, crc32);
1257 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/e%08x", eid_str, tmp, req->
dcontext, (
unsigned)0);
1259 snprintf(key,
sizeof(key),
"hint/%s/%s/%s/r%s", eid_str, tmp, req->
dcontext, eidroot_str);
1262 if (strlen(tmp) > strlen(req->
hmd->
exten)) {
1274 static void qualify_peer(
struct dundi_peer *peer,
int schedonly);
1276 static void apply_peer(
struct dundi_transaction *trans,
struct dundi_peer *p)
1278 if (!trans->
addr.sin_addr.s_addr)
1303 struct dundi_peer *peer = (
struct dundi_peer *)data;
1308 memset(&peer->
addr, 0,
sizeof(peer->
addr));
1314 unsigned char key[16];
1324 ast_log(
LOG_NOTICE,
"No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
1330 ast_log(
LOG_NOTICE,
"No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
1353 unsigned char curblock[16];
1355 memcpy(curblock, iv,
sizeof(curblock));
1358 curblock[x] ^= src[x];
1360 memcpy(curblock, dst,
sizeof(curblock));
1369 unsigned char lastblock[16];
1371 memcpy(lastblock, iv,
sizeof(lastblock));
1375 dst[x] ^= lastblock[x];
1376 memcpy(lastblock, src,
sizeof(lastblock));
1386 int space = *dstlen;
1387 unsigned long bytes;
1389 unsigned char *decrypt_space;
1396 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
1397 ast_debug(1,
"Ouch, uncompress failed :(\n");
1401 *dstlen = bytes + 6;
1406 static int dundi_encrypt(
struct dundi_transaction *trans,
struct dundi_packet *pack)
1408 unsigned char *compress_space;
1411 unsigned long bytes;
1413 struct dundi_peer *peer;
1414 unsigned char iv[16];
1417 memset(compress_space, 0, len);
1420 res = compress(compress_space, &bytes, pack->
data + 6, pack->
datalen - 6);
1422 ast_debug(1,
"Ouch, compression failed!\n");
1425 memset(&ied, 0,
sizeof(ied));
1455 if ((ied.
pos + bytes) >=
sizeof(ied.
buf)) {
1460 ied.
pos += ((bytes + 15) / 16) * 16;
1470 static int check_key(
struct dundi_peer *peer,
unsigned char *newkey,
unsigned char *newsig, uint32_t keycrc32)
1472 unsigned char dst[128];
1480 }
else if (!newkey || !newsig)
1482 if (!memcmp(peer->
rxenckey, newkey, 128) &&
1483 !memcmp(peer->
rxenckey + 128, newsig, 128)) {
1514 ast_debug(1,
"Wow, new key combo passed signature and decrypt!\n");
1515 memcpy(peer->
rxenckey, newkey, 128);
1516 memcpy(peer->
rxenckey + 128, newsig, 128);
1523 static void deep_copy_peer(
struct dundi_peer *peer_dst,
const struct dundi_peer *peer_src)
1527 memcpy(peer_dst, peer_src,
sizeof(*peer_dst));
1529 memset(&peer_dst->
permit, 0,
sizeof(peer_dst->
permit));
1533 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(cur->
name) + 1)))
1543 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(cur->
name) + 1)))
1556 int final = hdr->
cmdresp & 0x80;
1557 int cmd = hdr->
cmdresp & 0x7f;
1562 unsigned char *bufcpy;
1574 struct dundi_peer *peer = NULL;
1586 memcpy(bufcpy, hdr->
ies, datalen);
1587 ast_debug(1,
"Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->
oseqno, datalen,
final ?
" (Final)" :
"");
1590 goto return_cleanup;
1611 if (strlen(peer->
inkey)) {
1612 hasauth = encrypted;
1677 if (!peer || !peer->
dynamic) {
1684 hasauth = encrypted;
1694 ntohs(trans->
addr.sin_port), expire);
1697 ast_verb(3,
"Registered DUNDi peer '%s' at '%s:%d'\n",
1713 if (ies.
cause < 1) {
1717 authpass = encrypted;
1797 if (ies.
cause < 1) {
1799 ast_debug(1,
"Looks like success of some sort (%d)\n", ies.
cause);
1801 authpass = encrypted;
1850 if (ies.
cause < 1) {
1854 hasauth = encrypted;
1902 memset(&ies, 0,
sizeof(ies));
1905 memset(ied, 0,
sizeof(*ied));
1938 ddatalen =
sizeof(decoded);
1949 ast_debug(1,
"Ouch, decrypt failed :(\n");
1977 static void destroy_packet(
struct dundi_packet *pack,
int needfree);
1980 struct dundi_packet *pack;
1989 static int ack_trans(
struct dundi_transaction *trans,
int iseqno)
1991 struct dundi_packet *pack;
1995 if ((pack->
h->
oseqno + 1) % 255 == iseqno) {
2012 struct dundi_transaction *trans;
2046 ast_debug(1,
"Dropping packet out of window!\n");
2053 struct sockaddr_in sin;
2057 socklen_t
len =
sizeof(sin);
2059 res = recvfrom(netsocket, buf,
sizeof(buf) - 1, 0,(
struct sockaddr *) &sin, &len);
2061 if (
errno != ECONNREFUSED)
2081 unsigned char tmp[16];
2087 while((s = strchr(secret,
';'))) *s =
'+';
2088 while((s = strchr(secret,
'/'))) *s =
'+';
2089 while((s = strchr(secret,
':'))) *s =
'+';
2090 while((s = strchr(secret,
'@'))) *s =
'+';
2098 snprintf(tmp,
sizeof(tmp),
"%s;%s", oldkey, newkey);
2100 snprintf(tmp,
sizeof(tmp),
"%s", newkey);
2103 snprintf(tmp,
sizeof(tmp),
"%d", (
int)rotatetime);
2114 ast_db_get(secretpath,
"secretexpiry", tmp,
sizeof(tmp));
2116 ast_db_get(secretpath,
"secret", tmp,
sizeof(tmp));
2117 current = strchr(tmp,
';');
2124 if ((time(NULL) - expired) < 0) {
2138 rotatetime = expired;
2153 printf(
"%ld/%ld\n", now, rotatetime);
2155 if ((now - rotatetime) >= 0) {
2171 while (!dundi_shutdown) {
2173 if ((res > 1000) || (res < 0))
2193 int striplen =
sizeof(
"/dundi/cache");
2196 while (!dundi_shutdown) {
2197 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
2202 for (; db_entry; db_entry = db_entry->
next) {
2207 ast_debug(1,
"clearing expired DUNDI cache entry: %s\n", db_entry->
key);
2214 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
2215 pthread_testcancel();
2217 pthread_testcancel();
2232 while (!dundi_shutdown) {
2273 e->
command =
"dundi set debug {on|off}";
2275 "Usage: dundi set debug {on|off}\n"
2276 " Enables/Disables dumping of DUNDi packets for debugging purposes\n";
2285 if (!strncasecmp(a->
argv[e->
args -1],
"on", 2)) {
2287 ast_cli(a->
fd,
"DUNDi Debugging Enabled\n");
2290 ast_cli(a->
fd,
"DUNDi Debugging Disabled\n");
2299 e->
command =
"dundi store history {on|off}";
2301 "Usage: dundi store history {on|off}\n"
2302 " Enables/Disables storing of DUNDi requests and times for debugging\n"
2312 if (!strncasecmp(a->
argv[e->
args -1],
"on", 2)) {
2313 global_storehistory = 1;
2314 ast_cli(a->
fd,
"DUNDi History Storage Enabled\n");
2316 global_storehistory = 0;
2317 ast_cli(a->
fd,
"DUNDi History Storage Disabled\n");
2327 e->
command =
"dundi flush [stats]";
2329 "Usage: dundi flush [stats]\n"
2330 " Flushes DUNDi answer cache, used primarily for debug. If\n"
2331 "'stats' is present, clears timer statistics instead of normal\n"
2337 if ((a->
argc < 2) || (a->
argc > 3))
2340 if (!strcasecmp(a->
argv[2],
"stats"))
2347 struct dundi_peer *p;
2362 ast_cli(a->
fd,
"DUNDi Cache Flushed\n");
2385 struct dundi_peer *p;
2394 if (!strncasecmp(word, s,
len) && ++which > state) {
2417 qsort(results, count,
sizeof(results[0]),
rescomp);
2429 struct timeval start;
2434 "Usage: dundi lookup <number>[@context] [bypass]\n"
2435 " Lookup the given number within the given DUNDi context\n"
2436 "(or e164 if none is specified). Bypasses cache if 'bypass'\n"
2437 "keyword is specified.\n";
2443 if ((a->
argc < 3) || (a->
argc > 4))
2446 if (!strcasecmp(a->
argv[3],
"bypass"))
2452 context = strchr(tmp,
'@');
2458 res =
dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
2461 ast_cli(a->
fd,
"DUNDi lookup returned error.\n");
2463 ast_cli(a->
fd,
"DUNDi lookup returned no results.\n");
2466 for (x=0;x<res;x++) {
2479 struct timeval start;
2482 e->
command =
"dundi precache";
2484 "Usage: dundi precache <number>[@context]\n"
2485 " Lookup the given number within the given DUNDi context\n"
2486 "(or e164 if none is specified) and precaches the results to any\n"
2487 "upstream DUNDi push servers.\n";
2492 if ((a->
argc < 3) || (a->
argc > 3))
2495 context = strchr(tmp,
'@');
2504 ast_cli(a->
fd,
"DUNDi precache returned error.\n");
2506 ast_cli(a->
fd,
"DUNDi precache returned no error.\n");
2522 "Usage: dundi query <entity>[@context]\n"
2523 " Attempts to retrieve contact information for a specific\n"
2524 "DUNDi entity identifier (EID) within a given DUNDi context (or\n"
2525 "e164 if none is specified).\n";
2530 if ((a->
argc < 3) || (a->
argc > 3))
2537 context = strchr(tmp,
'@');
2544 ast_cli(a->
fd,
"DUNDi Query EID returned error.\n");
2546 ast_cli(a->
fd,
"DUNDi Query EID returned no results.\n");
2548 ast_cli(a->
fd,
"DUNDi Query EID succeeded:\n");
2563 struct dundi_peer *peer;
2570 e->
command =
"dundi show peer";
2572 "Usage: dundi show peer [peer]\n"
2573 " Provide a detailed description of a specifid DUNDi peer.\n";
2586 switch(peer->
order) {
2591 order =
"Secondary";
2597 order =
"Quartiary";
2623 ast_cli(a->
fd,
"Last few query times:\n");
2638 #define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"
2639 #define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"
2640 struct dundi_peer *peer;
2641 int registeredonly=0;
2644 int online_peers = 0;
2645 int offline_peers = 0;
2646 int unmonitored_peers = 0;
2647 int total_peers = 0;
2650 e->
command =
"dundi show peers [registered|include|exclude|begin]";
2652 "Usage: dundi show peers [registered|include|exclude|begin]\n"
2653 " Lists all known DUNDi peers.\n"
2654 " If 'registered' is present, only registered peers are shown.\n";
2660 if ((a->
argc != 3) && (a->
argc != 4) && (a->
argc != 5))
2662 if ((a->
argc == 4)) {
2663 if (!strcasecmp(a->
argv[3],
"registered")) {
2669 ast_cli(a->
fd,
FORMAT2,
"EID",
"Host",
"Port",
"Model",
"AvgTime",
"Status");
2672 int print_line = -1;
2675 if (registeredonly && !peer->
addr.sin_addr.s_addr)
2679 strcpy(status,
"UNREACHABLE");
2683 snprintf(status,
sizeof(status),
"LAGGED (%d ms)", peer->
lastms);
2687 snprintf(status,
sizeof(status),
"OK (%d ms)", peer->
lastms);
2691 strcpy(status,
"UNKNOWN");
2695 strcpy(status,
"Unmonitored");
2696 unmonitored_peers++;
2699 snprintf(avgms,
sizeof(avgms),
"%d ms", peer->
avgms);
2701 strcpy(avgms,
"Unavail");
2707 if (!strcasecmp(a->
argv[3],
"include") && strstr(srch,a->
argv[4])) {
2709 }
else if (!strcasecmp(a->
argv[3],
"exclude") && !strstr(srch,a->
argv[4])) {
2711 }
else if (!strcasecmp(a->
argv[3],
"begin") && !strncasecmp(srch,a->
argv[4],strlen(a->
argv[4]))) {
2724 ast_cli(a->
fd,
"%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
2733 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
2734 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
2735 struct dundi_transaction *trans;
2738 e->
command =
"dundi show trans";
2740 "Usage: dundi show trans\n"
2741 " Lists all known DUNDi transactions.\n";
2765 e->
command =
"dundi show entityid";
2767 "Usage: dundi show entityid\n"
2768 " Displays the global entityid for this host.\n";
2778 ast_cli(a->
fd,
"Global EID for this system is '%s'\n", eid_str);
2784 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
2785 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
2786 struct dundi_request *req;
2790 e->
command =
"dundi show requests";
2792 "Usage: dundi show requests\n"
2793 " Lists all known pending DUNDi requests.\n";
2816 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2817 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2818 struct dundi_mapping *
map;
2823 e->
command =
"dundi show mappings";
2825 "Usage: dundi show mappings\n"
2826 " Lists all known DUNDi mappings.\n";
2834 ast_cli(a->
fd,
FORMAT2,
"DUNDi Cntxt",
"Weight",
"Local Cntxt",
"Options",
"Tech",
"Destination");
2849 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
2850 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
2856 e->
command =
"dundi show precache";
2858 "Usage: dundi show precache\n"
2859 " Lists all known DUNDi scheduled precache updates.\n";
2902 struct dundi_transaction *trans;
2906 if (p && !p->
addr.sin_addr.s_addr)
2911 if (!(trans =
ast_calloc(1,
sizeof(*trans))))
2914 if (global_storehistory) {
2958 struct dundi_peer *peer;
2976 if (ms < peer->
maxms) {
3021 if (write(trans->
parent->
pfds[1],
"killa!", 6) < 0) {
3041 struct dundi_packet *pack = (
struct dundi_packet *)data;
3064 struct dundi_packet *pack;
3068 len =
sizeof(
struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
3070 if (ast_test_flag(trans, FLAG_ENCRYPT))
3074 pack->
h = (
struct dundi_hdr *)(pack->
data);
3086 pack->
datalen =
sizeof(
struct dundi_hdr);
3088 memcpy(pack->
h->
ies, ied->buf, ied->pos);
3135 struct dundi_transaction *trans = (
struct dundi_transaction *)data;
3146 struct dundi_peer *p;
3174 memset(&ied, 0,
sizeof(ied));
3190 static int precache_trans(
struct dundi_transaction *trans,
struct dundi_mapping *maps,
int mapcount,
int *minexp,
int *foundanswers)
3198 int direct[1] = { 0, };
3205 memset(&hmd, 0,
sizeof(hmd));
3206 memset(&dr, 0,
sizeof(dr));
3208 for (x=0;x<mapcount;x++)
3212 for (x=0;x<ouranswers;x++) {
3213 if (dr[x].weight < max)
3218 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);
3225 if (ouranswers > 0) {
3226 *foundanswers += ouranswers;
3227 memset(&ied, 0,
sizeof(ied));
3236 for (x=0;x<ouranswers;x++) {
3238 if (dr[x].expiration && (expiration > dr[x].expiration))
3246 if (expiration < *minexp)
3247 *minexp = expiration;
3264 memset(&ied, 0,
sizeof(ied));
3280 struct dundi_transaction *trans;
3289 static int precache_transactions(
struct dundi_request *dr,
struct dundi_mapping *maps,
int mapcount,
int *expiration,
int *foundanswers)
3291 struct dundi_transaction *trans;
3312 ast_debug(1,
"Our transaction went away!\n");
3326 struct dundi_transaction *trans;
3341 struct dundi_transaction *trans;
3342 struct dundi_peer *peer;
3363 (peer->
order <= order)) {
3397 struct dundi_transaction *trans;
3403 if (!p->
addr.sin_addr.s_addr)
3419 trans->
eids[x] = *avoid[x];
3428 struct dundi_transaction *trans;
3442 struct dundi_transaction *trans;
3452 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[])
3454 struct dundi_peer *p;
3462 if (modeselect == 1) {
3476 if (p->
order <= order) {
3484 for (x=0;avoid[x];x++) {
3487 if (directs && !directs[x])
3503 }
else if (!*skipped || (p->
order < *skipped))
3504 *skipped = p->
order;
3512 struct dundi_request *cur;
3522 ast_debug(1,
"Found existing query for '%s@%s' for '%s' crc '%08x'\n",
3530 ast_debug(1,
"Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n",
3549 struct dundi_request *cur;
3565 uint32_t acrc32 = 0;
3567 for (x=0;avoid[x];x++) {
3570 acrc32 ^=
crc32(0L, (
unsigned char *)avoid[x],
sizeof(
dundi_eid));
3576 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[])
3579 struct dundi_request dr, *pending;
3588 struct timeval start;
3596 for (x=0;avoid[x];x++)
3599 memset(&dr, 0,
sizeof(dr));
3600 if (pipe(dr.
pfds)) {
3620 ast_debug(1,
"Oooh, duplicate request for '%s@%s' for '%s'\n",
3627 ast_debug(1,
"Waiting for similar request for '%s@%s' for '%s'\n",
3643 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
3682 int direct[1] = { 0, };
3684 memset(&hmd, 0,
sizeof(hmd));
3686 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
3696 if (!strcmp(number, qe->
number) && !strcasecmp(context, qe->
context)) {
3704 len += strlen(number) + 1;
3705 len += strlen(context) + 1;
3710 strcpy(qe->
number, number);
3727 struct dundi_mapping *cur;
3751 struct dundi_request dr;
3754 struct timeval start;
3755 struct dundi_mapping *maps = NULL, *cur;
3758 int foundcache, skipped, ttlms, ms;
3761 ast_debug(1,
"Precache internal (%s@%s)!\n", number, context);
3765 if (!strcasecmp(cur->dcontext, context))
3772 if (!strcasecmp(cur->dcontext, context))
3773 maps[nummaps++] = *cur;
3781 memset(&dr2, 0,
sizeof(dr2));
3782 memset(&dr, 0,
sizeof(dr));
3783 memset(&hmd, 0,
sizeof(hmd));
3791 if (pipe(dr.
pfds) < 0) {
3795 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
3807 if (dr.
pfds[0] > -1) {
3814 if (dr.
pfds[0] > -1) {
3830 struct dundi_request dr;
3836 struct timeval start;
3840 for (x=0;avoid[x];x++)
3843 memset(&dr, 0,
sizeof(dr));
3852 build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL);
3878 memset(&hmd, 0,
sizeof(hmd));
3918 args.context =
"e164";
3924 for (x = 0; x < results; x++) {
3926 snprintf(buf, len,
"%s/%s", dr[x].tech, dr[x].dest);
3940 .
name =
"DUNDILOOKUP",
3964 .
type =
"DUNDIQUERY",
3998 args.context =
"e164";
4000 if (!(drds =
ast_calloc(1,
sizeof(*drds)))) {
4005 snprintf(buf, len,
"%u", drds->
id);
4012 datastore->
data = drds;
4028 .
name =
"DUNDIQUERY",
4077 drds = datastore->
data;
4079 if (!strcasecmp(
args.resultnum,
"getnum")) {
4085 if (sscanf(
args.resultnum,
"%30u", &num) != 1) {
4091 if (num && num <= drds->num_results) {
4095 ast_log(
LOG_WARNING,
"Result number %u is not valid for DUNDi query results for ID %s!\n", num,
args.id);
4102 .
name =
"DUNDIRESULT",
4108 struct dundi_peer *peer;
4118 struct dundi_mapping *
map;
4155 struct dundi_peer *peer;
4170 struct dundi_mapping *
map;
4187 if (!(perm =
ast_calloc(1,
sizeof(*perm) + strlen(s) + 1)))
4190 strcpy(perm->
name, s);
4196 #define MAX_OPTS 128
4201 struct dundi_mapping *
map;
4209 if (!strcasecmp(map->
dcontext, name) &&
4212 (value[strlen(map->
lcontext)] ==
','))))
4222 memset(fields, 0,
sizeof(fields));
4236 }
else if (x >= 4) {
4243 }
else if (!strncmp(fields[1],
"${", 2) && fields[1][strlen(fields[1]) - 1] ==
'}') {
4251 for (y = 4;y < x; y++) {
4252 if (!strcasecmp(fields[y],
"nounsolicited"))
4254 else if (!strcasecmp(fields[y],
"nocomunsolicit"))
4256 else if (!strcasecmp(fields[y],
"residential"))
4258 else if (!strcasecmp(fields[y],
"commercial"))
4260 else if (!strcasecmp(fields[y],
"mobile"))
4262 else if (!strcasecmp(fields[y],
"nopartial"))
4268 ast_log(
LOG_WARNING,
"Expected at least %d arguments in map, but got only %d\n", 4, x);
4275 struct dundi_peer *peer = (
struct dundi_peer *)data;
4286 memset(&ied, 0,
sizeof(ied));
4300 struct dundi_peer *peer = (
struct dundi_peer *)data;
4313 if (peer->
maxms > 0) {
4336 if (!
ast_db_get(
"dundi/dpeers", eid_str, data,
sizeof(data))) {
4337 c = strchr(data,
':');
4341 if (sscanf(c,
"%5d:%30d", &port, &expire) == 2) {
4344 peer->
addr.sin_family = AF_INET;
4345 peer->
addr.sin_port = htons(port);
4355 struct dundi_peer *peer;
4370 if (!(peer =
ast_calloc(1,
sizeof(*peer)))) {
4377 peer->
addr.sin_family = AF_INET;
4388 for (; v; v = v->
next) {
4389 if (!strcasecmp(v->
name,
"inkey")) {
4391 }
else if (!strcasecmp(v->
name,
"outkey")) {
4393 }
else if (!strcasecmp(v->
name,
"port")) {
4394 peer->
addr.sin_port = htons(atoi(v->
value));
4395 }
else if (!strcasecmp(v->
name,
"host")) {
4396 if (!strcasecmp(v->
value,
"dynamic")) {
4401 memcpy(&peer->
addr.sin_addr, hp->h_addr,
sizeof(peer->
addr.sin_addr));
4408 }
else if (!strcasecmp(v->
name,
"ustothem")) {
4413 }
else if (!strcasecmp(v->
name,
"include")) {
4415 }
else if (!strcasecmp(v->
name,
"permit")) {
4417 }
else if (!strcasecmp(v->
name,
"noinclude")) {
4419 }
else if (!strcasecmp(v->
name,
"deny")) {
4421 }
else if (!strcasecmp(v->
name,
"register")) {
4423 }
else if (!strcasecmp(v->
name,
"order")) {
4424 if (!strcasecmp(v->
value,
"primary"))
4426 else if (!strcasecmp(v->
value,
"secondary"))
4428 else if (!strcasecmp(v->
value,
"tertiary"))
4430 else if (!strcasecmp(v->
value,
"quartiary"))
4435 }
else if (!strcasecmp(v->
name,
"qualify")) {
4436 if (!strcasecmp(v->
value,
"no")) {
4438 }
else if (!strcasecmp(v->
value,
"yes")) {
4440 }
else if (sscanf(v->
value,
"%30d", &peer->
maxms) != 1) {
4441 ast_log(
LOG_WARNING,
"Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4445 }
else if (!strcasecmp(v->
name,
"model")) {
4446 if (!strcasecmp(v->
value,
"inbound"))
4448 else if (!strcasecmp(v->
value,
"outbound"))
4450 else if (!strcasecmp(v->
value,
"symmetric"))
4452 else if (!strcasecmp(v->
value,
"none"))
4455 ast_log(
LOG_WARNING,
"Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4458 }
else if (!strcasecmp(v->
name,
"precache")) {
4459 if (!strcasecmp(v->
value,
"inbound"))
4461 else if (!strcasecmp(v->
value,
"outbound"))
4463 else if (!strcasecmp(v->
value,
"symmetric"))
4465 else if (!strcasecmp(v->
value,
"none"))
4468 ast_log(
LOG_WARNING,
"Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4473 (*globalpcmode) |= peer->
pcmodel;
4479 ast_log(
LOG_WARNING,
"Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4483 ast_log(
LOG_WARNING,
"Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4487 ast_log(
LOG_WARNING,
"Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4490 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",
4509 if (!strncasecmp(context,
"macro-", 6)) {
4515 if (!strcasecmp(exten,
"s")) {
4520 exten = chan->
exten;
4532 res =
dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4533 for (x=0;x<res;x++) {
4537 if (found >= priority)
4558 const char *dundiargs;
4561 if (!strncasecmp(context,
"macro-", 6)) {
4567 if (!strcasecmp(exten,
"s")) {
4572 exten = chan->
exten;
4584 res =
dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4587 for (x=0;x<res;x++) {
4597 snprintf(req,
sizeof(req),
"%s/%s,,%s", results[x].tech, results[x].dest,
4598 S_OR(dundiargs,
""));
4614 .description =
"DUNDi Discovered Dialplan Switch",
4631 struct sockaddr_in sin2;
4632 static int last_port = 0;
4633 int globalpcmodel = 0;
4646 if (!gethostname(hn,
sizeof(hn)-1)) {
4649 memcpy(&sin2.sin_addr, hp->h_addr,
sizeof(sin2.sin_addr));
4659 global_storehistory = 0;
4663 if (!strcasecmp(v->
name,
"port")){
4664 sin->sin_port = htons(atoi(v->
value));
4666 last_port=sin->sin_port;
4667 }
else if(sin->sin_port != last_port)
4669 }
else if (!strcasecmp(v->
name,
"bindaddr")) {
4670 struct hostent *hep;
4674 memcpy(&sin->sin_addr, hep->h_addr,
sizeof(sin->sin_addr));
4677 }
else if (!strcasecmp(v->
name,
"authdebug")) {
4679 }
else if (!strcasecmp(v->
name,
"ttl")) {
4683 ast_log(
LOG_WARNING,
"'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
4686 }
else if (!strcasecmp(v->
name,
"autokill")) {
4687 if (sscanf(v->
value,
"%30d", &x) == 1) {
4689 global_autokilltimeout = x;
4695 global_autokilltimeout = 0;
4697 }
else if (!strcasecmp(v->
name,
"entityid")) {
4699 global_eid = testeid;
4702 }
else if (!strcasecmp(v->
name,
"tos")) {
4705 }
else if (!strcasecmp(v->
name,
"department")) {
4707 }
else if (!strcasecmp(v->
name,
"organization")) {
4709 }
else if (!strcasecmp(v->
name,
"locality")) {
4711 }
else if (!strcasecmp(v->
name,
"stateprov")) {
4713 }
else if (!strcasecmp(v->
name,
"country")) {
4715 }
else if (!strcasecmp(v->
name,
"email")) {
4717 }
else if (!strcasecmp(v->
name,
"phone")) {
4719 }
else if (!strcasecmp(v->
name,
"storehistory")) {
4721 }
else if (!strcasecmp(v->
name,
"cachetime")) {
4722 if ((sscanf(v->
value,
"%30d", &x) == 1)) {
4723 dundi_cache_time = x;
4725 ast_log(
LOG_WARNING,
"'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
4742 if (strcasecmp(cat,
"general") && strcasecmp(cat,
"mappings")) {
4746 else if (!strcasecmp(cat,
"*")) {
4775 pthread_kill(previous_netthreadid, SIGURG);
4776 pthread_join(previous_netthreadid, NULL);
4779 pthread_kill(previous_precachethreadid, SIGURG);
4780 pthread_join(previous_precachethreadid, NULL);
4783 pthread_cancel(previous_clearcachethreadid);
4784 pthread_join(previous_clearcachethreadid, NULL);
4801 struct sockaddr_in sin;
4811 struct sockaddr_in sin;
4816 sin.sin_family = AF_INET;
4818 sin.sin_addr.s_addr = INADDR_ANY;
4830 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
4832 if (netsocket < 0) {
4836 if (bind(netsocket, (
struct sockaddr *) &sin,
sizeof(sin))) {
4857 ast_verb(2,
"DUNDi Ready and Listening on %s port %d\n",
ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
4866 .nonoptreq =
"res_crypto",
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)
int ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Decrypt a message using a given private key.
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
static int discover_transactions(struct dundi_request *dr)
int ast_unlock_context(struct ast_context *con)
struct dundi_mapping::@317 list
#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)
#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.
static int get_mapping_weight(struct dundi_mapping *map)
#define DUNDI_MODEL_SYMMETRIC
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
char dcontext[AST_MAX_EXTENSION]
Distributed Universal Number Discovery (DUNDi) See also.
int ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig)
Check the authenticity of a message signature using a given public key.
static char * dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
char * lookups[DUNDI_TIMING_HISTORY]
int dundi_precache(const char *dcontext, const char *number)
Pre-cache to push upstream peers.
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)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static int register_request(struct dundi_request *dr, struct dundi_request **pending)
char called_number[AST_MAX_EXTENSION]
static char * dundi_show_requests(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 char * dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define DUNDI_IE_CACHEBYPASS
static pthread_t precachethreadid
char lcontext[AST_MAX_EXTENSION]
#define ast_pthread_create_detached(a, b, c, d)
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)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
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)
static int do_register_expire(const void *data)
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
static dundi_eid global_eid
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
#define ast_test_flag(p, flag)
struct dundi_entity_info * dei
static void * process_precache(void *ign)
static void * dundi_lookup_thread(void *data)
static void destroy_map(struct dundi_mapping *map)
#define ast_clear_flag_nonstd(p, flag)
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
struct ast_var_t * ast_var_assign(const char *name, const char *value)
static void * network_thread(void *ignore)
#define DUNDI_TIMING_HISTORY
dundi_eid eids[DUNDI_MAX_STACK+1]
#define ast_set_flag(p, flag)
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.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
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.
static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx)
void ast_verbose(const char *fmt,...)
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.
struct dundi_mapping * maps
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
struct dundi_transaction * trans
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
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]
static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
Compares the source address and port of two sockaddr_in.
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 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.
Configuration File Parser.
static char * dundi_do_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
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 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)
int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
Retrieve information on a specific EID.
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.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
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.
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)
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
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)
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
#define DUNDI_IE_DEPARTMENT
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)
static struct dundi_transaction * find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
An Entity ID is essentially a MAC address, brief and unique.
void ast_var_delete(struct ast_var_t *var)
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
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. This can be used to handle reference co...
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.
void ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
AES decrypt data.
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.
struct dundi_mapping * next
int args
This gets set in ast_cli_register()
static int has_permission(struct permissionlist *permlist, char *cont)
static pthread_t netthreadid
#define ast_pthread_create_background(a, b, c, d)
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)
void ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
AES encrypt data.
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 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)
int ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Encrypt a message using a given private key.
#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.
int ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *sig)
Sign a message signature using a given private key.
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)
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
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)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
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
#define ast_config_load(filename, flags)
Load a config file.
void dundi_set_output(void(*func)(const char *))
#define DUNDI_DEFAULT_RETRANS_TIMER
#define AST_PTHREADT_NULL
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define DUNDI_MODEL_INBOUND
struct sla_ringing_trunk * last
Data structure associated with a custom dialplan function.
Access Control of various sorts.
Asterisk internal frame definitions.
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.
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
static int set_config(char *config_file, struct sockaddr_in *sin, int reload)
long int ast_random(void)
static int global_storehistory
static void build_iv(unsigned char *iv)
static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
static int get_trans_id(void)
static dundi_eid empty_eid
static int dundi_discover(struct dundi_transaction *trans)
#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.
struct dundi_transaction::packetlist packets
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
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.
struct ast_context * ast_walk_contexts(struct ast_context *con)
static int dundi_query(struct dundi_transaction *trans)
int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int nocache)
Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspec...
const char * ast_get_context_name(struct ast_context *con)
static void dundi_debug_output(const char *data)
unsigned char * encsharedkey
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
static struct sched_context * sched
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
static char * dundi_show_mappings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int socket_read(int *id, int fd, short events, void *cbdata)
static char * dundi_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define ast_strdupa(s)
duplicate a string in memory from the stack
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".
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free's) the given sched_context structure
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 If family is specified, only those keys will be returned...
static pthread_t clearcachethreadid
static int global_autokilltimeout
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
int ast_unlock_contexts(void)
Unlocks contexts.
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
static void check_password(void)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct dundi_transaction * qualtrans
static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc32, int *lowexpiration)
static int load_module(void)
#define DUNDI_IE_CALLED_CONTEXT
const ast_string_field name
#define DUNDI_IE_ORGANIZATION
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
const char * ast_get_extension_name(struct ast_exten *exten)
#define DUNDI_DEFAULT_KEY_EXPIRE
#define DUNDI_DEFAULT_VERSION
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 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)
struct ast_var_t::@158 entries
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
int directs[DUNDI_MAX_STACK+1]
static void * dundi_precache_thread(void *data)
static void * dundi_query_thread(void *data)
AES_KEY ast_aes_decrypt_key
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)
static struct ast_cli_entry cli_dundi[]
struct dundi_peer::permissionlist permit
if(yyss+yystacksize-1<=yyssp)
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.
#define DUNDI_IE_CALLED_NUMBER
#define DUNDI_COMMAND_PRECACHERQ
int ast_sched_runq(struct sched_context *con)
Runs the queue.
#define DUNDI_COMMAND_PRECACHERP
char macroexten[AST_MAX_EXTENSION]
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_error_output(const char *data)
static int update_key(struct dundi_peer *peer)
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
unsigned char txenckey[256]
static int check_request(struct dundi_request *dr)
struct sched_context * sched_context_create(void)
New schedule context.
#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
int dundi_eid_zero(dundi_eid *eid)
static int str2tech(char *str)
struct dundi_result results[MAX_RESULTS]
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
#define DUNDI_COMMAND_EIDQUERY
static int unload_module(void)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static void mark_mappings(void)
static struct ast_app_option dundi_query_opts[128]
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)
struct dundi_request::@315 trans
static int do_qualify(const void *data)
#define DUNDI_COMMAND_INVALID
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_APP_ARG(name)
Define an application argument.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
struct ast_variable * next
#define DUNDI_COMMAND_DPDISCOVER
struct permission::@310 list
static void build_mapping(const char *name, const char *value)
static struct adsi_event events[]
static char * dundi_do_lookup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dundi_ack(struct dundi_transaction *trans, int final)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
static struct ast_datastore_info dundi_result_datastore_info
static struct ast_custom_function dundi_query_function
struct dundi_transaction * parent
#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 struct hostent * hp
static int dundi_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
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)
ast_context: An extension context
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
int inet_aton(const char *cp, struct in_addr *pin)
#define ast_custom_function_register(acf)
Register a custom function.
#define DUNDI_COMMAND_NULL
#define DUNDI_MODEL_OUTBOUND
static struct ast_switch dundi_switch
char exten[AST_MAX_EXTENSION]
#define ast_test_flag_nonstd(p, flag)
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb If both parameters are NULL, the entire database will be purged...
struct ast_key * ast_key_get(const char *key, int type)
Retrieve a key.
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)
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
static void prune_peers(void)
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
static struct ast_custom_function dundi_result_function
#define DUNDI_COMMAND_CANCEL
static char stateprov[80]
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)