Thu Sep 7 01:02:59 2017

Asterisk developer's documentation


dundi-parser.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Distributed Universal Number Discovery (DUNDi)
00022  *
00023  */
00024 
00025 /*** MODULEINFO
00026    <support_level>extended</support_level>
00027  ***/
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
00032 
00033 #include <sys/socket.h>
00034 #include <netinet/in.h>
00035 #include <arpa/inet.h>
00036 
00037 #include "asterisk/frame.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/dundi.h"
00040 #include "dundi-parser.h"
00041 
00042 static void internaloutput(const char *str)
00043 {
00044    fputs(str, stdout);
00045 }
00046 
00047 static void internalerror(const char *str)
00048 {
00049    fprintf(stderr, "WARNING: %s", str);
00050 }
00051 
00052 static void (*outputf)(const char *str) = internaloutput;
00053 static void (*errorf)(const char *str) = internalerror;
00054 
00055 char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
00056 {
00057    int x;
00058    char *os = s;
00059    if (maxlen < 13) {
00060       if (s && (maxlen > 0))
00061          *s = '\0';
00062    } else {
00063       for (x=0;x<6;x++) {
00064          sprintf(s, "%02X", (unsigned)eid->eid[x]);
00065          s += 2;
00066       }
00067    }
00068    return os;
00069 }
00070 
00071 int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
00072 {
00073    unsigned int eid_int[6];
00074    int x;
00075    if (sscanf(s, "%2x%2x%2x%2x%2x%2x", &eid_int[0], &eid_int[1], &eid_int[2],
00076        &eid_int[3], &eid_int[4], &eid_int[5]) != 6)
00077          return -1;
00078    for (x = 0; x < 6; x++)
00079       eid->eid[x] = eid_int[x];
00080    return 0;
00081 }
00082 
00083 int dundi_eid_zero(dundi_eid *eid)
00084 {
00085    int x;
00086    for (x = 0; x < ARRAY_LEN(eid->eid); x++)
00087       if (eid->eid[x]) return 0;
00088    return 1;
00089 }
00090 
00091 static void dump_string(char *output, int maxlen, void *value, int len)
00092 {
00093    if (maxlen > len + 1)
00094       maxlen = len + 1;
00095 
00096    snprintf(output, maxlen, "%s", (char *) value);
00097 }
00098 
00099 static void dump_cbypass(char *output, int maxlen, void *value, int len)
00100 {
00101    snprintf(output, maxlen, "Bypass Caches");
00102 }
00103 
00104 static void dump_eid(char *output, int maxlen, void *value, int len)
00105 {
00106    if (len == 6)
00107       ast_eid_to_str(output, maxlen, (dundi_eid *)value);
00108    else
00109       snprintf(output, maxlen, "Invalid EID len %d", len);
00110 }
00111 
00112 char *dundi_hint2str(char *buf, int bufsiz, int flags)
00113 {
00114    strcpy(buf, "");
00115    buf[bufsiz-1] = '\0';
00116    if (flags & DUNDI_HINT_TTL_EXPIRED) {
00117       strncat(buf, "TTLEXPIRED|", bufsiz - strlen(buf) - 1);
00118    }
00119    if (flags & DUNDI_HINT_DONT_ASK) {
00120       strncat(buf, "DONTASK|", bufsiz - strlen(buf) - 1);
00121    }
00122    if (flags & DUNDI_HINT_UNAFFECTED) {
00123       strncat(buf, "UNAFFECTED|", bufsiz - strlen(buf) - 1);
00124    }
00125    /* Get rid of trailing | */
00126    if (ast_strlen_zero(buf))
00127       strcpy(buf, "NONE|");
00128    buf[strlen(buf)-1] = '\0';
00129    return buf;
00130 }
00131 
00132 static void dump_hint(char *output, int maxlen, void *value, int len)
00133 {
00134    char tmp2[256];
00135    char tmp3[256];
00136    int datalen;
00137    struct dundi_hint *hint;
00138    if (len < sizeof(*hint)) {
00139       snprintf(output, maxlen, "<invalid contents>");
00140       return;
00141    }
00142 
00143    hint = (struct dundi_hint *) value;;
00144 
00145    datalen = len - offsetof(struct dundi_hint, data);
00146    if (datalen > sizeof(tmp3) - 1)
00147       datalen = sizeof(tmp3) - 1;
00148 
00149    memcpy(tmp3, hint->data, datalen);
00150    tmp3[datalen] = '\0';
00151 
00152    dundi_hint2str(tmp2, sizeof(tmp2), ntohs(hint->flags));
00153 
00154    if (ast_strlen_zero(tmp3))
00155       snprintf(output, maxlen, "[%s]", tmp2);
00156    else
00157       snprintf(output, maxlen, "[%s] %s", tmp2, tmp3);
00158 }
00159 
00160 static void dump_cause(char *output, int maxlen, void *value, int len)
00161 {
00162    static const char * const causes[] = {
00163       "SUCCESS",
00164       "GENERAL",
00165       "DYNAMIC",
00166       "NOAUTH" ,
00167       };
00168    char tmp2[256];
00169    struct dundi_cause *cause;
00170    int datalen;
00171    int causecode;
00172 
00173    if (len < sizeof(*cause)) {
00174       snprintf(output, maxlen, "<invalid contents>");
00175       return;
00176    }
00177 
00178    cause = (struct dundi_cause*) value;
00179    causecode = cause->causecode;
00180 
00181    datalen = len - offsetof(struct dundi_cause, desc);
00182    if (datalen > sizeof(tmp2) - 1)
00183       datalen = sizeof(tmp2) - 1;
00184 
00185    memcpy(tmp2, cause->desc, datalen);
00186    tmp2[datalen] = '\0';
00187 
00188    if (causecode < ARRAY_LEN(causes)) {
00189       if (ast_strlen_zero(tmp2))
00190          snprintf(output, maxlen, "%s", causes[causecode]);
00191       else
00192          snprintf(output, maxlen, "%s: %s", causes[causecode], tmp2);
00193    } else {
00194       if (ast_strlen_zero(tmp2))
00195          snprintf(output, maxlen, "%d", causecode);
00196       else
00197          snprintf(output, maxlen, "%d: %s", causecode, tmp2);
00198    }
00199 }
00200 
00201 static void dump_int(char *output, int maxlen, void *value, int len)
00202 {
00203    if (len == (int)sizeof(unsigned int))
00204       snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value)));
00205    else
00206       ast_copy_string(output, "Invalid INT", maxlen);
00207 }
00208 
00209 static void dump_short(char *output, int maxlen, void *value, int len)
00210 {
00211    if (len == (int)sizeof(unsigned short))
00212       snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
00213    else
00214       ast_copy_string(output, "Invalid SHORT", maxlen);
00215 }
00216 
00217 static void dump_byte(char *output, int maxlen, void *value, int len)
00218 {
00219    if (len == (int)sizeof(unsigned char))
00220       snprintf(output, maxlen, "%d", *((unsigned char *)value));
00221    else
00222       ast_copy_string(output, "Invalid BYTE", maxlen);
00223 }
00224 
00225 static char *proto2str(int proto, char *buf, int bufsiz)
00226 {  
00227    switch(proto) {
00228    case DUNDI_PROTO_NONE:
00229       strncpy(buf, "None", bufsiz - 1);
00230       break;
00231    case DUNDI_PROTO_IAX:
00232       strncpy(buf, "IAX", bufsiz - 1);
00233       break;
00234    case DUNDI_PROTO_SIP:
00235       strncpy(buf, "SIP", bufsiz - 1);
00236       break;
00237    case DUNDI_PROTO_H323:
00238       strncpy(buf, "H.323", bufsiz - 1);
00239       break;
00240    default:
00241       snprintf(buf, bufsiz, "Unknown Proto(%d)", proto);
00242    }
00243    buf[bufsiz-1] = '\0';
00244    return buf;
00245 }
00246 
00247 char *dundi_flags2str(char *buf, int bufsiz, int flags)
00248 {
00249    strcpy(buf, "");
00250    buf[bufsiz-1] = '\0';
00251    if (flags & DUNDI_FLAG_EXISTS) {
00252       strncat(buf, "EXISTS|", bufsiz - strlen(buf) - 1);
00253    }
00254    if (flags & DUNDI_FLAG_MATCHMORE) {
00255       strncat(buf, "MATCHMORE|", bufsiz - strlen(buf) - 1);
00256    }
00257    if (flags & DUNDI_FLAG_CANMATCH) {
00258       strncat(buf, "CANMATCH|", bufsiz - strlen(buf) - 1);
00259    }
00260    if (flags & DUNDI_FLAG_IGNOREPAT) {
00261       strncat(buf, "IGNOREPAT|", bufsiz - strlen(buf) - 1);
00262    }
00263    if (flags & DUNDI_FLAG_RESIDENTIAL) {
00264       strncat(buf, "RESIDENCE|", bufsiz - strlen(buf) - 1);
00265    }
00266    if (flags & DUNDI_FLAG_COMMERCIAL) {
00267       strncat(buf, "COMMERCIAL|", bufsiz - strlen(buf) - 1);
00268    }
00269    if (flags & DUNDI_FLAG_MOBILE) {
00270       strncat(buf, "MOBILE", bufsiz - strlen(buf) - 1);
00271    }
00272    if (flags & DUNDI_FLAG_NOUNSOLICITED) {
00273       strncat(buf, "NOUNSLCTD|", bufsiz - strlen(buf) - 1);
00274    }
00275    if (flags & DUNDI_FLAG_NOCOMUNSOLICIT) {
00276       strncat(buf, "NOCOMUNSLTD|", bufsiz - strlen(buf) - 1);
00277    }
00278    /* Get rid of trailing | */
00279    if (ast_strlen_zero(buf))
00280       strcpy(buf, "NONE|");
00281    buf[strlen(buf)-1] = '\0';
00282    return buf;
00283 }
00284 
00285 static void dump_answer(char *output, int maxlen, void *value, int len)
00286 {
00287    struct dundi_answer *answer;
00288    char proto[40];
00289    char flags[40];
00290    char eid_str[40];
00291    char tmp[512]="";
00292    int datalen;
00293 
00294    if (len < sizeof(*answer)) {
00295       snprintf(output, maxlen, "Invalid Answer");
00296       return;
00297    }
00298 
00299    answer = (struct dundi_answer *)(value);
00300 
00301    datalen = len - offsetof(struct dundi_answer, data);
00302    if (datalen > sizeof(tmp) - 1)
00303       datalen = sizeof(tmp) - 1;
00304 
00305    memcpy(tmp, answer->data, datalen);
00306    tmp[datalen] = '\0';
00307 
00308    ast_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
00309    snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]", 
00310       dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)), 
00311       ntohs(answer->weight),
00312       proto2str(answer->protocol, proto, sizeof(proto)), 
00313          tmp, eid_str);
00314 }
00315 
00316 static void dump_encrypted(char *output, int maxlen, void *value, int len)
00317 {
00318    char iv[33];
00319    int x;
00320    if ((len > 16) && !(len % 16)) {
00321       /* Build up IV */
00322       for (x=0;x<16;x++) {
00323          snprintf(iv + (x << 1), 3, "%02x", (unsigned)((unsigned char *)value)[x]);
00324       }
00325       snprintf(output, maxlen, "[IV %s] %d encrypted blocks\n", iv, len / 16);
00326    } else
00327       snprintf(output, maxlen, "Invalid Encrypted Datalen %d", len);
00328 }
00329 
00330 static void dump_raw(char *output, int maxlen, void *value, int len)
00331 {
00332    int x;
00333    unsigned char *u = value;
00334    output[maxlen - 1] = '\0';
00335    strcpy(output, "[ ");
00336    for (x=0;x<len;x++) {
00337       snprintf(output + strlen(output), maxlen - strlen(output) - 1, "%02x ", (unsigned)u[x]);
00338    }
00339    strncat(output + strlen(output), "]", maxlen - strlen(output) - 1);
00340 }
00341 
00342 static struct dundi_ie {
00343    int ie;
00344    char *name;
00345    void (*dump)(char *output, int maxlen, void *value, int len);
00346 } infoelts[] = {
00347    { DUNDI_IE_EID, "ENTITY IDENT", dump_eid },
00348    { DUNDI_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
00349    { DUNDI_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
00350    { DUNDI_IE_EID_DIRECT, "DIRECT EID", dump_eid },
00351    { DUNDI_IE_ANSWER, "ANSWER", dump_answer },
00352    { DUNDI_IE_TTL, "TTL", dump_short },
00353    { DUNDI_IE_VERSION, "VERSION", dump_short },
00354    { DUNDI_IE_EXPIRATION, "EXPIRATION", dump_short },
00355    { DUNDI_IE_UNKNOWN, "UKWN DUNDI CMD", dump_byte },
00356    { DUNDI_IE_CAUSE, "CAUSE", dump_cause },
00357    { DUNDI_IE_REQEID, "REQUEST EID", dump_eid },
00358    { DUNDI_IE_ENCDATA, "ENCDATA", dump_encrypted },
00359    { DUNDI_IE_SHAREDKEY, "SHAREDKEY", dump_raw },
00360    { DUNDI_IE_SIGNATURE, "SIGNATURE", dump_raw },
00361    { DUNDI_IE_KEYCRC32, "KEYCRC32", dump_int },
00362    { DUNDI_IE_HINT, "HINT", dump_hint },
00363    { DUNDI_IE_DEPARTMENT, "DEPARTMENT", dump_string },
00364    { DUNDI_IE_ORGANIZATION, "ORGANIZTN", dump_string },
00365    { DUNDI_IE_LOCALITY, "LOCALITY", dump_string },
00366    { DUNDI_IE_STATE_PROV, "STATEPROV", dump_string },
00367    { DUNDI_IE_COUNTRY, "COUNTRY", dump_string },
00368    { DUNDI_IE_EMAIL, "EMAIL", dump_string },
00369    { DUNDI_IE_PHONE, "PHONE", dump_string },
00370    { DUNDI_IE_IPADDR, "ADDRESS", dump_string },
00371    { DUNDI_IE_CACHEBYPASS, "CBYPASS", dump_cbypass },
00372 };
00373 
00374 const char *dundi_ie2str(int ie)
00375 {
00376    int x;
00377    for (x = 0; x < ARRAY_LEN(infoelts); x++) {
00378       if (infoelts[x].ie == ie)
00379          return infoelts[x].name;
00380    }
00381    return "Unknown IE";
00382 }
00383 
00384 static void dump_ies(unsigned char *iedata, int spaces, int len)
00385 {
00386    int ielen;
00387    int ie;
00388    int x;
00389    int found;
00390    char interp[1024];
00391    char tmp[1024];
00392    if (len < 2)
00393       return;
00394    while(len >= 2) {
00395       ie = iedata[0];
00396       ielen = iedata[1];
00397       /* Encrypted data is the remainder */
00398       if (ie == DUNDI_IE_ENCDATA)
00399          ielen = len - 2;
00400       if (ielen + 2> len) {
00401          snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
00402          outputf(tmp);
00403          return;
00404       }
00405       found = 0;
00406       for (x = 0; x < ARRAY_LEN(infoelts); x++) {
00407          if (infoelts[x].ie == ie) {
00408             if (infoelts[x].dump) {
00409                infoelts[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
00410                snprintf(tmp, (int)sizeof(tmp), "   %s%-15.15s : %s\n", (spaces ? "     " : "" ), infoelts[x].name, interp);
00411                outputf(tmp);
00412             } else {
00413                if (ielen)
00414                   snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
00415                else
00416                   strcpy(interp, "Present");
00417                snprintf(tmp, (int)sizeof(tmp), "   %s%-15.15s : %s\n", (spaces ? "     " : "" ), infoelts[x].name, interp);
00418                outputf(tmp);
00419             }
00420             found++;
00421          }
00422       }
00423       if (!found) {
00424          snprintf(tmp, (int)sizeof(tmp), "   %sUnknown IE %03d  : Present\n", (spaces ? "     " : "" ), ie);
00425          outputf(tmp);
00426       }
00427       iedata += (2 + ielen);
00428       len -= (2 + ielen);
00429    }
00430    outputf("\n");
00431 }
00432 
00433 void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
00434 {
00435    char *pref[] = {
00436       "Tx",
00437       "Rx",
00438       "    ETx",
00439       "    Erx" };
00440    char *commands[] = {
00441       "ACK         ",
00442       "DPDISCOVER  ",
00443       "DPRESPONSE  ",
00444       "EIDQUERY    ",
00445       "EIDRESPONSE ",
00446       "PRECACHERQ  ",
00447       "PRECACHERP  ",
00448       "INVALID     ",
00449       "UNKNOWN CMD ",
00450       "NULL        ",
00451       "REQREQ      ",
00452       "REGRESPONSE ",
00453       "CANCEL      ",
00454       "ENCRYPT     ",
00455       "ENCREJ      " };
00456    char class2[20];
00457    char *class;
00458    char subclass2[20];
00459    char *subclass;
00460    char tmp[256];
00461    const char *retries = "Yes";
00462    if ((fhi->cmdresp & 0x3f) > (int)sizeof(commands)/(int)sizeof(char *)) {
00463       snprintf(class2, (int)sizeof(class2), "(%d?)", fhi->cmdresp);
00464       class = class2;
00465    } else {
00466       class = commands[(int)(fhi->cmdresp & 0x3f)];
00467    }
00468    snprintf(subclass2, (int)sizeof(subclass2), "%02x", (unsigned)fhi->cmdflags);
00469    subclass = subclass2;
00470    snprintf(tmp, (int)sizeof(tmp), 
00471       "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n",
00472       pref[rx],
00473       retries, fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");
00474    outputf(tmp);
00475    snprintf(tmp, (int)sizeof(tmp), 
00476       "%s     Flags: %s STrans: %5.5d  DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? "     " : "",
00477       subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,
00478       ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00479       fhi->cmdresp & 0x80 ? " (Final)" : "");
00480    outputf(tmp);
00481    dump_ies(fhi->ies, rx > 1, datalen);
00482 }
00483 
00484 int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
00485 {
00486    char tmp[256];
00487    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00488       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);
00489       errorf(tmp);
00490       return -1;
00491    }
00492    ied->buf[ied->pos++] = ie;
00493    ied->buf[ied->pos++] = datalen;
00494    memcpy(ied->buf + ied->pos, data, datalen);
00495    ied->pos += datalen;
00496    return 0;
00497 }
00498 
00499 int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
00500 {
00501    char tmp[256];
00502    int datalen = data ? strlen(data) + 1 : 1;
00503    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00504       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);
00505       errorf(tmp);
00506       return -1;
00507    }
00508    ied->buf[ied->pos++] = ie;
00509    ied->buf[ied->pos++] = datalen;
00510    ied->buf[ied->pos++] = cause;
00511    if (data) {
00512       memcpy(ied->buf + ied->pos, data, datalen-1);
00513       ied->pos += datalen-1;
00514    }
00515    return 0;
00516 }
00517 
00518 int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
00519 {
00520    char tmp[256];
00521    int datalen = data ? strlen(data) + 2 : 2;
00522    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00523       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);
00524       errorf(tmp);
00525       return -1;
00526    }
00527    ied->buf[ied->pos++] = ie;
00528    ied->buf[ied->pos++] = datalen;
00529    flags = htons(flags);
00530    memcpy(ied->buf + ied->pos, &flags, sizeof(flags));
00531    ied->pos += 2;
00532    if (data) {
00533       memcpy(ied->buf + ied->pos, data, datalen-2);
00534       ied->pos += datalen-2;
00535    }
00536    return 0;
00537 }
00538 
00539 int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
00540 {
00541    char tmp[256];
00542    datalen += 16;
00543    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00544       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);
00545       errorf(tmp);
00546       return -1;
00547    }
00548    ied->buf[ied->pos++] = ie;
00549    ied->buf[ied->pos++] = datalen;
00550    memcpy(ied->buf + ied->pos, iv, 16);
00551    ied->pos += 16;
00552    if (data) {
00553       memcpy(ied->buf + ied->pos, data, datalen-16);
00554       ied->pos += datalen-16;
00555    }
00556    return 0;
00557 }
00558 
00559 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)
00560 {
00561    char tmp[256];
00562    int datalen = data ? strlen(data) + 11 : 11;
00563    int x;
00564    unsigned short myw;
00565    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00566       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);
00567       errorf(tmp);
00568       return -1;
00569    }
00570    ied->buf[ied->pos++] = ie;
00571    ied->buf[ied->pos++] = datalen;
00572    for (x=0;x<6;x++)
00573       ied->buf[ied->pos++] = eid->eid[x];
00574    ied->buf[ied->pos++] = protocol;
00575    myw = htons(flags);
00576    memcpy(ied->buf + ied->pos, &myw, 2);
00577    ied->pos += 2;
00578    myw = htons(weight);
00579    memcpy(ied->buf + ied->pos, &myw, 2);
00580    ied->pos += 2;
00581    memcpy(ied->buf + ied->pos, data, datalen-11);
00582    ied->pos += datalen-11;
00583    return 0;
00584 }
00585 
00586 int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
00587 {
00588    return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
00589 }
00590 
00591 int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value) 
00592 {
00593    unsigned int newval;
00594    newval = htonl(value);
00595    return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00596 }
00597 
00598 int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value) 
00599 {
00600    unsigned short newval;
00601    newval = htons(value);
00602    return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00603 }
00604 
00605 int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
00606 {
00607    return dundi_ie_append_raw(ied, ie, str, strlen(str));
00608 }
00609 
00610 int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
00611 {
00612    return dundi_ie_append_raw(ied, ie, (unsigned char *)eid, sizeof(dundi_eid));
00613 }
00614 
00615 int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
00616 {
00617    return dundi_ie_append_raw(ied, ie, &dat, 1);
00618 }
00619 
00620 int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie) 
00621 {
00622    return dundi_ie_append_raw(ied, ie, NULL, 0);
00623 }
00624 
00625 void dundi_set_output(void (*func)(const char *))
00626 {
00627    outputf = func;
00628 }
00629 
00630 void dundi_set_error(void (*func)(const char *))
00631 {
00632    errorf = func;
00633 }
00634 
00635 int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
00636 {
00637    /* Parse data into information elements */
00638    int len;
00639    int ie;
00640    char tmp[256];
00641    memset(ies, 0, (int)sizeof(struct dundi_ies));
00642    ies->ttl = -1;
00643    ies->expiration = -1;
00644    ies->unknowncmd = -1;
00645    ies->cause = -1;
00646    while(datalen >= 2) {
00647       ie = data[0];
00648       len = data[1];
00649       if (len > datalen - 2) {
00650          errorf("Information element length exceeds message size\n");
00651          return -1;
00652       }
00653       switch(ie) {
00654       case DUNDI_IE_EID:
00655       case DUNDI_IE_EID_DIRECT:
00656          if (len != (int)sizeof(dundi_eid)) {
00657             errorf("Improper entity identifer, expecting 6 bytes!\n");
00658          } else if (ies->eidcount < DUNDI_MAX_STACK) {
00659             ies->eids[ies->eidcount] = (dundi_eid *)(data + 2);
00660             ies->eid_direct[ies->eidcount] = (ie == DUNDI_IE_EID_DIRECT);
00661             ies->eidcount++;
00662          } else
00663             errorf("Too many entities in stack!\n");
00664          break;
00665       case DUNDI_IE_REQEID:
00666          if (len != (int)sizeof(dundi_eid)) {
00667             errorf("Improper requested entity identifer, expecting 6 bytes!\n");
00668          } else
00669             ies->reqeid = (dundi_eid *)(data + 2);
00670          break;
00671       case DUNDI_IE_CALLED_CONTEXT:
00672          ies->called_context = (char *)data + 2;
00673          break;
00674       case DUNDI_IE_CALLED_NUMBER:
00675          ies->called_number = (char *)data + 2;
00676          break;
00677       case DUNDI_IE_ANSWER:
00678          if (len < sizeof(struct dundi_answer)) {
00679             snprintf(tmp, (int)sizeof(tmp), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer), len);
00680             errorf(tmp);
00681          } else {
00682             if (ies->anscount < DUNDI_MAX_ANSWERS)
00683                ies->answers[ies->anscount++]= (struct dundi_answer *)(data + 2);
00684             else 
00685                errorf("Ignoring extra answers!\n");
00686          }
00687          break;
00688       case DUNDI_IE_TTL:
00689          if (len != (int)sizeof(unsigned short)) {
00690             snprintf(tmp, (int)sizeof(tmp), "Expecting ttl to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00691             errorf(tmp);
00692          } else
00693             ies->ttl = ntohs(*((unsigned short *)(data + 2)));
00694          break;
00695       case DUNDI_IE_VERSION:
00696          if (len != (int)sizeof(unsigned short)) {
00697             snprintf(tmp, (int)sizeof(tmp),  "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00698             errorf(tmp);
00699          } else
00700             ies->version = ntohs(*((unsigned short *)(data + 2)));
00701          break;
00702       case DUNDI_IE_EXPIRATION:
00703          if (len != (int)sizeof(unsigned short)) {
00704             snprintf(tmp, (int)sizeof(tmp),  "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00705             errorf(tmp);
00706          } else
00707             ies->expiration = ntohs(*((unsigned short *)(data + 2)));
00708          break;
00709       case DUNDI_IE_KEYCRC32:
00710          if (len != (int)sizeof(unsigned int)) {
00711             snprintf(tmp, (int)sizeof(tmp),  "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00712             errorf(tmp);
00713          } else
00714             ies->keycrc32 = ntohl(*((unsigned int *)(data + 2)));
00715          break;
00716       case DUNDI_IE_UNKNOWN:
00717          if (len == 1)
00718             ies->unknowncmd = data[2];
00719          else {
00720             snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
00721             errorf(tmp);
00722          }
00723          break;
00724       case DUNDI_IE_CAUSE:
00725          if (len >= 1) {
00726             ies->cause = data[2];
00727             ies->causestr = (char *)data + 3;
00728          } else {
00729             snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len);
00730             errorf(tmp);
00731          }
00732          break;
00733       case DUNDI_IE_HINT:
00734          if (len >= 2) {
00735             ies->hint = (struct dundi_hint *)(data + 2);
00736          } else {
00737             snprintf(tmp, (int)sizeof(tmp), "Expected at least two byte hint, but was %d long\n", len);
00738             errorf(tmp);
00739          }
00740          break;
00741       case DUNDI_IE_DEPARTMENT:
00742          ies->q_dept = (char *)data + 2;
00743          break;
00744       case DUNDI_IE_ORGANIZATION:
00745          ies->q_org = (char *)data + 2;
00746          break;
00747       case DUNDI_IE_LOCALITY:
00748          ies->q_locality = (char *)data + 2;
00749          break;
00750       case DUNDI_IE_STATE_PROV:
00751          ies->q_stateprov = (char *)data + 2;
00752          break;
00753       case DUNDI_IE_COUNTRY:
00754          ies->q_country = (char *)data + 2;
00755          break;
00756       case DUNDI_IE_EMAIL:
00757          ies->q_email = (char *)data + 2;
00758          break;
00759       case DUNDI_IE_PHONE:
00760          ies->q_phone = (char *)data + 2;
00761          break;
00762       case DUNDI_IE_IPADDR:
00763          ies->q_ipaddr = (char *)data + 2;
00764          break;
00765       case DUNDI_IE_ENCDATA:
00766          /* Recalculate len as the remainder of the message, regardless of
00767             theoretical length */
00768          len = datalen - 2;
00769          if ((len > 16) && !(len % 16)) {
00770             ies->encblock = (struct dundi_encblock *)(data + 2);
00771             ies->enclen = len - 16;
00772          } else {
00773             snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted data length %d\n", len);
00774             errorf(tmp);
00775          }
00776          break;
00777       case DUNDI_IE_SHAREDKEY:
00778          if (len == 128) {
00779             ies->encsharedkey = (unsigned char *)(data + 2);
00780          } else {
00781             snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted shared key length %d\n", len);
00782             errorf(tmp);
00783          }
00784          break;
00785       case DUNDI_IE_SIGNATURE:
00786          if (len == 128) {
00787             ies->encsig = (unsigned char *)(data + 2);
00788          } else {
00789             snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted signature length %d\n", len);
00790             errorf(tmp);
00791          }
00792          break;
00793       case DUNDI_IE_CACHEBYPASS:
00794          ies->cbypass = 1;
00795          break;
00796       default:
00797          snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
00798          outputf(tmp);
00799       }
00800       /* Overwrite information element with 0, to null terminate previous portion */
00801       data[0] = 0;
00802       datalen -= (len + 2);
00803       data += (len + 2);
00804    }
00805    /* Null-terminate last field */
00806    *data = '\0';
00807    if (datalen) {
00808       errorf("Invalid information element contents, strange boundary\n");
00809       return -1;
00810    }
00811    return 0;
00812 }

Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1