--- ./channels/chan_sip.c 2014-08-08 13:01:59.000000000 +0100 +++ ./channels/chan_sip.c 2014-08-13 09:39:09.000000000 +0100 @@ -910,9 +910,12 @@ struct ast_str *data; /* XXX Do we need to unref socket.ser when the request goes away? */ struct sip_socket socket; /*!< The socket used for this request */ + char chan_bindhost[MAXHOSTNAMELEN];/* used to pass IP address string */ AST_LIST_ENTRY(sip_request) next; }; +#define MAXROUTE_TABLELEN 64 + /* \brief given a sip_request and an offset, return the char * that resides there * * It used to be that rlPart1, rlPart2, and the header and line arrays were character @@ -1836,6 +1839,10 @@ static struct sockaddr_in bindaddr; /*!< UDP: The address we bind to */ +struct in_addr remote_addr[MAXROUTE_TABLELEN]; /*! remote addresses to search for binding */ +struct in_addr local_bindaddr[MAXROUTE_TABLELEN]; /*! corrisponding bind addresses */ + + /*! \brief our (internal) default address/port to put in SIP/SDP messages * internip is initialized picking a suitable address from one of the * interfaces, and the same port number we bind to. It is used as the @@ -6747,7 +6754,8 @@ return NULL; } - if (req) { + /* req can be null and have req->chan_bindhost */ + if (req && req->socket.type) { set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */ } else { set_socket_transport(&p->socket, SIP_TRANSPORT_UDP); @@ -6791,7 +6799,82 @@ p->ocseq = INITIAL_CSEQ; if (sip_methods[intended_method].need_rtp) { - p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); + /* Leaving original asteirks code */ + + struct in_addr destip,chan_bindaddr; + chan_bindaddr.s_addr = 0; + char desthost[MAXHOSTNAMELEN];//store host string + inet_aton(desthost,&destip); + + /* Calls comming in first leg else there is a call originating from this box i.e second leg */ + if ( sin != NULL ) { + + /* Source address of packet used to map to local_bindaddr addresses. This search and mapping could be */ + /* avoided if the arrival interface of the call could be passed into this function */ + unsigned int i=0; + for (i=0; i < sizeof(remote_addr) / sizeof(remote_addr[0]);i++) { + if ( sin->sin_addr.s_addr == remote_addr[i].s_addr ) { + ast_log(LOG_NOTICE, "sip_request_call ########### source matched as %s ###\n",ast_inet_ntoa(remote_addr[i]));//########## + ast_log(LOG_NOTICE, "sip_request_call ########### binding locally as %s ###\n",ast_inet_ntoa(local_bindaddr[i]));//########## + chan_bindaddr.s_addr = local_bindaddr[i].s_addr; + } + } + ast_log(LOG_NOTICE, "sip_alloc ############## binding on %s first leg\n",ast_inet_ntoa(chan_bindaddr)); + + } else { + + /* Get IP address from destination to pass to sip_alloc in the req */ + unsigned ipbytes[4]; + sscanf(req->chan_bindhost, "%*d@%d.%d.%d.%d:",&ipbytes[0], &ipbytes[1], &ipbytes[2], &ipbytes[3]); + + sprintf(desthost,"%d.%d.%d.%d",ipbytes[0],ipbytes[1],ipbytes[2],ipbytes[3]); + + inet_aton(desthost,&destip); + + ast_log(LOG_NOTICE, "####### Hostip %d.%d.%d.%d \n",ipbytes[0],ipbytes[1],ipbytes[2],ipbytes[3]); + ast_log(LOG_NOTICE, "####### chan bind host %s \n",req->chan_bindhost); + //ast_log(LOG_NOTICE, "####### chan sin.sin_addr %s \n",ast_inet_ntoa(sin->sin_addr)); + ast_log(LOG_NOTICE, "####### destip ipaddress %s \n",ast_inet_ntoa(destip)); + /* search for matching remote ip address destinations */ + unsigned int i=0; + for (i=0; i < sizeof(remote_addr) / sizeof(remote_addr[0]);i++) { + if ( destip.s_addr == remote_addr[i].s_addr ) { + ast_log(LOG_NOTICE, "####### destination matched as %s \n",ast_inet_ntoa(remote_addr[i])); + ast_log(LOG_NOTICE, "####### binding locally as %s \n",ast_inet_ntoa(local_bindaddr[i])); + chan_bindaddr.s_addr = local_bindaddr[i].s_addr; + } + } + + /* If desthost did not match maybe its a hostname */ + if ( !chan_bindaddr.s_addr ) { + sscanf(req->chan_bindhost, "%*d@%*d-%s:",desthost);//our hostnames have a prefix of "X-" which is discarded to leave the real hostname. + ast_log(LOG_NOTICE, "####### hostname %s \n",desthost); + struct ast_hostent ahp; + struct hostent *hp; + hp = ast_gethostbyname(desthost,&ahp); + /* if the hostname did resolve */ + if (hp) { + destip = **(struct in_addr **)hp->h_addr_list; + ast_log(LOG_NOTICE, "############ resolved ipaddress %s \n",ast_inet_ntoa(destip)); + } else { + ast_log(LOG_WARNING, "Could not look up IP address of hostname.\n"); + } + + /* Search and map using the IP address having been resolved. */ + unsigned int i=0; + for (i=0; i < sizeof(remote_addr) / sizeof(remote_addr[0]);i++) { + if ( destip.s_addr == remote_addr[i].s_addr ) { + ast_log(LOG_NOTICE, "####### destination matched as %s \n",ast_inet_ntoa(remote_addr[i])); + ast_log(LOG_NOTICE, "####### binding locally as %s \n",ast_inet_ntoa(local_bindaddr[i])); + chan_bindaddr.s_addr = local_bindaddr[i].s_addr; + } + } + } + ast_log(LOG_NOTICE, "sip_alloc ############## binding on %s second leg \n",ast_inet_ntoa(chan_bindaddr)); + } + + p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, chan_bindaddr ); + //p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); /* If the global videosupport flag is on, we always create a RTP interface for video */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT)) p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); @@ -22177,7 +22260,14 @@ } ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat)); - if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL))) { + + /* Get dest string to and pass to sip_alloc in the req */ + + struct sip_request *req; + ast_copy_string(req->chan_bindhost,dest,sizeof(tmp)); + ast_log(LOG_NOTICE, "####### sip_request_call dest string: %s \n",req->chan_bindhost); + + if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, req))) { ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest); *cause = AST_CAUSE_SWITCH_CONGESTION; return NULL; @@ -23525,9 +23615,32 @@ ast_clear_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION); ast_clear_flag(&global_flags[1], SIP_PAGE2_FAX_DETECT); + unsigned i=0; /* initalise global IP address arrays */ + for ( i=0;i < MAXROUTE_TABLELEN - 1;i++) { + remote_addr[i].s_addr = 0; + local_bindaddr[i].s_addr = 0; + } /* Read the [general] config section of sip.conf (or from realtime config) */ for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { + unsigned i=0; + char buf[MAXHOSTNAMELEN];/* Temporarily holds IP address string*/ + for ( i=0;i < MAXROUTE_TABLELEN - 1;i++) { + snprintf(buf, sizeof(buf),"remoteaddr%u",i); + if (!memcmp(v->name, buf,strlen(buf))) { + inet_aton(v->value, &remote_addr[i]); + ast_log(LOG_NOTICE, "Remote IP %s \n",ast_inet_ntoa(remote_addr[i])); + } + } + + for ( i=0;i < MAXROUTE_TABLELEN - 1;i++) { + snprintf(buf, sizeof(buf),"localbindaddr%u",i); + if (!memcmp(v->name, buf,strlen(buf))) { + inet_aton(v->value, &local_bindaddr[i]); + ast_log(LOG_NOTICE, "Local Bind IP ip %s \n",ast_inet_ntoa(local_bindaddr[i])); + } + } + if (handle_common_options(&global_flags[0], &dummy[0], v)) continue; if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) {