<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11437">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved; Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pbx_dundi: added IPv4/IPv6 dual bind support to DUNDi<br><br>ASTERISK-28234<br>Reported-by: Kirsty Tyerman<br><br>Change-Id: I5d6e6b52dbe51415046bb3953fd16f5b421bc2e1<br>---<br>M configs/samples/dundi.conf.sample<br>A doc/CHANGES-staging/pbx_dundi_ipv6.txt<br>M pbx/pbx_dundi.c<br>3 files changed, 114 insertions(+), 26 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/dundi.conf.sample b/configs/samples/dundi.conf.sample</span><br><span>index b97d3b2..3c67164 100644</span><br><span>--- a/configs/samples/dundi.conf.sample</span><br><span>+++ b/configs/samples/dundi.conf.sample</span><br><span>@@ -21,8 +21,10 @@</span><br><span> ;phone=+12565551212</span><br><span> ;</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; Specify bind address and port number.  Default is</span><br><span style="color: hsl(0, 100%, 40%);">-; 4520</span><br><span style="color: hsl(120, 100%, 40%);">+; Specify bind address. IPv6 addresses are accepted. Default is 0.0.0.0</span><br><span style="color: hsl(120, 100%, 40%);">+; You can specify 'bindaddr2' to bind to another address however</span><br><span style="color: hsl(120, 100%, 40%);">+; 'bindaddr and 'bindaddr2' need to be different IP protocols.</span><br><span style="color: hsl(120, 100%, 40%);">+; Specify port number. Default is 4520.</span><br><span> ;</span><br><span> ;bindaddr=0.0.0.0</span><br><span> ;port=4520</span><br><span>diff --git a/doc/CHANGES-staging/pbx_dundi_ipv6.txt b/doc/CHANGES-staging/pbx_dundi_ipv6.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..c15ae44</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/pbx_dundi_ipv6.txt</span><br><span>@@ -0,0 +1,3 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: pbx_dundi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The DUNDi PBX module now supports IPv4/IPv6 dual binding.</span><br><span>diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c</span><br><span>index ec150f3..6cc7711 100644</span><br><span>--- a/pbx/pbx_dundi.c</span><br><span>+++ b/pbx/pbx_dundi.c</span><br><span>@@ -183,7 +183,8 @@</span><br><span> </span><br><span> static struct io_context *io;</span><br><span> static struct ast_sched_context *sched;</span><br><span style="color: hsl(0, 100%, 40%);">-static int netsocket = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+static int netsocket = -1; /* Socket for bindaddr if only one bindaddr. Otherwise the IPv4 socket when bindaddr2 given. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int netsocket2 = -1; /* IPv6 socket when bindaddr2 given. */</span><br><span> static pthread_t netthreadid = AST_PTHREADT_NULL;</span><br><span> static pthread_t precachethreadid = AST_PTHREADT_NULL;</span><br><span> static pthread_t clearcachethreadid = AST_PTHREADT_NULL;</span><br><span>@@ -2079,14 +2080,14 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int socket_read(int *id, int fd, short events, void *cbdata)</span><br><span style="color: hsl(120, 100%, 40%);">+static int socket_read(int *id, int fd, short events, void *sock)</span><br><span> {</span><br><span>        struct ast_sockaddr sin;</span><br><span>     int res;</span><br><span>     struct dundi_hdr *h;</span><br><span>         char buf[MAX_PACKET_SIZE];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  res = ast_recvfrom(netsocket, buf, sizeof(buf), 0, &sin);</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ast_recvfrom(*((int *)sock), buf, sizeof(buf), 0, &sin);</span><br><span>   if (res < 0) {</span><br><span>            if (errno != ECONNREFUSED)</span><br><span>                   ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));</span><br><span>@@ -2196,7 +2197,11 @@</span><br><span>        from the network, and queue them for delivery to the channels */</span><br><span>  int res;</span><br><span>     /* Establish I/O callback for socket read */</span><br><span style="color: hsl(0, 100%, 40%);">-    int *socket_read_id = ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        int *socket_read_id = ast_io_add(io, netsocket, socket_read, AST_IO_IN, &netsocket);</span><br><span style="color: hsl(120, 100%, 40%);">+      int *socket_read_id2 = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (netsocket2 >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             socket_read_id2 = ast_io_add(io, netsocket2, socket_read, AST_IO_IN, &netsocket2);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span> </span><br><span>        while (!dundi_shutdown) {</span><br><span>            res = ast_sched_wait(sched);</span><br><span>@@ -2213,6 +2218,10 @@</span><br><span> </span><br><span>    ast_io_remove(io, socket_read_id);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        if (socket_read_id2) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_io_remove(io, socket_read_id2);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return NULL;</span><br><span> }</span><br><span> </span><br><span>@@ -3162,7 +3171,17 @@</span><br><span>       int res;</span><br><span>     if (dundidebug)</span><br><span>              dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));</span><br><span style="color: hsl(0, 100%, 40%);">-     res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (netsocket2 < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ast_sockaddr_is_ipv4(&pack->parent->addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      res = ast_sendto(netsocket2, pack->data, pack->datalen, 0, &pack->parent->addr);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (res < 0) {</span><br><span>            ast_log(LOG_WARNING, "Failed to transmit to '%s': %s\n",</span><br><span>                   ast_sockaddr_stringify(&pack->parent->addr), strerror(errno));</span><br><span>@@ -4916,7 +4935,7 @@</span><br><span>     get_ipaddress(ipaddr, sizeof(ipaddr), hn, family);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int set_config(char *config_file, struct ast_sockaddr *sin, int reload)</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)</span><br><span> {</span><br><span>    struct ast_config *cfg;</span><br><span>      struct ast_variable *v;</span><br><span>@@ -4927,7 +4946,8 @@</span><br><span>      int port = 0;</span><br><span>        int globalpcmodel = 0;</span><br><span>       dundi_eid testeid;</span><br><span style="color: hsl(0, 100%, 40%);">-      char bind_addr[80];</span><br><span style="color: hsl(120, 100%, 40%);">+   char bind_addr[80]={0,};</span><br><span style="color: hsl(120, 100%, 40%);">+      char bind_addr2[80]={0,};</span><br><span> </span><br><span>        if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {</span><br><span>               ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);</span><br><span>@@ -4957,6 +4977,12 @@</span><br><span>                                    ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);</span><br><span>                               }</span><br><span>                    }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (!strcasecmp(v->name, "bindaddr2")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (get_ipaddress(bind_addr2, sizeof(bind_addr2), v->value, AF_UNSPEC) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (!ast_sockaddr_parse(sin2, bind_addr2, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);</span><br><span style="color: hsl(120, 100%, 40%);">+                                }</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span>            } else if (!strcasecmp(v->name, "authdebug")) {</span><br><span>                         authdebug = ast_true(v->value);</span><br><span>           } else if (!strcasecmp(v->name, "ttl")) {</span><br><span>@@ -5031,6 +5057,10 @@</span><br><span> </span><br><span>  set_host_ipaddr(sin);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ast_sockaddr_isnull(sin2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_sockaddr_set_port(sin2, port);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  AST_LIST_UNLOCK(&peers);</span><br><span> </span><br><span>     mark_mappings();</span><br><span>@@ -5093,6 +5123,14 @@</span><br><span>            clearcachethreadid = AST_PTHREADT_NULL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (netsocket >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              close(netsocket);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (netsocket2 >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             close(netsocket2);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  mark_mappings();</span><br><span>     prune_mappings();</span><br><span>    mark_peers();</span><br><span>@@ -5118,10 +5156,12 @@</span><br><span> static int reload(void)</span><br><span> {</span><br><span>      struct ast_sockaddr sin;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_sockaddr sin2;</span><br><span> </span><br><span>        ast_sockaddr_setnull(&sin);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sockaddr_setnull(&sin2);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (set_config("dundi.conf", &sin, 1))</span><br><span style="color: hsl(120, 100%, 40%);">+  if (set_config("dundi.conf", &sin, 1, &sin2))</span><br><span>              return AST_MODULE_LOAD_FAILURE;</span><br><span> </span><br><span>  return AST_MODULE_LOAD_SUCCESS;</span><br><span>@@ -5130,6 +5170,7 @@</span><br><span> static int load_module(void)</span><br><span> {</span><br><span>         struct ast_sockaddr sin;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_sockaddr sin2;</span><br><span> </span><br><span>        dundi_set_output(dundi_debug_output);</span><br><span>        dundi_set_error(dundi_error_output);</span><br><span>@@ -5143,29 +5184,69 @@</span><br><span>       }</span><br><span> </span><br><span>        ast_sockaddr_setnull(&sin);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sockaddr_setnull(&sin2);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (set_config("dundi.conf", &sin, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (set_config("dundi.conf", &sin, 0, &sin2)) {</span><br><span>            goto declined;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_sockaddr_is_ipv6(&sin)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);</span><br><span style="color: hsl(0, 100%, 40%);">-   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ast_sockaddr_isnull(&sin2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if ((ast_sockaddr_is_ipv4(&sin) == ast_sockaddr_is_ipv4(&sin2)) || (ast_sockaddr_is_ipv6(&sin) == ast_sockaddr_is_ipv6(&sin2))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_log(LOG_ERROR, "bindaddr & bindaddr2 should be different IP protocols.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /*bind netsocket to ipv4, netsocket2 to ipv6 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>            netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);</span><br><span style="color: hsl(120, 100%, 40%);">+          netsocket2 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (netsocket < 0 || netsocket2 < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                       goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ast_sockaddr_is_ipv4(&sin)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (ast_bind(netsocket, &sin)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_sockaddr_stringify(&sin), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                           goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (ast_bind(netsocket2, &sin2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_sockaddr_stringify(&sin2), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                          goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (ast_bind(netsocket, &sin2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_sockaddr_stringify(&sin2), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                          goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (ast_bind(netsocket2, &sin)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                   ast_sockaddr_stringify(&sin), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                           goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_set_qos(netsocket, tos, 0, "DUNDi");</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_set_qos(netsocket2, tos, 0, "DUNDi");</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ast_sockaddr_is_ipv6(&sin)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);</span><br><span style="color: hsl(120, 100%, 40%);">+         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (netsocket < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                       goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ast_bind(netsocket, &sin))  {</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_sockaddr_stringify(&sin), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto declined;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_set_qos(netsocket, tos, 0, "DUNDi");</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (netsocket < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">-         goto declined;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_bind(netsocket, &sin))  {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                     ast_sockaddr_stringify(&sin), strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">-             goto declined;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_set_qos(netsocket, tos, 0, "DUNDi");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>   if (start_network_thread()) {</span><br><span>                ast_log(LOG_ERROR, "Unable to start network thread\n");</span><br><span>            goto declined;</span><br><span>@@ -5179,6 +5260,8 @@</span><br><span>       ast_custom_function_register(&dundi_result_function);</span><br><span> </span><br><span>        ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_sockaddr_isnull(&sin2))</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin2));</span><br><span> </span><br><span>   return AST_MODULE_LOAD_SUCCESS;</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11437">change 11437</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/11437"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I5d6e6b52dbe51415046bb3953fd16f5b421bc2e1 </div>
<div style="display:none"> Gerrit-Change-Number: 11437 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kirsty Tyerman <kirsty.tyerman@boeing.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>