Index: modules/rr/loose.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/rr/loose.c,v retrieving revision 1.36 diff -u -r1.36 loose.c --- modules/rr/loose.c 23 Feb 2005 17:16:05 -0000 1.36 +++ modules/rr/loose.c 15 Apr 2005 14:52:55 -0000 @@ -30,6 +30,8 @@ * --------- * 2003-02-28 scratchpad compatibility abandoned (jiri) * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) + * 2005-04-10 check_route_param() and all hooks for keeping reference to + * Route params added (bogdan) */ @@ -57,6 +59,10 @@ #define ROUTE_SUFFIX ">\r\n" #define ROUTE_SUFFIX_LEN (sizeof(ROUTE_SUFFIX)-1) +/* variables used to hook the param part of the local route -bogdan */ +static unsigned int routed_msg_id; +static str routed_params = {0,0}; + /* * Test whether we are processing pre-loaded route set @@ -511,12 +517,16 @@ if (is_myself(&puri.host, puri.port_no)) #endif { - /* if (enable_double_rr && is_2rr(&_ruri->params)) { */ - /* DBG("ras(): Removing 2nd URI of mine: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); */ + /*if (enable_double_rr && is_2rr(&_ruri->params)) { + * DBG("ras(): Removing 2nd URI of mine: '%.*s'\n", + * rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); */ + /* set the hooks for the params -bogdan */ + routed_msg_id = _m->id; + routed_params = puri.params; if (!rt->next) { - /* No next route in the same header, remove the whole header - * field immediately - */ + /* No next route in the same header, remove the whole header + * field immediately + */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_strict: Cannot remove Route HF\n"); return RR_ERROR; @@ -661,11 +671,15 @@ if (is_myself(&puri.host, puri.port_no)) #endif { - DBG("after_loose: Topmost route URI: '%.*s' is me\n", uri->len, ZSW(uri->s)); + DBG("after_loose: Topmost route URI: '%.*s' is me\n", + uri->len, ZSW(uri->s)); + /* set the hooks for the params -bogdan */ + routed_msg_id = _m->id; + routed_params = puri.params; if (!rt->next) { - /* No next route in the same header, remove the whole header - * field immediately - */ + /* No next route in the same header, remove the whole header + * field immediately + */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_loose: Can't remove Route HF\n"); return RR_ERROR; @@ -684,16 +698,16 @@ if (enable_double_rr && is_2rr(&puri.params)) { if (!rt->next) { - /* No next route in the same header, remove the whole header - * field immediately - */ + /* No next route in the same header, remove the whole header + * field immediately + */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_loose: Can't remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { - LOG(L_ERR, "after_loose: Error while finding next route\n"); + LOG(L_ERR,"after_loose: Error while finding next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ @@ -783,3 +797,32 @@ } } } + + + +int check_route_param(struct sip_msg * msg, char *re, char *foo) +{ + regmatch_t pmatch; + char bk; + + /* check if the hooked params belong to the same message */ + if (routed_msg_id != msg->id) + return -1; + + /* check if params are present */ + if ( !routed_params.s || !routed_params.len ) + return -1; + + /* do the well-known trick to convert to null terminted */ + bk = routed_params.s[routed_params.len]; + routed_params.s[routed_params.len] = 0; + DBG("DEBUG:rr:check_route_param: params are <%s>\n", routed_params.s); + if (regexec( (regex_t*)re, routed_params.s, 1, &pmatch, 0)!=0) { + routed_params.s[routed_params.len] = bk; + return -1; + } else { + routed_params.s[routed_params.len] = bk; + return 1; + } +} + Index: modules/rr/loose.h =================================================================== RCS file: /cvsroot/ser/sip_router/modules/rr/loose.h,v retrieving revision 1.3 diff -u -r1.3 loose.h --- modules/rr/loose.h 24 Aug 2004 09:00:38 -0000 1.3 +++ modules/rr/loose.h 15 Apr 2005 14:52:56 -0000 @@ -40,4 +40,6 @@ int loose_route(struct sip_msg* _m, char* _s1, char* _s2); +int check_route_param(struct sip_msg * msg, char *re, char *foo); + #endif /* LOOSE_H */ Index: modules/rr/record.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/rr/record.c,v retrieving revision 1.14 diff -u -r1.14 record.c --- modules/rr/record.c 24 Aug 2004 09:00:38 -0000 1.14 +++ modules/rr/record.c 15 Apr 2005 14:52:56 -0000 @@ -29,6 +29,7 @@ * History: * ------- * 2003-04-04 Extracted from common.[ch] (janakj) + * 2005-04-10 add_rr_param() function and all corresponing hooks added (bogdan) */ #include @@ -63,6 +64,22 @@ #define INBOUND 1 /* Insert inbound Record-Route */ #define OUTBOUND 0 /* Insert outbound Record-Route */ +#define RR_PARAM_BUF_SIZE 512 + +static unsigned int last_rr_msg; + +/* RR suffix lump and offset - used for inserting RR params + * after RR was done; use a two values array for INBOUND and + * OUTBOUND RR -bogdan */ +static struct lump *rr_suffix_lump[2] = {0,0}; +static int rr_suffix_end_offset[2] = {0,0}; + +/* RR param buffer - usd for storing RR param which are + * added before RR insertion -bogdan */ +static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE]; +static str rr_param_buf = {rr_param_buf_ptr,0}; +static unsigned int rr_param_msg; + /* * Extract username from the Request URI @@ -104,16 +121,20 @@ { char* prefix, *suffix, *crlf, *r2; int suffix_len, prefix_len; + char *p; prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0); prefix = pkg_malloc(prefix_len); if (enable_full_lr) { suffix_len = (_lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN) + - ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0) + + rr_param_buf.len; } else { suffix_len = (_lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN) + - ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0) + + rr_param_buf.len; } + rr_suffix_end_offset[_inbound] = RR_SR_TERM_LEN; suffix = pkg_malloc(suffix_len); crlf = pkg_malloc(2); @@ -145,21 +166,24 @@ #endif prefix[RR_PREFIX_LEN + user->len] = '@'; } - + + p = suffix; if (tag && tag->len) { - memcpy(suffix, RR_FROMTAG, RR_FROMTAG_LEN); - memcpy(suffix + RR_FROMTAG_LEN, tag->s, tag->len); - if (enable_full_lr) { - memcpy(suffix + RR_FROMTAG_LEN + tag->len, _lr ? RR_LR_FULL_TERM : RR_SR_TERM, _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN); - } else { - memcpy(suffix + RR_FROMTAG_LEN + tag->len, _lr ? RR_LR_TERM : RR_SR_TERM, _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN); - } + memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); + p += RR_FROMTAG_LEN; + memcpy(p, tag->s, tag->len); + p += tag->len; + } + if (rr_param_buf.len) { + memcpy( p, rr_param_buf.s, rr_param_buf.len); + p += rr_param_buf.len; + } + if (enable_full_lr) { + memcpy( p, _lr ? RR_LR_FULL_TERM : RR_SR_TERM, + _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN); } else { - if (enable_full_lr) { - memcpy(suffix, _lr ? RR_LR_FULL_TERM : RR_SR_TERM, _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN); - } else { - memcpy(suffix, _lr ? RR_LR_TERM : RR_SR_TERM, _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN); - } + memcpy( p, _lr ? RR_LR_TERM : RR_SR_TERM, + _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN); } memcpy(crlf, CRLF, 2); @@ -177,6 +201,7 @@ r2 = 0; } if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, 0))) goto lump_err; + rr_suffix_lump[_inbound] = _l2; suffix = 0; if (!(_l2 = insert_new_lump_before(_l2, crlf, 2, 0))) goto lump_err; crlf = 0; @@ -225,6 +250,12 @@ tag = 0; } + if (rr_param_buf.len && rr_param_msg!=_m->id) { + /* rr_params were set for a different message -> reset buffer */ + rr_param_buf.len = 0; + DBG("----> reset rr_param_buf\n"); + } + if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); @@ -256,6 +287,8 @@ return -4; } + /* reset the rr_param buffer */ + rr_param_buf.len = 0; return 0; } @@ -266,8 +299,6 @@ */ static inline int do_RR(struct sip_msg* _m, int _lr) { - static unsigned int last_rr_msg; - if (_m->id == last_rr_msg) { LOG(L_ERR, "record_route(): Double attempt to record-route\n"); return -1; @@ -395,3 +426,72 @@ { return do_RR(_m, 0); } + + +/* + * Appends a string to an existent lump + */ +static inline int append_to_lump( struct lump *l, str *s, int end_offset) +{ + char *p; + + /* update buffer */ + p = pkg_realloc( l->u.value, l->len+s->len); + if (p==0) { + LOG(L_ERR,"ERROR:rr:add_rr_param: no more pkg memory\n"); + return -1; + } + memmove(p+l->len-end_offset+s->len, p+l->len-end_offset, end_offset); + memcpy( p+l->len-end_offset, s->s, s->len); + /* update lump structure */ + l->len += s->len; + l->u.value = p; + return 0; +} + + +/* + * Appends a new Record-Route parameter + */ +int add_rr_param(struct sip_msg* msg, char* param, char* foo) +{ + str *rr_param; + int i; + + rr_param = (str*)param; + + if (last_rr_msg==msg->id) { + /* RR was already done -> have to modify the RR-sufix lump */ + for( i=OUTBOUND ; i<=INBOUND ; i++ ) { + if ( !rr_suffix_lump[i] || !rr_suffix_end_offset[i] ) + continue; + if (append_to_lump( rr_suffix_lump[i], rr_param, + rr_suffix_end_offset[i])!=0) { + LOG(L_ERR,"ERROR:rr:add_rr_param: failed to update lump\n"); + goto error; + } + } + } else { + /* RR not done yet -> store the param in the static buffer */ + if (rr_param_msg!=msg->id) { + /* it's about a different messge -> reset buffer */ + rr_param_buf.len = 0; + rr_param_msg = msg->id; + } + if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) { + LOG(L_ERR,"ERROR:rr:add_rr_param: maximum size of " + "rr_param_buf exceeded\n"); + goto error; + } + memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len); + rr_param_buf.len += rr_param->len; + DBG("DEBUG:rr:add_rr_param: rr_param_buf=<%.*s>\n",rr_param_buf.len, + rr_param_buf.s); + } + return 1; + +error: + return -1; +} + + Index: modules/rr/record.h =================================================================== RCS file: /cvsroot/ser/sip_router/modules/rr/record.h,v retrieving revision 1.2 diff -u -r1.2 record.h --- modules/rr/record.h 24 Aug 2004 09:00:38 -0000 1.2 +++ modules/rr/record.h 15 Apr 2005 14:52:56 -0000 @@ -56,4 +56,10 @@ int record_route_strict(struct sip_msg* _m, char* _s1, char* _s2); +/* + * Appends a new Record-Route parameter + */ +int add_rr_param(struct sip_msg* msg, char* param, char* foo); + + #endif /* RECORD_H */ Index: modules/rr/rr_mod.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/rr/rr_mod.c,v retrieving revision 1.33 diff -u -r1.33 rr_mod.c --- modules/rr/rr_mod.c 24 Aug 2004 09:00:38 -0000 1.33 +++ modules/rr/rr_mod.c 15 Apr 2005 14:52:57 -0000 @@ -33,11 +33,14 @@ * 2003-03-19 all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei) * 2003-04-01 Added record_route with ip address parameter (janakj) * 2003-04-14 enable_full_lr parameter introduced (janakj) + * 2005-04-10 add_rr_param() and check_route_param() added (bogdan) */ #include #include +#include + #include "../../sr_module.h" #include "../../ut.h" #include "../../error.h" @@ -61,6 +64,7 @@ static int mod_init(void); static int str_fixup(void** param, int param_no); +static int regexp_fixup(void** param, int param_no); /* @@ -74,10 +78,18 @@ * Oh, BTW, have I mentioned already that you shouldn't use strict routing ? */ static cmd_export_t cmds[] = { - {"loose_route", loose_route, 0, 0, REQUEST_ROUTE}, - {"record_route", record_route, 0, 0, REQUEST_ROUTE}, - {"record_route_preset", record_route_preset, 1, str_fixup, REQUEST_ROUTE}, - {"record_route_strict" , record_route_strict, 0, 0, 0 }, + {"loose_route", loose_route, 0, 0, + REQUEST_ROUTE}, + {"record_route", record_route, 0, 0, + REQUEST_ROUTE}, + {"record_route_preset", record_route_preset, 1, str_fixup, + REQUEST_ROUTE}, + {"record_route_strict" , record_route_strict, 0, 0, + 0}, + {"add_rr_param", add_rr_param, 1, str_fixup, + REQUEST_ROUTE}, + {"check_route_param", check_route_param, 1, regexp_fixup, + REQUEST_ROUTE}, {0, 0, 0, 0, 0} }; @@ -149,3 +161,29 @@ return 0; } + + +static int regexp_fixup(void** param, int param_no) +{ + regex_t* re; + + if (param_no==1) { + if ((re=pkg_malloc(sizeof(regex_t)))==0) { + LOG(L_ERR,"ERROR:rr:regexp_fixup: no more pkg memory\n"); + return E_OUT_OF_MEM; + } + if (regcomp(re, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) { + pkg_free(re); + LOG(L_ERR, "ERROR:rr:regexp_fixup: bad regexp %s\n",(char*)*param); + return E_BAD_RE; + } + /* free string */ + pkg_free(*param); + /* replace it with the compiled re */ + *param=re; + } + return 0; +} + + +