|
@@ -34,6 +34,7 @@
|
|
|
#include "../../core/mem/mem.h"
|
|
|
#include "../../core/data_lump.h"
|
|
|
#include "../../core/parser/parse_param.h"
|
|
|
+#include "../../core/parser/parse_uri.h"
|
|
|
#include "../../core/strutils.h"
|
|
|
#include "../../core/dset.h"
|
|
|
|
|
@@ -55,16 +56,34 @@ const static char *proto_strings[] = {
|
|
|
[PROTO_WSS] = "%3Btransport%3Dws",
|
|
|
};
|
|
|
|
|
|
-static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params)
|
|
|
+static char *path_strzdup(char *src, int len)
|
|
|
+{
|
|
|
+ char *res;
|
|
|
+
|
|
|
+ if (!src)
|
|
|
+ return NULL;
|
|
|
+ if(len<0) {
|
|
|
+ len = strlen(src);
|
|
|
+ }
|
|
|
+ if (!(res = (char *) pkg_malloc(len + 1)))
|
|
|
+ return NULL;
|
|
|
+ strncpy(res, src, len);
|
|
|
+ res[len] = 0;
|
|
|
+
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+static int prepend_path(sip_msg_t* _m, str *user, path_param_t param,
|
|
|
+ str *add_params)
|
|
|
{
|
|
|
struct lump *l;
|
|
|
- char *prefix, *suffix, *cp;
|
|
|
+ char *prefix, *suffix, *cp, *dp;
|
|
|
const char *proto_str;
|
|
|
int prefix_len, suffix_len;
|
|
|
struct hdr_field *hf;
|
|
|
|
|
|
/* maximum possible length of suffix */
|
|
|
- suffix_len = strlen(";lr;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
|
|
|
+ suffix_len = sizeof(";lr;r2=on;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
|
|
|
+ IP_ADDR_MAX_STR_SIZE + 2 + (add_params ? add_params->len : 0) + 1;
|
|
|
|
|
|
cp = suffix = pkg_malloc(suffix_len);
|
|
@@ -79,17 +98,32 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
|
|
|
default:
|
|
|
break;
|
|
|
case PATH_PARAM_RECEIVED:
|
|
|
- if (_m->rcv.proto < (sizeof(proto_strings) / sizeof(*proto_strings)))
|
|
|
- proto_str = proto_strings[(unsigned int) _m->rcv.proto];
|
|
|
- else
|
|
|
- proto_str = NULL;
|
|
|
-
|
|
|
- if(_m->rcv.src_ip.af==AF_INET6) {
|
|
|
- cp += sprintf(cp, ";received=sip:[%s]:%hu%s", ip_addr2a(&_m->rcv.src_ip),
|
|
|
- _m->rcv.src_port, proto_str ? : "");
|
|
|
+ if(path_received_format==0) {
|
|
|
+ if (_m->rcv.proto
|
|
|
+ < (sizeof(proto_strings) / sizeof(*proto_strings))) {
|
|
|
+ proto_str = proto_strings[(unsigned int) _m->rcv.proto];
|
|
|
+ } else {
|
|
|
+ proto_str = NULL;
|
|
|
+ }
|
|
|
+ if(_m->rcv.src_ip.af==AF_INET6) {
|
|
|
+ cp += sprintf(cp, ";received=sip:[%s]:%hu%s",
|
|
|
+ ip_addr2a(&_m->rcv.src_ip),
|
|
|
+ _m->rcv.src_port, proto_str ? : "");
|
|
|
+ } else {
|
|
|
+ cp += sprintf(cp, ";received=sip:%s:%hu%s"
|
|
|
+ , ip_addr2a(&_m->rcv.src_ip),
|
|
|
+ _m->rcv.src_port, proto_str ? : "");
|
|
|
+ }
|
|
|
} else {
|
|
|
- cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip),
|
|
|
- _m->rcv.src_port, proto_str ? : "");
|
|
|
+ if(_m->rcv.src_ip.af==AF_INET6) {
|
|
|
+ cp += sprintf(cp, ";received=[%s]~%hu~%d",
|
|
|
+ ip_addr2a(&_m->rcv.src_ip),
|
|
|
+ _m->rcv.src_port, (int)_m->rcv.proto);
|
|
|
+ } else {
|
|
|
+ cp += sprintf(cp, ";received=%s~%hu~%d",
|
|
|
+ ip_addr2a(&_m->rcv.src_ip),
|
|
|
+ _m->rcv.src_port, (int)_m->rcv.proto);
|
|
|
+ }
|
|
|
}
|
|
|
break;
|
|
|
case PATH_PARAM_OB:
|
|
@@ -100,7 +134,11 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
|
|
|
if (add_params && add_params->len)
|
|
|
cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
|
|
|
|
|
|
- cp += sprintf(cp, ">\r\n");
|
|
|
+ if(path_enable_r2==0) {
|
|
|
+ cp += sprintf(cp, ">\r\n");
|
|
|
+ } else {
|
|
|
+ cp += sprintf(cp, ";r2=on>\r\n");
|
|
|
+ }
|
|
|
|
|
|
prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
|
|
|
prefix = pkg_malloc(prefix_len);
|
|
@@ -136,6 +174,19 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
|
|
|
l = insert_new_lump_before(l, suffix, cp - suffix, 0);
|
|
|
if (!l) goto out2;
|
|
|
|
|
|
+ if(path_enable_r2!=0) {
|
|
|
+ dp = path_strzdup(prefix, prefix_len);
|
|
|
+ if(dp==NULL) goto out1;
|
|
|
+ l = insert_new_lump_before(l, dp, prefix_len, 0);
|
|
|
+ if (!l) goto out1;
|
|
|
+ l = insert_subst_lump_before(l, SUBST_RCV_ALL, 0);
|
|
|
+ if (!l) goto out1;
|
|
|
+ dp = path_strzdup(suffix, cp - suffix);
|
|
|
+ if(dp==NULL) goto out1;
|
|
|
+ l = insert_new_lump_before(l, suffix, cp - suffix, 0);
|
|
|
+ if (!l) goto out1;
|
|
|
+ }
|
|
|
+
|
|
|
return 1;
|
|
|
|
|
|
out3:
|
|
@@ -162,11 +213,11 @@ int ki_add_path(struct sip_msg* _msg)
|
|
|
&& path_obb.use_outbound(_msg)) {
|
|
|
if (path_obb.encode_flow_token(&user, _msg->rcv) != 0) {
|
|
|
LM_ERR("encoding outbound flow-token\n");
|
|
|
- return -1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- /* Only include ;ob parameter if this is the first-hop (that
|
|
|
- means only one Via:) */
|
|
|
+ /* Only include ;ob parameter if this is the first-hop
|
|
|
+ * (that means only one Via:) */
|
|
|
if (parse_via_header(_msg, 2, &via) < 0)
|
|
|
param = PATH_PARAM_OB;
|
|
|
}
|
|
@@ -284,20 +335,77 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
|
|
|
param_t *params;
|
|
|
static char dst_uri_buf[MAX_URI_SIZE];
|
|
|
static str dst_uri;
|
|
|
-
|
|
|
+ char *p;
|
|
|
+ int n;
|
|
|
+ int nproto;
|
|
|
+ str sproto;
|
|
|
+
|
|
|
if (parse_params(r_param, CLASS_CONTACT, &hooks, ¶ms) != 0) {
|
|
|
LM_ERR("failed to parse route parameters\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (hooks.contact.received) {
|
|
|
- dst_uri.s = dst_uri_buf;
|
|
|
+ if (hooks.contact.received
|
|
|
+ && hooks.contact.received->body.len>0) {
|
|
|
+ /* 24 => sip:...;transport=sctp */
|
|
|
+ if(hooks.contact.received->body.len + 24 >= MAX_URI_SIZE) {
|
|
|
+ LM_ERR("received uri is too long\n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ dst_uri.s = dst_uri_buf;
|
|
|
dst_uri.len = MAX_URI_SIZE;
|
|
|
- if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
|
|
|
- LM_ERR("unescaping received failed\n");
|
|
|
- free_params(params);
|
|
|
- return;
|
|
|
- }
|
|
|
+ if(path_enable_r2==0) {
|
|
|
+ if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
|
|
|
+ LM_ERR("unescaping received failed\n");
|
|
|
+ free_params(params);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ /* ip~port~proto */
|
|
|
+ strncpy(dst_uri_buf, "sip:", 4);
|
|
|
+ strncpy(dst_uri_buf+4, hooks.contact.received->body.s,
|
|
|
+ hooks.contact.received->body.len);
|
|
|
+ dst_uri_buf[hooks.contact.received->body.len] = '\0';
|
|
|
+ p = dst_uri_buf + 4;
|
|
|
+ n = 0;
|
|
|
+ while(*p!='\0') {
|
|
|
+ if(*p=='~') {
|
|
|
+ n++;
|
|
|
+ if(n==1) {
|
|
|
+ /* port */
|
|
|
+ *p = ':';
|
|
|
+ } else if(n==2) {
|
|
|
+ /* proto */
|
|
|
+ *p = ';';
|
|
|
+ p++;
|
|
|
+ if(*p=='\0') {
|
|
|
+ LM_ERR("invalid received format\n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ nproto = *p - '0';
|
|
|
+ if (nproto != PROTO_UDP) {
|
|
|
+ proto_type_to_str(nproto, &sproto);
|
|
|
+ if (sproto.len == 0) {
|
|
|
+ LM_ERR("unknown proto in received param\n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ strncpy(p, "transport=", 10);
|
|
|
+ p += 10;
|
|
|
+ memcpy(p, sproto.s, sproto.len);
|
|
|
+ p += sproto.len;
|
|
|
+ *p = '\0';
|
|
|
+ dst_uri.len = p - dst_uri_buf;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LM_ERR("invalid number of spearators (%d)\n", n);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LM_DBG("setting dst uri: %.*s\n", dst_uri.len, dst_uri.s);
|
|
|
if (set_dst_uri(_m, &dst_uri) != 0) {
|
|
|
LM_ERR("failed to set dst-uri\n");
|
|
|
free_params(params);
|
|
@@ -307,5 +415,6 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
|
|
|
forking */
|
|
|
ruri_mark_new(); /* re-use uri for serial forking */
|
|
|
}
|
|
|
+done:
|
|
|
free_params(params);
|
|
|
}
|