Module: sip-router
Branch: master
Commit: c486a9358f146ac2b3e5047021c197c3eb6b41d8
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c486a9358f146ac2b3e5047021c197c3eb6b41d8

Author: Peter Dunkley <[email protected]>
Committer: Peter Dunkley <[email protected]>
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, &reg_xavp_cfg.s                       
                },
        {"xavp_rcd",           STR_PARAM, &reg_xavp_rcd.s                       
                },
        {"gruu_enabled",       INT_PARAM, &reg_gruu_enabled                     
                },
+       {"outbound_mode",      INT_PARAM, &reg_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);


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to