<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>