31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
38 #include "dundi-parser.h"
41 static void internaloutput(
const char *str)
46 static void internalerror(
const char *str)
48 fprintf(stderr,
"WARNING: %s", str);
51 static void (*outputf)(
const char *str) = internaloutput;
52 static void (*errorf)(
const char *str) = internalerror;
54 char *dundi_eid_to_str_short(
char *s,
int maxlen,
dundi_eid *eid)
59 if (s && (maxlen > 0))
63 sprintf(s,
"%02hhX", (
unsigned char)eid->eid[x]);
70 int dundi_str_short_to_eid(
dundi_eid *eid,
const char *s)
72 unsigned int eid_int[6];
74 if (sscanf(s,
"%2x%2x%2x%2x%2x%2x", &eid_int[0], &eid_int[1], &eid_int[2],
75 &eid_int[3], &eid_int[4], &eid_int[5]) != 6)
77 for (x = 0; x < 6; x++)
78 eid->eid[x] = eid_int[x];
85 for (x = 0; x < ARRAY_LEN(eid->eid); x++)
86 if (eid->eid[x])
return 0;
90 static void dump_string(
char *output,
int maxlen,
void *value,
int len)
95 snprintf(output, maxlen,
"%s", (
char *) value);
98 static void dump_cbypass(
char *output,
int maxlen,
void *value,
int len)
100 snprintf(output, maxlen,
"Bypass Caches");
103 static void dump_eid(
char *output,
int maxlen,
void *value,
int len)
108 snprintf(output, maxlen,
"Invalid EID len %d", len);
111 char *dundi_hint2str(
char *buf,
int bufsiz,
int flags)
114 buf[bufsiz-1] =
'\0';
116 strncat(buf,
"TTLEXPIRED|", bufsiz - strlen(buf) - 1);
119 strncat(buf,
"DONTASK|", bufsiz - strlen(buf) - 1);
122 strncat(buf,
"UNAFFECTED|", bufsiz - strlen(buf) - 1);
125 if (ast_strlen_zero(buf))
126 strcpy(buf,
"NONE|");
127 buf[strlen(buf)-1] =
'\0';
131 static void dump_hint(
char *output,
int maxlen,
void *value,
int len)
137 if (len <
sizeof(*hint)) {
138 snprintf(output, maxlen,
"<invalid contents>");
145 if (datalen >
sizeof(tmp3) - 1)
146 datalen =
sizeof(tmp3) - 1;
148 memcpy(tmp3, hint->
data, datalen);
149 tmp3[datalen] =
'\0';
151 dundi_hint2str(tmp2,
sizeof(tmp2), ntohs(hint->
flags));
153 if (ast_strlen_zero(tmp3))
154 snprintf(output, maxlen,
"[%s]", tmp2);
156 snprintf(output, maxlen,
"[%s] %s", tmp2, tmp3);
159 static void dump_cause(
char *output,
int maxlen,
void *value,
int len)
161 static const char *
const causes[] = {
172 if (len <
sizeof(*cause)) {
173 snprintf(output, maxlen,
"<invalid contents>");
181 if (datalen >
sizeof(tmp2) - 1)
182 datalen =
sizeof(tmp2) - 1;
184 memcpy(tmp2, cause->
desc, datalen);
185 tmp2[datalen] =
'\0';
187 if (causecode < ARRAY_LEN(causes)) {
188 if (ast_strlen_zero(tmp2))
189 snprintf(output, maxlen,
"%s", causes[causecode]);
191 snprintf(output, maxlen,
"%s: %s", causes[causecode], tmp2);
193 if (ast_strlen_zero(tmp2))
194 snprintf(output, maxlen,
"%d", causecode);
196 snprintf(output, maxlen,
"%d: %s", causecode, tmp2);
200 static void dump_int(
char *output,
int maxlen,
void *value,
int len)
202 if (len == (
int)
sizeof(
unsigned int))
203 snprintf(output, maxlen,
"%lu", (
unsigned long)ntohl(*((
unsigned int *)value)));
208 static void dump_short(
char *output,
int maxlen,
void *value,
int len)
210 if (len == (
int)
sizeof(
unsigned short))
211 snprintf(output, maxlen,
"%d", ntohs(*((
unsigned short *)value)));
216 static void dump_byte(
char *output,
int maxlen,
void *value,
int len)
218 if (len == (
int)
sizeof(
unsigned char))
219 snprintf(output, maxlen,
"%d", *((
unsigned char *)value));
224 static char *proto2str(
int proto,
char *buf,
int bufsiz)
228 strncpy(buf,
"None", bufsiz - 1);
231 strncpy(buf,
"IAX", bufsiz - 1);
234 strncpy(buf,
"SIP", bufsiz - 1);
237 strncpy(buf,
"H.323", bufsiz - 1);
240 strncpy(buf,
"PJSIP", bufsiz - 1);
242 snprintf(buf, bufsiz,
"Unknown Proto(%d)", proto);
244 buf[bufsiz-1] =
'\0';
248 char *dundi_flags2str(
char *buf,
int bufsiz,
int flags)
251 buf[bufsiz-1] =
'\0';
253 strncat(buf,
"EXISTS|", bufsiz - strlen(buf) - 1);
256 strncat(buf,
"MATCHMORE|", bufsiz - strlen(buf) - 1);
259 strncat(buf,
"CANMATCH|", bufsiz - strlen(buf) - 1);
262 strncat(buf,
"IGNOREPAT|", bufsiz - strlen(buf) - 1);
265 strncat(buf,
"RESIDENCE|", bufsiz - strlen(buf) - 1);
268 strncat(buf,
"COMMERCIAL|", bufsiz - strlen(buf) - 1);
271 strncat(buf,
"MOBILE", bufsiz - strlen(buf) - 1);
274 strncat(buf,
"NOUNSLCTD|", bufsiz - strlen(buf) - 1);
277 strncat(buf,
"NOCOMUNSLTD|", bufsiz - strlen(buf) - 1);
280 if (ast_strlen_zero(buf))
281 strcpy(buf,
"NONE|");
282 buf[strlen(buf)-1] =
'\0';
286 static void dump_answer(
char *output,
int maxlen,
void *value,
int len)
295 if (len <
sizeof(*answer)) {
296 snprintf(output, maxlen,
"Invalid Answer");
303 if (datalen >
sizeof(tmp) - 1)
304 datalen =
sizeof(tmp) - 1;
306 memcpy(tmp, answer->
data, datalen);
310 snprintf(output, maxlen,
"[%s] %d <%s/%s> from [%s]",
311 dundi_flags2str(flags,
sizeof(flags), ntohs(answer->
flags)),
313 proto2str(answer->
protocol, proto,
sizeof(proto)),
317 static void dump_encrypted(
char *output,
int maxlen,
void *value,
int len)
321 if ((len > 16) && !(len % 16)) {
324 snprintf(iv + (x << 1), 3,
"%02hhx", ((
unsigned char *)value)[x]);
326 snprintf(output, maxlen,
"[IV %s] %d encrypted blocks\n", iv, len / 16);
328 snprintf(output, maxlen,
"Invalid Encrypted Datalen %d", len);
331 static void dump_raw(
char *output,
int maxlen,
void *value,
int len)
334 unsigned char *u = value;
335 output[maxlen - 1] =
'\0';
336 strcpy(output,
"[ ");
337 for (x=0;x<len;x++) {
338 snprintf(output + strlen(output), maxlen - strlen(output) - 1,
"%02hhx ", u[x]);
340 strncat(output + strlen(output),
"]", maxlen - strlen(output) - 1);
346 void (*dump)(
char *output,
int maxlen,
void *value,
int len);
375 const char *dundi_ie2str(
int ie)
378 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
379 if (infoelts[x].ie == ie)
380 return infoelts[x].name;
385 static void dump_ies(
unsigned char *iedata,
int spaces,
int len)
401 if (ielen + 2> len) {
402 snprintf(tmp, (
int)
sizeof(tmp),
"Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
407 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
408 if (infoelts[x].ie == ie) {
409 if (infoelts[x].dump) {
410 infoelts[x].dump(interp, (
int)
sizeof(interp), iedata + 2, ielen);
411 snprintf(tmp, (
int)
sizeof(tmp),
" %s%-15.15s : %s\n", (spaces ?
" " :
"" ), infoelts[x].name, interp);
415 snprintf(interp, (
int)
sizeof(interp),
"%d bytes", ielen);
417 strcpy(interp,
"Present");
418 snprintf(tmp, (
int)
sizeof(tmp),
" %s%-15.15s : %s\n", (spaces ?
" " :
"" ), infoelts[x].name, interp);
425 snprintf(tmp, (
int)
sizeof(tmp),
" %sUnknown IE %03d : Present\n", (spaces ?
" " :
"" ), ie);
428 iedata += (2 + ielen);
462 if ((fhi->
cmdresp & 0x3f) >= ARRAY_LEN(commands)) {
463 snprintf(class2,
sizeof(class2),
"(%d?)", fhi->
cmdresp & 0x3f);
466 class = commands[fhi->cmdresp & 0x3f];
468 snprintf(subclass2,
sizeof(subclass2),
"%02hhx", (
unsigned char)fhi->
cmdflags);
469 subclass = subclass2;
470 snprintf(tmp,
sizeof(tmp),
471 "%s-Frame -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n",
476 snprintf(tmp, (
int)
sizeof(tmp),
477 "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s]%s\n", (rx > 1) ?
" " :
"",
480 fhi->
cmdresp & 0x80 ?
" (Final)" :
"");
483 dump_ies(fhi->ies, rx > 1, datalen);
486 int dundi_ie_append_raw(
struct dundi_ie_data *ied,
unsigned char ie,
void *data,
int datalen)
489 if (datalen > ((
int)
sizeof(ied->buf) - ied->pos)) {
490 snprintf(tmp, (
int)
sizeof(tmp),
"Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (
int)
sizeof(ied->buf) - ied->pos);
494 ied->buf[ied->pos++] = ie;
495 ied->buf[ied->pos++] = datalen;
496 memcpy(ied->buf + ied->pos, data, datalen);
501 int dundi_ie_append_cause(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned char cause,
char *data)
504 int datalen = data ? strlen(data) + 1 : 1;
505 if (datalen > ((
int)
sizeof(ied->buf) - ied->pos)) {
506 snprintf(tmp, (
int)
sizeof(tmp),
"Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (
int)
sizeof(ied->buf) - ied->pos);
510 ied->buf[ied->pos++] = ie;
511 ied->buf[ied->pos++] = datalen;
512 ied->buf[ied->pos++] = cause;
514 memcpy(ied->buf + ied->pos, data, datalen-1);
515 ied->pos += datalen-1;
520 int dundi_ie_append_hint(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned short flags,
char *data)
523 int datalen = data ? strlen(data) + 2 : 2;
524 if (datalen > ((
int)
sizeof(ied->buf) - ied->pos)) {
525 snprintf(tmp, (
int)
sizeof(tmp),
"Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (
int)
sizeof(ied->buf) - ied->pos);
529 ied->buf[ied->pos++] = ie;
530 ied->buf[ied->pos++] = datalen;
531 flags = htons(flags);
532 memcpy(ied->buf + ied->pos, &flags,
sizeof(flags));
535 memcpy(ied->buf + ied->pos, data, datalen-2);
536 ied->pos += datalen-2;
541 int dundi_ie_append_encdata(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned char *iv,
void *data,
int datalen)
545 if (datalen > ((
int)
sizeof(ied->buf) - ied->pos)) {
546 snprintf(tmp, (
int)
sizeof(tmp),
"Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (
int)
sizeof(ied->buf) - ied->pos);
550 ied->buf[ied->pos++] = ie;
551 ied->buf[ied->pos++] = datalen;
552 memcpy(ied->buf + ied->pos, iv, 16);
555 memcpy(ied->buf + ied->pos, data, datalen-16);
556 ied->pos += datalen-16;
561 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)
564 int datalen = data ? strlen(data) + 11 : 11;
567 if (datalen > ((
int)
sizeof(ied->buf) - ied->pos)) {
568 snprintf(tmp, (
int)
sizeof(tmp),
"Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (
int)
sizeof(ied->buf) - ied->pos);
572 ied->buf[ied->pos++] = ie;
573 ied->buf[ied->pos++] = datalen;
575 ied->buf[ied->pos++] = eid->eid[x];
576 ied->buf[ied->pos++] = protocol;
578 memcpy(ied->buf + ied->pos, &myw, 2);
581 memcpy(ied->buf + ied->pos, &myw, 2);
583 memcpy(ied->buf + ied->pos, data, datalen-11);
584 ied->pos += datalen-11;
588 int dundi_ie_append_addr(
struct dundi_ie_data *ied,
unsigned char ie,
struct sockaddr_in *sin)
590 return dundi_ie_append_raw(ied, ie, sin, (
int)
sizeof(
struct sockaddr_in));
593 int dundi_ie_append_int(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned int value)
596 newval = htonl(value);
597 return dundi_ie_append_raw(ied, ie, &newval, (
int)
sizeof(newval));
600 int dundi_ie_append_short(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned short value)
602 unsigned short newval;
603 newval = htons(value);
604 return dundi_ie_append_raw(ied, ie, &newval, (
int)
sizeof(newval));
607 int dundi_ie_append_str(
struct dundi_ie_data *ied,
unsigned char ie,
char *str)
609 return dundi_ie_append_raw(ied, ie, str, strlen(str));
614 return dundi_ie_append_raw(ied, ie, (
unsigned char *)eid,
sizeof(
dundi_eid));
617 int dundi_ie_append_byte(
struct dundi_ie_data *ied,
unsigned char ie,
unsigned char dat)
619 return dundi_ie_append_raw(ied, ie, &dat, 1);
622 int dundi_ie_append(
struct dundi_ie_data *ied,
unsigned char ie)
624 return dundi_ie_append_raw(ied, ie, NULL, 0);
627 void dundi_set_output(
void (*func)(
const char *))
632 void dundi_set_error(
void (*func)(
const char *))
637 int dundi_parse_ies(
struct dundi_ies *ies,
unsigned char *data,
int datalen)
643 memset(ies, 0, (
int)
sizeof(
struct dundi_ies));
645 ies->expiration = -1;
646 ies->unknowncmd = -1;
648 while(datalen >= 2) {
651 if (len > datalen - 2) {
652 errorf(
"Information element length exceeds message size\n");
659 errorf(
"Improper entity identifer, expecting 6 bytes!\n");
660 }
else if (ies->eidcount < DUNDI_MAX_STACK) {
661 ies->eids[ies->eidcount] = (
dundi_eid *)(data + 2);
665 errorf(
"Too many entities in stack!\n");
669 errorf(
"Improper requested entity identifer, expecting 6 bytes!\n");
674 ies->called_context = (
char *)data + 2;
677 ies->called_number = (
char *)data + 2;
681 snprintf(tmp, (
int)
sizeof(tmp),
"Answer expected to be >=%d bytes long but was %d\n", (
int)
sizeof(
struct dundi_answer), len);
684 if (ies->anscount < DUNDI_MAX_ANSWERS)
685 ies->answers[ies->anscount++]= (
struct dundi_answer *)(data + 2);
687 errorf(
"Ignoring extra answers!\n");
691 if (len != (
int)
sizeof(
unsigned short)) {
692 snprintf(tmp, (
int)
sizeof(tmp),
"Expecting ttl to be %d bytes long but was %d\n", (
int)
sizeof(
unsigned short), len);
695 ies->ttl = ntohs(*((
unsigned short *)(data + 2)));
698 if (len != (
int)
sizeof(
unsigned short)) {
699 snprintf(tmp, (
int)
sizeof(tmp),
"Expecting version to be %d bytes long but was %d\n", (
int)
sizeof(
unsigned short), len);
702 ies->version = ntohs(*((
unsigned short *)(data + 2)));
705 if (len != (
int)
sizeof(
unsigned short)) {
706 snprintf(tmp, (
int)
sizeof(tmp),
"Expecting expiration to be %d bytes long but was %d\n", (
int)
sizeof(
unsigned short), len);
709 ies->expiration = ntohs(*((
unsigned short *)(data + 2)));
712 if (len != (
int)
sizeof(
unsigned int)) {
713 snprintf(tmp, (
int)
sizeof(tmp),
"Expecting expiration to be %d bytes long but was %d\n", (
int)
sizeof(
unsigned int), len);
716 ies->keycrc32 = ntohl(*((
unsigned int *)(data + 2)));
720 ies->unknowncmd = data[2];
722 snprintf(tmp, (
int)
sizeof(tmp),
"Expected single byte Unknown command, but was %d long\n", len);
728 ies->cause = data[2];
729 ies->causestr = (
char *)data + 3;
731 snprintf(tmp, (
int)
sizeof(tmp),
"Expected at least one byte cause, but was %d long\n", len);
739 snprintf(tmp, (
int)
sizeof(tmp),
"Expected at least two byte hint, but was %d long\n", len);
744 ies->q_dept = (
char *)data + 2;
747 ies->q_org = (
char *)data + 2;
750 ies->q_locality = (
char *)data + 2;
753 ies->q_stateprov = (
char *)data + 2;
756 ies->q_country = (
char *)data + 2;
759 ies->q_email = (
char *)data + 2;
762 ies->q_phone = (
char *)data + 2;
765 ies->q_ipaddr = (
char *)data + 2;
771 if ((len > 16) && !(len % 16)) {
773 ies->enclen = len - 16;
775 snprintf(tmp, (
int)
sizeof(tmp),
"Invalid encrypted data length %d\n", len);
781 ies->encsharedkey = (
unsigned char *)(data + 2);
783 snprintf(tmp, (
int)
sizeof(tmp),
"Invalid encrypted shared key length %d\n", len);
789 ies->encsig = (
unsigned char *)(data + 2);
791 snprintf(tmp, (
int)
sizeof(tmp),
"Invalid encrypted signature length %d\n", len);
799 snprintf(tmp, (
int)
sizeof(tmp),
"Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
804 datalen -= (len + 2);
810 errorf(
"Invalid information element contents, strange boundary\n");
#define DUNDI_IE_EXPIRATION
#define DUNDI_IE_EID_DIRECT
Asterisk main include file. File version handling, generic pbx functions.
Distributed Universal Number Discovery (DUNDi) See also.
#define DUNDI_IE_CACHEBYPASS
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
#define DUNDI_IE_SHAREDKEY
#define DUNDI_FLAG_RETRANS
#define DUNDI_IE_DEPARTMENT
#define DUNDI_FLAG_RESERVED
Socket address structure.
An Entity ID is essentially a MAC address, brief and unique.
#define DUNDI_IE_LOCALITY
#define DUNDI_IE_KEYCRC32
#define DUNDI_IE_SIGNATURE
Asterisk internal frame definitions.
static struct agi_command commands[]
AGI commands list.
#define DUNDI_IE_CALLED_CONTEXT
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
#define DUNDI_IE_ORGANIZATION
#define DUNDI_IE_CALLED_NUMBER
#define DUNDI_IE_STATE_PROV
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.