Add IPv6 to Asterisk.

This adds a generic API for accommodating IPv6 and IPv4 addresses
within Asterisk. While many files have been updated to make use of the
API, chan_sip and the RTP code are the files which actually support
IPv6 addresses at the time of this commit. The way has been paved for
easier upgrading for other files in the near future, though.

Big thanks go to Simon Perrault, Marc Blanchet, and Jean-Philippe Dionne
for their hard work on this.

(closes issue #17565)
Reported by: russell
Patches: 
      asteriskv6-test-report.pdf uploaded by russell (license 2)

Review: https://reviewboard.asterisk.org/r/743



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@274783 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Mark Michelson 15 years ago
parent 816f26c16c
commit cd4ebd336f

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

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

@ -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;
}

@ -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));

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

@ -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") ||

@ -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));

@ -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;
}
}
}

@ -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;
}
}

File diff suppressed because it is too large Load Diff

@ -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")) {

@ -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];

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

@ -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);

@ -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 */

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

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

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

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

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

@ -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 */

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

@ -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 */

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

@ -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;
};

@ -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);

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

@ -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 */

@ -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);

@ -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));
}
}

@ -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);

@ -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);
}

@ -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);

@ -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);

File diff suppressed because it is too large Load Diff

@ -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 */

Loading…
Cancel
Save