aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */