Module: sip-router Branch: master Commit: c486a9358f146ac2b3e5047021c197c3eb6b41d8 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c486a935...
Author: Peter Dunkley peter.dunkley@crocodile-rcs.com Committer: Peter Dunkley peter.dunkley@crocodile-rcs.com Date: Mon Jan 7 16:08:13 2013 +0000
modules_k/registrar: New outbound_mode parameter
- Controls whether outbound options-tag is required in REGISTER requests and whether they are added to responses to REGISTER requests. - Needed so that an Outbound Edge Proxy can add a Flow-Timer: header to 200 OK responses (to REGISTERs) that contain a Requires: header with the outbound options-tag.
---
modules_k/registrar/reg_mod.c | 7 +++ modules_k/registrar/reg_mod.h | 5 ++ modules_k/registrar/reply.c | 117 +++++++++++++++++++++++++++++++++-------- modules_k/registrar/rerrno.h | 3 +- modules_k/registrar/save.c | 10 ++++ 5 files changed, 119 insertions(+), 23 deletions(-)
diff --git a/modules_k/registrar/reg_mod.c b/modules_k/registrar/reg_mod.c index de4067f..4f83696 100644 --- a/modules_k/registrar/reg_mod.c +++ b/modules_k/registrar/reg_mod.c @@ -119,6 +119,7 @@ int path_use_params = 0; /*!< if the received- and nat-parameters of last Path sruid_t _reg_sruid;
int reg_gruu_enabled = 1; +int reg_outbound_mode = 0;
/* Populate this AVP if testing for specific registration instance. */ char *reg_callid_avp_param = 0; @@ -222,6 +223,7 @@ static param_export_t params[] = { {"xavp_cfg", STR_PARAM, ®_xavp_cfg.s }, {"xavp_rcd", STR_PARAM, ®_xavp_rcd.s }, {"gruu_enabled", INT_PARAM, ®_gruu_enabled }, + {"outbound_mode", INT_PARAM, ®_outbound_mode }, {0, 0, 0} };
@@ -373,6 +375,11 @@ static int mod_init(void) sock_flag = -1; }
+ if (reg_outbound_mode < 0 || reg_outbound_mode > 2) { + LM_ERR("outbound_mode modparam must be 0 (not supported), 1 (supported), or 2 (supported and required)\n"); + return -1; + } + /* fix the flags */ sock_flag = (sock_flag!=-1)?(1<<sock_flag):0; tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0; diff --git a/modules_k/registrar/reg_mod.h b/modules_k/registrar/reg_mod.h index 5033550..04d31fa 100644 --- a/modules_k/registrar/reg_mod.h +++ b/modules_k/registrar/reg_mod.h @@ -67,6 +67,10 @@ #define REG_SAVE_REPL_FL (1<<2) #define REG_SAVE_ALL_FL ((1<<3)-1)
+#define REG_OUTBOUND_NONE 0 +#define REG_OUTBOUND_SUPPORTED 1 +#define REG_OUTBOUND_REQUIRE 2 + extern int nat_flag; extern int tcp_persistent_flag; extern int received_avp; @@ -84,6 +88,7 @@ extern int path_enabled; extern int path_mode; extern int path_use_params; extern int reg_gruu_enabled; +extern int reg_outbound_mode;
extern str sock_hdr_name; extern int sock_flag; diff --git a/modules_k/registrar/reply.c b/modules_k/registrar/reply.c index e403889..5ce444e 100644 --- a/modules_k/registrar/reply.c +++ b/modules_k/registrar/reply.c @@ -373,6 +373,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host) #define MSG_200 "OK" #define MSG_400 "Bad Request" #define MSG_420 "Bad Extension" +#define MSG_421 "Extension Required" #define MSG_500 "Server Internal Error" #define MSG_503 "Service Unavailable"
@@ -406,6 +407,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host) #define EI_R_CALLID_LEN "Callid too long" /* R_CALLID_LEN */ #define EI_R_PARSE_PATH "Path parse error" /* R_PARSE_PATH */ #define EI_R_PATH_UNSUP "No support for found Path indicated" /* R_PATH_UNSUP */ +#define EI_R_OB_UNSUP "No support for Outbound indicated" /* R_OB_UNSUP */
str error_info[] = { {EI_R_FINE, sizeof(EI_R_FINE) - 1}, @@ -437,7 +439,8 @@ str error_info[] = { {EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1}, {EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1}, {EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1}, - {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1} + {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}, + {EI_R_OB_UNSUP, sizeof(EI_R_OB_UNSUP) - 1},
};
@@ -471,7 +474,8 @@ int codes[] = { 400, /* R_CONTACT_LEN */ 400, /* R_CALLID_LEN */ 400, /* R_PARSE_PATH */ - 420 /* R_PATH_UNSUP */ + 420, /* R_PATH_UNSUP */ + 421 /* R_OB_UNSUP */
};
@@ -537,6 +541,46 @@ static int add_unsupported(struct sip_msg* _m, str* _p) LUMP_RPL_HDR | LUMP_RPL_NODUP); return 0; } + +#define REQUIRE "Require: " +#define REQUIRE_LEN (sizeof(REQUIRE) - 1) + +static int add_require(struct sip_msg* _m, str* _p) +{ + char* buf; + + buf = (char*)pkg_malloc(REQUIRE_LEN + _p->len + CRLF_LEN); + if (!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, REQUIRE, REQUIRE_LEN); + memcpy(buf + REQUIRE_LEN, _p->s, _p->len); + memcpy(buf + REQUIRE_LEN + _p->len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, REQUIRE_LEN + _p->len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; +} + +#define SUPPORTED "Supported: " +#define SUPPORTED_LEN (sizeof(SUPPORTED) - 1) + +static int add_supported(struct sip_msg* _m, str* _p) +{ + char* buf; + + buf = (char*)pkg_malloc(SUPPORTED_LEN + _p->len + CRLF_LEN); + if (!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, SUPPORTED, SUPPORTED_LEN); + memcpy(buf + SUPPORTED_LEN, _p->s, _p->len); + memcpy(buf + SUPPORTED_LEN + _p->len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, SUPPORTED_LEN + _p->len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; +}
/*! \brief * Send a reply @@ -544,6 +588,7 @@ static int add_unsupported(struct sip_msg* _m, str* _p) int reg_send_reply(struct sip_msg* _m) { str unsup = str_init(SUPPORTED_PATH_STR); + str outbound_str = str_init(SUPPORTED_OUTBOUND_STR); long code; str msg = str_init(MSG_200); /* makes gcc shut up */ char* buf; @@ -552,34 +597,62 @@ int reg_send_reply(struct sip_msg* _m) add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE); contact.data_len = 0; } - - if (rerrno == R_FINE && path_enabled && _m->path_vec.s) { - if (path_mode != PATH_MODE_OFF) { - if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } - else if (get_supported(_m) & F_SUPPORTED_PATH) { - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } else if (path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; + + switch (rerrno) { + case R_FINE: + if (path_enabled && _m->path_vec.s) { + if (path_mode != PATH_MODE_OFF) { + if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if (add_unsupported(_m, &unsup) < 0) + return -1; + if (add_path(_m, &_m->path_vec) < 0) + return -1; + } + else if (get_supported(_m) & F_SUPPORTED_PATH) { + if (add_path(_m, &_m->path_vec) < 0) + return -1; + } else if (path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if (add_unsupported(_m, &unsup) < 0) + return -1; + if (add_path(_m, &_m->path_vec) < 0) + return -1; + } } } + + switch(reg_outbound_mode) + { + case REG_OUTBOUND_NONE: + default: + break; + case REG_OUTBOUND_REQUIRE: + if (add_require(_m, &outbound_str) < 0) + return -1; + /* Fall-thru */ + case REG_OUTBOUND_SUPPORTED: + if (add_supported(_m, &outbound_str) < 0) + return -1; + break; + } + break; + case R_OB_UNSUP: + if (add_require(_m, &outbound_str) < 0) + return -1; + if (add_supported(_m, &outbound_str) < 0) + return -1; + break; + default: + break; }
code = codes[rerrno]; switch(code) { - case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break; + case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1;break; case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break; case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break; + case 421: msg.s = MSG_420; msg.len = sizeof(MSG_421)-1;break; case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break; case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break; } diff --git a/modules_k/registrar/rerrno.h b/modules_k/registrar/rerrno.h index 5cc1fc4..63add5a 100644 --- a/modules_k/registrar/rerrno.h +++ b/modules_k/registrar/rerrno.h @@ -63,7 +63,8 @@ typedef enum rerr { R_CONTACT_LEN,/*!< Contact URI or RECEIVED too long */ R_CALLID_LEN, /*!< Callid too long */ R_PARSE_PATH, /*!< Error while parsing Path */ - R_PATH_UNSUP /*!< Path not supported by UAC */ + R_PATH_UNSUP, /*!< Path not supported by UAC */ + R_OB_UNSUP /*!< Outbound not supported by UAC */
} rerr_t;
diff --git a/modules_k/registrar/save.c b/modules_k/registrar/save.c index 06bf559..7596c6a 100644 --- a/modules_k/registrar/save.c +++ b/modules_k/registrar/save.c @@ -61,6 +61,7 @@ #include "../../mod_fix.h" #include "../../lib/srutils/sruid.h" #include "../../lib/kcore/cmpapi.h" +#include "../../lib/kcore/parse_supported.h" #include "../../lib/kcore/statistics.h" #ifdef USE_TCP #include "../../tcp_server.h" @@ -840,6 +841,15 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri) if (check_contacts(_m, &st) > 0) { goto error; } + + if (parse_supported(_m) == 0) { + if (!(((struct supported_body *)_m->supported->parsed)->supported_all + & F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) { + LM_WARN("Outbound required by server and not supported by UAC\n"); + rerrno = R_OB_UNSUP; + goto error; + } + } get_act_time(); c = get_first_contact(_m);