2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief Distributed Universal Number Discovery (DUNDi)
27 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
38 #include "asterisk/frame.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/dundi.h"
41 #include "dundi-parser.h"
42 #include "asterisk/dundi.h"
44 static void internaloutput(const char *str
)
49 static void internalerror(const char *str
)
51 fprintf(stderr
, "WARNING: %s", str
);
54 static void (*outputf
)(const char *str
) = internaloutput
;
55 static void (*errorf
)(const char *str
) = internalerror
;
57 char *dundi_eid_to_str(char *s
, int maxlen
, dundi_eid
*eid
)
62 if (s
&& (maxlen
> 0))
66 sprintf(s
, "%02x:", eid
->eid
[x
]);
69 sprintf(s
, "%02x", eid
->eid
[5]);
74 char *dundi_eid_to_str_short(char *s
, int maxlen
, dundi_eid
*eid
)
79 if (s
&& (maxlen
> 0))
83 sprintf(s
, "%02X", eid
->eid
[x
]);
90 int dundi_str_to_eid(dundi_eid
*eid
, char *s
)
92 unsigned int eid_int
[6];
94 if (sscanf(s
, "%x:%x:%x:%x:%x:%x", &eid_int
[0], &eid_int
[1], &eid_int
[2],
95 &eid_int
[3], &eid_int
[4], &eid_int
[5]) != 6)
98 eid
->eid
[x
] = eid_int
[x
];
102 int dundi_str_short_to_eid(dundi_eid
*eid
, char *s
)
104 unsigned int eid_int
[6];
106 if (sscanf(s
, "%2x%2x%2x%2x%2x%2x", &eid_int
[0], &eid_int
[1], &eid_int
[2],
107 &eid_int
[3], &eid_int
[4], &eid_int
[5]) != 6)
110 eid
->eid
[x
] = eid_int
[x
];
114 int dundi_eid_zero(dundi_eid
*eid
)
117 for (x
=0;x
<sizeof(eid
->eid
) / sizeof(eid
->eid
[0]);x
++)
118 if (eid
->eid
[x
]) return 0;
122 int dundi_eid_cmp(dundi_eid
*eid1
, dundi_eid
*eid2
)
124 return memcmp(eid1
, eid2
, sizeof(dundi_eid
));
127 static void dump_string(char *output
, int maxlen
, void *value
, int len
)
132 strncpy(output
, value
, maxlen
);
133 output
[maxlen
] = '\0';
136 static void dump_cbypass(char *output
, int maxlen
, void *value
, int len
)
139 strncpy(output
, "Bypass Caches", maxlen
);
140 output
[maxlen
] = '\0';
143 static void dump_eid(char *output
, int maxlen
, void *value
, int len
)
146 dundi_eid_to_str(output
, maxlen
, (dundi_eid
*)value
);
148 snprintf(output
, maxlen
, "Invalid EID len %d", len
);
151 char *dundi_hint2str(char *buf
, int bufsiz
, int flags
)
154 buf
[bufsiz
-1] = '\0';
155 if (flags
& DUNDI_HINT_TTL_EXPIRED
) {
156 strncat(buf
, "TTLEXPIRED|", bufsiz
- strlen(buf
) - 1);
158 if (flags
& DUNDI_HINT_DONT_ASK
) {
159 strncat(buf
, "DONTASK|", bufsiz
- strlen(buf
) - 1);
161 if (flags
& DUNDI_HINT_UNAFFECTED
) {
162 strncat(buf
, "UNAFFECTED|", bufsiz
- strlen(buf
) - 1);
164 /* Get rid of trailing | */
165 if (ast_strlen_zero(buf
))
166 strcpy(buf
, "NONE|");
167 buf
[strlen(buf
)-1] = '\0';
171 static void dump_hint(char *output
, int maxlen
, void *value
, int len
)
173 unsigned short flags
;
177 strncpy(output
, "<invalid contents>", maxlen
);
180 memcpy(&flags
, value
, sizeof(flags
));
181 flags
= ntohs(flags
);
182 memset(tmp
, 0, sizeof(tmp
));
183 dundi_hint2str(tmp2
, sizeof(tmp2
), flags
);
184 snprintf(tmp
, sizeof(tmp
), "[%s] ", tmp2
);
185 memcpy(tmp
+ strlen(tmp
), value
+ 2, len
- 2);
186 strncpy(output
, tmp
, maxlen
- 1);
189 static void dump_cause(char *output
, int maxlen
, void *value
, int len
)
191 static char *causes
[] = {
202 strncpy(output
, "<invalid contents>", maxlen
);
205 cause
= *((unsigned char *)value
);
206 memset(tmp2
, 0, sizeof(tmp2
));
210 memcpy(tmp2
, value
+ 1, mlen
);
211 if (cause
< sizeof(causes
) / sizeof(causes
[0])) {
213 snprintf(tmp
, sizeof(tmp
), "%s: %s", causes
[cause
], tmp2
);
215 snprintf(tmp
, sizeof(tmp
), "%s", causes
[cause
]);
218 snprintf(tmp
, sizeof(tmp
), "%d: %s", cause
, tmp2
);
220 snprintf(tmp
, sizeof(tmp
), "%d", cause
);
223 strncpy(output
,tmp
, maxlen
);
224 output
[maxlen
] = '\0';
227 static void dump_int(char *output
, int maxlen
, void *value
, int len
)
229 if (len
== (int)sizeof(unsigned int))
230 snprintf(output
, maxlen
, "%lu", (unsigned long)ntohl(*((unsigned int *)value
)));
232 snprintf(output
, maxlen
, "Invalid INT");
235 static void dump_short(char *output
, int maxlen
, void *value
, int len
)
237 if (len
== (int)sizeof(unsigned short))
238 snprintf(output
, maxlen
, "%d", ntohs(*((unsigned short *)value
)));
240 snprintf(output
, maxlen
, "Invalid SHORT");
243 static void dump_byte(char *output
, int maxlen
, void *value
, int len
)
245 if (len
== (int)sizeof(unsigned char))
246 snprintf(output
, maxlen
, "%d", *((unsigned char *)value
));
248 snprintf(output
, maxlen
, "Invalid BYTE");
251 static char *proto2str(int proto
, char *buf
, int bufsiz
)
254 case DUNDI_PROTO_NONE
:
255 strncpy(buf
, "None", bufsiz
- 1);
257 case DUNDI_PROTO_IAX
:
258 strncpy(buf
, "IAX", bufsiz
- 1);
260 case DUNDI_PROTO_SIP
:
261 strncpy(buf
, "SIP", bufsiz
- 1);
263 case DUNDI_PROTO_H323
:
264 strncpy(buf
, "H.323", bufsiz
- 1);
267 snprintf(buf
, bufsiz
, "Unknown Proto(%d)", proto
);
269 buf
[bufsiz
-1] = '\0';
273 char *dundi_flags2str(char *buf
, int bufsiz
, int flags
)
276 buf
[bufsiz
-1] = '\0';
277 if (flags
& DUNDI_FLAG_EXISTS
) {
278 strncat(buf
, "EXISTS|", bufsiz
- strlen(buf
) - 1);
280 if (flags
& DUNDI_FLAG_MATCHMORE
) {
281 strncat(buf
, "MATCHMORE|", bufsiz
- strlen(buf
) - 1);
283 if (flags
& DUNDI_FLAG_CANMATCH
) {
284 strncat(buf
, "CANMATCH|", bufsiz
- strlen(buf
) - 1);
286 if (flags
& DUNDI_FLAG_IGNOREPAT
) {
287 strncat(buf
, "IGNOREPAT|", bufsiz
- strlen(buf
) - 1);
289 if (flags
& DUNDI_FLAG_RESIDENTIAL
) {
290 strncat(buf
, "RESIDENCE|", bufsiz
- strlen(buf
) - 1);
292 if (flags
& DUNDI_FLAG_COMMERCIAL
) {
293 strncat(buf
, "COMMERCIAL|", bufsiz
- strlen(buf
) - 1);
295 if (flags
& DUNDI_FLAG_MOBILE
) {
296 strncat(buf
, "MOBILE", bufsiz
- strlen(buf
) - 1);
298 if (flags
& DUNDI_FLAG_NOUNSOLICITED
) {
299 strncat(buf
, "NOUNSLCTD|", bufsiz
- strlen(buf
) - 1);
301 if (flags
& DUNDI_FLAG_NOCOMUNSOLICIT
) {
302 strncat(buf
, "NOCOMUNSLTD|", bufsiz
- strlen(buf
) - 1);
304 /* Get rid of trailing | */
305 if (ast_strlen_zero(buf
))
306 strcpy(buf
, "NONE|");
307 buf
[strlen(buf
)-1] = '\0';
311 static void dump_answer(char *output
, int maxlen
, void *value
, int len
)
313 struct dundi_answer
*answer
;
319 answer
= (struct dundi_answer
*)(value
);
320 memcpy(tmp
, answer
->data
, (len
>= 500) ? 500 : len
- 10);
321 dundi_eid_to_str(eid_str
, sizeof(eid_str
), &answer
->eid
);
322 snprintf(output
, maxlen
, "[%s] %d <%s/%s> from [%s]",
323 dundi_flags2str(flags
, sizeof(flags
), ntohs(answer
->flags
)),
324 ntohs(answer
->weight
),
325 proto2str(answer
->protocol
, proto
, sizeof(proto
)),
328 strncpy(output
, "Invalid Answer", maxlen
- 1);
331 static void dump_encrypted(char *output
, int maxlen
, void *value
, int len
)
335 if ((len
> 16) && !(len
% 16)) {
338 snprintf(iv
+ (x
<< 1), 3, "%02x", ((unsigned char *)value
)[x
]);
340 snprintf(output
, maxlen
, "[IV %s] %d encrypted blocks\n", iv
, len
/ 16);
342 snprintf(output
, maxlen
, "Invalid Encrypted Datalen %d", len
);
345 static void dump_raw(char *output
, int maxlen
, void *value
, int len
)
348 unsigned char *u
= value
;
349 output
[maxlen
- 1] = '\0';
350 strcpy(output
, "[ ");
351 for (x
=0;x
<len
;x
++) {
352 snprintf(output
+ strlen(output
), maxlen
- strlen(output
) - 1, "%02x ", u
[x
]);
354 strncat(output
+ strlen(output
), "]", maxlen
- strlen(output
) - 1);
357 static struct dundi_ie
{
360 void (*dump
)(char *output
, int maxlen
, void *value
, int len
);
362 { DUNDI_IE_EID
, "ENTITY IDENT", dump_eid
},
363 { DUNDI_IE_CALLED_CONTEXT
, "CALLED CONTEXT", dump_string
},
364 { DUNDI_IE_CALLED_NUMBER
, "CALLED NUMBER", dump_string
},
365 { DUNDI_IE_EID_DIRECT
, "DIRECT EID", dump_eid
},
366 { DUNDI_IE_ANSWER
, "ANSWER", dump_answer
},
367 { DUNDI_IE_TTL
, "TTL", dump_short
},
368 { DUNDI_IE_VERSION
, "VERSION", dump_short
},
369 { DUNDI_IE_EXPIRATION
, "EXPIRATION", dump_short
},
370 { DUNDI_IE_UNKNOWN
, "UKWN DUNDI CMD", dump_byte
},
371 { DUNDI_IE_CAUSE
, "CAUSE", dump_cause
},
372 { DUNDI_IE_REQEID
, "REQUEST EID", dump_eid
},
373 { DUNDI_IE_ENCDATA
, "ENCDATA", dump_encrypted
},
374 { DUNDI_IE_SHAREDKEY
, "SHAREDKEY", dump_raw
},
375 { DUNDI_IE_SIGNATURE
, "SIGNATURE", dump_raw
},
376 { DUNDI_IE_KEYCRC32
, "KEYCRC32", dump_int
},
377 { DUNDI_IE_HINT
, "HINT", dump_hint
},
378 { DUNDI_IE_DEPARTMENT
, "DEPARTMENT", dump_string
},
379 { DUNDI_IE_ORGANIZATION
, "ORGANIZTN", dump_string
},
380 { DUNDI_IE_LOCALITY
, "LOCALITY", dump_string
},
381 { DUNDI_IE_STATE_PROV
, "STATEPROV", dump_string
},
382 { DUNDI_IE_COUNTRY
, "COUNTRY", dump_string
},
383 { DUNDI_IE_EMAIL
, "EMAIL", dump_string
},
384 { DUNDI_IE_PHONE
, "PHONE", dump_string
},
385 { DUNDI_IE_IPADDR
, "ADDRESS", dump_string
},
386 { DUNDI_IE_CACHEBYPASS
, "CBYPASS", dump_cbypass
},
389 const char *dundi_ie2str(int ie
)
392 for (x
=0;x
<(int)sizeof(ies
) / (int)sizeof(ies
[0]); x
++) {
399 static void dump_ies(unsigned char *iedata
, int spaces
, int len
)
412 /* Encrypted data is the remainder */
413 if (ie
== DUNDI_IE_ENCDATA
)
415 if (ielen
+ 2> len
) {
416 snprintf(tmp
, (int)sizeof(tmp
), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen
+ 2, len
);
421 for (x
=0;x
<(int)sizeof(ies
) / (int)sizeof(ies
[0]); x
++) {
422 if (ies
[x
].ie
== ie
) {
424 ies
[x
].dump(interp
, (int)sizeof(interp
), iedata
+ 2, ielen
);
425 snprintf(tmp
, (int)sizeof(tmp
), " %s%-15.15s : %s\n", (spaces
? " " : "" ), ies
[x
].name
, interp
);
429 snprintf(interp
, (int)sizeof(interp
), "%d bytes", ielen
);
431 strcpy(interp
, "Present");
432 snprintf(tmp
, (int)sizeof(tmp
), " %s%-15.15s : %s\n", (spaces
? " " : "" ), ies
[x
].name
, interp
);
439 snprintf(tmp
, (int)sizeof(tmp
), " %sUnknown IE %03d : Present\n", (spaces
? " " : "" ), ie
);
442 iedata
+= (2 + ielen
);
448 void dundi_showframe(struct dundi_hdr
*fhi
, int rx
, struct sockaddr_in
*sin
, int datalen
)
477 if (ntohs(fhi
->dtrans
) & DUNDI_FLAG_RETRANS
)
478 strcpy(retries
, "Yes");
480 strcpy(retries
, "No");
481 if ((ntohs(fhi
->strans
) & DUNDI_FLAG_RESERVED
)) {
482 /* Ignore frames with high bit set to 1 */
485 if ((fhi
->cmdresp
& 0x3f) > (int)sizeof(commands
)/(int)sizeof(char *)) {
486 snprintf(class2
, (int)sizeof(class2
), "(%d?)", fhi
->cmdresp
);
489 class = commands
[(int)(fhi
->cmdresp
& 0x3f)];
491 snprintf(subclass2
, (int)sizeof(subclass2
), "%02x", fhi
->cmdflags
);
492 subclass
= subclass2
;
493 snprintf(tmp
, (int)sizeof(tmp
),
494 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n",
496 retries
, fhi
->oseqno
, fhi
->iseqno
, class, fhi
->cmdresp
& 0x40 ? "Response" : "Command");
498 snprintf(tmp
, (int)sizeof(tmp
),
499 "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s:%d]%s\n", (rx
> 1) ? " " : "",
500 subclass
, ntohs(fhi
->strans
) & ~DUNDI_FLAG_RESERVED
, ntohs(fhi
->dtrans
) & ~DUNDI_FLAG_RETRANS
,
501 ast_inet_ntoa(sin
->sin_addr
), ntohs(sin
->sin_port
),
502 fhi
->cmdresp
& 0x80 ? " (Final)" : "");
504 dump_ies(fhi
->ies
, rx
> 1, datalen
);
507 int dundi_ie_append_raw(struct dundi_ie_data
*ied
, unsigned char ie
, void *data
, int datalen
)
510 if (datalen
> ((int)sizeof(ied
->buf
) - ied
->pos
)) {
511 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
);
515 ied
->buf
[ied
->pos
++] = ie
;
516 ied
->buf
[ied
->pos
++] = datalen
;
517 memcpy(ied
->buf
+ ied
->pos
, data
, datalen
);
522 int dundi_ie_append_cause(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned char cause
, char *data
)
525 int datalen
= data
? strlen(data
) + 1 : 1;
526 if (datalen
> ((int)sizeof(ied
->buf
) - ied
->pos
)) {
527 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
);
531 ied
->buf
[ied
->pos
++] = ie
;
532 ied
->buf
[ied
->pos
++] = datalen
;
533 ied
->buf
[ied
->pos
++] = cause
;
534 memcpy(ied
->buf
+ ied
->pos
, data
, datalen
-1);
535 ied
->pos
+= datalen
-1;
539 int dundi_ie_append_hint(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned short flags
, char *data
)
542 int datalen
= data
? strlen(data
) + 2 : 2;
543 if (datalen
> ((int)sizeof(ied
->buf
) - ied
->pos
)) {
544 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
);
548 ied
->buf
[ied
->pos
++] = ie
;
549 ied
->buf
[ied
->pos
++] = datalen
;
550 flags
= htons(flags
);
551 memcpy(ied
->buf
+ ied
->pos
, &flags
, sizeof(flags
));
553 memcpy(ied
->buf
+ ied
->pos
, data
, datalen
-1);
554 ied
->pos
+= datalen
-2;
558 int dundi_ie_append_encdata(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned char *iv
, void *data
, int datalen
)
562 if (datalen
> ((int)sizeof(ied
->buf
) - ied
->pos
)) {
563 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
);
567 ied
->buf
[ied
->pos
++] = ie
;
568 ied
->buf
[ied
->pos
++] = datalen
;
569 memcpy(ied
->buf
+ ied
->pos
, iv
, 16);
572 memcpy(ied
->buf
+ ied
->pos
, data
, datalen
-16);
573 ied
->pos
+= datalen
-16;
578 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
)
581 int datalen
= data
? strlen(data
) + 11 : 11;
584 if (datalen
> ((int)sizeof(ied
->buf
) - ied
->pos
)) {
585 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
);
589 ied
->buf
[ied
->pos
++] = ie
;
590 ied
->buf
[ied
->pos
++] = datalen
;
592 ied
->buf
[ied
->pos
++] = eid
->eid
[x
];
593 ied
->buf
[ied
->pos
++] = protocol
;
595 memcpy(ied
->buf
+ ied
->pos
, &myw
, 2);
598 memcpy(ied
->buf
+ ied
->pos
, &myw
, 2);
600 memcpy(ied
->buf
+ ied
->pos
, data
, datalen
-11);
601 ied
->pos
+= datalen
-11;
605 int dundi_ie_append_addr(struct dundi_ie_data
*ied
, unsigned char ie
, struct sockaddr_in
*sin
)
607 return dundi_ie_append_raw(ied
, ie
, sin
, (int)sizeof(struct sockaddr_in
));
610 int dundi_ie_append_int(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned int value
)
613 newval
= htonl(value
);
614 return dundi_ie_append_raw(ied
, ie
, &newval
, (int)sizeof(newval
));
617 int dundi_ie_append_short(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned short value
)
619 unsigned short newval
;
620 newval
= htons(value
);
621 return dundi_ie_append_raw(ied
, ie
, &newval
, (int)sizeof(newval
));
624 int dundi_ie_append_str(struct dundi_ie_data
*ied
, unsigned char ie
, char *str
)
626 return dundi_ie_append_raw(ied
, ie
, str
, strlen(str
));
629 int dundi_ie_append_eid(struct dundi_ie_data
*ied
, unsigned char ie
, dundi_eid
*eid
)
631 return dundi_ie_append_raw(ied
, ie
, (unsigned char *)eid
, sizeof(dundi_eid
));
634 int dundi_ie_append_byte(struct dundi_ie_data
*ied
, unsigned char ie
, unsigned char dat
)
636 return dundi_ie_append_raw(ied
, ie
, &dat
, 1);
639 int dundi_ie_append(struct dundi_ie_data
*ied
, unsigned char ie
)
641 return dundi_ie_append_raw(ied
, ie
, NULL
, 0);
644 void dundi_set_output(void (*func
)(const char *))
649 void dundi_set_error(void (*func
)(const char *))
654 int dundi_parse_ies(struct dundi_ies
*ies
, unsigned char *data
, int datalen
)
656 /* Parse data into information elements */
660 memset(ies
, 0, (int)sizeof(struct dundi_ies
));
662 ies
->expiration
= -1;
663 ies
->unknowncmd
= -1;
665 while(datalen
>= 2) {
668 if (len
> datalen
- 2) {
669 errorf("Information element length exceeds message size\n");
674 case DUNDI_IE_EID_DIRECT
:
675 if (len
!= (int)sizeof(dundi_eid
)) {
676 errorf("Improper entity identifer, expecting 6 bytes!\n");
677 } else if (ies
->eidcount
< DUNDI_MAX_STACK
) {
678 ies
->eids
[ies
->eidcount
] = (dundi_eid
*)(data
+ 2);
679 ies
->eid_direct
[ies
->eidcount
] = (ie
== DUNDI_IE_EID_DIRECT
);
682 errorf("Too many entities in stack!\n");
684 case DUNDI_IE_REQEID
:
685 if (len
!= (int)sizeof(dundi_eid
)) {
686 errorf("Improper requested entity identifer, expecting 6 bytes!\n");
688 ies
->reqeid
= (dundi_eid
*)(data
+ 2);
690 case DUNDI_IE_CALLED_CONTEXT
:
691 ies
->called_context
= (char *)data
+ 2;
693 case DUNDI_IE_CALLED_NUMBER
:
694 ies
->called_number
= (char *)data
+ 2;
696 case DUNDI_IE_ANSWER
:
697 if (len
< sizeof(struct dundi_answer
)) {
698 snprintf(tmp
, (int)sizeof(tmp
), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer
), len
);
701 if (ies
->anscount
< DUNDI_MAX_ANSWERS
)
702 ies
->answers
[ies
->anscount
++]= (struct dundi_answer
*)(data
+ 2);
704 errorf("Ignoring extra answers!\n");
708 if (len
!= (int)sizeof(unsigned short)) {
709 snprintf(tmp
, (int)sizeof(tmp
), "Expecting ttl to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len
);
712 ies
->ttl
= ntohs(*((unsigned short *)(data
+ 2)));
714 case DUNDI_IE_VERSION
:
715 if (len
!= (int)sizeof(unsigned short)) {
716 snprintf(tmp
, (int)sizeof(tmp
), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len
);
719 ies
->version
= ntohs(*((unsigned short *)(data
+ 2)));
721 case DUNDI_IE_EXPIRATION
:
722 if (len
!= (int)sizeof(unsigned short)) {
723 snprintf(tmp
, (int)sizeof(tmp
), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len
);
726 ies
->expiration
= ntohs(*((unsigned short *)(data
+ 2)));
728 case DUNDI_IE_KEYCRC32
:
729 if (len
!= (int)sizeof(unsigned int)) {
730 snprintf(tmp
, (int)sizeof(tmp
), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len
);
733 ies
->keycrc32
= ntohl(*((unsigned int *)(data
+ 2)));
735 case DUNDI_IE_UNKNOWN
:
737 ies
->unknowncmd
= data
[2];
739 snprintf(tmp
, (int)sizeof(tmp
), "Expected single byte Unknown command, but was %d long\n", len
);
745 ies
->cause
= data
[2];
746 ies
->causestr
= (char *)data
+ 3;
748 snprintf(tmp
, (int)sizeof(tmp
), "Expected at least one byte cause, but was %d long\n", len
);
754 ies
->hint
= (struct dundi_hint
*)(data
+ 2);
756 snprintf(tmp
, (int)sizeof(tmp
), "Expected at least two byte hint, but was %d long\n", len
);
760 case DUNDI_IE_DEPARTMENT
:
761 ies
->q_dept
= (char *)data
+ 2;
763 case DUNDI_IE_ORGANIZATION
:
764 ies
->q_org
= (char *)data
+ 2;
766 case DUNDI_IE_LOCALITY
:
767 ies
->q_locality
= (char *)data
+ 2;
769 case DUNDI_IE_STATE_PROV
:
770 ies
->q_stateprov
= (char *)data
+ 2;
772 case DUNDI_IE_COUNTRY
:
773 ies
->q_country
= (char *)data
+ 2;
776 ies
->q_email
= (char *)data
+ 2;
779 ies
->q_phone
= (char *)data
+ 2;
781 case DUNDI_IE_IPADDR
:
782 ies
->q_ipaddr
= (char *)data
+ 2;
784 case DUNDI_IE_ENCDATA
:
785 /* Recalculate len as the remainder of the message, regardless of
786 theoretical length */
788 if ((len
> 16) && !(len
% 16)) {
789 ies
->encblock
= (struct dundi_encblock
*)(data
+ 2);
790 ies
->enclen
= len
- 16;
792 snprintf(tmp
, (int)sizeof(tmp
), "Invalid encrypted data length %d\n", len
);
796 case DUNDI_IE_SHAREDKEY
:
798 ies
->encsharedkey
= (unsigned char *)(data
+ 2);
800 snprintf(tmp
, (int)sizeof(tmp
), "Invalid encrypted shared key length %d\n", len
);
804 case DUNDI_IE_SIGNATURE
:
806 ies
->encsig
= (unsigned char *)(data
+ 2);
808 snprintf(tmp
, (int)sizeof(tmp
), "Invalid encrypted signature length %d\n", len
);
812 case DUNDI_IE_CACHEBYPASS
:
816 snprintf(tmp
, (int)sizeof(tmp
), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie
), ie
, len
);
819 /* Overwrite information element with 0, to null terminate previous portion */
821 datalen
-= (len
+ 2);
824 /* Null-terminate last field */
827 errorf("Invalid information element contents, strange boundary\n");