[Asterisk-code-review] pbx dundi: Added IPv6 support for dundi (asterisk[13])

Adam Secombe asteriskteam at digium.com
Sun Aug 6 22:12:10 CDT 2017


Adam Secombe has uploaded this change for review. ( https://gerrit.asterisk.org/6173


Change subject: pbx_dundi: Added IPv6 support for dundi
......................................................................

pbx_dundi: Added IPv6 support for dundi

ASTERISK-27164
Reported-by: Adam Secombe

Change-Id: Ifbe298afc6416ba400db7be404a25994ad23968a
---
M include/asterisk/dundi.h
M pbx/dundi-parser.c
M pbx/dundi-parser.h
M pbx/pbx_dundi.c
4 files changed, 463 insertions(+), 115 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/73/6173/1

diff --git a/include/asterisk/dundi.h b/include/asterisk/dundi.h
index 2bffd02..b36aa5d 100644
--- a/include/asterisk/dundi.h
+++ b/include/asterisk/dundi.h
@@ -259,4 +259,10 @@
 /*! \brief Pre-cache to push upstream peers */
 int dundi_precache(const char *dcontext, const char *number);
 
+union ip_addr
+{
+    struct sockaddr_in6 i6;                      
+    struct sockaddr_in i4;                    
+};
+
 #endif /* _ASTERISK_DUNDI_H */
diff --git a/pbx/dundi-parser.c b/pbx/dundi-parser.c
index c178fd6..e3b04fa 100644
--- a/pbx/dundi-parser.c
+++ b/pbx/dundi-parser.c
@@ -39,6 +39,8 @@
 #include "asterisk/dundi.h"
 #include "dundi-parser.h"
 
+
+extern int netsock_ai_family ;
 static void internaloutput(const char *str)
 {
 	fputs(str, stdout);
@@ -430,7 +432,7 @@
 	outputf("\n");
 }
 
-void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
+void dundi_showframe(struct dundi_hdr *fhi, int rx, union ip_addr *sin, int datalen)
 {
 	char *pref[] = {
 		"Tx",
@@ -471,11 +473,25 @@
 		pref[rx],
 		fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");
 	outputf(tmp);
-	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(sin->sin_addr), ntohs(sin->sin_port),
-		fhi->cmdresp & 0x80 ? " (Final)" : "");
+
+    if ( netsock_ai_family == AF_INET6)
+    {
+        char str[INET6_ADDRSTRLEN];
+        inet_ntop(AF_INET6, &(sin->i6.sin6_addr), str, INET6_ADDRSTRLEN);
+        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,
+            str, ntohs(sin->i6.sin6_port),
+            fhi->cmdresp & 0x80 ? " (Final)" : "");
+    }
+    else
+    {
+        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(sin->i4.sin_addr), ntohs(sin->i4.sin_port),
+            fhi->cmdresp & 0x80 ? " (Final)" : "");
+    }
 	outputf(tmp);
 	dump_ies(fhi->ies, rx > 1, datalen);
 }
@@ -582,9 +598,13 @@
 	return 0;
 }
 
-int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
+int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, union ip_addr *sin)
 {
-	return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
+#ifdef IPV6
+	return dundi_ie_append_raw(ied, ie, &sin->i6, (int)sizeof(sin->i6));
+#else
+	return dundi_ie_append_raw(ied, ie, &sin->i4, (int)sizeof(sin->i4));
+#endif
 }
 
 int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value) 
diff --git a/pbx/dundi-parser.h b/pbx/dundi-parser.h
index b24d486..7174b69 100644
--- a/pbx/dundi-parser.h
+++ b/pbx/dundi-parser.h
@@ -60,12 +60,12 @@
 extern void dundi_set_output(void (*output)(const char *data));
 /* Choose a different function for errors */
 extern void dundi_set_error(void (*output)(const char *data));
-extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
+extern void dundi_showframe(struct dundi_hdr *fhi, int rx, union ip_addr *sin, int datalen);
 
 extern const char *dundi_ie2str(int ie);
 
 extern int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen);
-extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);
+extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, union ip_addr *sin);
 extern int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value);
 extern int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value);
 extern int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str);
diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c
index ff4fa3f..0627797 100644
--- a/pbx/pbx_dundi.c
+++ b/pbx/pbx_dundi.c
@@ -182,6 +182,8 @@
 #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME
 #endif
 
+
+
 static struct io_context *io;
 static struct ast_sched_context *sched;
 static int netsocket = -1;
@@ -211,6 +213,10 @@
 static time_t rotatetime;
 static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } };
 static int dundi_shutdown = 0;
+
+
+int netsock_ai_family = AF_INET;
+
 
 struct permission {
 	AST_LIST_ENTRY(permission) list;
@@ -242,8 +248,9 @@
 
 struct dundi_request;
 
+
 struct dundi_transaction {
-	struct sockaddr_in addr;                       /*!< Other end of transaction */
+    union ip_addr  addr;                            /*!< Other end of transaction */
 	struct timeval start;                          /*!< When this transaction was created */
 	dundi_eid eids[DUNDI_MAX_STACK + 1];
 	int eidcount;                                  /*!< Number of eids in eids */
@@ -302,7 +309,7 @@
 
 struct dundi_peer {
 	dundi_eid eid;
-	struct sockaddr_in addr;               /*!< Address of DUNDi peer */
+    union ip_addr  addr;                    /*!< Address of DUNDi peer */    
 	AST_LIST_HEAD_NOLOCK(permissionlist, permission) permit;
 	struct permissionlist include;
 	dundi_eid us_eid;
@@ -352,6 +359,8 @@
 static struct dundi_peer *any_peer;
 
 static int dundi_xmit(struct dundi_packet *pack);
+
+static int get_ai_family(const char *address);
 
 static void dundi_debug_output(const char *data)
 {
@@ -405,16 +414,38 @@
 		return -1;
 }
 
+
+static force_inline int inaddrcmp6(const struct sockaddr_in6 *sin1, const struct sockaddr_in6 *sin2)
+{
+    char str1[INET6_ADDRSTRLEN];
+    char str2[INET6_ADDRSTRLEN];
+
+    inet_ntop(AF_INET6, &(sin1->sin6_addr), str1, INET6_ADDRSTRLEN);
+    inet_ntop(AF_INET6, &(sin2->sin6_addr), str2, INET6_ADDRSTRLEN);
+
+    return ((strcmp(str1,str2) != 0) || (sin1->sin6_port != sin2->sin6_port));
+}
+
 static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]);
 static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]);
 static struct dundi_transaction *create_transaction(struct dundi_peer *p);
-static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
+static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, union ip_addr *sin)
 {
 	struct dundi_transaction *trans;
 
+    int cmp;
 	/* Look for an exact match first */
 	AST_LIST_TRAVERSE(&alltrans, trans, all) {
-		if (!inaddrcmp(&trans->addr, sin) &&
+        if ( netsock_ai_family == AF_INET6)
+        {
+            cmp = inaddrcmp6(&trans->addr.i6, &sin->i6);
+        }
+        else
+        {
+            cmp = inaddrcmp(&trans->addr.i4, &sin->i4);
+        }
+
+		if (  !cmp &&
 		     ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
 			  ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
 			  if (hdr->strans)
@@ -450,7 +481,7 @@
 {
 	return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
 }
-static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
+static void dundi_reject(struct dundi_hdr *h, union ip_addr *sin)
 {
 	struct {
 		struct dundi_packet pack;
@@ -462,7 +493,14 @@
 		return;
 	memset(&tmp, 0, sizeof(tmp));
 	memset(&trans, 0, sizeof(trans));
-	memcpy(&trans.addr, sin, sizeof(trans.addr));
+    if ( netsock_ai_family == AF_INET6)
+    {
+	    memcpy(&trans.addr, &sin->i6, sizeof(trans.addr.i6));
+    }
+    else
+    {
+	    memcpy(&trans.addr, &sin->i4, sizeof(trans.addr.i4));
+    }
 	tmp.hdr.strans = h->dtrans;
 	tmp.hdr.dtrans = h->strans;
 	tmp.hdr.iseqno = h->oseqno;
@@ -1291,8 +1329,16 @@
 
 static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
 {
-	if (!trans->addr.sin_addr.s_addr)
-		memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
+    if ( netsock_ai_family == AF_INET6)
+    {
+        if (!trans->addr.i6.sin6_addr.s6_addr[0])
+            memcpy(&trans->addr.i6, &p->addr.i6, sizeof(struct sockaddr_in6));
+    }
+    else
+    {
+        if (!trans->addr.i4.sin_addr.s_addr)
+            memcpy(&trans->addr.i4, &p->addr.i4, sizeof(trans->addr.i4));
+    }
 	trans->us_eid = p->us_eid;
 	trans->them_eid = p->eid;
 	/* Enable encryption if appropriate */
@@ -1706,16 +1752,31 @@
 				int needqual = 0;
 				AST_SCHED_DEL(sched, peer->registerexpire);
 				peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
-				snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr),
-					ntohs(trans->addr.sin_port), expire);
+                if ( netsock_ai_family == AF_INET6)
+                {
+                    char str[128]={0,};
+                    inet_ntop(AF_INET6, &(trans->addr.i6.sin6_addr), str, INET6_ADDRSTRLEN);
+                    snprintf(data, sizeof(data), "%s:%d:%d", str,
+                        ntohs(trans->addr.i6.sin6_port), expire);
+                    if (inaddrcmp6(&peer->addr.i6, &trans->addr.i6)) {
+                        ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",
+                                ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
+                                str, ntohs(trans->addr.i6.sin6_port));
+                        needqual = 1;
+                    }
+                }
+                else
+                {
+                    snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.i4.sin_addr),
+                        ntohs(trans->addr.i4.sin_port), expire);
+                    if (inaddrcmp(&peer->addr.i4, &trans->addr.i4)) {
+                        ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",
+                                ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
+                                ast_inet_ntoa(trans->addr.i4.sin_addr), ntohs(trans->addr.i4.sin_port));
+                        needqual = 1;
+                    }
+                }
 				ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
-				if (inaddrcmp(&peer->addr, &trans->addr)) {
-					ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",
-							ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
-							ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port));
-					needqual = 1;
-				}
-
 				memcpy(&peer->addr, &trans->addr, sizeof(peer->addr));
 				dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration);
 				dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
@@ -1840,7 +1901,16 @@
 							ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
 						if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
 							/* If it's them, update our address */
-							ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr));
+                            if ( netsock_ai_family == AF_INET6)
+                            {
+                                char str[80]={0,};
+                                inet_ntop(AF_INET6, &(trans->addr.i6.sin6_addr), str, INET6_ADDRSTRLEN);
+                                ast_copy_string(trans->parent->dei->ipaddr, str, sizeof(trans->parent->dei->ipaddr));
+                            }
+                            else
+                            {
+							    ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.i4.sin_addr), sizeof(trans->parent->dei->ipaddr));
+                            }
 						}
 					}
 					if (ies.hint) {
@@ -2023,7 +2093,7 @@
 	return 0;
 }
 
-static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
+static int handle_frame(struct dundi_hdr *h, union ip_addr *sin, int datalen)
 {
 	struct dundi_transaction *trans;
 	trans = find_transaction(h, sin);
@@ -2066,13 +2136,20 @@
 
 static int socket_read(int *id, int fd, short events, void *cbdata)
 {
-	struct sockaddr_in sin;
+    union ip_addr sin;
 	int res;
 	struct dundi_hdr *h;
 	char buf[MAX_PACKET_SIZE];
 	socklen_t len = sizeof(sin);
 
-	res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
+    if (netsock_ai_family == AF_INET6)
+    {
+	    res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin.i6, &len);
+    }
+    else
+    {
+	    res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin.i4, &len);
+    }
 	if (res < 0) {
 		if (errno != ECONNREFUSED)
 			ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
@@ -2625,8 +2702,18 @@
 		ast_cli(a->fd, "Peer:    %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
 		ast_cli(a->fd, "Model:   %s\n", model2str(peer->model));
 		ast_cli(a->fd, "Order:   %s\n", order);
-		ast_cli(a->fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
-		ast_cli(a->fd, "Port:    %d\n", ntohs(peer->addr.sin_port));
+        if ( netsock_ai_family == AF_INET6)
+        {
+            char host[INET6_ADDRSTRLEN]={0,};
+            peer->addr.i6.sin6_addr.s6_addr ?  inet_ntop(AF_INET6, &(peer->addr.i6.sin6_addr), host, INET6_ADDRSTRLEN):strcpy(host,"<Unspecified>");
+            ast_cli(a->fd, "Host:    %s\n", host);
+            ast_cli(a->fd, "Port:     %d\n", ntohs(peer->addr.i6.sin6_port));
+        }
+        else
+        {
+            ast_cli(a->fd, "Host:    %s\n", peer->addr.i4.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.i4.sin_addr) : "<Unspecified>");
+            ast_cli(a->fd, "Port:    %d\n", ntohs(peer->addr.i4.sin_port));
+        }
 		ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
 		ast_cli(a->fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
 		ast_cli(a->fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
@@ -2668,6 +2755,7 @@
 	int offline_peers = 0;
 	int unmonitored_peers = 0;
 	int total_peers = 0;
+    char host[INET6_ADDRSTRLEN]={0,};
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "dundi show peers [registered|include|exclude|begin]";
@@ -2697,8 +2785,17 @@
 		int print_line = -1;
 		char srch[2000];
 		total_peers++;
-		if (registeredonly && !peer->addr.sin_addr.s_addr)
-			continue;
+
+        if ( netsock_ai_family == AF_INET6 && registeredonly && !peer->addr.i6.sin6_addr.s6_addr)
+        {
+            continue;
+        }
+
+        if ( netsock_ai_family == AF_INET && registeredonly && !peer->addr.i4.sin_addr.s_addr)
+        {
+            continue;
+        }
+
 		if (peer->maxms) {
 			if (peer->lastms < 0) {
 				strcpy(status, "UNREACHABLE");
@@ -2724,9 +2821,18 @@
 			snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
 		else
 			strcpy(avgms, "Unavail");
-		snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
-					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
-					peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
+        if (netsock_ai_family == AF_INET6)
+        {
+            peer->addr.i6.sin6_addr.s6_addr ? inet_ntop(AF_INET6, &(peer->addr.i6.sin6_addr), host, INET6_ADDRSTRLEN) : strcpy(host,"(Unspecified)");
+            snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),host,
+                        peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.i6.sin6_port), model2str(peer->model), avgms, status);
+        }
+        else
+        {
+            snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
+                        peer->addr.i4.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.i4.sin_addr) : "(Unspecified)",
+                        peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.i4.sin_port), model2str(peer->model), avgms, status);
+        }
 
                 if (a->argc == 5) {
                   if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {
@@ -2741,9 +2847,18 @@
                 }
 
         if (print_line) {
-			ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
-					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
-					peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
+            if ( netsock_ai_family == AF_INET6)
+            {
+                ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
+                        host,
+                        peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.i6.sin6_port), model2str(peer->model), avgms, status);
+            }
+            else
+            {
+                ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
+                        peer->addr.i4.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.i4.sin_addr) : "(Unspecified)",
+                        peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.i4.sin_port), model2str(peer->model), avgms, status);
+            }
 		}
 	}
 	ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
@@ -2774,8 +2889,19 @@
 	AST_LIST_LOCK(&peers);
 	ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
 	AST_LIST_TRAVERSE(&alltrans, trans, all) {
-		ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr),
-			ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
+        if ( netsock_ai_family == AF_INET6)
+        {
+            char host[INET6_ADDRSTRLEN]={0,};
+            inet_ntop(AF_INET6, &(trans->addr.i6.sin6_addr), host, INET6_ADDRSTRLEN);
+            ast_cli(a->fd, FORMAT, host,
+                ntohs(trans->addr.i6.sin6_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
+        }
+        else
+        {
+            ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.i4.sin_addr),
+                ntohs(trans->addr.i4.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
+
+        }
 	}
 	AST_LIST_UNLOCK(&peers);
 	return CLI_SUCCESS;
@@ -3067,7 +3193,7 @@
 	ast_db_freetree(db_tree);
 
 	return CLI_SUCCESS;
-#undef FORMAT
+#undef FORMATEID
 #undef FORMAT2
 }
 
@@ -3095,8 +3221,18 @@
 	int tid;
 
 	/* Don't allow creation of transactions to non-registered peers */
-	if (p && !p->addr.sin_addr.s_addr)
-		return NULL;
+
+    if ( netsock_ai_family == AF_INET6)
+    {
+	    if (p && !p->addr.i6.sin6_addr.s6_addr[0])
+            return NULL;
+    }
+    else
+    {
+	    if (p && !p->addr.i4.sin_addr.s_addr)
+            return NULL;
+    }
+
 	tid = get_trans_id();
 	if (tid < 1)
 		return NULL;
@@ -3127,9 +3263,20 @@
 		dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
 	res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
 	if (res < 0) {
-		ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
-			ast_inet_ntoa(pack->parent->addr.sin_addr),
-			ntohs(pack->parent->addr.sin_port), strerror(errno));
+        if ( netsock_ai_family == AF_INET6)
+        {
+            char host[INET6_ADDRSTRLEN]={0,};
+            inet_ntop(AF_INET6, &(pack->parent->addr.i6.sin6_addr), host, INET6_ADDRSTRLEN);
+            ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
+                host,
+                ntohs(pack->parent->addr.i6.sin6_port), strerror(errno));
+        }
+        else
+        {
+            ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
+                ast_inet_ntoa(pack->parent->addr.i4.sin_addr),
+                ntohs(pack->parent->addr.i4.sin_port), strerror(errno));
+         }
 	}
 	if (res > 0)
 		res = 0;
@@ -3236,9 +3383,23 @@
 	if (pack->retrans < 1) {
 		pack->retransid = -1;
 		if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
-			ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
-				ast_inet_ntoa(pack->parent->addr.sin_addr),
-				ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
+        {
+            if ( netsock_ai_family == AF_INET6)
+            {
+                char host[INET6_ADDRSTRLEN]={0,};
+                inet_ntop(AF_INET6, &(pack->parent->addr.i6.sin6_addr), host, INET6_ADDRSTRLEN);
+                ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
+                    host,
+                    ntohs(pack->parent->addr.i6.sin6_port), pack->h->oseqno, ntohs(pack->h->strans));
+
+            }
+            else
+            {
+                ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
+                    ast_inet_ntoa(pack->parent->addr.i4.sin_addr),
+                    ntohs(pack->parent->addr.i4.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
+            }
+        }
 		destroy_trans(pack->parent, 1);
 		res = 0;
 	} else {
@@ -3593,8 +3754,17 @@
 	char eid_str2[20];
 
 	/* Ignore if not registered */
-	if (!p->addr.sin_addr.s_addr)
-		return 0;
+    if ( netsock_ai_family == AF_INET6)
+    {
+	    if (!p->addr.i6.sin6_addr.s6_addr)
+            return 0;
+    }
+    else
+    {
+	    if (!p->addr.i4.sin_addr.s_addr)
+            return 0;
+    }
+
 	if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
 		return 0;
 
@@ -4519,6 +4689,8 @@
 		}
 	}
 }
+
+// TODO : check address population
 static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
 {
 	char data[256];
@@ -4533,9 +4705,19 @@
 			c++;
 			if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {
 				/* Got it! */
-				inet_aton(data, &peer->addr.sin_addr);
-				peer->addr.sin_family = AF_INET;
-				peer->addr.sin_port = htons(port);
+                if ( netsock_ai_family == AF_INET6)
+                {
+                    inet_pton(AF_INET6, data, &(peer->addr.i6.sin6_addr));
+                    peer->addr.i6.sin6_family = AF_INET6;
+                    peer->addr.i6.sin6_port = htons(port);
+                }
+                else
+                {
+                    inet_aton(data, &peer->addr.i4.sin_addr);
+                    peer->addr.i4.sin_family = AF_INET;
+                    peer->addr.i4.sin_port = htons(port);
+
+                }
 				peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
 			}
 		}
@@ -4546,7 +4728,6 @@
 static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
 {
 	struct dundi_peer *peer;
-	struct ast_hostent he;
 	struct hostent *hp;
 	dundi_eid testeid;
 	int needregister=0;
@@ -4567,8 +4748,18 @@
 		peer->registerid = -1;
 		peer->registerexpire = -1;
 		peer->qualifyid = -1;
-		peer->addr.sin_family = AF_INET;
-		peer->addr.sin_port = htons(DUNDI_PORT);
+
+        if ( netsock_ai_family == AF_INET6)
+        {
+            peer->addr.i6.sin6_family = AF_INET6;
+            peer->addr.i6.sin6_port = htons(DUNDI_PORT);
+        }
+        else
+        {
+            peer->addr.i4.sin_family = AF_INET;
+            peer->addr.i4.sin_port = htons(DUNDI_PORT);
+        }
+
 		populate_addr(peer, eid);
 		AST_LIST_INSERT_HEAD(&peers, peer, list);
 	}
@@ -4584,19 +4775,36 @@
 		} else if (!strcasecmp(v->name, "outkey")) {
 			ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
 		} else if (!strcasecmp(v->name, "port")) {
-			peer->addr.sin_port = htons(atoi(v->value));
+
+        if ( netsock_ai_family == AF_INET6)
+        {
+			peer->addr.i6.sin6_port = htons(atoi(v->value));
+        }
+        else
+        {
+			peer->addr.i4.sin_port = htons(atoi(v->value));
+        }
 		} else if (!strcasecmp(v->name, "host")) {
 			if (!strcasecmp(v->value, "dynamic")) {
 				peer->dynamic = 1;
 			} else {
-				hp = ast_gethostbyname(v->value, &he);
-				if (hp) {
-					memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
-					peer->dynamic = 0;
-				} else {
-					ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
-					peer->dead = 1;
-				}
+                if ( netsock_ai_family == AF_INET6)
+                {
+                    inet_pton(AF_INET6, v->value, &(peer->addr.i6.sin6_addr));
+                    peer->dynamic = 0;
+                }
+                else
+                {
+                    struct ast_hostent  he;
+                    hp = ast_gethostbyname(v->value, &he);
+                    if (hp) {
+                            memcpy(&peer->addr.i4.sin_addr, hp->h_addr, sizeof(peer->addr.i4.sin_addr));
+                            peer->dynamic = 0;
+                    } else {
+                            ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
+                            peer->dead = 1;
+                    }
+                }
 			}
 		} else if (!strcasecmp(v->name, "ustothem")) {
 			if (!ast_str_to_eid(&testeid, v->value))
@@ -4811,7 +5019,32 @@
 	.matchmore   = dundi_matchmore,
 };
 
-static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
+
+static int get_ai_family(const char *address)
+{
+    struct addrinfo hint, *res = NULL;
+    int ret;
+
+    memset(&hint, '\0', sizeof hint);
+
+    hint.ai_family = PF_UNSPEC;
+    hint.ai_flags = AI_NUMERICHOST;
+
+    ret = getaddrinfo(address, NULL, &hint, &res);
+    if (ret) {
+		ast_log(LOG_ERROR, "Invalid address %s \n", address);
+        return -1;
+    }
+
+   ret = res->ai_family;
+
+   freeaddrinfo(res);
+
+   return ret;
+}
+
+
+static int set_config(char *config_file, union ip_addr* sin, int reload)
 {
 	struct ast_config *cfg;
 	struct ast_variable *v;
@@ -4819,9 +5052,11 @@
 	int x;
 	struct ast_flags config_flags = { 0 };
 	char hn[MAXHOSTNAMELEN] = "";
+    struct hostent *hp;
 	struct ast_hostent he;
-	struct hostent *hp;
-	struct sockaddr_in sin2;
+	
+    union ip_addr sin2;
+
 	static int last_port = 0;
 	int globalpcmodel = 0;
 	dundi_eid testeid;
@@ -4836,15 +5071,30 @@
 	any_peer = NULL;
 
 	ipaddr[0] = '\0';
+
 	if (!gethostname(hn, sizeof(hn)-1)) {
-		hp = ast_gethostbyname(hn, &he);
-		if (hp) {
-			memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
-			ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));
-		} else
-			ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
+        if ( netsock_ai_family == AF_INET6)
+        {
+            struct in6_addr ipv6addr;
+            strcpy(ipaddr,"::1"); // localaddress
+            inet_pton(AF_INET6,ipaddr,&ipv6addr);
+            hp =   gethostbyaddr(&ipv6addr, sizeof ipv6addr, AF_INET6);		
+            if ( hp) {
+                memcpy(&sin2.i6.sin6_addr, hp->h_addr, sizeof(sin2.i6.sin6_addr));
+            }
+        }
+        else
+        {
+            hp = ast_gethostbyname(hn, &he);
+            if (hp) {
+                memcpy(&sin2.i4.sin_addr, hp->h_addr, sizeof(sin2.i4.sin_addr));
+                ast_copy_string(ipaddr, ast_inet_ntoa(sin2.i4.sin_addr), sizeof(ipaddr));
+            }
+
+        }
 	} else
-		ast_log(LOG_WARNING, "Unable to get host name!\n");
+		ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
+
 	AST_LIST_LOCK(&peers);
 
 	if (ast_eid_is_empty(&ast_eid_default)) {
@@ -4857,19 +5107,48 @@
 	v = ast_variable_browse(cfg, "general");
 	while(v) {
 		if (!strcasecmp(v->name, "port")){
-			sin->sin_port = htons(atoi(v->value));
-			if(last_port==0){
-				last_port=sin->sin_port;
-			} else if(sin->sin_port != last_port)
-				ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
+            if ( netsock_ai_family == AF_INET6)
+            {
+                sin->i6.sin6_port = htons(atoi(v->value));
+                if(last_port==0){
+                    last_port=sin->i6.sin6_port;
+                } else if(sin->i6.sin6_port != last_port)
+                    ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
+            }
+            else
+            {
+                sin->i4.sin_port = htons(atoi(v->value));
+                if(last_port==0){
+                    last_port=sin->i4.sin_port;
+                } else if(sin->i4.sin_port != last_port)
+                    ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
+            }
 		} else if (!strcasecmp(v->name, "bindaddr")) {
 			struct hostent *hep;
-			struct ast_hostent hent;
-			hep = ast_gethostbyname(v->value, &hent);
-			if (hep) {
-				memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr));
-			} else
-				ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
+
+            netsock_ai_family = get_ai_family(v->value);
+            if ( netsock_ai_family == -1)
+            {
+                return -1;
+            }
+            
+            if( netsock_ai_family == AF_INET6)
+            {
+                if ( inet_pton(AF_INET6,v->value, &(sin->i6.sin6_addr)) < 0 )
+                {
+                    ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
+                }
+            }
+            else
+            {
+                struct ast_hostent hent;
+                hep = ast_gethostbyname(v->value, &hent);
+                if (hep) {
+                    memcpy(&sin->i4.sin_addr, hep->h_addr, sizeof(sin->i4.sin_addr));
+                } else
+                    ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
+            }
+
 		} else if (!strcasecmp(v->name, "authdebug")) {
 			authdebug = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "ttl")) {
@@ -4994,7 +5273,7 @@
 
 static int reload(void)
 {
-	struct sockaddr_in sin;
+    union ip_addr sin;
 
 	if (set_config("dundi.conf", &sin, 1))
 		return AST_MODULE_LOAD_FAILURE;
@@ -5004,44 +5283,81 @@
 
 static int load_module(void)
 {
-	struct sockaddr_in sin;
+    union ip_addr sin;
 
 	dundi_set_output(dundi_debug_output);
 	dundi_set_error(dundi_error_output);
-
-	sin.sin_family = AF_INET;
-	sin.sin_port = htons(DUNDI_PORT);
-	sin.sin_addr.s_addr = INADDR_ANY;
 
 	/* Make a UDP socket */
 	io = io_context_create();
 	sched = ast_sched_context_create();
 
-	if (!io || !sched) {
-		goto declined;
-	}
+	if (!io || !sched)
+		return AST_MODULE_LOAD_DECLINE;
 
-	if (set_config("dundi.conf", &sin, 0)) {
-		goto declined;
-	}
+    memset(&sin,0,sizeof(union ip_addr));
 
-	netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+	if (set_config("dundi.conf", &sin, 0))
+		return AST_MODULE_LOAD_DECLINE;
+
+    if ( netsock_ai_family == AF_INET6)
+    {
+        sin.i6.sin6_family = AF_INET6;
+        if ( sin.i6.sin6_port == 0 )
+        {
+            sin.i6.sin6_port = htons(DUNDI_PORT);
+        }
+        if ( sin.i6.sin6_addr.s6_addr[0] == 0)
+        {
+            sin.i6.sin6_addr = in6addr_any;
+        }
+	    netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+    }
+    else
+    {
+        sin.i4.sin_family = AF_INET;
+        if ( sin.i4.sin_port == 0 )
+        {
+            sin.i4.sin_port = htons(DUNDI_PORT);
+        }
+        if ( !sin.i4.sin_addr.s_addr)
+        {
+            sin.i4.sin_addr.s_addr = INADDR_ANY;
+        }
+	    netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+    }
 
 	if (netsocket < 0) {
 		ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
-		goto declined;
+		return AST_MODULE_LOAD_DECLINE;
 	}
-	if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) {
-		ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",
-			ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
-		goto declined;
-	}
+
+    if ( netsock_ai_family == AF_INET6)
+    {
+       char str[128]={0,};
+        inet_ntop(AF_INET6, &(sin.i6.sin6_addr), str, INET6_ADDRSTRLEN);
+        if (bind(netsocket, (struct sockaddr_in6 *) &sin.i6, sizeof(sin.i6))) {
+            ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",
+                str, ntohs(sin.i6.sin6_port), strerror(errno));
+            return AST_MODULE_LOAD_DECLINE;
+        }
+    }
+    else
+    {
+        if (bind(netsocket, (struct sockaddr *) &sin.i4, sizeof(sin.i4))) {
+            ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",
+                ast_inet_ntoa(sin.i4.sin_addr), ntohs(sin.i4.sin_port), strerror(errno));
+            return AST_MODULE_LOAD_DECLINE;
+        }
+    }
+
 
 	ast_set_qos(netsocket, tos, 0, "DUNDi");
 
 	if (start_network_thread()) {
 		ast_log(LOG_ERROR, "Unable to start network thread\n");
-		goto declined;
+		close(netsocket);
+		return AST_MODULE_LOAD_DECLINE;
 	}
 
 	ast_cli_register_multiple(cli_dundi, ARRAY_LEN(cli_dundi));
@@ -5051,13 +5367,19 @@
 	ast_custom_function_register(&dundi_query_function);
 	ast_custom_function_register(&dundi_result_function);
 
-	ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+    if (netsock_ai_family == AF_INET6)
+    {
+        char str[128]={0,};
+        inet_ntop(AF_INET6, &(sin.i6.sin6_addr), str, INET6_ADDRSTRLEN);
+        ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", str, ntohs(sin.i6.sin6_port));
+    }
+    else
+    {
+	    ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.i4.sin_addr), ntohs(sin.i4.sin_port));
+    }   
+
 
 	return AST_MODULE_LOAD_SUCCESS;
-
-declined:
-	unload_module();
-	return AST_MODULE_LOAD_DECLINE;
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Distributed Universal Number Discovery (DUNDi)",

-- 
To view, visit https://gerrit.asterisk.org/6173
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifbe298afc6416ba400db7be404a25994ad23968a
Gerrit-Change-Number: 6173
Gerrit-PatchSet: 1
Gerrit-Owner: Adam Secombe <adam.j.secombe at boeing.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170806/3b79c708/attachment-0001.html>


More information about the asterisk-code-review mailing list