Module: sip-router
Branch: master
Commit: c486a9358f146ac2b3e5047021c197c3eb6b41d8
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c486a93…
Author: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley(a)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);