From 4cdc6437a6e0b75ca0fdcccd307d7354a5388c97 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 14 Sep 2021 15:06:42 +0200 Subject: Add --remote-nat-sip --remote-nat-rtp --- src/sip/main.c | 32 ++++++++++++++++++++++------- src/sip/sip.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++--------- src/sip/sip.h | 4 +++- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/sip/main.c b/src/sip/main.c index 355a0c0..cd584a8 100644 --- a/src/sip/main.c +++ b/src/sip/main.c @@ -43,6 +43,8 @@ const char *remote_peer = NULL; const char *asserted_id = NULL; int local_register = 0; int remote_register = 0; +int remote_nat_sip = 0; +int remote_nat_rtp = 0; const char *register_user = NULL; const char *register_peer = NULL; int local_auth = 0; @@ -105,6 +107,12 @@ static void print_help() printf(" Define, if we must register to a registrar.\n"); printf(" If '--register' was given, but not any of '--local-register' or\n"); printf(" '--remote-register', remote registration automatically used.\n"); + printf(" --remote-nat-sip\n"); + printf(" Ignore the address+port from the SIP contact. Use the address+port from\n"); + printf(" where the SIP massasge was sent.\n"); + printf(" --remote-nat-rtp\n"); + printf(" Ignore the RTP address from the SDP message. Use the RTP address from\n"); + printf(" the remote peer. (untested!)\n"); printf(" -A --auth \n"); printf(" Define, if we must perform authentication.\n"); printf(" Realm can be set to anything. It is relevant for local authentication.\n"); @@ -135,12 +143,14 @@ static void print_help() #define OPT_RECEIVE_NER 257 #define OPT_LOCAL_REG 258 #define OPT_REMOTE_REG 259 -#define OPT_LOCAL_AUTH 260 -#define OPT_REMOTE_AUTH 261 -#define OPT_REG_INTER 262 -#define OPT_OPT_INTER 263 -#define OPT_STUN_INTER 264 -#define OPT_EXPIRES 265 +#define OPT_REMOTE_SIP 260 +#define OPT_REMOTE_RTP 261 +#define OPT_LOCAL_AUTH 262 +#define OPT_REMOTE_AUTH 263 +#define OPT_REG_INTER 264 +#define OPT_OPT_INTER 265 +#define OPT_STUN_INTER 266 +#define OPT_EXPIRES 267 static void add_options(void) { @@ -156,6 +166,8 @@ static void add_options(void) option_add('R', "register", 1); option_add(OPT_LOCAL_REG, "local-register", 0); option_add(OPT_REMOTE_REG, "remote-register", 0); + option_add(OPT_REMOTE_SIP, "remote-nat-sip", 0); + option_add(OPT_REMOTE_RTP, "remote-nat-rtp", 0); option_add('A', "auth", 3); option_add(OPT_LOCAL_AUTH, "local-auth", 0); option_add(OPT_REMOTE_AUTH, "remote-auth", 0); @@ -237,6 +249,12 @@ static int handle_options(int short_option, int argi, char **argv) case OPT_REMOTE_REG: remote_register = 1; break; + case OPT_REMOTE_SIP: + remote_nat_sip = 1; + break; + case OPT_REMOTE_RTP: + remote_nat_rtp = 1; + break; case 'A': auth_user = options_strdup(argv[argi]); auth_password = options_strdup(argv[argi + 1]); @@ -336,7 +354,7 @@ int main(int argc, char *argv[]) } if (!cc_argc || !!strncasecmp(cc_argv[0], "help", 4)) { - sip_ep = sip_endpoint_create(user_agent, send_no_ringing_after_progress, receive_no_ringing_after_progress, name, local_user, local_peer, remote_user, remote_peer, asserted_id, local_register, remote_register, register_user, register_peer, local_auth, remote_auth, auth_user, auth_password, auth_realm, public_ip, stun_server, register_interval, options_interval, stun_interval, expires); + sip_ep = sip_endpoint_create(user_agent, send_no_ringing_after_progress, receive_no_ringing_after_progress, name, local_user, local_peer, remote_user, remote_peer, asserted_id, local_register, remote_register, remote_nat_sip, remote_nat_rtp, register_user, register_peer, local_auth, remote_auth, auth_user, auth_password, auth_realm, public_ip, stun_server, register_interval, options_interval, stun_interval, expires); if (!sip_ep) { PDEBUG(DSIP, DEBUG_ERROR, "SIP initializing failed!\n"); goto error; diff --git a/src/sip/sip.c b/src/sip/sip.c index ff6ea31..0988213 100644 --- a/src/sip/sip.c +++ b/src/sip/sip.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "sip.h" #ifndef SOFIA_SIP_GCC_4_8_PATCH_APLLIED @@ -167,6 +168,23 @@ static const char *sdp_replace_contact(const char *input, const char *address) return sdp; } +void rtp_peer_nat(sip_endpoint_t *sip_ep, char **sdp_p) +{ + if (sip_ep->remote_nat_rtp && sip_ep->remote_peer[0]) { + /* replace peer by remote contact, note that port in peer is ignored */ + char peer[256], *p; + strcpy(peer, sip_ep->remote_contact_peer); + p = strchr(peer, ':'); + if (*p) + *p = '\0'; + const char *s = sdp_replace_contact(*sdp_p, peer); + free(*sdp_p); + *sdp_p = malloc(strlen(s) + 1); + memcpy(*sdp_p, s, strlen(s)); + (*sdp_p)[strlen(s)] = '\0'; + } +} + /* authenticate (remote) */ static int authenticate(sip_endpoint_t *sip_ep, nua_handle_t *nh, sip_t const *sip) { @@ -510,8 +528,10 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) // contact is set above /* append port of local peer */ p = osmo_cc_port_of_address(call->sip_ep->local_peer); - if (p) + if (p) { + strcat(contact, ":"); strcat(contact, p); + } PDEBUG(DSIP, DEBUG_DEBUG, " -> Contact = %s\n", contact); } @@ -879,13 +899,28 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha if (sip->sip_contact->m_url->url_user) strcpy(contact_user, sip->sip_contact->m_url->url_user); - if (sip->sip_contact->m_url->url_host) { - // FIXME: unstable/might not work with IPv6 - strcpy(contact_peer, sip->sip_contact->m_url->url_host); - if (sip->sip_contact->m_url->url_port && sip->sip_contact->m_url->url_port[0]) { - strcat(contact_peer, ":"); - strcat(contact_peer, sip->sip_contact->m_url->url_port); + if (sip_ep->remote_nat_sip) { + su_addrinfo_t *addrinfo = msg_addrinfo(data->e_msg); + getnameinfo(addrinfo->ai_addr, (socklen_t)addrinfo->ai_addrlen, contact_peer, sizeof(contact_peer), NULL, 0, NI_NUMERICHOST); + switch (addrinfo->ai_addr->sa_family) { + case AF_INET: + sprintf(strchr(contact_peer, '\0'), ":%d", ntohs(((struct sockaddr_in *) addrinfo->ai_addr)->sin_port)); + break; + case AF_INET6: + sprintf(strchr(contact_peer, '\0'), ":%d", ntohs(((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_port)); + break; } + PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by UDP source)\n", contact_user, contact_peer); + } else { + if (sip->sip_contact->m_url->url_host) { + // FIXME: unstable/might not work with IPv6 + strcpy(contact_peer, sip->sip_contact->m_url->url_host); + if (sip->sip_contact->m_url->url_port && sip->sip_contact->m_url->url_port[0]) { + strcat(contact_peer, ":"); + strcat(contact_peer, sip->sip_contact->m_url->url_port); + } + } + PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by remote)\n", contact_user, contact_peer); } if (!sip_ep->local_register) { @@ -899,8 +934,6 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha return; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s\n", contact_user, contact_peer); - if (sip_ep->authenticate_local && sip_ep->auth_realm[0]) { authorization = sip->sip_authorization; status = check_authorization(authorization, "REGISTER", sip_ep->auth_user, sip_ep->auth_password, sip_ep->auth_realm, sip_ep->register_nonce, &auth_text); @@ -1079,6 +1112,7 @@ static void call_i_invite(call_t *call, nua_handle_t *nh, sip_t const *sip) call->sdp_request = malloc(sip->sip_payload->pl_len + 1); memcpy(call->sdp_request, sip->sip_payload->pl_data, sip->sip_payload->pl_len); call->sdp_request[sip->sip_payload->pl_len] = '\0'; + rtp_peer_nat(call->sip_ep, &call->sdp_request); } else { PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); new_state(call, SIP_STATE_IN_INVITE); @@ -1183,6 +1217,7 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand call->sdp_response = malloc(sip->sip_payload->pl_len + 1); memcpy(call->sdp_response, sip->sip_payload->pl_data, sip->sip_payload->pl_len); call->sdp_response[sip->sip_payload->pl_len] = '\0'; + rtp_peer_nat(call->sip_ep, &call->sdp_response); osmo_cc_debug_sdp(call->sdp_response); } else if (!call->sdp_response && status >= 200 && status <= 299) { PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); @@ -1580,6 +1615,12 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t case nua_i_terminated: PDEBUG(DSIP, DEBUG_DEBUG, "terminated received\n"); break; + case nua_i_prack: + PDEBUG(DSIP, DEBUG_DEBUG, "prack indication received\n"); + break; + case nua_r_prack: + PDEBUG(DSIP, DEBUG_DEBUG, "prack response received\n"); + break; default: PDEBUG(DSIP, DEBUG_DEBUG, "Event %d not handled\n", event); } @@ -1671,7 +1712,7 @@ static void register_option_timeout(struct timer *timer) TAG_END()); } -sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires) +sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, int remote_nat_sip, int remote_nat_rtp, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires) { sip_endpoint_t *sip_ep; char local[256]; @@ -1696,6 +1737,8 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_ sip_ep->local_register = local_register; sip_ep->remote_register = remote_register; + sip_ep->remote_nat_sip = remote_nat_sip; + sip_ep->remote_nat_rtp = remote_nat_rtp; sip_ep->register_user = register_user; sip_ep->register_peer = register_peer; @@ -1753,6 +1796,7 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_ NUTAG_AUTOANSWER(0), TAG_IF(expires, NUTAG_SESSION_TIMER(expires)), // wozu das? NUTAG_ALLOW("INFO"), + NUTAG_ALLOW("PRACK"), TAG_NULL()); if (sip_ep->remote_register) diff --git a/src/sip/sip.h b/src/sip/sip.h index 04635bd..da39cd3 100644 --- a/src/sip/sip.h +++ b/src/sip/sip.h @@ -51,6 +51,8 @@ typedef struct sip_endpoint { const char *asserted_id; int local_register; int remote_register; + int remote_nat_sip; + int remote_nat_rtp; const char *register_user; const char *register_peer; int authenticate_local; @@ -109,7 +111,7 @@ typedef struct sip_call { } call_t; void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg); -sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires); +sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, int remote_nat_sip, int remote_nat_rtp, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires); void sip_endpoint_destroy(sip_endpoint_t *sip_ep); int sip_init(int debug_level); void sip_exit(void); -- cgit v1.2.3