aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-08 22:08:07 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-08 22:08:07 +0000
commitc3c2e5edfd715b3a99aac1567623a0b1b7d49de0 (patch)
treec05335b563c3f7cb9a3edbf3e101d8e1b80e0be4
parentaf344f1a5be5b43f1d10b95ea6e57ebfa761cf50 (diff)
Add IPv6 to Asterisk.
This adds a generic API for accommodating IPv6 and IPv4 addresses within Asterisk. While many files have been updated to make use of the API, chan_sip and the RTP code are the files which actually support IPv6 addresses at the time of this commit. The way has been paved for easier upgrading for other files in the near future, though. Big thanks go to Simon Perrault, Marc Blanchet, and Jean-Philippe Dionne for their hard work on this. (closes issue #17565) Reported by: russell Patches: asteriskv6-test-report.pdf uploaded by russell (license 2) Review: https://reviewboard.asterisk.org/r/743 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@274783 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--CHANGES2
-rw-r--r--addons/chan_ooh323.c20
-rw-r--r--apps/app_externalivr.c8
-rw-r--r--channels/chan_gtalk.c35
-rw-r--r--channels/chan_h323.c63
-rw-r--r--channels/chan_iax2.c30
-rw-r--r--channels/chan_jingle.c25
-rw-r--r--channels/chan_mgcp.c73
-rw-r--r--channels/chan_multicast_rtp.c9
-rw-r--r--channels/chan_sip.c1858
-rw-r--r--channels/chan_skinny.c28
-rw-r--r--channels/chan_unistim.c12
-rw-r--r--channels/sip/dialplan_functions.c31
-rw-r--r--channels/sip/include/dialog.h2
-rw-r--r--channels/sip/include/globals.h2
-rw-r--r--channels/sip/include/reqresp_parser.h14
-rw-r--r--channels/sip/include/sip.h27
-rw-r--r--channels/sip/reqresp_parser.c244
-rw-r--r--configs/sip.conf.sample4
-rw-r--r--include/asterisk/acl.h16
-rw-r--r--include/asterisk/config.h10
-rw-r--r--include/asterisk/dnsmgr.h10
-rw-r--r--include/asterisk/netsock2.h523
-rw-r--r--include/asterisk/rtp_engine.h46
-rw-r--r--include/asterisk/tcptls.h9
-rw-r--r--main/acl.c101
-rw-r--r--main/app.c10
-rw-r--r--main/config.c16
-rw-r--r--main/dnsmgr.c43
-rw-r--r--main/http.c55
-rw-r--r--main/manager.c91
-rw-r--r--main/netsock2.c499
-rw-r--r--main/rtp_engine.c155
-rw-r--r--main/tcptls.c58
-rw-r--r--res/res_rtp_asterisk.c448
-rw-r--r--res/res_rtp_multicast.c34
36 files changed, 3043 insertions, 1568 deletions
diff --git a/CHANGES b/CHANGES
index c46d4c7e4..387ac7c54 100644
--- a/CHANGES
+++ b/CHANGES
@@ -69,6 +69,8 @@ SIP Changes
Charge messages to snom phones.
* Added support for G.719 media streams.
* Added support for 16khz signed linear media streams.
+ * SIP is now able to bind to and communicate with IPv6 addresses. In addition,
+ RTP has been outfitted with the same abilities.
IAX2 Changes
-----------
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 0024b596c..f088e9c58 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -460,6 +460,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
{
struct ooh323_pvt *pvt = NULL;
struct sockaddr_in ouraddr;
+ struct ast_sockaddr tmp;
struct in_addr ipAddr;
if (gH323Debug)
ast_verbose("--- ooh323_alloc\n");
@@ -481,8 +482,10 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
return NULL;
}
+ ouraddr.sin_family = AF_INET;
ouraddr.sin_addr = ipAddr;
- if (!(pvt->rtp = ast_rtp_instance_new("asterisk", sched, &ouraddr, NULL))) {
+ tmp = ast_sockaddr_from_sin(ouraddr);
+ if (!(pvt->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
ast_log(LOG_WARNING, "Unable to create RTP session: %s\n",
strerror(errno));
ast_mutex_unlock(&pvt->lock);
@@ -3803,6 +3806,7 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
struct ooh323_pvt *p;
struct sockaddr_in them;
struct sockaddr_in us;
+ struct ast_sockaddr tmp;
int mode;
if (gH323Debug)
@@ -3818,8 +3822,10 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
return -1;
}
- ast_rtp_instance_get_remote_address(rtp, &them);
- ast_rtp_instance_get_local_address(rtp, &us);
+ ast_rtp_instance_get_remote_address(rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &them);
+ ast_rtp_instance_get_local_address(rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &us);
return 0;
}
@@ -3829,6 +3835,7 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
{
struct sockaddr_in us;
+ struct ast_sockaddr tmp;
ooMediaInfo mediaInfo;
int x;
format_t format = 0;
@@ -3849,7 +3856,8 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
}
/* figure out our local RTP port and tell the H.323 stack about it*/
- ast_rtp_instance_get_local_address(p->rtp, &us);
+ ast_rtp_instance_get_local_address(p->rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &us);
if (p->rtptimeout) {
ast_rtp_instance_set_timeout(p->rtp, p->rtptimeout);
@@ -3913,6 +3921,7 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp,
{
struct ooh323_pvt *p = NULL;
struct sockaddr_in them;
+ struct ast_sockaddr tmp;
if (gH323Debug)
ast_verbose("--- setup_rtp_connection %s:%d\n", remoteIp, remotePort);
@@ -3928,7 +3937,8 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp,
them.sin_family = AF_INET;
them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
them.sin_port = htons(remotePort);
- ast_rtp_instance_set_remote_address(p->rtp, &them);
+ tmp = ast_sockaddr_from_sin(&them);
+ ast_rtp_instance_set_remote_address(p->rtp, &tmp);
if (p->writeformat & AST_FORMAT_G726_AAL2)
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c
index 5e33cdd3d..919815d73 100644
--- a/apps/app_externalivr.c
+++ b/apps/app_externalivr.c
@@ -492,6 +492,7 @@ static int app_exec(struct ast_channel *chan, const char *data)
.name = "IVR",
};
struct ast_hostent hp;
+ struct sockaddr_in remote_address_tmp;
/*communicate through socket to server*/
ast_debug(1, "Parsing hostname:port for socket connect from \"%s\"\n", app_args[0]);
@@ -506,9 +507,10 @@ static int app_exec(struct ast_channel *chan, const char *data)
}
ast_gethostbyname(hostname, &hp);
- ivr_desc.remote_address.sin_family = AF_INET;
- ivr_desc.remote_address.sin_port = htons(port);
- memcpy(&ivr_desc.remote_address.sin_addr.s_addr, hp.hp.h_addr, sizeof(hp.hp.h_addr));
+ remote_address_tmp.sin_family = AF_INET;
+ remote_address_tmp.sin_port = htons(port);
+ memcpy(&remote_address_tmp.sin_addr.s_addr, hp.hp.h_addr, sizeof(hp.hp.h_addr));
+ ast_sockaddr_from_sin(&ivr_desc.remote_address, &remote_address_tmp);
if (!(ser = ast_tcptls_client_create(&ivr_desc)) || !(ser = ast_tcptls_client_start(ser))) {
goto exit;
}
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index 252e3fe20..1a964e75a 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -774,8 +774,10 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch
struct aji_client *c = client->connection;
struct gtalk_candidate *ours1 = NULL, *ours2 = NULL;
struct sockaddr_in sin = { 0, };
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr bindaddr_tmp;
struct sockaddr_in dest;
- struct in_addr us;
+ struct ast_sockaddr us;
iks *iq, *gtalk, *candidate, *transport;
char user[17], pass[17], preference[5], port[7];
char *lowerfrom = NULL;
@@ -809,9 +811,11 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch
goto safeout;
}
- ast_rtp_instance_get_local_address(p->rtp, &sin);
- ast_find_ourip(&us, bindaddr);
- if (!strcmp(ast_inet_ntoa(us), "127.0.0.1")) {
+ ast_rtp_instance_get_local_address(p->rtp, &sin_tmp);
+ ast_sockaddr_to_sin(&sin_tmp, &sin);
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ ast_find_ourip(&us, &bindaddr_tmp);
+ if (!strcmp(ast_sockaddr_stringify_addr(&us), "127.0.0.1")) {
ast_log(LOG_WARNING, "Found a loopback IP on the system, check your network configuration or set the bindaddr attribute.");
}
@@ -823,7 +827,8 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch
snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(ours1->username, user, sizeof(ours1->username));
ast_copy_string(ours1->password, pass, sizeof(ours1->password));
- ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
+ ast_copy_string(ours1->ip, ast_sockaddr_stringify_addr(&us),
+ sizeof(ours1->ip));
ours1->protocol = AJI_PROTOCOL_UDP;
ours1->type = AJI_CONNECT_LOCAL;
ours1->generation = 0;
@@ -911,6 +916,7 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const
struct aji_buddy *buddy;
char idroster[200];
char *data, *exten = NULL;
+ struct ast_sockaddr bindaddr_tmp;
ast_debug(1, "The client is %s for alloc\n", client->name);
if (!sid && !strchr(them, '/')) { /* I started call! */
@@ -950,7 +956,8 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const
tmp->initiator = 1;
}
/* clear codecs */
- if (!(tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL))) {
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ if (!(tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL))) {
ast_log(LOG_ERROR, "Failed to create a new RTP instance (possibly an invalid bindaddr?)\n");
ast_free(tmp);
return NULL;
@@ -1263,6 +1270,8 @@ static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p)
struct ast_hostent ahp;
struct sockaddr_in sin = { 0, };
struct sockaddr_in aux = { 0, };
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr aux_tmp;
if (time(NULL) == p->laststun)
return 0;
@@ -1281,16 +1290,17 @@ static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p)
p->ourcandidates->username);
/* Find out the result of the STUN */
- ast_rtp_instance_get_remote_address(p->rtp, &aux);
+ ast_rtp_instance_get_remote_address(p->rtp, &aux_tmp);
+ ast_sockaddr_to_sin(&aux_tmp, &aux);
/* If the STUN result is different from the IP of the hostname,
lock on the stun IP of the hostname advertised by the
remote client */
if (aux.sin_addr.s_addr &&
aux.sin_addr.s_addr != sin.sin_addr.s_addr)
- ast_rtp_instance_stun_request(p->rtp, &aux, username);
+ ast_rtp_instance_stun_request(p->rtp, &aux_tmp, username);
else
- ast_rtp_instance_stun_request(p->rtp, &sin, username);
+ ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
if (aux.sin_addr.s_addr) {
ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
@@ -2057,6 +2067,9 @@ static int gtalk_load_config(void)
/*! \brief Load module into PBX, register channel */
static int load_module(void)
{
+ struct ast_sockaddr bindaddr_tmp;
+ struct ast_sockaddr ourip_tmp;
+
char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
free(jabber_loaded);
if (!jabber_loaded) {
@@ -2083,10 +2096,12 @@ static int load_module(void)
if (!io)
ast_log(LOG_WARNING, "Unable to create I/O context\n");
- if (ast_find_ourip(&__ourip, bindaddr)) {
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp)) {
ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n");
return 0;
}
+ __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
ast_rtp_glue_register(&gtalk_rtp_glue);
ast_cli_register_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 10234199a..cf41acc69 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -954,15 +954,20 @@ static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static int __oh323_rtp_create(struct oh323_pvt *pvt)
{
- struct sockaddr_in our_addr;
+ struct ast_sockaddr our_addr;
if (pvt->rtp)
return 0;
- if (ast_find_ourip(&our_addr.sin_addr, bindaddr)) {
- ast_mutex_unlock(&pvt->lock);
- ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
- return -1;
+ {
+ struct ast_sockaddr tmp;
+
+ tmp = ast_sockaddr_from_sin(bindaddr);
+ if (ast_find_ourip(&our_addr, &tmp)) {
+ ast_mutex_unlock(&pvt->lock);
+ ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
+ return -1;
+ }
}
pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
if (!pvt->rtp) {
@@ -1408,9 +1413,14 @@ static struct oh323_user *build_user(const char *name, struct ast_variable *v, s
ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
ASTOBJ_UNREF(user, oh323_destroy_user);
return NULL;
- } else if (ast_get_ip(&user->addr, v->value)) {
- ASTOBJ_UNREF(user, oh323_destroy_user);
- return NULL;
+ } else {
+ struct ast_sockaddr tmp;
+
+ if (ast_get_ip(&tmp, v->value)) {
+ ASTOBJ_UNREF(user, oh323_destroy_user);
+ return NULL;
+ }
+ ast_sockaddr_to_sin(&tmp, &user->addr);
}
/* Let us know we need to use ip authentication */
user->host = 1;
@@ -1522,10 +1532,15 @@ static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, s
ASTOBJ_UNREF(peer, oh323_destroy_peer);
return NULL;
}
- if (ast_get_ip(&peer->addr, v->value)) {
- ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
- ASTOBJ_UNREF(peer, oh323_destroy_peer);
- return NULL;
+ {
+ struct ast_sockaddr tmp;
+
+ if (ast_get_ip(&tmp, v->value)) {
+ ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
+ ASTOBJ_UNREF(peer, oh323_destroy_peer);
+ return NULL;
+ }
+ ast_sockaddr_to_sin(&tmp, &peer->addr);
}
} else if (!strcasecmp(v->name, "port")) {
peer->addr.sin_port = htons(atoi(v->value));
@@ -1922,7 +1937,12 @@ static struct rtp_info *external_rtp_create(unsigned call_reference, const char
return NULL;
}
/* figure out our local RTP port and tell the H.323 stack about it */
- ast_rtp_instance_get_local_address(pvt->rtp, &us);
+ {
+ struct ast_sockaddr tmp;
+
+ ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &us);
+ }
ast_mutex_unlock(&pvt->lock);
ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
@@ -1971,7 +1991,12 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp,
them.sin_port = htons(remotePort);
if (them.sin_addr.s_addr) {
- ast_rtp_instance_set_remote_address(pvt->rtp, &them);
+ {
+ struct ast_sockaddr tmp;
+
+ tmp = ast_sockaddr_from_sin(them);
+ ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
+ }
if (pvt->recvonly) {
pvt->recvonly = 0;
rtp_change = NEED_UNHOLD;
@@ -3204,8 +3229,14 @@ static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
return -1;
}
- ast_rtp_instance_get_remote_address(rtp, &them);
- ast_rtp_instance_get_local_address(rtp, &us);
+ {
+ struct ast_sockaddr tmp;
+
+ ast_rtp_instance_get_remote_address(rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &them);
+ ast_rtp_instance_get_local_address(rtp, &tmp);
+ ast_sockaddr_to_sin(&tmp, &us);
+ }
#if 0 /* Native bridge still isn't ready */
h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
#endif
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index ba482a065..7880e719d 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -4441,11 +4441,15 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka
sin->sin_family = AF_INET;
if (!(peer = find_peer(peername, 1))) {
+ struct ast_sockaddr sin_tmp;
+
cai->found = 0;
- if (ast_get_ip_or_srv(sin, peername, srvlookup ? "_iax._udp" : NULL)) {
+ sin_tmp.ss.ss_family = AF_INET;
+ if (ast_get_ip_or_srv(&sin_tmp, peername, srvlookup ? "_iax._udp" : NULL)) {
ast_log(LOG_WARNING, "No such host: %s\n", peername);
return -1;
}
+ ast_sockaddr_to_sin(&sin_tmp, sin);
sin->sin_port = htons(IAX_DEFAULT_PORTNO);
/* use global iax prefs for unknown peer/user */
/* But move the calling channel's native codec to the top of the preference list */
@@ -8312,14 +8316,18 @@ static int iax2_append_register(const char *hostname, const char *username,
const char *secret, const char *porta)
{
struct iax2_registry *reg;
+ struct ast_sockaddr reg_addr_tmp;
if (!(reg = ast_calloc(1, sizeof(*reg))))
return -1;
- if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
+ reg->addr.sin_family = AF_INET;
+ ast_sockaddr_from_sin(&reg_addr_tmp, &reg->addr);
+ if (ast_dnsmgr_lookup(hostname, &reg_addr_tmp, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
ast_free(reg);
return -1;
}
+ ast_sockaddr_to_sin(&reg_addr_tmp, &reg->addr);
ast_copy_string(reg->username, username, sizeof(reg->username));
@@ -11991,6 +11999,7 @@ static int check_srcaddr(struct sockaddr *sa, socklen_t salen)
static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr)
{
struct sockaddr_in sin;
+ struct ast_sockaddr sin_tmp;
int nonlocal = 1;
int port = IAX_DEFAULT_PORTNO;
int sockfd = defaultsockfd;
@@ -12010,10 +12019,11 @@ static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr)
port = IAX_DEFAULT_PORTNO;
}
- if (!ast_get_ip(&sin, addr)) {
+ if (!ast_get_ip(&sin_tmp, addr)) {
struct ast_netsock *sock;
int res;
+ ast_sockaddr_to_sin(&sin_tmp, &sin);
sin.sin_port = 0;
sin.sin_family = AF_INET;
res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
@@ -12212,19 +12222,29 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
}
}
} else {
+ struct ast_sockaddr peer_addr_tmp;
+
/* Non-dynamic. Make sure we become that way if we're not */
ast_sched_thread_del(sched, peer->expire);
ast_clear_flag64(peer, IAX_DYNAMIC);
- if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
+ peer_addr_tmp.ss.ss_family = AF_INET;
+ if (ast_dnsmgr_lookup(v->value, &peer_addr_tmp, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
return peer_unref(peer);
+ ast_sockaddr_to_sin(&peer_addr_tmp,
+ &peer->addr);
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
}
if (!maskfound)
inet_aton("255.255.255.255", &peer->mask);
} else if (!strcasecmp(v->name, "defaultip")) {
- if (ast_get_ip(&peer->defaddr, v->value))
+ struct ast_sockaddr peer_defaddr_tmp;
+
+ if (ast_get_ip(&peer_defaddr_tmp, v->value)) {
return peer_unref(peer);
+ }
+ ast_sockaddr_to_sin(&peer_defaddr_tmp,
+ &peer->defaddr);
} else if (!strcasecmp(v->name, "sourceaddress")) {
peer_set_srcaddr(peer, v->value);
} else if (!strcasecmp(v->name, "permit") ||
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index b876dfd0d..35618b1fa 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -581,6 +581,9 @@ static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p,
struct aji_client *c = client->connection;
struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
struct sockaddr_in sin = { 0, };
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr us_tmp;
+ struct ast_sockaddr bindaddr_tmp;
struct sockaddr_in dest;
struct in_addr us;
struct in_addr externaddr;
@@ -617,8 +620,11 @@ static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p,
goto safeout;
}
- ast_rtp_instance_get_local_address(p->rtp, &sin);
- ast_find_ourip(&us, bindaddr);
+ ast_rtp_instance_get_local_address(p->rtp, &sin_tmp);
+ ast_sockaddr_to_sin(&sin_tmp, &sin);
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ ast_find_ourip(&us_tmp, &bindaddr_tmp);
+ us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp));
/* Setup our first jingle candidate */
ours1->component = 1;
@@ -739,6 +745,7 @@ static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from,
struct aji_resource *resources = NULL;
struct aji_buddy *buddy;
char idroster[200];
+ struct ast_sockaddr bindaddr_tmp;
ast_debug(1, "The client is %s for alloc\n", client->name);
if (!sid && !strchr(from, '/')) { /* I started call! */
@@ -775,7 +782,8 @@ static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from,
ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
tmp->initiator = 1;
}
- tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
tmp->parent = client;
if (!tmp->rtp) {
ast_log(LOG_WARNING, "Out of RTP sessions?\n");
@@ -1061,6 +1069,7 @@ static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
struct hostent *hp;
struct ast_hostent ahp;
struct sockaddr_in sin;
+ struct ast_sockaddr sin_tmp;
if (time(NULL) == p->laststun)
return 0;
@@ -1075,7 +1084,8 @@ static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
sin.sin_port = htons(tmp->port);
snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
- ast_rtp_instance_stun_request(p->rtp, &sin, username);
+ sin_tmp = ast_sockaddr_from_sin(sin);
+ ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
tmp = tmp->next;
}
return 1;
@@ -1867,6 +1877,9 @@ static int jingle_load_config(void)
/*! \brief Load module into PBX, register channel */
static int load_module(void)
{
+ struct ast_sockaddr ourip_tmp;
+ struct ast_sockaddr bindaddr_tmp;
+
char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
free(jabber_loaded);
if (!jabber_loaded) {
@@ -1893,10 +1906,12 @@ static int load_module(void)
if (!io)
ast_log(LOG_WARNING, "Unable to create I/O context\n");
- if (ast_find_ourip(&__ourip, bindaddr)) {
+ bindaddr_tmp = ast_sockaddr_from_sin(bindaddr);
+ if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp)) {
ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
return 0;
}
+ __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
ast_rtp_glue_register(&jingle_rtp_glue);
ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 420bc51a8..63dcb936d 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -1769,8 +1769,19 @@ static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, s
if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
(g->addr.sin_port != sin->sin_port)) {
memcpy(&g->addr, sin, sizeof(g->addr));
- if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
- memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
+ {
+ struct ast_sockaddr tmp1, tmp2;
+ struct sockaddr_in tmp3 = {0,};
+
+ tmp3.sin_addr = g->ourip;
+ ast_sockaddr_from_sin(&tmp1, &g->addr);
+ ast_sockaddr_from_sin(&tmp2, &tmp3);
+ if (ast_ouraddrfor(&tmp1, &tmp2)) {
+ memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
+ }
+ ast_sockaddr_to_sin(&tmp2, &tmp3);
+ g->ourip = tmp3.sin_addr;
+ }
ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
}
/* not dynamic, check if the name matches */
@@ -1934,6 +1945,7 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
format_t peercapability;
int peerNonCodecCapability;
struct sockaddr_in sin;
+ struct ast_sockaddr sin_tmp;
char *codecs;
struct ast_hostent ahp; struct hostent *hp;
int codec, codec_count=0;
@@ -1965,7 +1977,8 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
sin.sin_port = htons(portno);
- ast_rtp_instance_set_remote_address(sub->rtp, &sin);
+ ast_sockaddr_from_sin(&sin_tmp, &sin);
+ ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
/* Scan through the RTP payload types specified in a "m=" line: */
ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
@@ -2148,6 +2161,7 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
int codec;
char costr[80];
struct sockaddr_in sin;
+ struct ast_sockaddr sin_tmp;
char v[256];
char s[256];
char o[256];
@@ -2157,6 +2171,7 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
char a[1024] = "";
format_t x;
struct sockaddr_in dest = { 0, };
+ struct ast_sockaddr dest_tmp;
struct mgcp_endpoint *p = sub->parent;
/* XXX We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us XXX */
@@ -2165,9 +2180,11 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
return -1;
}
- ast_rtp_instance_get_local_address(sub->rtp, &sin);
+ ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
+ ast_sockaddr_to_sin(&sin_tmp, &sin);
if (rtp) {
- ast_rtp_instance_get_remote_address(sub->rtp, &dest);
+ ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
+ ast_sockaddr_to_sin(&dest_tmp, &dest);
} else {
if (sub->tmpdest.sin_addr.s_addr) {
dest.sin_addr = sub->tmpdest.sin_addr;
@@ -2240,11 +2257,13 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_
char tmp[80];
struct mgcp_endpoint *p = sub->parent;
format_t x;
+ struct ast_sockaddr sub_tmpdest_tmp;
if (ast_strlen_zero(sub->cxident) && rtp) {
/* We don't have a CXident yet, store the destination and
wait a bit */
- ast_rtp_instance_get_remote_address(rtp, &sub->tmpdest);
+ ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
+ ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
return 0;
}
ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
@@ -2876,6 +2895,8 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
static void start_rtp(struct mgcp_subchannel *sub)
{
+ struct ast_sockaddr bindaddr_tmp;
+
ast_mutex_lock(&sub->lock);
/* check again to be on the safe side */
if (sub->rtp) {
@@ -2883,7 +2904,8 @@ static void start_rtp(struct mgcp_subchannel *sub)
sub->rtp = NULL;
}
/* Allocate the RTP now */
- sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+ ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
+ sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
if (sub->rtp && sub->owner)
ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
if (sub->rtp) {
@@ -3967,22 +3989,32 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
/* Non-dynamic. Make sure we become that way if we're not */
AST_SCHED_DEL(sched, gw->expire);
gw->dynamic = 0;
- if (ast_get_ip(&gw->addr, v->value)) {
- if (!gw_reload) {
- ast_mutex_destroy(&gw->msgs_lock);
- ast_free(gw);
+ {
+ struct ast_sockaddr tmp;
+
+ ast_sockaddr_from_sin(&tmp, &gw->addr);
+ if (ast_get_ip(&tmp, v->value)) {
+ if (!gw_reload) {
+ ast_mutex_destroy(&gw->msgs_lock);
+ ast_free(gw);
+ }
+ return NULL;
}
- return NULL;
+ ast_sockaddr_to_sin(&tmp, &gw->addr);
}
}
} else if (!strcasecmp(v->name, "defaultip")) {
- if (ast_get_ip(&gw->defaddr, v->value)) {
+ struct ast_sockaddr tmp;
+
+ ast_sockaddr_from_sin(&tmp, &gw->defaddr);
+ if (ast_get_ip(&tmp, v->value)) {
if (!gw_reload) {
ast_mutex_destroy(&gw->msgs_lock);
ast_free(gw);
}
return NULL;
}
+ ast_sockaddr_to_sin(&tmp, &gw->defaddr);
} else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) {
gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
@@ -4325,8 +4357,19 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
}
- if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) {
- memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
+ {
+ struct ast_sockaddr tmp1, tmp2;
+ struct sockaddr_in tmp3 = {0,};
+
+ tmp3.sin_addr = gw->ourip;
+ ast_sockaddr_from_sin(&tmp1, &gw->addr);
+ ast_sockaddr_from_sin(&tmp2, &tmp3);
+ if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
+ memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
+ } else {
+ ast_sockaddr_to_sin(&tmp2, &tmp3);
+ gw->ourip = tmp3.sin_addr;
+ }
}
}
diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c
index 24c073215..f385d4467 100644
--- a/channels/chan_multicast_rtp.c
+++ b/channels/chan_multicast_rtp.c
@@ -111,7 +111,8 @@ static struct ast_channel *multicast_rtp_request(const char *type, format_t form
{
char *tmp = ast_strdupa(data), *multicast_type = tmp, *destination, *control;
struct ast_rtp_instance *instance;
- struct sockaddr_in control_address = { .sin_family = AF_INET, }, destination_address = { .sin_family = AF_INET, };
+ struct ast_sockaddr control_address;
+ struct ast_sockaddr destination_address;
struct ast_channel *chan;
format_t fmt = ast_best_codec(format);
@@ -125,13 +126,15 @@ static struct ast_channel *multicast_rtp_request(const char *type, format_t form
}
*destination++ = '\0';
- if (ast_parse_arg(destination, PARSE_INADDR | PARSE_PORT_REQUIRE, &destination_address)) {
+ if (!ast_sockaddr_parse(&destination_address, destination,
+ PARSE_PORT_REQUIRE)) {
goto failure;
}
if ((control = strchr(destination, '/'))) {
*control++ = '\0';
- if (ast_parse_arg(control, PARSE_INADDR | PARSE_PORT_REQUIRE, &control_address)) {
+ if (!ast_sockaddr_parse(&control_address, control,
+ PARSE_PORT_REQUIRE)) {
goto failure;
}
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index c65d85b9f..d0c131f13 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -252,7 +252,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
-#include "asterisk/netsock.h"
+#include "asterisk/netsock2.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.h"
@@ -1117,7 +1117,7 @@ static struct sip_auth *authl = NULL;
*/
static int sipsock = -1;
-struct sockaddr_in bindaddr; /*!< UDP: The address we bind to */
+struct ast_sockaddr bindaddr; /*!< UDP: The address we bind to */
/*! \brief our (internal) default address/port to put in SIP/SDP messages
* internip is initialized picking a suitable address from one of the
@@ -1125,7 +1125,7 @@ struct sockaddr_in bindaddr; /*!< UDP: The address we bind to */
* default address/port in SIP messages, and as the default address
* (but not port) in SDP messages.
*/
-static struct sockaddr_in internip;
+static struct ast_sockaddr internip;
/*! \brief our external IP address/port for SIP sessions.
* externip.sin_addr is only set when we know we might be behind
@@ -1145,8 +1145,8 @@ static struct sockaddr_in internip;
* Other variables (externhost, externexpire, externrefresh) are used
* to support the above functions.
*/
-static struct sockaddr_in externip; /*!< External IP address if we are behind NAT */
-static struct sockaddr_in media_address; /*!< External RTP IP address if we are behind NAT */
+static struct ast_sockaddr externip; /*!< External IP address if we are behind NAT */
+static struct ast_sockaddr media_address; /*!< External RTP IP address if we are behind NAT */
static char externhost[MAXHOSTNAMELEN]; /*!< External host name */
static time_t externexpire; /*!< Expiration counter for re-resolving external host name in dynamic DNS */
@@ -1165,7 +1165,7 @@ static struct ast_ha *localaddr; /*!< List of local networks, on the same sid
static int ourport_tcp; /*!< The port used for TCP connections */
static int ourport_tls; /*!< The port used for TCP/TLS connections */
-static struct sockaddr_in debugaddr;
+static struct ast_sockaddr debugaddr;
static struct ast_config *notify_types = NULL; /*!< The list of manual NOTIFY types we know how to send */
@@ -1201,9 +1201,10 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d
static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
static const char *sip_get_callid(struct ast_channel *chan);
-static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin);
+static int handle_request_do(struct sip_request *req, struct ast_sockaddr *addr);
static int sip_standard_port(enum sip_transport type, int port);
static int sip_prepare_socket(struct sip_pvt *p);
+static int get_address_family_filter(const struct ast_sockaddr *addr);
/*--- Transmitting responses and requests */
static int sipsock_read(int *id, int fd, short events, void *ignore);
@@ -1212,7 +1213,7 @@ static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, struct as
static void add_cc_call_info_to_response(struct sip_pvt *p, struct sip_request *resp);
static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
static int retrans_pkt(const void *data);
-static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
+static int transmit_response_using_temp(ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
@@ -1248,11 +1249,11 @@ static int __sip_autodestruct(const void *data);
static void *registry_unref(struct sip_registry *reg, char *tag);
static int update_call_counter(struct sip_pvt *fup, int event);
static int auto_congest(const void *arg);
-static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method);
+static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method);
static void free_old_route(struct sip_route *route);
static void list_route(struct sip_route *route);
static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards);
-static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
+static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
struct sip_request *req, const char *uri);
static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
static void check_pendings(struct sip_pvt *p);
@@ -1268,7 +1269,7 @@ static char get_sdp_line(int *start, int stop, struct sip_request *req, const ch
static int find_sdp(struct sip_request *req);
static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action);
static int process_sdp_o(const char *o, struct sip_pvt *p);
-static int process_sdp_c(const char *c, struct ast_hostent *hp);
+static int process_sdp_c(const char *c, struct ast_sockaddr *addr);
static int process_sdp_a_sendonly(const char *a, int *sendonly);
static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec);
static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
@@ -1292,8 +1293,8 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
const char *uri, enum xmittype reliable, int ignore);
static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
int sipmethod, const char *uri, enum xmittype reliable,
- struct sockaddr_in *sin, struct sip_peer **authpeer);
-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct sockaddr_in *sin);
+ struct ast_sockaddr *addr, struct sip_peer **authpeer);
+static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr);
/*--- Domain handling */
static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
@@ -1375,13 +1376,17 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data);
static int sip_addheader(struct ast_channel *chan, const char *data);
static int sip_do_reload(enum channelreloadreason reason);
static char *sip_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr,
+ const char *name, int flag, int family);
+static int ast_sockaddr_resolve_first(struct ast_sockaddr *addr,
+ const char *name, int flag);
/*--- Debugging
Functions for enabling debug per IP or fully, or enabling history logging for
a SIP dialog
*/
static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to debuglog at end of dialog, before destroying data */
-static inline int sip_debug_test_addr(const struct sockaddr_in *addr);
+static inline int sip_debug_test_addr(const struct ast_sockaddr *addr);
static inline int sip_debug_test_pvt(struct sip_pvt *p);
static void append_history_full(struct sip_pvt *p, const char *fmt, ...);
static void sip_dump_history(struct sip_pvt *dialog);
@@ -1394,7 +1399,7 @@ static void sip_destroy_peer_fn(void *peer);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only, int transport);
+static struct sip_peer *find_peer(const char *peer, struct ast_sockaddr *addr, int realtime, int forcenamematch, int devstate_only, int transport);
static int sip_poke_peer_s(const void *data);
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
static void reg_source_db(struct sip_peer *peer);
@@ -1404,15 +1409,15 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
static void set_socket_transport(struct sip_socket *socket, int transport);
/* Realtime device support */
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms);
+static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *username, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms);
static void update_peer(struct sip_peer *p, int expire);
static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config);
static const char *get_name_from_variable(struct ast_variable *var, const char *newpeername);
-static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin, int devstate_only);
+static struct sip_peer *realtime_peer(const char *peername, struct ast_sockaddr *sin, int devstate_only);
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
/*--- Internal UA client handling (outbound registrations) */
-static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, struct sip_pvt *p);
+static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p);
static void sip_registry_destroy(struct sip_registry *reg);
static int sip_register(const char *value, int lineno);
static const char *regstate2str(enum sipregistrystate regstate) attribute_const;
@@ -1469,13 +1474,13 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
static int init_resp(struct sip_request *resp, const char *msg);
static inline int resp_needs_contact(const char *msg, enum sipmethod method);
static int respprep(struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req);
-static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p);
+static const struct ast_sockaddr *sip_real_dst(const struct sip_pvt *p);
static void build_via(struct sip_pvt *p);
static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin, int newdialog, struct sockaddr_in *remote_address);
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog, struct ast_sockaddr *remote_address);
static char *generate_random_string(char *buf, size_t size);
static void build_callid_pvt(struct sip_pvt *pvt);
-static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
+static void build_callid_registry(struct sip_registry *reg, const struct ast_sockaddr *ourip, const char *fromdomain);
static void make_our_tag(char *tagbuf, size_t len);
static int add_header(struct sip_request *req, const char *var, const char *value);
static int add_content(struct sip_request *req, const char *line);
@@ -1493,19 +1498,19 @@ static void append_date(struct sip_request *req);
static void build_contact(struct sip_pvt *p);
/*------Request handling functions */
-static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
+static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock);
static int handle_request_update(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, const char *e, int *nounlock);
+static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *recount, const char *e, int *nounlock);
static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock);
static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, const char *e);
+static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e);
+static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
-static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *nounlock);
-static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e);
+static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
+static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno, int *nounlock);
/*------Response handling functions */
@@ -1877,7 +1882,7 @@ static int sip_cc_monitor_request_cc(struct ast_cc_monitor *monitor, int *availa
sip_pvt_lock(monitor_instance->subscription_pvt);
create_addr(monitor_instance->subscription_pvt, monitor_instance->peername, 0, 1, NULL);
- ast_sip_ouraddrfor(&monitor_instance->subscription_pvt->sa.sin_addr, &monitor_instance->subscription_pvt->ourip, monitor_instance->subscription_pvt);
+ ast_sip_ouraddrfor(&monitor_instance->subscription_pvt->sa, &monitor_instance->subscription_pvt->ourip, monitor_instance->subscription_pvt);
monitor_instance->subscription_pvt->subscribed = CALL_COMPLETION;
monitor_instance->subscription_pvt->expiry = when;
@@ -2793,14 +2798,19 @@ static int proxy_update(struct sip_proxy *proxy)
{
/* if it's actually an IP address and not a name,
there's no need for a managed lookup */
- if (!inet_aton(proxy->name, &proxy->ip.sin_addr)) {
+ if (!ast_sockaddr_parse(&proxy->ip, proxy->name, 0)) {
/* Ok, not an IP address, then let's check if it's a domain or host */
/* XXX Todo - if we have proxy port, don't do SRV */
+ proxy->ip.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
if (ast_get_ip_or_srv(&proxy->ip, proxy->name, sip_cfg.srvlookup ? "_sip._udp" : NULL) < 0) {
- ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name);
- return FALSE;
+ ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name);
+ return FALSE;
}
+
}
+
+ ast_sockaddr_set_port(&proxy->ip, proxy->port);
+
proxy->last_dnsupdate = time(NULL);
return TRUE;
}
@@ -2819,26 +2829,6 @@ unsigned int port_str2int(const char *pt, unsigned int standard)
return port;
}
-/*! \brief Allocate and initialize sip proxy */
-static struct sip_proxy *proxy_allocate(char *name, char *port, int force)
-{
- struct sip_proxy *proxy;
-
- if (ast_strlen_zero(name)) {
- return NULL;
- }
-
- proxy = ao2_alloc(sizeof(*proxy), NULL);
- if (!proxy)
- return NULL;
- proxy->force = force;
- ast_copy_string(proxy->name, name, sizeof(proxy->name));
- proxy->ip.sin_port = htons(port_str2int(port, STANDARD_SIP_PORT));
- proxy->ip.sin_family = AF_INET;
- proxy_update(proxy);
- return proxy;
-}
-
/*! \brief Get default outbound proxy or global proxy */
static struct sip_proxy *obproxy_get(struct sip_pvt *dialog, struct sip_peer *peer)
{
@@ -2889,21 +2879,13 @@ static int find_sip_method(const char *msg)
}
/*! \brief See if we pass debug IP filter */
-static inline int sip_debug_test_addr(const struct sockaddr_in *addr)
+static inline int sip_debug_test_addr(const struct ast_sockaddr *addr)
{
- if (!sipdebug)
- return 0;
- if (debugaddr.sin_addr.s_addr) {
- if (((ntohs(debugaddr.sin_port) != 0)
- && (debugaddr.sin_port != addr->sin_port))
- || (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
- return 1;
+ return sipdebug && !ast_sockaddr_isnull(addr) && !ast_sockaddr_cmp_addr(&debugaddr, addr);
}
/*! \brief The real destination address for a write */
-static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p)
+static const struct ast_sockaddr *sip_real_dst(const struct sip_pvt *p)
{
if (p->outboundproxy)
return &p->outboundproxy->ip;
@@ -3007,15 +2989,15 @@ static inline const char *get_transport_pvt(struct sip_pvt *p)
static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
{
int res = 0;
- const struct sockaddr_in *dst = sip_real_dst(p);
+ const struct ast_sockaddr *dst = sip_real_dst(p);
- ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
+ ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", data->str, get_transport_pvt(p), ast_sockaddr_stringify(dst));
if (sip_prepare_socket(p) < 0)
return XMIT_ERROR;
if (p->socket.type == SIP_TRANSPORT_UDP) {
- res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+ res = ast_sendto(p->socket.fd, data->str, len, 0, dst);
} else if (p->socket.tcptls_session) {
res = sip_tcptls_write(p->socket.tcptls_session, data->str, len);
} else {
@@ -3034,7 +3016,7 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
}
}
if (res != len)
- ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
+ ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, ast_sockaddr_stringify(dst), res, strerror(errno));
return res;
}
@@ -3046,10 +3028,10 @@ static void build_via(struct sip_pvt *p)
const char *rport = (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) || ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)) ? ";rport" : "";
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
- snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s",
+ snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s;branch=z9hG4bK%08x%s",
get_transport_pvt(p),
- ast_inet_ntoa(p->ourip.sin_addr),
- ntohs(p->ourip.sin_port), (int) p->branch, rport);
+ ast_sockaddr_stringify(&p->ourip),
+ (int) p->branch, rport);
}
/*! \brief NAT fix - decide which IP address to use for Asterisk server?
@@ -3059,9 +3041,11 @@ static void build_via(struct sip_pvt *p)
* externip or can get away with our internal bindaddr
* 'us' is always overwritten.
*/
-static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, struct sip_pvt *p)
+static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p)
{
- struct sockaddr_in theirs;
+ struct ast_sockaddr theirs;
+ struct sockaddr_in theirs_sin, externip_sin, us_sin;
+
/* Set want_remap to non-zero if we want to remap 'us' to an externally
* reachable IP address and port. This is done if:
* 1. we have a localaddr list (containing 'internal' addresses marked
@@ -3074,76 +3058,100 @@ static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, str
* when passed to ast_apply_ha() so it does need to be remapped.
* This fourth condition is checked later.
*/
- int want_remap;
+ int want_remap = 0;
- *us = internip; /* starting guess for the internal address */
+ ast_sockaddr_copy(us, &internip); /* starting guess for the internal address */
/* now ask the system what would it use to talk to 'them' */
- ast_ouraddrfor(them, &us->sin_addr);
- theirs.sin_addr = *them;
+ ast_ouraddrfor(them, us);
+ ast_sockaddr_copy(&theirs, them);
- want_remap = localaddr &&
- (externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) &&
- ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ;
+ if (ast_sockaddr_is_ipv6(&theirs)) {
+ if (localaddr && !ast_sockaddr_isnull(&externip)) {
+ ast_log(LOG_WARNING, "Address remapping activated in sip.conf "
+ "but we're using IPv6, which doesn't need it. Please "
+ "remove \"localnet\" and/or \"externip\" settings.\n");
+ }
+ } else {
+ ast_sockaddr_to_sin(&theirs, &theirs_sin);
+ ast_sockaddr_to_sin(us, &us_sin);
+
+ want_remap = localaddr &&
+ !(ast_sockaddr_isnull(&externip) && stunaddr.sin_addr.s_addr) &&
+ ast_apply_ha(localaddr, &theirs_sin) == AST_SENSE_ALLOW ;
+ }
if (want_remap &&
- (!sip_cfg.matchexterniplocally || !ast_apply_ha(localaddr, us)) ) {
+ (!sip_cfg.matchexterniplocally || !ast_apply_ha(localaddr, &us_sin)) ) {
/* if we used externhost or stun, see if it is time to refresh the info */
if (externexpire && time(NULL) >= externexpire) {
if (stunaddr.sin_addr.s_addr) {
- ast_stun_request(sipsock, &stunaddr, NULL, &externip);
+ ast_sockaddr_to_sin(&externip, &externip_sin);
+ ast_stun_request(sipsock, &stunaddr, NULL, &externip_sin);
} else {
- if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
+ if (ast_sockaddr_resolve_first(&externip, externhost, 0)) {
ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
+ }
+ externexpire = time(NULL);
}
externexpire = time(NULL) + externrefresh;
}
- if (externip.sin_addr.s_addr) {
- *us = externip;
+ if (ast_sockaddr_isnull(&externip)) {
+ ast_sockaddr_copy(us, &externip);
switch (p->socket.type) {
case SIP_TRANSPORT_TCP:
- us->sin_port = htons(externtcpport);
+ if (!externtcpport && ast_sockaddr_port(&externip)) {
+ /* for consistency, default to the externip port */
+ externtcpport = ast_sockaddr_port(&externip);
+ }
+ ast_sockaddr_set_port(us, externtcpport);
break;
case SIP_TRANSPORT_TLS:
- us->sin_port = htons(externtlsport);
+ ast_sockaddr_set_port(us, externtlsport);
break;
case SIP_TRANSPORT_UDP:
break; /* fall through */
default:
- us->sin_port = htons(STANDARD_SIP_PORT); /* we should never get here */
+ /* we should never get here */
+ ast_sockaddr_set_port(us, STANDARD_SIP_PORT);
}
}
- else
+ else {
ast_log(LOG_WARNING, "stun failed\n");
+ }
ast_debug(1, "Target address %s is not local, substituting externip\n",
- ast_inet_ntoa(*(struct in_addr *)&them->s_addr));
+ ast_sockaddr_stringify(them));
} else if (p) {
/* no remapping, but we bind to a specific address, so use it. */
switch (p->socket.type) {
case SIP_TRANSPORT_TCP:
- if (sip_tcp_desc.local_address.sin_addr.s_addr) {
- *us = sip_tcp_desc.local_address;
+ if (!ast_sockaddr_is_any(&sip_tcp_desc.local_address)) {
+ ast_sockaddr_copy(us,
+ &sip_tcp_desc.local_address);
} else {
- us->sin_port = sip_tcp_desc.local_address.sin_port;
+ ast_sockaddr_set_port(us,
+ ast_sockaddr_port(&sip_tcp_desc.local_address));
}
break;
case SIP_TRANSPORT_TLS:
- if (sip_tls_desc.local_address.sin_addr.s_addr) {
- *us = sip_tls_desc.local_address;
+ if (!ast_sockaddr_is_any(&sip_tls_desc.local_address)) {
+ ast_sockaddr_copy(us,
+ &sip_tls_desc.local_address);
} else {
- us->sin_port = sip_tls_desc.local_address.sin_port;
+ ast_sockaddr_set_port(us,
+ ast_sockaddr_port(&sip_tls_desc.local_address));
}
- break;
+ break;
case SIP_TRANSPORT_UDP:
/* fall through on purpose */
default:
- if (bindaddr.sin_addr.s_addr) {
- *us = bindaddr;
+ if (!ast_sockaddr_is_any(&bindaddr)) {
+ ast_sockaddr_copy(us, &bindaddr);
}
}
- } else if (bindaddr.sin_addr.s_addr) {
- *us = bindaddr;
+ } else if (!ast_sockaddr_is_any(&bindaddr)) {
+ ast_sockaddr_copy(us, &bindaddr);
}
- ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s:%d\n", get_transport(p->socket.type), ast_inet_ntoa(us->sin_addr), ntohs(us->sin_port));
+ ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s\n", get_transport(p->socket.type), ast_sockaddr_stringify(us));
}
/*! \brief Append to SIP dialog history with arg list */
@@ -3231,11 +3239,11 @@ static int retrans_pkt(const void *data)
}
if (sip_debug_test_pvt(pkt->owner)) {
- const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
- ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
+ const struct ast_sockaddr *dst = sip_real_dst(pkt->owner);
+ ast_verbose("Retransmitting #%d (%s) to %s:\n%s\n---\n",
pkt->retrans, sip_nat_mode(pkt->owner),
- ast_inet_ntoa(dst->sin_addr),
- ntohs(dst->sin_port), pkt->data->str);
+ ast_sockaddr_stringify(dst),
+ pkt->data->str);
}
append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
@@ -3709,12 +3717,12 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
finalize_content(req);
add_blank(req);
if (sip_debug_test_pvt(p)) {
- const struct sockaddr_in *dst = sip_real_dst(p);
+ const struct ast_sockaddr *dst = sip_real_dst(p);
- ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
+ ast_verbose("\n<--- %sTransmitting (%s) to %s --->\n%s\n<------------>\n",
reliable ? "Reliably " : "", sip_nat_mode(p),
- ast_inet_ntoa(dst->sin_addr),
- ntohs(dst->sin_port), req->data->str);
+ ast_sockaddr_stringify(dst),
+ req->data->str);
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = 0, };
@@ -3755,10 +3763,11 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
finalize_content(req);
add_blank(req);
if (sip_debug_test_pvt(p)) {
- if (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT))
- ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str);
- else
- ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str);
+ if (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT)) {
+ ast_verbose("%sTransmitting (NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->recv), req->data->str);
+ } else {
+ ast_verbose("%sTransmitting (no NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->sa), req->data->str);
+ }
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = 0, };
@@ -4012,7 +4021,7 @@ static int sip_sendtext(struct ast_channel *ast, const char *text)
that name and store that in the "regserver" field in the sippeers
table to facilitate multi-server setups.
*/
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms)
+static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms)
{
char port[10];
char ipaddr[INET_ADDRSTRLEN];
@@ -4033,9 +4042,9 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin,
snprintf(str_lastms, sizeof(str_lastms), "%d", lastms);
snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */
- ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
- snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
-
+ ast_copy_string(ipaddr, ast_sockaddr_stringify_addr(addr), sizeof(ipaddr));
+ ast_copy_string(port, ast_sockaddr_stringify_port(addr), sizeof(port));
+
if (ast_strlen_zero(sysname)) /* No system name, disable this */
sysname = NULL;
else if (sip_cfg.rtsave_sysname)
@@ -4209,7 +4218,7 @@ static const char *get_name_from_variable(struct ast_variable *var, const char *
* This returns a pointer to a peer and because we use build_peer, we can rest
* assured that the refcount is bumped.
*/
-static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin, int devstate_only)
+static struct sip_peer *realtime_peer(const char *newpeername, struct ast_sockaddr *addr, int devstate_only)
{
struct sip_peer *peer;
struct ast_variable *var = NULL;
@@ -4219,7 +4228,6 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
char ipaddr[INET_ADDRSTRLEN];
char portstring[6]; /*up to 5 digits plus null terminator*/
char *cat = NULL;
- unsigned short portnum;
int realtimeregs = ast_check_realtime("sipregs");
/* First check on peer name */
@@ -4228,8 +4236,9 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL);
var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", SENTINEL);
- if (!var && sin)
- var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL);
+ if (!var && addr) {
+ var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_sockaddr_stringify_addr(addr), SENTINEL);
+ }
if (!var) {
var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL);
/*!\note
@@ -4238,16 +4247,21 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
* is because we only have the IP address and the host field might be
* set as a name (and the reverse PTR might not match).
*/
- if (var && sin) {
+ if (var && addr) {
for (tmp = var; tmp; tmp = tmp->next) {
if (!strcasecmp(tmp->name, "host")) {
- struct hostent *hp;
- struct ast_hostent ahp;
- if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
+ struct ast_sockaddr *addrs = NULL;
+
+ if (ast_sockaddr_resolve(&addrs,
+ tmp->value,
+ PARSE_PORT_FORBID,
+ get_address_family_filter(&bindaddr)) <= 0 ||
+ ast_sockaddr_cmp(&addrs[0], addr)) {
/* No match */
ast_variables_destroy(var);
var = NULL;
}
+ ast_free(addrs);
break;
}
}
@@ -4255,10 +4269,9 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
}
}
- if (!var && sin) { /* Then check on IP address for dynamic peers */
- ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
- portnum = ntohs(sin->sin_port);
- sprintf(portstring, "%u", portnum);
+ if (!var && addr) { /* Then check on IP address for dynamic peers */
+ ast_copy_string(ipaddr, ast_sockaddr_stringify_addr(addr), sizeof(ipaddr));
+ ast_copy_string(portstring, ast_sockaddr_stringify_port(addr), sizeof(portstring));
var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL); /* First check for fixed IP hosts */
if (var) {
if (realtimeregs) {
@@ -4368,7 +4381,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
ref_peer(peer, "add registration ref"));
}
ao2_t_link(peers, peer, "link peer into peers table");
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
}
@@ -4425,7 +4438,7 @@ static int find_by_name(void *obj, void *arg, void *data, int flags)
* \note Avoid using this function in new functions if there is a way to avoid it,
* since it might cause a database lookup.
*/
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only, int transport)
+static struct sip_peer *find_peer(const char *peer, struct ast_sockaddr *addr, int realtime, int which_objects, int devstate_only, int transport)
{
struct sip_peer *p = NULL;
struct sip_peer tmp_peer;
@@ -4433,9 +4446,8 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
if (peer) {
ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &which_objects, "ao2_find in peers table");
- } else if (sin) { /* search by addr? */
- tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
- tmp_peer.addr.sin_port = sin->sin_port;
+ } else if (addr) { /* search by addr? */
+ ast_sockaddr_copy(&tmp_peer.addr, addr);
tmp_peer.flags[0].flags = 0;
tmp_peer.transports = transport;
p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
@@ -4449,7 +4461,7 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
}
if (!p && (realtime || devstate_only)) {
- p = realtime_peer(peer, sin, devstate_only);
+ p = realtime_peer(peer, addr, devstate_only);
if (p) {
switch (which_objects) {
case FINDUSERS:
@@ -4582,17 +4594,20 @@ static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket
*/
static int dialog_initialize_rtp(struct sip_pvt *dialog)
{
+ struct ast_sockaddr bindaddr_tmp;
+
if (!sip_methods[dialog->method].need_rtp) {
return 0;
}
- if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
+ ast_sockaddr_copy(&bindaddr_tmp, &bindaddr);
+ if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) ||
(ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (dialog->capability & AST_FORMAT_VIDEO_MASK))) {
- if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
+ if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout);
@@ -4602,7 +4617,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
}
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) {
- if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
+ if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout);
@@ -4634,7 +4649,6 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
*/
static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
{
-
/* this checks that the dialog is contacting the peer on a valid
* transport type based on the peers transport configuration,
* otherwise, this function bails out */
@@ -4642,9 +4656,9 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
return -1;
copy_socket_data(&dialog->socket, &peer->socket);
- if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
+ if (!(ast_sockaddr_isnull(&peer->addr) && ast_sockaddr_isnull(&peer->defaddr)) &&
(!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) {
- dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
+ dialog->sa = ast_sockaddr_isnull(&peer->addr) ? peer->defaddr : peer->addr;
dialog->recv = dialog->sa;
} else
return -1;
@@ -4656,8 +4670,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
dialog->capability = peer->capability;
dialog->prefs = peer->prefs;
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
+ struct sockaddr_in bindaddr_tmp;
+
/* t38pt_udptl was enabled in the peer and not in [general] */
- if (dialog->udptl || (!dialog->udptl && (dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr)))) {
+ ast_sockaddr_to_sin(&bindaddr, &bindaddr_tmp);
+ if (dialog->udptl || (!dialog->udptl && (dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_tmp.sin_addr)))) {
dialog->t38_maxdatagram = peer->t38_maxdatagram;
set_t38_capabilities(dialog);
} else {
@@ -4723,7 +4740,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
dialog->disallowed_methods = peer->disallowed_methods;
ast_cc_copy_config_params(dialog->cc_params, peer->cc_params);
if (ast_strlen_zero(dialog->tohost))
- ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr));
+ ast_string_field_set(dialog, tohost, ast_sockaddr_stringify_host(&dialog->sa));
if (!ast_strlen_zero(peer->fromdomain)) {
ast_string_field_set(dialog, fromdomain, peer->fromdomain);
if (!dialog->initreq.headers) {
@@ -4779,24 +4796,27 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
/*! \brief create address structure from device name
* Or, if peer not found, find it in the global DNS
* returns TRUE (-1) on failure, FALSE on success */
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin, int newdialog, struct sockaddr_in *remote_address)
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog, struct ast_sockaddr *remote_address)
{
- struct hostent *hp;
- struct ast_hostent ahp;
struct sip_peer *peer;
- char *port;
- int portno = 0;
- char host[MAXHOSTNAMELEN], *hostn;
- char peername[256];
+ char *peername, *peername2, *hostn;
+ char host[MAXHOSTNAMELEN];
+ char service[MAXHOSTNAMELEN];
int srv_ret = 0;
+ int tportno;
- ast_copy_string(peername, opeer, sizeof(peername));
- port = strchr(peername, ':');
- if (port) {
- *port++ = '\0';
+ AST_DECLARE_APP_ARGS(hostport,
+ AST_APP_ARG(host);
+ AST_APP_ARG(port);
+ );
+
+ peername = ast_strdupa(opeer);
+ peername2 = ast_strdupa(opeer);
+ AST_NONSTANDARD_RAW_ARGS(hostport, peername2, ':');
+
+ if (hostport.port)
dialog->portinuri = 1;
- }
- dialog->sa.sin_family = AF_INET;
+
dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0);
@@ -4807,12 +4827,8 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
set_socket_transport(&dialog->socket, 0);
}
res = create_addr_from_peer(dialog, peer);
- if (remote_address && remote_address->sin_addr.s_addr) {
- dialog->sa = dialog->recv = *remote_address;
- } else if (!ast_strlen_zero(port)) {
- if ((portno = atoi(port))) {
- dialog->sa.sin_port = dialog->recv.sin_port = htons(portno);
- }
+ if (!ast_sockaddr_isnull(remote_address)) {
+ ast_sockaddr_copy(&dialog->sa, remote_address);
}
dialog->relatedpeer = ref_peer(peer, "create_addr: setting dialog's relatedpeer pointer");
unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup");
@@ -4823,20 +4839,15 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
return -1;
}
- ast_string_field_set(dialog, tohost, peername);
+ ast_string_field_set(dialog, tohost, hostport.host);
dialog->allowed_methods &= ~sip_cfg.disallowed_methods;
/* Get the outbound proxy information */
ref_proxy(dialog, obproxy_get(dialog, NULL));
- if (sin) {
+ if (addr) {
/* This address should be updated using dnsmgr */
- memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr));
- if (!sin->sin_port) {
- portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT);
- } else {
- portno = ntohs(sin->sin_port);
- }
+ ast_sockaddr_copy(&dialog->sa, addr);
} else {
/* Let's see if we can find the host in DNS. First try DNS SRV records,
@@ -4848,33 +4859,35 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
/* Section 4.2 of RFC 3263 specifies that if a port number is specified, then
* an A record lookup should be used instead of SRV.
*/
- if (!port && sip_cfg.srvlookup) {
- char service[MAXHOSTNAMELEN];
- int tportno;
-
+ if (!hostport.port && sip_cfg.srvlookup) {
snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername);
- srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
- if (srv_ret > 0) {
+ if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno,
+ service)) > 0) {
hostn = host;
- portno = tportno;
}
}
- if (!portno)
- portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT);
- hp = ast_gethostbyname(hostn, &ahp);
- if (!hp) {
+
+ if (ast_sockaddr_resolve_first(&dialog->sa, hostn, 0)) {
ast_log(LOG_WARNING, "No such host: %s\n", peername);
- return -1;
}
- memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
+
+ if (srv_ret > 0) {
+ ast_sockaddr_set_port(&dialog->sa, tportno);
+ }
}
if (!dialog->socket.type)
set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP);
- if (!dialog->socket.port)
- dialog->socket.port = bindaddr.sin_port;
- dialog->sa.sin_port = htons(portno);
- dialog->recv = dialog->sa;
+ if (!dialog->socket.port) {
+ dialog->socket.port = htons(ast_sockaddr_port(&bindaddr));
+ }
+
+ if (!ast_sockaddr_port(&dialog->sa)) {
+ ast_sockaddr_set_port(&dialog->sa,
+ (dialog->socket.type == SIP_TRANSPORT_TLS) ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
+ }
+ ast_sockaddr_copy(&dialog->recv, &dialog->sa);
return 0;
}
@@ -6800,16 +6813,12 @@ static char *generate_random_string(char *buf, size_t size)
static char *generate_uri(struct sip_pvt *pvt, char *buf, size_t size)
{
struct ast_str *uri = ast_str_alloca(size);
- int ourport = ntohs(pvt->ourip.sin_port);
ast_str_set(&uri, 0, "%s", pvt->socket.type == SIP_TRANSPORT_TLS ? "sips:" : "sip:");
/* Here would be a great place to generate a UUID, but for now we'll
* use the handy random string generation function we already have
*/
ast_str_append(&uri, 0, "%s", generate_random_string(buf, size));
- ast_str_append(&uri, 0, "@%s", ast_inet_ntoa(pvt->ourip.sin_addr));
- if (!sip_standard_port(pvt->socket.type, ourport)) {
- ast_str_append(&uri, 0, ":%d", ourport);
- }
+ ast_str_append(&uri, 0, "@%s", ast_sockaddr_stringify(&pvt->ourip));
ast_copy_string(buf, ast_str_buffer(uri), size);
return buf;
}
@@ -6819,18 +6828,18 @@ static void build_callid_pvt(struct sip_pvt *pvt)
{
char buf[33];
- const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip.sin_addr));
+ const char *host = S_OR(pvt->fromdomain, ast_sockaddr_stringify(&pvt->ourip));
ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
}
/*! \brief Build SIP Call-ID value for a REGISTER transaction */
-static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain)
+static void build_callid_registry(struct sip_registry *reg, const struct ast_sockaddr *ourip, const char *fromdomain)
{
char buf[33];
- const char *host = S_OR(fromdomain, ast_inet_ntoa(ourip));
+ const char *host = S_OR(fromdomain, ast_sockaddr_stringify_host(ourip));
ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
}
@@ -6865,7 +6874,7 @@ static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p)
* Returns a reference to the object so whoever uses it later must
* remember to release the reference.
*/
-struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
int useglobal_nat, const int intended_method, struct sip_request *req)
{
struct sip_pvt *p;
@@ -6909,11 +6918,11 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
p->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
}
- if (!sin)
+ if (!addr) {
p->ourip = internip;
- else {
- p->sa = *sin;
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ } else {
+ ast_sockaddr_copy(&p->sa, addr);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
}
/* Copy global flags to this PVT at setup. */
@@ -6930,7 +6939,10 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
if (sip_methods[intended_method].need_rtp) {
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
- if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
+ struct sockaddr_in bindaddr_tmp;
+
+ ast_sockaddr_to_sin(&bindaddr, &bindaddr_tmp);
+ if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_tmp.sin_addr))) {
ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
p->t38_maxdatagram = global_t38_maxdatagram;
} else {
@@ -6943,10 +6955,11 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
p->autoframing = global_autoframing;
}
- if (useglobal_nat && sin) {
+ if (useglobal_nat && addr) {
/* Setup NAT structure according to global settings if we have an address */
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
- p->recv = *sin;
+ ast_sockaddr_copy(&p->recv, addr);
+
do_setnat(p);
}
@@ -6990,7 +7003,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
* Returns a reference to the sip_pvt object, remember to give it back once done.
* Called by handle_incoming(), sipsock_read
*/
-static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
+static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method)
{
struct sip_pvt *p = NULL;
char *tag = ""; /* note, tag is never NULL */
@@ -7009,7 +7022,8 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
/* RFC 3261 section 24.4.1. Send a 400 Bad Request if the request is malformed. */
if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "400 Bad Request");
+ transmit_response_using_temp(callid, addr, 1, intended_method,
+ req, "400 Bad Request");
}
return NULL; /* Invalid packet */
}
@@ -7096,10 +7110,10 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
if (intended_method == SIP_REFER) {
/* We do support REFER, but not outside of a dialog yet */
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)");
+ transmit_response_using_temp(callid, addr, 1, intended_method, req, "603 Declined (no dialog)");
} else {
/* Ok, time to create a new SIP dialog object, a pvt */
- if ((p = sip_alloc(callid, sin, 1, intended_method, req))) {
+ if ((p = sip_alloc(callid, addr, 1, intended_method, req))) {
/* Ok, we've created a dialog, let's go and process it */
sip_pvt_lock(p);
} else {
@@ -7111,18 +7125,18 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
Sorry, we apologize for the inconvienience
*/
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "500 Server internal error");
+ transmit_response_using_temp(callid, addr, 1, intended_method, req, "500 Server internal error");
ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n");
}
}
return p; /* can be NULL */
} else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) {
/* A method we do not support, let's take it on the volley */
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "501 Method Not Implemented");
+ transmit_response_using_temp(callid, addr, 1, intended_method, req, "501 Method Not Implemented");
ast_debug(2, "Got a request with unsupported SIP method.\n");
} else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
/* This is a request outside of a dialog that we don't know about */
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
+ transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist");
ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>");
}
/* We do not respond to responses for dialogs that we don't know about, we just drop
@@ -7572,7 +7586,7 @@ static int find_sdp(struct sip_request *req)
}
-static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_type media, struct sockaddr_in *sin)
+static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_type media, struct ast_sockaddr *addr)
{
const char *m;
const char *c;
@@ -7581,14 +7595,13 @@ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_ty
int x = 0;
int numberofports;
int len;
- char host[258] = ""; /*Initialize to empty so we will know if we have any input */
- struct ast_hostent audiohp;
- struct hostent *hp;
+ int af;
+ char proto[4], host[258] = ""; /*Initialize to empty so we will know if we have any input */
c = get_sdp_iterate(&citerator, req, "c");
- if (sscanf(c, "IN IP4 %256s", host) != 1) {
- ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
- /* Continue since there may be a valid host in a c= line specific to the audio stream */
+ if (sscanf(c, "IN %3s %256s", proto, host) != 2) {
+ ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
+ /* Continue since there may be a valid host in a c= line specific to the audio stream */
}
/* We only want the m and c lines for audio */
for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
@@ -7602,25 +7615,31 @@ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_ty
*/
c = get_sdp_iterate(&citerator, req, "c");
if (!ast_strlen_zero(c)) {
- sscanf(c, "IN IP4 %256s", host);
+ sscanf(c, "IN %3s %256s", proto, host);
}
break;
}
}
+ if (!strcmp("IP4", proto)) {
+ af = AF_INET;
+ } else if (!strcmp("IP6", proto)) {
+ af = AF_INET6;
+ } else {
+ ast_log(LOG_WARNING, "Unknown protocol '%s'.\n", proto);
+ return -1;
+ }
+
if (ast_strlen_zero(host) || x == 0) {
ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video");
return -1;
}
- hp = ast_gethostbyname(host, &audiohp);
- if (!hp) {
+ if (ast_sockaddr_resolve_first_af(addr, host, 0, af)) {
ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video");
return -1;
}
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- sin->sin_port = htons(x);
return 0;
}
@@ -7644,23 +7663,20 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int len = -1;
/* Host information */
- struct ast_hostent sessionhp;
- struct ast_hostent audiohp;
- struct ast_hostent videohp;
- struct ast_hostent texthp;
- struct ast_hostent imagehp;
- struct hostent *hp = NULL; /*!< RTP Audio host IP */
- struct hostent *vhp = NULL; /*!< RTP video host IP */
- struct hostent *thp = NULL; /*!< RTP text host IP */
- struct hostent *ihp = NULL; /*!< UDPTL host ip */
+ struct ast_sockaddr sessionsa;
+ struct ast_sockaddr audiosa;
+ struct ast_sockaddr videosa;
+ struct ast_sockaddr textsa;
+ struct ast_sockaddr imagesa;
+ struct ast_sockaddr *sa = NULL; /*!< RTP Audio host IP */
+ struct ast_sockaddr *vsa = NULL; /*!< RTP video host IP */
+ struct ast_sockaddr *tsa = NULL; /*!< RTP text host IP */
+ struct ast_sockaddr *isa = NULL; /*!< UDPTL host ip */
int portno = -1; /*!< RTP Audio port number */
int vportno = -1; /*!< RTP Video port number */
int tportno = -1; /*!< RTP Text port number */
int udptlportno = -1; /*!< UDPTL Image port number */
- struct sockaddr_in sin; /*!< media socket address */
- struct sockaddr_in vsin; /*!< video socket address */
struct sockaddr_in isin; /*!< image socket address */
- struct sockaddr_in tsin; /*!< text socket address */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
format_t peercapability = 0, vpeercapability = 0, tpeercapability = 0;
@@ -7741,12 +7757,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
return (p->session_modify == FALSE) ? 0 : -1;
break;
case 'c':
- if (process_sdp_c(value, &sessionhp)) {
+ if (process_sdp_c(value, &sessionsa)) {
processed = TRUE;
- hp = &sessionhp.hp;
- vhp = hp;
- thp = hp;
- ihp = hp;
+ sa = &sessionsa;
+ vsa = sa;
+ tsa = sa;
+ isa = sa;
}
break;
case 'a':
@@ -7891,24 +7907,24 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
switch (type) {
case 'c':
if (audio) {
- if (process_sdp_c(value, &audiohp)) {
+ if (process_sdp_c(value, &audiosa)) {
processed = TRUE;
- hp = &audiohp.hp;
+ sa = &audiosa;
}
} else if (video) {
- if (process_sdp_c(value, &videohp)) {
+ if (process_sdp_c(value, &videosa)) {
processed = TRUE;
- vhp = &videohp.hp;
+ vsa = &videosa;
}
} else if (text) {
- if (process_sdp_c(value, &texthp)) {
+ if (process_sdp_c(value, &textsa)) {
processed = TRUE;
- thp = &texthp.hp;
+ tsa = &textsa;
}
} else if (image) {
- if (process_sdp_c(value, &imagehp)) {
+ if (process_sdp_c(value, &imagesa)) {
processed = TRUE;
- ihp = &imagehp.hp;
+ isa = &imagesa;
}
}
break;
@@ -7956,7 +7972,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Sanity checks */
- if (!hp && !vhp && !thp && !ihp) {
+ if (!sa && !vsa && !tsa && !isa) {
ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n");
return -1;
}
@@ -8042,13 +8058,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Setup audio address and port */
if (p->rtp) {
if (portno > 0) {
- sin.sin_family = AF_INET;
- sin.sin_port = htons(portno);
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- ast_rtp_instance_set_remote_address(p->rtp, &sin);
- if (debug)
- ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
+ ast_sockaddr_set_port(sa, portno);
+ ast_rtp_instance_set_remote_address(p->rtp, sa);
+ if (debug) {
+ ast_verbose("Peer audio RTP is at port %s\n",
+ ast_sockaddr_stringify(sa));
+ }
+ /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
they are acceptable */
p->jointcapability = newjointcapability; /* Our joint codec profile for this call */
p->peercapability = newpeercapability; /* The other sides capability in latest offer */
@@ -8085,12 +8101,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Setup video address and port */
if (p->vrtp) {
if (vportno > 0) {
- vsin.sin_family = AF_INET;
- vsin.sin_port = htons(vportno);
- memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr));
- ast_rtp_instance_set_remote_address(p->vrtp, &vsin);
- if (debug)
- ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
+ ast_sockaddr_set_port(vsa, vportno);
+ ast_rtp_instance_set_remote_address(p->vrtp, vsa);
+ if (debug) {
+ ast_verbose("Peer video RTP is at port %s\n",
+ ast_sockaddr_stringify(vsa));
+ }
ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
} else {
ast_rtp_instance_stop(p->vrtp);
@@ -8102,12 +8118,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Setup text address and port */
if (p->trtp) {
if (tportno > 0) {
- tsin.sin_family = AF_INET;
- tsin.sin_port = htons(tportno);
- memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr));
- ast_rtp_instance_set_remote_address(p->trtp, &tsin);
- if (debug)
- ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port));
+ ast_sockaddr_set_port(tsa, tportno);
+ ast_rtp_instance_set_remote_address(p->trtp, tsa);
+ if (debug) {
+ ast_verbose("Peer T.140 RTP is at port %s\n",
+ ast_sockaddr_stringify(tsa));
+ }
if ((p->jointcapability & AST_FORMAT_T140RED)) {
p->red = 1;
ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
@@ -8128,7 +8144,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
isin.sin_port = htons(udptlportno);
if (ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
struct sockaddr_in remote_address = { 0, };
- ast_rtp_instance_get_remote_address(p->rtp, &remote_address);
+ struct ast_sockaddr remote_address_tmp;
+
+ ast_rtp_instance_get_remote_address(p->rtp,
+ &remote_address_tmp);
+ ast_sockaddr_to_sin(&remote_address_tmp,
+ &remote_address);
if (remote_address.sin_addr.s_addr) {
memcpy(&isin, &remote_address, sizeof(isin));
if (debug) {
@@ -8136,7 +8157,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
}
} else {
- memcpy(&isin.sin_addr, ihp->h_addr, sizeof(isin.sin_addr));
+ ast_sockaddr_to_sin(isa, &isin);
}
ast_udptl_set_peer(p->udptl, &isin);
if (debug)
@@ -8207,7 +8228,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && !ast_sockaddr_isnull(sa) && (!sendonly || sendonly == -1)) {
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
@@ -8223,7 +8244,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (sip_cfg.notifyhold)
sip_peer_hold(p, FALSE);
ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
- } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) {
+ } else if (ast_sockaddr_isnull(sa) || (sendonly && sendonly != -1)) {
int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
@@ -8335,21 +8356,29 @@ static int process_sdp_o(const char *o, struct sip_pvt *p)
return TRUE;
}
-static int process_sdp_c(const char *c, struct ast_hostent *ast_hp)
+static int process_sdp_c(const char *c, struct ast_sockaddr *addr)
{
- char host[258];
- struct hostent *hp;
+ char proto[4], host[258];
+ int af;
/* Check for Media-description-level-address */
- if (sscanf(c, "IN IP4 %255s", host) != 1) {
- ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
- return FALSE;
- } else {
- if (!(hp = ast_gethostbyname(host, ast_hp))) {
+ if (sscanf(c, "IN %3s %255s", proto, host) == 2) {
+ if (!strcmp("IP4", proto)) {
+ af = AF_INET;
+ } else if (!strcmp("IP6", proto)) {
+ af = AF_INET6;
+ } else {
+ ast_log(LOG_WARNING, "Unknown protocol '%s'.\n", proto);
+ return FALSE;
+ }
+ if (ast_sockaddr_resolve_first_af(addr, host, 0, af)) {
ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in c= line, '%s'\n", c);
return FALSE;
}
return TRUE;
+ } else {
+ ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
+ return FALSE;
}
return FALSE;
}
@@ -8791,13 +8820,13 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const st
/* Add rport to first VIA header if requested */
snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s",
- leftmost, ast_inet_ntoa(p->recv.sin_addr),
- ntohs(p->recv.sin_port),
+ leftmost, ast_sockaddr_stringify_addr(&p->recv),
+ ast_sockaddr_port(&p->recv),
others ? "," : "", others ? others : "");
} else {
/* We should *always* add a received to the topmost via */
snprintf(new, sizeof(new), "%s;received=%s%s%s",
- leftmost, ast_inet_ntoa(p->recv.sin_addr),
+ leftmost, ast_sockaddr_stringify_addr(&p->recv),
others ? "," : "", others ? others : "");
}
oh = new; /* the header to copy */
@@ -8852,12 +8881,9 @@ static void add_route(struct sip_request *req, struct sip_route *route)
static void set_destination(struct sip_pvt *p, char *uri)
{
char *h, *maddr, hostname[256];
- int port, hn;
- struct hostent *hp;
- struct ast_hostent ahp;
+ int hn;
int debug=sip_debug_test_pvt(p);
int tls_on = FALSE;
- int use_dns = sip_cfg.srvlookup;
if (debug)
ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
@@ -8875,44 +8901,53 @@ static void set_destination(struct sip_pvt *p, char *uri)
tls_on = TRUE;
}
}
- hn = strcspn(h, ":;>") + 1;
+ hn = strcspn(h, ";>") + 1;
if (hn > sizeof(hostname))
hn = sizeof(hostname);
ast_copy_string(hostname, h, hn);
/* XXX bug here if string has been trimmed to sizeof(hostname) */
h += hn - 1;
- /* Is "port" present? if not default to STANDARD_SIP_PORT */
- if (*h == ':') {
- /* Parse port */
- ++h;
- port = strtol(h, &h, 10);
- use_dns = FALSE;
- } else
- port = tls_on ? STANDARD_TLS_PORT : STANDARD_SIP_PORT;
+ /*! \todo XXX If we have sip_cfg.srvlookup on, then look for NAPTR/SRV,
+ * otherwise, just look for A records */
+ if (ast_sockaddr_resolve_first(&p->sa, hostname, 0)) {
+ ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname);
+ return;
+ }
- /* Got the hostname:port - but maybe there's a "maddr=" to override address? */
+ /* Got the hostname - but maybe there's a "maddr=" to override address? */
maddr = strstr(h, "maddr=");
if (maddr) {
+ int port;
+
maddr += 6;
- hn = strspn(maddr, "0123456789.") + 1;
+ hn = strspn(maddr, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789-.:[]") + 1;
if (hn > sizeof(hostname))
hn = sizeof(hostname);
ast_copy_string(hostname, maddr, hn);
+
+ port = ast_sockaddr_port(&p->sa);
+
+ /*! \todo XXX If we have sip_cfg.srvlookup on, then look for
+ * NAPTR/SRV, otherwise, just look for A records */
+ if (ast_sockaddr_resolve_first(&p->sa, hostname, PARSE_PORT_FORBID)) {
+ ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname);
+ return;
+ }
+
+ ast_sockaddr_set_port(&p->sa, port);
}
- /*! \todo XXX If we have use_dns on, then look for NAPTR/SRV, otherwise, just look for A records */
-
- hp = ast_gethostbyname(hostname, &ahp);
- if (hp == NULL) {
- ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname);
- return;
+ if (!ast_sockaddr_port(&p->sa)) {
+ ast_sockaddr_set_port(&p->sa, tls_on ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
+ }
+
+ if (debug) {
+ ast_verbose("set_destination: set destination to %s\n",
+ ast_sockaddr_stringify(&p->sa));
}
- p->sa.sin_family = AF_INET;
- memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
- p->sa.sin_port = htons(port);
- if (debug)
- ast_verbose("set_destination: set destination to %s, port %d\n", ast_inet_ntoa(p->sa.sin_addr), port);
}
/*! \brief Initialize SIP response, based on SIP request */
@@ -9320,7 +9355,7 @@ static void temp_pvt_cleanup(void *data)
}
/*! \brief Transmit response, no retransmits, using a temporary pvt structure */
-static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg)
+static int transmit_response_using_temp(ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg)
{
struct sip_pvt *p = NULL;
@@ -9339,20 +9374,20 @@ static int transmit_response_using_temp(ast_string_field callid, struct sockaddr
/* Initialize the bare minimum */
p->method = intended_method;
- if (!sin)
- p->ourip = internip;
- else {
- p->sa = *sin;
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ if (!addr) {
+ ast_sockaddr_copy(&p->ourip, &internip);
+ } else {
+ ast_sockaddr_copy(&p->sa, addr);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
}
p->branch = ast_random();
make_our_tag(p->tag, sizeof(p->tag));
p->ocseq = INITIAL_CSEQ;
- if (useglobal_nat && sin) {
+ if (useglobal_nat && addr) {
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
- p->recv = *sin;
+ ast_sockaddr_copy(&p->recv, addr);
do_setnat(p);
}
@@ -9620,7 +9655,7 @@ static int add_rpid(struct sip_request *req, struct sip_pvt *p)
return 0;
if (ast_strlen_zero(lid_name))
lid_name = lid_num;
- fromdomain = S_OR(p->fromdomain, ast_strdupa(ast_inet_ntoa(p->ourip.sin_addr)));
+ fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
lid_num = ast_uri_encode(lid_num, tmp2, sizeof(tmp2), 1);
@@ -9857,21 +9892,23 @@ static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
\note called from add_sdp()
*/
static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext,
- struct sockaddr_in *sin, struct sockaddr_in *vsin, struct sockaddr_in *tsin,
- struct sockaddr_in *dest, struct sockaddr_in *vdest, struct sockaddr_in *tdest)
+ struct ast_sockaddr *addr, struct ast_sockaddr *vaddr,
+ struct ast_sockaddr *taddr, struct ast_sockaddr *dest,
+ struct ast_sockaddr *vdest, struct ast_sockaddr *tdest)
{
/* First, get our address */
- ast_rtp_instance_get_local_address(p->rtp, sin);
- if (p->vrtp)
- ast_rtp_instance_get_local_address(p->vrtp, vsin);
- if (p->trtp)
- ast_rtp_instance_get_local_address(p->trtp, tsin);
+ ast_rtp_instance_get_local_address(p->rtp, addr);
+ if (p->vrtp) {
+ ast_rtp_instance_get_local_address(p->vrtp, vaddr);
+ }
+ if (p->trtp) {
+ ast_rtp_instance_get_local_address(p->trtp, taddr);
+ }
/* Now, try to figure out where we want them to send data */
/* Is this a re-invite to move the media out, then use the original offer from caller */
- if (p->redirip.sin_addr.s_addr) { /* If we have a redirection IP, use it */
- dest->sin_port = p->redirip.sin_port;
- dest->sin_addr = p->redirip.sin_addr;
+ if (!ast_sockaddr_isnull(&p->redirip)) { /* If we have a redirection IP, use it */
+ ast_sockaddr_copy(dest, &p->redirip);
} else {
/*
* Audio Destination IP:
@@ -9884,15 +9921,17 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*
* 1. Provided by the RTP engine.
*/
- dest->sin_addr = media_address.sin_addr.s_addr ? media_address.sin_addr :
- (sin->sin_addr.s_addr ? sin->sin_addr : p->ourip.sin_addr);
- dest->sin_port = sin->sin_port;
+ ast_sockaddr_copy(dest,
+ !ast_sockaddr_isnull(&media_address) ? &media_address :
+ !ast_sockaddr_is_any(addr) ? addr :
+ &p->ourip);
+ ast_sockaddr_set_port(dest, ast_sockaddr_port(addr));
}
+
if (needvideo) {
/* Determine video destination */
- if (p->vredirip.sin_addr.s_addr) {
- vdest->sin_addr = p->vredirip.sin_addr;
- vdest->sin_port = p->vredirip.sin_port;
+ if (!ast_sockaddr_isnull(&p->vredirip)) {
+ ast_sockaddr_copy(vdest, &p->vredirip);
} else {
/*
* Video Destination IP:
@@ -9905,16 +9944,18 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*
* 1. Provided by the RTP engine.
*/
- vdest->sin_addr = media_address.sin_addr.s_addr ? media_address.sin_addr :
- (vsin->sin_addr.s_addr ? vsin->sin_addr : p->ourip.sin_addr);
- vdest->sin_port = vsin->sin_port;
+ ast_sockaddr_copy(vdest,
+ !ast_sockaddr_isnull(&media_address) ? &media_address :
+ !ast_sockaddr_is_any(vaddr) ? vaddr :
+ &p->ourip);
+ ast_sockaddr_set_port(vdest, ast_sockaddr_port(vaddr));
}
}
+
if (needtext) {
/* Determine text destination */
- if (p->tredirip.sin_addr.s_addr) {
- tdest->sin_addr = p->tredirip.sin_addr;
- tdest->sin_port = p->tredirip.sin_port;
+ if (!ast_sockaddr_isnull(&p->tredirip)) {
+ ast_sockaddr_copy(tdest, &p->tredirip);
} else {
/*
* Text Destination IP:
@@ -9927,9 +9968,11 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*
* 1. Provided by the RTP engine.
*/
- tdest->sin_addr = media_address.sin_addr.s_addr ? media_address.sin_addr :
- (tsin->sin_addr.s_addr ? tsin->sin_addr : p->ourip.sin_addr);
- tdest->sin_port = tsin->sin_port;
+ ast_sockaddr_copy(tdest,
+ !ast_sockaddr_isnull(&media_address) ? &media_address :
+ !ast_sockaddr_is_any(taddr) ? taddr :
+ &p->ourip);
+ ast_sockaddr_set_port(tdest, ast_sockaddr_port(taddr));
}
}
}
@@ -9961,13 +10004,14 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
{
format_t alreadysent = 0;
- struct sockaddr_in sin = { 0, };
- struct sockaddr_in vsin = { 0, };
- struct sockaddr_in tsin = { 0, };
- struct sockaddr_in dest = { 0, };
+ struct ast_sockaddr addr = { {0,} };
+ struct ast_sockaddr vaddr = { {0,} };
+ struct ast_sockaddr taddr = { {0,} };
+ struct ast_sockaddr dest = { {0,} };
+ struct ast_sockaddr vdest = { {0,} };
+ struct ast_sockaddr tdest = { {0,} };
+ struct sockaddr_in dest_tmp;
struct sockaddr_in udptlsin = { 0, };
- struct sockaddr_in vdest = { 0, };
- struct sockaddr_in tdest = { 0, };
struct sockaddr_in udptldest = { 0, };
/* SDP fields */
@@ -10048,11 +10092,19 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
}
}
- get_our_media_address(p, needvideo, needtext, &sin, &vsin, &tsin, &dest, &vdest, &tdest);
+ get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest);
- snprintf(owner, sizeof(owner), "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
+ snprintf(owner, sizeof(owner), "o=%s %d %d IN %s %s\r\n",
+ ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner,
+ p->sessionid, p->sessionversion,
+ (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
+ "IP6" : "IP4",
+ ast_sockaddr_stringify_addr(&dest));
- snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
+ snprintf(connection, sizeof(connection), "c=IN %s %s\r\n",
+ (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
+ "IP6" : "IP4",
+ ast_sockaddr_stringify_addr(&dest));
if (add_audio) {
capability = p->jointcapability;
@@ -10066,21 +10118,23 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
if (capability & AST_FORMAT_AUDIO_MASK)
needaudio = TRUE;
- if (debug)
- ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
+ if (debug) {
+ ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&p->ourip));
+ }
/* Ok, we need video. Let's add what we need for video and set codecs.
Video is handled differently than audio since we can not transcode. */
if (needvideo) {
get_crypto_attrib(p->vsrtp, &v_a_crypto);
- ast_str_append(&m_video, 0, "m=video %d RTP/%s", ntohs(vdest.sin_port),
+ ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest),
v_a_crypto ? "SAVP" : "AVP");
/* Build max bitrate string */
if (p->maxcallbitrate)
snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
- if (debug)
- ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vdest.sin_port));
+ if (debug) {
+ ast_verbose("Video is at %s\n", ast_sockaddr_stringify(&p->ourip));
+ }
}
/* Ok, we need text. Let's add what we need for text and set codecs.
@@ -10089,11 +10143,11 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
if (sipdebug_text)
ast_verbose("Lets set up the text sdp\n");
get_crypto_attrib(p->tsrtp, &t_a_crypto);
- ast_str_append(&m_text, 0, "m=text %d RTP/%s", ntohs(tdest.sin_port),
+ ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest),
t_a_crypto ? "SAVP" : "AVP");
- if (debug) /* XXX should I use tdest below ? */
- ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port));
-
+ if (debug) { /* XXX should I use tdest below ? */
+ ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&p->ourip));
+ }
}
/* Start building generic SDP headers */
@@ -10102,7 +10156,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
peer doesn't have to ast_gethostbyname() us */
get_crypto_attrib(p->srtp, &a_crypto);
- ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ntohs(dest.sin_port),
+ ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest),
a_crypto ? "SAVP" : "AVP");
if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
@@ -10200,19 +10254,21 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
udptldest.sin_port = p->udptlredirip.sin_port;
udptldest.sin_addr = p->udptlredirip.sin_addr;
} else {
- udptldest.sin_addr = p->ourip.sin_addr;
+ ast_sockaddr_to_sin(&p->ourip, &udptldest);
udptldest.sin_port = udptlsin.sin_port;
}
- if (debug)
- ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port));
+ if (debug) {
+ ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_sockaddr_stringify_addr(&p->ourip), ntohs(udptlsin.sin_port));
+ }
/* We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us */
ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
- if (udptldest.sin_addr.s_addr != dest.sin_addr.s_addr) {
+ ast_sockaddr_to_sin(&dest, &dest_tmp);
+ if (udptldest.sin_addr.s_addr != dest_tmp.sin_addr.s_addr) {
ast_str_append(&m_modem, 0, "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
}
@@ -10551,19 +10607,13 @@ static void extract_uri(struct sip_pvt *p, struct sip_request *req)
/*! \brief Build contact header - the contact header we send out */
static void build_contact(struct sip_pvt *p)
{
-
- int ourport = ntohs(p->ourip.sin_port);
- /* only add port if it's non-standard for the transport type */
- if (!sip_standard_port(p->socket.type, ourport)) {
- if (p->socket.type == SIP_TRANSPORT_UDP)
- ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport);
- else
- ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport, get_transport(p->socket.type));
+ if (p->socket.type == SIP_TRANSPORT_UDP) {
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten,
+ ast_strlen_zero(p->exten) ? "" : "@", ast_sockaddr_stringify(&p->ourip));
} else {
- if (p->socket.type == SIP_TRANSPORT_UDP)
- ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
- else
- ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), get_transport(p->socket.type));
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", p->exten,
+ ast_strlen_zero(p->exten) ? "" : "@", ast_sockaddr_stringify(&p->ourip),
+ get_transport(p->socket.type));
}
}
@@ -10603,7 +10653,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
- d = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
+ d = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
l = p->owner->connected.id.number;
n = p->owner->connected.id.name;
@@ -10647,13 +10697,12 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
l = tmp_l;
}
- ourport = (p->fromdomainport) ? p->fromdomainport : ntohs(p->ourip.sin_port);
+ ourport = (p->fromdomainport) ? p->fromdomainport : ast_sockaddr_port(&p->ourip);
if (!sip_standard_port(p->socket.type, ourport))
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, d, ourport, p->tag);
else
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, d, p->tag);
-
if (!ast_strlen_zero(explicit_uri)) {
ast_str_set(&invite, 0, "%s", explicit_uri);
} else {
@@ -10673,8 +10722,9 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
ast_str_append(&invite, 0, "%s@", n);
}
ast_str_append(&invite, 0, "%s", p->tohost);
- if (p->portinuri)
- ast_str_append(&invite, 0, ":%d", ntohs(p->sa.sin_port));
+ if (p->portinuri) {
+ ast_str_append(&invite, 0, ":%d", ast_sockaddr_port(&p->sa));
+ }
ast_str_append(&invite, 0, "%s", urioptions);
}
}
@@ -10759,9 +10809,12 @@ static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
/* We at least have a number to place in the Diversion header, which is enough */
if (ast_strlen_zero(diverting_name)) {
- snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
+ snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number,
+ ast_sockaddr_stringify_host(&pvt->ourip), reason);
} else {
- snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", diverting_name, diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
+ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s",
+ diverting_name, diverting_number,
+ ast_sockaddr_stringify_host(&pvt->ourip), reason);
}
add_header(req, "Diversion", header_text);
@@ -10784,7 +10837,7 @@ static int transmit_publish(struct sip_epa_entry *epa_entry, enum sip_publish_ty
dialog_unlink_all(pvt, TRUE, TRUE);
dialog_unref(pvt, "create_addr failed in transmit_publish. Unref dialog");
}
- ast_sip_ouraddrfor(&pvt->sa.sin_addr, &pvt->ourip, pvt);
+ ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);
ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
expires = (publish_type == SIP_PUBLISH_REMOVE) ? 0 : DEFAULT_PUBLISH_EXPIRES;
pvt->expiry = expires;
@@ -10986,6 +11039,8 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
if (!mwi->dnsmgr) {
char transport[MAXHOSTNAMELEN];
snprintf(transport, sizeof(transport), "_sip._%s", get_transport(mwi->transport));
+
+ mwi->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
ast_dnsmgr_lookup(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL);
}
@@ -11002,8 +11057,8 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
ref_proxy(mwi->call, obproxy_get(mwi->call, NULL));
- if (!mwi->us.sin_port && mwi->portno) {
- mwi->us.sin_port = htons(mwi->portno);
+ if (!ast_sockaddr_port(&mwi->us) && mwi->portno) {
+ ast_sockaddr_set_port(&mwi->us, mwi->portno);
}
/* Setup the destination of our subscription */
@@ -11016,10 +11071,10 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
mwi->call->expiry = mwi_expiry;
if (!mwi->dnsmgr && mwi->portno) {
- mwi->call->sa.sin_port = htons(mwi->portno);
- mwi->call->recv.sin_port = htons(mwi->portno);
+ ast_sockaddr_set_port(&mwi->call->sa, mwi->portno);
+ ast_sockaddr_set_port(&mwi->call->recv, mwi->portno);
} else {
- mwi->portno = ntohs(mwi->call->sa.sin_port);
+ mwi->portno = ast_sockaddr_port(&mwi->call->sa);
}
/* Set various other information */
@@ -11038,7 +11093,7 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
}
set_socket_transport(&mwi->call->socket, mwi->transport);
mwi->call->socket.port = htons(mwi->portno);
- ast_sip_ouraddrfor(&mwi->call->sa.sin_addr, &mwi->call->ourip, mwi->call);
+ ast_sip_ouraddrfor(&mwi->call->sa, &mwi->call->ourip, mwi->call);
build_contact(mwi->call);
build_via(mwi->call);
build_callid_pvt(mwi->call);
@@ -11353,8 +11408,8 @@ static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs,
{
struct sip_request req;
struct ast_str *out = ast_str_alloca(500);
- int ourport = (p->fromdomainport) ? p->fromdomainport : ntohs(p->ourip.sin_port);
- const char *domain = S_OR(p->fromdomain,ast_inet_ntoa(p->ourip.sin_addr));
+ int ourport = (p->fromdomainport) ? p->fromdomainport : ast_sockaddr_port(&p->ourip);
+ const char *domain = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
const char *exten = S_OR(vmexten, default_vmexten);
initreqprep(&req, p, SIP_NOTIFY, NULL);
@@ -11697,6 +11752,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
char transport[MAXHOSTNAMELEN];
peer = find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0);
snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */
+ r->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, sip_cfg.srvlookup ? transport : NULL);
if (peer) {
peer = unref_peer(peer, "removing peer ref for dnsmgr_lookup");
@@ -11715,7 +11771,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
} else {
/* Build callid for registration if we haven't registered before */
if (!r->callid_valid) {
- build_callid_registry(r, internip.sin_addr, default_fromdomain);
+ build_callid_registry(r, &internip, default_fromdomain);
r->callid_valid = TRUE;
}
/* Allocate SIP dialog for registration */
@@ -11728,8 +11784,9 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname);
/* Use port number specified if no SRV record was found */
- if (!r->us.sin_port && r->portno)
- r->us.sin_port = htons(r->portno);
+ if (!ast_sockaddr_port(&r->us) && r->portno) {
+ ast_sockaddr_set_port(&r->us, r->portno);
+ }
/* Find address to hostname */
if (create_addr(p, S_OR(r->peername, r->hostname), &r->us, 0, NULL)) {
@@ -11755,15 +11812,15 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
ast_string_field_set(r, callid, p->callid);
if (!r->dnsmgr && r->portno) {
- p->sa.sin_port = htons(r->portno);
- p->recv.sin_port = htons(r->portno);
+ ast_sockaddr_set_port(&p->sa, r->portno);
+ ast_sockaddr_set_port(&p->recv, r->portno);
}
if (!ast_strlen_zero(p->fromdomain)) {
portno = (p->fromdomainport) ? p->fromdomainport : STANDARD_SIP_PORT;
} else if (!ast_strlen_zero(r->regdomain)) {
portno = (r->regdomainport) ? r->regdomainport : STANDARD_SIP_PORT;
} else {
- portno = ntohs(p->sa.sin_port);
+ portno = ast_sockaddr_port(&p->sa);
}
ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */
@@ -11793,7 +11850,8 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
/* Set transport and port so the correct contact is built */
set_socket_transport(&p->socket, r->transport);
if (r->transport == SIP_TRANSPORT_TLS || r->transport == SIP_TRANSPORT_TCP) {
- p->socket.port = sip_tcp_desc.local_address.sin_port;
+ p->socket.port =
+ htons(ast_sockaddr_port(&sip_tcp_desc.local_address));
}
/*
@@ -11801,7 +11859,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
based on whether the remote host is on the external or
internal network so we can register through nat
*/
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
build_contact(p);
}
@@ -12196,7 +12254,7 @@ static int expire_register(const void *data)
if (peer->selfdestruct ||
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
}
}
@@ -12224,30 +12282,28 @@ static int sip_poke_peer_s(const void *data)
static void reg_source_db(struct sip_peer *peer)
{
char data[256];
- struct in_addr in;
+ struct ast_sockaddr sa;
int expire;
- int port;
- char *scan, *addr, *port_str, *expiry_str, *username, *contact;
+ char *scan, *addr, *expiry_str, *username, *contact;
if (peer->rt_fromcontact)
return;
if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data)))
return;
- scan = data;
- addr = strsep(&scan, ":");
- port_str = strsep(&scan, ":");
+ addr = scan = data;
+ if ('[' == scan[0]) {
+ /* It must be a bracket enclosed IPv6 address */
+ scan = strchr(scan, ']') + 1;
+ }
+ scan = strchr(scan, ':') + 1;
expiry_str = strsep(&scan, ":");
username = strsep(&scan, ":");
contact = scan; /* Contact include sip: and has to be the last part of the database entry as long as we use : as a separator */
- if (!inet_aton(addr, &in))
- return;
-
- if (port_str)
- port = atoi(port_str);
- else
+ if (!ast_sockaddr_parse(&sa, addr, 0)) {
return;
+ }
if (expiry_str)
expire = atoi(expiry_str);
@@ -12259,13 +12315,10 @@ static void reg_source_db(struct sip_peer *peer)
if (contact)
ast_string_field_set(peer, fullcontact, contact);
- ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n",
- peer->name, peer->username, ast_inet_ntoa(in), port, expire);
+ ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s for %d\n",
+ peer->name, peer->username, ast_sockaddr_stringify_host(&sa), expire);
- memset(&peer->addr, 0, sizeof(peer->addr));
- peer->addr.sin_family = AF_INET;
- peer->addr.sin_addr = in;
- peer->addr.sin_port = htons(port);
+ ast_sockaddr_copy(&peer->addr, &sa);
if (sipsock < 0) {
/* SIP isn't up yet, so schedule a poke only, pretty soon */
AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer,
@@ -12303,12 +12356,9 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
return TRUE;
}
-static int __set_address_from_contact(const char *fullcontact, struct sockaddr_in *sin, int tcp)
+static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp)
{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = STANDARD_SIP_PORT;
- char *host, *pt, *transport;
+ char *domain, *transport;
char contact_buf[256];
char *contact;
@@ -12323,32 +12373,32 @@ static int __set_address_from_contact(const char *fullcontact, struct sockaddr_i
* We still need to be able to send to the remote agent through the proxy.
*/
- if (parse_uri(contact, "sip:,sips:", &contact, NULL, &host, &pt, &transport)) {
+ if (parse_uri(contact, "sip:,sips:", &contact, NULL, &domain,
+ &transport)) {
ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact);
}
- /* set port */
- if (((get_transport_str2enum(transport) == SIP_TRANSPORT_TLS)) || !(strncasecmp(fullcontact, "sips", 4))) {
- port = port_str2int(pt, STANDARD_TLS_PORT);
- } else {
- port = port_str2int(pt, STANDARD_SIP_PORT);
- }
-
-
/* XXX This could block for a long time XXX */
/* We should only do this if it's a name, not an IP */
/* \todo - if there's no PORT number in contact - we are required to check NAPTR/SRV records
to find transport, port address and hostname. If there's a port number, we have to
assume that the domain part is a host name and only look for an A/AAAA record in DNS.
*/
- hp = ast_gethostbyname(host, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host);
+
+ if (ast_sockaddr_resolve_first(addr, domain, 0)) {
+ ast_log(LOG_WARNING, "Invalid host name in Contact: (can't "
+ "resolve in DNS) : '%s'\n", domain);
return -1;
}
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- sin->sin_port = htons(port);
+
+ /* set port */
+ if (!ast_sockaddr_port(addr)) {
+ ast_sockaddr_set_port(addr,
+ (get_transport_str2enum(transport) ==
+ SIP_TRANSPORT_TLS ||
+ !strncasecmp(fullcontact, "sips", 4)) ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
+ }
return 0;
}
@@ -12374,14 +12424,11 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
char data[SIPBUFSIZE];
const char *expires = get_header(req, "Expires");
int expire = atoi(expires);
- char *curi, *host, *pt, *transport;
- int port;
+ char *curi, *domain, *transport;
int transport_type;
const char *useragent;
- struct hostent *hp;
- struct ast_hostent ahp;
- struct sockaddr_in oldsin, testsin;
-
+ struct ast_sockaddr oldsin, testsa;
+ struct sockaddr_in testsin;
ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
@@ -12445,23 +12492,12 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
ast_string_field_build(pvt, our_contact, "<%s>", curi);
/* Make sure it's a SIP URL */
- if (parse_uri(curi, "sip:,sips:", &curi, NULL, &host, &pt, &transport)) {
+ if (parse_uri(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) {
ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:) trying to use anyway\n");
}
- /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records.
- The domain part is actually a host. */
- peer->portinuri = !ast_strlen_zero(pt) ? TRUE : FALSE;
-
/* handle the transport type specified in Contact header. */
- if ((transport_type = get_transport_str2enum(transport))) {
- /* if the port is not specified but the transport is, make sure to set the
- * default port to match the specified transport. This may or may not be the
- * same transport used by the pvt struct for the Register dialog. */
-
- port = port_str2int(pt, (transport_type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT);
- } else {
- port = port_str2int(pt, STANDARD_SIP_PORT);
+ if (!(transport_type = get_transport_str2enum(transport))) {
transport_type = pvt->socket.type;
}
@@ -12475,25 +12511,32 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
oldsin = peer->addr;
/* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
}
if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) && !ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT)) {
- /* use the data provided in the Contact header for call routing */
+ /* use the data provided in the Contact header for call routing */
ast_debug(1, "Store REGISTER's Contact header for call routing.\n");
/* XXX This could block for a long time XXX */
/*! \todo Check NAPTR/SRV if we have not got a port in the URI */
- hp = ast_gethostbyname(host, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Invalid host '%s'\n", host);
+ if (ast_sockaddr_resolve_first(&testsa, domain, 0)) {
+ ast_log(LOG_WARNING, "Invalid domain '%s'\n", domain);
ast_string_field_set(peer, fullcontact, "");
ast_string_field_set(pvt, our_contact, "");
return PARSE_REGISTER_FAILED;
}
- peer->addr.sin_family = AF_INET;
- memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
- peer->addr.sin_port = htons(port);
+ ast_sockaddr_copy(&peer->addr, &testsa);
+
+ /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records.
+ The domain part is actually a host. */
+ peer->portinuri = ast_sockaddr_port(&testsa) ? TRUE : FALSE;
+
+ if (!ast_sockaddr_port(&testsa)) {
+ ast_sockaddr_set_port(&testsa,
+ transport_type == SIP_TRANSPORT_TLS ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
+ }
} else {
/* Don't trust the contact field. Just use what they came to us
with */
@@ -12502,22 +12545,23 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
}
/* Check that they're allowed to register at this IP */
- memcpy(&testsin.sin_addr, &peer->addr.sin_addr, sizeof(testsin.sin_addr));
- if (ast_apply_ha(sip_cfg.contact_ha, &testsin) != AST_SENSE_ALLOW ||
- ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) {
- ast_log(LOG_WARNING, "Host '%s' disallowed by contact ACL (violating IP %s)\n", host, ast_inet_ntoa(testsin.sin_addr));
- ast_string_field_set(peer, fullcontact, "");
- ast_string_field_set(pvt, our_contact, "");
- return PARSE_REGISTER_DENIED;
+ if (!ast_sockaddr_is_ipv6(&peer->addr)) {
+ ast_sockaddr_to_sin(&peer->addr, &testsin);
+ if (ast_apply_ha(sip_cfg.contact_ha, &testsin) != AST_SENSE_ALLOW ||
+ ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) {
+ ast_log(LOG_WARNING, "Domain '%s' disallowed by contact ACL (violating IP %s)\n", domain,
+ ast_sockaddr_stringify_addr(&testsa));
+ ast_string_field_set(peer, fullcontact, "");
+ ast_string_field_set(pvt, our_contact, "");
+ return PARSE_REGISTER_DENIED;
+ }
}
/* if the Contact header information copied into peer->addr matches the
* received address, and the transport types are the same, then copy socket
* data into the peer struct */
if ((peer->socket.type == pvt->socket.type) &&
- (peer->addr.sin_addr.s_addr == pvt->recv.sin_addr.s_addr) &&
- (peer->addr.sin_port == pvt->recv.sin_port)){
-
+ !ast_sockaddr_cmp(&peer->addr, &pvt->recv)) {
copy_socket_data(&peer->socket, &pvt->socket);
}
@@ -12547,18 +12591,20 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
}
}
pvt->expiry = expire;
- snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), expire, peer->username, peer->fullcontact);
+ snprintf(data, sizeof(data), "%s:%d:%s:%s", ast_sockaddr_stringify(&peer->addr),
+ expire, peer->username, peer->fullcontact);
/* Saving TCP connections is useless, we won't be able to reconnect
XXX WHY???? XXX
\todo Fix this immediately.
*/
if (!peer->rt_fromcontact && (peer->socket.type & SIP_TRANSPORT_UDP))
ast_db_put("SIP/Registry", peer->name, data);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\nPort: %d\r\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port));
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name, ast_sockaddr_stringify(&peer->addr));
/* Is this a new IP address for us? */
- if (VERBOSITY_ATLEAST(2) && inaddrcmp(&peer->addr, &oldsin)) {
- ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s port %d\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port));
+ if (VERBOSITY_ATLEAST(2) && ast_sockaddr_cmp(&peer->addr, &oldsin)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s\n", peer->name,
+ ast_sockaddr_stringify(&peer->addr));
}
sip_poke_peer(peer, 0);
register_peer_exten(peer, 1);
@@ -13084,7 +13130,7 @@ static char *terminate_uri(char *uri)
to get a challenge (nonce) then a second one with auth
- Registration requests are only matched with peers that are marked as "dynamic"
*/
-static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
+static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
struct sip_request *req, const char *uri)
{
enum check_auth_result res = AUTH_NOT_FOUND;
@@ -13100,8 +13146,8 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
c = get_in_brackets(tmp);
c = remove_uri_parameters(c);
- if (parse_uri(c, "sip:,sips:", &name, &dummy, &domain, &dummy, NULL)) {
- ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr));
+ if (parse_uri(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
+ ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_sockaddr_stringify_addr(addr));
return -1;
}
@@ -13136,14 +13182,20 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
}
}
peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE, 0);
- if (!(peer && ast_apply_ha(peer->ha, sin))) {
- /* Peer fails ACL check */
- if (peer) {
- unref_peer(peer, "register_verify: unref_peer: from find_peer operation");
- peer = NULL;
- res = AUTH_ACL_FAILED;
- } else
- res = AUTH_NOT_FOUND;
+
+ if (!ast_sockaddr_is_ipv6(addr)) {
+ struct sockaddr_in sin_tmp;
+
+ ast_sockaddr_to_sin(addr, &sin_tmp);
+ if (!(peer && ast_apply_ha(peer->ha, &sin_tmp))) {
+ /* Peer fails ACL check */
+ if (peer) {
+ unref_peer(peer, "register_verify: unref_peer: from find_peer operation");
+ peer = NULL;
+ res = AUTH_ACL_FAILED;
+ } else
+ res = AUTH_NOT_FOUND;
+ }
}
if (peer) {
@@ -13207,7 +13259,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
peer = temp_peer(name);
if (peer) {
ao2_t_link(peers, peer, "link peer into peer table");
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table");
}
ao2_lock(peer);
@@ -13236,7 +13288,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
ast_string_field_set(p, fullcontact, peer->fullcontact);
/* Say OK and ask subsystem to retransmit msg counter */
transmit_response_with_date(p, "200 OK", req);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\nPort: %d\r\n", peer->name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name, ast_sockaddr_stringify(addr));
peer->lastmsgssent = -1;
res = 0;
break;
@@ -13260,9 +13312,17 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
case AUTH_SECRET_FAILED:
/* Wrong password in authentication. Go away, don't try again until you fixed it */
transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
- if (global_authfailureevents)
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: AUTH_SECRET_FAILED\r\nAddress: %s\r\nPort: %d\r\n",
- name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ if (global_authfailureevents) {
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
+ "ChannelType: SIP\r\n"
+ "Peer: SIP/%s\r\n"
+ "PeerStatus: Rejected\r\n"
+ "Cause: AUTH_SECRET_FAILED\r\n"
+ "Address: %s\r\n"
+ "Port: %s\r\n",
+ name, ast_sockaddr_stringify_addr(addr),
+ ast_sockaddr_stringify_port(addr));
+ }
break;
case AUTH_USERNAME_MISMATCH:
/* Username and digest username does not match.
@@ -13275,9 +13335,17 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
if (sip_cfg.alwaysauthreject) {
transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
if (global_authfailureevents) {
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: %s\r\nAddress: %s\r\nPort: %d\r\n",
- name, res == AUTH_PEER_NOT_DYNAMIC ? "AUTH_PEER_NOT_DYNAMIC" : "URI_NOT_FOUND",
- ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
+ "ChannelType: SIP\r\n"
+ "Peer: SIP/%s\r\n"
+ "PeerStatus: Rejected\r\n"
+ "Cause: %s\r\n"
+ "Address: %s\r\n"
+ "Port: %s\r\n",
+ name,
+ res == AUTH_PEER_NOT_DYNAMIC ? "AUTH_PEER_NOT_DYNAMIC" : "URI_NOT_FOUND",
+ ast_sockaddr_stringify_addr(addr),
+ ast_sockaddr_stringify_port(addr));
}
} else {
/* URI not found */
@@ -13290,8 +13358,10 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
"PeerStatus: Rejected\r\n"
"Cause: AUTH_PEER_NOT_DYNAMIC\r\n"
"Address: %s\r\n"
- "Port: %d\r\n",
- name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ "Port: %s\r\n",
+ name,
+ ast_sockaddr_stringify_addr(addr),
+ ast_sockaddr_stringify_port(addr));
}
} else {
transmit_response(p, "404 Not found", &p->initreq);
@@ -13302,9 +13372,11 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
"PeerStatus: Rejected\r\n"
"Cause: %s\r\n"
"Address: %s\r\n"
- "Port: %d\r\n",
- name, (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND",
- ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ "Port: %s\r\n",
+ name,
+ (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND",
+ ast_sockaddr_stringify_addr(addr),
+ ast_sockaddr_stringify_port(addr));
}
}
}
@@ -13645,7 +13717,7 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
uri = ast_strdupa(get_in_brackets(tmp));
- if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, &dummy, NULL)) {
+ if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
return SIP_GET_DEST_INVALID_URI;
}
@@ -13662,7 +13734,7 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
if (!ast_strlen_zero(tmpf)) {
from = get_in_brackets(tmpf);
- if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL, NULL)) {
+ if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL)) {
ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
return SIP_GET_DEST_INVALID_URI;
}
@@ -14033,7 +14105,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp));
c = get_in_brackets(tmp);
- if (parse_uri(c, "sip:,sips:", &c, NULL, &a, NULL, NULL)) {
+ if (parse_uri(c, "sip:,sips:", &c, NULL, &a, NULL)) {
ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c);
return -1;
}
@@ -14104,9 +14176,9 @@ static attribute_unused void check_via_response(struct sip_pvt *p, struct sip_re
if (!strncmp(cur, "rport=", 6)) {
int port = strtol(cur+6, NULL, 10);
/* XXX add error checking */
- p->ourip.sin_port = ntohs(port);
+ ast_sockaddr_set_port(&p->ourip, port);
} else if (!strncmp(cur, "received=", 9)) {
- if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip))
+ if (ast_parse_arg(cur + 9, PARSE_ADDR, &p->ourip))
; /* XXX add error checking */
}
}
@@ -14127,14 +14199,17 @@ static void check_via(struct sip_pvt *p, struct sip_request *req)
/* Check for rport */
c = strstr(via, ";rport");
- if (c && (c[6] != '=')) /* rport query, not answer */
+ if (c && (c[6] != '=')) { /* rport query, not answer */
ast_set_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT);
+ ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT);
+ }
/* Check for maddr */
maddr = strstr(via, "maddr=");
if (maddr) {
maddr += 6;
- c = maddr + strspn(maddr, "0123456789.");
+ c = maddr + strspn(maddr, "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.:[]");
*c = '\0';
}
@@ -14144,9 +14219,6 @@ static void check_via(struct sip_pvt *p, struct sip_request *req)
c = strchr(via, ' ');
if (c) {
- struct hostent *hp;
- struct ast_hostent ahp;
-
*c = '\0';
c = ast_skip_blanks(c+1);
if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) {
@@ -14157,28 +14229,28 @@ static void check_via(struct sip_pvt *p, struct sip_request *req)
if (pt)
*pt++ = '\0'; /* remember port pointer */
- if (maddr && (hp = ast_gethostbyname(maddr, &ahp))) {
- memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
- } else {
+ if (maddr && ast_sockaddr_resolve_first(&p->sa, maddr, 0)) {
p->sa = p->recv;
}
- p->sa.sin_port = htons(port_str2int(pt, STANDARD_SIP_PORT));
+
+ ast_sockaddr_set_port(&p->sa, port_str2int(pt, STANDARD_SIP_PORT));
if (sip_debug_test_pvt(p)) {
- const struct sockaddr_in *dst = sip_real_dst(p);
- ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), sip_nat_mode(p));
+ ast_verbose("Sending to %s (%s)\n",
+ ast_sockaddr_stringify(sip_real_dst(p)),
+ sip_nat_mode(p));
}
}
}
/*! \brief Validate device authentication */
static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
- struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
+ struct sip_request *req, int sipmethod, struct ast_sockaddr *addr,
struct sip_peer **authpeer,
enum xmittype reliable, char *calleridname, char *uri2)
{
enum check_auth_result res;
- int debug=sip_debug_test_addr(sin);
+ int debug = sip_debug_test_addr(addr);
struct sip_peer *peer;
if (sipmethod == SIP_SUBSCRIBE) {
@@ -14197,19 +14269,25 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
}
if (!peer) {
- if (debug)
- ast_verbose("No matching peer for '%s' from '%s:%d'\n",
- of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ if (debug) {
+ ast_verbose("No matching peer for '%s' from '%s'\n",
+ of, ast_sockaddr_stringify(&p->recv));
+ }
return AUTH_DONT_KNOW;
}
- if (!ast_apply_ha(peer->ha, sin)) {
- ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
- unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED");
- return AUTH_ACL_FAILED;
+ if (!ast_sockaddr_is_ipv6(addr)) {
+ struct sockaddr_in sin_tmp;
+
+ ast_sockaddr_to_sin(addr, &sin_tmp);
+ if (!ast_apply_ha(peer->ha, &sin_tmp)) {
+ ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
+ unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED");
+ return AUTH_ACL_FAILED;
+ }
}
if (debug)
- ast_verbose("Found peer '%s' for '%s' from %s:%d\n",
- peer->name, of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ ast_verbose("Found peer '%s' for '%s' from %s\n",
+ peer->name, of, ast_sockaddr_stringify(&p->recv));
/* XXX what about p->prefs = peer->prefs; ? */
/* Set Frame packetization */
@@ -14346,7 +14424,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
*/
static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
int sipmethod, const char *uri, enum xmittype reliable,
- struct sockaddr_in *sin, struct sip_peer **authpeer)
+ struct ast_sockaddr *addr, struct sip_peer **authpeer)
{
char from[256] = { 0, };
char *dummy = NULL; /* dummy return value for parse_uri */
@@ -14392,7 +14470,7 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
ast_string_field_set(p, from, of);
/* ignore all fields but name */
- if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, &dummy, NULL)) {
+ if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
}
@@ -14438,7 +14516,7 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
}
}
- res = check_peer_ok(p, of, req, sipmethod, sin,
+ res = check_peer_ok(p, of, req, sipmethod, addr,
authpeer, reliable, calleridname, uri2);
if (res != AUTH_DONT_KNOW)
return res;
@@ -14467,9 +14545,9 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
/*! \brief Find user
If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced
*/
-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct sockaddr_in *sin)
+static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr)
{
- return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL);
+ return check_user_full(p, req, sipmethod, uri, reliable, addr, NULL);
}
/*! \brief Get text out of a SIP MESSAGE packet */
@@ -14674,8 +14752,8 @@ static char *sip_show_tcp(struct ast_cli_entry *e, int cmd, struct ast_cli_args
struct sip_threadinfo *th;
struct ao2_iterator i;
-#define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n"
-#define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n"
+#define FORMAT2 "%-47.47s %9.9s %6.6s\n"
+#define FORMAT "%-47.47s %-9.9s %-6.6s\n"
switch (cmd) {
case CLI_INIT:
@@ -14691,12 +14769,12 @@ static char *sip_show_tcp(struct ast_cli_entry *e, int cmd, struct ast_cli_args
if (a->argc != 3)
return CLI_SHOWUSAGE;
- ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type");
+ ast_cli(a->fd, FORMAT2, "Address", "Transport", "Type");
i = ao2_iterator_init(threadt, 0);
while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) {
- ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->tcptls_session->remote_address.sin_addr),
- ntohs(th->tcptls_session->remote_address.sin_port),
+ ast_cli(a->fd, FORMAT,
+ ast_sockaddr_stringify(&th->tcptls_session->remote_address),
get_transport(th->type),
(th->tcptls_session->client ? "Client" : "Server"));
ao2_t_ref(th, -1, "decrement ref from iterator");
@@ -14890,8 +14968,8 @@ static char *_sip_show_peers(int fd, int *total, struct mansession *s, const str
struct ao2_iterator i;
/* the last argument is left-aligned, so we don't need a size anyways */
-#define FORMAT2 "%-25.25s %-15.15s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n"
-#define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n"
+#define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n"
+#define FORMAT "%-25.25s %-39.39s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n"
char name[256];
int total_peers = 0;
@@ -14982,28 +15060,29 @@ static char *_sip_show_peers(int fd, int *total, struct mansession *s, const str
else if (pstatus == 0)
peers_mon_offline++;
else {
- if (peer->addr.sin_port == 0)
+ if (ast_sockaddr_isnull(&peer->addr) ||
+ !ast_sockaddr_port(&peer->addr)) {
peers_unmon_offline++;
- else
+ } else {
peers_unmon_online++;
+ }
}
snprintf(srch, sizeof(srch), FORMAT, name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
+ ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr),
peer->host_dynamic ? " D " : " ", /* Dynamic or not? */
ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */
- ntohs(peer->addr.sin_port), status,
+ ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status,
realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
if (!s) {/* Normal CLI list */
ast_cli(fd, FORMAT, name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
+ ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr),
peer->host_dynamic ? " D " : " ", /* Dynamic or not? */
ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */
-
- ntohs(peer->addr.sin_port), status,
+ ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status,
realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
} else { /* Manager format */
/* The names here need to be the same as other channels */
@@ -15023,8 +15102,8 @@ static char *_sip_show_peers(int fd, int *total, struct mansession *s, const str
"RealtimeDevice: %s\r\n\r\n",
idtext,
peer->name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-",
- ntohs(peer->addr.sin_port),
+ ast_sockaddr_isnull(&peer->addr) ? "-none-" : ast_sockaddr_stringify(&peer->addr),
+ ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr),
peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */
ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */
ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */
@@ -15361,17 +15440,16 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
struct sip_peer tmp;
ast_copy_string(tmp.name, name, sizeof(tmp.name));
if ((peer = ao2_t_find(peers, &tmp, OBJ_POINTER | OBJ_UNLINK, "finding to unlink from peers"))) {
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_unlink(peers_by_ip, peer, "unlinking peer from peers_by_ip also");
}
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name);
/* put it back! */
ao2_t_link(peers, peer, "link peer into peer table");
- if (peer->addr.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
-
} else
ast_cli(a->fd, "Peer '%s' pruned.\n", name);
unref_peer(peer, "sip_prune_realtime: unref_peer: tossing temp peer ptr");
@@ -15675,8 +15753,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1);
ast_cli(fd, " Timer B : %d\n", peer->timer_b);
ast_cli(fd, " ToHost : %s\n", peer->tohost);
- ast_cli(fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port));
- ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
+ ast_cli(fd, " Addr->IP : %s\n", ast_sockaddr_stringify(&peer->addr));
+ ast_cli(fd, " Defaddr->IP : %s\n", ast_sockaddr_stringify(&peer->defaddr));
ast_cli(fd, " Prim.Transp. : %s\n", get_transport(peer->socket.type));
ast_cli(fd, " Allowed.Trsp : %s\n", get_transport_list(peer->transports));
if (!ast_strlen_zero(sip_cfg.regcontext))
@@ -15781,8 +15859,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
/* - is enumerated */
astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
astman_append(s, "ToHost: %s\r\n", peer->tohost);
- astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port));
- astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
+ astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", ast_sockaddr_stringify_addr(&peer->addr), ast_sockaddr_port(&peer->addr));
+ astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_sockaddr_stringify_addr(&peer->defaddr), ast_sockaddr_port(&peer->defaddr));
astman_append(s, "Default-Username: %s\r\n", peer->username);
if (!ast_strlen_zero(sip_cfg.regcontext))
astman_append(s, "RegExtension: %s\r\n", peer->regexten);
@@ -15983,8 +16061,8 @@ static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
/*! \brief Show SIP Registry (registrations with other SIP proxies */
static char *sip_show_registry(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
-#define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n"
-#define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n"
+#define FORMAT2 "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n"
+#define FORMAT "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n"
char host[80];
char user[80];
char tmpdat[256];
@@ -16090,8 +16168,12 @@ static int show_chanstats_cb(void *__cur, void *__arg, int flags)
return 0; /* don't care, we scan all channels */
if (!cur->rtp) {
- if (sipdebug)
- ast_cli(fd, "%-15.15s %-11.11s (inv state: %s) -- %s\n", ast_inet_ntoa(cur->sa.sin_addr), cur->callid, invitestate2string[cur->invitestate].desc, "-- No RTP active");
+ if (sipdebug) {
+ ast_cli(fd, "%-15.15s %-11.11s (inv state: %s) -- %s\n",
+ ast_sockaddr_stringify_addr(&cur->sa), cur->callid,
+ invitestate2string[cur->invitestate].desc,
+ "-- No RTP active");
+ }
return 0; /* don't care, we scan all channels */
}
@@ -16108,7 +16190,7 @@ static int show_chanstats_cb(void *__cur, void *__arg, int flags)
}
ast_cli(fd, FORMAT,
- ast_inet_ntoa(cur->sa.sin_addr),
+ ast_sockaddr_stringify_addr(&cur->sa),
cur->callid,
durbuf,
stats.rxcount > (unsigned int) 100000 ? (unsigned int) (stats.rxcount)/(unsigned int) 1000 : stats.rxcount,
@@ -16183,22 +16265,15 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
return CLI_SHOWUSAGE;
ast_cli(a->fd, "\n\nGlobal Settings:\n");
ast_cli(a->fd, "----------------\n");
- ast_cli(a->fd, " UDP SIP Port: %d\n", ntohs(bindaddr.sin_port));
- ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_inet_ntoa(bindaddr.sin_addr));
- ast_cli(a->fd, " TCP SIP Port: ");
- if (sip_tcp_desc.local_address.sin_family == AF_INET) {
- ast_cli(a->fd, "%d\n", ntohs(sip_tcp_desc.local_address.sin_port));
- ast_cli(a->fd, " TCP Bindaddress: %s\n", ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr));
- } else {
- ast_cli(a->fd, "Disabled\n");
- }
- ast_cli(a->fd, " TLS SIP Port: ");
- if (default_tls_cfg.enabled != FALSE) {
- ast_cli(a->fd, "%d\n", ntohs(sip_tls_desc.local_address.sin_port));
- ast_cli(a->fd, " TLS Bindaddress: %s\n", ast_inet_ntoa(sip_tls_desc.local_address.sin_addr));
- } else {
- ast_cli(a->fd, "Disabled\n");
- }
+ ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_sockaddr_stringify(&bindaddr));
+ ast_cli(a->fd, " TCP SIP Bindaddress: %s\n",
+ sip_cfg.tcp_enabled != FALSE ?
+ ast_sockaddr_stringify(&sip_tcp_desc.local_address) :
+ "Disabled");
+ ast_cli(a->fd, " TLS SIP Bindaddress: %s\n",
+ default_tls_cfg.enabled != FALSE ?
+ ast_sockaddr_stringify(&sip_tls_desc.local_address) :
+ "Disabled");
ast_cli(a->fd, " Videosupport: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT)));
ast_cli(a->fd, " Textsupport: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT)));
ast_cli(a->fd, " Ignore SDP sess. ver.: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION)));
@@ -16263,8 +16338,8 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
/* determine if/how SIP address can be remapped */
if (localaddr == NULL)
msg = "Disabled, no localnet list";
- else if (externip.sin_addr.s_addr == 0)
- msg = "Disabled, externip is 0.0.0.0";
+ else if (ast_sockaddr_isnull(&externip))
+ msg = "Disabled";
else if (stunaddr.sin_addr.s_addr != 0)
msg = "Enabled using STUN";
else if (!ast_strlen_zero(externhost))
@@ -16273,9 +16348,9 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
msg = "Enabled using externip";
ast_cli(a->fd, " SIP address remapping: %s\n", msg);
ast_cli(a->fd, " Externhost: %s\n", S_OR(externhost, "<none>"));
- ast_cli(a->fd, " Externip: %s:%d\n", ast_inet_ntoa(externip.sin_addr), ntohs(externip.sin_port));
+ ast_cli(a->fd, " Externip: %s\n", ast_sockaddr_stringify(&externip));
ast_cli(a->fd, " Externrefresh: %d\n", externrefresh);
- ast_cli(a->fd, " Internal IP: %s:%d\n", ast_inet_ntoa(internip.sin_addr), ntohs(internip.sin_port));
+ ast_cli(a->fd, " Internal IP: %s\n", ast_sockaddr_stringify(&internip));
{
struct ast_ha *d;
const char *prefix = "Localnet:";
@@ -16437,7 +16512,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
{
struct sip_pvt *cur = __cur;
struct __show_chan_arg *arg = __arg;
- const struct sockaddr_in *dst = sip_real_dst(cur);
+ const struct ast_sockaddr *dst = sip_real_dst(cur);
/* XXX indentation preserved to reduce diff. Will be fixed later */
if (cur->subscribed == NONE && !arg->subscriptions) {
@@ -16445,7 +16520,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
char formatbuf[SIPBUFSIZE/2];
- ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr),
+ ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0),
@@ -16461,7 +16536,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
struct ast_str *mailbox_str = ast_str_alloca(512);
if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
- ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr),
+ ast_cli(arg->fd, FORMAT4, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
/* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
@@ -16704,11 +16779,19 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
ast_cli(a->fd, " T.38 support %s\n", AST_CLI_YESNO(cur->udptl != NULL));
ast_cli(a->fd, " Video support %s\n", AST_CLI_YESNO(cur->vrtp != NULL));
ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate);
- ast_cli(a->fd, " Theoretical Address: %s:%d\n", ast_inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port));
- ast_cli(a->fd, " Received Address: %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port));
+ ast_cli(a->fd, " Theoretical Address: %s\n", ast_sockaddr_stringify(&cur->sa));
+ ast_cli(a->fd, " Received Address: %s\n", ast_sockaddr_stringify(&cur->recv));
ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer));
ast_cli(a->fd, " Force rport: %s\n", AST_CLI_YESNO(ast_test_flag(&cur->flags[0], SIP_NAT_FORCE_RPORT)));
- ast_cli(a->fd, " Audio IP: %s %s\n", ast_inet_ntoa(cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip.sin_addr), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" );
+ if (ast_sockaddr_isnull(&cur->redirip)) {
+ ast_cli(a->fd,
+ " Audio IP: %s (local)\n",
+ ast_sockaddr_stringify_addr(&cur->ourip));
+ } else {
+ ast_cli(a->fd,
+ " Audio IP: %s (Outside bridge)\n",
+ ast_sockaddr_stringify_addr(&cur->redirip));
+ }
ast_cli(a->fd, " Our Tag: %s\n", cur->tag);
ast_cli(a->fd, " Their Tag: %s\n", cur->theirtag);
ast_cli(a->fd, " SIP User agent: %s\n", cur->useragent);
@@ -17045,27 +17128,11 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
/*! \brief Enable SIP Debugging for a single IP */
static char *sip_do_debug_ip(int fd, const char *arg)
{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p;
-
- p = ast_strdupa(arg);
- strsep(&p, ":");
- if (p)
- port = atoi(p);
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL)
+ if (ast_sockaddr_resolve_first(&debugaddr, arg, 0)) {
return CLI_SHOWUSAGE;
+ }
- debugaddr.sin_family = AF_INET;
- memcpy(&debugaddr.sin_addr, hp->h_addr, sizeof(debugaddr.sin_addr));
- debugaddr.sin_port = htons(port);
- if (port == 0)
- ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_inet_ntoa(debugaddr.sin_addr));
- else
- ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(debugaddr.sin_addr), port);
-
+ ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify_addr(&debugaddr));
sipdebug |= sip_debug_console;
return CLI_SUCCESS;
@@ -17077,14 +17144,11 @@ static char *sip_do_debug_peer(int fd, const char *arg)
struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE, 0);
if (!peer)
ast_cli(fd, "No such peer '%s'\n", arg);
- else if (peer->addr.sin_addr.s_addr == 0)
+ else if (ast_sockaddr_isnull(&peer->addr))
ast_cli(fd, "Unable to get IP address of peer '%s'\n", arg);
else {
- debugaddr.sin_family = AF_INET;
- debugaddr.sin_addr = peer->addr.sin_addr;
- debugaddr.sin_port = peer->addr.sin_port;
- ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n",
- ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port));
+ ast_sockaddr_copy(&debugaddr, &peer->addr);
+ ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify_addr(&debugaddr));
sipdebug |= sip_debug_console;
}
if (peer)
@@ -17394,7 +17458,7 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d
else if (!ast_strlen_zero(p->uri))
ast_copy_string(uri, p->uri, sizeof(uri));
else
- snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_inet_ntoa(p->sa.sin_addr));
+ snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host(&p->sa));
snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random());
@@ -17548,9 +17612,9 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
return -1;
if (!strcasecmp(colname, "ip")) {
- ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
+ ast_copy_string(buf, ast_sockaddr_stringify_addr(&peer->addr), len);
} else if (!strcasecmp(colname, "port")) {
- snprintf(buf, len, "%d", ntohs(peer->addr.sin_port));
+ snprintf(buf, len, "%d", ast_sockaddr_port(&peer->addr));
} else if (!strcasecmp(colname, "status")) {
peer_status(peer, buf, len);
} else if (!strcasecmp(colname, "language")) {
@@ -17659,9 +17723,9 @@ static int function_sipchaninfo_read(struct ast_channel *chan, const char *cmd,
}
if (!strcasecmp(data, "peerip")) {
- ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", len);
+ ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->sa), len);
} else if (!strcasecmp(data, "recvip")) {
- ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", len);
+ ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->recv), len);
} else if (!strcasecmp(data, "from")) {
ast_copy_string(buf, p->from, len);
} else if (!strcasecmp(data, "uri")) {
@@ -18458,7 +18522,7 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest
}
ast_string_field_set(p, theirtag, NULL);
if (ast_strlen_zero(p->authname)) {
- ast_log(LOG_WARNING, "Asked to authenticate NOTIFY to %s:%d but we have no matching peer or realm auth!\n", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ ast_log(LOG_WARNING, "Asked to authenticate NOTIFY to %s but we have no matching peer or realm auth!\n", ast_sockaddr_stringify(&p->recv));
pvt_set_needdestroy(p, "unable to authenticate NOTIFY");
}
if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) {
@@ -18553,8 +18617,8 @@ static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest,
case 401: /* Not www-authorized on SIP method */
case 407: /* Proxy auth */
if (ast_strlen_zero(p->authname)) {
- ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n",
- ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ ast_log(LOG_WARNING, "Asked to authenticate REFER to %s but we have no matching peer or realm auth!\n",
+ ast_sockaddr_stringify(&p->recv));
if (p->owner) {
ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
}
@@ -18985,8 +19049,8 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
if (p->options)
p->options->auth_type = resp;
if (ast_strlen_zero(p->authname)) {
- ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n",
- msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
+ msg, ast_sockaddr_stringify(&p->recv));
pvt_set_needdestroy(p, "unable to authenticate BYE");
} else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) {
ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From"));
@@ -19093,7 +19157,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
else if (sipmethod == SIP_REFER)
handle_response_refer(p, resp, rest, req, seqno);
else
- ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg);
+ ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_sockaddr_stringify(&p->sa), msg);
break;
case 603: /* Declined transfer */
if (sipmethod == SIP_REFER) {
@@ -19105,7 +19169,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
if ((resp >= 300) && (resp < 700)) {
/* Fatal response */
if ((resp != 487))
- ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr));
+ ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa));
if (sipmethod == SIP_INVITE)
stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
@@ -19177,7 +19241,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
}
}
} else
- ast_log(LOG_NOTICE, "Don't know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_inet_ntoa(p->sa.sin_addr));
+ ast_log(LOG_NOTICE, "Don't know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_sockaddr_stringify(&p->sa));
}
} else {
/* Responses to OUTGOING SIP requests on INCOMING calls
@@ -19286,7 +19350,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
}
if ((resp >= 300) && (resp < 700)) {
if ((resp != 487))
- ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr));
+ ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa));
switch(resp) {
case 415: /* Unsupported media type */
case 488: /* Not acceptable here - codec error */
@@ -19637,7 +19701,7 @@ static int handle_cc_notify(struct sip_pvt *pvt, struct sip_request *req)
}
/*! \brief Handle incoming notifications */
-static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e)
+static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e)
{
/* This is mostly a skeleton for future improvements */
/* Mostly created to return proper answers on notifications on outbound REFER's */
@@ -19867,7 +19931,7 @@ static int handle_request_options(struct sip_pvt *p, struct sip_request *req)
handle_request_do(), we unlock p->owner before the masq. By setting nounlock
we are indicating to handle_request_do() that we have already unlocked the owner.
*/
-static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *nounlock)
+static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock)
{
int earlyreplace = 0;
int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */
@@ -20356,7 +20420,7 @@ static int handle_request_update(struct sip_pvt *p, struct sip_request *req)
* plan but try to find the active call and masquerade
* into it
*/
-static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, const char *e, int *nounlock)
+static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *recount, const char *e, int *nounlock)
{
int res = 1;
int gotdest;
@@ -20382,7 +20446,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
char exten[AST_MAX_EXTENSION];
char context[AST_MAX_CONTEXT];
} pickup = {
- .exten = "",
+ .exten = "",
};
st_ref = SESSION_TIMER_REFRESHER_AUTO;
@@ -20485,17 +20549,17 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* We already have a pending invite. Sorry. You are on hold. */
p->glareinvite = seqno;
if (p->rtp && find_sdp(req)) {
- struct sockaddr_in sin;
- if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &sin)) {
+ struct ast_sockaddr addr;
+ if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &addr)) {
ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n");
} else {
- ast_rtp_instance_set_alt_remote_address(p->rtp, &sin);
+ ast_rtp_instance_set_alt_remote_address(p->rtp, &addr);
}
if (p->vrtp) {
- if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &sin)) {
+ if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &addr)) {
ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n");
} else {
- ast_rtp_instance_set_alt_remote_address(p->vrtp, &sin);
+ ast_rtp_instance_set_alt_remote_address(p->vrtp, &addr);
}
}
}
@@ -20700,7 +20764,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* Handle authentication if this is our first invite */
int cc_recall_core_id = -1;
set_pvt_allowed_methods(p, req);
- res = check_user_full(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin, &authpeer);
+ res = check_user_full(p, req, SIP_INVITE, e, XMIT_RELIABLE, addr, &authpeer);
if (res == AUTH_CHALLENGE_SENT) {
p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */
res = 0;
@@ -20728,7 +20792,10 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer");
/* If T38 is needed but not present, then make it magically appear */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl) {
- if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
+ struct sockaddr_in bindaddr_sin_tmp;
+
+ ast_sockaddr_to_sin(&bindaddr, &bindaddr_sin_tmp);
+ if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_sin_tmp.sin_addr))) {
p->t38_maxdatagram = global_t38_maxdatagram;
set_t38_capabilities(p);
} else {
@@ -21030,7 +21097,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* Go and take over the target call */
if (sipdebug)
ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid);
- res = handle_invite_replaces(p, req, debug, seqno, sin, nounlock);
+ res = handle_invite_replaces(p, req, debug, seqno, addr, nounlock);
refer_locked = 0;
goto request_invite_cleanup;
}
@@ -21892,7 +21959,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
if (!ast_strlen_zero(get_header(req, "Also"))) {
ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n",
- ast_inet_ntoa(p->recv.sin_addr));
+ ast_sockaddr_stringify(&p->recv));
if (ast_strlen_zero(p->context))
ast_string_field_set(p, context, sip_cfg.default_context);
res = get_also_info(p, req);
@@ -21910,7 +21977,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
ast_queue_hangup(p->owner);
}
} else {
- ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_inet_ntoa(p->recv.sin_addr));
+ ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_sockaddr_stringify(&p->recv));
if (p->owner)
ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR);
}
@@ -22361,7 +22428,7 @@ static int handle_sip_publish_remove(struct sip_pvt *p, struct sip_request *req,
return res;
}
-static int handle_request_publish(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, const int seqno, const char *uri)
+static int handle_request_publish(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const int seqno, const char *uri)
{
const char *etag = get_header(req, "SIP-If-Match");
const char *event = get_header(req, "Event");
@@ -22382,7 +22449,7 @@ static int handle_request_publish(struct sip_pvt *p, struct sip_request *req, st
return -1;
}
- auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_RELIABLE, sin);
+ auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_RELIABLE, addr);
if (auth_result == AUTH_CHALLENGE_SENT) {
p->lastinvite = seqno;
return 0;
@@ -22501,7 +22568,7 @@ static int handle_cc_subscribe(struct sip_pvt *p, struct sip_request *req)
}
/*! \brief Handle incoming SUBSCRIBE request */
-static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e)
+static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e)
{
int gotdest = 0;
int res = 0;
@@ -22582,7 +22649,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
event = (char *) eventheader; /* XXX is this legal ? */
/* Handle authentication */
- res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer);
+ res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, addr, &authpeer);
/* if an authentication response was sent, we are done here */
if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */
return 0;
@@ -22782,7 +22849,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
- ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension.\n", p->exten, p->context, ast_inet_ntoa(p->sa.sin_addr));
+ ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension.\n", p->exten, p->context, ast_sockaddr_stringify(&p->sa));
transmit_response(p, "404 Not found", req);
pvt_set_needdestroy(p, "no extension for SUBSCRIBE");
return 0;
@@ -22836,7 +22903,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
}
/*! \brief Handle incoming REGISTER request */
-static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, const char *e)
+static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
{
enum check_auth_result res;
@@ -22845,7 +22912,7 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
if (sipdebug)
ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
check_via(p, req);
- if ((res = register_verify(p, sin, req, e)) < 0) {
+ if ((res = register_verify(p, addr, req, e)) < 0) {
const char *reason;
switch (res) {
@@ -22875,7 +22942,7 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
break;
}
ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n",
- get_header(req, "To"), ast_inet_ntoa(sin->sin_addr),
+ get_header(req, "To"), ast_sockaddr_stringify(addr),
reason);
append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason);
} else
@@ -22892,7 +22959,7 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
/*! \brief Handle incoming SIP requests (methods)
\note This is where all incoming requests go first */
/* called with p and p->owner locked */
-static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock)
+static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock)
{
/* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things
relatively static */
@@ -23069,7 +23136,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
res = handle_request_options(p, req);
break;
case SIP_INVITE:
- res = handle_request_invite(p, req, debug, seqno, sin, recount, e, nounlock);
+ res = handle_request_invite(p, req, debug, seqno, addr, recount, e, nounlock);
break;
case SIP_REFER:
res = handle_request_refer(p, req, debug, seqno, nounlock);
@@ -23084,13 +23151,13 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
res = handle_request_message(p, req);
break;
case SIP_PUBLISH:
- res = handle_request_publish(p, req, sin, seqno, e);
+ res = handle_request_publish(p, req, addr, seqno, e);
break;
case SIP_SUBSCRIBE:
- res = handle_request_subscribe(p, req, sin, seqno, e);
+ res = handle_request_subscribe(p, req, addr, seqno, e);
break;
case SIP_REGISTER:
- res = handle_request_register(p, req, sin, e);
+ res = handle_request_register(p, req, addr, e);
break;
case SIP_INFO:
if (req->debug)
@@ -23101,7 +23168,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
transmit_response(p, "200 OK", req);
break;
case SIP_NOTIFY:
- res = handle_request_notify(p, req, sin, seqno, e);
+ res = handle_request_notify(p, req, addr, seqno, e);
break;
case SIP_UPDATE:
res = handle_request_update(p, req);
@@ -23134,7 +23201,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
default:
transmit_response_with_allow(p, "501 Method Not Implemented", req, 0);
ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n",
- cmd, ast_inet_ntoa(p->sa.sin_addr));
+ cmd, ast_sockaddr_stringify(&p->sa));
/* If this is some new method, and we don't have a call, destroy it now */
if (!p->initreq.headers) {
pvt_set_needdestroy(p, "unimplemented method");
@@ -23241,13 +23308,12 @@ static int queue_request(struct sip_pvt *p, const struct sip_request *req)
static int sipsock_read(int *id, int fd, short events, void *ignore)
{
struct sip_request req;
- struct sockaddr_in sin = { 0, };
+ struct ast_sockaddr addr;
int res;
- socklen_t len = sizeof(sin);
static char readbuf[65535];
memset(&req, 0, sizeof(req));
- res = recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&sin, &len);
+ res = ast_recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, &addr);
if (res < 0) {
#if !defined(__FreeBSD__)
if (errno == EAGAIN)
@@ -23273,9 +23339,9 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
req.socket.fd = sipsock;
set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
req.socket.tcptls_session = NULL;
- req.socket.port = bindaddr.sin_port;
+ req.socket.port = htons(ast_sockaddr_port(&bindaddr));
- handle_request_do(&req, &sin);
+ handle_request_do(&req, &addr);
deinit_req(&req);
return 1;
@@ -23285,21 +23351,20 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
This is used for all transports (udp, tcp and tcp/tls)
*/
-static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
+static int handle_request_do(struct sip_request *req, struct ast_sockaddr *addr)
{
struct sip_pvt *p;
int recount = 0;
int nounlock = 0;
int lockretry;
- if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */
+ if (sip_debug_test_addr(addr)) /* Set the debug flag early on packet level */
req->debug = 1;
if (sip_cfg.pedanticsipchecking)
req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */
if (req->debug) {
- ast_verbose("\n<--- SIP read from %s:%s:%d --->\n%s\n<------------->\n",
- get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr),
- ntohs(sin->sin_port), req->data->str);
+ ast_verbose("\n<--- SIP read from %s:%s --->\n%s\n<------------->\n",
+ get_transport(req->socket.type), ast_sockaddr_stringify(addr), req->data->str);
}
if (parse_request(req) == -1) { /* Bad packet, can't parse */
@@ -23321,7 +23386,7 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
ast_mutex_lock(&netlock);
/* Find the active SIP dialog or create a new one */
- p = find_call(req, sin, req->method); /* returns p locked */
+ p = find_call(req, addr, req->method); /* returns p locked */
if (p == NULL) {
ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req->len);
ast_mutex_unlock(&netlock);
@@ -23343,7 +23408,7 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
usleep(1);
}
}
- p->recv = *sin;
+ ast_sockaddr_copy(&p->recv, addr);
if (p->do_history) /* This is a request or response, note what it was for */
append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2));
@@ -23378,7 +23443,7 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
process_request_queue(p, &recount, &nounlock);
}
- if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) {
+ if (handle_incoming(p, req, addr, &recount, &nounlock) == -1) {
/* Request failed */
ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
}
@@ -23411,9 +23476,9 @@ static int sip_standard_port(enum sip_transport type, int port)
static int threadinfo_locate_cb(void *obj, void *arg, int flags)
{
struct sip_threadinfo *th = obj;
- struct sockaddr_in *s = arg;
+ struct ast_sockaddr *s = arg;
- if (!inaddrcmp(&th->tcptls_session->remote_address, s)) {
+ if (!ast_sockaddr_cmp(s, &th->tcptls_session->remote_address)) {
return CMP_MATCH | CMP_STOP;
}
@@ -23425,7 +23490,7 @@ static int threadinfo_locate_cb(void *obj, void *arg, int flags)
*
* \note This function returns an astobj2 reference
*/
-static struct ast_tcptls_session_instance *sip_tcp_locate(struct sockaddr_in *s)
+static struct ast_tcptls_session_instance *sip_tcp_locate(struct ast_sockaddr *s)
{
struct sip_threadinfo *th;
struct ast_tcptls_session_instance *tcptls_instance = NULL;
@@ -23438,6 +23503,20 @@ static struct ast_tcptls_session_instance *sip_tcp_locate(struct sockaddr_in *s)
return tcptls_instance;
}
+/*!
+ * \brief Helper for dns resolution to filter by address family.
+ *
+ * \note return 0 if addr is [::] else it returns addr's family.
+ */
+int get_address_family_filter(const struct ast_sockaddr *addr)
+{
+ if (ast_sockaddr_is_ipv6(addr) && ast_sockaddr_is_any(addr)) {
+ return 0;
+ }
+
+ return addr->ss.ss_family;
+}
+
/*! \todo Get socket for dialog, prepare if needed, and return file handle */
static int sip_prepare_socket(struct sip_pvt *p)
{
@@ -23445,11 +23524,8 @@ static int sip_prepare_socket(struct sip_pvt *p)
static const char name[] = "SIP socket";
struct sip_threadinfo *th = NULL;
struct ast_tcptls_session_instance *tcptls_session;
- struct ast_tcptls_session_args tmp_ca = {
- .name = name,
- .accept_fd = -1,
- };
struct ast_tcptls_session_args *ca;
+ struct ast_sockaddr sa_tmp;
/* check to see if a socket is already active */
if ((s->fd != -1) && (s->type == SIP_TRANSPORT_UDP)) {
@@ -23483,8 +23559,8 @@ static int sip_prepare_socket(struct sip_pvt *p)
*/
/* 1. check for existing threads */
- tmp_ca.remote_address = *(sip_real_dst(p));
- if ((tcptls_session = sip_tcp_locate(&tmp_ca.remote_address))) {
+ ast_sockaddr_copy(&sa_tmp, sip_real_dst(p));
+ if ((tcptls_session = sip_tcp_locate(&sa_tmp))) {
s->fd = tcptls_session->fd;
if (s->tcptls_session) {
ao2_ref(s->tcptls_session, -1);
@@ -23504,7 +23580,7 @@ static int sip_prepare_socket(struct sip_pvt *p)
goto create_tcptls_session_fail;
}
ca->accept_fd = -1;
- ca->remote_address = *(sip_real_dst(p));
+ ast_sockaddr_copy(&ca->remote_address,sip_real_dst(p));
/* if type is TLS, we need to create a tls cfg for this session arg */
if (s->type == SIP_TRANSPORT_TLS) {
if (!(ca->tls_cfg = ast_calloc(1, sizeof(*ca->tls_cfg)))) {
@@ -23606,7 +23682,7 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *e
return 0;
/* Do we have an IP address? If not, skip this peer */
- if (!peer->addr.sin_addr.s_addr && !peer->defaddr.sin_addr.s_addr)
+ if (ast_sockaddr_isnull(&peer->addr) || ast_sockaddr_isnull(&peer->defaddr))
return 0;
if (event) {
@@ -23642,7 +23718,7 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *e
return 0;
}
/* Recalculate our side, and recalculate Call ID */
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
build_via(p);
ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
build_callid_pvt(p);
@@ -23672,7 +23748,7 @@ static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
return;
/* If the call is not in UP state or redirected outside Asterisk, no need to check timers */
- if (dialog->owner->_state != AST_STATE_UP || dialog->redirip.sin_addr.s_addr)
+ if (dialog->owner->_state != AST_STATE_UP || !ast_sockaddr_isnull(&dialog->redirip))
return;
/* If the call is involved in a T38 fax session do not check RTP timeout */
@@ -24179,7 +24255,7 @@ static int sip_poke_peer(struct sip_peer *peer, int force)
struct sip_pvt *p;
int xmitres = 0;
- if ((!peer->maxms && !force) || !peer->addr.sin_addr.s_addr) {
+ if ((!peer->maxms && !force) || ast_sockaddr_isnull(&peer->addr)) {
/* IF we have no IP, or this isn't to be monitored, return
immediately after clearing things out */
AST_SCHED_DEL_UNREF(sched, peer->pokeexpire,
@@ -24218,10 +24294,10 @@ static int sip_poke_peer(struct sip_peer *peer, int force)
if (!ast_strlen_zero(peer->tohost))
ast_string_field_set(p, tohost, peer->tohost);
else
- ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
+ ast_string_field_set(p, tohost, ast_sockaddr_stringify_host(&peer->addr));
/* Recalculate our side, and recalculate Call ID */
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
build_via(p);
ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
build_callid_pvt(p);
@@ -24309,7 +24385,7 @@ static int sip_devicestate(void *data)
* hosts out of memory.
*/
if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE, 0))) {
- if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
+ if (!(ast_sockaddr_isnull(&p->addr) && ast_sockaddr_isnull(&p->defaddr))) {
/* we have an address for the peer */
/* Check status in this order
@@ -24380,7 +24456,7 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
char dialstring[256];
char *remote_address;
enum sip_transport transport = 0;
- struct sockaddr_in remote_address_sin = { .sin_family = AF_INET };
+ struct ast_sockaddr remote_address_sa = { {0,} };
format_t oldformat = format;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(peerorhost);
@@ -24482,25 +24558,15 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
}
if (!ast_strlen_zero(remote_address)) {
- struct hostent *hp;
- struct ast_hostent ahp;
- char *port;
- unsigned short port_num = transport & SIP_TRANSPORT_TLS ? STANDARD_TLS_PORT : STANDARD_SIP_PORT;
-
- port = strchr(remote_address, ':');
- if (port) {
- *port++ = '\0';
- if (sscanf(port, "%hu", &port_num) != 1) {
- ast_log(LOG_WARNING, "Invalid port number provided in remote address. Using %hu\n", port_num);
- }
- }
-
- hp = ast_gethostbyname(remote_address, &ahp);
- if (!hp) {
+ if (ast_sockaddr_resolve_first(&remote_address_sa, remote_address, 0)) {
ast_log(LOG_WARNING, "Unable to find IP address for host %s. We will not use this remote IP address\n", remote_address);
} else {
- memcpy(&remote_address_sin.sin_addr, hp->h_addr, sizeof(remote_address_sin.sin_addr));
- remote_address_sin.sin_port = htons(port_num);
+ if (!ast_sockaddr_port(&remote_address_sa)) {
+ ast_sockaddr_set_port(&remote_address_sa,
+ transport & SIP_TRANSPORT_TLS ?
+ STANDARD_TLS_PORT :
+ STANDARD_SIP_PORT);
+ }
}
}
@@ -24511,7 +24577,7 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
ext = extension (user part of URI)
dnid = destination of the call (applies to the To: header)
*/
- if (create_addr(p, host, NULL, 1, &remote_address_sin)) {
+ if (create_addr(p, host, NULL, 1, &remote_address_sa)) {
*cause = AST_CAUSE_UNREGISTERED;
ast_debug(3, "Cant create SIP call - target device not registered\n");
dialog_unlink_all(p, TRUE, TRUE);
@@ -24522,7 +24588,7 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
if (ast_strlen_zero(p->peername) && ext)
ast_string_field_set(p, peername, ext);
/* Recalculate our side, and recalculate Call ID */
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
build_via(p);
ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
build_callid_pvt(p);
@@ -24961,7 +25027,6 @@ static void set_peer_defaults(struct sip_peer *peer)
*/
peer->expire = -1;
peer->pokeexpire = -1;
- peer->addr.sin_port = htons(STANDARD_SIP_PORT);
set_socket_transport(&peer->socket, SIP_TRANSPORT_UDP);
}
peer->type = SIP_TYPE_PEER;
@@ -24974,8 +25039,8 @@ static void set_peer_defaults(struct sip_peer *peer)
ast_string_field_set(peer, mohinterpret, default_mohinterpret);
ast_string_field_set(peer, mohsuggest, default_mohsuggest);
ast_string_field_set(peer, engine, default_engine);
- peer->addr.sin_family = AF_INET;
- peer->defaddr.sin_family = AF_INET;
+ ast_sockaddr_setnull(&peer->addr);
+ ast_sockaddr_setnull(&peer->defaddr);
peer->capability = sip_cfg.capability;
peer->maxcallbitrate = default_maxcallbitrate;
peer->rtptimeout = global_rtptimeout;
@@ -25262,41 +25327,58 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
} else if (!strcasecmp(v->name, "fromuser")) {
ast_string_field_set(peer, fromuser, v->value);
} else if (!strcasecmp(v->name, "outboundproxy")) {
- char *port, *next, *force, *proxyname;
- int forceopt = FALSE;
- /* Set peer channel variable */
- next = proxyname = ast_strdupa(v->value);
- if ((port = strchr(proxyname, ':'))) {
- *port++ = '\0';
- next = port;
+ char *tok, *proxyname;
+
+ if (ast_strlen_zero(v->value)) {
+ ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno);
+ continue;
}
- if ((force = strchr(next, ','))) {
- *force++ = '\0';
- forceopt = strcmp(force, "force");
+
+ peer->outboundproxy =
+ ao2_alloc(sizeof(*peer->outboundproxy), NULL);
+
+ tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ","));
+
+ sip_parse_host(tok, v->lineno, &proxyname,
+ &peer->outboundproxy->port,
+ &peer->outboundproxy->transport);
+
+ tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ","));
+
+ if ((tok = strtok(NULL, ","))) {
+ peer->outboundproxy->force = !strncasecmp(ast_skip_blanks(tok), "force", 5);
+ } else {
+ peer->outboundproxy->force = FALSE;
+ }
+
+ if (ast_strlen_zero(proxyname)) {
+ ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno);
+ sip_cfg.outboundproxy.name[0] = '\0';
+ continue;
}
- /* Allocate proxy object */
- peer->outboundproxy = proxy_allocate(proxyname, port, forceopt);
+
+ ast_copy_string(peer->outboundproxy->name, proxyname, sizeof(peer->outboundproxy->name));
+
+ proxy_update(peer->outboundproxy);
} else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
if (!found || !peer->host_dynamic) {
/* Initialize stuff if this is a new peer, or if it used to
* not be dynamic before the reload. */
- memset(&peer->addr.sin_addr, 0, 4);
- peer->addr.sin_port = 0;
+ ast_sockaddr_setnull(&peer->addr);
}
peer->host_dynamic = TRUE;
} else {
/* Non-dynamic. Make sure we become that way if we're not */
AST_SCHED_DEL_UNREF(sched, peer->expire,
unref_peer(peer, "removing register expire ref"));
- /* the port will either be set to a default value or a config specified value once all option parsing is complete */
- peer->addr.sin_port = 0;
peer->host_dynamic = FALSE;
srvlookup = v->value;
if (global_dynamic_exclude_static) {
int err = 0;
- sip_cfg.contact_ha = ast_append_ha("deny", (char *)ast_inet_ntoa(peer->addr.sin_addr), sip_cfg.contact_ha, &err);
+ sip_cfg.contact_ha = ast_append_ha("deny", ast_sockaddr_stringify(&peer->addr),
+ sip_cfg.contact_ha, &err);
if (err) {
ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
}
@@ -25504,7 +25586,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (realtime && !strcasecmp(v->name, "lastms")) {
sscanf(v->value, "%30d", &peer->lastms);
} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
- inet_aton(v->value, &(peer->addr.sin_addr));
+ ast_sockaddr_parse(&peer->addr, v->value, PARSE_PORT_FORBID);
} else if (realtime && !strcasecmp(v->name, "fullcontact")) {
if (alt_fullcontact && !alt) {
/* Reset, because the alternate also has a fullcontact and we
@@ -25605,12 +25687,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
set_socket_transport(&peer->socket, peer->default_outbound_transport);
}
- if (port && !realtime && peer->host_dynamic) {
- peer->defaddr.sin_port = htons(port);
- } else if (port) {
- peer->addr.sin_port = htons(port);
- }
-
if (ast_str_strlen(fullcontact)) {
ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
peer->rt_fromcontact = TRUE;
@@ -25622,7 +25698,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
* specified, use that address instead. */
/* XXX May need to revisit the final argument; does the realtime DB store whether
* the original contact was over TLS or not? XXX */
- if (!ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT) || !peer->addr.sin_addr.s_addr) {
+ if (!ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT) || ast_sockaddr_isnull(&peer->addr)) {
__set_address_from_contact(fullcontact->str, &peer->addr, 0);
}
}
@@ -25639,20 +25715,32 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
snprintf(transport, sizeof(transport), "_sip._%s", get_transport(peer->socket.type));
+ peer->addr.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL)) {
ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name);
unref_peer(peer, "getting rid of a peer pointer");
return NULL;
}
- ast_string_field_set(peer, tohost, srvlookup);
+ ast_string_field_set(peer, tohost, peer->dnsmgr ? srvlookup :
+ ast_sockaddr_stringify_host(&peer->addr));
+ }
+
+ if (port && !realtime && peer->host_dynamic) {
+ ast_sockaddr_set_port(&peer->defaddr, port);
+ } else if (port) {
+ ast_sockaddr_set_port(&peer->addr, port);
}
- if (!peer->addr.sin_port) {
- peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
+ if (ast_sockaddr_port(&peer->addr) == 0) {
+ ast_sockaddr_set_port(&peer->addr,
+ (peer->socket.type & SIP_TRANSPORT_TLS) ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
}
- if (!peer->defaddr.sin_port) {
- peer->defaddr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
+ if (ast_sockaddr_port(&peer->defaddr) == 0) {
+ ast_sockaddr_set_port(&peer->defaddr,
+ (peer->socket.type & SIP_TRANSPORT_TLS) ?
+ STANDARD_TLS_PORT : STANDARD_SIP_PORT);
}
if (!peer->socket.port) {
peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
@@ -25735,12 +25823,14 @@ static int reload_config(enum channelreloadreason reason)
struct ast_flags dummy[2];
struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? 0 : CONFIG_FLAG_FILEUNCHANGED };
int auto_sip_domains = FALSE;
- struct sockaddr_in old_bindaddr = bindaddr;
+ struct ast_sockaddr old_bindaddr = bindaddr;
int registry_count = 0, peer_count = 0, timerb_set = 0, timert1_set = 0;
time_t run_start, run_end;
-
+ struct sockaddr_in externip_sin;
+ int bindport = 0;
+
run_start = time(0);
- ast_unload_realtime("sipregs");
+ ast_unload_realtime("sipregs");
ast_unload_realtime("sippeers");
cfg = ast_config_load(config, config_flags);
@@ -25775,18 +25865,11 @@ static int reload_config(enum channelreloadreason reason)
}
}
- /* Initialize tcp sockets */
- memset(&sip_tcp_desc.local_address, 0, sizeof(sip_tcp_desc.local_address));
- memset(&sip_tls_desc.local_address, 0, sizeof(sip_tls_desc.local_address));
-
ast_free_ha(sip_cfg.contact_ha);
sip_cfg.contact_ha = NULL;
default_tls_cfg.enabled = FALSE; /* Default: Disable TLS */
- sip_tcp_desc.local_address.sin_port = htons(STANDARD_SIP_PORT);
- sip_tls_desc.local_address.sin_port = htons(STANDARD_TLS_PORT);
-
if (reason != CHANNEL_MODULE_LOAD) {
ast_debug(4, "--------------- SIP reload started\n");
@@ -25845,7 +25928,7 @@ static int reload_config(enum channelreloadreason reason)
ast_clear_flag(&global_flags[1], AST_FLAGS_ALL);
/* Reset IP addresses */
- memset(&bindaddr, 0, sizeof(bindaddr));
+ ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0);
memset(&stunaddr, 0, sizeof(stunaddr));
memset(&internip, 0, sizeof(internip));
@@ -25856,16 +25939,13 @@ static int reload_config(enum channelreloadreason reason)
memset(&media_address, 0, sizeof(media_address));
memset(&default_prefs, 0 , sizeof(default_prefs));
memset(&sip_cfg.outboundproxy, 0, sizeof(struct sip_proxy));
- sip_cfg.outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT);
- sip_cfg.outboundproxy.ip.sin_family = AF_INET; /*!< Type of address: IPv4 */
sip_cfg.outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */
default_transports = 0; /*!< Reset default transport to zero here, default value later on */
default_primary_transport = 0; /*!< Reset default primary transport to zero here, default value later on */
ourport_tcp = STANDARD_SIP_PORT;
ourport_tls = STANDARD_TLS_PORT;
- externtcpport = 0;
- externtlsport = 0;
- bindaddr.sin_port = htons(STANDARD_SIP_PORT);
+ externtcpport = STANDARD_SIP_PORT;
+ externtlsport = STANDARD_TLS_PORT;
sip_cfg.srvlookup = DEFAULT_SRVLOOKUP;
global_tos_sip = DEFAULT_TOS_SIP;
global_tos_audio = DEFAULT_TOS_AUDIO;
@@ -25920,6 +26000,7 @@ static int reload_config(enum channelreloadreason reason)
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* Default for all devices: TRUE */
sip_cfg.peer_rtupdate = TRUE;
global_dynamic_exclude_static = 0; /* Exclude static peers */
+ sip_cfg.tcp_enabled = FALSE;
/* Session-Timers */
global_st_mode = SESSION_TIMER_MODE_ACCEPT;
@@ -26056,14 +26137,18 @@ static int reload_config(enum channelreloadreason reason)
}
}
} else if (!strcasecmp(v->name, "tcpenable")) {
- sip_tcp_desc.local_address.sin_family = ast_false(v->value) ? 0 : AF_INET;
- ast_debug(2, "Enabling TCP socket for listening\n");
+ if (!ast_false(v->value)) {
+ ast_debug(2, "Enabling TCP socket for listening\n");
+ sip_cfg.tcp_enabled = TRUE;
+ }
} else if (!strcasecmp(v->name, "tcpbindaddr")) {
- int family = sip_tcp_desc.local_address.sin_family;
- if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tcp_desc.local_address))
- ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config);
- sip_tcp_desc.local_address.sin_family = family;
- ast_debug(2, "Setting TCP socket address to %s\n", v->value);
+ if (ast_parse_arg(v->value, PARSE_ADDR,
+ &sip_tcp_desc.local_address)) {
+ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n",
+ v->name, v->value, v->lineno, config);
+ }
+ ast_debug(2, "Setting TCP socket address to %s\n",
+ ast_sockaddr_stringify(&sip_tcp_desc.local_address));
} else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) {
global_dynamic_exclude_static = ast_true(v->value);
} else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) {
@@ -26155,7 +26240,6 @@ static int reload_config(enum channelreloadreason reason)
default_fromdomainport = STANDARD_SIP_PORT;
}
} else if (!strcasecmp(v->name, "outboundproxy")) {
- int portnum;
char *tok, *proxyname;
if (ast_strlen_zero(v->value)) {
@@ -26165,10 +26249,10 @@ static int reload_config(enum channelreloadreason reason)
tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ","));
- sip_parse_host(tok, v->lineno, &proxyname, &portnum, &sip_cfg.outboundproxy.transport);
+ sip_parse_host(tok, v->lineno, &proxyname,
+ &sip_cfg.outboundproxy.port,
+ &sip_cfg.outboundproxy.transport);
- sip_cfg.outboundproxy.ip.sin_port = htons(portnum);
-
if ((tok = strtok(NULL, ","))) {
sip_cfg.outboundproxy.force = !strncasecmp(ast_skip_blanks(tok), "force", 5);
} else {
@@ -26227,8 +26311,9 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value);
externexpire = time(NULL);
} else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) {
- if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr))
+ if (ast_parse_arg(v->value, PARSE_ADDR, &bindaddr)) {
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
+ }
} else if (!strcasecmp(v->name, "localnet")) {
struct ast_ha *na;
int ha_error = 0;
@@ -26240,23 +26325,21 @@ static int reload_config(enum channelreloadreason reason)
if (ha_error)
ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value);
} else if (!strcasecmp(v->name, "media_address")) {
- if (ast_parse_arg(v->value, PARSE_INADDR, &media_address))
+ if (ast_parse_arg(v->value, PARSE_ADDR, &media_address))
ast_log(LOG_WARNING, "Invalid address for media_address keyword: %s\n", v->value);
} else if (!strcasecmp(v->name, "externip")) {
- if (ast_parse_arg(v->value, PARSE_INADDR, &externip))
- ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
+ if (ast_parse_arg(v->value, PARSE_ADDR, &externip)) {
+ ast_log(LOG_WARNING,
+ "Invalid address for externip keyword: %s\n",
+ v->value);
+ }
externexpire = 0;
- /* If no port was specified use the value of bindport */
- if (!externip.sin_port)
- externip.sin_port = bindaddr.sin_port;
} else if (!strcasecmp(v->name, "externhost")) {
ast_copy_string(externhost, v->value, sizeof(externhost));
- if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
+ if (ast_sockaddr_resolve_first(&externip, externhost, 0)) {
ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
+ }
externexpire = time(NULL);
- /* If no port was specified use the value of bindport */
- if (!externip.sin_port)
- externip.sin_port = bindaddr.sin_port;
} else if (!strcasecmp(v->name, "externrefresh")) {
if (sscanf(v->value, "%30d", &externrefresh) != 1) {
ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno);
@@ -26264,13 +26347,12 @@ static int reload_config(enum channelreloadreason reason)
}
} else if (!strcasecmp(v->name, "externtcpport")) {
if (!(externtcpport = port_str2int(v->value, 0))) {
- ast_log(LOG_WARNING, "Invalid externtcpport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
- externtcpport = ntohs(sip_tcp_desc.local_address.sin_port);
+ ast_log(LOG_WARNING, "Invalid externtcpport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
+ externtcpport = 0;
}
} else if (!strcasecmp(v->name, "externtlsport")) {
- if (!(externtlsport = port_str2int(v->value, 0))) {
+ if (!(externtlsport = port_str2int(v->value, STANDARD_TLS_PORT))) {
ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
- externtlsport = ntohs(sip_tls_desc.local_address.sin_port);
}
} else if (!strcasecmp(v->name, "allow")) {
int error = ast_parse_allow_disallow(&default_prefs, &sip_cfg.capability, v->value, TRUE);
@@ -26331,12 +26413,8 @@ static int reload_config(enum channelreloadreason reason)
if (ast_str2cos(v->value, &global_cos_text))
ast_log(LOG_WARNING, "Invalid cos_text value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "bindport")) {
- int i;
- if (sscanf(v->value, "%5d", &i) == 1) {
- bindaddr.sin_port = htons(i);
- } else {
+ if (sscanf(v->value, "%5d", &bindport) != 1)
ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
- }
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
default_qualify = 0;
@@ -26449,13 +26527,6 @@ static int reload_config(enum channelreloadreason reason)
default_transports = default_primary_transport = SIP_TRANSPORT_UDP;
}
- /* if not configured, set the defaults for externtcpport and externtlsport */
- if (!externtcpport) {
- externtcpport = ntohs(externip.sin_port); /* for consistency, default to the externip port */
- }
- if (!externtlsport) {
- externtlsport = STANDARD_TLS_PORT;
- }
/* Build list of authentication to various SIP realms, i.e. service providers */
for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) {
/* Format for authentication is auth = username:password@realm */
@@ -26482,7 +26553,7 @@ static int reload_config(enum channelreloadreason reason)
/* user.conf entries are always of type friend */
peer->type = SIP_TYPE_USER | SIP_TYPE_PEER;
ao2_t_link(peers, peer, "link peer into peer table");
- if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
+ if ((peer->type & SIP_TYPE_PEER) && !ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
@@ -26552,7 +26623,7 @@ static int reload_config(enum channelreloadreason reason)
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, 0);
if (peer) {
ao2_t_link(peers, peer, "link peer into peers table");
- if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
+ if ((peer->type & SIP_TYPE_PEER) && !ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
@@ -26560,22 +26631,34 @@ static int reload_config(enum channelreloadreason reason)
}
}
}
-
+
+ if (bindport) {
+ if (ast_sockaddr_port(&bindaddr)) {
+ ast_log(LOG_WARNING, "bindport is also specified in bindaddr. "
+ "Using %d.\n", bindport);
+ }
+ ast_sockaddr_set_port(&bindaddr, bindport);
+ }
+
+ if (!ast_sockaddr_port(&bindaddr)) {
+ ast_sockaddr_set_port(&bindaddr, STANDARD_SIP_PORT);
+ }
+
/* Set UDP address and open socket */
- bindaddr.sin_family = AF_INET;
- internip = bindaddr;
- if (ast_find_ourip(&internip.sin_addr, bindaddr)) {
+ ast_sockaddr_copy(&internip, &bindaddr);
+ if (ast_find_ourip(&internip, &bindaddr)) {
ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n");
ast_config_destroy(cfg);
return 0;
}
ast_mutex_lock(&netlock);
- if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) {
+ if ((sipsock > -1) && (ast_sockaddr_cmp(&old_bindaddr, &bindaddr))) {
close(sipsock);
sipsock = -1;
}
if (sipsock < 0) {
- sipsock = socket(AF_INET, SOCK_DGRAM, 0);
+ sipsock = socket(ast_sockaddr_is_ipv6(&bindaddr) ?
+ AF_INET6 : AF_INET, SOCK_DGRAM, 0);
if (sipsock < 0) {
ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno));
ast_config_destroy(cfg);
@@ -26590,35 +26673,43 @@ static int reload_config(enum channelreloadreason reason)
ast_enable_packet_fragmentation(sipsock);
- if (bind(sipsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
- ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
- ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
- strerror(errno));
+ if (ast_bind(sipsock, &bindaddr) < 0) {
+ ast_log(LOG_WARNING, "Failed to bind to %s: %s\n",
+ ast_sockaddr_stringify(&bindaddr), strerror(errno));
close(sipsock);
sipsock = -1;
} else {
- ast_verb(2, "SIP Listening on %s:%d\n",
- ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
- ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
+ ast_verb(2, "SIP Listening on %s\n", ast_sockaddr_stringify(&bindaddr));
+ ast_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
}
}
}
if (stunaddr.sin_addr.s_addr != 0) {
ast_debug(1, "stun to %s:%d\n",
ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port));
+ ast_sockaddr_to_sin(&externip, &externip_sin);
ast_stun_request(sipsock, &stunaddr,
- NULL, &externip);
- ast_debug(1, "STUN sees us at %s:%d\n",
- ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port));
+ NULL, &externip_sin);
+ ast_debug(1, "STUN sees us at %s\n",
+ ast_sockaddr_stringify(&externip));
}
ast_mutex_unlock(&netlock);
/* Start TCP server */
+ if (sip_cfg.tcp_enabled) {
+ if (ast_sockaddr_isnull(&sip_tcp_desc.local_address)) {
+ ast_sockaddr_copy(&sip_tcp_desc.local_address, &bindaddr);
+ }
+ if (!ast_sockaddr_port(&sip_tcp_desc.local_address)) {
+ ast_sockaddr_set_port(&sip_tcp_desc.local_address, STANDARD_SIP_PORT);
+ }
+ } else {
+ ast_sockaddr_setnull(&sip_tcp_desc.local_address);
+ }
ast_tcptls_server_start(&sip_tcp_desc);
- if (sip_tcp_desc.accept_fd == -1 && sip_tcp_desc.local_address.sin_family == AF_INET) {
+ if (sip_cfg.tcp_enabled && sip_tcp_desc.accept_fd == -1) {
/* TCP server start failed. Tell the admin */
ast_log(LOG_ERROR, "SIP TCP Server start failed. Not listening on TCP socket.\n");
- sip_tcp_desc.local_address.sin_family = 0;
} else {
ast_debug(2, "SIP TCP server started\n");
}
@@ -26627,6 +26718,15 @@ static int reload_config(enum channelreloadreason reason)
memcpy(sip_tls_desc.tls_cfg, &default_tls_cfg, sizeof(default_tls_cfg));
if (ast_ssl_setup(sip_tls_desc.tls_cfg)) {
+ if (ast_sockaddr_isnull(&sip_tls_desc.local_address)) {
+ ast_sockaddr_copy(&sip_tls_desc.local_address, &bindaddr);
+ ast_sockaddr_set_port(&sip_tls_desc.local_address,
+ STANDARD_TLS_PORT);
+ }
+ if (!ast_sockaddr_port(&sip_tls_desc.local_address)) {
+ ast_sockaddr_set_port(&sip_tls_desc.local_address,
+ STANDARD_TLS_PORT);
+ }
ast_tcptls_server_start(&sip_tls_desc);
if (default_tls_cfg.enabled && sip_tls_desc.accept_fd == -1) {
ast_log(LOG_ERROR, "TLS Server start failed. Not listening on TLS socket.\n");
@@ -26647,26 +26747,36 @@ static int reload_config(enum channelreloadreason reason)
char temp[MAXHOSTNAMELEN];
/* First our default IP address */
- if (bindaddr.sin_addr.s_addr) {
- add_sip_domain(ast_inet_ntoa(bindaddr.sin_addr), SIP_DOMAIN_AUTO, NULL);
- } else if (internip.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&bindaddr)) {
+ add_sip_domain(ast_sockaddr_stringify(&bindaddr), SIP_DOMAIN_AUTO, NULL);
+ } else if (!ast_sockaddr_isnull(&internip)) {
/* Our internal IP address, if configured */
- add_sip_domain(ast_inet_ntoa(internip.sin_addr), SIP_DOMAIN_AUTO, NULL);
+ add_sip_domain(ast_sockaddr_stringify(&internip), SIP_DOMAIN_AUTO, NULL);
} else {
ast_log(LOG_NOTICE, "Can't add wildcard IP address to domain list, please add IP address to domain manually.\n");
}
/* If TCP is running on a different IP than UDP, then add it too */
- if (sip_tcp_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tcp_desc.local_address))
- add_sip_domain(ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL);
+ if (!ast_sockaddr_isnull(&sip_tcp_desc.local_address) &&
+ !ast_sockaddr_cmp(&bindaddr, &sip_tcp_desc.local_address)) {
+ add_sip_domain(ast_sockaddr_stringify(&sip_tcp_desc.local_address),
+ SIP_DOMAIN_AUTO, NULL);
+ }
- /* If TLS is running on a differen IP than UDP and TCP, then add that too */
- if (sip_tls_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tls_desc.local_address) && inaddrcmp(&sip_tcp_desc.local_address, &sip_tls_desc.local_address))
- add_sip_domain(ast_inet_ntoa(sip_tls_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL);
+ /* If TLS is running on a different IP than UDP and TCP, then add that too */
+ if (!ast_sockaddr_isnull(&sip_tls_desc.local_address) &&
+ !ast_sockaddr_cmp(&bindaddr, &sip_tls_desc.local_address) &&
+ !ast_sockaddr_cmp(&sip_tcp_desc.local_address,
+ &sip_tls_desc.local_address)) {
+ add_sip_domain(ast_sockaddr_stringify(&sip_tcp_desc.local_address),
+ SIP_DOMAIN_AUTO, NULL);
+ }
/* Our extern IP address, if configured */
- if (externip.sin_addr.s_addr)
- add_sip_domain(ast_inet_ntoa(externip.sin_addr), SIP_DOMAIN_AUTO, NULL);
+ if (!ast_sockaddr_isnull(&externip)) {
+ add_sip_domain(ast_sockaddr_stringify(&externip), SIP_DOMAIN_AUTO,
+ NULL);
+ }
/* Extern host name (NAT traversal support) */
if (!ast_strlen_zero(externhost))
@@ -26698,15 +26808,23 @@ static int reload_config(enum channelreloadreason reason)
static int apply_directmedia_ha(struct sip_pvt *p, const char *op)
{
- struct sockaddr_in us = {0,}, them = {0,};
- int res;
+ struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, };
+ struct sockaddr_in them_sin;
+ int res = AST_SENSE_ALLOW;
ast_rtp_instance_get_remote_address(p->rtp, &them);
ast_rtp_instance_get_local_address(p->rtp, &us);
- if (!(res = ast_apply_ha(p->directmediaha, &them))) {
+ /* Currently ast_apply_ha doesn't support IPv6 */
+ if (ast_sockaddr_is_ipv6(&them)) {
+ return res;
+ }
+
+ ast_sockaddr_to_sin(&them, &them_sin);
+
+ if ((res = ast_apply_ha(p->directmediaha, &them_sin)) == AST_SENSE_DENY) {
ast_debug(3, "Reinvite %s to %s denied by directmedia ACL on %s\n",
- op, ast_inet_ntoa(them.sin_addr), ast_inet_ntoa(us.sin_addr));
+ op, ast_sockaddr_stringify(&them), ast_sockaddr_stringify(&us));
}
return res;
@@ -26744,11 +26862,14 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
else
memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
+ struct sockaddr_in ourip_sin;
+ ast_sockaddr_to_sin(&p->ourip, &ourip_sin);
if (!p->pendinginvite) {
- ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+ ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : ourip_sin.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+
transmit_reinvite_with_sdp(p, TRUE, FALSE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : ourip_sin.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
@@ -26886,19 +27007,19 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if (instance) {
changed |= ast_rtp_instance_get_remote_address(instance, &p->redirip);
- } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
+ } else if (!ast_sockaddr_isnull(&p->redirip)) {
memset(&p->redirip, 0, sizeof(p->redirip));
changed = 1;
}
if (vinstance) {
changed |= ast_rtp_instance_get_remote_address(vinstance, &p->vredirip);
- } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
+ } else if (!ast_sockaddr_isnull(&p->vredirip)) {
memset(&p->vredirip, 0, sizeof(p->vredirip));
changed = 1;
}
if (tinstance) {
changed |= ast_rtp_instance_get_remote_address(tinstance, &p->tredirip);
- } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
+ } else if (!ast_sockaddr_isnull(&p->tredirip)) {
memset(&p->tredirip, 0, sizeof(p->tredirip));
changed = 1;
}
@@ -26910,12 +27031,12 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if (chan->_state != AST_STATE_UP) { /* We are in early state */
if (p->do_history)
append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
- ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
+ ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_sockaddr_stringify(instance ? &p->redirip : &p->ourip));
} else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
- ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
+ ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_sockaddr_stringify(instance ? &p->redirip : &p->ourip));
transmit_reinvite_with_sdp(p, FALSE, FALSE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_sockaddr_stringify(instance ? &p->redirip : &p->ourip));
/* We have a pending Invite. Send re-invite when we're done with the invite */
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
@@ -27321,6 +27442,40 @@ static int reload(void)
return 1;
}
+/*! \brief Return the first entry from ast_sockaddr_resolve filtered by address family
+ *
+ * \warn Using this function probably means you have a faulty design.
+ */
+static int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr,
+ const char* name, int flag, int family)
+{
+ struct ast_sockaddr *addrs;
+ int addrs_cnt;
+
+ addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
+ if (addrs_cnt <= 0) {
+ return 1;
+ }
+ if (addrs_cnt > 1) {
+ ast_log(LOG_DEBUG, "Multiple addresses, using the first one only\n");
+ }
+
+ ast_sockaddr_copy(addr, &addrs[0]);
+
+ ast_free(addrs);
+ return 0;
+}
+
+/*! \brief Return the first entry from ast_sockaddr_resolve filtered by family of binddaddr
+ *
+ * \warn Using this function probably means you have a faulty design.
+ */
+static int ast_sockaddr_resolve_first(struct ast_sockaddr *addr,
+ const char* name, int flag)
+{
+ return ast_sockaddr_resolve_first_af(addr, name, flag, get_address_family_filter(&bindaddr));
+}
+
/*! \brief
* \note The only member of the peer used here is the name field
*/
@@ -27342,16 +27497,26 @@ static int peer_cmp_cb(void *obj, void *arg, int flags)
}
/*!
- * \note the peer's ip address field is used to create key.
+ * Hash function based on the the peer's ip address. For IPv6, we use the end
+ * of the address.
+ * \todo Find a better hashing function
*/
static int peer_iphash_cb(const void *obj, const int flags)
{
const struct sip_peer *peer = obj;
- int ret1 = peer->addr.sin_addr.s_addr;
- if (ret1 < 0)
- ret1 = -ret1;
+ int ret = 0;
+
+ if (ast_sockaddr_isnull(&peer->addr)) {
+ ast_log(LOG_ERROR, "Empty address\n");
+ }
- return ret1;
+ ret = ast_sockaddr_hash(&peer->addr);
+
+ if (ret < 0) {
+ ret = -ret;
+ }
+
+ return ret;
}
/*!
@@ -27376,7 +27541,7 @@ static int peer_ipcmp_cb(void *obj, void *arg, int flags)
{
struct sip_peer *peer = obj, *peer2 = arg;
- if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr) {
+ if (ast_sockaddr_cmp_addr(&peer->addr, &peer2->addr)) {
/* IP doesn't match */
return 0;
}
@@ -27393,7 +27558,8 @@ static int peer_ipcmp_cb(void *obj, void *arg, int flags)
}
/* Now only return a match if the port matches, as well. */
- return peer->addr.sin_port == peer2->addr.sin_port ? (CMP_MATCH | CMP_STOP) : 0;
+ return ast_sockaddr_port(&peer->addr) == ast_sockaddr_port(&peer2->addr) ?
+ (CMP_MATCH | CMP_STOP) : 0;
}
@@ -27401,7 +27567,7 @@ static int threadt_hash_cb(const void *obj, const int flags)
{
const struct sip_threadinfo *th = obj;
- return (int) th->tcptls_session->remote_address.sin_addr.s_addr;
+ return ast_sockaddr_hash(&th->tcptls_session->remote_address);
}
static int threadt_cmp_cb(void *obj, void *arg, int flags)
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 2c0224a7c..6ddc3f0cf 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -2804,6 +2804,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
struct ast_format_list fmt;
struct sockaddr_in us = { 0, };
struct sockaddr_in them = { 0, };
+ struct ast_sockaddr them_tmp;
+ struct ast_sockaddr us_tmp;
sub = c->tech_pvt;
@@ -2818,7 +2820,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
d = l->device;
if (rtp){
- ast_rtp_instance_get_remote_address(rtp, &them);
+ ast_rtp_instance_get_remote_address(rtp, &them_tmp);
+ ast_sockaddr_to_sin(&them_tmp, &them);
/* Shutdown any early-media or previous media on re-invite */
transmit_stopmediatransmission(d, sub);
@@ -2832,7 +2835,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
if (!(l->directmedia) || (l->nat)){
- ast_rtp_instance_get_local_address(rtp, &us);
+ ast_rtp_instance_get_local_address(rtp, &us_tmp);
+ ast_sockaddr_to_sin(&us_tmp, &us);
us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
transmit_startmediatransmission(d, sub, us, fmt);
} else {
@@ -3702,12 +3706,14 @@ static void start_rtp(struct skinny_subchannel *sub)
struct skinny_line *l = sub->parent;
struct skinny_device *d = l->device;
int hasvideo = 0;
+ struct ast_sockaddr bindaddr_tmp;
ast_mutex_lock(&sub->lock);
/* Allocate the RTP */
- sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+ ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
+ sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
if (hasvideo)
- sub->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+ sub->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
if (sub->rtp) {
ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
@@ -5603,6 +5609,8 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
struct ast_format_list fmt;
struct sockaddr_in sin = { 0, };
struct sockaddr_in us = { 0, };
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr us_tmp;
uint32_t addr;
int port;
int status;
@@ -5629,8 +5637,10 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
l = sub->parent;
if (sub->rtp) {
- ast_rtp_instance_set_remote_address(sub->rtp, &sin);
- ast_rtp_instance_get_local_address(sub->rtp, &us);
+ ast_sockaddr_from_sin(&sin_tmp, &sin);
+ ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
+ ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
+ ast_sockaddr_to_sin(&us_tmp, &us);
us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
} else {
ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
@@ -6802,9 +6812,13 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con
}
} else if (!strcasecmp(v->name, "host")) {
if (type & (TYPE_DEVICE)) {
- if (ast_get_ip(&CDEV->addr, v->value)) {
+ struct ast_sockaddr CDEV_addr_tmp;
+
+ if (ast_get_ip(&CDEV_addr_tmp, v->value)) {
ast_log(LOG_WARNING, "Bad IP '%s' at line %d.\n", v->value, v->lineno);
}
+ ast_sockaddr_to_sin(&CDEV_addr_tmp,
+ &CDEV->addr);
continue;
}
} else if (!strcasecmp(v->name, "port")) {
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 0ebf879a1..18b76c5e8 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -2038,6 +2038,9 @@ static void start_rtp(struct unistim_subchannel *sub)
struct sockaddr_in sin = { 0, };
format_t codec;
struct sockaddr_in sout = { 0, };
+ struct ast_sockaddr us_tmp;
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr sout_tmp;
/* Sanity checks */
if (!sub) {
@@ -2062,7 +2065,8 @@ static void start_rtp(struct unistim_subchannel *sub)
/* Allocate the RTP */
if (unistimdebug)
ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
- sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout, NULL);
+ ast_sockaddr_from_sin(&sout_tmp, &sout);
+ sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
if (!sub->rtp) {
ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
strerror(errno), ast_inet_ntoa(sout.sin_addr));
@@ -2078,13 +2082,15 @@ static void start_rtp(struct unistim_subchannel *sub)
ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
/* Create the RTP connection */
- ast_rtp_instance_get_local_address(sub->rtp, &us);
+ ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
+ ast_sockaddr_to_sin(&us_tmp, &us);
sin.sin_family = AF_INET;
/* Setting up RTP for our side */
memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
sizeof(sin.sin_addr));
sin.sin_port = htons(sub->parent->parent->rtp_port);
- ast_rtp_instance_set_remote_address(sub->rtp, &sin);
+ ast_sockaddr_from_sin(&sin_tmp, &sin);
+ ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
if (!(sub->owner->nativeformats & sub->owner->readformat)) {
format_t fmt;
char tmp[256];
diff --git a/channels/sip/dialplan_functions.c b/channels/sip/dialplan_functions.c
index d09627ed8..6e1f65b84 100644
--- a/channels/sip/dialplan_functions.c
+++ b/channels/sip/dialplan_functions.c
@@ -62,9 +62,9 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
}
if (!strcasecmp(args.param, "peerip")) {
- ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", buflen);
+ ast_copy_string(buf, ast_sockaddr_isnull(&p->sa) ? "" : ast_sockaddr_stringify_addr(&p->sa), buflen);
} else if (!strcasecmp(args.param, "recvip")) {
- ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", buflen);
+ ast_copy_string(buf, ast_sockaddr_isnull(&p->recv) ? "" : ast_sockaddr_stringify_addr(&p->recv), buflen);
} else if (!strcasecmp(args.param, "from")) {
ast_copy_string(buf, p->from, buflen);
} else if (!strcasecmp(args.param, "uri")) {
@@ -76,7 +76,7 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
} else if (!strcasecmp(args.param, "t38passthrough")) {
ast_copy_string(buf, (p->t38.state == T38_DISABLED) ? "0" : "1", buflen);
} else if (!strcasecmp(args.param, "rtpdest")) {
- struct sockaddr_in sin;
+ struct ast_sockaddr addr;
struct ast_rtp_instance *stream;
if (ast_strlen_zero(args.type))
@@ -96,10 +96,10 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
return 0;
}
- ast_rtp_instance_get_remote_address(stream, &sin);
- snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ ast_rtp_instance_get_remote_address(stream, &addr);
+ snprintf(buf, buflen, "%s", ast_sockaddr_stringify(&addr));
} else if (!strcasecmp(args.param, "rtpsource")) {
- struct sockaddr_in sin;
+ struct ast_sockaddr sa;
struct ast_rtp_instance *stream;
if (ast_strlen_zero(args.type))
@@ -119,15 +119,15 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
return 0;
}
- ast_rtp_instance_get_local_address(stream, &sin);
+ ast_rtp_instance_get_local_address(stream, &sa);
- if (!sin.sin_addr.s_addr) {
- struct sockaddr_in dest_sin;
- ast_rtp_instance_get_remote_address(stream, &dest_sin);
- ast_ouraddrfor(&dest_sin.sin_addr, &sin.sin_addr);
+ if (ast_sockaddr_isnull(&sa)) {
+ struct ast_sockaddr dest_sa;
+ ast_rtp_instance_get_remote_address(stream, &dest_sa);
+ ast_ouraddrfor(&dest_sa, &sa);
}
- snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ snprintf(buf, buflen, "%s", ast_sockaddr_stringify(&sa));
} else if (!strcasecmp(args.param, "rtpqos")) {
struct ast_rtp_instance *rtp = NULL;
@@ -225,7 +225,7 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
}
#ifdef TEST_FRAMEWORK
-static int test_sip_rtpqos_1_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
+static int test_sip_rtpqos_1_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
{
/* Needed to pass sanity checks */
ast_rtp_instance_set_data(instance, data);
@@ -268,7 +268,7 @@ AST_TEST_DEFINE(test_sip_rtpqos_1)
.write = test_sip_rtpqos_1_write,
.get_stat = test_sip_rtpqos_1_get_stat,
};
- struct sockaddr_in sin = { .sin_port = 31337, .sin_addr = { .s_addr = 4 * 16777216 + 3 * 65536 + 2 * 256 + 1 } };
+ struct ast_sockaddr sa = { {0, } };
struct ast_rtp_instance_stats mine = { 0, };
struct sip_pvt *p = NULL;
struct ast_channel *chan = NULL;
@@ -331,11 +331,12 @@ AST_TEST_DEFINE(test_sip_rtpqos_1)
res = AST_TEST_NOT_RUN;
goto done;
}
+
if (!(p->rtp = ast_rtp_instance_new("test", sched, &bindaddr, &mine))) {
res = AST_TEST_NOT_RUN;
goto done;
}
- ast_rtp_instance_set_remote_address(p->rtp, &sin);
+ ast_rtp_instance_set_remote_address(p->rtp, &sa);
if (!(chan = ast_dummy_channel_alloc())) {
res = AST_TEST_NOT_RUN;
goto done;
diff --git a/channels/sip/include/dialog.h b/channels/sip/include/dialog.h
index 8972c02d9..ed31b7774 100644
--- a/channels/sip/include/dialog.h
+++ b/channels/sip/include/dialog.h
@@ -34,7 +34,7 @@
struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, char *tag, char *file, int line, const char *func);
struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, char *tag, char *file, int line, const char *func);
-struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *sin,
int useglobal_nat, const int intended_method, struct sip_request *req);
void sip_scheddestroy_final(struct sip_pvt *p, int ms);
void sip_scheddestroy(struct sip_pvt *p, int ms);
diff --git a/channels/sip/include/globals.h b/channels/sip/include/globals.h
index 0d7131d87..414d2189b 100644
--- a/channels/sip/include/globals.h
+++ b/channels/sip/include/globals.h
@@ -24,7 +24,7 @@
#ifndef _SIP_GLOBALS_H
#define _SIP_GLOBALS_H
-extern struct sockaddr_in bindaddr; /*!< UDP: The address we bind to */
+extern struct ast_sockaddr bindaddr; /*!< UDP: The address we bind to */
extern struct sched_context *sched; /*!< The scheduling context */
/*! \brief Definition of this channel for PBX channel registration */
diff --git a/channels/sip/include/reqresp_parser.h b/channels/sip/include/reqresp_parser.h
index 58784a621..d8631c982 100644
--- a/channels/sip/include/reqresp_parser.h
+++ b/channels/sip/include/reqresp_parser.h
@@ -28,7 +28,7 @@
* \note
* - Multiple scheme's can be specified ',' delimited. ex: "sip:,sips:"
* - If a component is not requested, do not split around it. This means
- * that if we don't have domain, we cannot split name:pass and domain:port.
+ * that if we don't have domain, we cannot split name:pass.
* - It is safe to call with ret_name, pass, domain, port pointing all to
* the same place.
* - If no secret parameter is provided, ret_name will return with both parts, user:secret
@@ -42,7 +42,8 @@
* general form we are expecting is sip:user:password;user-parameters@host:port;uri-parameters?headers
* \endverbatim
*/
-int parse_uri(char *uri, const char *scheme, char **ret_name, char **pass, char **domain, char **port, char **transport);
+int parse_uri(char *uri, const char *scheme, char **ret_name, char **pass,
+ char **domain, char **transport);
/*!
* \brief parses a URI in to all of its components and any trailing residue
@@ -51,7 +52,9 @@ int parse_uri(char *uri, const char *scheme, char **ret_name, char **pass, char
* \retval -1 on error.
*
*/
-int parse_uri_full(char *uri, const char *scheme, char **user, char **pass, char **host, char **port, struct uriparams *params, char **headers, char **residue);
+int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
+ char **domain, struct uriparams *params, char **headers,
+ char **residue);
/*!
* \brief Get caller id name from SIP headers, copy into output buffer
@@ -100,7 +103,10 @@ int get_in_brackets_full(char *tmp, char **out, char **residue);
* \retval 0 success
* \retval -1 failure
*/
-int parse_name_andor_addr(char *uri, const char *scheme, char **name, char **user, char **pass, char **host, char **port, struct uriparams *params, char **headers, char **remander);
+int parse_name_andor_addr(char *uri, const char *scheme, char **name,
+ char **user, char **pass, char **domain,
+ struct uriparams *params, char **headers,
+ char **remander);
/*! \brief Parse all contact header contacts
* \retval 0 success
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index 13527517f..92fa68e82 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -646,7 +646,8 @@ enum sip_tcptls_alert {
*/
struct sip_proxy {
char name[MAXHOSTNAMELEN]; /*!< DNS name of domain/host or IP */
- struct sockaddr_in ip; /*!< Currently used IP address and port */
+ struct ast_sockaddr ip; /*!< Currently used IP address and port */
+ int port;
time_t last_dnsupdate; /*!< When this was resolved */
enum sip_transport transport;
int force; /*!< If it's an outbound proxy, Force use of this outbound proxy for all outbound requests */
@@ -702,6 +703,7 @@ struct sip_settings {
char default_subscribecontext[AST_MAX_CONTEXT];
struct ast_ha *contact_ha; /*! \brief Global list of addresses dynamic peers are not allowed to use */
format_t capability; /*!< Supported codecs */
+ int tcp_enabled;
};
/*! \brief The SIP socket definition */
@@ -1008,16 +1010,16 @@ struct sip_pvt {
long invite_branch; /*!< The branch used when we sent the initial INVITE */
int64_t sessionversion_remote; /*!< Remote UA's SDP Session Version */
unsigned int portinuri:1; /*!< Non zero if a port has been specified, will also disable srv lookups */
- struct sockaddr_in sa; /*!< Our peer */
- struct sockaddr_in redirip; /*!< Where our RTP should be going if not to us */
- struct sockaddr_in vredirip; /*!< Where our Video RTP should be going if not to us */
- struct sockaddr_in tredirip; /*!< Where our Text RTP should be going if not to us */
+ struct ast_sockaddr sa; /*!< Our peer */
+ struct ast_sockaddr redirip; /*!< Where our RTP should be going if not to us */
+ struct ast_sockaddr vredirip; /*!< Where our Video RTP should be going if not to us */
+ struct ast_sockaddr tredirip; /*!< Where our Text RTP should be going if not to us */
time_t lastrtprx; /*!< Last RTP received */
time_t lastrtptx; /*!< Last RTP sent */
int rtptimeout; /*!< RTP timeout time */
struct ast_ha *directmediaha; /*!< Which IPs are allowed to interchange direct media with this peer - copied from sip_peer */
- struct sockaddr_in recv; /*!< Received as */
- struct sockaddr_in ourip; /*!< Our IP (as seen from the outside) */
+ struct ast_sockaddr recv; /*!< Received as */
+ struct ast_sockaddr ourip; /*!< Our IP (as seen from the outside) */
enum transfermodes allowtransfer; /*!< REFER: restriction scheme */
struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
@@ -1209,7 +1211,7 @@ struct sip_peer {
ast_group_t pickupgroup; /*!< Pickup group */
struct sip_proxy *outboundproxy;/*!< Outbound proxy for this peer */
struct ast_dnsmgr_entry *dnsmgr;/*!< DNS refresh manager for peer */
- struct sockaddr_in addr; /*!< IP address of peer */
+ struct ast_sockaddr addr; /*!< IP address of peer */
unsigned int portinuri:1; /*!< Whether the port should be included in the URI */
struct sip_pvt *call; /*!< Call pointer */
int pokeexpire; /*!< Qualification: When to expire poke (qualify= checking) */
@@ -1217,7 +1219,7 @@ struct sip_peer {
int maxms; /*!< Qualification: Max ms we will accept for the host to be up, 0 to not monitor */
int qualifyfreq; /*!< Qualification: Qualification: How often to check for the host to be up */
struct timeval ps; /*!< Qualification: Time for sending SIP OPTION in sip_pke_peer() */
- struct sockaddr_in defaddr; /*!< Default IP address, used until registration */
+ struct ast_sockaddr defaddr; /*!< Default IP address, used until registration */
struct ast_ha *ha; /*!< Access control list */
struct ast_ha *contactha; /*!< Restrict what IPs are allowed in the Contact header (for registration) */
struct ast_ha *directmediaha; /*!< Restrict what IPs are allowed to interchange direct media with */
@@ -1281,7 +1283,7 @@ struct sip_registry {
int callid_valid; /*!< 0 means we haven't chosen callid for this registry yet. */
unsigned int ocseq; /*!< Sequence number we got to for REGISTERs for this registry */
struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager for register */
- struct sockaddr_in us; /*!< Who the server thinks we are */
+ struct ast_sockaddr us; /*!< Who the server thinks we are */
int noncecount; /*!< Nonce-count */
char lastmsg[256]; /*!< Last Message sent/received */
};
@@ -1321,7 +1323,7 @@ struct sip_subscription_mwi {
unsigned int subscribed:1; /*!< Whether we are currently subscribed or not */
struct sip_pvt *call; /*!< Outbound subscription dialog */
struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager for subscription */
- struct sockaddr_in us; /*!< Who the server thinks we are */
+ struct ast_sockaddr us; /*!< Who the server thinks we are */
};
/*!
@@ -1697,8 +1699,7 @@ struct contact {
char *name;
char *user;
char *pass;
- char *host;
- char *port;
+ char *domain;
struct uriparams params;
char *headers;
char *expires;
diff --git a/channels/sip/reqresp_parser.c b/channels/sip/reqresp_parser.c
index bf35bc226..59cefaa46 100644
--- a/channels/sip/reqresp_parser.c
+++ b/channels/sip/reqresp_parser.c
@@ -28,7 +28,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "include/reqresp_parser.h"
/*! \brief * parses a URI in its components.*/
-int parse_uri_full(char *uri, const char *scheme, char **user, char **pass, char **host, char **port, struct uriparams *params, char **headers, char **residue)
+int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
+ char **domain, struct uriparams *params, char **headers,
+ char **residue)
{
char *userinfo = NULL;
char *parameters = NULL;
@@ -58,31 +60,24 @@ int parse_uri_full(char *uri, const char *scheme, char **user, char **pass, char
}
}
- if (!host) {
- /* if we don't want to split around host, keep everything as a userinfo - cos thats how old parse_uri operated*/
+ if (!domain) {
+ /* if we don't want to split around domain, keep everything as a
+ * userinfo - cos thats how old parse_uri operated*/
userinfo = uri;
} else {
- char *hostport;
+ char *dom = "";
if ((c = strchr(uri, '@'))) {
*c++ = '\0';
- hostport = c;
+ dom = c;
userinfo = uri;
- uri = hostport; /* userinfo can contain ? and ; chars so step forward before looking for params and headers */
+ uri = c; /* userinfo can contain ? and ; chars so step forward before looking for params and headers */
} else {
/* domain-only URI, according to the SIP RFC. */
- hostport = uri;
+ dom = uri;
userinfo = "";
}
- if (port && (c = strchr(hostport, ':'))) { /* Remove :port */
- *c++ = '\0';
- *port = c;
- uri = c;
- } else if (port) {
- *port = "";
- }
-
- *host = hostport;
+ *domain = dom;
}
if (pass && (c = strchr(userinfo, ':'))) { /* user:password */
@@ -201,7 +196,7 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
{
int res = AST_TEST_PASS;
char uri[1024];
- char *user, *pass, *host, *port, *headers, *residue;
+ char *user, *pass, *domain, *headers, *residue;
struct uriparams params;
struct testdata {
@@ -209,15 +204,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
char *uri;
char **userptr;
char **passptr;
- char **hostptr;
- char **portptr;
+ char **domainptr;
char **headersptr;
char **residueptr;
struct uriparams *paramsptr;
char *user;
char *pass;
- char *host;
- char *port;
+ char *domain;
char *headers;
char *residue;
struct uriparams params;
@@ -234,17 +227,15 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=residue",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
- .residue = "param2=residue",
+ .residue = "param2=residue",
.params.transport = "tcp",
.params.lr = 0,
.params.user = ""
@@ -255,15 +246,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=discard2?header=blah&header2=blah2;param3=residue",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "header=blah&header2=blah2",
.residue = "param3=residue",
.params.transport = "tcp",
@@ -276,15 +265,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:-_.!~*'()&=+$,;?/:secret@host:5060;transport=tcp",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "-_.!~*'()&=+$,;?/",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "",
.params.transport = "tcp",
@@ -297,15 +284,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:-_.!~*'()&=+$,@host:5060;transport=tcp",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "-_.!~*'()&=+$,",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "",
.params.transport = "tcp",
@@ -318,15 +303,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@1-1.a-1.:5060;transport=tcp",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "1-1.a-1.",
- .port = "5060",
+ .domain = "1-1.a-1.:5060",
.headers = "",
.residue = "",
.params.transport = "tcp",
@@ -339,15 +322,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$;transport=tcp",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "",
.params.transport = "tcp",
@@ -360,15 +341,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$?header=blah&header2=blah2;-_.!~*'()[]/:&+$=residue",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "header=blah&header2=blah2",
.residue = "-_.!~*'()[]/:&+$=residue",
.params.transport = "",
@@ -381,15 +360,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;param=discard;lr?header=blah",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "header=blah",
.residue = "",
.params.transport = "",
@@ -402,15 +379,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;param=discard;lr=yes?header=blah",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "header=blah",
.residue = "",
.params.transport = "",
@@ -423,15 +398,13 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
.uri = "sip:user:secret@host:5060;paramlr=lr;lr=no;lr=off;lr=0;lr=;=lr;lrextra;lrparam2=lr?header=blah",
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "header=blah",
.residue = "",
.params.transport = "",
@@ -466,16 +439,19 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
}
AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
- user = pass = host = port = headers = residue = NULL;
+ user = pass = domain = headers = residue = NULL;
params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
params.lr = 0;
ast_copy_string(uri,testdataptr->uri,sizeof(uri));
- if (parse_uri_full(uri, "sip:,sips:", testdataptr->userptr, testdataptr->passptr, testdataptr->hostptr, testdataptr->portptr, testdataptr->paramsptr, testdataptr->headersptr, testdataptr->residueptr) ||
+ if (parse_uri_full(uri, "sip:,sips:", testdataptr->userptr,
+ testdataptr->passptr, testdataptr->domainptr,
+ testdataptr->paramsptr,
+ testdataptr->headersptr,
+ testdataptr->residueptr) ||
((testdataptr->userptr) && strcmp(testdataptr->user, user)) ||
((testdataptr->passptr) && strcmp(testdataptr->pass, pass)) ||
- ((testdataptr->hostptr) && strcmp(testdataptr->host, host)) ||
- ((testdataptr->portptr) && strcmp(testdataptr->port, port)) ||
+ ((testdataptr->domainptr) && strcmp(testdataptr->domain, domain)) ||
((testdataptr->headersptr) && strcmp(testdataptr->headers, headers)) ||
((testdataptr->residueptr) && strcmp(testdataptr->residue, residue)) ||
((testdataptr->paramsptr) && strcmp(testdataptr->params.transport,params.transport)) ||
@@ -492,13 +468,14 @@ AST_TEST_DEFINE(sip_parse_uri_fully_test)
}
-int parse_uri(char *uri, const char *scheme, char **user, char **pass, char **host, char **port, char **transport) {
+int parse_uri(char *uri, const char *scheme, char **user, char **pass,
+ char **domain, char **transport) {
int ret;
char *headers;
struct uriparams params;
headers = NULL;
- ret = parse_uri_full(uri, scheme, user, pass, host, port, &params, &headers, NULL);
+ ret = parse_uri_full(uri, scheme, user, pass, domain, &params, &headers, NULL);
if (transport) {
*transport=params.transport;
}
@@ -508,7 +485,7 @@ int parse_uri(char *uri, const char *scheme, char **user, char **pass, char **ho
AST_TEST_DEFINE(sip_parse_uri_test)
{
int res = AST_TEST_PASS;
- char *name, *pass, *domain, *port, *transport;
+ char *name, *pass, *domain, *transport;
char uri1[] = "sip:name@host";
char uri2[] = "sip:name@host;transport=tcp";
char uri3[] = "sip:name:secret@host;transport=tcp";
@@ -535,70 +512,66 @@ AST_TEST_DEFINE(sip_parse_uri_test)
}
/* Test 1, simple URI */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri1, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri1, "sip:,sips:", &name, &pass, &domain, &transport) ||
strcmp(name, "name") ||
!ast_strlen_zero(pass) ||
strcmp(domain, "host") ||
- !ast_strlen_zero(port) ||
!ast_strlen_zero(transport)) {
ast_test_status_update(test, "Test 1: simple uri failed. \n");
res = AST_TEST_FAIL;
}
/* Test 2, add tcp transport */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri2, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri2, "sip:,sips:", &name, &pass, &domain, &transport) ||
strcmp(name, "name") ||
!ast_strlen_zero(pass) ||
strcmp(domain, "host") ||
- !ast_strlen_zero(port) ||
strcmp(transport, "tcp")) {
ast_test_status_update(test, "Test 2: uri with addtion of tcp transport failed. \n");
res = AST_TEST_FAIL;
}
/* Test 3, add secret */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri3, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri3, "sip:,sips:", &name, &pass, &domain, &transport) ||
strcmp(name, "name") ||
strcmp(pass, "secret") ||
strcmp(domain, "host") ||
- !ast_strlen_zero(port) ||
strcmp(transport, "tcp")) {
ast_test_status_update(test, "Test 3: uri with addition of secret failed.\n");
res = AST_TEST_FAIL;
}
/* Test 4, add port and unparsed header field*/
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri4, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri4, "sip:,sips:", &name, &pass, &domain, &transport) ||
strcmp(name, "name") ||
strcmp(pass, "secret") ||
- strcmp(domain, "host") ||
- strcmp(port, "port") ||
+ strcmp(domain, "host:port") ||
strcmp(transport, "tcp")) {
ast_test_status_update(test, "Test 4: add port and unparsed header field failed.\n");
res = AST_TEST_FAIL;
}
/* Test 5, verify parse_uri does not crash when given a NULL uri */
- name = pass = domain = port = transport = NULL;
- if (!parse_uri(NULL, "sip:,sips:", &name, &pass, &domain, &port, &transport)) {
+ name = pass = domain = transport = NULL;
+ if (!parse_uri(NULL, "sip:,sips:", &name, &pass, &domain, &transport)) {
ast_test_status_update(test, "Test 5: passing a NULL uri failed.\n");
res = AST_TEST_FAIL;
}
/* Test 6, verify parse_uri does not crash when given a NULL output parameters */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri6, "sip:,sips:", NULL, NULL, NULL, NULL, NULL)) {
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri6, "sip:,sips:", NULL, NULL, NULL, NULL)) {
ast_test_status_update(test, "Test 6: passing NULL output parameters failed.\n");
res = AST_TEST_FAIL;
}
- /* Test 7, verify parse_uri returns user:secret and domain:port when no port or secret output parameters are supplied. */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri7, "sip:,sips:", &name, NULL, &domain, NULL, NULL) ||
+ /* Test 7, verify parse_uri returns user:secret and domain when no port or secret output parameters are supplied. */
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri7, "sip:,sips:", &name, NULL, &domain, NULL) ||
strcmp(name, "name:secret") ||
strcmp(domain, "host:port")) {
@@ -607,8 +580,8 @@ AST_TEST_DEFINE(sip_parse_uri_test)
}
/* Test 8, verify parse_uri can handle a domain only uri */
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri8, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri8, "sip:,sips:", &name, &pass, &domain, &transport) ||
strcmp(domain, "host") ||
!ast_strlen_zero(name)) {
ast_test_status_update(test, "Test 8: add port and unparsed header field failed.\n");
@@ -616,12 +589,11 @@ AST_TEST_DEFINE(sip_parse_uri_test)
}
/* Test 9, add port and unparsed header field with domain only uri*/
- name = pass = domain = port = transport = NULL;
- if (parse_uri(uri9, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (parse_uri(uri9, "sip:,sips:", &name, &pass, &domain, &transport) ||
!ast_strlen_zero(name) ||
!ast_strlen_zero(pass) ||
strcmp(domain, "host") ||
- strcmp(port, "port") ||
strcmp(transport, "tcp")) {
ast_test_status_update(test, "Test 9: domain only uri failed \n");
res = AST_TEST_FAIL;
@@ -630,12 +602,11 @@ AST_TEST_DEFINE(sip_parse_uri_test)
/* Test 10, handle invalid/missing "sip:,sips:" scheme
* we expect parse_uri to return an error, but still parse
* the results correctly here */
- name = pass = domain = port = transport = NULL;
- if (!parse_uri(uri10, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (!parse_uri(uri10, "sip:,sips:", &name, &pass, &domain, &transport) ||
!ast_strlen_zero(name) ||
!ast_strlen_zero(pass) ||
strcmp(domain, "host") ||
- strcmp(port, "port") ||
strcmp(transport, "tcp")) {
ast_test_status_update(test, "Test 10: missing \"sip:sips:\" scheme failed\n");
res = AST_TEST_FAIL;
@@ -644,12 +615,11 @@ AST_TEST_DEFINE(sip_parse_uri_test)
/* Test 11, simple domain only URI with missing scheme
* we expect parse_uri to return an error, but still parse
* the results correctly here */
- name = pass = domain = port = transport = NULL;
- if (!parse_uri(uri11, "sip:,sips:", &name, &pass, &domain, &port, &transport) ||
+ name = pass = domain = transport = NULL;
+ if (!parse_uri(uri11, "sip:,sips:", &name, &pass, &domain, &transport) ||
!ast_strlen_zero(name) ||
!ast_strlen_zero(pass) ||
strcmp(domain, "host") ||
- !ast_strlen_zero(port) ||
!ast_strlen_zero(transport)) {
ast_test_status_update(test, "Test 11: simple uri with missing scheme failed. \n");
res = AST_TEST_FAIL;
@@ -871,7 +841,7 @@ int get_name_and_number(const char *hdr, char **name, char **number)
tmp_number = get_in_brackets(header);
/* parse out the number here */
- if (parse_uri(tmp_number, "sip:,sips:", &tmp_number, &dummy, &domain, &dummy, NULL) || ast_strlen_zero(tmp_number)) {
+ if (parse_uri(tmp_number, "sip:,sips:", &tmp_number, &dummy, &domain, NULL) || ast_strlen_zero(tmp_number)) {
ast_log(LOG_ERROR, "can not parse name and number from sip header.\n");
return -1;
}
@@ -1149,7 +1119,10 @@ AST_TEST_DEFINE(get_in_brackets_test)
}
-int parse_name_andor_addr(char *uri, const char *scheme, char **name, char **user, char **pass, char **host, char **port, struct uriparams *params, char **headers, char **residue)
+int parse_name_andor_addr(char *uri, const char *scheme, char **name,
+ char **user, char **pass, char **domain,
+ struct uriparams *params, char **headers,
+ char **residue)
{
static char buf[1024];
char **residue2=residue;
@@ -1164,14 +1137,15 @@ int parse_name_andor_addr(char *uri, const char *scheme, char **name, char **use
residue2 = NULL;
}
- return parse_uri_full(uri, scheme, user, pass, host, port, params, headers, residue2);
+ return parse_uri_full(uri, scheme, user, pass, domain, params, headers,
+ residue2);
}
AST_TEST_DEFINE(parse_name_andor_addr_test)
{
int res = AST_TEST_PASS;
char uri[1024];
- char *name, *user, *pass, *host, *port, *headers, *residue;
+ char *name, *user, *pass, *domain, *headers, *residue;
struct uriparams params;
struct testdata {
@@ -1180,16 +1154,14 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
char **nameptr;
char **userptr;
char **passptr;
- char **hostptr;
- char **portptr;
+ char **domainptr;
char **headersptr;
char **residueptr;
struct uriparams *paramsptr;
char *name;
char *user;
char *pass;
- char *host;
- char *port;
+ char *domain;
char *headers;
char *residue;
struct uriparams params;
@@ -1206,16 +1178,14 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
.nameptr = &name,
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.name = "name :@ ",
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "tag=tag",
.params.transport = "tcp",
@@ -1229,16 +1199,14 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
.nameptr = &name,
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.name = "givenname familyname",
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "expires=3600",
.params.transport = "tcp",
@@ -1252,16 +1220,14 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
.nameptr = &name,
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.name = "",
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5060",
+ .domain = "host:5060",
.headers = "",
.residue = "q=1",
.params.transport = "tcp",
@@ -1275,16 +1241,14 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
.nameptr = &name,
.userptr = &user,
.passptr = &pass,
- .hostptr = &host,
- .portptr = &port,
+ .domainptr = &domain,
.headersptr = &headers,
.residueptr = &residue,
.paramsptr = &params,
.name = "",
.user = "",
.pass = "",
- .host = "host",
- .port = "",
+ .domain = "host",
.headers = "",
.residue = "",
.params.transport = "",
@@ -1313,16 +1277,22 @@ AST_TEST_DEFINE(parse_name_andor_addr_test)
}
AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
- name = user = pass = host = port = headers = residue = NULL;
+ name = user = pass = domain = headers = residue = NULL;
params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
params.lr = 0;
ast_copy_string(uri,testdataptr->uri,sizeof(uri));
- if (parse_name_andor_addr(uri, "sip:,sips:", testdataptr->nameptr, testdataptr->userptr, testdataptr->passptr, testdataptr->hostptr, testdataptr->portptr, testdataptr->paramsptr, testdataptr->headersptr, testdataptr->residueptr) ||
+ if (parse_name_andor_addr(uri, "sip:,sips:",
+ testdataptr->nameptr,
+ testdataptr->userptr,
+ testdataptr->passptr,
+ testdataptr->domainptr,
+ testdataptr->paramsptr,
+ testdataptr->headersptr,
+ testdataptr->residueptr) ||
((testdataptr->nameptr) && strcmp(testdataptr->name, name)) ||
((testdataptr->userptr) && strcmp(testdataptr->user, user)) ||
((testdataptr->passptr) && strcmp(testdataptr->pass, pass)) ||
- ((testdataptr->hostptr) && strcmp(testdataptr->host, host)) ||
- ((testdataptr->portptr) && strcmp(testdataptr->port, port)) ||
+ ((testdataptr->domainptr) && strcmp(testdataptr->domain, domain)) ||
((testdataptr->headersptr) && strcmp(testdataptr->headers, headers)) ||
((testdataptr->residueptr) && strcmp(testdataptr->residue, residue)) ||
((testdataptr->paramsptr) && strcmp(testdataptr->params.transport,params.transport)) ||
@@ -1391,7 +1361,11 @@ int parse_contact_header(char *contactheader, struct contactliststruct *contactl
AST_LIST_HEAD_SET_NOLOCK(contactlist, contact);
while ((last = get_comma(contactheader,&comma)) != -1) {
- res = parse_name_andor_addr(contactheader,"sip:,sips:",&contact->name,&contact->user,&contact->pass,&contact->host,&contact->port,&contact->params,&contact->headers,&residue);
+ res = parse_name_andor_addr(contactheader, "sip:,sips:",
+ &contact->name, &contact->user,
+ &contact->pass, &contact->domain,
+ &contact->params, &contact->headers,
+ &residue);
if (res == -1) {
return res;
}
@@ -1462,8 +1436,7 @@ AST_TEST_DEFINE(parse_contact_header_test)
.name = "name :@;?&,",
.user = "user",
.pass = "secret",
- .host = "host",
- .port = "5082",
+ .domain = "host:5082",
.params.transport = "tcp",
.params.ttl = "",
.params.lr = 0,
@@ -1482,8 +1455,7 @@ AST_TEST_DEFINE(parse_contact_header_test)
.name = "",
.user = ",user1,",
.pass = ",secret1,",
- .host = "host1",
- .port = "",
+ .domain = "host1",
.params.transport = "",
.params.ttl = "7",
.params.lr = 0,
@@ -1495,8 +1467,7 @@ AST_TEST_DEFINE(parse_contact_header_test)
.name = "",
.user = "",
.pass = "",
- .host = "host2",
- .port = "",
+ .domain = "host2",
.params.transport = "",
.params.ttl = "",
.params.lr = 0,
@@ -1552,8 +1523,7 @@ AST_TEST_DEFINE(parse_contact_header_test)
strcmp(tdcontactptr->name, contactptr->name) ||
strcmp(tdcontactptr->user, contactptr->user) ||
strcmp(tdcontactptr->pass, contactptr->pass) ||
- strcmp(tdcontactptr->host, contactptr->host) ||
- strcmp(tdcontactptr->port, contactptr->port) ||
+ strcmp(tdcontactptr->domain, contactptr->domain) ||
strcmp(tdcontactptr->headers, contactptr->headers) ||
strcmp(tdcontactptr->expires, contactptr->expires) ||
strcmp(tdcontactptr->q, contactptr->q) ||
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 0ed59e8f9..598ce920f 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -665,8 +665,8 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; a. "externip = hostname[:port]" specifies a static address[:port] to
; be used in SIP and SDP messages.
; The hostname is looked up only once, when [re]loading sip.conf .
-; If a port number is not present, use the "bindport" value (which is
-; not guaranteed to work correctly, because a NAT box might remap the
+; If a port number is not present, use the port specified in the "udpbindaddr"
+; (which is not guaranteed to work correctly, because a NAT box might remap the
; port number as well as the address).
; This approach can be useful if you have a NAT device where you can
; configure the mapping statically. Examples:
diff --git a/include/asterisk/acl.h b/include/asterisk/acl.h
index c8916a68a..2c4f62051 100644
--- a/include/asterisk/acl.h
+++ b/include/asterisk/acl.h
@@ -29,6 +29,7 @@ extern "C" {
#endif
#include "asterisk/network.h"
+#include "asterisk/netsock2.h"
#include "asterisk/io.h"
#define AST_SENSE_DENY 0
@@ -124,12 +125,12 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin);
* of getting an entire hostent structure, you instead are given
* only the IP address inserted into a sockaddr_in structure.
*
- * \param[out] sin The IP address is written into sin->sin_addr
+ * \param[out] addr The IP address is written into sin->sin_addr
* \param value The hostname to look up
* \retval 0 Success
* \retval -1 Failure
*/
-int ast_get_ip(struct sockaddr_in *sin, const char *value);
+int ast_get_ip(struct ast_sockaddr *addr, const char *value);
/*!
* \brief Get the IP address given a hostname and optional service
@@ -141,14 +142,17 @@ int ast_get_ip(struct sockaddr_in *sin, const char *value);
* an SRV lookup will be done for "_sip._udp.example.com". If service is NULL,
* then this function acts exactly like a call to ast_get_ip.
*
- * \param[out] sin The IP address is written into sin->sin_addr
+ * \param addr The IP address found. The address family is used as an input parameter to
+ * filter the returned adresses. if it is 0, both IPv4 and IPv6 addresses
+ * can be returned.
+ *
* \param value The hostname to look up
* \param service A specific service provided by the host. A NULL service results
* in an A-record lookup instead of an SRV lookup
* \retval 0 Success
* \retval -1 Failure
*/
-int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service);
+int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *value, const char *service);
/*!
* \brief Get our local IP address when contacting a remote host
@@ -164,7 +168,7 @@ int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *se
* \retval -1 Failure
* \retval 0 Success
*/
-int ast_ouraddrfor(struct in_addr *them, struct in_addr *us);
+int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us);
/*!
* \brief Find an IP address associated with a specific interface
@@ -219,7 +223,7 @@ struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original);
* \retval 0 Success
* \retval -1 Failure
*/
-int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr);
+int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr);
/*!
* \brief Convert a string to the appropriate COS value
diff --git a/include/asterisk/config.h b/include/asterisk/config.h
index 47de72573..fdaeb0e3e 100644
--- a/include/asterisk/config.h
+++ b/include/asterisk/config.h
@@ -592,6 +592,14 @@ enum ast_parse_flags {
PARSE_INT16 = 0x0004,
PARSE_UINT16 = 0x0005,
#endif
+
+ /* Returns a struct ast_sockaddr, with optional default value
+ * (passed by reference) and port handling (accept, ignore,
+ * require, forbid). The format is 'ipaddress[:port]'. IPv6 address
+ * literals need square brackets around them if a port is specified.
+ */
+ PARSE_ADDR = 0x000e,
+
/* Returns a struct sockaddr_in, with optional default value
* (passed by reference) and port handling (accept, ignore,
* require, forbid). The format is 'host.name[:port]'
@@ -614,7 +622,7 @@ enum ast_parse_flags {
PARSE_IN_RANGE = 0x0020, /* accept values inside a range */
PARSE_OUT_RANGE = 0x0040, /* accept values outside a range */
- /* Port handling, for sockaddr_in. accept/ignore/require/forbid
+ /* Port handling, for ast_sockaddr. accept/ignore/require/forbid
* port number after the hostname or address.
*/
PARSE_PORT_MASK = 0x0300, /* 0x000: accept port if present */
diff --git a/include/asterisk/dnsmgr.h b/include/asterisk/dnsmgr.h
index bf960536d..2c96d8e40 100644
--- a/include/asterisk/dnsmgr.h
+++ b/include/asterisk/dnsmgr.h
@@ -27,7 +27,7 @@
extern "C" {
#endif
-#include "asterisk/network.h"
+#include "asterisk/netsock2.h"
#include "asterisk/srv.h"
/*!
@@ -51,8 +51,9 @@ struct ast_dnsmgr_entry;
*
* \return a DNS manager entry
* \version 1.6.1 result changed from struct in_addr to struct sockaddr_in to store port number
+ * \version 1.8.0 result changed from struct ast_sockaddr_in to ast_sockaddr for IPv6 support
*/
-struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service);
+struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service);
/*!
* \brief Free a DNS manager entry
@@ -67,7 +68,8 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry);
* \brief Allocate and initialize a DNS manager entry
*
* \param name the hostname
- * \param result where to store the IP address as the DNS manager refreshes it
+ * \param result where to store the IP address as the DNS manager refreshes it. The address family
+ * is used as an input parameter to filter the returned adresses. if it is 0, both IPv4 * and IPv6 addresses can be returned.
* \param dnsmgr Where to store the allocate DNS manager entry
* \param service
*
@@ -79,7 +81,7 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry);
* \retval non-zero failure
* \version 1.6.1 result changed from struct in_addr to struct aockaddr_in to store port number
*/
-int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service);
+int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service);
/*!
* \brief Force a refresh of a dnsmgr entry
diff --git a/include/asterisk/netsock2.h b/include/asterisk/netsock2.h
new file mode 100644
index 000000000..dd4fba97e
--- /dev/null
+++ b/include/asterisk/netsock2.h
@@ -0,0 +1,523 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * Viagénie <asteriskv6@viagenie.ca>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Network socket handling
+ */
+
+#ifndef _ASTERISK_NETSOCK2_H
+#define _ASTERISK_NETSOCK2_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+/*!
+ * Values for address families that we support. This is reproduced from socket.h
+ * because we do not want users to include that file. Only netsock2.c should
+ * ever include socket.h.
+ */
+enum {
+ AST_AF_UNSPEC = 0,
+ AST_AF_INET = 2,
+ AST_AF_INET6 = 10,
+};
+
+/*!
+ * Socket address structure. The first member is big enough to contain addresses
+ * of any family. The second member contains the length (in bytes) used in the
+ * first member.
+ *
+ * Some BSDs have the length embedded in sockaddr structs. We ignore them.
+ * (This is the right thing to do.)
+ */
+struct ast_sockaddr {
+ struct sockaddr_storage ss;
+ socklen_t len;
+};
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Checks if the ast_sockaddr is null. "null" in this sense essentially
+ * means uninitialized, or having a 0 length.
+ *
+ * \param addr Pointer to the ast_sockaddr we wish to check
+ * \retval 1 \a addr is null
+ * \retval 0 \a addr is non-null.
+ */
+static inline int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
+{
+ return addr->len == 0;
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Sets address \a addr to null.
+ *
+ * \retval void
+ */
+static inline void ast_sockaddr_setnull(struct ast_sockaddr *addr)
+{
+ addr->len = 0;
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Copies the data from one ast_sockaddr to another
+ *
+ * \param dst The destination ast_sockaddr
+ * \param src The source ast_sockaddr
+ * \retval void
+ */
+static inline void ast_sockaddr_copy(struct ast_sockaddr *dst,
+ const struct ast_sockaddr *src)
+{
+ memcpy(dst, src, src->len);
+ dst->len = src->len;
+};
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Compares two ast_sockaddr structures
+ *
+ * \retval -1 \a a is lexicographically smaller than \a b
+ * \retval 0 \a a is equal to \a b
+ * \retval 1 \a b is lexicographically smaller than \a a
+ */
+int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Compares the addresses of two ast_sockaddr structures.
+ *
+ * \retval -1 \a a is lexicographically smaller than \a b
+ * \retval 0 \a a is equal to \a b
+ * \retval 1 \a b is lexicographically smaller than \a a
+ */
+int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b);
+
+#define AST_SOCKADDR_STR_ADDR (1 << 0)
+#define AST_SOCKADDR_STR_PORT (1 << 1)
+#define AST_SOCKADDR_STR_BRACKETS (1 << 2)
+#define AST_SOCKADDR_STR_HOST AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_BRACKETS
+#define AST_SOCKADDR_STR_DEFAULT AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_PORT
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Convert a socket address to a string.
+ *
+ * \details
+ * This will be of the form a.b.c.d:xyz
+ * for IPv4 and [a:b:c:...:d]:xyz for IPv6.
+ *
+ * This function is thread-safe. The returned string is on static
+ * thread-specific storage.
+ *
+ * \param addr The input to be stringified
+ * \param format one of the following:
+ * AST_SOCKADDR_STR_DEFAULT:
+ * a.b.c.d:xyz for IPv4
+ * [a:b:c:...:d]:xyz for IPv6.
+ * AST_SOCKADDR_STR_ADDR: address only
+ * a.b.c.d for IPv4
+ * a:b:c:...:d for IPv6.
+ * AST_SOCKADDR_STR_HOST: address only, suitable for a URL
+ * a.b.c.d for IPv4
+ * [a:b:c:...:d] for IPv6.
+ * AST_SOCKADDR_STR_PORT: port only
+ * \retval "(null)" \a addr is null
+ * \retval "" An error occurred during processing
+ * \retval string The stringified form of the address
+ */
+char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *addr, int format);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() with default format
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify(const struct ast_sockaddr *addr)
+{
+ return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_DEFAULT);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() to return an address only
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
+{
+ return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_ADDR);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() to return an address only,
+ * suitable for a URL (with brackets for IPv6).
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
+{
+ return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_HOST);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() to return a port only
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
+{
+ return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_PORT);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Parse an IPv4 or IPv6 address string.
+ *
+ * \details
+ * Parses a string containing an IPv4 or IPv6 address followed by an optional
+ * port (separated by a colon) into a struct ast_sockaddr. The allowed formats
+ * are the following:
+ *
+ * a.b.c.d
+ * a.b.c.d:port
+ * a:b:c:...:d
+ * [a:b:c:...:d]
+ * [a:b:c:...:d]:port
+ *
+ * Host names are NOT allowed.
+ *
+ * \param[out] addr The resulting ast_sockaddr
+ * \param str The string to parse
+ * \param flags If set to zero, a port MAY be present. If set to
+ * PARSE_PORT_IGNORE, a port MAY be present but will be ignored. If set to
+ * PARSE_PORT_REQUIRE, a port MUST be present. If set to PARSE_PORT_FORBID, a
+ * port MUST NOT be present.
+ *
+ * \retval 1 Success
+ * \retval 0 Failure
+ */
+int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Parses a string with an IPv4 or IPv6 address and place results into an array
+ *
+ * \details
+ * Parses a string containing a host name or an IPv4 or IPv6 address followed
+ * by an optional port (separated by a colon). The result is returned into a
+ * array of struct ast_sockaddr. Allowed formats for str are the following:
+ *
+ * hostname:port
+ * host.example.com:port
+ * a.b.c.d
+ * a.b.c.d:port
+ * a:b:c:...:d
+ * [a:b:c:...:d]
+ * [a:b:c:...:d]:port
+ *
+ * \param[out] addrs The resulting array of ast_sockaddrs
+ * \param str The string to parse
+ * \param flags If set to zero, a port MAY be present. If set to
+ * PARSE_PORT_IGNORE, a port MAY be present but will be ignored. If set to
+ * PARSE_PORT_REQUIRE, a port MUST be present. If set to PARSE_PORT_FORBID, a
+ * port MUST NOT be present.
+ *
+ * \param family Only addresses of the given family will be returned. Use 0 or
+ * AST_SOCKADDR_UNSPEC to get addresses of all families.
+ *
+ * \retval 0 Failure
+ * \retval non-zero The number of elements in addrs array.
+ */
+int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
+ int flags, int family);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Get the port number of a socket address.
+ *
+ * \warning Do not use this function unless you really know what you are doing.
+ * And "I want the port number" is not knowing what you are doing.
+ *
+ * \retval 0 Address is null
+ * \retval non-zero The port number of the ast_sockaddr
+ */
+uint16_t ast_sockaddr_port(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Sets the port number of a socket address.
+ *
+ * \warning Do not use this function unless you really know what you are doing.
+ * And "I want the port number" is not knowing what you are doing.
+ *
+ * \param addr Address on which to set the port
+ * \param port The port you wish to set the address to use
+ * \retval void
+ */
+void ast_sockaddr_set_port(struct ast_sockaddr *addr, uint16_t port);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Get an IPv4 address of an ast_sockaddr
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ * \return IPv4 address in network byte order
+ */
+uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Determine if the address is an IPv4 address
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ * \retval 1 This is an IPv4 address
+ * \retval 0 This is an IPv6 or IPv4-mapped IPv6 address
+ */
+int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Determine if this is an IPv4-mapped IPv6 address
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ *
+ * \retval 1 This is an IPv4-mapped IPv6 address.
+ * \retval 0 This is not an IPv4-mapped IPv6 address.
+ */
+int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Determine if this is an IPv6 address
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ *
+ * \retval 1 This is an IPv6 or IPv4-mapped IPv6 address.
+ * \retval 0 This is an IPv4 address.
+ */
+int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Determine if the address type is unspecified, or "any" address.
+ *
+ * \details
+ * For IPv4, this would be the address 0.0.0.0, and for IPv6,
+ * this would be the address ::. The port number is ignored.
+ *
+ * \retval 1 This is an "any" address
+ * \retval 0 This is not an "any" address
+ */
+int ast_sockaddr_is_any(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Computes a hash value from the address. The port is ignored.
+ *
+ * \retval 0 Unknown address family
+ * \retval other A 32-bit hash derived from the address
+ */
+int ast_sockaddr_hash(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around accept(2) that uses struct ast_sockaddr.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * accept(2).
+ */
+int ast_accept(int sockfd, struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around bind(2) that uses struct ast_sockaddr.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * bind(2).
+ */
+int ast_bind(int sockfd, const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around connect(2) that uses struct ast_sockaddr.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * connect(2).
+ */
+int ast_connect(int sockfd, const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around getsockname(2) that uses struct ast_sockaddr.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * getsockname(2).
+ */
+int ast_getsockname(int sockfd, struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around recvfrom(2) that uses struct ast_sockaddr.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * recvfrom(2).
+ */
+ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct ast_sockaddr *src_addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around sendto(2) that uses ast_sockaddr.
+ *
+ * \details
+ * For parameter and
+ * return information, see the man page for sendto(2)
+ */
+ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct ast_sockaddr *dest_addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Set type of service
+ *
+ * \details
+ * Set ToS ("Type of Service for IPv4 and "Traffic Class for IPv6) and
+ * CoS (Linux's SO_PRIORITY)
+ *
+ * \param sockfd File descriptor for socket on which to set the parameters
+ * \param tos The type of service for the socket
+ * \param cos The cost of service for the socket
+ * \param desc A text description of the socket in question.
+ * \retval 0 Success
+ * \retval -1 Error, with errno set to an appropriate value
+ */
+int ast_set_qos(int sockfd, int tos, int cos, const char *desc);
+
+/*!
+ * These are backward compatibility functions that may be used by subsystems
+ * that have not yet been converted to IPv6. They will be removed when all
+ * subsystems are IPv6-ready.
+ */
+/*@{*/
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Converts a struct ast_sockaddr to a struct sockaddr_in.
+ *
+ * \param addr The ast_sockaddr to convert
+ * \param[out] sin The resulting sockaddr_in struct
+ * \retval nonzero Success
+ * \retval zero Failure
+ */
+int ast_sockaddr_to_sin(const struct ast_sockaddr *addr,
+ struct sockaddr_in *sin);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Converts a struct sockaddr_in to a struct ast_sockaddr.
+ *
+ * \param sin The sockaddr_in to convert
+ * \return an ast_sockaddr structure
+ */
+void ast_sockaddr_from_sin(struct ast_sockaddr *addr, const struct sockaddr_in *sin);
+
+/*@}*/
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_NETSOCK2_H */
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index cccf06a96..0a2fe7726 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -71,7 +71,7 @@ extern "C" {
#include "asterisk/astobj2.h"
#include "asterisk/frame.h"
-#include "asterisk/netsock.h"
+#include "asterisk/netsock2.h"
#include "asterisk/sched.h"
#include "asterisk/res_srtp.h"
@@ -313,7 +313,7 @@ struct ast_rtp_engine {
/*! Module this RTP engine came from, used for reference counting */
struct ast_module *mod;
/*! Callback for setting up a new RTP instance */
- int (*new)(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
+ int (*new)(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *sa, void *data);
/*! Callback for destroying an RTP instance */
int (*destroy)(struct ast_rtp_instance *instance);
/*! Callback for writing out a frame */
@@ -339,9 +339,9 @@ struct ast_rtp_engine {
/*! Callback for setting packetization preferences */
void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);
/*! Callback for setting the remote address that RTP is to be sent to */
- void (*remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+ void (*remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa);
/*! Callback for setting an alternate remote address */
- void (*alt_remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+ void (*alt_remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa);
/*! Callback for changing DTMF mode */
int (*dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
/*! Callback for retrieving statistics */
@@ -369,7 +369,7 @@ struct ast_rtp_engine {
/*! Callback to indicate that packets will now flow */
int (*activate)(struct ast_rtp_instance *instance);
/*! Callback to request that the RTP engine send a STUN BIND request */
- void (*stun_request)(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
+ void (*stun_request)(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
/*! Callback to get the transcodeable formats supported */
int (*available_formats)(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk);
/*! Linked list information */
@@ -519,7 +519,7 @@ int ast_rtp_glue_unregister(struct ast_rtp_glue *glue);
*
* \param engine_name Name of the engine to use for the RTP instance
* \param sched Scheduler context that the RTP engine may want to use
- * \param sin Address we want to bind to
+ * \param sa Address we want to bind to
* \param data Unique data for the engine
*
* \retval non-NULL success
@@ -533,14 +533,16 @@ int ast_rtp_glue_unregister(struct ast_rtp_glue *glue);
* \endcode
*
* This creates a new RTP instance using the default engine and asks the RTP engine to bind to the address given
- * in the sin structure.
+ * in the address structure.
*
* \note The RTP engine does not have to use the address provided when creating an RTP instance. It may choose to use
* another depending on it's own configuration.
*
* \since 1.8
*/
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data);
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
+ struct sched_context *sched, const struct ast_sockaddr *sa,
+ void *data);
/*!
* \brief Destroy an RTP instance
@@ -663,7 +665,8 @@ struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int r
*
* \since 1.8
*/
-int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address);
+
/*!
* \brief Set the address of an an alternate RTP address to receive from
@@ -677,7 +680,7 @@ int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struc
* Example usage:
*
* \code
- * ast_rtp_instance_set_alt_remote_address(instance, &sin);
+ * ast_rtp_instance_set_alt_remote_address(instance, &address);
* \endcode
*
* This changes the alternate remote address that RTP will be sent to on instance to the address given in the sin
@@ -685,7 +688,7 @@ int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struc
*
* \since 1.8
*/
-int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address);
/*!
* \brief Set the address that we are expecting to receive RTP on
@@ -707,7 +710,8 @@ int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, s
*
* \since 1.8
*/
-int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance,
+ const struct ast_sockaddr *address);
/*!
* \brief Get the local address that we are expecting RTP on
@@ -721,15 +725,15 @@ int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct
* Example usage:
*
* \code
- * struct sockaddr_in sin;
- * ast_rtp_instance_get_local_address(instance, &sin);
+ * struct ast_sockaddr address;
+ * ast_rtp_instance_get_local_address(instance, &address);
* \endcode
*
- * This gets the local address that we are expecting RTP on and stores it in the 'sin' structure.
+ * This gets the local address that we are expecting RTP on and stores it in the 'address' structure.
*
* \since 1.8
*/
-int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address);
/*!
* \brief Get the address of the remote endpoint that we are sending RTP to
@@ -743,16 +747,16 @@ int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct
* Example usage:
*
* \code
- * struct sockaddr_in sin;
- * ast_rtp_instance_get_remote_address(instance, &sin);
+ * struct ast_sockaddr address;
+ * ast_rtp_instance_get_remote_address(instance, &address);
* \endcode
*
* This retrieves the current remote address set on the instance pointed to by instance and puts the value
- * into the sin structure.
+ * into the address structure.
*
* \since 1.8
*/
-int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
+int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address);
/*!
* \brief Set the value of an RTP instance extended property
@@ -1598,7 +1602,7 @@ int ast_rtp_instance_activate(struct ast_rtp_instance *instance);
*
* \since 1.8
*/
-void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
+void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
/*!
* \brief Set the RTP timeout value
diff --git a/include/asterisk/tcptls.h b/include/asterisk/tcptls.h
index ad0438583..2cc2c0fa3 100644
--- a/include/asterisk/tcptls.h
+++ b/include/asterisk/tcptls.h
@@ -48,6 +48,7 @@
#ifndef _ASTERISK_TCPTLS_H
#define _ASTERISK_TCPTLS_H
+#include "asterisk/netsock2.h"
#include "asterisk/utils.h"
#if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE))
@@ -120,9 +121,9 @@ struct ast_tls_config {
* arguments for the accepting thread
*/
struct ast_tcptls_session_args {
- struct sockaddr_in local_address;
- struct sockaddr_in old_address; /*!< copy of the local or remote address depending on if its a client or server session */
- struct sockaddr_in remote_address;
+ struct ast_sockaddr local_address;
+ struct ast_sockaddr old_address; /*!< copy of the local or remote address depending on if its a client or server session */
+ struct ast_sockaddr remote_address;
char hostname[MAXHOSTNAMELEN]; /*!< only necessary for SSL clients so we can compare to common name */
struct ast_tls_config *tls_cfg; /*!< points to the SSL configuration if any */
int accept_fd;
@@ -143,7 +144,7 @@ struct ast_tcptls_session_instance {
SSL *ssl; /* ssl state */
/* iint (*ssl_setup)(SSL *); */
int client;
- struct sockaddr_in remote_address;
+ struct ast_sockaddr remote_address;
struct ast_tcptls_session_args *parent;
ast_mutex_t lock;
};
diff --git a/main/acl.c b/main/acl.c
index caa1d56f0..082048a16 100644
--- a/main/acl.c
+++ b/main/acl.c
@@ -48,7 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/srv.h"
#if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
-static int get_local_address(struct in_addr *ourip)
+static int get_local_address(struct ast_sockaddr *ourip)
{
return -1;
}
@@ -112,7 +112,7 @@ static void score_address(const struct sockaddr_in *sin, struct in_addr *best_ad
}
}
-static int get_local_address(struct in_addr *ourip)
+static int get_local_address(struct ast_sockaddr *ourip)
{
int s, res = -1;
#ifdef SOLARIS
@@ -207,7 +207,9 @@ static int get_local_address(struct in_addr *ourip)
#endif /* BSD_OR_LINUX */
if (res == 0 && ourip) {
- memcpy(ourip, &best_addr, sizeof(*ourip));
+ ast_sockaddr_setnull(ourip);
+ ourip->ss.ss_family = AF_INET;
+ ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
}
return res;
}
@@ -372,27 +374,49 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
return res;
}
-int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
+static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag,
+ int family)
+{
+ struct ast_sockaddr *addrs;
+ int addrs_cnt;
+
+ addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
+ if (addrs_cnt > 0) {
+ if (addrs_cnt > 1) {
+ ast_debug(1, "Multiple addresses. Using the first only\n");
+ }
+ ast_sockaddr_copy(addr, &addrs[0]);
+ ast_free(addrs);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *value, const char *service)
{
- struct hostent *hp;
- struct ast_hostent ahp;
char srv[256];
char host[256];
- int tportno = ntohs(sin->sin_port);
+ int srv_ret = 0;
+ int tportno;
+
if (service) {
snprintf(srv, sizeof(srv), "%s.%s", service, value);
- if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
- sin->sin_port = htons(tportno);
+ if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
value = host;
}
}
- if ((hp = ast_gethostbyname(value, &ahp))) {
- sin->sin_family = hp->h_addrtype;
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- } else {
- ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
+
+ if (resolve_first(addr, value, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
return -1;
}
+
+ if (srv_ret > 0) {
+ ast_sockaddr_set_port(addr, tportno);
+ }
+
return 0;
}
@@ -474,51 +498,53 @@ const char *ast_tos2str(unsigned int tos)
return "unknown";
}
-int ast_get_ip(struct sockaddr_in *sin, const char *value)
+int ast_get_ip(struct ast_sockaddr *addr, const char *value)
{
- return ast_get_ip_or_srv(sin, value, NULL);
+ return ast_get_ip_or_srv(addr, value, NULL);
}
-int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
+int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
{
+ int port;
int s;
- struct sockaddr_in sin;
- socklen_t slen;
- if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+ port = ast_sockaddr_port(us);
+
+ if ((s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET,
+ SOCK_DGRAM, 0)) < 0) {
ast_log(LOG_ERROR, "Cannot create socket\n");
return -1;
}
- sin.sin_family = AF_INET;
- sin.sin_port = htons(5060);
- sin.sin_addr = *them;
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
+
+ if (ast_connect(s, them)) {
ast_log(LOG_WARNING, "Cannot connect\n");
close(s);
return -1;
}
- slen = sizeof(sin);
- if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
+ if (ast_getsockname(s, us)) {
+
ast_log(LOG_WARNING, "Cannot get socket name\n");
close(s);
return -1;
}
close(s);
- ast_debug(3, "Found IP address for this socket\n");
- *us = sin.sin_addr;
+ ast_debug(3, "For destination '%s', our source address is '%s'.\n",
+ ast_sockaddr_stringify_addr(them),
+ ast_sockaddr_stringify_addr(us));
+
+ ast_sockaddr_set_port(us, port);
+
return 0;
}
-int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
+int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr)
{
char ourhost[MAXHOSTNAMELEN] = "";
- struct ast_hostent ahp;
- struct hostent *hp;
- struct in_addr saddr;
+ struct ast_sockaddr root;
/* just use the bind address if it is nonzero */
- if (ntohl(bindaddr.sin_addr.s_addr)) {
- memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
+ if (!ast_sockaddr_is_any(bindaddr)) {
+ ast_sockaddr_copy(ourip, bindaddr);
ast_debug(3, "Attached to given IP address\n");
return 0;
}
@@ -526,15 +552,14 @@ int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
if (gethostname(ourhost, sizeof(ourhost) - 1)) {
ast_log(LOG_WARNING, "Unable to get hostname\n");
} else {
- if ((hp = ast_gethostbyname(ourhost, &ahp))) {
- memcpy(ourip, hp->h_addr, sizeof(*ourip));
- ast_debug(3, "Found one IP address based on local hostname %s.\n", ourhost);
+ if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, 0) == 0) {
return 0;
}
}
ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
/* A.ROOT-SERVERS.NET. */
- if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) {
+ if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
+ !ast_ouraddrfor(&root, ourip)) {
return 0;
}
return get_local_address(ourip);
diff --git a/main/app.c b/main/app.c
index a171f2611..050c4e238 100644
--- a/main/app.c
+++ b/main/app.c
@@ -1190,7 +1190,7 @@ unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, ch
{
int argc;
char *scan, *wasdelim = NULL;
- int paren = 0, quote = 0;
+ int paren = 0, quote = 0, bracket = 0;
if (!array || !arraylen) {
return 0;
@@ -1213,6 +1213,12 @@ unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, ch
if (paren) {
paren--;
}
+ } else if (*scan == '[') {
+ bracket++;
+ } else if (*scan == ']') {
+ if (bracket) {
+ bracket--;
+ }
} else if (*scan == '"' && delim != '"') {
quote = quote ? 0 : 1;
if (remove_chars) {
@@ -1227,7 +1233,7 @@ unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, ch
} else {
scan++;
}
- } else if ((*scan == delim) && !paren && !quote) {
+ } else if ((*scan == delim) && !paren && !quote && !bracket) {
wasdelim = scan;
*scan++ = '\0';
break;
diff --git a/main/config.c b/main/config.c
index 9400abd8c..e1c51dcd6 100644
--- a/main/config.c
+++ b/main/config.c
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h" /* for the ast_str_*() API */
+#include "asterisk/netsock2.h"
#define MAX_NESTED_COMMENTS 128
#define COMMENT_START ";--"
@@ -2386,7 +2387,20 @@ int ast_parse_arg(const char *arg, enum ast_parse_flags flags,
result ? *result : x, error);
break;
}
- case PARSE_INADDR:
+ case PARSE_ADDR:
+ {
+ struct ast_sockaddr *addr = (struct ast_sockaddr *)p_result;
+
+ if (!ast_sockaddr_parse(addr, arg, flags & PARSE_PORT_MASK)) {
+ error = 1;
+ }
+
+ ast_debug(3, "extract addr from %s gives %s(%d)\n",
+ arg, ast_sockaddr_stringify(addr), error);
+
+ break;
+ }
+ case PARSE_INADDR: /* TODO Remove this (use PARSE_ADDR instead). */
{
char *port, *buf;
struct sockaddr_in _sa_buf; /* buffer for the result */
diff --git a/main/dnsmgr.c b/main/dnsmgr.c
index ca181e3f2..29ac4e30f 100644
--- a/main/dnsmgr.c
+++ b/main/dnsmgr.c
@@ -51,7 +51,7 @@ static pthread_t refresh_thread = AST_PTHREADT_NULL;
struct ast_dnsmgr_entry {
/*! where we will store the resulting IP address and port number */
- struct sockaddr_in *result;
+ struct ast_sockaddr *result;
/*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */
char *service;
/*! Set to 1 if the entry changes */
@@ -83,7 +83,7 @@ static struct refresh_info master_refresh_info = {
.verbose = 0,
};
-struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service)
+struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
{
struct ast_dnsmgr_entry *entry;
int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0);
@@ -120,10 +120,7 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
ast_free(entry);
}
-/*
- * Allocate a new DNS manager entry and perform the initial lookup before returning
- */
-int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
+int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
{
if (ast_strlen_zero(name) || !result || !dnsmgr)
return -1;
@@ -131,13 +128,6 @@ int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_d
if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name))
return 0;
- /* if it's actually an IP address and not a name,
- there's no need for a managed lookup */
- if (inet_aton(name, &result->sin_addr)) {
- result->sin_family = AF_INET;
- return 0;
- }
-
ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name);
/* do a lookup now but add a manager so it will automagically get updated in the background */
@@ -157,25 +147,26 @@ int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_d
*/
static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
{
- char iabuf[INET_ADDRSTRLEN];
- char iabuf2[INET_ADDRSTRLEN];
- struct sockaddr_in tmp;
+ struct ast_sockaddr tmp;
int changed = 0;
-
+
ast_mutex_lock(&entry->lock);
if (verbose)
ast_verb(3, "refreshing '%s'\n", entry->name);
memset(&tmp, 0, sizeof(tmp));
- tmp.sin_port = entry->result->sin_port;
-
- if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, entry->result)) {
- ast_copy_string(iabuf, ast_inet_ntoa(entry->result->sin_addr), sizeof(iabuf));
- ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2));
- ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n",
- entry->name, iabuf, ntohs(entry->result->sin_port), iabuf2, ntohs(tmp.sin_port));
- *entry->result = tmp;
- changed = entry->changed = 1;
+
+ if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service)) {
+ if (!ast_sockaddr_port(&tmp))
+ ast_sockaddr_set_port(&tmp, ast_sockaddr_port(entry->result));
+ if (ast_sockaddr_cmp(&tmp, entry->result)) {
+ ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s to %s\n",
+ entry->name, ast_sockaddr_stringify(entry->result),
+ ast_sockaddr_stringify(&tmp));
+
+ ast_sockaddr_copy(entry->result, &tmp);
+ changed = entry->changed = 1;
+ }
}
ast_mutex_unlock(&entry->lock);
diff --git a/main/http.c b/main/http.c
index dcbfc4d66..6390297e5 100644
--- a/main/http.c
+++ b/main/http.c
@@ -316,12 +316,12 @@ static int httpstatus_callback(struct ast_tcptls_session_instance *ser,
ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
- ast_inet_ntoa(http_desc.old_address.sin_addr));
- ast_str_append(&out, 0, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
- ntohs(http_desc.old_address.sin_port));
+ ast_sockaddr_stringify_addr(&http_desc.old_address));
+ ast_str_append(&out, 0, "<tr><td><i>Bind Port</i></td><td><b>%s</b></td></tr>\r\n",
+ ast_sockaddr_stringify_port(&http_desc.old_address));
if (http_tls_cfg.enabled) {
- ast_str_append(&out, 0, "<tr><td><i>SSL Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
- ntohs(https_desc.old_address.sin_port));
+ ast_str_append(&out, 0, "<tr><td><i>SSL Bind Port</i></td><td><b>%s</b></td></tr>\r\n",
+ ast_sockaddr_stringify_port(&https_desc.old_address));
}
ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
for (v = get_vars; v; v = v->next) {
@@ -989,6 +989,8 @@ static int __ast_http_load(int reload)
char newprefix[MAX_PREFIX] = "";
struct http_uri_redirect *redirect;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+ struct sockaddr_in tmp = {0,};
+ struct sockaddr_in tmp2 = {0,};
cfg = ast_config_load2("http.conf", "http", config_flags);
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
@@ -996,11 +998,13 @@ static int __ast_http_load(int reload)
}
/* default values */
- memset(&http_desc.local_address, 0, sizeof(http_desc.local_address));
- http_desc.local_address.sin_port = htons(8088);
+ tmp.sin_family = AF_INET;
+ tmp.sin_port = htons(8088);
+ ast_sockaddr_from_sin(&http_desc.local_address, &tmp);
- memset(&https_desc.local_address, 0, sizeof(https_desc.local_address));
- https_desc.local_address.sin_port = htons(8089);
+ tmp2.sin_family = AF_INET;
+ tmp2.sin_port = htons(8089);
+ ast_sockaddr_from_sin(&https_desc.local_address, &tmp2);
http_tls_cfg.enabled = 0;
if (http_tls_cfg.certfile) {
@@ -1038,10 +1042,15 @@ static int __ast_http_load(int reload)
} else if (!strcasecmp(v->name, "enablestatic")) {
newenablestatic = ast_true(v->value);
} else if (!strcasecmp(v->name, "bindport")) {
- http_desc.local_address.sin_port = htons(atoi(v->value));
+ ast_sockaddr_set_port(&http_desc.local_address,
+ atoi(v->value));
} else if (!strcasecmp(v->name, "bindaddr")) {
if ((hp = ast_gethostbyname(v->value, &ahp))) {
- memcpy(&http_desc.local_address.sin_addr, hp->h_addr, sizeof(http_desc.local_address.sin_addr));
+ ast_sockaddr_to_sin(&http_desc.local_address,
+ &tmp);
+ memcpy(&tmp.sin_addr, hp->h_addr, sizeof(tmp.sin_addr));
+ ast_sockaddr_from_sin(&http_desc.local_address,
+ &tmp);
} else {
ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
}
@@ -1062,11 +1071,15 @@ static int __ast_http_load(int reload)
ast_config_destroy(cfg);
}
/* if the https addres has not been set, default is the same as non secure http */
- if (!https_desc.local_address.sin_addr.s_addr) {
- https_desc.local_address.sin_addr = http_desc.local_address.sin_addr;
+ ast_sockaddr_to_sin(&http_desc.local_address, &tmp);
+ ast_sockaddr_to_sin(&https_desc.local_address, &tmp2);
+ if (!tmp2.sin_addr.s_addr) {
+ tmp2.sin_addr = tmp.sin_addr;
+ ast_sockaddr_from_sin(&https_desc.local_address, &tmp2);
}
- if (enabled) {
- http_desc.local_address.sin_family = https_desc.local_address.sin_family = AF_INET;
+ if (!enabled) {
+ http_desc.local_address.ss.ss_family = 0;
+ https_desc.local_address.ss.ss_family = 0;
}
if (strcmp(prefix, newprefix)) {
ast_copy_string(prefix, newprefix, sizeof(prefix));
@@ -1084,6 +1097,7 @@ static char *handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_a
{
struct ast_http_uri *urih;
struct http_uri_redirect *redirect;
+ struct sockaddr_in tmp;
switch (cmd) {
case CLI_INIT:
@@ -1101,16 +1115,17 @@ static char *handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_a
}
ast_cli(a->fd, "HTTP Server Status:\n");
ast_cli(a->fd, "Prefix: %s\n", prefix);
- if (!http_desc.old_address.sin_family) {
+ ast_sockaddr_to_sin(&http_desc.old_address, &tmp);
+ if (!tmp.sin_family) {
ast_cli(a->fd, "Server Disabled\n\n");
} else {
ast_cli(a->fd, "Server Enabled and Bound to %s:%d\n\n",
- ast_inet_ntoa(http_desc.old_address.sin_addr),
- ntohs(http_desc.old_address.sin_port));
+ ast_inet_ntoa(tmp.sin_addr), ntohs(tmp.sin_port));
if (http_tls_cfg.enabled) {
+ ast_sockaddr_to_sin(&https_desc.old_address, &tmp);
ast_cli(a->fd, "HTTPS Server Enabled and Bound to %s:%d\n\n",
- ast_inet_ntoa(https_desc.old_address.sin_addr),
- ntohs(https_desc.old_address.sin_port));
+ ast_inet_ntoa(tmp.sin_addr),
+ ntohs(tmp.sin_port));
}
}
diff --git a/main/manager.c b/main/manager.c
index dffe92a15..5c8f893af 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -1984,7 +1984,8 @@ static enum ast_security_event_transport_type mansession_get_transport(const str
static struct sockaddr_in *mansession_encode_sin_local(const struct mansession *s,
struct sockaddr_in *sin_local)
{
- *sin_local = s->tcptls_session->parent->local_address;
+ ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address,
+ sin_local);
return sin_local;
}
@@ -4598,14 +4599,18 @@ static int do_message(struct mansession *s)
static void *session_do(void *data)
{
struct ast_tcptls_session_instance *ser = data;
- struct mansession_session *session = build_mansession(ser->remote_address);
+ struct mansession_session *session;
struct mansession s = {
.tcptls_session = data,
};
int flags;
int res;
+ struct sockaddr_in ser_remote_address_tmp;
struct protoent *p;
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ session = build_mansession(ser_remote_address_tmp);
+
if (session == NULL) {
goto done;
}
@@ -4640,7 +4645,7 @@ static void *session_do(void *data)
/* these fields duplicate those in the 'ser' structure */
session->fd = s.fd = ser->fd;
session->f = s.f = ser->f;
- session->sin = ser->remote_address;
+ session->sin = ser_remote_address_tmp;
s.session = session;
AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
@@ -5912,17 +5917,35 @@ out_401:
static int manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return generic_http_callback(ser, method, FORMAT_HTML, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static int mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return generic_http_callback(ser, method, FORMAT_XML, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static int rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return generic_http_callback(ser, method, FORMAT_RAW, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static struct ast_http_uri rawmanuri = {
@@ -5953,17 +5976,35 @@ static struct ast_http_uri managerxmluri = {
/* Callback with Digest authentication */
static int auth_manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return auth_http_callback(ser, method, FORMAT_HTML, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static int auth_mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return auth_http_callback(ser, method, FORMAT_XML, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static int auth_rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
{
- return auth_http_callback(ser, method, FORMAT_RAW, &ser->remote_address, uri, get_params, headers);
+ int retval;
+ struct sockaddr_in ser_remote_address_tmp;
+
+ ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+ retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
+ ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+ return retval;
}
static struct ast_http_uri arawmanuri = {
@@ -6049,12 +6090,10 @@ static char *handle_manager_show_settings(struct ast_cli_entry *e, int cmd, stru
ast_cli(a->fd, "----------------\n");
ast_cli(a->fd, FORMAT, "Manager (AMI):", AST_CLI_YESNO(manager_enabled));
ast_cli(a->fd, FORMAT, "Web Manager (AMI/HTTP):", AST_CLI_YESNO(webmanager_enabled));
- ast_cli(a->fd, FORMAT, "TCP Bindaddress:", ast_inet_ntoa(ami_desc.local_address.sin_addr));
- ast_cli(a->fd, FORMAT2, "TCP Port:", ntohs(ami_desc.local_address.sin_port));
+ ast_cli(a->fd, FORMAT, "TCP Bindaddress:", ast_sockaddr_stringify(&ami_desc.local_address));
ast_cli(a->fd, FORMAT2, "HTTP Timeout (minutes):", httptimeout);
ast_cli(a->fd, FORMAT, "TLS Enable:", AST_CLI_YESNO(ami_tls_cfg.enabled));
- ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ast_inet_ntoa(amis_desc.local_address.sin_addr));
- ast_cli(a->fd, FORMAT2, "TLS Port:", ntohs(amis_desc.local_address.sin_port));
+ ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ast_sockaddr_stringify(&amis_desc.local_address));
ast_cli(a->fd, FORMAT, "TLS Certfile:", ami_tls_cfg.certfile);
ast_cli(a->fd, FORMAT, "TLS Privatekey:", ami_tls_cfg.pvtfile);
ast_cli(a->fd, FORMAT, "TLS Cipher:", ami_tls_cfg.cipher);
@@ -6093,6 +6132,8 @@ static int __init_manager(int reload)
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
char a1[256];
char a1_hash[256];
+ struct sockaddr_in ami_desc_local_address_tmp = { 0, };
+ struct sockaddr_in amis_desc_local_address_tmp = { 0, };
manager_enabled = 0;
@@ -6151,10 +6192,8 @@ static int __init_manager(int reload)
/* default values */
ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm));
- memset(&ami_desc.local_address, 0, sizeof(struct sockaddr_in));
- memset(&amis_desc.local_address, 0, sizeof(amis_desc.local_address));
- amis_desc.local_address.sin_port = htons(5039);
- ami_desc.local_address.sin_port = htons(DEFAULT_MANAGER_PORT);
+ amis_desc_local_address_tmp.sin_port = htons(5039);
+ ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT);
ami_tls_cfg.enabled = 0;
if (ami_tls_cfg.certfile) {
@@ -6186,11 +6225,12 @@ static int __init_manager(int reload)
} else if (!strcasecmp(var->name, "webenabled")) {
webmanager_enabled = ast_true(val);
} else if (!strcasecmp(var->name, "port")) {
- ami_desc.local_address.sin_port = htons(atoi(val));
+ ami_desc_local_address_tmp.sin_port = htons(atoi(val));
} else if (!strcasecmp(var->name, "bindaddr")) {
- if (!inet_aton(val, &ami_desc.local_address.sin_addr)) {
+ if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) {
ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
- memset(&ami_desc.local_address.sin_addr, 0, sizeof(ami_desc.local_address.sin_addr));
+ memset(&ami_desc_local_address_tmp.sin_addr, 0,
+ sizeof(ami_desc_local_address_tmp.sin_addr));
}
} else if (!strcasecmp(var->name, "brokeneventsaction")) {
broken_events_action = ast_true(val);
@@ -6228,15 +6268,18 @@ static int __init_manager(int reload)
}
if (manager_enabled) {
- ami_desc.local_address.sin_family = AF_INET;
+ ami_desc_local_address_tmp.sin_family = AF_INET;
}
/* if the amis address has not been set, default is the same as non secure ami */
- if (!amis_desc.local_address.sin_addr.s_addr) {
- amis_desc.local_address.sin_addr = ami_desc.local_address.sin_addr;
+ if (!amis_desc_local_address_tmp.sin_addr.s_addr) {
+ amis_desc_local_address_tmp.sin_addr =
+ ami_desc_local_address_tmp.sin_addr;
}
if (ami_tls_cfg.enabled) {
- amis_desc.local_address.sin_family = AF_INET;
+ amis_desc_local_address_tmp.sin_family = AF_INET;
}
+ ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp);
+ ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp);
AST_RWLIST_WRLOCK(&users);
diff --git a/main/netsock2.c b/main/netsock2.c
new file mode 100644
index 000000000..4d93a911b
--- /dev/null
+++ b/main/netsock2.c
@@ -0,0 +1,499 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * Viagénie <asteriskv6@viagenie.ca>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Network socket handling
+ *
+ * \author Viagénie <asteriskv6@viagenie.ca>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/config.h"
+#include "asterisk/netsock2.h"
+#include "asterisk/utils.h"
+#include "asterisk/threadstorage.h"
+
+static int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
+{
+ const struct sockaddr_in6 *sin6;
+ struct sockaddr_in sin4;
+
+ if (!ast_sockaddr_is_ipv6(addr)) {
+ return 0;
+ }
+
+ if (!ast_sockaddr_is_ipv4_mapped(addr)) {
+ return 0;
+ }
+
+ sin6 = (const struct sockaddr_in6*)&addr->ss;
+
+ memset(&sin4, 0, sizeof(sin4));
+ sin4.sin_family = AF_INET;
+ sin4.sin_port = sin6->sin6_port;
+ sin4.sin_addr.s_addr = ((uint32_t *)&sin6->sin6_addr)[3];
+
+ ast_sockaddr_from_sin(ast_mapped, &sin4);
+
+ return 1;
+}
+
+
+AST_THREADSTORAGE(ast_sockaddr_stringify_buf);
+
+char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format)
+{
+ struct ast_sockaddr sa_ipv4;
+ const struct ast_sockaddr *sa_tmp;
+ char host[NI_MAXHOST];
+ char port[NI_MAXSERV];
+ struct ast_str *str;
+ int e;
+ static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;
+
+
+ if (ast_sockaddr_isnull(sa)) {
+ return "(null)";
+ }
+
+ if (!(str = ast_str_thread_get(&ast_sockaddr_stringify_buf, size))) {
+ return "";
+ }
+
+ if (ast_sockaddr_ipv4_mapped(sa, &sa_ipv4)) {
+ sa_tmp = &sa_ipv4;
+ } else {
+ sa_tmp = sa;
+ }
+
+ if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa->len,
+ format & AST_SOCKADDR_STR_ADDR ? host : NULL,
+ format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0,
+ format & AST_SOCKADDR_STR_PORT ? port : 0,
+ format & AST_SOCKADDR_STR_PORT ? sizeof(port): 0,
+ NI_NUMERICHOST | NI_NUMERICSERV))) {
+ ast_log(LOG_ERROR, "getnameinfo(): %s\n", gai_strerror(e));
+ return "";
+ }
+
+ switch (format) {
+ case AST_SOCKADDR_STR_DEFAULT:
+ ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ?
+ "[%s]:%s" : "%s:%s", host, port);
+ break;
+ case AST_SOCKADDR_STR_ADDR:
+ ast_str_set(&str, 0, "%s", host);
+ break;
+ case AST_SOCKADDR_STR_HOST:
+ ast_str_set(&str, 0,
+ sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
+ break;
+ case AST_SOCKADDR_STR_PORT:
+ ast_str_set(&str, 0, "%s", port);
+ break;
+ default:
+ ast_log(LOG_ERROR, "Invalid format\n");
+ return "";
+ }
+
+ return ast_str_buffer(str);
+}
+
+int static _ast_sockaddr_parse(char *str, char **host, char **port, int flags)
+{
+ char *s = str;
+
+ ast_debug(5, "Splitting '%s' gives...\n", str);
+ *host = NULL;
+ *port = NULL;
+ if (*s == '[') {
+ *host = ++s;
+ for (; *s && *s != ']'; ++s) {
+ }
+ if (*s == ']') {
+ *s++ = '\0';
+ }
+ if (*s == ':') {
+ *port = s + 1;
+ }
+ } else {
+ *host = s;
+ for (; *s; ++s) {
+ if (*s == ':') {
+ if (*port) {
+ *port = NULL;
+ break;
+ } else {
+ *port = s;
+ }
+ }
+ }
+ if (*port) {
+ **port = '\0';
+ ++*port;
+ }
+ }
+ ast_debug(5, "...host '%s' and port '%s'.\n", *host, *port);
+
+ switch (flags & PARSE_PORT_MASK) {
+ case PARSE_PORT_IGNORE:
+ *port = NULL;
+ break;
+ case PARSE_PORT_REQUIRE:
+ if (*port == NULL) {
+ ast_log(LOG_WARNING, "missing port\n");
+ return 0;
+ }
+ break;
+ case PARSE_PORT_FORBID:
+ if (*port != NULL) {
+ ast_log(LOG_WARNING, "port disallowed\n");
+ return 0;
+ }
+ break;
+ }
+
+ return 1;
+}
+
+
+
+int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
+{
+ struct addrinfo hints;
+ struct addrinfo *res;
+ char *s;
+ char *host;
+ char *port;
+ int e;
+
+ s = ast_strdupa(str);
+ if (!_ast_sockaddr_parse(s, &host, &port, flags)) {
+ return 0;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ /* Hint to get only one entry from getaddrinfo */
+ hints.ai_socktype = SOCK_DGRAM;
+
+ hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+ if ((e = getaddrinfo(host, port, &hints, &res))) {
+ ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
+ host, S_OR(port, "(null)"), gai_strerror(e));
+ return 0;
+ }
+
+ /*
+ * I don't see how this could be possible since we're not resolving host
+ * names. But let's be careful...
+ */
+ if (res->ai_next != NULL) {
+ ast_log(LOG_WARNING, "getaddrinfo() returned multiple "
+ "addresses. Ignoring all but the first.\n");
+ }
+
+ addr->len = res->ai_addrlen;
+ memcpy(&addr->ss, res->ai_addr, addr->len);
+
+ freeaddrinfo(res);
+
+ return 1;
+}
+
+int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
+ int flags, int family)
+{
+ struct addrinfo hints, *res, *ai;
+ char *s, *host, *port;
+ int e, i, res_cnt;
+
+ s = ast_strdupa(str);
+ if (!_ast_sockaddr_parse(s, &host, &port, flags)) {
+ return 0;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ((e = getaddrinfo(host, port, &hints, &res))) {
+ ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
+ host, S_OR(port, "(null)"), gai_strerror(e));
+ return 0;
+ }
+
+ res_cnt = 0;
+ for (ai = res; ai; ai = ai->ai_next) {
+ res_cnt++;
+ }
+
+ if ((*addrs = ast_malloc(res_cnt * sizeof(struct ast_sockaddr))) == NULL) {
+ res_cnt = 0;
+ goto cleanup;
+ }
+
+ i = 0;
+ for (ai = res; ai; ai = ai->ai_next) {
+ (*addrs)[i].len = ai->ai_addrlen;
+ memcpy(&(*addrs)[i].ss, ai->ai_addr, ai->ai_addrlen);
+ ++i;
+ }
+
+cleanup:
+ freeaddrinfo(res);
+ return res_cnt;
+}
+
+int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
+{
+ const struct ast_sockaddr *a_tmp, *b_tmp;
+ struct ast_sockaddr ipv4_mapped;
+
+ a_tmp = a;
+ b_tmp = b;
+
+ if (a_tmp->len != b_tmp->len) {
+ if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped)) {
+ a_tmp = &ipv4_mapped;
+ } else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped)) {
+ b_tmp = &ipv4_mapped;
+ }
+ }
+
+ if (a_tmp->len < b_tmp->len) {
+ return -1;
+ } else if (a_tmp->len > b_tmp->len) {
+ return 1;
+ }
+
+ return memcmp(&a_tmp->ss, &b_tmp->ss, a_tmp->len);
+}
+
+int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
+{
+ const struct ast_sockaddr *a_tmp, *b_tmp;
+ struct ast_sockaddr ipv4_mapped;
+ const struct in_addr *ip4a, *ip4b;
+ const struct in6_addr *ip6a, *ip6b;
+ int ret = -1;
+
+ a_tmp = a;
+ b_tmp = b;
+
+ if (a_tmp->len != b_tmp->len) {
+ if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped)) {
+ a_tmp = &ipv4_mapped;
+ } else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped)) {
+ b_tmp = &ipv4_mapped;
+ }
+ }
+
+ if (a->len < b->len) {
+ ret = -1;
+ } else if (a->len > b->len) {
+ ret = 1;
+ }
+
+ switch (a_tmp->ss.ss_family) {
+ case AF_INET:
+ ip4a = &((const struct sockaddr_in*)&a_tmp->ss)->sin_addr;
+ ip4b = &((const struct sockaddr_in*)&b_tmp->ss)->sin_addr;
+ ret = memcmp(ip4a, ip4b, sizeof(*ip4a));
+ break;
+ case AF_INET6:
+ ip6a = &((const struct sockaddr_in6*)&a_tmp->ss)->sin6_addr;
+ ip6b = &((const struct sockaddr_in6*)&b_tmp->ss)->sin6_addr;
+ ret = memcmp(ip6a, ip6b, sizeof(*ip6a));
+ break;
+ }
+ return ret;
+}
+
+uint16_t ast_sockaddr_port(const struct ast_sockaddr *addr)
+{
+ if (addr->ss.ss_family == AF_INET &&
+ addr->len == sizeof(struct sockaddr_in)) {
+ return ntohs(((struct sockaddr_in *)&addr->ss)->sin_port);
+ } else if (addr->ss.ss_family == AF_INET6 &&
+ addr->len == sizeof(struct sockaddr_in6)) {
+ return ntohs(((struct sockaddr_in6 *)&addr->ss)->sin6_port);
+ }
+ ast_log(LOG_ERROR, "Not an IPv4 nor IPv6 address, cannot get port.\n");
+ return 0;
+}
+
+void ast_sockaddr_set_port(struct ast_sockaddr *addr, uint16_t port)
+{
+ if (addr->ss.ss_family == AF_INET &&
+ addr->len == sizeof(struct sockaddr_in)) {
+ ((struct sockaddr_in *)&addr->ss)->sin_port = htons(port);
+ } else if (addr->ss.ss_family == AF_INET6 &&
+ addr->len == sizeof(struct sockaddr_in6)) {
+ ((struct sockaddr_in6 *)&addr->ss)->sin6_port = htons(port);
+ } else {
+ ast_log(LOG_ERROR,
+ "Not an IPv4 nor IPv6 address, cannot set port.\n");
+ }
+}
+
+uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
+{
+ const struct sockaddr_in *sin = (struct sockaddr_in *)&addr->ss;
+ return ntohl(sin->sin_addr.s_addr);
+}
+
+int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
+{
+ return addr->ss.ss_family == AF_INET &&
+ addr->len == sizeof(struct sockaddr_in);
+}
+
+int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
+{
+ const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr->ss;
+ return addr->len && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr);
+}
+
+int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
+{
+ return addr->ss.ss_family == AF_INET6 &&
+ addr->len == sizeof(struct sockaddr_in6);
+}
+
+int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
+{
+ return (ast_sockaddr_is_ipv4(addr) &&
+ ((const struct sockaddr_in *)&addr->ss)->sin_addr.s_addr ==
+ INADDR_ANY) ||
+ (ast_sockaddr_is_ipv6(addr) &&
+ IN6_IS_ADDR_UNSPECIFIED(&((const struct sockaddr_in6 *)&addr->ss)->sin6_addr));
+}
+
+int ast_sockaddr_hash(const struct ast_sockaddr *addr)
+{
+ /*
+ * For IPv4, return the IP address as-is. For IPv6, return the last 32
+ * bits.
+ */
+ switch (addr->ss.ss_family) {
+ case AF_INET:
+ return ((const struct sockaddr_in *)&addr->ss)->sin_addr.s_addr;
+ case AF_INET6:
+ return ((uint32_t *)&((const struct sockaddr_in6 *)&addr->ss)->sin6_addr)[3];
+ default:
+ ast_log(LOG_ERROR, "Unknown address family '%d'.\n",
+ addr->ss.ss_family);
+ return 0;
+ }
+}
+
+int ast_accept(int sockfd, struct ast_sockaddr *addr)
+{
+ addr->len = sizeof(addr->ss);
+ return accept(sockfd, (struct sockaddr *)&addr->ss, &addr->len);
+}
+
+int ast_bind(int sockfd, const struct ast_sockaddr *addr)
+{
+ return bind(sockfd, (const struct sockaddr *)&addr->ss, addr->len);
+}
+
+int ast_connect(int sockfd, const struct ast_sockaddr *addr)
+{
+ return connect(sockfd, (const struct sockaddr *)&addr->ss, addr->len);
+}
+
+int ast_getsockname(int sockfd, struct ast_sockaddr *addr)
+{
+ addr->len = sizeof(addr->ss);
+ return getsockname(sockfd, (struct sockaddr *)&addr->ss, &addr->len);
+}
+
+ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct ast_sockaddr *src_addr)
+{
+ src_addr->len = sizeof(src_addr->ss);
+ return recvfrom(sockfd, buf, len, flags,
+ (struct sockaddr *)&src_addr->ss, &src_addr->len);
+}
+
+ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct ast_sockaddr *dest_addr)
+{
+ return sendto(sockfd, buf, len, flags,
+ (const struct sockaddr *)&dest_addr->ss, dest_addr->len);
+}
+
+int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
+{
+ int res;
+
+ if ((res = setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) {
+ ast_log(LOG_WARNING, "Unable to set %s TOS to %d (may be you have no "
+ "root privileges): %s\n", desc, tos, strerror(errno));
+ } else if (tos) {
+ ast_verb(2, "Using %s TOS bits %d\n", desc, tos);
+ }
+
+#ifdef linux
+ if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &cos, sizeof(cos))) {
+ ast_log(LOG_WARNING, "Unable to set %s CoS to %d: %s\n", desc, cos,
+ strerror(errno));
+ } else if (cos) {
+ ast_verb(2, "Using %s CoS mark %d\n", desc, cos);
+ }
+#endif
+
+ return res;
+}
+
+int ast_sockaddr_to_sin(const struct ast_sockaddr *addr,
+ struct sockaddr_in *sin)
+{
+ if (ast_sockaddr_isnull(addr)) {
+ memset(sin, 0, sizeof(*sin));
+ return 1;
+ }
+
+ if (addr->len != sizeof(*sin)) {
+ ast_log(LOG_ERROR, "Bad address cast to IPv4\n");
+ return 0;
+ }
+
+ if (addr->ss.ss_family != AF_INET) {
+ ast_log(LOG_DEBUG, "Address family is not AF_INET\n");
+ }
+
+ *sin = *(struct sockaddr_in *)&addr->ss;
+ return 1;
+}
+
+void ast_sockaddr_from_sin(struct ast_sockaddr *addr, const struct sockaddr_in *sin)
+{
+ *((struct sockaddr_in *)&addr->ss) = *sin;
+
+ if (addr->ss.ss_family != AF_INET) {
+ ast_log(LOG_DEBUG, "Address family is not AF_INET\n");
+ }
+
+ addr->len = sizeof(*sin);
+}
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index eeaa008a8..d23056b5f 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/pbx.h"
#include "asterisk/translate.h"
+#include "asterisk/netsock2.h"
struct ast_srtp_res *res_srtp = NULL;
struct ast_srtp_policy_res *res_srtp_policy = NULL;
@@ -51,11 +52,11 @@ struct ast_rtp_instance {
/*! RTP properties that have been set and their value */
int properties[AST_RTP_PROPERTY_MAX];
/*! Address that we are expecting RTP to come in to */
- struct sockaddr_in local_address;
+ struct ast_sockaddr local_address;
/*! Address that we are sending RTP to */
- struct sockaddr_in remote_address;
+ struct ast_sockaddr remote_address;
/*! Alternate address that we are receiving RTP from */
- struct sockaddr_in alt_remote_address;
+ struct ast_sockaddr alt_remote_address;
/*! Instance that we are bridged to if doing remote or local bridging */
struct ast_rtp_instance *bridged;
/*! Payload and packetization information */
@@ -294,9 +295,11 @@ int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
return 0;
}
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data)
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
+ struct sched_context *sched, const struct ast_sockaddr *sa,
+ void *data)
{
- struct sockaddr_in address = { 0, };
+ struct ast_sockaddr address = {{0,}};
struct ast_rtp_instance *instance = NULL;
struct ast_rtp_engine *engine = NULL;
@@ -331,11 +334,8 @@ struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sc
return NULL;
}
instance->engine = engine;
- instance->local_address.sin_family = AF_INET;
- instance->local_address.sin_addr = sin->sin_addr;
- instance->remote_address.sin_family = AF_INET;
- address.sin_family = AF_INET;
- address.sin_addr = sin->sin_addr;
+ ast_sockaddr_copy(&instance->local_address, sa);
+ ast_sockaddr_copy(&address, sa);
ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
@@ -371,17 +371,17 @@ struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int r
return instance->engine->read(instance, rtcp);
}
-int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance,
+ const struct ast_sockaddr *address)
{
- instance->local_address.sin_addr = address->sin_addr;
- instance->local_address.sin_port = address->sin_port;
+ ast_sockaddr_copy(&instance->local_address, address);
return 0;
}
-int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance,
+ const struct ast_sockaddr *address)
{
- instance->remote_address.sin_addr = address->sin_addr;
- instance->remote_address.sin_port = address->sin_port;
+ ast_sockaddr_copy(&instance->remote_address, address);
/* moo */
@@ -392,10 +392,10 @@ int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struc
return 0;
}
-int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance,
+ const struct ast_sockaddr *address)
{
- instance->alt_remote_address.sin_addr = address->sin_addr;
- instance->alt_remote_address.sin_port = address->sin_port;
+ ast_sockaddr_copy(&instance->alt_remote_address, address);
/* oink */
@@ -406,24 +406,22 @@ int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, s
return 0;
}
-int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance,
+ struct ast_sockaddr *address)
{
- if ((address->sin_family != AF_INET) ||
- (address->sin_port != instance->local_address.sin_port) ||
- (address->sin_addr.s_addr != instance->local_address.sin_addr.s_addr)) {
- memcpy(address, &instance->local_address, sizeof(*address));
+ if (ast_sockaddr_cmp(address, &instance->local_address) != 0) {
+ ast_sockaddr_copy(address, &instance->local_address);
return 1;
}
return 0;
}
-int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
+int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance,
+ struct ast_sockaddr *address)
{
- if ((address->sin_family != AF_INET) ||
- (address->sin_port != instance->remote_address.sin_port) ||
- (address->sin_addr.s_addr != instance->remote_address.sin_addr.s_addr)) {
- memcpy(address, &instance->remote_address, sizeof(*address));
+ if (ast_sockaddr_cmp(address, &instance->remote_address) != 0) {
+ ast_sockaddr_copy(address, &instance->remote_address);
return 1;
}
@@ -959,8 +957,8 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
enum ast_bridge_result res = AST_BRIDGE_FAILED;
struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
format_t oldcodec0 = codec0, oldcodec1 = codec1;
- struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
- struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
+ struct ast_sockaddr ac1 = {{0,}}, vac1 = {{0,}}, tac1 = {{0,}}, ac0 = {{0,}}, vac0 = {{0,}}, tac0 = {{0,}};
+ struct ast_sockaddr t1 = {{0,}}, vt1 = {{0,}}, tt1 = {{0,}}, t0 = {{0,}}, vt0 = {{0,}}, tt0 = {{0,}};
struct ast_frame *fr = NULL;
/* Test the first channel */
@@ -1035,44 +1033,59 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
codec0 = glue0->get_codec(c0);
}
- if ((inaddrcmp(&t1, &ac1)) ||
- (vinstance1 && inaddrcmp(&vt1, &vac1)) ||
- (tinstance1 && inaddrcmp(&tt1, &tac1)) ||
+ if ((ast_sockaddr_cmp(&t1, &ac1)) ||
+ (vinstance1 && ast_sockaddr_cmp(&vt1, &vac1)) ||
+ (tinstance1 && ast_sockaddr_cmp(&tt1, &tac1)) ||
(codec1 != oldcodec1)) {
- ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %s)\n",
- c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), ast_getformatname(codec1));
- ast_debug(1, "Oooh, '%s' changed end vaddress to %s:%d (format %s)\n",
- c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), ast_getformatname(codec1));
- ast_debug(1, "Oooh, '%s' changed end taddress to %s:%d (format %s)\n",
- c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), ast_getformatname(codec1));
- ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
- c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), ast_getformatname(oldcodec1));
- ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
- c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), ast_getformatname(oldcodec1));
- ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
- c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), ast_getformatname(oldcodec1));
- if (glue0->update_peer(c0, t1.sin_addr.s_addr ? instance1 : NULL, vt1.sin_addr.s_addr ? vinstance1 : NULL, tt1.sin_addr.s_addr ? tinstance1 : NULL, codec1, 0)) {
+ ast_debug(1, "Oooh, '%s' changed end address to %s (format %s)\n",
+ c1->name, ast_sockaddr_stringify(&t1),
+ ast_getformatname(codec1));
+ ast_debug(1, "Oooh, '%s' changed end vaddress to %s (format %s)\n",
+ c1->name, ast_sockaddr_stringify(&vt1),
+ ast_getformatname(codec1));
+ ast_debug(1, "Oooh, '%s' changed end taddress to %s (format %s)\n",
+ c1->name, ast_sockaddr_stringify(&tt1),
+ ast_getformatname(codec1));
+ ast_debug(1, "Oooh, '%s' was %s/(format %s)\n",
+ c1->name, ast_sockaddr_stringify(&ac1),
+ ast_getformatname(oldcodec1));
+ ast_debug(1, "Oooh, '%s' was %s/(format %s)\n",
+ c1->name, ast_sockaddr_stringify(&vac1),
+ ast_getformatname(oldcodec1));
+ ast_debug(1, "Oooh, '%s' was %s/(format %s)\n",
+ c1->name, ast_sockaddr_stringify(&tac1),
+ ast_getformatname(oldcodec1));
+ if (glue0->update_peer(c0,
+ ast_sockaddr_isnull(&t1) ? NULL : instance1,
+ ast_sockaddr_isnull(&vt1) ? NULL : vinstance1,
+ ast_sockaddr_isnull(&tt1) ? NULL : tinstance1,
+ codec1, 0)) {
ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
}
- memcpy(&ac1, &t1, sizeof(ac1));
- memcpy(&vac1, &vt1, sizeof(vac1));
- memcpy(&tac1, &tt1, sizeof(tac1));
+ ast_sockaddr_copy(&ac1, &t1);
+ ast_sockaddr_copy(&vac1, &vt1);
+ ast_sockaddr_copy(&tac1, &tt1);
oldcodec1 = codec1;
}
- if ((inaddrcmp(&t0, &ac0)) ||
- (vinstance0 && inaddrcmp(&vt0, &vac0)) ||
- (tinstance0 && inaddrcmp(&tt0, &tac0)) ||
+ if ((ast_sockaddr_cmp(&t0, &ac0)) ||
+ (vinstance0 && ast_sockaddr_cmp(&vt0, &vac0)) ||
+ (tinstance0 && ast_sockaddr_cmp(&tt0, &tac0)) ||
(codec0 != oldcodec0)) {
- ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %s)\n",
- c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), ast_getformatname(codec0));
- ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
- c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), ast_getformatname(oldcodec0));
- if (glue1->update_peer(c1, t0.sin_addr.s_addr ? instance0 : NULL, vt0.sin_addr.s_addr ? vinstance0 : NULL, tt0.sin_addr.s_addr ? tinstance0 : NULL, codec0, 0)) {
+ ast_debug(1, "Oooh, '%s' changed end address to %s (format %s)\n",
+ c0->name, ast_sockaddr_stringify(&t0),
+ ast_getformatname(codec0));
+ ast_debug(1, "Oooh, '%s' was %s/(format %s)\n",
+ c0->name, ast_sockaddr_stringify(&ac0),
+ ast_getformatname(oldcodec0));
+ if (glue1->update_peer(c1, t0.len ? instance0 : NULL,
+ vt0.len ? vinstance0 : NULL,
+ tt0.len ? tinstance0 : NULL,
+ codec0, 0)) {
ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
}
- memcpy(&ac0, &t0, sizeof(ac0));
- memcpy(&vac0, &vt0, sizeof(vac0));
- memcpy(&tac0, &tt0, sizeof(tac0));
+ ast_sockaddr_copy(&ac0, &t0);
+ ast_sockaddr_copy(&vac0, &vt0);
+ ast_sockaddr_copy(&tac0, &tt0);
oldcodec0 = codec0;
}
@@ -1122,9 +1135,9 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
}
/* Update local address information */
ast_rtp_instance_get_remote_address(instance0, &t0);
- memcpy(&ac0, &t0, sizeof(ac0));
+ ast_sockaddr_copy(&ac0, &t0);
ast_rtp_instance_get_remote_address(instance1, &t1);
- memcpy(&ac1, &t1, sizeof(ac1));
+ ast_sockaddr_copy(&ac1, &t1);
/* Update codec information */
if (glue0->get_codec && c0->tech_pvt) {
oldcodec0 = codec0 = glue0->get_codec(c0);
@@ -1201,6 +1214,7 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as
*vinstance0 = NULL, *vinstance1 = NULL,
*tinstance0 = NULL, *tinstance1 = NULL;
struct ast_rtp_glue *glue0, *glue1;
+ struct ast_sockaddr addr1, addr2;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_bridge_result res = AST_BRIDGE_FAILED;
@@ -1249,6 +1263,17 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as
goto done;
}
+
+ /* If address families differ, force a local bridge */
+ ast_rtp_instance_get_remote_address(instance0, &addr1);
+ ast_rtp_instance_get_remote_address(instance1, &addr2);
+
+ if (addr1.ss.ss_family != addr2.ss.ss_family ||
+ (ast_sockaddr_is_ipv4_mapped(&addr1) != ast_sockaddr_is_ipv4_mapped(&addr2))) {
+ audio_glue0_res = AST_RTP_GLUE_RESULT_LOCAL;
+ audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
+ }
+
/* If we need to get DTMF see if we can do it outside of the RTP stream itself */
if ((flags & AST_BRIDGE_DTMF_CHANNEL_0) && instance0->properties[AST_RTP_PROPERTY_DTMF]) {
res = AST_BRIDGE_FAILED_NOWARN;
@@ -1640,7 +1665,9 @@ int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
return instance->engine->activate ? instance->engine->activate(instance) : 0;
}
-void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
+void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance,
+ struct ast_sockaddr *suggestion,
+ const char *username)
{
if (instance->engine->stun_request) {
instance->engine->stun_request(instance, suggestion, username);
diff --git a/main/tcptls.c b/main/tcptls.c
index 8c95502e7..b505f2a01 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -235,8 +235,7 @@ void *ast_tcptls_server_root(void *data)
{
struct ast_tcptls_session_args *desc = data;
int fd;
- struct sockaddr_in sin;
- socklen_t sinlen;
+ struct ast_sockaddr addr;
struct ast_tcptls_session_instance *tcptls_session;
pthread_t launched;
@@ -248,8 +247,7 @@ void *ast_tcptls_server_root(void *data)
i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout);
if (i <= 0)
continue;
- sinlen = sizeof(sin);
- fd = accept(desc->accept_fd, (struct sockaddr *) &sin, &sinlen);
+ fd = ast_accept(desc->accept_fd, &addr);
if (fd < 0) {
if ((errno != EAGAIN) && (errno != EINTR))
ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
@@ -268,7 +266,7 @@ void *ast_tcptls_server_root(void *data)
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
tcptls_session->fd = fd;
tcptls_session->parent = desc;
- memcpy(&tcptls_session->remote_address, &sin, sizeof(tcptls_session->remote_address));
+ ast_sockaddr_copy(&tcptls_session->remote_address, &addr);
tcptls_session->client = 0;
@@ -373,10 +371,10 @@ struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_se
goto client_start_error;
}
- if (connect(desc->accept_fd, (const struct sockaddr *) &desc->remote_address, sizeof(desc->remote_address))) {
- ast_log(LOG_ERROR, "Unable to connect %s to %s:%d: %s\n",
+ if (ast_connect(desc->accept_fd, &desc->remote_address)) {
+ ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n",
desc->name,
- ast_inet_ntoa(desc->remote_address.sin_addr), ntohs(desc->remote_address.sin_port),
+ ast_sockaddr_stringify(&desc->remote_address),
strerror(errno));
goto client_start_error;
}
@@ -407,17 +405,18 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s
struct ast_tcptls_session_instance *tcptls_session = NULL;
/* Do nothing if nothing has changed */
- if (!memcmp(&desc->old_address, &desc->remote_address, sizeof(desc->old_address))) {
+ if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
ast_debug(1, "Nothing changed in %s\n", desc->name);
return NULL;
}
- desc->old_address = desc->remote_address;
+ ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
if (desc->accept_fd != -1)
close(desc->accept_fd);
- desc->accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ?
+ AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (desc->accept_fd < 0) {
ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n",
desc->name, strerror(errno));
@@ -426,12 +425,12 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s
/* if a local address was specified, bind to it so the connection will
originate from the desired address */
- if (desc->local_address.sin_family != 0) {
+ if (!ast_sockaddr_isnull(&desc->local_address)) {
setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
- if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) {
- ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n",
- desc->name,
- ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port),
+ if (ast_bind(desc->accept_fd, &desc->local_address)) {
+ ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
+ desc->name,
+ ast_sockaddr_stringify(&desc->local_address),
strerror(errno));
goto error;
}
@@ -445,7 +444,8 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s
tcptls_session->fd = desc->accept_fd;
tcptls_session->parent = desc;
tcptls_session->parent->worker_fn = NULL;
- memcpy(&tcptls_session->remote_address, &desc->remote_address, sizeof(tcptls_session->remote_address));
+ ast_sockaddr_copy(&tcptls_session->remote_address,
+ &desc->remote_address);
return tcptls_session;
@@ -463,12 +463,12 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
int x = 1;
/* Do nothing if nothing has changed */
- if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) {
+ if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
ast_debug(1, "Nothing changed in %s\n", desc->name);
return;
}
- desc->old_address = desc->local_address;
+ ast_sockaddr_copy(&desc->old_address, &desc->local_address);
/* Shutdown a running server if there is one */
if (desc->master != AST_PTHREADT_NULL) {
@@ -481,22 +481,23 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
close(desc->accept_fd);
/* If there's no new server, stop here */
- if (desc->local_address.sin_family == 0) {
+ if (ast_sockaddr_isnull(&desc->local_address)) {
ast_debug(2, "Server disabled: %s\n", desc->name);
return;
}
- desc->accept_fd = socket(AF_INET, SOCK_STREAM, 0);
+ desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ?
+ AF_INET6 : AF_INET, SOCK_STREAM, 0);
if (desc->accept_fd < 0) {
ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
return;
}
setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
- if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) {
- ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n",
+ if (ast_bind(desc->accept_fd, &desc->local_address)) {
+ ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
desc->name,
- ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port),
+ ast_sockaddr_stringify(&desc->local_address),
strerror(errno));
goto error;
}
@@ -507,9 +508,9 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
flags = fcntl(desc->accept_fd, F_GETFL);
fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
- ast_log(LOG_ERROR, "Unable to launch thread for %s on %s:%d: %s\n",
+ ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
desc->name,
- ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port),
+ ast_sockaddr_stringify(&desc->local_address),
strerror(errno));
goto error;
}
@@ -537,7 +538,6 @@ int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_
{
if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
tls_cfg->enabled = ast_true(value) ? 1 : 0;
- tls_desc->local_address.sin_family = AF_INET;
} else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
ast_free(tls_cfg->certfile);
tls_cfg->certfile = ast_strdup(value);
@@ -558,10 +558,8 @@ int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_
} else if (!strcasecmp(varname, "tlsdontverifyserver")) {
ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER);
} else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
- if (ast_parse_arg(value, PARSE_INADDR, &tls_desc->local_address))
+ if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value);
- } else if (!strcasecmp(varname, "tlsbindport") || !strcasecmp(varname, "sslbindport")) {
- tls_desc->local_address.sin_port = htons(atoi(value));
} else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
if (!strcasecmp(value, "tlsv1")) {
ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index b896d64fa..4ab06e4fb 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -35,7 +35,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
-#include <math.h>
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
@@ -45,7 +44,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
-#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
@@ -87,8 +85,8 @@ static int rtpdebug; /*!< Are we debugging? */
static int rtcpdebug; /*!< Are we debugging RTCP? */
static int rtcpstats; /*!< Are we debugging RTCP? */
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
-static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
-static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
+static struct ast_sockaddr rtpdebugaddr; /*!< Debug packets to/from this host */
+static struct ast_sockaddr rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
#ifdef SO_NO_CHECK
static int nochecksums;
#endif
@@ -168,8 +166,8 @@ struct ast_rtp {
struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
- struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
- struct sockaddr_in alt_rtp_address; /*!<Alternate remote address information */
+ struct ast_sockaddr strict_rtp_address; /*!< Remote address information for strict RTP purposes */
+ struct ast_sockaddr alt_rtp_address; /*!<Alternate remote address information */
struct rtp_red *red;
};
@@ -187,8 +185,8 @@ struct ast_rtp {
struct ast_rtcp {
int rtcp_info;
int s; /*!< Socket */
- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
+ struct ast_sockaddr us; /*!< Socket representation of the local endpoint. */
+ struct ast_sockaddr them; /*!< Socket representation of the remote endpoint. */
unsigned int soc; /*!< What they told us */
unsigned int spc; /*!< What they told us */
unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
@@ -253,7 +251,7 @@ struct rtp_red {
AST_LIST_HEAD_NOLOCK(frame_list, ast_frame);
/* Forward Declarations */
-static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
+static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
static int ast_rtp_destroy(struct ast_rtp_instance *instance);
static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
@@ -263,14 +261,14 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
-static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
-static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr);
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr);
static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
-static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
static void ast_rtp_stop(struct ast_rtp_instance *instance);
/* RTP Engine Declaration */
@@ -297,45 +295,31 @@ static struct ast_rtp_engine asterisk_rtp_engine = {
.stop = ast_rtp_stop,
};
-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
+static inline int rtp_debug_test_addr(struct ast_sockaddr *addr)
{
if (!rtpdebug) {
return 0;
}
- if (rtpdebugaddr.sin_addr.s_addr) {
- if (((ntohs(rtpdebugaddr.sin_port) != 0)
- && (rtpdebugaddr.sin_port != addr->sin_port))
- || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
-
- return 1;
+ return ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0;
}
-static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
+static inline int rtcp_debug_test_addr(struct ast_sockaddr *addr)
{
if (!rtcpdebug) {
return 0;
}
- if (rtcpdebugaddr.sin_addr.s_addr) {
- if (((ntohs(rtcpdebugaddr.sin_port) != 0)
- && (rtcpdebugaddr.sin_port != addr->sin_port))
- || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
-
- return 1;
+ return ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0;
}
-static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t *salen, int rtcp)
+static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
{
int len;
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
- if ((len = recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa, salen)) < 0) {
+ if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
return len;
}
@@ -346,17 +330,17 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
return len;
}
-static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t *salen)
+static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
{
- return __rtp_recvfrom(instance, buf, size, flags, sa, salen, 1);
+ return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
}
-static int rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t *salen)
+static int rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
{
- return __rtp_recvfrom(instance, buf, size, flags, sa, salen, 0);
+ return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
}
-static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t salen, int rtcp)
+static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
{
int len = size;
void *temp = buf;
@@ -367,17 +351,17 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
return -1;
}
- return sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa, salen);
+ return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa);
}
-static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t salen)
+static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
{
- return __rtp_sendto(instance, buf, size, flags, sa, salen, 1);
+ return __rtp_sendto(instance, buf, size, flags, sa, 1);
}
-static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t salen)
+static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
{
- return __rtp_sendto(instance, buf, size, flags, sa, salen, 0);
+ return __rtp_sendto(instance, buf, size, flags, sa, 0);
}
static int rtp_get_rate(format_t subclass)
@@ -423,9 +407,9 @@ static double stddev_compute(double stddev, double sample, double normdev, doubl
#undef SQUARE
}
-static int create_new_socket(const char *type)
+static int create_new_socket(const char *type, int af)
{
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ int sock = socket(af, SOCK_DGRAM, 0);
if (sock < 0) {
if (!type) {
@@ -445,7 +429,9 @@ static int create_new_socket(const char *type)
return sock;
}
-static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
+static int ast_rtp_new(struct ast_rtp_instance *instance,
+ struct sched_context *sched, struct ast_sockaddr *addr,
+ void *data)
{
struct ast_rtp *rtp = NULL;
int x, startplace;
@@ -461,7 +447,10 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *
rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
/* Create a new socket for us to listen on and use */
- if ((rtp->s = create_new_socket("RTP")) < 0) {
+ if ((rtp->s =
+ create_new_socket("RTP",
+ ast_sockaddr_is_ipv4(addr) ? AF_INET :
+ ast_sockaddr_is_ipv6(addr) ? AF_INET6 : -1)) < 0) {
ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
ast_free(rtp);
return -1;
@@ -473,11 +462,11 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *
startplace = x;
for (;;) {
- sin->sin_port = htons(x);
+ ast_sockaddr_set_port(addr, x);
/* Try to bind, this will tell us whether the port is available or not */
- if (!bind(rtp->s, (struct sockaddr *)sin, sizeof(*sin))) {
+ if (!ast_bind(rtp->s, addr)) {
ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
- ast_rtp_instance_set_local_address(instance, sin);
+ ast_rtp_instance_set_local_address(instance, addr);
break;
}
@@ -538,7 +527,7 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
int hdrlen = 12, res = 0, i = 0, payload = 101;
char data[256];
unsigned int *rtpheader = (unsigned int*)data;
@@ -546,7 +535,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* If we have no remote address information bail out now */
- if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+ if (ast_sockaddr_isnull(&remote_address)) {
return -1;
}
@@ -581,15 +570,16 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
/* Actually send the packet */
for (i = 0; i < 2; i++) {
rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
- res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+ res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
if (res < 0) {
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
- ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+ ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
}
if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_sockaddr_stringify(&remote_address),
+ payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
}
rtp->seqno++;
rtp->send_duration += 160;
@@ -607,7 +597,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
int hdrlen = 12, res = 0;
char data[256];
unsigned int *rtpheader = (unsigned int*)data;
@@ -615,7 +605,7 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* Make sure we know where the other side is so we can send them the packet */
- if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+ if (ast_sockaddr_isnull(&remote_address)) {
return -1;
}
@@ -627,17 +617,17 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
/* Boom, send it on out */
- res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+ res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
if (res < 0) {
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
- ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), strerror(errno));
+ ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
}
if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_sockaddr_stringify(&remote_address),
+ rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
}
/* And now we increment some values for the next time we swing by */
@@ -650,7 +640,7 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
int hdrlen = 12, res = 0, i = 0;
char data[256];
unsigned int *rtpheader = (unsigned int*)data;
@@ -658,7 +648,7 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* Make sure we know where the remote side is so we can send them the packet we construct */
- if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+ if (ast_sockaddr_isnull(&remote_address)) {
return -1;
}
@@ -690,16 +680,16 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
/* Send it 3 times, that's the magical number */
for (i = 0; i < 3; i++) {
- res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+ res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
if (res < 0) {
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
- ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), strerror(errno));
+ ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
}
if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_sockaddr_stringify(&remote_address),
+ rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
}
}
@@ -785,10 +775,10 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
double rxlost_current;
- if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
+ if (!rtp || !rtp->rtcp)
return 0;
- if (!rtp->rtcp->them.sin_addr.s_addr) {
+ if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
return 0;
@@ -841,7 +831,7 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
len += 12;
- res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+ res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
if (res < 0) {
ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
@@ -852,13 +842,12 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
rtp->rtcp->rr_count++;
if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
- ast_verbose("\n* Sending RTCP RR to %s:%d\n"
+ ast_verbose("\n* Sending RTCP RR to %s\n"
" Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
" IA jitter: %.4f\n"
" Their last SR: %u\n"
" DLSR: %4.4f (sec)\n\n",
- ast_inet_ntoa(rtp->rtcp->them.sin_addr),
- ntohs(rtp->rtcp->them.sin_port),
+ ast_sockaddr_stringify(&rtp->rtcp->them),
rtp->ssrc, rtp->themssrc, fraction, lost,
rtp->rxjitter,
rtp->rtcp->themrxlsr,
@@ -888,11 +877,10 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
struct timeval dlsr;
char bdata[512];
- /* Commented condition is always not NULL if rtp->rtcp is not NULL */
- if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
+ if (!rtp || !rtp->rtcp)
return 0;
- if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
+ if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
ast_verbose("RTCP SR transmission error, rtcp halted\n");
AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
return 0;
@@ -941,9 +929,11 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
len += 12;
- res =rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+ res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
if (res < 0) {
- ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
+ ast_log(LOG_ERROR, "RTCP SR transmission error to %s, rtcp halted %s\n",
+ ast_sockaddr_stringify(&rtp->rtcp->them),
+ strerror(errno));
AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
return 0;
}
@@ -955,7 +945,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
rtp->rtcp->lastsrtxcount = rtp->txcount;
if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
- ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+ ast_verbose("* Sent RTCP SR to %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
@@ -968,7 +958,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
}
- manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
+ manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s\r\n"
"OurSSRC: %u\r\n"
"SentNTP: %u.%010u\r\n"
"SentRTP: %u\r\n"
@@ -980,7 +970,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
"IAJitter: %.4f\r\n"
"TheirLastSR: %u\r\n"
"DLSR: %4.4f (sec)\r\n",
- ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
+ ast_sockaddr_stringify(&rtp->rtcp->them),
rtp->ssrc,
(unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
rtp->lastts,
@@ -1019,7 +1009,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
int pred, mark = 0;
unsigned int ms = calc_txstamp(rtp, &frame->delivery);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
int rate = rtp_get_rate(frame->subclass.codec) / 1000;
if (frame->subclass.codec == AST_FORMAT_G722) {
@@ -1094,7 +1084,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* If we know the remote address construct a packet and send it out */
- if (remote_address.sin_port && remote_address.sin_addr.s_addr) {
+ if (!ast_sockaddr_isnull(&remote_address)) {
int hdrlen = 12, res;
unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
@@ -1102,13 +1092,17 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
- if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, (struct sockaddr *)&remote_address, sizeof(remote_address))) < 0) {
+ if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, &remote_address)) < 0) {
if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
- ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+ ast_debug(1, "RTP Transmission error of packet %d to %s: %s\n",
+ rtp->seqno,
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
} else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
/* Only give this error message once if we are not RTP debugging */
if (option_debug || rtpdebug)
- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+ ast_debug(0, "RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
+ ast_sockaddr_stringify(&remote_address));
ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
}
} else {
@@ -1122,8 +1116,9 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
}
if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), codec, rtp->seqno, rtp->lastts, res - hdrlen);
+ ast_verbose("Sent RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_sockaddr_stringify(&remote_address),
+ codec, rtp->seqno, rtp->lastts, res - hdrlen);
}
}
@@ -1172,13 +1167,13 @@ static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
format_t codec, subclass;
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* If we don't actually know the remote address don't even bother doing anything */
- if (!remote_address.sin_addr.s_addr) {
+ if (ast_sockaddr_isnull(&remote_address)) {
ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
return 0;
}
@@ -1341,17 +1336,19 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
ast_rtp_instance_get_remote_address(instance, &remote_address);
if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
- ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(remote_address.sin_addr));
+ ast_debug(1, "Ignore potential DTMF echo from '%s'\n",
+ ast_sockaddr_stringify(&remote_address));
rtp->resp = 0;
rtp->dtmfsamples = 0;
return &ast_null_frame;
}
- ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(remote_address.sin_addr));
+ ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp,
+ ast_sockaddr_stringify(&remote_address));
if (rtp->resp == 'X') {
rtp->f.frametype = AST_FRAME_CONTROL;
rtp->f.subclass.integer = AST_CONTROL_FLASH;
@@ -1368,10 +1365,10 @@ static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, en
return &rtp->f;
}
-static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark, struct frame_list *frames)
+static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark, struct frame_list *frames)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
unsigned int event, event_end, samples;
char resp = 0;
struct ast_frame *f = NULL;
@@ -1388,8 +1385,9 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
samples &= 0xFFFF;
if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(remote_address.sin_addr),
- ntohs(remote_address.sin_port), payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
+ ast_verbose("Got RTP RFC2833 from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n",
+ ast_sockaddr_stringify(&remote_address),
+ payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
}
/* Print out debug if turned on */
@@ -1492,7 +1490,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
return;
}
-static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
+static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
unsigned int event, flags, power;
@@ -1571,7 +1569,7 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
return f;
}
-static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
+static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
@@ -1582,12 +1580,12 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len);
if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
ast_rtp_instance_get_remote_address(instance, &remote_address);
- ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
- ast_inet_ntoa(remote_address.sin_addr));
+ ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
+ ast_sockaddr_stringify(&remote_address));
ast_set_flag(rtp, FLAG_3389_WARNING);
}
@@ -1615,15 +1613,16 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
+ struct ast_sockaddr addr;
unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
int res, packetwords, position = 0;
struct ast_frame *f = &ast_null_frame;
/* Read in RTCP data from the socket */
- if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
+ if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
+ sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
+ 0, &addr)) < 0) {
ast_assert(errno != EBADF);
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
@@ -1636,11 +1635,11 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
/* Send to whoever sent to us */
- if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (rtp->rtcp->them.sin_port != sin.sin_port)) {
- memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
+ if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
+ ast_sockaddr_copy(&rtp->rtcp->them, &addr);
if (option_debug || rtpdebug)
- ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+ ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
+ ast_sockaddr_stringify(&rtp->rtcp->them));
}
}
@@ -1665,8 +1664,9 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
return &ast_null_frame;
}
- if (rtcp_debug_test_addr(&sin)) {
- ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ if (rtcp_debug_test_addr(&addr)) {
+ ast_verbose("\n\nGot RTCP from %s\n",
+ ast_sockaddr_stringify(&addr));
ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
ast_verbose("Reception reports: %d\n", rc);
ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
@@ -1685,7 +1685,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
- if (rtcp_debug_test_addr(&sin)) {
+ if (rtcp_debug_test_addr(&addr)) {
ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
@@ -1735,7 +1735,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
rtp->rtcp->normdevrtt = normdevrtt_current;
rtp->rtcp->rtt_count++;
- } else if (rtcp_debug_test_addr(&sin)) {
+ } else if (rtcp_debug_test_addr(&addr)) {
ast_verbose("Internal RTCP NTP clock skew detected: "
"lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
"diff=%d\n",
@@ -1784,7 +1784,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
rtp->rtcp->reported_jitter_count++;
- if (rtcp_debug_test_addr(&sin)) {
+ if (rtcp_debug_test_addr(&addr)) {
ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
@@ -1796,7 +1796,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
}
if (rtt) {
- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
"PT: %d(%s)\r\n"
"ReceptionReports: %d\r\n"
"SenderSSRC: %u\r\n"
@@ -1808,7 +1808,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
"LastSR: %lu.%010lu\r\n"
"DLSR: %4.4f(sec)\r\n"
"RTT: %llu(sec)\r\n",
- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+ ast_sockaddr_stringify(&addr),
pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
rc,
rtcpheader[i + 1],
@@ -1821,7 +1821,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
ntohl(rtcpheader[i + 5])/65536.0,
(unsigned long long)rtt);
} else {
- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
"PT: %d(%s)\r\n"
"ReceptionReports: %d\r\n"
"SenderSSRC: %u\r\n"
@@ -1832,7 +1832,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
"IAJitter: %u\r\n"
"LastSR: %lu.%010lu\r\n"
"DLSR: %4.4f(sec)\r\n",
- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+ ast_sockaddr_stringify(&addr),
pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
rc,
rtcpheader[i + 1],
@@ -1847,7 +1847,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
}
break;
case RTCP_PT_FUR:
- if (rtcp_debug_test_addr(&sin))
+ if (rtcp_debug_test_addr(&addr))
ast_verbose("Received an RTCP Fast Update Request\n");
rtp->f.frametype = AST_FRAME_CONTROL;
rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
@@ -1858,15 +1858,18 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
f = &rtp->f;
break;
case RTCP_PT_SDES:
- if (rtcp_debug_test_addr(&sin))
- ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+ if (rtcp_debug_test_addr(&addr))
+ ast_verbose("Received an SDES from %s\n",
+ ast_sockaddr_stringify(&rtp->rtcp->them));
break;
case RTCP_PT_BYE:
- if (rtcp_debug_test_addr(&sin))
- ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+ if (rtcp_debug_test_addr(&addr))
+ ast_verbose("Received a BYE from %s\n",
+ ast_sockaddr_stringify(&rtp->rtcp->them));
break;
default:
- ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+ ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n",
+ pt, ast_sockaddr_stringify(&rtp->rtcp->them));
break;
}
position += (length + 1);
@@ -1884,7 +1887,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
int res = 0, payload = 0, bridged_payload = 0, mark;
struct ast_rtp_payload_type payload_type;
int reconstruct = ntohl(rtpheader[0]);
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
/* Get fields from packet */
payload = (reconstruct & 0x7f0000) >> 16;
@@ -1916,18 +1919,27 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
ast_rtp_instance_get_remote_address(instance1, &remote_address);
/* Send the packet back out */
- res = rtp_sendto(instance1, (void *)rtpheader, len, 0, (struct sockaddr *)&remote_address, sizeof(remote_address));
+ res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address);
if (res < 0) {
if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
- ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+ ast_log(LOG_WARNING,
+ "RTP Transmission error of packet to %s: %s\n",
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
} else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
if (option_debug || rtpdebug)
- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+ ast_log(LOG_WARNING,
+ "RTP NAT: Can't write RTP to private "
+ "address %s, waiting for other end to "
+ "send audio...\n",
+ ast_sockaddr_stringify(&remote_address));
ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
}
return 0;
} else if (rtp_debug_test_addr(&remote_address)) {
- ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bridged_payload, len - hdrlen);
+ ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n",
+ ast_sockaddr_stringify(&remote_address),
+ bridged_payload, len - hdrlen);
}
return 0;
@@ -1936,12 +1948,11 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
+ struct ast_sockaddr addr;
int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
struct ast_rtp_payload_type payload;
- struct sockaddr_in remote_address = { 0, };
+ struct ast_sockaddr remote_address = { {0,} };
struct frame_list frames;
/* If this is actually RTCP let's hop on over and handle it */
@@ -1958,7 +1969,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
}
/* Actually read in the data from the socket */
- if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr*)&sin, &len)) < 0) {
+ if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET,
+ sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0,
+ &addr)) < 0) {
ast_assert(errno != EBADF);
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
@@ -1975,16 +1988,19 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
/* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
- memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
+ ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
rtp->strict_rtp_state = STRICT_RTP_CLOSED;
} else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
- if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
+ if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
/* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
- if ((rtp->alt_rtp_address.sin_addr.s_addr == sin.sin_addr.s_addr) && (rtp->alt_rtp_address.sin_port == sin.sin_port)) {
+ if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
/* ooh, we did! You're now the new expected address, son! */
- rtp->strict_rtp_address = sin;
+ ast_sockaddr_copy(&rtp->strict_rtp_address,
+ &addr);
} else {
- ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
+ ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n",
+ ast_sockaddr_stringify(&addr),
+ ast_sockaddr_stringify(&rtp->strict_rtp_address));
return &ast_null_frame;
}
}
@@ -1996,27 +2012,30 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
ast_rtp_instance_get_remote_address(instance, &remote_address);
if (!(version = (seqno & 0xC0000000) >> 30)) {
- if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
- (!remote_address.sin_port && !remote_address.sin_addr.s_addr)) {
- ast_rtp_instance_set_remote_address(instance, &sin);
+ struct sockaddr_in addr_tmp;
+ ast_sockaddr_to_sin(&addr, &addr_tmp);
+ if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
+ ast_sockaddr_isnull(&remote_address)) {
+ ast_sockaddr_from_sin(&addr, &addr_tmp);
+ ast_rtp_instance_set_remote_address(instance, &addr);
}
return &ast_null_frame;
}
/* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
- if ((remote_address.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (remote_address.sin_port != sin.sin_port)) {
- ast_rtp_instance_set_remote_address(instance, &sin);
- memcpy(&remote_address, &sin, sizeof(remote_address));
+ if (ast_sockaddr_cmp(&remote_address, &addr)) {
+ ast_rtp_instance_set_remote_address(instance, &addr);
+ ast_sockaddr_copy(&remote_address, &addr);
if (rtp->rtcp) {
- memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
- rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
+ ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+ ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
}
rtp->rxseqno = 0;
ast_set_flag(rtp, FLAG_NAT_ACTIVE);
if (option_debug || rtpdebug)
- ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+ ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n",
+ ast_sockaddr_stringify(&remote_address));
}
}
@@ -2097,7 +2116,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
}
/* Do not schedule RR if RTCP isn't run */
- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+ if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) {
/* Schedule transmission of Receiver Report */
rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
}
@@ -2111,9 +2130,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
}
- if (rtp_debug_test_addr(&sin)) {
- ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
+ if (rtp_debug_test_addr(&addr)) {
+ ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_sockaddr_stringify(&addr),
+ payloadtype, seqno, timestamp,res - hdrlen);
}
payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
@@ -2126,13 +2146,15 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
* by passing the pointer to the frame list to it so that the method
* can append frames to the list as needed.
*/
- process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark, &frames);
+ process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
} else if (payload.code == AST_RTP_CISCO_DTMF) {
- f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
+ f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
} else if (payload.code == AST_RTP_CN) {
- f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
+ f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
} else {
- ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(remote_address.sin_addr));
+ ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
+ payloadtype,
+ ast_sockaddr_stringify(&remote_address));
}
if (f) {
@@ -2283,19 +2305,26 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
return;
}
- if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
+
+ /* Grab the IP address and port we are going to use */
+ ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
+ ast_sockaddr_set_port(&rtp->rtcp->us,
+ ast_sockaddr_port(&rtp->rtcp->us) + 1);
+
+ if ((rtp->rtcp->s =
+ create_new_socket("RTCP",
+ ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
+ AF_INET :
+ ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
+ AF_INET6 : -1)) < 0) {
ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
ast_free(rtp->rtcp);
rtp->rtcp = NULL;
return;
}
- /* Grab the IP address and port we are going to use */
- ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
- rtp->rtcp->us.sin_port = htons(ntohs(rtp->rtcp->us.sin_port) + 1);
-
/* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
- if (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
+ if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
close(rtp->rtcp->s);
ast_free(rtp->rtcp);
@@ -2319,14 +2348,17 @@ static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
}
-static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
if (rtp->rtcp) {
ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
- memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
- rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
+ ast_sockaddr_copy(&rtp->rtcp->them, addr);
+ if (!ast_sockaddr_isnull(addr)) {
+ ast_sockaddr_set_port(&rtp->rtcp->them,
+ ast_sockaddr_port(addr) + 1);
+ }
}
rtp->rxseqno = 0;
@@ -2338,14 +2370,14 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
return;
}
-static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
/* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
* RTCP from an "unexpected" source
*/
- rtp->alt_rtp_address = *sin;
+ ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
return;
}
@@ -2485,17 +2517,20 @@ static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_ins
(!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
}
-static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ struct sockaddr_in suggestion_tmp;
- ast_stun_request(rtp->s, suggestion, username, NULL);
+ ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
+ ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
+ ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
}
static void ast_rtp_stop(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct sockaddr_in sin = { 0, };
+ struct ast_sockaddr addr = { {0,} };
if (rtp->rtcp) {
AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
@@ -2506,10 +2541,9 @@ static void ast_rtp_stop(struct ast_rtp_instance *instance)
rtp->red = NULL;
}
- ast_rtp_instance_set_remote_address(instance, &sin);
+ ast_rtp_instance_set_remote_address(instance, &addr);
if (rtp->rtcp) {
- memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
- memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
+ ast_sockaddr_setnull(&rtp->rtcp->them);
}
ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
@@ -2517,60 +2551,28 @@ static void ast_rtp_stop(struct ast_rtp_instance *instance)
static char *rtp_do_debug_ip(struct ast_cli_args *a)
{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p, *arg = ast_strdupa(a->argv[4]);
-
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL) {
+ char *arg = ast_strdupa(a->argv[4]);
+
+ if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0)) {
ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
return CLI_FAILURE;
}
- rtpdebugaddr.sin_family = AF_INET;
- memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
- rtpdebugaddr.sin_port = htons(port);
- if (port == 0) {
- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
- } else {
- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
- }
+ ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
+ ast_sockaddr_stringify(&rtpdebugaddr));
rtpdebug = 1;
return CLI_SUCCESS;
}
static char *rtcp_do_debug_ip(struct ast_cli_args *a)
{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p, *arg = ast_strdupa(a->argv[4]);
-
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL) {
+ char *arg = ast_strdupa(a->argv[4]);
+
+ if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0)) {
ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
return CLI_FAILURE;
}
- rtcpdebugaddr.sin_family = AF_INET;
- memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
- rtcpdebugaddr.sin_port = htons(port);
- if (port == 0) {
- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
- } else {
- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
- }
+ ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n",
+ ast_sockaddr_stringify(&rtcpdebugaddr));
rtcpdebug = 1;
return CLI_SUCCESS;
}
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index b58f4b36e..19d21bcfb 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -44,7 +44,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
-#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
@@ -90,7 +89,7 @@ struct multicast_rtp {
};
/* Forward Declarations */
-static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
+static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
static int multicast_rtp_activate(struct ast_rtp_instance *instance);
static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
@@ -107,7 +106,7 @@ static struct ast_rtp_engine multicast_rtp_engine = {
};
/*! \brief Function called to create a new multicast instance */
-static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
+static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
{
struct multicast_rtp *multicast;
const char *type = data;
@@ -143,22 +142,30 @@ static int multicast_send_control_packet(struct ast_rtp_instance *instance, stru
struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
.command = htonl(command),
};
- struct sockaddr_in control_address, remote_address;
+ struct ast_sockaddr control_address, remote_address;
ast_rtp_instance_get_local_address(instance, &control_address);
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* Ensure the user of us have given us both the control address and destination address */
- if (!control_address.sin_addr.s_addr || !remote_address.sin_addr.s_addr) {
+ if (ast_sockaddr_isnull(&control_address) ||
+ ast_sockaddr_isnull(&remote_address)) {
return -1;
}
- control_packet.ip = remote_address.sin_addr.s_addr;
- control_packet.port = htonl(ntohs(remote_address.sin_port));
+ /* The protocol only supports IPv4. */
+ if (ast_sockaddr_is_ipv6(&remote_address)) {
+ ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
+ "remote address.\n");
+ return -1;
+ }
+
+ control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
+ control_packet.port = htonl(ast_sockaddr_port(&remote_address));
/* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
- sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, (struct sockaddr *)&control_address, sizeof(control_address));
- sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, (struct sockaddr *)&control_address, sizeof(control_address));
+ ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
+ ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
return 0;
}
@@ -196,7 +203,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
{
struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
struct ast_frame *f = frame;
- struct sockaddr_in remote_address;
+ struct ast_sockaddr remote_address;
int hdrlen = 12, res, codec;
unsigned char *rtpheader;
@@ -223,11 +230,12 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
/* Finally send it out to the eager phones listening for us */
ast_rtp_instance_get_remote_address(instance, &remote_address);
- res = sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+ res = ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address);
if (res < 0) {
- ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s:%u: %s\n",
- ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+ ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
+ ast_sockaddr_stringify(&remote_address),
+ strerror(errno));
}
/* If we were forced to duplicate the frame free the new one */