summaryrefslogtreecommitdiff
path: root/channels/sip/config_parser.c
diff options
context:
space:
mode:
authorTerry Wilson <twilson@digium.com>2012-02-09 18:14:39 +0000
committerTerry Wilson <twilson@digium.com>2012-02-09 18:14:39 +0000
commite5c51ee44c79950ff90660f29ae4b78ce8cc06d2 (patch)
tree4a25b55ca8c3dcb00699c36ec270f0ff25750ca3 /channels/sip/config_parser.c
parent8f5c33f95a44347308fa9987ddad0598ba060522 (diff)
Add auto_force_rport and auto_comedia NAT options
This patch adds the auto_force_rport and auto_comedia NAT options. It also converts the nat= setting to a list of comma-separated combinable options: no, force_rport, comedia, auto_force_rport, and auto_comedia. nat=yes remains as an undocumented option equal to "force_rport,comedia". The first instance of 'yes' or 'no' in the list stops parsing and overrides any previously set options. If an auto_* option is specified with its non-auto_ counterpart, the auto setting takes precedence. This patch builds upon the patch posted to ASTERISK-17860 by JIRA user pedro-garcia. (closes issue ASTERISK-17860) Review: https://reviewboard.asterisk.org/r/1698/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@354597 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/sip/config_parser.c')
-rw-r--r--channels/sip/config_parser.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/channels/sip/config_parser.c b/channels/sip/config_parser.c
index 72a7b2c7d..55695e545 100644
--- a/channels/sip/config_parser.c
+++ b/channels/sip/config_parser.c
@@ -765,11 +765,128 @@ AST_TEST_DEFINE(sip_parse_host_line_test)
}
+/*! \brief Parse the comma-separated nat= option values */
+void sip_parse_nat_option(const char *value, struct ast_flags *mask, struct ast_flags *flags)
+{
+ char *parse, *this;
+
+ if (!(parse = ast_strdupa(value))) {
+ return;
+ }
+
+ /* Since we need to completely override the general settings if we are being called
+ * later for a peer, always set the flags for all options on the mask */
+ ast_set_flag(&mask[0], SIP_NAT_FORCE_RPORT);
+ ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP);
+ ast_set_flag(&mask[2], SIP_PAGE3_NAT_AUTO_RPORT);
+ ast_set_flag(&mask[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
+
+ while ((this = strsep(&parse, ","))) {
+ if (ast_false(this)) {
+ ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT);
+ ast_clear_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
+ ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
+ ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
+ break; /* It doesn't make sense to have no + something else */
+ } else if (!strcasecmp(this, "yes")) {
+ ast_log(LOG_WARNING, "nat=yes is deprecated, use nat=force_rport,comedia instead\n");
+ ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
+ ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
+ ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
+ ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
+ break; /* It doesn't make sense to have yes + something else */
+ } else if (!strcasecmp(this, "force_rport") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+ ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
+ } else if (!strcasecmp(this, "comedia") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+ ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
+ } else if (!strcasecmp(this, "auto_force_rport")) {
+ ast_set_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
+ /* In case someone did something dumb like nat=force_rport,auto_force_rport */
+ ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT);
+ } else if (!strcasecmp(this, "auto_comedia")) {
+ ast_set_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
+ /* In case someone did something dumb like nat=comedia,auto_comedia*/
+ ast_clear_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
+ }
+ }
+}
+
+#define TEST_FORCE_RPORT 1 << 0
+#define TEST_COMEDIA 1 << 1
+#define TEST_AUTO_FORCE_RPORT 1 << 2
+#define TEST_AUTO_COMEDIA 1 << 3
+static int match_nat_options(int val, struct ast_flags *flags)
+{
+ if ((!ast_test_flag(&flags[0], SIP_NAT_FORCE_RPORT)) != !(val & TEST_FORCE_RPORT)) {
+ return 0;
+ }
+ if (!ast_test_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP) != !(val & TEST_COMEDIA)) {
+ return 0;
+ }
+ if (!ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT) != !(val & TEST_AUTO_FORCE_RPORT)) {
+ return 0;
+ }
+ if (!ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) != !(val & TEST_AUTO_COMEDIA)) {
+ return 0;
+ }
+ return 1;
+}
+
+AST_TEST_DEFINE(sip_parse_nat_test)
+{
+ int i, res = AST_TEST_PASS;
+ struct ast_flags mask[3] = {{0}}, flags[3] = {{0}};
+ struct {
+ const char *str;
+ int i;
+ } options[] = {
+ { "yes", TEST_FORCE_RPORT | TEST_COMEDIA },
+ { "no", 0 },
+ { "force_rport", TEST_FORCE_RPORT },
+ { "comedia", TEST_COMEDIA },
+ { "auto_force_rport", TEST_AUTO_FORCE_RPORT },
+ { "auto_comedia", TEST_AUTO_COMEDIA },
+ { "force_rport,auto_force_rport", TEST_AUTO_FORCE_RPORT },
+ { "auto_force_rport,force_rport", TEST_AUTO_FORCE_RPORT },
+ { "comedia,auto_comedia", TEST_AUTO_COMEDIA },
+ { "auto_comedia,comedia", TEST_AUTO_COMEDIA },
+ { "force_rport,comedia", TEST_FORCE_RPORT | TEST_COMEDIA },
+ { "force_rport,auto_comedia", TEST_FORCE_RPORT | TEST_AUTO_COMEDIA },
+ { "force_rport,yes,no", TEST_FORCE_RPORT | TEST_COMEDIA },
+ { "auto_comedia,no,yes", 0 },
+ };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "sip_parse_nat_test";
+ info->category = "/channels/chan_sip/";
+ info->summary = "tests sip.conf nat line parsing";
+ info->description =
+ "Tests parsing of various nat line configurations. "
+ "Verifies output matches expected behavior.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ for (i = 0; i < ARRAY_LEN(options); i++) {
+ sip_parse_nat_option(options[i].str, mask, flags);
+ if (!match_nat_options(options[i].i, flags)) {
+ ast_test_status_update(test, "Failed nat=%s\n", options[i].str);
+ res = AST_TEST_FAIL;
+ }
+ memset(flags, 0, sizeof(flags));
+ memset(mask, 0, sizeof(mask));
+ }
+
+ return res;
+}
/*! \brief SIP test registration */
void sip_config_parser_register_tests(void)
{
AST_TEST_REGISTER(sip_parse_register_line_test);
AST_TEST_REGISTER(sip_parse_host_line_test);
+ AST_TEST_REGISTER(sip_parse_nat_test);
}
/*! \brief SIP test registration */
@@ -777,5 +894,6 @@ void sip_config_parser_unregister_tests(void)
{
AST_TEST_UNREGISTER(sip_parse_register_line_test);
AST_TEST_UNREGISTER(sip_parse_host_line_test);
+ AST_TEST_UNREGISTER(sip_parse_nat_test);
}