Asterisk - The Open Source Telephony Project GIT-master-f36a736
dundi-parser.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2005, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Distributed Universal Number Discovery (DUNDi)
22 *
23 */
24
25/*** MODULEINFO
26 <support_level>extended</support_level>
27 ***/
28
29#include "asterisk.h"
30
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34
35#include "asterisk/frame.h"
36#include "asterisk/utils.h"
37#include "asterisk/dundi.h"
38#include "dundi-parser.h"
39
40
41static void internaloutput(const char *str)
42{
43 fputs(str, stdout);
44}
45
46static void internalerror(const char *str)
47{
48 fprintf(stderr, "WARNING: %s", str);
49}
50
51static void (*outputf)(const char *str) = internaloutput;
52static void (*errorf)(const char *str) = internalerror;
53
54char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
55{
56 int x;
57 char *os = s;
58 if (maxlen < 13) {
59 if (s && (maxlen > 0))
60 *s = '\0';
61 } else {
62 for (x=0;x<6;x++) {
63 sprintf(s, "%02hhX", (unsigned char)eid->eid[x]);
64 s += 2;
65 }
66 }
67 return os;
68}
69
70int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
71{
72 unsigned int eid_int[6];
73 int x;
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)
76 return -1;
77 for (x = 0; x < 6; x++)
78 eid->eid[x] = eid_int[x];
79 return 0;
80}
81
83{
84 int x;
85 for (x = 0; x < ARRAY_LEN(eid->eid); x++)
86 if (eid->eid[x]) return 0;
87 return 1;
88}
89
90static void dump_string(char *output, int maxlen, void *value, int len)
91{
92 if (maxlen > len + 1)
93 maxlen = len + 1;
94
95 snprintf(output, maxlen, "%s", (char *) value);
96}
97
98static void dump_cbypass(char *output, int maxlen, void *value, int len)
99{
100 snprintf(output, maxlen, "Bypass Caches");
101}
102
103static void dump_eid(char *output, int maxlen, void *value, int len)
104{
105 if (len == 6)
106 ast_eid_to_str(output, maxlen, (dundi_eid *)value);
107 else
108 snprintf(output, maxlen, "Invalid EID len %d", len);
109}
110
111char *dundi_hint2str(char *buf, int bufsiz, int flags)
112{
113 strcpy(buf, "");
114 buf[bufsiz-1] = '\0';
115 if (flags & DUNDI_HINT_TTL_EXPIRED) {
116 strncat(buf, "TTLEXPIRED|", bufsiz - strlen(buf) - 1);
117 }
118 if (flags & DUNDI_HINT_DONT_ASK) {
119 strncat(buf, "DONTASK|", bufsiz - strlen(buf) - 1);
120 }
121 if (flags & DUNDI_HINT_UNAFFECTED) {
122 strncat(buf, "UNAFFECTED|", bufsiz - strlen(buf) - 1);
123 }
124 /* Get rid of trailing | */
125 if (ast_strlen_zero(buf))
126 strcpy(buf, "NONE|");
127 buf[strlen(buf)-1] = '\0';
128 return buf;
129}
130
131static void dump_hint(char *output, int maxlen, void *value, int len)
132{
133 char tmp2[256];
134 char tmp3[256];
135 int datalen;
136 struct dundi_hint *hint;
137 if (len < sizeof(*hint)) {
138 snprintf(output, maxlen, "<invalid contents>");
139 return;
140 }
141
142 hint = (struct dundi_hint *) value;;
143
144 datalen = len - offsetof(struct dundi_hint, data);
145 if (datalen > sizeof(tmp3) - 1)
146 datalen = sizeof(tmp3) - 1;
147
148 memcpy(tmp3, hint->data, datalen);
149 tmp3[datalen] = '\0';
150
151 dundi_hint2str(tmp2, sizeof(tmp2), ntohs(hint->flags));
152
153 if (ast_strlen_zero(tmp3))
154 snprintf(output, maxlen, "[%s]", tmp2);
155 else
156 snprintf(output, maxlen, "[%s] %s", tmp2, tmp3);
157}
158
159static void dump_cause(char *output, int maxlen, void *value, int len)
160{
161 static const char * const causes[] = {
162 "SUCCESS",
163 "GENERAL",
164 "DYNAMIC",
165 "NOAUTH" ,
166 };
167 char tmp2[256];
168 struct dundi_cause *cause;
169 int datalen;
170 int causecode;
171
172 if (len < sizeof(*cause)) {
173 snprintf(output, maxlen, "<invalid contents>");
174 return;
175 }
176
177 cause = (struct dundi_cause*) value;
178 causecode = cause->causecode;
179
180 datalen = len - offsetof(struct dundi_cause, desc);
181 if (datalen > sizeof(tmp2) - 1)
182 datalen = sizeof(tmp2) - 1;
183
184 memcpy(tmp2, cause->desc, datalen);
185 tmp2[datalen] = '\0';
186
187 if (causecode < ARRAY_LEN(causes)) {
188 if (ast_strlen_zero(tmp2))
189 snprintf(output, maxlen, "%s", causes[causecode]);
190 else
191 snprintf(output, maxlen, "%s: %s", causes[causecode], tmp2);
192 } else {
193 if (ast_strlen_zero(tmp2))
194 snprintf(output, maxlen, "%d", causecode);
195 else
196 snprintf(output, maxlen, "%d: %s", causecode, tmp2);
197 }
198}
199
200static void dump_int(char *output, int maxlen, void *value, int len)
201{
202 if (len == (int)sizeof(unsigned int))
203 snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value)));
204 else
205 ast_copy_string(output, "Invalid INT", maxlen);
206}
207
208static void dump_short(char *output, int maxlen, void *value, int len)
209{
210 if (len == (int)sizeof(unsigned short))
211 snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
212 else
213 ast_copy_string(output, "Invalid SHORT", maxlen);
214}
215
216static void dump_byte(char *output, int maxlen, void *value, int len)
217{
218 if (len == (int)sizeof(unsigned char))
219 snprintf(output, maxlen, "%d", *((unsigned char *)value));
220 else
221 ast_copy_string(output, "Invalid BYTE", maxlen);
222}
223
224static char *proto2str(int proto, char *buf, int bufsiz)
225{
226 switch(proto) {
227 case DUNDI_PROTO_NONE:
228 strncpy(buf, "None", bufsiz - 1);
229 break;
230 case DUNDI_PROTO_IAX:
231 strncpy(buf, "IAX", bufsiz - 1);
232 break;
233 case DUNDI_PROTO_SIP:
234 strncpy(buf, "SIP", bufsiz - 1);
235 break;
236 case DUNDI_PROTO_H323:
237 strncpy(buf, "H.323", bufsiz - 1);
238 break;
240 strncpy(buf, "PJSIP", bufsiz - 1);
241 default:
242 snprintf(buf, bufsiz, "Unknown Proto(%d)", proto);
243 }
244 buf[bufsiz-1] = '\0';
245 return buf;
246}
247
248char *dundi_flags2str(char *buf, int bufsiz, int flags)
249{
250 strcpy(buf, "");
251 buf[bufsiz-1] = '\0';
252 if (flags & DUNDI_FLAG_EXISTS) {
253 strncat(buf, "EXISTS|", bufsiz - strlen(buf) - 1);
254 }
255 if (flags & DUNDI_FLAG_MATCHMORE) {
256 strncat(buf, "MATCHMORE|", bufsiz - strlen(buf) - 1);
257 }
258 if (flags & DUNDI_FLAG_CANMATCH) {
259 strncat(buf, "CANMATCH|", bufsiz - strlen(buf) - 1);
260 }
261 if (flags & DUNDI_FLAG_IGNOREPAT) {
262 strncat(buf, "IGNOREPAT|", bufsiz - strlen(buf) - 1);
263 }
264 if (flags & DUNDI_FLAG_RESIDENTIAL) {
265 strncat(buf, "RESIDENCE|", bufsiz - strlen(buf) - 1);
266 }
267 if (flags & DUNDI_FLAG_COMMERCIAL) {
268 strncat(buf, "COMMERCIAL|", bufsiz - strlen(buf) - 1);
269 }
270 if (flags & DUNDI_FLAG_MOBILE) {
271 strncat(buf, "MOBILE", bufsiz - strlen(buf) - 1);
272 }
273 if (flags & DUNDI_FLAG_NOUNSOLICITED) {
274 strncat(buf, "NOUNSLCTD|", bufsiz - strlen(buf) - 1);
275 }
276 if (flags & DUNDI_FLAG_NOCOMUNSOLICIT) {
277 strncat(buf, "NOCOMUNSLTD|", bufsiz - strlen(buf) - 1);
278 }
279 /* Get rid of trailing | */
280 if (ast_strlen_zero(buf))
281 strcpy(buf, "NONE|");
282 buf[strlen(buf)-1] = '\0';
283 return buf;
284}
285
286static void dump_answer(char *output, int maxlen, void *value, int len)
287{
288 struct dundi_answer *answer;
289 char proto[40];
290 char flags[40];
291 char eid_str[40];
292 char tmp[512]="";
293 int datalen;
294
295 if (len < sizeof(*answer)) {
296 snprintf(output, maxlen, "Invalid Answer");
297 return;
298 }
299
300 answer = (struct dundi_answer *)(value);
301
302 datalen = len - offsetof(struct dundi_answer, data);
303 if (datalen > sizeof(tmp) - 1)
304 datalen = sizeof(tmp) - 1;
305
306 memcpy(tmp, answer->data, datalen);
307 tmp[datalen] = '\0';
308
309 ast_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
310 snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]",
311 dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)),
312 ntohs(answer->weight),
313 proto2str(answer->protocol, proto, sizeof(proto)),
314 tmp, eid_str);
315}
316
317static void dump_encrypted(char *output, int maxlen, void *value, int len)
318{
319 char iv[33];
320 int x;
321 if ((len > 16) && !(len % 16)) {
322 /* Build up IV */
323 for (x=0;x<16;x++) {
324 snprintf(iv + (x << 1), 3, "%02hhx", ((unsigned char *)value)[x]);
325 }
326 snprintf(output, maxlen, "[IV %s] %d encrypted blocks\n", iv, len / 16);
327 } else
328 snprintf(output, maxlen, "Invalid Encrypted Datalen %d", len);
329}
330
331static void dump_raw(char *output, int maxlen, void *value, int len)
332{
333 int x;
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]);
339 }
340 strncat(output + strlen(output), "]", maxlen - strlen(output) - 1);
341}
342
343static struct dundi_ie {
344 int ie;
345 char *name;
346 void (*dump)(char *output, int maxlen, void *value, int len);
347} infoelts[] = {
348 { DUNDI_IE_EID, "ENTITY IDENT", dump_eid },
349 { DUNDI_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
350 { DUNDI_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
351 { DUNDI_IE_EID_DIRECT, "DIRECT EID", dump_eid },
352 { DUNDI_IE_ANSWER, "ANSWER", dump_answer },
353 { DUNDI_IE_TTL, "TTL", dump_short },
354 { DUNDI_IE_VERSION, "VERSION", dump_short },
355 { DUNDI_IE_EXPIRATION, "EXPIRATION", dump_short },
356 { DUNDI_IE_UNKNOWN, "UKWN DUNDI CMD", dump_byte },
357 { DUNDI_IE_CAUSE, "CAUSE", dump_cause },
358 { DUNDI_IE_REQEID, "REQUEST EID", dump_eid },
359 { DUNDI_IE_ENCDATA, "ENCDATA", dump_encrypted },
360 { DUNDI_IE_SHAREDKEY, "SHAREDKEY", dump_raw },
361 { DUNDI_IE_SIGNATURE, "SIGNATURE", dump_raw },
362 { DUNDI_IE_KEYCRC32, "KEYCRC32", dump_int },
363 { DUNDI_IE_HINT, "HINT", dump_hint },
364 { DUNDI_IE_DEPARTMENT, "DEPARTMENT", dump_string },
365 { DUNDI_IE_ORGANIZATION, "ORGANIZTN", dump_string },
366 { DUNDI_IE_LOCALITY, "LOCALITY", dump_string },
367 { DUNDI_IE_STATE_PROV, "STATEPROV", dump_string },
368 { DUNDI_IE_COUNTRY, "COUNTRY", dump_string },
369 { DUNDI_IE_EMAIL, "EMAIL", dump_string },
370 { DUNDI_IE_PHONE, "PHONE", dump_string },
371 { DUNDI_IE_IPADDR, "ADDRESS", dump_string },
372 { DUNDI_IE_CACHEBYPASS, "CBYPASS", dump_cbypass },
374
375const char *dundi_ie2str(int ie)
376{
377 int x;
378 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
379 if (infoelts[x].ie == ie)
380 return infoelts[x].name;
381 }
382 return "Unknown IE";
383}
384
385static void dump_ies(unsigned char *iedata, int spaces, int len)
386{
387 int ielen;
388 int ie;
389 int x;
390 int found;
391 char interp[1024];
392 char tmp[1051];
393 if (len < 2)
394 return;
395 while(len >= 2) {
396 ie = iedata[0];
397 ielen = iedata[1];
398 /* Encrypted data is the remainder */
399 if (ie == DUNDI_IE_ENCDATA)
400 ielen = len - 2;
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);
403 outputf(tmp);
404 return;
405 }
406 found = 0;
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);
412 outputf(tmp);
413 } else {
414 if (ielen)
415 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
416 else
417 strcpy(interp, "Present");
418 snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), infoelts[x].name, interp);
419 outputf(tmp);
420 }
421 found++;
422 }
423 }
424 if (!found) {
425 snprintf(tmp, (int)sizeof(tmp), " %sUnknown IE %03d : Present\n", (spaces ? " " : "" ), ie);
426 outputf(tmp);
427 }
428 iedata += (2 + ielen);
429 len -= (2 + ielen);
430 }
431 outputf("\n");
432}
433
434void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
435{
436 char *pref[] = {
437 "Tx",
438 "Rx",
439 " ETx",
440 " Erx" };
441 char *commands[] = {
442 "ACK ",
443 "DPDISCOVER ",
444 "DPRESPONSE ",
445 "EIDQUERY ",
446 "EIDRESPONSE ",
447 "PRECACHERQ ",
448 "PRECACHERP ",
449 "INVALID ",
450 "UNKNOWN CMD ",
451 "NULL ",
452 "REGREQ ",
453 "REGRESPONSE ",
454 "CANCEL ",
455 "ENCRYPT ",
456 "ENCREJ " };
457 char class2[20];
458 char *class;
459 char subclass2[20];
460 char *subclass;
461 char tmp[256];
462 if ((fhi->cmdresp & 0x3f) >= ARRAY_LEN(commands)) {
463 snprintf(class2, sizeof(class2), "(%d?)", fhi->cmdresp & 0x3f);
464 class = class2;
465 } else {
466 class = commands[fhi->cmdresp & 0x3f];
467 }
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",
472 pref[rx],
473 fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");
474 outputf(tmp);
475
476 snprintf(tmp, (int)sizeof(tmp),
477 "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s]%s\n", (rx > 1) ? " " : "",
478 subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,
480 fhi->cmdresp & 0x80 ? " (Final)" : "");
481
482 outputf(tmp);
483 dump_ies(fhi->ies, rx > 1, datalen);
484}
485
486int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
487{
488 char tmp[256];
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);
491 errorf(tmp);
492 return -1;
493 }
494 ied->buf[ied->pos++] = ie;
495 ied->buf[ied->pos++] = datalen;
496 memcpy(ied->buf + ied->pos, data, datalen);
497 ied->pos += datalen;
498 return 0;
499}
500
501int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
502{
503 char tmp[256];
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);
507 errorf(tmp);
508 return -1;
509 }
510 ied->buf[ied->pos++] = ie;
511 ied->buf[ied->pos++] = datalen;
512 ied->buf[ied->pos++] = cause;
513 if (data) {
514 memcpy(ied->buf + ied->pos, data, datalen-1);
515 ied->pos += datalen-1;
516 }
517 return 0;
518}
519
520int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
521{
522 char tmp[256];
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);
526 errorf(tmp);
527 return -1;
528 }
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));
533 ied->pos += 2;
534 if (data) {
535 memcpy(ied->buf + ied->pos, data, datalen-2);
536 ied->pos += datalen-2;
537 }
538 return 0;
539}
540
541int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
542{
543 char tmp[256];
544 datalen += 16;
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);
547 errorf(tmp);
548 return -1;
549 }
550 ied->buf[ied->pos++] = ie;
551 ied->buf[ied->pos++] = datalen;
552 memcpy(ied->buf + ied->pos, iv, 16);
553 ied->pos += 16;
554 if (data) {
555 memcpy(ied->buf + ied->pos, data, datalen-16);
556 ied->pos += datalen-16;
557 }
558 return 0;
559}
560
561int 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)
562{
563 char tmp[256];
564 int datalen = data ? strlen(data) + 11 : 11;
565 int x;
566 unsigned short myw;
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);
569 errorf(tmp);
570 return -1;
571 }
572 ied->buf[ied->pos++] = ie;
573 ied->buf[ied->pos++] = datalen;
574 for (x=0;x<6;x++)
575 ied->buf[ied->pos++] = eid->eid[x];
576 ied->buf[ied->pos++] = protocol;
577 myw = htons(flags);
578 memcpy(ied->buf + ied->pos, &myw, 2);
579 ied->pos += 2;
580 myw = htons(weight);
581 memcpy(ied->buf + ied->pos, &myw, 2);
582 ied->pos += 2;
583 memcpy(ied->buf + ied->pos, data, datalen-11);
584 ied->pos += datalen-11;
585 return 0;
586}
587
588int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
589{
590 return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
591}
592
593int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
594{
595 unsigned int newval;
596 newval = htonl(value);
597 return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
598}
599
600int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
601{
602 unsigned short newval;
603 newval = htons(value);
604 return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
605}
606
607int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
608{
609 return dundi_ie_append_raw(ied, ie, str, strlen(str));
610}
611
612int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
613{
614 return dundi_ie_append_raw(ied, ie, (unsigned char *)eid, sizeof(dundi_eid));
615}
616
617int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
618{
619 return dundi_ie_append_raw(ied, ie, &dat, 1);
620}
621
622int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
623{
624 return dundi_ie_append_raw(ied, ie, NULL, 0);
625}
626
627void dundi_set_output(void (*func)(const char *))
628{
629 outputf = func;
630}
631
632void dundi_set_error(void (*func)(const char *))
633{
634 errorf = func;
635}
636
637int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
638{
639 /* Parse data into information elements */
640 int len;
641 int ie;
642 char tmp[256];
643 memset(ies, 0, (int)sizeof(struct dundi_ies));
644 ies->ttl = -1;
645 ies->expiration = -1;
646 ies->unknowncmd = -1;
647 ies->cause = -1;
648 while(datalen >= 2) {
649 ie = data[0];
650 len = data[1];
651 if (len > datalen - 2) {
652 errorf("Information element length exceeds message size\n");
653 return -1;
654 }
655 switch(ie) {
656 case DUNDI_IE_EID:
658 if (len != (int)sizeof(dundi_eid)) {
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);
662 ies->eid_direct[ies->eidcount] = (ie == DUNDI_IE_EID_DIRECT);
663 ies->eidcount++;
664 } else
665 errorf("Too many entities in stack!\n");
666 break;
667 case DUNDI_IE_REQEID:
668 if (len != (int)sizeof(dundi_eid)) {
669 errorf("Improper requested entity identifer, expecting 6 bytes!\n");
670 } else
671 ies->reqeid = (dundi_eid *)(data + 2);
672 break;
674 ies->called_context = (char *)data + 2;
675 break;
677 ies->called_number = (char *)data + 2;
678 break;
679 case DUNDI_IE_ANSWER:
680 if (len < sizeof(struct dundi_answer)) {
681 snprintf(tmp, (int)sizeof(tmp), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer), len);
682 errorf(tmp);
683 } else {
684 if (ies->anscount < DUNDI_MAX_ANSWERS)
685 ies->answers[ies->anscount++]= (struct dundi_answer *)(data + 2);
686 else
687 errorf("Ignoring extra answers!\n");
688 }
689 break;
690 case DUNDI_IE_TTL:
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);
693 errorf(tmp);
694 } else
695 ies->ttl = ntohs(*((unsigned short *)(data + 2)));
696 break;
697 case DUNDI_IE_VERSION:
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);
700 errorf(tmp);
701 } else
702 ies->version = ntohs(*((unsigned short *)(data + 2)));
703 break;
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);
707 errorf(tmp);
708 } else
709 ies->expiration = ntohs(*((unsigned short *)(data + 2)));
710 break;
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);
714 errorf(tmp);
715 } else
716 ies->keycrc32 = ntohl(*((unsigned int *)(data + 2)));
717 break;
718 case DUNDI_IE_UNKNOWN:
719 if (len == 1)
720 ies->unknowncmd = data[2];
721 else {
722 snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
723 errorf(tmp);
724 }
725 break;
726 case DUNDI_IE_CAUSE:
727 if (len >= 1) {
728 ies->cause = data[2];
729 ies->causestr = (char *)data + 3;
730 } else {
731 snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len);
732 errorf(tmp);
733 }
734 break;
735 case DUNDI_IE_HINT:
736 if (len >= 2) {
737 ies->hint = (struct dundi_hint *)(data + 2);
738 } else {
739 snprintf(tmp, (int)sizeof(tmp), "Expected at least two byte hint, but was %d long\n", len);
740 errorf(tmp);
741 }
742 break;
744 ies->q_dept = (char *)data + 2;
745 break;
747 ies->q_org = (char *)data + 2;
748 break;
750 ies->q_locality = (char *)data + 2;
751 break;
753 ies->q_stateprov = (char *)data + 2;
754 break;
755 case DUNDI_IE_COUNTRY:
756 ies->q_country = (char *)data + 2;
757 break;
758 case DUNDI_IE_EMAIL:
759 ies->q_email = (char *)data + 2;
760 break;
761 case DUNDI_IE_PHONE:
762 ies->q_phone = (char *)data + 2;
763 break;
764 case DUNDI_IE_IPADDR:
765 ies->q_ipaddr = (char *)data + 2;
766 break;
767 case DUNDI_IE_ENCDATA:
768 /* Recalculate len as the remainder of the message, regardless of
769 theoretical length */
770 len = datalen - 2;
771 if ((len > 16) && !(len % 16)) {
772 ies->encblock = (struct dundi_encblock *)(data + 2);
773 ies->enclen = len - 16;
774 } else {
775 snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted data length %d\n", len);
776 errorf(tmp);
777 }
778 break;
780 if (len == 128) {
781 ies->encsharedkey = (unsigned char *)(data + 2);
782 } else {
783 snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted shared key length %d\n", len);
784 errorf(tmp);
785 }
786 break;
788 if (len == 128) {
789 ies->encsig = (unsigned char *)(data + 2);
790 } else {
791 snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted signature length %d\n", len);
792 errorf(tmp);
793 }
794 break;
796 ies->cbypass = 1;
797 break;
798 default:
799 snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
800 outputf(tmp);
801 }
802 /* Overwrite information element with 0, to null terminate previous portion */
803 data[0] = 0;
804 datalen -= (len + 2);
805 data += (len + 2);
806 }
807 /* Null-terminate last field */
808 *data = '\0';
809 if (datalen) {
810 errorf("Invalid information element contents, strange boundary\n");
811 return -1;
812 }
813 return 0;
814}
char weight
const char * str
Definition: app_jack.c:147
Asterisk main include file. File version handling, generic pbx functions.
static int tmp()
Definition: bt_open.c:389
static const char desc[]
Definition: cdr_radius.c:84
static int answer(void *data)
Definition: chan_pjsip.c:687
static const struct causes_map causes[]
Definition: channel.c:136
int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
Definition: dundi-parser.c:593
static void dump_int(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:200
static void dump_encrypted(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:317
int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
Definition: dundi-parser.c:541
static void dump_raw(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:331
static void dump_ies(unsigned char *iedata, int spaces, int len)
Definition: dundi-parser.c:385
void dundi_set_output(void(*func)(const char *))
Definition: dundi-parser.c:627
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
Definition: dundi-parser.c:486
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
Definition: dundi-parser.c:70
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)
Definition: dundi-parser.c:561
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:612
int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
Definition: dundi-parser.c:617
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:600
int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
Definition: dundi-parser.c:588
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
Definition: dundi-parser.c:622
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:248
static void dump_short(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:208
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
Definition: dundi-parser.c:637
static void(* errorf)(const char *str)
Definition: dundi-parser.c:52
static char * proto2str(int proto, char *buf, int bufsiz)
Definition: dundi-parser.c:224
static void dump_answer(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:286
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:434
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
Definition: dundi-parser.c:607
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:54
static void dump_string(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:90
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:82
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:501
static void dump_hint(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:131
static void dump_cbypass(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:98
static void internalerror(const char *str)
Definition: dundi-parser.c:46
const char * dundi_ie2str(int ie)
Definition: dundi-parser.c:375
void dundi_set_error(void(*func)(const char *))
Definition: dundi-parser.c:632
static void dump_byte(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:216
static void(* outputf)(const char *str)
Definition: dundi-parser.c:51
static struct dundi_ie infoelts[]
static void dump_eid(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:103
static void internaloutput(const char *str)
Definition: dundi-parser.c:41
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:520
char * dundi_hint2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:111
static void dump_cause(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:159
#define DUNDI_MAX_STACK
Definition: dundi-parser.h:18
#define DUNDI_MAX_ANSWERS
Definition: dundi-parser.h:19
Distributed Universal Number Discovery (DUNDi) See also.
#define DUNDI_IE_COUNTRY
Definition: dundi.h:205
#define DUNDI_IE_VERSION
Definition: dundi.h:190
#define DUNDI_IE_CACHEBYPASS
Definition: dundi.h:209
#define DUNDI_FLAG_RETRANS
Definition: dundi.h:50
#define DUNDI_IE_ENCDATA
Definition: dundi.h:195
#define DUNDI_IE_IPADDR
Definition: dundi.h:208
#define DUNDI_IE_DEPARTMENT
Definition: dundi.h:201
#define DUNDI_IE_ORGANIZATION
Definition: dundi.h:202
#define DUNDI_IE_TTL
Definition: dundi.h:189
#define DUNDI_IE_LOCALITY
Definition: dundi.h:203
#define DUNDI_IE_SIGNATURE
Definition: dundi.h:197
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:191
#define DUNDI_IE_HINT
Definition: dundi.h:199
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:185
#define DUNDI_IE_CAUSE
Definition: dundi.h:193
#define DUNDI_IE_PHONE
Definition: dundi.h:207
#define DUNDI_IE_REQEID
Definition: dundi.h:194
#define DUNDI_IE_CALLED_NUMBER
Definition: dundi.h:186
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:187
#define DUNDI_IE_EID
Definition: dundi.h:184
#define DUNDI_IE_SHAREDKEY
Definition: dundi.h:196
#define DUNDI_IE_UNKNOWN
Definition: dundi.h:192
#define DUNDI_IE_KEYCRC32
Definition: dundi.h:198
@ DUNDI_PROTO_NONE
Definition: dundi.h:55
@ DUNDI_PROTO_PJSIP
Definition: dundi.h:63
@ DUNDI_PROTO_SIP
Definition: dundi.h:59
@ DUNDI_PROTO_IAX
Definition: dundi.h:57
@ DUNDI_PROTO_H323
Definition: dundi.h:61
#define DUNDI_IE_EMAIL
Definition: dundi.h:206
#define DUNDI_FLAG_RESERVED
Definition: dundi.h:51
@ DUNDI_FLAG_MOBILE
Definition: dundi.h:82
@ DUNDI_FLAG_COMMERCIAL
Definition: dundi.h:80
@ DUNDI_FLAG_NOCOMUNSOLICIT
Definition: dundi.h:86
@ DUNDI_FLAG_CANMATCH
Definition: dundi.h:74
@ DUNDI_FLAG_MATCHMORE
Definition: dundi.h:72
@ DUNDI_FLAG_RESIDENTIAL
Definition: dundi.h:78
@ DUNDI_FLAG_EXISTS
Definition: dundi.h:70
@ DUNDI_FLAG_IGNOREPAT
Definition: dundi.h:76
@ DUNDI_FLAG_NOUNSOLICITED
Definition: dundi.h:84
#define DUNDI_IE_STATE_PROV
Definition: dundi.h:204
@ DUNDI_HINT_DONT_ASK
Definition: dundi.h:94
@ DUNDI_HINT_UNAFFECTED
Definition: dundi.h:96
@ DUNDI_HINT_TTL_EXPIRED
Definition: dundi.h:92
#define DUNDI_IE_ANSWER
Definition: dundi.h:188
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Asterisk internal frame definitions.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3746
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
unsigned char eid[6]
Definition: utils.h:814
Socket address structure.
Definition: netsock2.h:97
unsigned short flags
Definition: dundi.h:107
unsigned char data[0]
Definition: dundi.h:109
char desc[0]
Definition: dundi.h:138
unsigned char causecode
Definition: dundi.h:137
unsigned short strans
Definition: dundi.h:35
unsigned char ies[0]
Definition: dundi.h:41
unsigned char cmdflags
Definition: dundi.h:40
unsigned char cmdresp
Definition: dundi.h:39
unsigned char iseqno
Definition: dundi.h:37
unsigned short dtrans
Definition: dundi.h:36
unsigned char oseqno
Definition: dundi.h:38
unsigned short flags
Definition: dundi.h:113
unsigned char data[0]
Definition: dundi.h:114
unsigned char buf[8192]
Definition: dundi-parser.h:56
char * name
Definition: dundi-parser.c:345
void(* dump)(char *output, int maxlen, void *value, int len)
Definition: dundi-parser.c:346
struct dundi_answer * answers[DUNDI_MAX_ANSWERS+1]
Definition: dundi-parser.h:28
char * causestr
Definition: dundi-parser.h:45
char * q_org
Definition: dundi-parser.h:38
dundi_eid * reqeid
Definition: dundi-parser.h:24
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
char * called_context
Definition: dundi-parser.h:26
int eid_direct[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:23
char * q_country
Definition: dundi-parser.h:41
int unknowncmd
Definition: dundi-parser.h:34
char * q_phone
Definition: dundi-parser.h:43
char * q_locality
Definition: dundi-parser.h:39
char * q_ipaddr
Definition: dundi-parser.h:44
char * called_number
Definition: dundi-parser.h:27
int eidcount
Definition: dundi-parser.h:25
unsigned long keycrc32
Definition: dundi-parser.h:48
unsigned char * encsharedkey
Definition: dundi-parser.h:46
struct dundi_hint * hint
Definition: dundi-parser.h:29
int anscount
Definition: dundi-parser.h:30
char * q_email
Definition: dundi-parser.h:42
unsigned char * encsig
Definition: dundi-parser.h:47
char * q_dept
Definition: dundi-parser.h:37
int expiration
Definition: dundi-parser.h:33
char * q_stateprov
Definition: dundi-parser.h:40
struct dundi_encblock * encblock
Definition: dundi-parser.h:49
int value
Definition: syslog.c:37
Utility functions.
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
#define ARRAY_LEN(a)
Definition: utils.h:666