some platforms (e.g. FreeBSD4) need netinet/in.h to be included
[asterisk/asterisk.git] / pbx / dundi-parser.c
old mode 100755 (executable)
new mode 100644 (file)
index 99c74f8..bab1bfc
@@ -1,27 +1,39 @@
 /*
- * Distributed Universal Number Discovery (DUNDi)
+ * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2004, Digium Inc.
+ * Copyright (C) 1999 - 2005, Digium, Inc.
  *
- * Written by Mark Spencer <markster@digium.com>
+ * Mark Spencer <markster@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Distributed Universal Number Discovery (DUNDi)
  *
- * This program is Free Software distributed under the terms of
- * of the GNU General Public License.
  */
 
-#include <sys/types.h>
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
 #include <sys/socket.h>
-#include <string.h>
 #include <netinet/in.h>
-#include <asterisk/frame.h>
-#include <asterisk/utils.h>
 #include <arpa/inet.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <asterisk/dundi.h>
+
+#include "asterisk/frame.h"
+#include "asterisk/utils.h"
+#include "asterisk/dundi.h"
 #include "dundi-parser.h"
-#include <asterisk/dundi.h>
 
 static void internaloutput(const char *str)
 {
@@ -69,7 +81,7 @@ char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
        return os;
 }
 
-int dundi_str_to_eid(dundi_eid *eid, char *s)
+int dundi_str_to_eid(dundi_eid *eid, const char *s)
 {
        unsigned int eid_int[6];
        int x;
@@ -81,7 +93,7 @@ int dundi_str_to_eid(dundi_eid *eid, char *s)
        return 0;
 }
 
-int dundi_str_short_to_eid(dundi_eid *eid, char *s)
+int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
 {
        unsigned int eid_int[6];
        int x;
@@ -108,11 +120,15 @@ int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2)
 
 static void dump_string(char *output, int maxlen, void *value, int len)
 {
-       maxlen--;
-       if (maxlen > len)
-               maxlen = len;
-       strncpy(output,value, maxlen);
-       output[maxlen] = '\0';
+       if (maxlen > len + 1)
+               maxlen = len + 1;
+
+       snprintf(output, maxlen, "%s", (char *) value);
+}
+
+static void dump_cbypass(char *output, int maxlen, void *value, int len)
+{
+       snprintf(output, maxlen, "Bypass Caches");
 }
 
 static void dump_eid(char *output, int maxlen, void *value, int len)
@@ -145,20 +161,30 @@ char *dundi_hint2str(char *buf, int bufsiz, int flags)
 
 static void dump_hint(char *output, int maxlen, void *value, int len)
 {
-       unsigned short flags;
-       char tmp[512];
        char tmp2[256];
-       if (len < 2) {
-               strncpy(output, "<invalid contents>", maxlen);
+       char tmp3[256];
+       int datalen;
+       struct dundi_hint *hint;
+       if (len < sizeof(*hint)) {
+               snprintf(output, maxlen, "<invalid contents>");
                return;
        }
-       memcpy(&flags, value, sizeof(flags));
-       flags = ntohs(flags);
-       memset(tmp, 0, sizeof(tmp));
-       dundi_hint2str(tmp2, sizeof(tmp2), flags);
-       snprintf(tmp, sizeof(tmp), "[%s] ", tmp2);
-       memcpy(tmp + strlen(tmp), value + 2, len - 2);
-       strncpy(output, tmp, maxlen - 1);
+
+       hint = (struct dundi_hint *) value;;
+
+       datalen = len - offsetof(struct dundi_hint, data);
+       if (datalen > sizeof(tmp3) - 1)
+               datalen = sizeof(tmp3) - 1;
+
+       memcpy(tmp3, hint->data, datalen);
+       tmp3[datalen] = '\0';
+
+       dundi_hint2str(tmp2, sizeof(tmp2), ntohs(hint->flags));
+
+       if (ast_strlen_zero(tmp3))
+               snprintf(output, maxlen, "[%s]", tmp2);
+       else
+               snprintf(output, maxlen, "[%s] %s", tmp2, tmp3);
 }
 
 static void dump_cause(char *output, int maxlen, void *value, int len)
@@ -169,34 +195,37 @@ static void dump_cause(char *output, int maxlen, void *value, int len)
                "DYNAMIC",
                "NOAUTH" ,
                };
-       char tmp[256];
        char tmp2[256];
-       int mlen;
-       unsigned char cause;
-       if (len < 1) {
-               strncpy(output, "<invalid contents>", maxlen);
+       struct dundi_cause *cause;
+       int datalen;
+       int causecode;
+
+       if (len < sizeof(*cause)) {
+               snprintf(output, maxlen, "<invalid contents>");
                return;
        }
-       cause = *((unsigned char *)value);
-       memset(tmp2, 0, sizeof(tmp2));
-       mlen = len - 1;
-       if (mlen > 255)
-               mlen = 255;
-       memcpy(tmp2, value + 1, mlen);
-       if (cause < sizeof(causes) / sizeof(causes[0])) {
-               if (len > 1)
-                       snprintf(tmp, sizeof(tmp), "%s: %s", causes[cause], tmp2);
+
+       cause = (struct dundi_cause*) value;
+       causecode = cause->causecode;
+
+       datalen = len - offsetof(struct dundi_cause, desc);
+       if (datalen > sizeof(tmp2) - 1)
+               datalen = sizeof(tmp2) - 1;
+
+       memcpy(tmp2, cause->desc, datalen);
+       tmp2[datalen] = '\0';
+
+       if (causecode < sizeof(causes) / sizeof(causes[0])) {
+               if (ast_strlen_zero(tmp2))
+                       snprintf(output, maxlen, "%s", causes[causecode]);
                else
-                       snprintf(tmp, sizeof(tmp), "%s", causes[cause]);
+                       snprintf(output, maxlen, "%s: %s", causes[causecode], tmp2);
        } else {
-               if (len > 1)
-                       snprintf(tmp, sizeof(tmp), "%d: %s", cause, tmp2);
+               if (ast_strlen_zero(tmp2))
+                       snprintf(output, maxlen, "%d", causecode);
                else
-                       snprintf(tmp, sizeof(tmp), "%d", cause);
+                       snprintf(output, maxlen, "%d: %s", causecode, tmp2);
        }
-       
-       strncpy(output,tmp, maxlen);
-       output[maxlen] = '\0';
 }
 
 static void dump_int(char *output, int maxlen, void *value, int len)
@@ -204,7 +233,7 @@ static void dump_int(char *output, int maxlen, void *value, int len)
        if (len == (int)sizeof(unsigned int))
                snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value)));
        else
-               snprintf(output, maxlen, "Invalid INT");
+               ast_copy_string(output, "Invalid INT", maxlen);
 }
 
 static void dump_short(char *output, int maxlen, void *value, int len)
@@ -212,7 +241,7 @@ static void dump_short(char *output, int maxlen, void *value, int len)
        if (len == (int)sizeof(unsigned short))
                snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
        else
-               snprintf(output, maxlen, "Invalid SHORT");
+               ast_copy_string(output, "Invalid SHORT", maxlen);
 }
 
 static void dump_byte(char *output, int maxlen, void *value, int len)
@@ -220,7 +249,7 @@ static void dump_byte(char *output, int maxlen, void *value, int len)
        if (len == (int)sizeof(unsigned char))
                snprintf(output, maxlen, "%d", *((unsigned char *)value));
        else
-               snprintf(output, maxlen, "Invalid BYTE");
+               ast_copy_string(output, "Invalid BYTE", maxlen);
 }
 
 static char *proto2str(int proto, char *buf, int bufsiz)
@@ -290,17 +319,28 @@ static void dump_answer(char *output, int maxlen, void *value, int len)
        char flags[40];
        char eid_str[40];
        char tmp[512]="";
-       if (len >= 10) {
-               answer = (struct dundi_answer *)(value);
-               memcpy(tmp, answer->data, (len >= 500) ? 500 : len - 10);
-               dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
-               snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]", 
-                       dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)), 
-                       ntohs(answer->weight),
-                       proto2str(answer->protocol, proto, sizeof(proto)), 
-                               tmp, eid_str);
-       } else
-               strncpy(output, "Invalid Answer", maxlen - 1);
+       int datalen;
+
+       if (len < sizeof(*answer)) {
+               snprintf(output, maxlen, "Invalid Answer");
+               return;
+       }
+
+       answer = (struct dundi_answer *)(value);
+
+       datalen = len - offsetof(struct dundi_answer, data);
+       if (datalen > sizeof(tmp) - 1)
+               datalen = sizeof(tmp) - 1;
+
+       memcpy(tmp, answer->data, datalen);
+       tmp[datalen] = '\0';
+
+       dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
+       snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]", 
+               dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)), 
+               ntohs(answer->weight),
+               proto2str(answer->protocol, proto, sizeof(proto)), 
+                       tmp, eid_str);
 }
 
 static void dump_encrypted(char *output, int maxlen, void *value, int len)
@@ -358,6 +398,7 @@ static struct dundi_ie {
        { DUNDI_IE_EMAIL, "EMAIL", dump_string },
        { DUNDI_IE_PHONE, "PHONE", dump_string },
        { DUNDI_IE_IPADDR, "ADDRESS", dump_string },
+       { DUNDI_IE_CACHEBYPASS, "CBYPASS", dump_cbypass },
 };
 
 const char *dundi_ie2str(int ie)
@@ -380,7 +421,7 @@ static void dump_ies(unsigned char *iedata, int spaces, int len)
        char tmp[1024];
        if (len < 2)
                return;
-       while(len > 2) {
+       while(len >= 2) {
                ie = iedata[0];
                ielen = iedata[1];
                /* Encrypted data is the remainder */
@@ -432,8 +473,8 @@ void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int
                "DPRESPONSE  ",
                "EIDQUERY    ",
                "EIDRESPONSE ",
-               "UNKNOWN (5)?",
-               "UNKNOWN (6)?",
+               "PRECACHERQ  ",
+               "PRECACHERP  ",
                "INVALID     ",
                "UNKNOWN CMD ",
                "NULL        ",
@@ -448,7 +489,6 @@ void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int
        char *subclass;
        char tmp[256];
        char retries[20];
-       char iabuf[INET_ADDRSTRLEN];
        if (ntohs(fhi->dtrans) & DUNDI_FLAG_RETRANS)
                strcpy(retries, "Yes");
        else
@@ -473,7 +513,7 @@ void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int
        snprintf(tmp, (int)sizeof(tmp), 
                "%s     Flags: %s STrans: %5.5d  DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? "     " : "",
                subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,
-               ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port),
+               ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
                fhi->cmdresp & 0x80 ? " (Final)" : "");
        outputf(tmp);
        dump_ies(fhi->ies, rx > 1, datalen);
@@ -494,7 +534,7 @@ int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data,
        return 0;
 }
 
-int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, unsigned char *data)
+int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
 {
        char tmp[256];
        int datalen = data ? strlen(data) + 1 : 1;
@@ -511,7 +551,7 @@ int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned
        return 0;
 }
 
-int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, unsigned char *data)
+int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
 {
        char tmp[256];
        int datalen = data ? strlen(data) + 2 : 2;
@@ -550,7 +590,7 @@ int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigne
        return 0;
 }
 
-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, unsigned char *data)
+int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
 {
        char tmp[256];
        int datalen = data ? strlen(data) + 11 : 11;
@@ -596,7 +636,7 @@ int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned
        return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
 }
 
-int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, unsigned char *str)
+int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
 {
        return dundi_ie_append_raw(ied, ie, str, strlen(str));
 }
@@ -663,10 +703,10 @@ int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
                                ies->reqeid = (dundi_eid *)(data + 2);
                        break;
                case DUNDI_IE_CALLED_CONTEXT:
-                       ies->called_context = data + 2;
+                       ies->called_context = (char *)data + 2;
                        break;
                case DUNDI_IE_CALLED_NUMBER:
-                       ies->called_number = data + 2;
+                       ies->called_number = (char *)data + 2;
                        break;
                case DUNDI_IE_ANSWER:
                        if (len < sizeof(struct dundi_answer)) {
@@ -718,7 +758,7 @@ int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
                case DUNDI_IE_CAUSE:
                        if (len >= 1) {
                                ies->cause = data[2];
-                               ies->causestr = data + 3;
+                               ies->causestr = (char *)data + 3;
                        } else {
                                snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len);
                                errorf(tmp);
@@ -733,28 +773,28 @@ int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
                        }
                        break;
                case DUNDI_IE_DEPARTMENT:
-                       ies->q_dept = data + 2;
+                       ies->q_dept = (char *)data + 2;
                        break;
                case DUNDI_IE_ORGANIZATION:
-                       ies->q_org = data + 2;
+                       ies->q_org = (char *)data + 2;
                        break;
                case DUNDI_IE_LOCALITY:
-                       ies->q_locality = data + 2;
+                       ies->q_locality = (char *)data + 2;
                        break;
                case DUNDI_IE_STATE_PROV:
-                       ies->q_stateprov = data + 2;
+                       ies->q_stateprov = (char *)data + 2;
                        break;
                case DUNDI_IE_COUNTRY:
-                       ies->q_country = data + 2;
+                       ies->q_country = (char *)data + 2;
                        break;
                case DUNDI_IE_EMAIL:
-                       ies->q_email = data + 2;
+                       ies->q_email = (char *)data + 2;
                        break;
                case DUNDI_IE_PHONE:
-                       ies->q_phone = data + 2;
+                       ies->q_phone = (char *)data + 2;
                        break;
                case DUNDI_IE_IPADDR:
-                       ies->q_ipaddr = data + 2;
+                       ies->q_ipaddr = (char *)data + 2;
                        break;
                case DUNDI_IE_ENCDATA:
                        /* Recalculate len as the remainder of the message, regardless of
@@ -784,6 +824,9 @@ int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
                                errorf(tmp);
                        }
                        break;
+               case DUNDI_IE_CACHEBYPASS:
+                       ies->cbypass = 1;
+                       break;
                default:
                        snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
                        outputf(tmp);