--- channels/chan_sip.c.orig 2011-11-15 16:24:31.000000000 +0100 +++ channels/chan_sip.c 2011-12-03 14:35:00.000000000 +0100 @@ -14810,6 +14810,11 @@ ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name); res = AUTH_PEER_NOT_DYNAMIC; } else { + if (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO)) { + ast_copy_flags(&peer->flags[0], &p->flags[0], SIP_NAT_FORCE_RPORT); + ast_copy_flags(&peer->flags[1], &p->flags[1], SIP_PAGE2_SYMMETRICRTP); + } + ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT_FORCE_RPORT); if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri2, XMIT_UNRELIABLE, req->ignore))) { if (sip_cancel_destroy(p)) @@ -15895,6 +15900,17 @@ ast_sockaddr_set_port(&p->sa, port != 0 ? port : STANDARD_SIP_PORT); + if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO) && ast_sockaddr_cmp(&tmp, &p->recv)) { + char new[512]; + snprintf(new, sizeof(new), "%s:%d", + ast_sockaddr_stringify_addr(&p->recv), + ast_sockaddr_port(&p->recv)); + ast_log(LOG_NOTICE, "NAT detected for %s\n", new); + + ast_set_flag(&p->flags[0], SIP_NAT_FORCE_RPORT); + ast_set_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); + } + if (sip_debug_test_pvt(p)) { ast_verbose("Sending to %s (%s)\n", ast_sockaddr_stringify(sip_real_dst(p)), @@ -16890,7 +16906,9 @@ snprintf(srch, sizeof(srch), FORMAT, name, ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr), peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ - ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ + ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO) ? + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " ): + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " " ), /* NAT=yes? */ peer->ha ? " A " : " ", /* permit/deny */ ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status, peer->description ? peer->description : "", @@ -16900,7 +16918,9 @@ ast_cli(fd, FORMAT, name, ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr), peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ - ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ + ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO) ? + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " ): + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " " ), /* NAT=yes? */ peer->ha ? " A " : " ", /* permit/deny */ ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status, peer->description ? peer->description : "", @@ -16927,7 +16947,9 @@ ast_sockaddr_isnull(&peer->addr) ? "-none-" : ast_sockaddr_stringify_fmt(&peer->addr, AST_SOCKADDR_STR_HOST), ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ - ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */ + ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO) ? + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "auto:yes" : "auto:no" ): + ( ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no" ), /* NAT=yes? */ ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ peer->ha ? "yes" : "no", /* permit/deny */ @@ -17576,6 +17598,7 @@ ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); + ast_cli(fd, " NAT auto : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO))); ast_cli(fd, " Force rport : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT))); ast_cli(fd, " ACL : %s\n", AST_CLI_YESNO(peer->ha != NULL)); ast_cli(fd, " DirectMedACL : %s\n", AST_CLI_YESNO(peer->directmediaha != NULL)); @@ -17687,6 +17710,7 @@ astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); + astman_append(s, "SIP-AutoNAT: %s\r\n", (ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO)?"Y":"N")); astman_append(s, "SIP-Forcerport: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT)?"Y":"N")); astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N")); @@ -18296,6 +18320,7 @@ ast_cli(a->fd, " Allowed transports: %s\n", get_transport_list(default_transports)); ast_cli(a->fd, " Outbound transport: %s\n", sip_get_transport(default_primary_transport)); ast_cli(a->fd, " Context: %s\n", sip_cfg.default_context); + ast_cli(a->fd, " NAT autodetect: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[2], SIP_PAGE3_NAT_AUTO))); ast_cli(a->fd, " Force rport: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[0], SIP_NAT_FORCE_RPORT))); ast_cli(a->fd, " DTMF: %s\n", dtmfmode2str(ast_test_flag(&global_flags[0], SIP_DTMF))); ast_cli(a->fd, " Qualify: %d\n", default_qualify); @@ -18666,6 +18691,7 @@ ast_cli(a->fd, " Theoretical Address: %s\n", ast_sockaddr_stringify(&cur->sa)); ast_cli(a->fd, " Received Address: %s\n", ast_sockaddr_stringify(&cur->recv)); ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer)); + ast_cli(a->fd, " NAT auto: %s\n", AST_CLI_YESNO(ast_test_flag(&cur->flags[2], SIP_PAGE3_NAT_AUTO))); ast_cli(a->fd, " Force rport: %s\n", AST_CLI_YESNO(ast_test_flag(&cur->flags[0], SIP_NAT_FORCE_RPORT))); if (ast_sockaddr_isnull(&cur->redirip)) { ast_cli(a->fd, @@ -26966,8 +26992,8 @@ /*! \brief Handle flag-type options common to configuration of devices - peers - \param flags array of two struct ast_flags - \param mask array of two struct ast_flags + \param flags array of three struct ast_flags + \param mask array of three struct ast_flags \param v linked list of config variables to process \returns non-zero if any config options were handled, zero otherwise */ @@ -27018,18 +27044,28 @@ } } else if (!strcasecmp(v->name, "nat")) { ast_set_flag(&mask[0], SIP_NAT_FORCE_RPORT); + ast_set_flag(&mask[2], SIP_PAGE3_NAT_AUTO); if (!strcasecmp(v->value, "no")) { ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT); + ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO); } else if (!strcasecmp(v->value, "force_rport")) { ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT); + ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO); } else if (!strcasecmp(v->value, "yes")) { ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT); + ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO); ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP); ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP); } else if (!strcasecmp(v->value, "comedia")) { ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT); + ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO); ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP); ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP); + } else if (!strcasecmp(v->value, "auto")) { + ast_set_flag(&flags[2], SIP_PAGE3_NAT_AUTO); + ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP); + ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT); + ast_clear_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP); } } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { ast_set_flag(&mask[0], SIP_REINVITE); @@ -28174,7 +28210,7 @@ struct sip_peer *peer; char *cat, *stringp, *context, *oldregcontext; char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; - struct ast_flags dummy[2]; + struct ast_flags dummy[3]; struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? 0 : CONFIG_FLAG_FILEUNCHANGED }; int auto_sip_domains = FALSE; struct ast_sockaddr old_bindaddr = bindaddr;