<p>Kirsty Tyerman has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/9150">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pbx_dundi: Added IPv6 support for dundi<br><br>Change includes move to netsock2 library.<br><br>ASTERISK-27164<br>Reported-by: Adam Secombe<br><br>Change-Id: Ia9e8dc3d153de7a291dbda4bd87fc827dd2bb846<br>---<br>M pbx/dundi-parser.c<br>M pbx/dundi-parser.h<br>M pbx/pbx_dundi.c<br>3 files changed, 188 insertions(+), 134 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/50/9150/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/pbx/dundi-parser.c b/pbx/dundi-parser.c<br>index 9b41aa9..bfc0c06 100644<br>--- a/pbx/dundi-parser.c<br>+++ b/pbx/dundi-parser.c<br>@@ -39,6 +39,7 @@<br> #include "asterisk/dundi.h"<br> #include "dundi-parser.h"<br> <br>+extern int netsock_ai_family;<br> static void internaloutput(const char *str)<br> {<br> fputs(str, stdout);<br>@@ -430,7 +431,7 @@<br> outputf("\n");<br> }<br> <br>-void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)<br>+void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)<br> {<br> char *pref[] = {<br> "Tx",<br>@@ -471,11 +472,13 @@<br> pref[rx],<br> fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");<br> outputf(tmp);<br>- snprintf(tmp, (int)sizeof(tmp), <br>- "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? " " : "",<br>+<br>+ snprintf(tmp, (int)sizeof(tmp),<br>+ "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s]%s\n", (rx > 1) ? " " : "",<br> subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,<br>- ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),<br>+ ast_sockaddr_stringify(sin),<br> fhi->cmdresp & 0x80 ? " (Final)" : "");<br>+<br> outputf(tmp);<br> dump_ies(fhi->ies, rx > 1, datalen);<br> }<br>@@ -582,9 +585,9 @@<br> return 0;<br> }<br> <br>-int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)<br>+int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct ast_sockaddr *sin)<br> {<br>- return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));<br>+ return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct ast_sockaddr));<br> }<br> <br> int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value) <br>diff --git a/pbx/dundi-parser.h b/pbx/dundi-parser.h<br>index b24d486..b405a42 100644<br>--- a/pbx/dundi-parser.h<br>+++ b/pbx/dundi-parser.h<br>@@ -60,12 +60,12 @@<br> extern void dundi_set_output(void (*output)(const char *data));<br> /* Choose a different function for errors */<br> extern void dundi_set_error(void (*output)(const char *data));<br>-extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);<br>+extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen);<br> <br> extern const char *dundi_ie2str(int ie);<br> <br> extern int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen);<br>-extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);<br>+extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct ast_sockaddr *sin);<br> extern int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value);<br> extern int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value);<br> extern int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str);<br>diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c<br>index 501bcd1..373c836 100644<br>--- a/pbx/pbx_dundi.c<br>+++ b/pbx/pbx_dundi.c<br>@@ -50,7 +50,6 @@<br> #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__)<br> #include <net/if_dl.h><br> #include <ifaddrs.h><br>-#include <signal.h><br> #endif<br> <br> #include "asterisk/file.h"<br>@@ -99,8 +98,8 @@<br> in the DUNDi lookup. If no results were found, the result will be blank.</para><br> </description><br> </function><br>- <br>- <br>+<br>+<br> <function name="DUNDIQUERY" language="en_US"><br> <synopsis><br> Initiate a DUNDi query.<br>@@ -243,7 +242,7 @@<br> struct dundi_request;<br> <br> struct dundi_transaction {<br>- struct sockaddr_in addr; /*!< Other end of transaction */<br>+ struct ast_sockaddr addr; /*!< Other end of transaction */<br> struct timeval start; /*!< When this transaction was created */<br> dundi_eid eids[DUNDI_MAX_STACK + 1];<br> int eidcount; /*!< Number of eids in eids */<br>@@ -302,7 +301,7 @@<br> <br> struct dundi_peer {<br> dundi_eid eid;<br>- struct sockaddr_in addr; /*!< Address of DUNDi peer */<br>+ struct ast_sockaddr addr; /*!< Address of DUNDi peer */ <br> AST_LIST_HEAD_NOLOCK(permissionlist, permission) permit;<br> struct permissionlist include;<br> dundi_eid us_eid;<br>@@ -352,6 +351,29 @@<br> static struct dundi_peer *any_peer;<br> <br> static int dundi_xmit(struct dundi_packet *pack);<br>+<br>+static int get_ai_family(const char *address)<br>+{<br>+ struct addrinfo hint, *res = NULL;<br>+ int ret;<br>+<br>+ memset(&hint, '\0', sizeof hint);<br>+<br>+ hint.ai_family = PF_UNSPEC;<br>+ hint.ai_flags = AI_NUMERICHOST;<br>+<br>+ ret = getaddrinfo(address, NULL, &hint, &res);<br>+ if (ret) {<br>+ ast_log(LOG_ERROR, "Invalid address %s \n", address);<br>+ return -1;<br>+ }<br>+<br>+ ret = res->ai_family;<br>+<br>+ freeaddrinfo(res);<br>+<br>+ return ret;<br>+}<br> <br> static void dundi_debug_output(const char *data)<br> {<br>@@ -408,13 +430,15 @@<br> 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[]);<br> static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]);<br> static struct dundi_transaction *create_transaction(struct dundi_peer *p);<br>-static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)<br>+static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct ast_sockaddr *sin)<br> {<br> struct dundi_transaction *trans;<br> <br>+ int cmp;<br> /* Look for an exact match first */<br> AST_LIST_TRAVERSE(&alltrans, trans, all) {<br>- if (!inaddrcmp(&trans->addr, sin) &&<br>+ cmp = ast_sockaddr_cmp(&trans->addr, sin);<br>+ if ( !cmp &&<br> ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||<br> ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {<br> if (hdr->strans)<br>@@ -450,7 +474,7 @@<br> {<br> return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);<br> }<br>-static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)<br>+static void dundi_reject(struct dundi_hdr *h, struct ast_sockaddr *sin)<br> {<br> struct {<br> struct dundi_packet pack;<br>@@ -462,7 +486,7 @@<br> return;<br> memset(&tmp, 0, sizeof(tmp));<br> memset(&trans, 0, sizeof(trans));<br>- memcpy(&trans.addr, sin, sizeof(trans.addr));<br>+ memcpy(&trans.addr, sin, sizeof(struct ast_sockaddr));<br> tmp.hdr.strans = h->dtrans;<br> tmp.hdr.dtrans = h->strans;<br> tmp.hdr.iseqno = h->oseqno;<br>@@ -562,7 +586,7 @@<br> if (map->weightstr) {<br> if (headp) {<br> pbx_substitute_variables_varshead(headp, map->weightstr, buf, sizeof(buf) - 1);<br>- } else { <br>+ } else {<br> pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1);<br> }<br> <br>@@ -994,9 +1018,9 @@<br> sizeof(trans->parent->dr[trans->parent->respcount].tech));<br> trans->parent->respcount++;<br> ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);<br>- } else if (trans->parent->dr[z].weight > ntohs(ies->answers[x]->weight)) {<br>+ } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) {<br> /* Update weight if appropriate */<br>- trans->parent->dr[z].weight = ntohs(ies->answers[x]->weight);<br>+ trans->parent->dr[z].weight = ies->answers[x]->weight;<br> }<br> } else<br> ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n",<br>@@ -1291,8 +1315,8 @@<br> <br> static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)<br> {<br>- if (!trans->addr.sin_addr.s_addr)<br>- memcpy(&trans->addr, &p->addr, sizeof(trans->addr));<br>+ if ( ast_sockaddr_isnull(&trans->addr))<br>+ memcpy(&trans->addr, &p->addr, sizeof(struct ast_sockaddr));<br> trans->us_eid = p->us_eid;<br> trans->them_eid = p->eid;<br> /* Enable encryption if appropriate */<br>@@ -1706,13 +1730,12 @@<br> int needqual = 0;<br> AST_SCHED_DEL(sched, peer->registerexpire);<br> peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);<br>- snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr),<br>- ntohs(trans->addr.sin_port), expire);<br>+ snprintf(data,sizeof(data),"%s:%d",ast_sockaddr_stringify(&trans->addr),expire);<br> ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);<br>- if (inaddrcmp(&peer->addr, &trans->addr)) {<br>- ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",<br>- ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),<br>- ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port));<br>+ if ( ast_sockaddr_cmp(&peer->addr,&trans->addr)) {<br>+ ast_verb(3, "Registered DUNDi peer '%s' at '%s'\n",<br>+ ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),<br>+ ast_sockaddr_stringify(&trans->addr));<br> needqual = 1;<br> }<br> <br>@@ -1764,9 +1787,9 @@<br> sizeof(trans->parent->dr[trans->parent->respcount].tech));<br> trans->parent->respcount++;<br> ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);<br>- } else if (trans->parent->dr[z].weight > ntohs(ies.answers[x]->weight)) {<br>+ } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) {<br> /* Update weight if appropriate */<br>- trans->parent->dr[z].weight = ntohs(ies.answers[x]->weight);<br>+ trans->parent->dr[z].weight = ies.answers[x]->weight;<br> }<br> } else<br> ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",<br>@@ -1840,7 +1863,7 @@<br> ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));<br> if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {<br> /* If it's them, update our address */<br>- ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr));<br>+ ast_copy_string(trans->parent->dei->ipaddr,ast_sockaddr_stringify_addr(&trans->addr),sizeof(trans->parent->dei->ipaddr));<br> }<br> }<br> if (ies.hint) {<br>@@ -2023,7 +2046,7 @@<br> return 0;<br> }<br> <br>-static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)<br>+static int handle_frame(struct dundi_hdr *h, struct ast_sockaddr *sin, int datalen)<br> {<br> struct dundi_transaction *trans;<br> trans = find_transaction(h, sin);<br>@@ -2066,13 +2089,13 @@<br> <br> static int socket_read(int *id, int fd, short events, void *cbdata)<br> {<br>- struct sockaddr_in sin;<br>+ struct ast_sockaddr sin;<br> int res;<br> struct dundi_hdr *h;<br> char buf[MAX_PACKET_SIZE];<br>- socklen_t len = sizeof(sin);<br> <br>- res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);<br>+ res = ast_recvfrom(netsocket,buf,sizeof(buf),0,&sin);<br>+<br> if (res < 0) {<br> if (errno != ECONNREFUSED)<br> ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));<br>@@ -2625,8 +2648,8 @@<br> ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));<br> ast_cli(a->fd, "Model: %s\n", model2str(peer->model));<br> ast_cli(a->fd, "Order: %s\n", order);<br>- ast_cli(a->fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");<br>- ast_cli(a->fd, "Port: %d\n", ntohs(peer->addr.sin_port));<br>+ ast_cli(a->fd, "Host: %s\n", ast_sockaddr_isnull(&peer->addr) ?"<Unspecified>": ast_sockaddr_stringify_host(&peer->addr));<br>+ ast_cli(a->fd, "Port: %d\n", ast_sockaddr_port(&peer->addr));<br> ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");<br> ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");<br> ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);<br>@@ -2658,8 +2681,8 @@<br> <br> static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)<br> {<br>-#define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"<br>-#define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"<br>+#define FORMAT2 "%-20.20s %-39s %-6.6s %-10.10s %-8.8s %-15.15s\n"<br>+#define FORMAT "%-20.20s %-39s %s %-6d %-10.10s %-8.8s %-15.15s\n"<br> struct dundi_peer *peer;<br> int registeredonly=0;<br> char avgms[20];<br>@@ -2697,7 +2720,8 @@<br> int print_line = -1;<br> char srch[2000];<br> total_peers++;<br>- if (registeredonly && !peer->addr.sin_addr.s_addr)<br>+<br>+ if (registeredonly && ast_sockaddr_isnull(&peer->addr)) <br> continue;<br> if (peer->maxms) {<br> if (peer->lastms < 0) {<br>@@ -2724,9 +2748,9 @@<br> snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);<br> else<br> strcpy(avgms, "Unavail");<br>- snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),<br>- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",<br>- peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);<br>+ snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), <br>+ &peer->eid),ast_sockaddr_stringify_host(&peer->addr),<br>+ peer->dynamic ? "(D)" : "(S)", ast_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);<br> <br> if (a->argc == 5) {<br> if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {<br>@@ -2742,8 +2766,8 @@<br> <br> if (print_line) {<br> ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),<br>- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",<br>- peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);<br>+ ast_sockaddr_stringify_host(&peer->addr),<br>+ peer->dynamic ? "(D)" : "(S)", ast_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);<br> }<br> }<br> ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);<br>@@ -2755,8 +2779,8 @@<br> <br> static char *dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)<br> {<br>-#define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"<br>-#define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"<br>+#define FORMAT2 "%-44s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"<br>+#define FORMAT "%-39s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"<br> struct dundi_transaction *trans;<br> switch (cmd) {<br> case CLI_INIT:<br>@@ -2774,8 +2798,9 @@<br> AST_LIST_LOCK(&peers);<br> ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");<br> AST_LIST_TRAVERSE(&alltrans, trans, all) {<br>- ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr),<br>- ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);<br>+ ast_cli(a->fd, FORMAT, ast_sockaddr_stringify_host(&trans->addr),<br>+ ast_sockaddr_port(&trans->addr), trans->strans, trans->dtrans,<br>+ trans->oseqno, trans->iseqno, trans->aseqno);<br> }<br> AST_LIST_UNLOCK(&peers);<br> return CLI_SUCCESS;<br>@@ -3095,7 +3120,8 @@<br> int tid;<br> <br> /* Don't allow creation of transactions to non-registered peers */<br>- if (p && !p->addr.sin_addr.s_addr)<br>+<br>+ if (p && ast_sockaddr_isnull(&p->addr))<br> return NULL;<br> tid = get_trans_id();<br> if (tid < 1)<br>@@ -3125,11 +3151,10 @@<br> int res;<br> if (dundidebug)<br> dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));<br>- res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));<br>+ res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, pack->parent->addr.len);<br> if (res < 0) {<br>- ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",<br>- ast_inet_ntoa(pack->parent->addr.sin_addr),<br>- ntohs(pack->parent->addr.sin_port), strerror(errno));<br>+ ast_log(LOG_WARNING, "Failed to transmit to '%s': %s\n",<br>+ ast_sockaddr_stringify(&pack->parent->addr), strerror(errno));<br> }<br> if (res > 0)<br> res = 0;<br>@@ -3236,9 +3261,8 @@<br> if (pack->retrans < 1) {<br> pack->retransid = -1;<br> if (!ast_test_flag(pack->parent, FLAG_ISQUAL))<br>- ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",<br>- ast_inet_ntoa(pack->parent->addr.sin_addr),<br>- ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));<br>+ ast_log(LOG_NOTICE, "Max retries exceeded to host '%s' msg %d on call %d\n",<br>+ ast_sockaddr_stringify(&pack->parent->addr), pack->h->oseqno, ntohs(pack->h->strans));<br> destroy_trans(pack->parent, 1);<br> res = 0;<br> } else {<br>@@ -3593,7 +3617,7 @@<br> char eid_str2[20];<br> <br> /* Ignore if not registered */<br>- if (!p->addr.sin_addr.s_addr)<br>+ if (ast_sockaddr_isnull(&p->addr))<br> return 0;<br> if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))<br> return 0;<br>@@ -4533,9 +4557,18 @@<br> c++;<br> if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {<br> /* Got it! */<br>- inet_aton(data, &peer->addr.sin_addr);<br>- peer->addr.sin_family = AF_INET;<br>- peer->addr.sin_port = htons(port);<br>+ struct ast_sockaddr *addrs;<br>+ int cnt;<br>+ cnt = ast_sockaddr_resolve(&addrs,data,PARSE_PORT_FORBID,AF_UNSPEC);<br>+ for ( int i=0; i < cnt; i++)<br>+ {<br>+ if ( i ==0 ) {<br>+ memcpy(&peer->addr,&addrs[i],sizeof(struct ast_sockaddr));<br>+ peer->addr.ss.ss_family = get_ai_family(data);<br>+ }<br>+ ast_free(&addrs[i]);<br>+ }<br>+ ast_sockaddr_set_port(&peer->addr,port);<br> peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);<br> }<br> }<br>@@ -4543,11 +4576,9 @@<br> }<br> <br> <br>-static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)<br>+static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode, sa_family_t family)<br> {<br> struct dundi_peer *peer;<br>- struct ast_hostent he;<br>- struct hostent *hp;<br> dundi_eid testeid;<br> int needregister=0;<br> char eid_str[20];<br>@@ -4567,8 +4598,8 @@<br> peer->registerid = -1;<br> peer->registerexpire = -1;<br> peer->qualifyid = -1;<br>- peer->addr.sin_family = AF_INET;<br>- peer->addr.sin_port = htons(DUNDI_PORT);<br>+ peer->addr.ss.ss_family = family;<br>+ ast_sockaddr_set_port(&peer->addr,DUNDI_PORT);<br> populate_addr(peer, eid);<br> AST_LIST_INSERT_HEAD(&peers, peer, list);<br> }<br>@@ -4584,20 +4615,28 @@<br> } else if (!strcasecmp(v->name, "outkey")) {<br> ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));<br> } else if (!strcasecmp(v->name, "port")) {<br>- peer->addr.sin_port = htons(atoi(v->value));<br>+ ast_sockaddr_set_port(&peer->addr,atoi(v->value));<br> } else if (!strcasecmp(v->name, "host")) {<br> if (!strcasecmp(v->value, "dynamic")) {<br> peer->dynamic = 1;<br> } else {<br>- hp = ast_gethostbyname(v->value, &he);<br>- if (hp) {<br>- memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));<br>- peer->dynamic = 0;<br>+ int cnt;<br>+ struct ast_sockaddr *addrs;<br>+ cnt = ast_sockaddr_resolve(&addrs,v->value,PARSE_PORT_FORBID,family);<br>+ if ( cnt > 0 ) {<br>+ for ( int i=0; i < cnt; i++) {<br>+ if ( i ==0 ) {<br>+ memcpy(&peer->addr,&addrs[i],sizeof(struct ast_sockaddr));<br>+ peer->addr.ss.ss_family = get_ai_family(v->value);<br>+ peer->dynamic = 0;<br>+ }<br>+ ast_free(&addrs[i]);<br>+ }<br> } else {<br> ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);<br> peer->dead = 1;<br> }<br>- }<br>+ }<br> } else if (!strcasecmp(v->name, "ustothem")) {<br> if (!ast_str_to_eid(&testeid, v->value))<br> peer->us_eid = testeid;<br>@@ -4663,6 +4702,11 @@<br> }<br> }<br> }<br>+<br>+ if ( ast_sockaddr_port(&peer->addr) == 0 ){<br>+ ast_sockaddr_set_port(&peer->addr,DUNDI_PORT);<br>+ }<br>+<br> (*globalpcmode) |= peer->pcmodel;<br> if (!peer->model && !peer->pcmodel) {<br> ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",<br>@@ -4811,18 +4855,16 @@<br> .matchmore = dundi_matchmore,<br> };<br> <br>-static int set_config(char *config_file, struct sockaddr_in* sin, int reload)<br>+<br>+static int set_config(char *config_file, struct ast_sockaddr* sin, int reload)<br> {<br> struct ast_config *cfg;<br> struct ast_variable *v;<br> char *cat;<br> int x;<br> struct ast_flags config_flags = { 0 };<br>- char hn[MAXHOSTNAMELEN] = "";<br>- struct ast_hostent he;<br>- struct hostent *hp;<br>- struct sockaddr_in sin2;<br> static int last_port = 0;<br>+ int port=0;<br> int globalpcmodel = 0;<br> dundi_eid testeid;<br> <br>@@ -4831,25 +4873,14 @@<br> return -1;<br> }<br> <br>+ sin->ss.ss_family = AF_INET; /*set default protocol as IPV4 */<br>+<br> dundi_ttl = DUNDI_DEFAULT_TTL;<br> dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;<br> any_peer = NULL;<br> <br>- ipaddr[0] = '\0';<br>- if (!gethostname(hn, sizeof(hn)-1)) {<br>- hp = ast_gethostbyname(hn, &he);<br>- if (hp) {<br>- memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));<br>- ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));<br>- } else<br>- ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);<br>- } else<br>- ast_log(LOG_WARNING, "Unable to get host name!\n");<br> AST_LIST_LOCK(&peers);<br> <br>- if (ast_eid_is_empty(&ast_eid_default)) {<br>- ast_log(LOG_WARNING, "Entity ID is not set.\n");<br>- }<br> memcpy(&global_eid, &ast_eid_default, sizeof(global_eid));<br> <br> global_storehistory = 0;<br>@@ -4857,19 +4888,28 @@<br> v = ast_variable_browse(cfg, "general");<br> while(v) {<br> if (!strcasecmp(v->name, "port")){<br>- sin->sin_port = htons(atoi(v->value));<br>- if(last_port==0){<br>- last_port=sin->sin_port;<br>- } else if(sin->sin_port != last_port)<br>- ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");<br>+ port = atoi(v->value);<br> } else if (!strcasecmp(v->name, "bindaddr")) {<br>- struct hostent *hep;<br>- struct ast_hostent hent;<br>- hep = ast_gethostbyname(v->value, &hent);<br>- if (hep) {<br>- memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr));<br>- } else<br>- ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);<br>+ if( get_ai_family(v->value)== AF_INET6) {<br>+ struct in6_addr *ip6;<br>+ ip6 = &((struct sockaddr_in6*)&sin->ss)->sin6_addr;<br>+ if ( inet_pton(AF_INET6,v->value, ip6)< 0 ) {<br>+ ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);<br>+ }<br>+ sin->ss.ss_family = AF_INET6;<br>+ sin->len = sizeof(struct sockaddr_in6);<br>+ } else {<br>+ struct ast_hostent hent;<br>+ struct hostent *hep;<br>+ struct in_addr *ip4;<br>+ hep = ast_gethostbyname(v->value, &hent);<br>+ if (hep) {<br>+ ip4 = &((struct sockaddr_in*)&sin->ss)->sin_addr;<br>+ memcpy(ip4, hep->h_addr, sizeof(*ip4));<br>+ sin->len = sizeof(struct sockaddr_in);<br>+ } else<br>+ ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);<br>+ }<br> } else if (!strcasecmp(v->name, "authdebug")) {<br> authdebug = ast_true(v->value);<br> } else if (!strcasecmp(v->name, "ttl")) {<br>@@ -4924,6 +4964,17 @@<br> }<br> v = v->next;<br> }<br>+<br>+ if ( port == 0) {<br>+ ast_sockaddr_set_port(sin,DUNDI_PORT);<br>+ last_port = DUNDI_PORT;<br>+ } else {<br>+ if ( port != last_port) {<br>+ ast_sockaddr_set_port(sin,port);<br>+ last_port = port;<br>+ }<br>+ }<br>+<br> AST_LIST_UNLOCK(&peers);<br> mark_mappings();<br> v = ast_variable_browse(cfg, "mappings");<br>@@ -4938,9 +4989,9 @@<br> if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {<br> /* Entries */<br> if (!ast_str_to_eid(&testeid, cat))<br>- build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);<br>+ build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel,sin->ss.ss_family);<br> else if (!strcasecmp(cat, "*")) {<br>- build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel);<br>+ build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel,sin->ss.ss_family);<br> any_peer = find_peer(NULL);<br> } else<br> ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);<br>@@ -4994,7 +5045,7 @@<br> <br> static int reload(void)<br> {<br>- struct sockaddr_in sin;<br>+ struct ast_sockaddr sin;<br> <br> if (set_config("dundi.conf", &sin, 1))<br> return AST_MODULE_LOAD_FAILURE;<br>@@ -5004,44 +5055,48 @@<br> <br> static int load_module(void)<br> {<br>- struct sockaddr_in sin;<br>+ struct ast_sockaddr sin;<br> <br> dundi_set_output(dundi_debug_output);<br> dundi_set_error(dundi_error_output);<br>-<br>- sin.sin_family = AF_INET;<br>- sin.sin_port = htons(DUNDI_PORT);<br>- sin.sin_addr.s_addr = INADDR_ANY;<br> <br> /* Make a UDP socket */<br> io = io_context_create();<br> sched = ast_sched_context_create();<br> <br>- if (!io || !sched) {<br>- goto declined;<br>- }<br>+ if (!io || !sched)<br>+ return AST_MODULE_LOAD_DECLINE;<br> <br>- if (set_config("dundi.conf", &sin, 0)) {<br>- goto declined;<br>- }<br>+ memset(&sin,0,sizeof(struct ast_sockaddr));<br> <br>- netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);<br>+<br>+ if (set_config("dundi.conf", &sin, 0))<br>+ return AST_MODULE_LOAD_DECLINE;<br>+<br>+ if (sin.ss.ss_family == AF_INET6) {<br>+ netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);<br>+ }<br>+ else {<br>+ netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);<br>+ }<br> <br> if (netsocket < 0) {<br> ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));<br>- goto declined;<br>+ return AST_MODULE_LOAD_DECLINE;<br> }<br>- if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) {<br>- ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",<br>- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));<br>- goto declined;<br>+<br>+ if (ast_bind(netsocket, &sin)) {<br>+ ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",<br>+ ast_sockaddr_stringify(&sin), strerror(errno));<br>+ return AST_MODULE_LOAD_DECLINE;<br> }<br> <br> ast_set_qos(netsocket, tos, 0, "DUNDi");<br> <br> if (start_network_thread()) {<br> ast_log(LOG_ERROR, "Unable to start network thread\n");<br>- goto declined;<br>+ close(netsocket);<br>+ return AST_MODULE_LOAD_DECLINE;<br> }<br> <br> ast_cli_register_multiple(cli_dundi, ARRAY_LEN(cli_dundi));<br>@@ -5051,20 +5106,16 @@<br> ast_custom_function_register(&dundi_query_function);<br> ast_custom_function_register(&dundi_result_function);<br> <br>- ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));<br>+ ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin));<br> <br> return AST_MODULE_LOAD_SUCCESS;<br>-<br>-declined:<br>- unload_module();<br>- return AST_MODULE_LOAD_DECLINE;<br> }<br> <br> AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Distributed Universal Number Discovery (DUNDi)",<br>- .support_level = AST_MODULE_SUPPORT_EXTENDED,<br>- .load = load_module,<br>- .unload = unload_module,<br>- .reload = reload,<br>- .nonoptreq = "res_crypto",<br>-);<br>+ .support_level = AST_MODULE_SUPPORT_EXTENDED,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .reload = reload,<br>+ .nonoptreq = "res_crypto",<br>+ );<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/9150">change 9150</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/9150"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 14 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ia9e8dc3d153de7a291dbda4bd87fc827dd2bb846 </div>
<div style="display:none"> Gerrit-Change-Number: 9150 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Kirsty Tyerman <kirsty.tyerman@boeing.com> </div>