New upstream version 4.4.3

changes/26/8326/1 upstream/4.4.3
Victor Seva 9 years ago
parent a28575161d
commit c742e1becc

File diff suppressed because it is too large Load Diff

@ -96,7 +96,7 @@ INSTALL_FLAVOUR=$(FLAVOUR)
# version number
VERSION = 4
PATCHLEVEL = 4
SUBLEVEL = 2
SUBLEVEL = 3
# memory manager switcher
# 0 - f_malloc (fast malloc)
@ -253,6 +253,7 @@ ifneq (, $(findstring Sun, $(CC_LONGVER)))
sed -e 's/.*\([0-9]\.[0-9]\).*/\1/g' )
CC_VER=$(CC) $(CC_SHORTVER)
MKDEP=$(CC) -xM1
CC_MKDEP_OPTS=-xMMD
endif
ifneq (, $(findstring Intel(R) C++ Compiler, $(CC_LONGVER)))
@ -1092,9 +1093,12 @@ endif #CC_SHORTVER, 6.0+, 5.0+, 4.5+ or 4.2+
else #CC_NAME, gcc
ifeq ($(CC_NAME), suncc)
C_DEFS+=-DCC_GCC_LIKE_ASM
C_DEFS+=-DSPARC64_MODE
CFLAGS+= -m64 -g -xO5 -fast -native -xarch=v9 -xCC \
CFLAGS+= -m64 -g -xO3 -xtarget=native -xmemalign=8i \
-fma=fused -fns=yes \
-xc99 # C99 support
LDFLAGS+=-m64
# -Dinline="" # add this if cc < 5.3 (define inline as null)
else
#other compilers
@ -1158,7 +1162,9 @@ endif #CC_SHORTVER, 6.0+, 5.0+, 4.5+ or 4.2+
else #CC_NAME, gcc
ifeq ($(CC_NAME), suncc)
CFLAGS+= -g -xO5 -fast -native -xCC \
C_DEFS+=-DCC_GCC_LIKE_ASM
CFLAGS+= -g -xO3 -xtarget=native -xmemalign=4i \
-fma=fused -fns=yes \
-xc99 # C99 support
# -Dinline="" # add this if cc < 5.3 (define inline as null)
else
@ -1588,11 +1594,11 @@ ifeq ($(CC_NAME), icc)
endif
ifeq ($(CC_NAME), suncc)
# -dy?
LDFLAGS+=-xO5 $(PROFILE)
LDFLAGS+=-xO3 $(PROFILE)
MOD_LDFLAGS:=-G $(LDFLAGS)
LIB_LDFLAGS:=-G $(LDFLAGS)
LIB_SONAME="-h "
LD_RPATH=-"-R "
LIB_SONAME=-Wl,-h,
LD_RPATH=-Wl,-R,
endif
# we need -fPIC -DPIC only for shared objects, we don't need them for
# the executable file, because it's always loaded at a fixed address
@ -1649,8 +1655,8 @@ ifeq ($(CC_NAME), suncc)
LDFLAGS+=-g $(PROFILE)
MOD_LDFLAGS:=-G $(LDFLAGS)
LIB_LDFLAGS:=-G $(LDFLAGS)
LIB_SONAME="-h "
LD_RPATH=-"-R "
LIB_SONAME=-Wl,-h,
LD_RPATH=-Wl,-R,
endif
endif #mode=release
@ -1679,9 +1685,8 @@ MOD_CFLAGS=-Kpic $(CFLAGS)
LIB_CFLAGS=-Kpic $(CFLAGS)
endif
ifeq ($(CC_NAME), suncc)
# FIMXE: use -KPIC instead -xcode ?
MOD_CFLAGS=-xcode=pic32 $(CFLAGS)
LIB_CFLAGS=-xcode=pic32 $(CFLAGS)
MOD_CFLAGS=-xcode=pic32 $(CFLAGS)
LIB_CFLAGS=-xcode=pic32 $(CFLAGS)
endif
ifeq ($(CC_NAME), clang)
MOD_CFLAGS=-fPIC -DPIC $(CFLAGS)
@ -1822,7 +1827,7 @@ ifeq ($(OS), solaris)
YACC=yacc
ifeq ($(CC_NAME), suncc)
LIBS= -lfast -ldl -lresolv
LIBS= -ldl -lresolv
endif
OLD_SOLARIS= $(shell echo "$(OSREL)" | \
sed -e 's/^5\.[0-6][^0-9]*$$/yes/' )

@ -272,7 +272,7 @@ clean_doxygen:
.PHONY: TAGS
.PHONY: tags
TAGS tags:
$(MKTAGS) --exclude="obsolete/*" -R .
$(MKTAGS) --exclude="obsolete/*" --exclude="test/*" -R .
.PHONY: TAGS-ALL
.PHONY: tags-all

@ -229,7 +229,7 @@ char *get_cfg_crt_name(void)
#define MODF_CALL(f_type, h, msg, src, ...) \
do { \
cmd=(src)[0].u.data; \
ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
ret=((f_type)cmd->function)((msg), __VA_ARGS__); \
MODF_HANDLE_RETCODE(h, ret); \
} while (0)
#else /* ! __SUNPRO_C (gcc, icc a.s.o) */
@ -263,7 +263,7 @@ char *get_cfg_crt_name(void)
do { \
cmd=(src)[0].u.data; \
MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
ret=((f_type)cmd->function)((msg), __VA_ARGS__); \
MODF_HANDLE_RETCODE(h, ret); \
/* free strings allocated by us or fixups */ \
MODF_RVE_PARAM_FREE(cmd, src, dst); \

@ -46,6 +46,9 @@
#define HAVE_ASM_INLINE_MEMBAR
#ifdef __SUNPRO_C
#pragma error_messages (off,E_ASM_UNUSED_PARAM)
#endif
/* try to guess if in SPARC64_MODE */
#if ! defined SPARC64_MODE && \

@ -2,6 +2,6 @@
* DO NOT EDIT IT
*/
#define REPO_VER "892ad6"
#define REPO_HASH "892ad6"
#define REPO_VER "5a2195"
#define REPO_HASH "5a2195"
#define REPO_STATE ""

@ -352,6 +352,7 @@ MEMDBG "memdbg"|"mem_dbg"
MEMSUM "mem_summary"
MEMSAFETY "mem_safety"
MEMJOIN "mem_join"
MEMSTATUSMODE "mem_status_mode"
CORELOG "corelog"|"core_log"
SIP_WARNING sip_warning
SERVER_SIGNATURE server_signature
@ -765,6 +766,7 @@ IMPORTFILE "import_file"
<INITIAL>{MEMSUM} { count(); yylval.strval=yytext; return MEMSUM; }
<INITIAL>{MEMSAFETY} { count(); yylval.strval=yytext; return MEMSAFETY; }
<INITIAL>{MEMJOIN} { count(); yylval.strval=yytext; return MEMJOIN; }
<INITIAL>{MEMSTATUSMODE} { count(); yylval.strval=yytext; return MEMSTATUSMODE; }
<INITIAL>{CORELOG} { count(); yylval.strval=yytext; return CORELOG; }
<INITIAL>{SIP_WARNING} { count(); yylval.strval=yytext; return SIP_WARNING; }
<INITIAL>{USER} { count(); yylval.strval=yytext; return USER; }
@ -1183,9 +1185,9 @@ IMPORTFILE "import_file"
<INITIAL>{COM_LINE}!{SER_CFG}{CR} { count();
sr_cfg_compat=SR_COMPAT_SER;}
<INITIAL>{COM_LINE}!{KAMAILIO_CFG}{CR} { count();
<INITIAL>{COM_LINE}!{KAMAILIO_CFG}{CR} { count();
sr_cfg_compat=SR_COMPAT_KAMAILIO;}
<INITIAL>{COM_LINE}!{MAXCOMPAT_CFG}{CR} { count();
<INITIAL>{COM_LINE}!{MAXCOMPAT_CFG}{CR} { count();
sr_cfg_compat=SR_COMPAT_MAX;}
<INITIAL>{PREP_START}{DEFINE}{EAT_ABLE}+ { count(); pp_define_set_type(0);
@ -1194,6 +1196,12 @@ IMPORTFILE "import_file"
state = DEFINE_S; BEGIN(DEFINE_ID); }
<INITIAL>{PREP_START}{REDEF}{EAT_ABLE}+ { count(); pp_define_set_type(2);
state = DEFINE_S; BEGIN(DEFINE_ID); }
<DEFINE_ID>{ID}{MINUS} { count();
LOG(L_CRIT,
"error at %s line %d: '-' not allowed\n",
(finame)?finame:"cfg", line);
exit(-1);
}
<DEFINE_ID>{ID} { count();
if (pp_define(yyleng, yytext)) return 1;
state = DEFINE_EOL_S; BEGIN(DEFINE_EOL); }
@ -1221,6 +1229,12 @@ IMPORTFILE "import_file"
<INITIAL,IFDEF_SKIP>{PREP_START}{IFNDEF}{EAT_ABLE}+ { count();
if (pp_ifdef_type(0)) return 1;
state = IFDEF_S; BEGIN(IFDEF_ID); }
<IFDEF_ID>{ID}{MINUS} { count();
LOG(L_CRIT,
"error at %s line %d: '-' not allowed\n",
(finame)?finame:"cfg", line);
exit(-1);
}
<IFDEF_ID>{ID} { count();
pp_ifdef_var(yyleng, yytext);
state = IFDEF_EOL_S; BEGIN(IFDEF_EOL); }

@ -380,6 +380,7 @@ extern char *default_routename;
%token MEMSUM
%token MEMSAFETY
%token MEMJOIN
%token MEMSTATUSMODE
%token CORELOG
%token SIP_WARNING
%token SERVER_SIGNATURE
@ -901,6 +902,8 @@ assign_stm:
| MEMSAFETY EQUAL error { yyerror("int value expected"); }
| MEMJOIN EQUAL intno { default_core_cfg.mem_join=$3; }
| MEMJOIN EQUAL error { yyerror("int value expected"); }
| MEMSTATUSMODE EQUAL intno { default_core_cfg.mem_status_mode=$3; }
| MEMSTATUSMODE EQUAL error { yyerror("int value expected"); }
| CORELOG EQUAL intno { default_core_cfg.corelog=$3; }
| CORELOG EQUAL error { yyerror("int value expected"); }
| SIP_WARNING EQUAL NUMBER { sip_warning=$3; }

@ -129,6 +129,7 @@ typedef struct _cfg_block {
atomic_t refcnt; /*!< reference counter,
the block is automatically deleted
when it reaches 0 */
int _pad; /*!< force 8 byte alignment */
unsigned char vars[1]; /*!< blob that contains the values */
} cfg_block_t;

@ -115,6 +115,7 @@ struct cfg_group_core default_core_cfg = {
4 pkg_sums, 8 shm_sums, 16 short_status */
0, /*!< mem_safety - 0 disabled */
0, /*!< mem_join - 0 disabled */
0, /*!< mem_status_mode - 0 only free fragments, 1 all fragements */
L_ERR, /*!< corelog */
L_ERR, /*!< latency log */
0, /*!< latency limit db */
@ -312,6 +313,8 @@ cfg_def_t core_cfg_def[] = {
"safety level for memory operations"},
{"mem_join", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"join free memory fragments"},
{"mem_status_mode", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"print status for free or all memory fragments"},
{"corelog", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"log level for non-critical core error messages"},
{"latency_log", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,

@ -103,6 +103,7 @@ struct cfg_group_core {
int mem_summary; /*!< display memory status/summary info on exit */
int mem_safety; /*!< memory safety control option */
int mem_join; /*!< memory free fragments join option */
int mem_status_mode; /*!< memory status printed for free/all fragments */
int corelog; /*!< log level for non-critcal core error messages */
int latency_log; /*!< log level for latency limits messages */
int latency_limit_db; /*!< alert limit of running db commands */

@ -734,3 +734,117 @@ int remove_lump(sip_msg_t *msg, struct lump *l)
}
return 0;
}
/**
*
*/
int sr_hdr_add(sip_msg_t *msg, str *sname, str *sbody)
{
struct lump* anchor;
str h;
h.len = sname->len + 2 + sbody->len + CRLF_LEN;
h.s = (char*)pkg_malloc(h.len+1);
if(h.s == 0) {
LM_ERR("no more pkg\n");
return -1;
}
anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
if(anchor == 0)
{
LM_ERR("cannot get the anchor\n");
pkg_free(h.s);
return -1;
}
memcpy(h.s, sname->s, sname->len);
memcpy(h.s+sname->len, ": ", 2);
memcpy(h.s+sname->len+2, sbody->s, sbody->len);
memcpy(h.s+sname->len+2+sbody->len, CRLF, CRLF_LEN);
h.s[h.len] = '\0';
if (insert_new_lump_after(anchor, h.s, h.len, 0) == 0)
{
LM_ERR("cannot insert lump\n");
pkg_free(h.s);
return -1;
}
LM_DBG("added new header [%s]\n", h.s);
return 0;
}
/**
*
*/
int sr_hdr_add_zz(sip_msg_t *msg, char *hname, char *hbody)
{
str sname;
str sbody;
sname.s = hname;
sname.len = strlen(sname.s);
sbody.s = hbody;
sbody.len = strlen(sbody.s);
return sr_hdr_add(msg, &sname, &sbody);
}
/**
*
*/
int sr_hdr_add_zs(sip_msg_t *msg, char *hname, str *sbody)
{
str sname;
sname.s = hname;
sname.len = strlen(sname.s);
return sr_hdr_add(msg, &sname, sbody);
}
/**
*
*/
hdr_field_t *sr_hdr_get_z(sip_msg_t *msg, char *hname)
{
hdr_field_t *hf;
str sname;
sname.s = hname;
sname.len = strlen(sname.s);
for (hf=msg->headers; hf; hf=hf->next) {
if (hf->name.len==sname.len
&& strncasecmp(hf->name.s, sname.s,
sname.len)==0) {
return hf;
}
}
return NULL;
}
/**
*
*/
int sr_hdr_del_z(sip_msg_t *msg, char *hname)
{
hdr_field_t *hf;
struct lump* l;
str sname;
sname.s = hname;
sname.len = strlen(sname.s);
for (hf=msg->headers; hf; hf=hf->next) {
if (hf->name.len==sname.len
&& strncasecmp(hf->name.s, sname.s,
sname.len)==0) {
l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
if (l==0) {
LM_ERR("unable to delete cookie header\n");
return -1;
}
return 0;
}
}
return 0;
}

@ -86,4 +86,11 @@ void del_nonshm_lump( struct lump** lump_list );
/*! \brief remove the lump from the internal lists */
int remove_lump(sip_msg_t *msg, struct lump *l);
int sr_hdr_add(sip_msg_t *msg, str *sname, str *sbody);
int sr_hdr_add_zz(sip_msg_t *msg, char *hname, char *hbody);
int sr_hdr_add_zs(sip_msg_t *msg, char *hname, str *sbody);
int sr_hdr_del_z(sip_msg_t *msg, char *hname);
hdr_field_t *sr_hdr_get_z(sip_msg_t *msg, char *hname);
#endif

@ -102,9 +102,12 @@ void free_lump_rpl(struct lump_rpl* lump)
{
if (lump) {
if (!((lump->flags)&LUMP_RPL_NOFREE) && ((lump->flags)&LUMP_RPL_NODUP)
&& lump->text.s)
&& lump->text.s) {
pkg_free(lump->text.s);
lump->text.s = 0;
}
pkg_free(lump);
lump = 0;
}
}

@ -106,6 +106,10 @@ typedef int fd_type;
#define FD_TYPE_DEFINED
#endif
#ifdef __SUNPRO_C
#pragma weak handle_io
#endif
/* maps a fd to some other structure; used in almost all cases
* except epoll and maybe kqueue or /dev/poll */
struct fd_map{

@ -658,7 +658,6 @@ static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
LM_CRIT("unknown address family %d\n", ip->af);
return 0;
}
return 0;
}

@ -19,7 +19,7 @@
*
*/
/** Kamailio core :: main file (init, daemonize, startup)
/** Kamailio core :: main file (init, daemonize, startup)
* @file main.c
* @ingroup core
* Module: core
@ -133,6 +133,7 @@
#include "async_task.h"
#include "dset.h"
#include "timer_proc.h"
#include "srapi.h"
#ifdef DEBUG_DMALLOC
#include <dmalloc.h>
@ -831,7 +832,20 @@ void sig_usr(int signo)
_exit(0);
break;
case SIGUSR1:
/* statistics, do nothing, printed only from the main proc */
#ifdef PKG_MALLOC
cfg_update_no_cbs();
memlog=cfg_get(core, core_cfg, memlog);
if (memlog <= cfg_get(core, core_cfg, debug)){
if (cfg_get(core, core_cfg, mem_summary) & 1) {
LOG(memlog, "Memory status (pkg):\n");
pkg_status();
}
if (cfg_get(core, core_cfg, mem_summary) & 2) {
LOG(memlog, "Memory still-in-use summary (pkg):\n");
pkg_sums();
}
}
#endif
break;
/* ignored*/
case SIGUSR2:
@ -1836,6 +1850,7 @@ int main(int argc, char** argv)
debug_flag=0;
dont_fork_cnt=0;
sr_cfgenv_init();
daemon_status_init();
dprint_init_colors();

@ -42,16 +42,16 @@
/*useful macros*/
#define FRAG_END(f) \
((struct qm_frag_end*)((char*)(f)+sizeof(struct qm_frag)+ \
(f)->size))
(f)->size))
#define FRAG_NEXT(f) \
((struct qm_frag*)((char*)(f)+sizeof(struct qm_frag)+(f)->size+ \
sizeof(struct qm_frag_end)))
sizeof(struct qm_frag_end)))
#define FRAG_PREV(f) \
( (struct qm_frag*) ( ((char*)(f)-sizeof(struct qm_frag_end))- \
((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))->size- \
sizeof(struct qm_frag) ) )
sizeof(struct qm_frag) ) )
#define PREV_FRAG_END(f) \
((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))
@ -85,7 +85,7 @@
#define FRAG_WAS_USED(f) (1)
/* other frag related defines:
* MEM_COALESCE_FRAGS
* MEM_COALESCE_FRAGS
* MEM_FRAG_AVOIDANCE
*/
@ -96,7 +96,7 @@
inline static unsigned long big_hash_idx(unsigned long s)
{
int idx;
/* s is rounded => s = k*2^n (ROUNDTO=2^n)
/* s is rounded => s = k*2^n (ROUNDTO=2^n)
* index= i such that 2^i > s >= 2^(i-1)
*
* => index = number of the first non null bit in s*/
@ -113,7 +113,7 @@ inline static unsigned long big_hash_idx(unsigned long s)
static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f,
const char* file, unsigned int line)
const char* file, unsigned int line)
{
if (f->check!=ST_CHECK_PATTERN){
LOG(L_CRIT, "BUG: qm_*: fragm. %p (address %p) "
@ -129,7 +129,7 @@ static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f,
LOG(L_CRIT, "BUG: qm_*: fragm. %p (address %p) "
"end overwritten (%lx, %lx)! Memory allocator was called "
"from %s:%u. Fragment marked by %s:%lu.\n",
f, (char*)f+sizeof(struct qm_frag),
f, (char*)f+sizeof(struct qm_frag),
FRAG_END(f)->check1, FRAG_END(f)->check2,
file, line, f->file, f->line);
qm_status(qm);
@ -156,7 +156,7 @@ static inline void qm_insert_free(struct qm_block* qm, struct qm_frag* frag)
struct qm_frag* f;
struct qm_frag* prev;
int hash;
hash=GET_HASH(frag->size);
for(f=qm->free_hash[hash].head.u.nxt_free; f!=&(qm->free_hash[hash].head);
f=f->u.nxt_free){
@ -182,7 +182,7 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size, int type)
struct qm_block* qm;
unsigned long init_overhead;
int h;
/* make address and size multiple of 8*/
start=(char*)ROUNDUP((unsigned long) address);
DBG("qm_malloc_init: QM_OPTIMIZE=%lu, /ROUNDTO=%lu\n",
@ -195,12 +195,12 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size, int type)
size-=(start-address);
if (size <(MIN_FRAG_SIZE+FRAG_OVERHEAD)) return 0;
size=ROUNDDOWN(size);
init_overhead=ROUNDUP(sizeof(struct qm_block))+sizeof(struct qm_frag)+
sizeof(struct qm_frag_end);
DBG("qm_malloc_init: size= %lu, init_overhead=%lu\n",
(unsigned long)size, init_overhead);
if (size < init_overhead)
{
/* not enough mem to create our control structures !!!*/
@ -216,13 +216,13 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size, int type)
qm->max_real_used=qm->real_used;
qm->type=type;
size-=init_overhead;
qm->first_frag=(struct qm_frag*)(start+ROUNDUP(sizeof(struct qm_block)));
qm->last_frag_end=(struct qm_frag_end*)(end-sizeof(struct qm_frag_end));
/* init initial fragment*/
qm->first_frag->size=size;
qm->last_frag_end->size=size;
#ifdef DBG_QM_MALLOC
qm->first_frag->check=ST_CHECK_PATTERN;
qm->last_frag_end->check1=END_CHECK_PATTERN1;
@ -235,16 +235,16 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size, int type)
qm->free_hash[h].head.size=0;
qm->free_hash[h].tail.size=0;
}
/* link initial fragment into the free list*/
qm_insert_free(qm, qm->first_frag);
/*qm->first_frag->u.nxt_free=&(qm->free_lst);
qm->last_frag_end->prev_free=&(qm->free_lst);
*/
* qm->last_frag_end->prev_free=&(qm->free_lst);
*/
return qm;
}
@ -254,23 +254,22 @@ static inline void qm_detach_free(struct qm_block* qm, struct qm_frag* frag)
{
struct qm_frag *prev;
struct qm_frag *next;
prev=FRAG_END(frag)->prev_free;
next=frag->u.nxt_free;
prev->u.nxt_free=next;
FRAG_END(next)->prev_free=prev;
}
#ifdef DBG_QM_MALLOC
static inline struct qm_frag* qm_find_free(struct qm_block* qm,
static inline struct qm_frag* qm_find_free(struct qm_block* qm,
size_t size,
int *h,
unsigned int *count)
#else
static inline struct qm_frag* qm_find_free(struct qm_block* qm,
static inline struct qm_frag* qm_find_free(struct qm_block* qm,
size_t size,
int* h)
#endif
@ -279,7 +278,7 @@ static inline struct qm_frag* qm_find_free(struct qm_block* qm,
struct qm_frag* f;
for (hash=GET_HASH(size); hash<QM_HASH_SIZE; hash++){
for (f=qm->free_hash[hash].head.u.nxt_free;
for (f=qm->free_hash[hash].head.u.nxt_free;
f!=&(qm->free_hash[hash].head); f=f->u.nxt_free){
#ifdef DBG_QM_MALLOC
*count+=1; /* *count++ generates a warning with gcc 2.9* -Wall */
@ -308,7 +307,7 @@ int split_frag(struct qm_block* qm, struct qm_frag* f, size_t new_size)
size_t rest;
struct qm_frag* n;
struct qm_frag_end* end;
rest=f->size-new_size;
#ifdef MEM_FRAG_AVOIDANCE
if ((rest> (FRAG_OVERHEAD+QM_MALLOC_OPTIMIZE))||
@ -362,7 +361,7 @@ void* qm_malloc(void* qmp, size_t size)
#endif
qm = (struct qm_block*)qmp;
#ifdef DBG_QM_MALLOC
list_cntr = 0;
MDBG("qm_malloc(%p, %lu) called from %s: %s(%d)\n",
@ -410,8 +409,8 @@ void* qm_malloc(void* qmp, size_t size)
FRAG_END(f)->check2=END_CHECK_PATTERN2;*/
MDBG("qm_malloc(%p, %lu) returns address %p frag. %p (size=%lu) on %d"
" -th hit\n",
qm, (unsigned long)size, (char*)f+sizeof(struct qm_frag), f,
f->size, list_cntr);
qm, (unsigned long)size, (char*)f+sizeof(struct qm_frag), f,
f->size, list_cntr);
#endif
#ifdef MALLOC_STATS
if(qm->type==MEM_TYPE_PKG) {
@ -503,8 +502,8 @@ void qm_free(void* qmp, void* p)
if(unlikely(cfg_get(core, core_cfg, mem_join)!=0)) {
next=prev=0;
/* mark this fragment as used (might fall into the middle of joined frags)
to give us an extra chance of detecting a double free call (if the joined
fragment has not yet been reused) */
* to give us an extra chance of detecting a double free call (if the joined
* fragment has not yet been reused) */
f->u.nxt_free=(void*)0x1L; /* bogus value, just to mark it as free */
/* join packets if possible*/
next=FRAG_NEXT(f);
@ -519,7 +518,7 @@ void qm_free(void* qmp, void* p)
qm->free_hash[GET_HASH(next->size)].no--; /* FIXME slow */
qm->ffrags--;
}
if (f > qm->first_frag){
prev=FRAG_PREV(f);
/* (struct qm_frag*)((char*)f - (struct qm_frag_end*)((char*)f-
@ -584,7 +583,7 @@ void* qm_realloc(void* qmp, void* p, size_t size)
abort();
}
#endif
if (size==0) {
if (p)
#ifdef DBG_QM_MALLOC
@ -626,12 +625,12 @@ void* qm_realloc(void* qmp, void* p, size_t size)
#endif
/* update used sizes: freed the splited frag */
/* split frag already adds FRAG_OVERHEAD for the newly created
free frag, so here we only need orig_size-f->size for real used
* free frag, so here we only need orig_size-f->size for real used
*/
qm->real_used-=(orig_size-f->size);
qm->used-=(orig_size-f->size);
}
}else if (f->size < size){
/* grow */
#ifdef DBG_QM_MALLOC
@ -641,7 +640,7 @@ void* qm_realloc(void* qmp, void* p, size_t size)
orig_size=f->size;
diff=size-f->size;
n=FRAG_NEXT(f);
if (((char*)n < (char*)qm->last_frag_end) &&
if (((char*)n < (char*)qm->last_frag_end) &&
(n->u.is_free)&&((n->size+FRAG_OVERHEAD)>=diff)){
/* join */
qm_detach_free(qm, n);
@ -712,7 +711,7 @@ void qm_check(struct qm_block* qm)
struct qm_frag* f;
long fcount = 0;
int memlog;
memlog=cfg_get(core, core_cfg, memlog);
LOG(memlog, "DEBUG: qm_check()\n");
f = qm->first_frag;
@ -751,7 +750,7 @@ void qm_check(struct qm_block* qm)
(FRAG_END(f)->check2 != END_CHECK_PATTERN2)) {
LOG(L_CRIT, "BUG: qm_*: fragm. %p (address %p)"
" end overwritten(%lx, %lx)!\n",
f, (char*)f + sizeof(struct qm_frag),
f, (char*)f + sizeof(struct qm_frag),
FRAG_END(f)->check1, FRAG_END(f)->check2);
qm_status(qm);
abort();
@ -787,18 +786,18 @@ void qm_status(void* qmp)
qm->used, qm->real_used, qm->size-qm->real_used);
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
"max used (+overhead)= %lu\n", qm->max_real_used);
if (mem_summary & 16) return;
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
"dumping all alloc'ed. fragments:\n");
for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;f=FRAG_NEXT(f)
,i++){
if (! f->u.is_free){
if ((! f->u.is_free) || (cfg_get(core, core_cfg, mem_status_mode)!=0)){
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
" %3d. %c address=%p frag=%p size=%lu used=%d\n",
i,
(f->u.is_free)?'a':'N',
(f->u.is_free)?'A':'N',
(char*)f+sizeof(struct qm_frag), f, f->size, FRAG_WAS_USED(f));
#ifdef DBG_QM_MALLOC
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
@ -807,6 +806,18 @@ void qm_status(void* qmp)
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
" start check=%lx, end check= %lx, %lx\n",
f->check, FRAG_END(f)->check1, FRAG_END(f)->check2);
if (f->check!=ST_CHECK_PATTERN){
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
" * beginning overwritten(%lx)!\n",
f->check);
}
if ((FRAG_END(f)->check1 != END_CHECK_PATTERN1)
|| (FRAG_END(f)->check2 != END_CHECK_PATTERN2)) {
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
" * end overwritten(%lx, %lx)!\n",
FRAG_END(f)->check1, FRAG_END(f)->check2);
}
#endif
}
}
@ -814,7 +825,7 @@ void qm_status(void* qmp)
"dumping free list stats :\n");
for(h=0,i=0;h<QM_HASH_SIZE;h++){
unused=0;
for (f=qm->free_hash[h].head.u.nxt_free,j=0;
for (f=qm->free_hash[h].head.u.nxt_free,j=0;
f!=&(qm->free_hash[h].head); f=f->u.nxt_free, i++, j++){
if (!FRAG_WAS_USED(f)){
unused++;
@ -822,7 +833,7 @@ void qm_status(void* qmp)
LOG_(DEFAULT_FACILITY, memlog, "qm_status: ",
"unused fragm.: hash = %3d, fragment %p,"
" address %p size %lu, created from %s: %s(%lu)\n",
h, f, (char*)f+sizeof(struct qm_frag), f->size,
h, f, (char*)f+sizeof(struct qm_frag), f->size,
f->file, f->func, f->line);
#endif
}
@ -888,7 +899,7 @@ static mem_counter* get_mem_counter(mem_counter **root, struct qm_frag* f)
for(x=*root;x;x=x->next)
if (x->file == f->file && x->func == f->func && x->line == f->line)
return x;
make_new:
make_new:
x = malloc(sizeof(mem_counter));
x->file = f->file;
x->func = f->func;
@ -910,16 +921,16 @@ void qm_sums(void* qmp)
int i;
mem_counter *root, *x;
int memlog;
qm = (struct qm_block*)qmp;
root=0;
if (!qm) return;
memlog=cfg_get(core, core_cfg, memlog);
LOG_(DEFAULT_FACILITY, memlog, "qm_sums: ",
"summarizing all alloc'ed. fragments:\n");
for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;
f=FRAG_NEXT(f),i++){
if (! f->u.is_free){
@ -946,8 +957,8 @@ void qm_sums(void* qmp)
void qm_mod_get_stats(void *qmp, void **qm_rootp)
{
if (!qm_rootp) {
return ;
}
return;
}
LM_DBG("get qm memory statistics\n");
@ -975,8 +986,8 @@ void qm_mod_get_stats(void *qmp, void **qm_rootp)
void qm_mod_free_stats(void *qm_rootp)
{
if (!qm_rootp) {
return ;
}
return;
}
LM_DBG("free qm memory statistics\n");

@ -59,15 +59,17 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
}
len = strlen(regex);
reg = pkg_malloc(len + 2 + 1);
reg = pkg_malloc(len + 4 + 1);
if (reg == 0) {
LM_ERR("No memory left\n");
return -1;
}
reg[0] = '^';
memcpy(reg + 1, regex, len);
reg[len + 1] = '$';
reg[len + 2] = '\0';
reg[1] = '(';
memcpy(reg + 2, regex, len);
reg[len + 2] = ')';
reg[len + 3] = '$';
reg[len + 4] = '\0';
if (regcomp(&preg, reg, REG_EXTENDED | REG_NOSUB | REG_ICASE)) {
LM_ERR("Error while compiling regular expression\n");

@ -579,8 +579,11 @@ avp_check("$xavp(op=>foo[*])","fm/$xavp(op=>fm[$var(id)])/g");
+ name = ( avp_name | avp_alias ) ['/'flags]
+ flags = 'g' | 'G' | 'd' | 'D' | 'n' | 'N' | 's' | 'S'
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
BRANCH_ROUTE, LOCAL_ROUTE and ONREPLY_ROUTE.
NOTE: if a list of AVPs is copied/moved (flag g|G), then the order of
the values is reversed. Copy/move twice in order to get the same order
as in original list.
This function can be used from ANY_ROUTE.
Example 1.19. avp_copy usage
...

@ -826,8 +826,12 @@ avp_check("$xavp(op=>foo[*])","fm/$xavp(op=>fm[$var(id)])/g");
</listitem>
</itemizedlist>
<para>
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
BRANCH_ROUTE, LOCAL_ROUTE and ONREPLY_ROUTE.
NOTE: if a list of AVPs is copied/moved (flag g|G), then the order
of the values is reversed. Copy/move twice in order to get the same
order as in original list.
</para>
<para>
This function can be used from ANY_ROUTE.
</para>
<example>
<title><function>avp_copy</function> usage</title>

@ -288,7 +288,8 @@ static void cnt_get_rpc(rpc_t* rpc, void* c)
if (rpc->scan(c, "s", &group) < 1)
return;
if (rpc->scan(c, "*s", &name) < 1)
return cnt_grp_get_all(rpc, c, group);
cnt_grp_get_all(rpc, c, group);
return;
/* group & name read */
if (counter_lookup(&h, group, name) < 0) {
rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
@ -427,7 +428,7 @@ static void cnt_grp_get_all_rpc(rpc_t* rpc, void* c)
/* rpc->fault(c, 400, "group name required"); */
return;
}
return cnt_grp_get_all(rpc, c, group);
cnt_grp_get_all(rpc, c, group);
}

@ -486,7 +486,7 @@ static void rpc_fault(struct binrpc_ctx* ctx, int code, char* fmt, ...)
va_end(ap);
len++; /* vnsprintf doesn't include the terminating 0 */
return _rpc_fault(ctx, code, buf, len);
_rpc_fault(ctx, code, buf, len);
}
/* Prepare the error reply without sending out the message */

@ -10,7 +10,7 @@ Daniel-Constantin Mierla
<miconda@gmail.com>
Copyright © 2014 asipto.com
Copyright © 2014 asipto.com
__________________________________________________________________
Table of Contents
@ -85,8 +85,14 @@ Chapter 1. Admin Guide
running Kamailio with this module loaded:
* mongo-c-driver - available at
https://github.com/mongodb/mongo-c-driver
Note: if you use tls module, use at least mongo-c-driver v1.2.1 -
there were reports of issues inside earlier versions of the driver.
Note: if you use tls module, use at least mongo-c-driver v1.3.5 and
compile the library by configuring it without automatic init and
cleanup (you have to run: './configure
--disable-automatic-init-and-cleanup') -- this option is planned to
be removed in future versions. An alternative for v1.3.5 could be
the patch from:
https://github.com/miconda/mongo-c-driver/commit/51d95009de39eaeca4
8491682a5ffec4f83cde55
3. Usage

@ -73,8 +73,13 @@
<ulink url="https://github.com/mongodb/mongo-c-driver">https://github.com/mongodb/mongo-c-driver</ulink>
</para>
<para>
Note: if you use tls module, use at least mongo-c-driver v1.2.1
- there were reports of issues inside earlier versions of the driver.
Note: if you use tls module, use at least mongo-c-driver v1.3.5
and compile the library by configuring it without automatic init
and cleanup (you have to run:
'./configure --disable-automatic-init-and-cleanup') -- this
option is planned to be removed in future versions. An alternative
for v1.3.5 could be the patch from:
https://github.com/miconda/mongo-c-driver/commit/51d95009de39eaeca48491682a5ffec4f83cde55
</para>
</listitem>
</itemizedlist>

@ -1204,7 +1204,7 @@ int db_mongodb_update(const db1_con_t* _h, const db_key_t* _k,
if(db_mongodb_bson_add(sdoc, _uk[i], _uv+i, i)<0)
goto error;
}
if(bson_append_document(udoc, "$set", 4, sdoc)<0) {
if(!bson_append_document(udoc, "$set", 4, sdoc)) {
LM_ERR("failed to append document to bson document\n");
goto error;
}

@ -138,7 +138,8 @@ static int db_unixodbc_submit_query(const db1_con_t* _h, const str* _s)
/* Connection broken */
if( !strncmp((char*)sqlstate,"08003",5) ||
!strncmp((char*)sqlstate,"08S01",5)
!strncmp((char*)sqlstate,"08S01",5) ||
!strncmp((char*)sqlstate,"HY000",5) /* ODBC 3 General error */
)
{
ret = reconnect(_h);

@ -66,6 +66,7 @@
#include "../../parser/parse_to.h"
#include "../../modules/tm/tm_load.h"
#include "../../rpc_lookup.h"
#include "../../srapi.h"
#include "../rr/api.h"
#include "dlg_hash.h"
#include "dlg_timer.h"
@ -459,6 +460,7 @@ static int pv_get_dlg_count(struct sip_msg *msg, pv_param_t *param,
static int mod_init(void)
{
unsigned int n;
sr_cfgenv_t *cenv = NULL;
if(dlg_ka_interval!=0 && dlg_ka_interval<30) {
LM_ERR("ka interval too low (%d), has to be at least 30\n",
@ -510,7 +512,7 @@ static int mod_init(void)
}
if (timeout_spec.s) {
if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0
if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0
&& (timeout_avp.type!=PVT_AVP)){
LM_ERR("malformed or non AVP timeout "
"AVP definition in '%.*s'\n", timeout_spec.len,timeout_spec.s);
@ -702,8 +704,11 @@ static int mod_init(void)
/* timer process to clean old unconfirmed dialogs */
register_sync_timers(1);
if(_dlg_track_cseq_updates!=0)
if(_dlg_track_cseq_updates!=0) {
cenv = sr_cfgenv_get();
cenv->cb_cseq_update = dlg_cseq_update;
dlg_register_cseq_callbacks();
}
return 0;
}
@ -743,7 +748,7 @@ static int child_init(int rank)
}
if ( ((dlg_db_mode==DB_MODE_REALTIME || dlg_db_mode==DB_MODE_DELAYED) &&
(rank>0 || rank==PROC_TIMER)) ||
(rank>0 || rank==PROC_TIMER || rank==PROC_RPC)) ||
(dlg_db_mode==DB_MODE_SHUTDOWN && (rank==PROC_MAIN)) ) {
if ( dlg_connect_db(&db_url) ) {
LM_ERR("failed to connect to database (rank=%d)\n",rank);

@ -35,8 +35,11 @@
#include "../../events.h"
#include "../../ut.h"
#include "../../trim.h"
#include "../../data_lump.h"
#include "../../parser/parse_to.h"
#include "../../parser/parse_from.h"
#include "../../parser/parse_cseq.h"
#include "../../modules/tm/tm_load.h"
#include "dlg_handlers.h"
@ -103,6 +106,155 @@ int dlg_cseq_prepare_msg(sip_msg_t *msg)
return 0;
}
/**
*
*/
int dlg_cseq_update(sip_msg_t *msg)
{
dlg_cell_t *dlg = NULL;
unsigned int direction;
unsigned int ninc = 0;
unsigned int vinc = 0;
str nval;
str *pval;
if(dlg_cseq_prepare_msg(msg)!=0) {
goto error;
}
if(msg->first_line.type==SIP_REPLY) {
/* nothing to do for outgoing replies */
goto done;
}
LM_DBG("initiating cseq updates\n");
direction = DLG_DIR_NONE;
dlg = dlg_lookup_msg_dialog(msg, &direction);
if(dlg == NULL) {
LM_DBG("no dialog for this request\n");
goto done;
}
/* supported only for downstrem direction */
if(direction != DLG_DIR_DOWNSTREAM) {
LM_DBG("request not going downstream (%u)\n", direction);
goto done;
}
ninc = 1;
/* take the increment value from dialog */
if((dlg->iflags&DLG_IFLAG_CSEQ_DIFF)==DLG_IFLAG_CSEQ_DIFF) {
/* get dialog variable holding cseq diff */
pval = get_dlg_variable(dlg, &_dlg_cseq_diff_var_name);
if(pval==NULL || pval->s==NULL || pval->len<=0) {
LM_DBG("dialog marked with cseq diff but no variable set yet\n");
goto done;
}
if(str2int(pval, &vinc)<0) {
LM_ERR("invalid dlg cseq diff var value: %.*s\n",
pval->len, pval->s);
goto done;
}
}
vinc += ninc;
if(vinc==0) {
LM_DBG("nothing to increment\n");
goto done;
}
nval.s = int2str(vinc, &nval.len);
if(set_dlg_variable(dlg, &_dlg_cseq_diff_var_name, &nval) <0) {
LM_ERR("failed to set the dlg cseq diff var\n");
goto done;
}
str2int(&get_cseq(msg)->number, &ninc);
vinc += ninc;
nval.s = int2str(vinc, &nval.len);
trim(&nval);
LM_DBG("adding auth cseq header value: %.*s\n", nval.len, nval.s);
parse_headers(msg, HDR_EOH_F, 0);
sr_hdr_add_zs(msg, "P-K-Auth-CSeq", &nval);
done:
if(dlg!=NULL) dlg_release(dlg);
return 0;
error:
if(dlg!=NULL) dlg_release(dlg);
return -1;
}
/**
*
*/
int dlg_cseq_refresh(sip_msg_t *msg, dlg_cell_t *dlg,
unsigned int direction)
{
unsigned int ninc = 0;
unsigned int vinc = 0;
str nval;
str *pval;
if(dlg_cseq_prepare_msg(msg)!=0) {
goto error;
}
if(msg->first_line.type==SIP_REPLY) {
/* nothing to do for outgoing replies */
goto done;
}
LM_DBG("initiating cseq refresh\n");
/* supported only for downstrem direction */
if(direction != DLG_DIR_DOWNSTREAM) {
LM_DBG("request not going downstream (%u)\n", direction);
goto done;
}
/* take the increment value from dialog */
if(!((dlg->iflags&DLG_IFLAG_CSEQ_DIFF)==DLG_IFLAG_CSEQ_DIFF)) {
LM_DBG("no cseq refresh required\n");
goto done;
}
/* get dialog variable holding cseq diff */
pval = get_dlg_variable(dlg, &_dlg_cseq_diff_var_name);
if(pval==NULL || pval->s==NULL || pval->len<=0) {
LM_DBG("dialog marked with cseq diff but no variable set yet\n");
goto done;
}
if(str2int(pval, &vinc)<0) {
LM_ERR("invalid dlg cseq diff var value: %.*s\n",
pval->len, pval->s);
goto done;
}
if(vinc==0) {
LM_DBG("nothing to increment\n");
goto done;
}
str2int(&get_cseq(msg)->number, &ninc);
vinc += ninc;
nval.s = int2str(vinc, &nval.len);
trim(&nval);
LM_DBG("adding cseq refresh header value: %.*s\n", nval.len, nval.s);
parse_headers(msg, HDR_EOH_F, 0);
sr_hdr_add_zs(msg, "P-K-CSeq-Refresh", &nval);
done:
if(dlg!=NULL) dlg_release(dlg);
return 0;
error:
if(dlg!=NULL) dlg_release(dlg);
return -1;
}
/**
*
*/
@ -153,9 +305,9 @@ int dlg_cseq_msg_received(void *data)
}
LM_DBG("via cseq cookie [%.*s] val [%.*s]\n", vcseq.len, vcseq.s,
vcseq.len-3, vcseq.s+3);
if(vcseq.len-3<get_cseq(&msg)->number.len) {
if(vcseq.len-3>get_cseq(&msg)->number.len) {
/* higher lenght to update - wrong */
LM_DBG("cseq in message (%d) longer than in via (%d)\n",
LM_DBG("cseq in message (%d) shorter than in via (%d)\n",
get_cseq(&msg)->number.len, vcseq.len-3);
goto done;
}
@ -188,15 +340,12 @@ int dlg_cseq_msg_sent(void *data)
sip_msg_t msg;
str *obuf;
unsigned int direction;
tm_cell_t *t;
unsigned int ninc = 0;
unsigned int vinc = 0;
dlg_cell_t *dlg = NULL;
str nval;
str *pval;
str nval = STR_NULL;
char tbuf[BUF_SIZE];
int tbuf_len = 0;
struct via_body *via;
hdr_field_t *hfk = NULL;
obuf = (str*)data;
memset(&msg, 0, sizeof(sip_msg_t));
@ -222,7 +371,7 @@ int dlg_cseq_msg_sent(void *data)
direction = DLG_DIR_NONE;
dlg = dlg_lookup_msg_dialog(&msg, &direction);
if(dlg == NULL) {
LM_DBG("no dialog for this request\n");
goto done;
@ -234,54 +383,38 @@ int dlg_cseq_msg_sent(void *data)
goto done;
}
parse_headers(&msg, HDR_EOH_F, 0);
/* check if transaction is marked for a new increment */
if(get_cseq(&msg)->method_id!=METHOD_ACK) {
t = d_tmb.t_gett();
if(t==NULL || t==T_UNDEFINED) {
LM_DBG("no transaction for request\n");
goto done;
}
if(t->uas.request==0) {
LM_DBG("no uas request - no cseq update needed\n");
goto done;
}
if((t->uas.request->msg_flags&FL_UAC_AUTH)==FL_UAC_AUTH) {
LM_DBG("uac auth request - cseq inc needed\n");
ninc = 1;
hfk = sr_hdr_get_z(&msg, "P-K-Auth-CSeq");
if(hfk!=NULL) {
LM_DBG("new cseq inc requested\n");
nval = hfk->body;
trim(&nval);
} else {
LM_DBG("new cseq inc not requested\n");
}
}
/* take the increment value from dialog */
if((dlg->iflags&DLG_IFLAG_CSEQ_DIFF)==DLG_IFLAG_CSEQ_DIFF) {
/* get dialog variable holding cseq diff */
pval = get_dlg_variable(dlg, &_dlg_cseq_diff_var_name);
if(pval==NULL || pval->s==NULL || pval->len<=0) {
LM_DBG("dialog marked with cseq diff but no variable set yet\n");
goto done;
}
if(str2int(pval, &vinc)<0) {
LM_ERR("invalid dlg cseq diff var value: %.*s\n",
pval->len, pval->s);
goto done;
if(nval.len<=0) {
hfk = sr_hdr_get_z(&msg, "P-K-CSeq-Refresh");
if(hfk!=NULL) {
LM_DBG("cseq refresh requested\n");
nval = hfk->body;
trim(&nval);
}
}
vinc += ninc;
if(vinc==0) {
LM_DBG("nothing to increment\n");
if(nval.len<=0) {
LM_DBG("cseq refresh requested, but no new value found\n");
goto done;
}
nval.s = int2str(vinc, &nval.len);
if(msg.len + 3 + 2*nval.len>=BUF_SIZE) {
LM_ERR("new messages is too big\n");
goto done;
}
if(set_dlg_variable(dlg, &_dlg_cseq_diff_var_name, &nval) <0) {
LM_ERR("failed to set the dlg cseq diff var\n");
goto done;
}
str2int(&get_cseq(&msg)->number, &ninc);
vinc += ninc;
nval.s = int2str(vinc, &nval.len);
LM_DBG("updating cseq to: %.*s\n", nval.len, nval.s);
/* new cseq value */
dlg->iflags |= DLG_IFLAG_CSEQ_DIFF;
@ -306,12 +439,25 @@ int dlg_cseq_msg_sent(void *data)
/* add new value */
memcpy(tbuf+tbuf_len, nval.s, nval.len);
tbuf_len += nval.len;
/* copy from after cseq number to the end of sip message */
memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
msg.buf + msg.len - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len);
tbuf_len += msg.buf+msg.len - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len;
if(hfk && hfk->name.s > get_cseq(&msg)->number.s) {
/* copy from after cseq number to the beginning of hfk */
memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
hfk->name.s - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len);
tbuf_len += hfk->name.s - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len;
/* copy from after hfk to the end of sip message */
memcpy(tbuf+tbuf_len, hfk->name.s + hfk->len,
msg.buf + msg.len - hfk->name.s - hfk->len);
tbuf_len += msg.buf + msg.len - hfk->name.s - hfk->len;
} else {
/* copy from after cseq number to the end of sip message */
memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
msg.buf + msg.len - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len);
tbuf_len += msg.buf+msg.len - get_cseq(&msg)->number.s
- get_cseq(&msg)->number.len;
}
} else {
/* CSeq is before Via */
/* copy till beginning of cseq number */
@ -332,12 +478,25 @@ int dlg_cseq_msg_sent(void *data)
tbuf[tbuf_len++] = 's';
memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s, get_cseq(&msg)->number.len);
tbuf_len += get_cseq(&msg)->number.len;
/* copy from after via to the end of sip message */
memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
msg.buf + msg.len - via->branch->value.s
- via->branch->value.len);
tbuf_len += msg.buf+msg.len - via->branch->value.s
- via->branch->value.len;
if(hfk && hfk->name.s > get_cseq(&msg)->number.s) {
/* copy from after via to the beginning of hfk */
memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
hfk->name.s - via->branch->value.s
- via->branch->value.len);
tbuf_len += hfk->name.s - via->branch->value.s
- via->branch->value.len;
/* copy from after hfk to the end of sip message */
memcpy(tbuf+tbuf_len, hfk->name.s + hfk->len,
msg.buf + msg.len - hfk->name.s - hfk->len);
tbuf_len += msg.buf + msg.len - hfk->name.s - hfk->len;
} else {
/* copy from after via to the end of sip message */
memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
msg.buf + msg.len - via->branch->value.s
- via->branch->value.len);
tbuf_len += msg.buf+msg.len - via->branch->value.s
- via->branch->value.len;
}
}
/* replace old msg content */
obuf->s = pkg_malloc((tbuf_len+1)*sizeof(char));

@ -32,7 +32,12 @@
#define _DLG_CSEQ_H_
#include "../../parser/msg_parser.h"
#include "dlg_hash.h"
int dlg_register_cseq_callbacks(void);
int dlg_cseq_update(sip_msg_t *msg);
int dlg_cseq_refresh(sip_msg_t *msg, dlg_cell_t *dlg,
unsigned int direction);
#endif

@ -48,6 +48,7 @@
#include "dlg_hash.h"
#include "dlg_timer.h"
#include "dlg_cb.h"
#include "dlg_cseq.h"
#include "dlg_handlers.h"
#include "dlg_req_within.h"
#include "dlg_db_handler.h"
@ -603,7 +604,7 @@ static void dlg_seq_onreply_helper(struct cell* t, int type,
*/
static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param)
{
return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
}
@ -616,7 +617,7 @@ static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *par
*/
static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param)
{
return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
}
@ -1163,7 +1164,7 @@ dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
/*!
* \brief Function that is registered as RR callback for dialog tracking
*
*
* Function that is registered as RR callback for dialog tracking. It
* sets the appropriate events after the SIP method and run the state
* machine to update the dialog state. It updates then the saved
@ -1255,7 +1256,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
}
if (dlg==0) {
if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
if (pre_match_parse(req, &callid, &ftag, &ttag, 1)<0)
return;
/* TODO - try to use the RR dir detection to speed up here the
* search -bogdan */
@ -1272,6 +1273,12 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
_dlg_ctx.iuid.h_entry = dlg->h_entry;
_dlg_ctx.iuid.h_id = dlg->h_id;
if(dlg->iflags & DLG_IFLAG_CSEQ_DIFF) {
if(dlg_cseq_refresh(req, dlg, dir)<0) {
LM_ERR("failed to refresh cseq update\n");
}
}
if (req->first_line.u.request.method_value != METHOD_ACK) {
iuid = dlg_get_iuid_shm_clone(dlg);
if(iuid!=NULL)

@ -185,7 +185,7 @@ int set_dlg_variable_unsafe(struct dlg_cell *dlg, str *key, str *val)
/* replace the current it with var and free the it */
var->next = it->next;
/* Take the previous vflags: */
var->vflags = it->vflags & DLG_FLAG_CHANGED;
var->vflags = it->vflags | DLG_FLAG_CHANGED;
if (it_prev) it_prev->next = var;
else *var_list = var;
}

@ -587,7 +587,8 @@ static void destroy(void)
ds_hash_load_destroy();
if(ds_ping_reply_codes)
shm_free(ds_ping_reply_codes);
if(ds_ping_reply_codes_cnt)
shm_free(ds_ping_reply_codes_cnt);
}
#define GET_VALUE(param_name,param,i_value,s_value,value_flags) do{ \

@ -219,7 +219,7 @@ modparam("dmq", "multi_notify", 1)
Example 1.5. Set num_workers parameter
...
modparam("dmq", "num_threads", 4)
modparam("dmq", "num_workers", 4)
...
3.5. ping_interval(int)

@ -166,7 +166,7 @@ modparam("dmq", "multi_notify", 1)
<title>Set <varname>num_workers</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("dmq", "num_threads", 4)
modparam("dmq", "num_workers", 4)
...
</programlisting>
</example>

@ -221,6 +221,8 @@ int evapi_dispatch_notify(char *obuf, int olen)
}
}
LM_DBG("the message was sent to %d clients\n", n);
return n;
}

@ -51,6 +51,7 @@ static char *_evapi_bind_param = NULL;
static int _evapi_netstring_format_param = 1;
static tm_api_t tmb;
static int _evapi_dispatcher_pid = -1;
static int mod_init(void);
static int child_init(int);
@ -164,16 +165,24 @@ static int child_init(int rank)
}
if (rank!=PROC_MAIN) {
evapi_close_notify_sockets_parent();
if(_evapi_dispatcher_pid!=getpid()) {
evapi_close_notify_sockets_parent();
}
return 0;
}
pid=fork_process(PROC_RPC, "EvAPI Dispatcher", 1);
pid=fork_process(PROC_NOCHLDINIT, "EvAPI Dispatcher", 1);
if (pid<0)
return -1; /* error */
if(pid==0) {
/* child */
_evapi_dispatcher_pid = getpid();
/* do child init to allow execution of rpc like functions */
if(init_child(PROC_RPC) < 0) {
LM_DBG("failed to do RPC child init for dispatcher\n");
return -1;
}
/* initialize the config framework */
if (cfg_child_init())
return -1;

@ -263,7 +263,7 @@ modparam("http_async_client", "curl_verbose", 1)
Choose the memory manager used by curl:
* shm: curl will use kamailio's SHM pool and memory manager
* sys: curl will use the system memory amd memory manager (malloc,
* sys: curl will use the system memory and memory manager (malloc,
free, ...)
Note: if this module is used in conjunction with another module using

@ -209,7 +209,7 @@ modparam("http_async_client", "curl_verbose", 1)
<emphasis>shm</emphasis>: curl will use kamailio's SHM pool and memory manager
</para></listitem>
<listitem><para>
<emphasis>sys</emphasis>: curl will use the system memory amd memory manager (malloc, free, ...)
<emphasis>sys</emphasis>: curl will use the system memory and memory manager (malloc, free, ...)
</para></listitem>
</itemizedlist>
<para>

@ -54,6 +54,7 @@
#include "../../modules/tm/tm_load.h"
#include "../../modules/pv/pv_api.h"
#include "async_http.h"
MODULE_VERSION
@ -227,6 +228,18 @@ struct module_exports exports = {
};
int mod_register(char *path, int *dlflags, void *p1, void *p2)
{
pv_register_api_t pvra;
pvra = (pv_register_api_t)find_export("pv_register_api", NO_SCRIPT, 0);
if (!pvra) {
LM_ERR("Cannot import pv functions (pv module must be loaded before this module)\n");
return -1;
}
pvra(&pv_api);
return 0;
}
/**
* init module function
@ -234,7 +247,6 @@ struct module_exports exports = {
static int mod_init(void)
{
unsigned int n;
pv_register_api_t pvra;
LM_INFO("Initializing Http Async module\n");
#ifdef STATISTICS
@ -304,13 +316,6 @@ static int mod_init(void)
memset(&tmb, 0, sizeof(tm_api_t));
}
pvra = (pv_register_api_t)find_export("pv_register_api", NO_SCRIPT, 0);
if (!pvra) {
LM_ERR("Cannot import pv functions (pv module must be loaded before this module)\n");
return -1;
}
pvra(&pv_api);
/* allocate workers array */
workers = shm_malloc(num_workers * sizeof(*workers));
if(workers == NULL) {
@ -496,11 +501,7 @@ static int w_http_async_post(sip_msg_t *msg, char *query, char* post, char* rt)
return -1;
}
if(async_send_query(msg, &sdata, &post_data, act)<0)
return -1;
/* force exit in config */
return 0;
return async_send_query(msg, &sdata, &post_data, act);
}
#define _IVALUE_ERROR(NAME) LM_ERR("invalid parameter '" #NAME "' (must be a number)\n")

@ -575,18 +575,18 @@ xlog("L_INFO", "API-server HTTP connection: $avp(route) Result code $var(res)\n"
Example 1.17. curl_http_query() usage
...
# GET-Request
http_client_query("http://tutpro.com/index.php?r_uri=$(ru{s.escape.param})&f_uri
=$(fu{s.escape.param})",
"$var(result)")
http_client_query("http://api.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(
fu{s.escape.param})",
"$var(result)");
switch ($retcode) {
...
}
...
...
# POST-Request
http_client_query("http://tutpro.com/index.php", "r_uri=$(ru{s.escape.param})&f_
uri=$(fu{s.escape.param})",
"$var(result)")
http_client_query("http://api.com/index.php", "r_uri=$(ru{s.escape.param})&f_uri
=$(fu{s.escape.param})",
"$var(result)");
switch ($retcode) {
...
}

@ -627,8 +627,8 @@ xlog("L_INFO", "API-server HTTP connection: $avp(route) Result code $var(res)\n"
<programlisting format="linespecific">
...
# GET-Request
http_client_query("http://tutpro.com/index.php?r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)")
http_client_query("http://api.com/index.php?r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)");
switch ($retcode) {
...
}
@ -637,8 +637,8 @@ switch ($retcode) {
<programlisting format="linespecific">
...
# POST-Request
http_client_query("http://tutpro.com/index.php", "r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)")
http_client_query("http://api.com/index.php", "r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)");
switch ($retcode) {
...
}
@ -672,7 +672,6 @@ switch ($retcode) {
<para>Parameters:</para>
<itemizedlist>
<listitem><para>No parameters</para></listitem>
</itemizedlist>
</section>
</section>

@ -535,7 +535,7 @@ static int w_ip_is_in_subnet(struct sip_msg* _msg, char* _s1, char* _s2)
str string1, string2;
enum enum_ip_type ip1_type, ip2_type;
char *cidr_pos = NULL;
int netmask = 0;
int netmask = -1;
if (_s1 == NULL || _s2 == NULL ) {
LM_ERR("bad parameters\n");
@ -586,7 +586,7 @@ static int w_ip_is_in_subnet(struct sip_msg* _msg, char* _s1, char* _s2)
break;
}
if (netmask == 0)
if (netmask == -1)
{
if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
return 1;

@ -1,21 +1,28 @@
#
# jansson module makefile
#
#
#
# WARNING: do not run this directly, it should be run by the master Makefile
include ../../Makefile.defs
auto_gen=
NAME=jansson.so
BUILDER = $(shell which pkg-config)
ifeq ($(BUILDER),)
DEFS+=-I$(LOCALBASE)/include \
LIBS+=-L$(SYSBASE)/include/lib -L$(LOCALBASE)/lib -ljansson
ifeq ($(CROSS_COMPILE),)
JNS_BUILDER=$(shell \
if pkg-config --exists jansson; then \
echo 'pkg-config jansson'; \
fi)
endif
ifneq ($(JNS_BUILDER),)
DEFS += $(shell $(JNS_BUILDER) --cflags)
LIBS += $(shell $(JNS_BUILDER) --libs)
else
DEFS+= $(shell pkg-config --cflags jansson)
LIBS+= $(shell pkg-config --libs jansson)
DEFS+=-I$(LOCALBASE)/include
LIBS+=-L$(SYSBASE)/include/lib -L$(LOCALBASE)/lib -ljansson
endif
DEFS+=-DOPENSER_MOD_INTERFACE
SERLIBPATH=../../lib

@ -39,6 +39,7 @@
#include "../../action.h"
#include "../../route_struct.h"
#include "../../lvalue.h"
#include "../../cfg/cfg_struct.h"
#include "../../rand/fastrand.h"
#include "../tm/tm_load.h"
#include "../jansson/jansson_utils.h"
@ -57,11 +58,15 @@ void io_shutdown(int sig);
int jsonrpc_io_child_process(int cmd_pipe)
{
struct event* pipe_ev = NULL;
global_ev_base = event_base_new();
global_evdns_base = evdns_base_new(global_ev_base, 1);
set_non_blocking(cmd_pipe);
struct event* pipe_ev = event_new(global_ev_base, cmd_pipe, EV_READ | EV_PERSIST, cmd_pipe_cb, NULL);
pipe_ev = event_new(global_ev_base, cmd_pipe,
EV_READ | EV_PERSIST, cmd_pipe_cb, NULL);
if(!pipe_ev) {
ERR("Failed to create pipe event\n");
return -1;
@ -449,6 +454,7 @@ void cmd_pipe_cb(int fd, short event, void *arg)
return;
}
cfg_update();
switch(cmd->type) {
case CMD_CLOSE:

@ -29,6 +29,7 @@
#include "../../trim.h"
#include "../../sr_module.h"
#include "../../timer_proc.h"
#include "../../cfg/cfg_struct.h"
#include "../tm/tm_load.h"
#include "../jansson/jansson_utils.h"
@ -158,7 +159,7 @@ static int child_init(int rank)
{
int pid;
if (rank>PROC_MAIN)
if (rank!=PROC_INIT)
cmd_pipe = pipe_fds[1];
if (rank!=PROC_MAIN)
@ -194,6 +195,7 @@ static int child_init(int rank)
return -1; /* error */
if(pid==0){
/* child */
if (cfg_child_init()) return -1;
close(pipe_fds[1]);
return jsonrpc_io_child_process(pipe_fds[0]);
}

@ -115,15 +115,15 @@ static int mod_init(void) {
LM_ERR("pipe() failed\n");
return -1;
}
return(0);
}
static int child_init(int rank)
static int child_init(int rank)
{
int pid;
if (rank>PROC_MAIN)
if (rank!=PROC_INIT)
cmd_pipe = pipe_fds[1];
if (rank!=PROC_MAIN)

@ -571,7 +571,7 @@ static int jsonrpc_scan(jsonrpc_ctx_t* ctx, char* fmt, ...)
case '{':
case '[':
LM_ERR("Unsupported param type '%c'\n", *fmt);
jsonrpc_fault(ctx, 500, "Unsupported param type");
jsonrpc_fault(ctx, 400, "Unsupported param type");
goto error;
default:
LM_ERR("Invalid param type in formatting string: [%c]\n", *fmt);
@ -1041,7 +1041,7 @@ static int jsonrpc_dispatch(sip_msg_t* msg, char* s1, char* s2)
ctx->jreq = srjson_NewDoc(NULL);
if(ctx->jreq==NULL) {
LM_ERR("Failed to init the json document\n");
return NONSIP_MSG_PASS;
return NONSIP_MSG_ERROR;
}
ctx->jreq->buf.s = get_body(msg);
@ -1050,7 +1050,7 @@ static int jsonrpc_dispatch(sip_msg_t* msg, char* s1, char* s2)
if(ctx->jreq->root == NULL)
{
LM_ERR("invalid json doc [[%s]]\n", ctx->jreq->buf.s);
return NONSIP_MSG_PASS;
return NONSIP_MSG_ERROR;
}
if (jsonrpc_init_reply(ctx) < 0) goto send_reply;

@ -393,6 +393,7 @@ static int mod_child_init(int rank)
if (pid<0)
return -1; /* error */
if(pid==0){
if (cfg_child_init()) return -1;
close(kz_worker_pipes_fds[i*2+1]);
return(kz_amqp_consumer_worker_proc(kz_worker_pipes_fds[i*2]));
}
@ -406,6 +407,7 @@ static int mod_child_init(int rank)
if (pid<0)
return -1; /* error */
if(pid==0){
if (cfg_child_init()) return -1;
return(kz_amqp_consumer_proc(s));
}
}
@ -416,6 +418,7 @@ static int mod_child_init(int rank)
if (pid<0)
return -1; /* error */
if(pid==0){
if (cfg_child_init()) return -1;
close(kz_cmd_pipe_fds[1]);
kz_amqp_publisher_proc(kz_cmd_pipe_fds[0]);
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-15 Robert Boisvert
* Copyright (C) 2013-16 Robert Boisvert
*
* This file is part of the mohqueue module for Kamailio, a free SIP server.
*
@ -42,6 +42,7 @@ static int mod_init (void);
**********/
mod_data *pmod_data;
pv_spec_t *prtp_pv;
/**********
* module exports
@ -97,6 +98,12 @@ struct module_exports exports = {
mod_child_init, /* per-child initialization function */
};
/**********
* local constants
**********/
str prtpstat [1] = {STR_STATIC_INIT ("$rtpstat")};
/**********
* local functions
**********/
@ -349,6 +356,8 @@ return;
int mod_init (void)
{
int rtplen;
/**********
* o allocate shared mem and init
* o init configuration data
@ -430,6 +439,23 @@ if (!pmod_data->fn_rtp_destroy)
goto initerr;
}
/**********
* get RTPSTAT pv spec
**********/
rtplen = pv_locate_name (prtpstat);
if(rtplen != prtpstat->len)
{
LM_ERR ("Unable to find RTPSTAT pv!\n");
goto initerr;
}
prtp_pv = pv_cache_get (&prtpstat);
if(!prtp_pv)
{
LM_ERR ("Unable to find pv spec for RTPSTAT!\n");
goto initerr;
}
/**********
* init MOH and call queue locks
**********/

@ -131,6 +131,7 @@ typedef struct
**********/
extern mod_data *pmod_data;
extern pv_spec_t *prtp_pv;
extern rtpmap prtpmap [];
#endif /* MOHQ_H */

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-15 Robert Boisvert
* Copyright (C) 2013-16 Robert Boisvert
*
* This file is part of the mohqueue module for Kamailio, a free SIP server.
*
@ -32,7 +32,7 @@
#define ALLOWHDR "Allow: INVITE, ACK, BYE, CANCEL, NOTIFY, PRACK"
#define CLENHDR "Content-Length"
#define SIPEOL "\r\n"
#define USRAGNT "Kamailio MOH Queue v1.2"
#define USRAGNT "Kamailio MOH Queue v1.3"
/**********
* local constants
@ -403,6 +403,26 @@ else
return;
}
/**********
* Check if RTP Still Active
*
* INPUT:
* Arg (1) = SIP message pointer
* OUTPUT: =0 if inactive
**********/
int chk_rtpstat (sip_msg_t *pmsg)
{
pv_value_t pval [1];
memset (pval, 0, sizeof (pv_value_t));
if (pv_get_spec_value (pmsg, prtp_pv, pval))
{ return 0; }
if (pval->flags & PV_VAL_NULL)
{ return 0; }
return 1;
}
/**********
* Close the Call
*
@ -1664,10 +1684,23 @@ return nret;
static void refer_cb
(struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
{
char *pfncname = "refer_cb: ";
call_lst *pcall = (call_lst *)*pcbp->param;
if (pcall->call_state != CLSTA_REFER)
{
if (!pcall->call_state)
{
LM_ERR
("%sREFER response ignored because call not in queue!\n", pfncname);
}
else
{
LM_ERR ("%sCall (%s) ignored because not in REFER state!\n", pfncname,
pcall->call_from);
}
return;
}
if ((ntype == TMCB_ON_FAILURE) || (pcbp->req == FAKED_REPLY))
{
LM_ERR ("%sCall (%s) did not respond to REFER!\n", pfncname,
@ -1676,6 +1709,11 @@ if ((ntype == TMCB_ON_FAILURE) || (pcbp->req == FAKED_REPLY))
delete_call (pcall);
return;
}
/**********
* check reply
**********/
int nreply = pcbp->code;
if ((nreply / 100) == 2)
{
@ -1692,8 +1730,17 @@ else
{ delete_call (pcall); }
else
{
pcall->call_state = CLSTA_INQUEUE;
update_call_rec (pcall);
if (!chk_rtpstat (pcbp->req))
{
LM_ERR ("%sRTP for call (%s) no longer active!\n",
pfncname, pcall->call_from);
delete_call (pcall);
}
else
{
pcall->call_state = CLSTA_INQUEUE;
update_call_rec (pcall);
}
}
}
return;

@ -44,7 +44,6 @@ typedef struct _mq_item
{
str key;
str val;
struct _mq_item *prev;
struct _mq_item *next;
} mq_item_t;
@ -266,8 +265,6 @@ int mq_head_fetch(str *name)
mh->ifirst = mh->ifirst->next;
if(mh->ifirst==NULL) {
mh->ilast = NULL;
} else {
mh->ifirst->prev = NULL;
}
mh->csize--;
@ -332,7 +329,6 @@ int mq_item_add(str *qname, str *key, str *val)
mh->ilast = mi;
} else {
mh->ilast->next = mi;
mi->prev = mh->ilast;
mh->ilast = mi;
}
mh->csize++;
@ -341,9 +337,9 @@ int mq_item_add(str *qname, str *key, str *val)
mi = mh->ifirst;
mh->ifirst = mh->ifirst->next;
if(mh->ifirst==NULL)
{
mh->ilast = NULL;
else
mh->ifirst->prev = NULL;
}
mh->csize--;
shm_free(mi);
}

@ -10,7 +10,7 @@ Daniel-Constantin Mierla
<miconda@gmail.com>
Copyright © 2014 asipto.com
Copyright © 2014 asipto.com
__________________________________________________________________
Table of Contents
@ -98,8 +98,14 @@ Chapter 1. Admin Guide
running Kamailio with this module loaded:
* mongo-c-driver - available at
https://github.com/mongodb/mongo-c-driver
Note: if you use tls module, use at least mongo-c-driver v1.2.1 -
there were reports of issues inside earlier versions of the driver.
Note: if you use tls module, use at least mongo-c-driver v1.3.5 and
compile the library by configuring it without automatic init and
cleanup (you have to run: './configure
--disable-automatic-init-and-cleanup') -- this option is planned to
be removed in future versions. An alternative for v1.3.5 could be
the patch from:
https://github.com/miconda/mongo-c-driver/commit/51d95009de39eaeca4
8491682a5ffec4f83cde55
3. Parameters
@ -135,7 +141,7 @@ modparam("ndb_mongodb", "server", "name=mgs2;uri='mongodb://127.0.0.2/kamailio'"
4.5. mongodb_next(replyid)
4.6. mongodb_free(replyid)
4.1. mongodb_cmd(srvname, dbname, cname, command, replyid)
4.1. mongodb_cmd(srvname, dbname, cname, command, replyid)
Send a valid command to MongoDB server identified by srvname. The reply
will be stored in a local container identified by replyid. All the
@ -167,7 +173,7 @@ if(mongodb_cmd("mgs1", "kamailio", "acc", "{ \"collStats\": \"acc\" }", "mgr1"))
}
...
4.2. mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
4.2. mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
Send a valid command to MongoDB server identified by srvname. The reply
will be stored in a local container identified by replyid. All the
@ -193,7 +199,7 @@ mgr1")) {
}
...
4.3. mongodb_find(srvname, dbname, cname, command, replyid)
4.3. mongodb_find(srvname, dbname, cname, command, replyid)
Send a find command to MongoDB server identified by srvname. The reply
will be stored in a local container identified by replyid. All the
@ -222,7 +228,7 @@ if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
}
...
4.4. mongodb_find_one(srvname, dbname, cname, command, replyid)
4.4. mongodb_find_one(srvname, dbname, cname, command, replyid)
Similar to mongodb_find(...), but it stops searching after first match,
returning the result with one object - faster when expecting to have a
@ -239,7 +245,7 @@ if(mongodb_find_one("mgs1", "kamailio", "subscriber", "{ \"username\" : \"111\"
}
...
4.5. mongodb_next(replyid)
4.5. mongodb_next(replyid)
Moves to next document in a MongoDB reply. This function can be used
after a succesful mongodb_cmd() or mongodb_find(). It returns true if
@ -258,7 +264,7 @@ if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
mongodb_free("mgr1");
...
4.6. mongodb_free(replyid)
4.6. mongodb_free(replyid)
Frees data in a previous reply from memory. After this function call,
accessing to a freed replyid returns null value.

@ -53,8 +53,13 @@
<ulink url="https://github.com/mongodb/mongo-c-driver">https://github.com/mongodb/mongo-c-driver</ulink>
</para>
<para>
Note: if you use tls module, use at least mongo-c-driver v1.2.1
- there were reports of issues inside earlier versions of the driver.
Note: if you use tls module, use at least mongo-c-driver v1.3.5
and compile the library by configuring it without automatic init
and cleanup (you have to run:
'./configure --disable-automatic-init-and-cleanup') -- this
option is planned to be removed in future versions. An alternative
for v1.3.5 could be the patch from:
https://github.com/miconda/mongo-c-driver/commit/51d95009de39eaeca48491682a5ffec4f83cde55
</para>
</listitem>
</itemizedlist>

@ -1,4 +1,4 @@
#
#
# WARNING: do not run this directly, it should be run by the master Makefile
include ../../Makefile.defs
@ -6,15 +6,32 @@ auto_gen=
NAME=outbound.so
ifeq ($(CROSS_COMPILE),)
BUILDER = $(shell which pkg-config)
endif
ifneq ($(BUILDER),)
SSL_BUILDER=$(shell \
if pkg-config --exists libssl; then \
echo 'pkg-config libssl'; \
fi)
CRYPTO_BUILDER=$(shell \
if pkg-config --exists libcrypto; then \
echo 'pkg-config libcrypto'; \
fi)
endif
ifneq ($(BUILDER),)
ifneq ($(SSL_BUILDER),)
DEFS += $(shell $(SSL_BUILDER) --cflags)
LIBS += $(shell $(SSL_BUILDER) --libs)
endif
ifneq ($(CRYPTO_BUILDER),)
DEFS += $(shell $(CRYPTO_BUILDER) --cflags)
LIBS += $(shell $(CRYPTO_BUILDER) --libs)
endif
else
DEFS += -I$(LOCALBASE)/ssl/include
LIBS += -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib \

@ -98,7 +98,7 @@
<section>
<title>External Libraries or Applications</title>
<para>
The following libraries or applications must be installed before
The following libraries or applications must be installed before
running &kamailio; with this module loaded:
<itemizedlist>
<listitem>
@ -113,7 +113,7 @@
<section>
<title>Parameters</title>
<section>
<section id="path.p.use_received">
<title><varname>use_received</varname> (int)</title>
<para>
If set to 1, the <quote>received</quote> parameter of the first Route &uri; is evaluated and
@ -137,12 +137,12 @@ modparam("path", "use_received", 1)
<section>
<title>Functions</title>
<section>
<section id="path.f.add_path">
<title>
<function moreinfo="none">add_path()</function>
</title>
<para>
This function is used to insert a Path header in the form
This function is used to insert a Path header in the form
<quote>Path: &lt;sip:1.2.3.4;lr&gt;</quote>, where <quote>1.2.3.4</quote> is the address
of the outgoing interface.
</para>
@ -170,12 +170,12 @@ if (!add_path()) {
</example>
</section>
<section>
<section id="path.f.add_path_u">
<title>
<function moreinfo="none">add_path(user)</function>
</title>
<para>
This function adds a Path header in the form
This function adds a Path header in the form
<quote>Path: &lt;sip:user@1.2.3.4;lr&gt;</quote>.
</para>
<para>Meaning of the parameters is as follows:</para>
@ -203,12 +203,12 @@ if (!add_path("loadbalancer")) {
</example>
</section>
<section>
<section id="path.f.add_path_up">
<title>
<function moreinfo="none">add_path(user, parameters)</function>
</title>
<para>
This function adds a Path header in the form
This function adds a Path header in the form
<quote>Path: &lt;sip:user@1.2.3.4;lr&gt;</quote> and appends the
given <emphasis>parameters</emphasis> as additional URI parameters.
</para>
@ -245,13 +245,13 @@ if (!add_path("loadbalancer", "ob")) {
</example>
</section>
<section>
<section id="path.f.add_path_rcv">
<title>
<function moreinfo="none">add_path_received()</function>
</title>
<para>
This function adds a Path header in the form
<quote>Path: &lt;sip:1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting its own
This function adds a Path header in the form
<quote>Path: &lt;sip:1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting its own
outgoing address as domain-part, and the address the request has been received from as
received-parameter.
</para>
@ -271,14 +271,14 @@ if (!add_path_received()) {
</example>
</section>
<section>
<section id="path.f.add_path_rcv_u">
<title>
<function moreinfo="none">add_path_received(user)</function>
</title>
<para>
This function adds a Path header in the form
This function adds a Path header in the form
<quote>Path: &lt;sip:user@1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting
'user' as username part of address, its own
'user' as username part of address, its own
outgoing address as domain-part, and the address the request has been received from as
received-parameter.
</para>
@ -298,14 +298,14 @@ if (!add_path_received("inbound")) {
</example>
</section>
<section>
<section id="path.f.add_path_rcv_up">
<title>
<function moreinfo="none">add_path_received(user, parameters)</function>
</title>
<para>
This function adds a Path header in the form
This function adds a Path header in the form
<quote>Path: &lt;sip:user@1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting
'user' as username part of address, its own
'user' as username part of address, its own
outgoing address as domain-part, and the address the request has been received from as
received-parameter.
</para>

@ -101,6 +101,7 @@ void destroy_shtable(shtable_t htable, int hash_size)
lock_destroy(&htable[i].lock);
free_subs_list(htable[i].entries->next, SHM_MEM_TYPE, 1);
shm_free(htable[i].entries);
htable[i].entries = NULL;
}
shm_free(htable);
htable= NULL;
@ -318,9 +319,14 @@ int delete_shtable(shtable_t htable,unsigned int hash_code,subs_t* subs)
{
found= s->local_cseq +1;
ps->next= s->next;
if(s->contact.s!=NULL)
if(s->contact.s!=NULL) {
shm_free(s->contact.s);
shm_free(s);
s->contact.s = NULL;
}
if (s) {
shm_free(s);
s = NULL;
}
break;
}
ps= s;
@ -340,15 +346,21 @@ void free_subs_list(subs_t* s_array, int mem_type, int ic)
s_array= s_array->next;
if(mem_type & PKG_MEM_TYPE)
{
if(ic)
if(ic) {
pkg_free(s->contact.s);
s->contact.s = NULL;
}
pkg_free(s);
s = NULL;
}
else
{
if(ic)
if(ic) {
shm_free(s->contact.s);
s->contact.s = NULL;
}
shm_free(s);
s = NULL;
}
}

@ -2126,7 +2126,7 @@ error:
#define EXTRACT_STRING(strng, chars)\
do {\
strng.s = (char *) chars;\
strng.len = strlen(strng.s);\
strng.len = strng.s == NULL ? 0 : strlen(strng.s);\
} while(0);
static int unset_watchers_updated_winfo(str *pres_uri)

@ -268,10 +268,14 @@ xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name)
return NULL;
}
int check_if_dialog(str body, int *is_dialog)
int check_if_dialog(str body, int *is_dialog, char **dialog_id)
{
xmlDocPtr doc;
xmlNodePtr node;
char *tmp_dialog_id;
*dialog_id = NULL;
*is_dialog = 0;
doc = xmlParseMemory(body.s, body.len);
if(doc== NULL)
@ -283,15 +287,260 @@ int check_if_dialog(str body, int *is_dialog)
node = doc->children;
node = xmlNodeGetChildByName(node, "dialog");
if(node == NULL)
*is_dialog = 0;
else
if(node != NULL)
{
*is_dialog = 1;
tmp_dialog_id = (char *)xmlGetProp(node, (xmlChar *)"id");
if (tmp_dialog_id != NULL)
{
*dialog_id = strdup(tmp_dialog_id);
xmlFree(tmp_dialog_id);
}
}
xmlFreeDoc(doc);
return 0;
}
int parse_dialog_state_from_body(str body, int *is_dialog, char **state)
{
xmlDocPtr doc;
xmlNodePtr node;
xmlNodePtr childNode;
char *tmp_state;
*state = NULL;
*is_dialog = 0;
doc = xmlParseMemory(body.s, body.len);
if(doc== NULL)
{
LM_ERR("failed to parse xml document\n");
return -1;
}
node = doc->children;
node = xmlNodeGetChildByName(node, "dialog");
if(node != NULL)
{
*is_dialog = 1;
childNode = xmlNodeGetChildByName(node, "state");
tmp_state = (char *)xmlNodeGetContent(childNode);
if (tmp_state != NULL)
{
*state = strdup(tmp_state);
xmlFree(tmp_state);
}
}
xmlFreeDoc(doc);
return 0;
}
int delete_presentity_if_dialog_id_exists(presentity_t* presentity, char* dialog_id) {
db_key_t query_cols[13], result_cols[6];
db_op_t query_ops[13];
db_val_t query_vals[13];
int n_query_cols = 0;
int rez_body_col = 0, rez_etag_col = 0, n_result_cols= 0;
db1_res_t *result = NULL;
db_row_t *row = NULL;
db_val_t *row_vals = NULL;
char* db_dialog_id = NULL;
int db_is_dialog = 0;
str tmp_db_body, tmp_db_etag;
int i = 0;
presentity_t old_presentity;
query_cols[n_query_cols] = &str_domain_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->domain;
n_query_cols++;
query_cols[n_query_cols] = &str_username_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->user;
n_query_cols++;
query_cols[n_query_cols] = &str_event_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->event->name;
n_query_cols++;
result_cols[rez_body_col=n_result_cols++] = &str_body_col;
result_cols[rez_etag_col=n_result_cols++] = &str_etag_col;
if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
{
LM_ERR("unsuccessful sql use table\n");
return -1;
}
if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals,
result_cols, n_query_cols, n_result_cols, 0, &result) < 0)
{
LM_ERR("unsuccessful sql query\n");
return -2;
}
if(result == NULL)
return -3;
// No results from query definitely means no dialog exists
if (result->n <= 0)
return 0;
// Loop the rows returned from the DB
for (i=0; i < result->n; i++)
{
row = &result->rows[i];
row_vals = ROW_VALUES(row);
tmp_db_body.s = (char*)row_vals[rez_body_col].val.string_val;
tmp_db_body.len = strlen(tmp_db_body.s);
tmp_db_etag.s = (char*)row_vals[rez_etag_col].val.string_val;
tmp_db_etag.len = strlen(tmp_db_etag.s);
if (check_if_dialog(tmp_db_body, &db_is_dialog, &db_dialog_id) == 0)
{
// If ID from DB matches the one we supplied
if (db_dialog_id && !strcmp(db_dialog_id, dialog_id))
{
old_presentity.domain = presentity->domain;
old_presentity.user = presentity->user;
old_presentity.event = presentity->event;
old_presentity.etag = tmp_db_etag;
LM_WARN("Presentity already exists - deleting it\n");
delete_presentity(&old_presentity);
pa_dbf.free_result(pa_db, result);
result = NULL;
free(db_dialog_id);
return 1;
}
free(db_dialog_id);
}
}
pa_dbf.free_result(pa_db, result);
result = NULL;
return 0;
}
int get_dialog_state(presentity_t* presentity, char** state)
{
db_key_t query_cols[13], result_cols[6];
db_op_t query_ops[13];
db_val_t query_vals[13];
int n_query_cols = 0;
int rez_body_col = 0, n_result_cols= 0;
db1_res_t *result = NULL;
db_row_t *row = NULL;
db_val_t *row_vals = NULL;
int db_is_dialog = 0;
str tmp_db_body;
int i = 0, parse_state_result = 0;
*state = NULL;
query_cols[n_query_cols] = &str_domain_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->domain;
n_query_cols++;
query_cols[n_query_cols] = &str_username_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->user;
n_query_cols++;
query_cols[n_query_cols] = &str_event_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->event->name;
n_query_cols++;
query_cols[n_query_cols] = &str_etag_col;
query_ops[n_query_cols] = OP_EQ;
query_vals[n_query_cols].type = DB1_STR;
query_vals[n_query_cols].nul = 0;
query_vals[n_query_cols].val.str_val = presentity->etag;
n_query_cols++;
result_cols[rez_body_col=n_result_cols++] = &str_body_col;
if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
{
LM_ERR("unsuccessful sql use table\n");
return -1;
}
if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals,
result_cols, n_query_cols, n_result_cols, 0, &result) < 0)
{
LM_ERR("unsuccessful sql query\n");
return -2;
}
if(result == NULL)
return -3;
// No results from query definitely means no dialog exists
if (result->n <= 0)
return 0;
// Loop the rows returned from the DB
for (i=0; i < result->n; i++)
{
row = &result->rows[i];
row_vals = ROW_VALUES(row);
tmp_db_body.s = (char*)row_vals[rez_body_col].val.string_val;
tmp_db_body.len = strlen(tmp_db_body.s);
parse_state_result = parse_dialog_state_from_body(tmp_db_body, &db_is_dialog, state);
pa_dbf.free_result(pa_db, result);
result = NULL;
return parse_state_result;
}
pa_dbf.free_result(pa_db, result);
result = NULL;
return 0;
}
int is_dialog_terminated(presentity_t* presentity)
{
char *state = NULL;
int rtn;
get_dialog_state(presentity, &state);
rtn = state && !strcasecmp(state, "terminated");
free(state);
return rtn;
}
int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
int new_t, int* sent_reply, char* sphere)
@ -316,6 +565,7 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
int ret = -1;
int db_record_exists = 0;
int num_watchers = 0;
char *old_dialog_id = NULL, *dialog_id = NULL;
if (sent_reply) *sent_reply= 0;
if(pres_notifier_processes == 0 && presentity->event->req_auth)
@ -435,6 +685,14 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
}
}
check_if_dialog(*body, &is_dialog, &dialog_id);
if (delete_presentity_if_dialog_id_exists(presentity, dialog_id) < 0) {
goto error;
}
free(dialog_id);
LM_DBG("inserting %d cols into table\n",n_query_cols);
if (pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0)
@ -529,16 +787,20 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
old_body.s = (char*)row_vals[rez_body_col].val.string_val;
old_body.len = strlen(old_body.s);
if(check_if_dialog(*body, &is_dialog)< 0)
if(check_if_dialog(*body, &is_dialog, &dialog_id)< 0)
{
LM_ERR("failed to check if dialog stored\n");
goto error;
}
if(is_dialog== 1) /* if the new body has a dialog - overwrite */
free(dialog_id);
if(is_dialog== 1) /* if the new body has a dialog - overwrite */
{
goto after_dialog_check;
}
if(check_if_dialog(old_body, &is_dialog)< 0)
if(check_if_dialog(old_body, &is_dialog, &old_dialog_id)< 0)
{
LM_ERR("failed to check if dialog stored\n");
goto error;
@ -547,6 +809,8 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
if(is_dialog==0 ) /* if the old body has no dialog - overwrite */
goto after_dialog_check;
free(old_dialog_id);
sender.s = (char*)row_vals[rez_sender_col].val.string_val;
sender.len= strlen(sender.s);
@ -702,6 +966,25 @@ after_dialog_check:
else
cur_etag= presentity->etag;
if (is_dialog_terminated(presentity))
{
LM_WARN("Trying to update an already terminated state. Skipping update.\n");
/* send 200OK */
if (publ_send200ok(msg, presentity->expires, cur_etag)< 0)
{
LM_ERR("sending 200OK reply\n");
goto error;
}
if (sent_reply) *sent_reply= 1;
if(etag.s)
pkg_free(etag.s);
etag.s= NULL;
goto done;
}
update_keys[n_update_cols] = &str_expires_col;
update_vals[n_update_cols].type = DB1_INT;
update_vals[n_update_cols].nul = 0;

@ -52,6 +52,7 @@
static str str_udp = { "UDP", 3 };
static str str_5060 = { "5060", 4 };
static str str_5061 = { "5061", 4 };
static str pv_str_1 = { "1", 1 };
static str pv_uri_scheme[] = {
{ "none", 4 },
@ -96,6 +97,11 @@ int pv_get_5060(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
return pv_get_strintval(msg, param, res, &str_5060, 5060);
}
int pv_get_5061(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
return pv_get_strintval(msg, param, res, &str_5061, 5061);
}
int pv_get_true(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
@ -278,8 +284,13 @@ int pv_get_xuri_attr(struct sip_msg *msg, struct sip_uri *parsed_uri,
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &parsed_uri->host);
} else if(param->pvn.u.isname.name.n==3) /* port */ {
if(parsed_uri->port.s==NULL)
return pv_get_5060(msg, param, res);
if(parsed_uri->port.s==NULL) {
if(parsed_uri->proto==PROTO_TLS) {
return pv_get_5061(msg, param, res);
} else {
return pv_get_5060(msg, param, res);
}
}
return pv_get_strintval(msg, param, res, &parsed_uri->port,
(int)parsed_uri->port_no);
} else if(param->pvn.u.isname.name.n==4) /* protocol */ {
@ -1139,8 +1150,13 @@ int pv_get_dsturi_attr(struct sip_msg *msg, pv_param_t *param,
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &uri.host);
} else if(param->pvn.u.isname.name.n==2) /* port */ {
if(uri.port.s==NULL)
return pv_get_5060(msg, param, res);
if(uri.port.s==NULL || uri.port.len<=0) {
if(uri.proto==PROTO_TLS) {
return pv_get_5061(msg, param, res);
} else {
return pv_get_5060(msg, param, res);
}
}
return pv_get_strintval(msg, param, res, &uri.port, (int)uri.port_no);
} else if(param->pvn.u.isname.name.n==3) /* proto */ {
if(uri.transport_val.s==NULL)

@ -506,8 +506,10 @@ int pv_parse_xavp_name(pv_spec_p sp, str *in)
return -1;
xname = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
if(xname==NULL)
if(xname==NULL) {
LM_ERR("not enough pkg mem\n");
return -1;
}
memset(xname, 0, sizeof(pv_xavp_name_t));
@ -530,9 +532,10 @@ int pv_parse_xavp_name(pv_spec_p sp, str *in)
xname->name.s, s.len, s.s);
xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
if(xname->next==NULL)
if(xname->next==NULL) {
LM_ERR("not enough pkg mem\n");
goto error;
}
memset(xname->next, 0, sizeof(pv_xavp_name_t));
p = pv_xavp_fill_ni(&s, xname->next);

@ -150,12 +150,14 @@ int check_contacts(struct sip_msg* _m, int* _s)
/* The first Contact HF is star */
/* Expires must be zero */
if (get_expires_hf(_m) != 0) {
LM_WARN("expires must be 0 for star contact\n");
rerrno = R_STAR_EXP;
return 1;
}
/* Message must contain no contacts */
if (((contact_body_t*)_m->contact->parsed)->contacts) {
LM_WARN("star contact cannot be mixed with other contacts\n");
rerrno = R_STAR_CONT;
return 1;
}
@ -164,6 +166,7 @@ int check_contacts(struct sip_msg* _m, int* _s)
p = _m->contact->next;
while(p) {
if (p->type == HDR_CONTACT_T) {
LM_WARN("star contact cannot be mixed with other contacts\n");
rerrno = R_STAR_CONT;
return 1;
}
@ -172,18 +175,24 @@ int check_contacts(struct sip_msg* _m, int* _s)
*_s = 1;
} else { /* The first Contact HF is not star */
/* Message must contain no star Contact HF */
p = _m->contact->next;
p = _m->contact;
while(p) {
if (p->type == HDR_CONTACT_T) {
/* Message must contain no star Contact HF */
if (((contact_body_t*)p->parsed)->star == 1) {
LM_WARN("star contact cannot be mixed with other contacts\n");
rerrno = R_STAR_CONT;
return 1;
}
/* check also the lenght of all contacts */
/* check also the length of all contacts */
for(c=((contact_body_t*)p->parsed)->contacts ; c ; c=c->next) {
if (c->uri.len > CONTACT_MAX_SIZE
|| (c->received && c->received->len>RECEIVED_MAX_SIZE) ) {
if (c->uri.len > CONTACT_MAX_SIZE) {
LM_WARN("contact uri is too long: [%.*s]\n", c->uri.len, c->uri.s);
rerrno = R_CONTACT_LEN;
return 1;
}
if (c->received && c->received->len>RECEIVED_MAX_SIZE) {
LM_WARN("received attribute of contact is too long\n");
rerrno = R_CONTACT_LEN;
return 1;
}

@ -43,7 +43,7 @@
#include "rr_mod.h"
#define RR_ERROR -1 /*!< An error occured while processing route set */
#define RR_ERROR -1 /*!< An error occurred while processing route set */
#define RR_DRIVEN 1 /*!< The next hop is determined from the route set */
#define RR_OB_DRIVEN 2 /*!< The next hop is determined from the route set based on flow-token */
#define NOT_RR_DRIVEN -1 /*!< The next hop is not determined from the route set */
@ -762,6 +762,7 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
struct socket_info *si;
int uri_is_myself;
int use_ob = 0;
str rparams;
hdr = _m->route;
rt = (rr_t*)hdr->parsed;
@ -855,7 +856,7 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
rt = (rr_t*)hdr->parsed;
} else rt = rt->next;
}
uri = rt->nameaddr.uri;
if (parse_uri(uri.s, uri.len, &puri) < 0) {
LM_ERR("failed to parse the next route URI (%.*s)\n",
@ -889,7 +890,7 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
LM_ERR("checking maddr failed\n");
return RR_ERROR;
}
if (set_dst_uri(_m, &uri) < 0) {
LM_ERR("failed to set dst_uri\n");
return RR_ERROR;
@ -902,7 +903,7 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
/* There is a previous route uri which was 2nd uri of mine
* and must be removed here */
if (rt != hdr->parsed) {
if (!del_lump(_m, hdr->body.s - _m->buf,
if (!del_lump(_m, hdr->body.s - _m->buf,
rt->nameaddr.name.s - hdr->body.s, 0)) {
LM_ERR("failed to remove Route HF\n");
return RR_ERROR;
@ -915,8 +916,10 @@ done:
status = RR_OB_DRIVEN;
/* run RR callbacks only if we have Route URI parameters */
if(routed_params.len > 0)
run_rr_callbacks( _m, &routed_params );
if(routed_params.len > 0) {
rparams = routed_params;
run_rr_callbacks( _m, &rparams );
}
return status;
}
@ -934,7 +937,7 @@ int loose_route(struct sip_msg* _m)
LM_DBG("There is no Route HF\n");
return -1;
}
if (parse_sip_msg_uri(_m)<0) {
LM_ERR("failed to parse Request URI\n");
return -1;
@ -954,6 +957,70 @@ int loose_route(struct sip_msg* _m)
}
}
/**
*
*/
int redo_route_params(sip_msg_t *msg)
{
hdr_field_t *hdr;
sip_uri_t puri;
rr_t* rt;
str uri;
int uri_is_myself;
int redo = 0;
if(msg->first_line.type != SIP_REQUEST) {
return -1;
}
if(msg->route==NULL || msg->route->parsed==NULL) {
return -1;
}
/* check if the hooked params belong to the same message */
if (routed_msg_id != msg->id || routed_msg_pid != msg->pid) {
redo = 1;
}
if((redo==0) && (routed_params.s==NULL || routed_params.len<=0)) {
redo = 1;
}
if((redo==0) && (routed_params.s<msg->buf
|| routed_params.s>msg->buf+msg->len)) {
redo = 1;
}
if(redo==1) {
hdr = msg->route;
rt = (rr_t*)hdr->parsed;
uri = rt->nameaddr.uri;
/* reset rr handling static vars for safety in error case */
routed_msg_id = 0;
routed_msg_pid = 0;
if (parse_uri(uri.s, uri.len, &puri) < 0) {
LM_ERR("failed to parse the first route URI (%.*s)\n",
uri.len, ZSW(uri.s));
return -1;
}
uri_is_myself = is_myself(&puri);
/* if the URI was added by me, remove it */
if (uri_is_myself>0) {
LM_DBG("Topmost route URI: '%.*s' is me\n",
uri.len, ZSW(uri.s));
/* set the hooks for the params */
routed_msg_id = msg->id;
routed_msg_pid = msg->pid;
routed_params = puri.params;
return 0;
} else {
return -1;
}
}
return 0;
}
/*!
* \brief Check if the route hdr has the required parameter
@ -967,22 +1034,31 @@ int loose_route(struct sip_msg* _m)
* \param re compiled regular expression to be checked against the Route header parameters
* \return -1 on failure, 1 on success
*/
int check_route_param(struct sip_msg * msg, regex_t* re)
int check_route_param(sip_msg_t * msg, regex_t* re)
{
regmatch_t pmatch;
char bk;
str params;
str rruri;
/* check if the hooked params belong to the same message */
if (routed_msg_id != msg->id || routed_msg_pid != msg->pid)
if(redo_route_params(msg)<0) {
return -1;
}
/* check if params are present */
if ( !routed_params.s || !routed_params.len )
if ( !routed_params.s || routed_params.len<=0 ) {
return -1;
}
rruri = ((rr_t*)(msg->route->parsed))->nameaddr.uri;
/* include also the first ';' */
for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ );
for( params=routed_params ;
params.s>rruri.s && params.s[0]!=';' ;
params.s--,params.len++ );
LM_DBG("route params checking against [%.*s] (orig: [%.*s])\n",
params.len, params.s, routed_params.len, routed_params.s);
/* do the well-known trick to convert to null terminted */
bk = params.s[params.len];
@ -1011,7 +1087,7 @@ int check_route_param(struct sip_msg * msg, regex_t* re)
* It might be an empty string if the parameter had no value.
* \return 0 if parameter was found (even if it has no value), -1 otherwise
*/
int get_route_param( struct sip_msg *msg, str *name, str *val)
int get_route_param(sip_msg_t *msg, str *name, str *val)
{
char *p;
char *end;
@ -1019,11 +1095,12 @@ int get_route_param( struct sip_msg *msg, str *name, str *val)
int quoted;
/* check if the hooked params belong to the same message */
if (routed_msg_id != msg->id)
if(redo_route_params(msg)<0) {
goto notfound;
}
/* check if params are present */
if ( !routed_params.s || !routed_params.len )
if ( !routed_params.s || routed_params.len<=0 )
goto notfound;
end = routed_params.s + routed_params.len;

@ -224,8 +224,12 @@ int stm_t_param(modparam_t type, void *val)
tmp.name = pit->body;
} else if(pit->name.len==4
&& strncasecmp(pit->name.s, "mode", 4)==0) {
if(tmp.mode==0)
str2int(&pit->body, &tmp.mode);
if(tmp.mode==0) {
if (str2int(&pit->body, &tmp.mode) < 0) {
LM_ERR("invalid mode: %.*s\n", pit->body.len, pit->body.s);
return -1;
}
}
} else if(pit->name.len==8
&& strncasecmp(pit->name.s, "interval", 8)==0) {
if(pit->body.s[pit->body.len-1]=='u'
@ -234,7 +238,10 @@ int stm_t_param(modparam_t type, void *val)
tmp.flags |= RTIMER_INTERVAL_USEC;
tmp.mode = 1;
}
str2int(&pit->body, &tmp.interval);
if (str2int(&pit->body, &tmp.interval) < 0) {
LM_ERR("invalid interval: %.*s\n", pit->body.len, pit->body.s);
return -1;
}
}
}
if(tmp.name.s==NULL)

@ -1809,6 +1809,7 @@ static int build_rtpp_socks(unsigned int current_rtpp_no) {
for (i = 0; i < rtpp_socks_size; i++) {
if (rtpp_socks[i] >= 0) {
close(rtpp_socks[i]);
rtpp_socks[i] = -1;
}
}
@ -1818,6 +1819,7 @@ static int build_rtpp_socks(unsigned int current_rtpp_no) {
LM_ERR("no more pkg memory for rtpp_socks\n");
return -1;
}
memset(rtpp_socks, -1, sizeof(int)*(rtpp_socks_size));
lock_get(rtpp_set_list->rset_head_lock);
for (rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
@ -1911,6 +1913,11 @@ child_init(int rank)
if(!rtpp_set_list)
return 0;
/* do not init sockets for PROC_INIT and main process when fork=yes */
if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
return 0;
}
mypid = getpid();
lock_get(rtpp_no_lock);
@ -1921,6 +1928,7 @@ child_init(int rank)
if (!rtpp_socks) {
return -1;
}
memset(rtpp_socks, -1, sizeof(int)*(rtpp_socks_size));
// vector of pointers to queried nodes
queried_nodes_ptr = (struct rtpp_node**)pkg_malloc(queried_nodes_limit * sizeof(struct rtpp_node*));

@ -1007,6 +1007,11 @@ child_init(int rank)
if(rtpp_set_list==NULL )
return 0;
/* do not init sockets for PROC_INIT and main process when fork=yes */
if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
return 0;
}
/* Iterate known RTP proxies - create sockets */
mypid = getpid();
@ -1015,6 +1020,7 @@ child_init(int rank)
LM_ERR("no more pkg memory\n");
return -1;
}
memset(rtpp_socks, -1, sizeof(int)*rtpp_no);
for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
rtpp_list = rtpp_list->rset_next){

@ -182,6 +182,8 @@ int sl_reply_helper(struct sip_msg *msg, int code, char *reason, str *tag)
sl_run_callbacks(SLCB_REPLY_READY, msg, code, reason, &buf, &dst);
*(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME;
/* supress multhoming support when sending a reply back -- that makes sure
that replies will come from where requests came in; good for NATs
(there is no known use for mhomed for locally generated replies;
@ -286,8 +288,6 @@ event_route_error:
if (ret<0) {
goto error;
}
*(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME;
update_sl_stats(code);
return 1;

@ -31,6 +31,10 @@ Olle E. Johansson
3.5. tcp_set_connection_lifetime([conid], lifetime)
3.6. tcp_enable_closed_event([conid])
4. Event routes
4.1. tcp:closed
List of Examples
1.1. Set closed_event parameter
@ -59,6 +63,10 @@ Chapter 1. Admin Guide
3.5. tcp_set_connection_lifetime([conid], lifetime)
3.6. tcp_enable_closed_event([conid])
4. Event routes
4.1. tcp:closed
1. Overview
This modules allows Kamailio to control the TCP connection options
@ -277,3 +285,22 @@ request_route {
event_route[tcp:closed] {
xlog("connection $conid was closed");
}
4. Event routes
4.1. tcp:closed
4.1. tcp:closed
This route is called when a socket is closed by the remote party, or
reset, or timeout. The corresponding $conid variable will be available
in the event route.
Whether this route is always called, never, or on a per socket basis is
controlled by the closed_event parameter.
...
event_route[tcp:closed] {
xlog("L_INFO", "TCP connection closed ($conid)\n");
}
...

@ -0,0 +1,35 @@
<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!-- Include general documentation entities -->
<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
%docentities;
]>
<section id="tcpops.ex.event_routes">
<title>Event routes</title>
<section>
<title>
<function moreinfo="none">tcp:closed</function>
</title>
<para>
This route is called when a socket is closed by the remote party,
or reset, or timeout. The corresponding <emphasis>$conid</emphasis>
variable will be available in the event route.
</para>
<para>
Whether this route is always called, never, or on a per socket basis
is controlled by the <emphasis>closed_event</emphasis> parameter.
</para>
<para>
<programlisting format="linespecific">
...
event_route[tcp:closed] {
xlog("L_INFO", "TCP connection closed ($conid)\n");
}
...
</programlisting>
</para>
</section>
</section>

@ -51,6 +51,7 @@
<xi:include href="params.xml"/>
<xi:include href="functions.xml"/>
<xi:include href="eventroutes.xml"/>
</chapter>
</book>

@ -999,11 +999,19 @@ if (starts_with("$rU", "+358"))
The core will take care of the last boundary ending "--". Detecting
wich one is the last and fixing the others if needed.
Note: it may be required that msg_apply_changes() from textops module
has to be executed if there are other operations over the new body.
Example 1.37. set_body_multipart usage
...
set_body_multipart("test", "text/plain", "delimiter");
msg_apply_changes();
append_body_part(...);
...
Will produce:
# Will produce:
...
Content-Type: multipart/mixed;boundary="delimiter"
Mime-Version: 1.0
@ -1040,7 +1048,9 @@ $var(b) = "7e Od 04 55 75 69 20 4d 61 6b 65 43 61 6c 6c"
append_body_part("$var(b)", "application/vnd.cirpack.isdn-ext", "signal;handling
=required");
...
Will append this the body:
# Will append this to the body:
...
Content-Type: application/vnd.cirpack.isdn-ext
Content-Disposition: signal;handling=required

@ -1391,13 +1391,22 @@ if (starts_with("$rU", "+358"))
The core will take care of the last boundary ending "--". Detecting wich one is
the last and fixing the others if needed.
</para>
<para>
Note: it may be required that msg_apply_changes() from textops module
has to be executed if there are other operations over the new body.
</para>
<example>
<title><function>set_body_multipart</function> usage</title>
<programlisting format="linespecific">
...
set_body_multipart("test", "text/plain", "delimiter");
msg_apply_changes();
append_body_part(...);
...
Will produce:
# Will produce:
...
Content-Type: multipart/mixed;boundary="delimiter"
Mime-Version: 1.0
@ -1452,7 +1461,9 @@ text
$var(b) = "7e Od 04 55 75 69 20 4d 61 6b 65 43 61 6c 6c"
append_body_part("$var(b)", "application/vnd.cirpack.isdn-ext", "signal;handling=required");
...
Will append this the body:
# Will append this to the body:
...
Content-Type: application/vnd.cirpack.isdn-ext
Content-Disposition: signal;handling=required

@ -191,7 +191,11 @@ Chapter 1. Admin Guide
This module implements the TLS transport for Kamailio using the OpenSSL
library (http://www.openssl.org). To enable the Kamailio TLS support
this module must be loaded and enable_tls=yes core setting must be
added to the Kamailio config file
added to the Kamailio config file.
IMPORTANT: tls module must be loaded before any other Kamailio module
that uses libssl (OpenSSL library). A safe option is to have tls module
loaded first (be in the first "loadmodule" inside Kamailio.cfg).
2. Quick Start

@ -2,7 +2,7 @@
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
[ <!ENTITY % local.common.attrib
"xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">
"xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">
<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
%docentities;
@ -48,8 +48,13 @@
This module implements the TLS transport for &kamailio;
using the <ulink url="http://www.openssl.org">OpenSSL library</ulink>
(http://www.openssl.org). To enable the &kamailio; TLS support this
module must be loaded and <emphasis>enable_tls=yes</emphasis> core setting
must be added to the Kamailio config file
module must be loaded and <emphasis>enable_tls=yes</emphasis> core setting
must be added to the Kamailio config file.
</para>
<para>
IMPORTANT: tls module must be loaded before any other &kamailio; module
that uses libssl (OpenSSL library). A safe option is to have tls module
loaded first (be in the first "loadmodule" inside &kamailio;.cfg).
</para>
</section>
<section id="tls.quick_start">

@ -1,4 +1,4 @@
/*
/*
* TLS module
*
* Copyright (C) 2005,2006 iptelorg GmbH
@ -43,7 +43,7 @@
#include <unistd.h>
#include <string.h>
#include <openssl/ssl.h>
#include "../../dprint.h"
#include "../../mem/shm_mem.h"
#include "../../tcp_init.h"
@ -160,7 +160,7 @@ inline static int backtrace2str(char* buf, int size)
char* next;
char* s;
char* e;
p=buf; end=buf+size;
bt_size=backtrace(bt, sizeof(bt)/sizeof(bt[0]));
bt_strs=backtrace_symbols(bt, bt_size);
@ -203,7 +203,7 @@ static void* ser_malloc(size_t size, const char* file, int line)
#ifdef RAND_NULL_MALLOC
static ticks_t st=0;
/* start random null returns only after
/* start random null returns only after
* NULL_GRACE_PERIOD from first call */
if (st==0) st=get_ticks();
if (((get_ticks()-st)<NULL_GRACE_PERIOD) || (random()%RAND_NULL_MALLOC)){
@ -212,7 +212,7 @@ static void* ser_malloc(size_t size, const char* file, int line)
/* ugly hack: keep the bt inside the alloc'ed fragment */
p=_shm_malloc(size+s, file, "via ser_malloc", line);
if (p==0){
LOG(L_CRIT, "tsl: ser_malloc(%d)[%s:%d]==null, bt: %s\n",
LOG(L_CRIT, "tsl: ser_malloc(%d)[%s:%d]==null, bt: %s\n",
size, file, line, bt_buf);
}else{
memcpy(p+size, bt_buf, s);
@ -240,7 +240,7 @@ static void* ser_realloc(void *ptr, size_t size, const char* file, int line)
#ifdef RAND_NULL_MALLOC
static ticks_t st=0;
/* start random null returns only after
/* start random null returns only after
* NULL_GRACE_PERIOD from first call */
if (st==0) st=get_ticks();
if (((get_ticks()-st)<NULL_GRACE_PERIOD) || (random()%RAND_NULL_MALLOC)){
@ -302,20 +302,20 @@ static void ser_free(void *ptr)
int tls_h_init_si(struct socket_info *si)
{
int ret;
/*
* reuse tcp initialization
*/
/*
* reuse tcp initialization
*/
ret = tcp_init(si);
if (ret != 0) {
ERR("Error while initializing TCP part of TLS socket %.*s:%d\n",
si->address_str.len, si->address_str.s, si->port_no);
si->address_str.len, si->address_str.s, si->port_no);
goto error;
}
si->proto = PROTO_TLS;
return 0;
error:
error:
if (si->socket != -1) {
close(si->socket);
si->socket = -1;
@ -326,7 +326,7 @@ int tls_h_init_si(struct socket_info *si)
/*
* initialize ssl methods
* initialize ssl methods
*/
static void init_ssl_methods(void)
{
@ -389,11 +389,11 @@ static int init_tls_compression(void)
STACK_OF(SSL_COMP)* comp_methods;
SSL_COMP* zlib_comp;
long ssl_version;
/* disabling compression */
# ifndef SSL_COMP_ZLIB_IDX
# define SSL_COMP_ZLIB_IDX 1 /* openssl/ssl/ssl_ciph.c:84 */
# endif
# endif
comp_methods = SSL_COMP_get_compression_methods();
if (comp_methods == 0) {
LOG(L_INFO, "tls: init_tls: compression support disabled in the"
@ -419,7 +419,7 @@ static int init_tls_compression(void)
DBG("tls: init_tls: found compression method %p id %d\n",
zlib_comp, zlib_comp->id);
if (zlib_comp->id == SSL_COMP_ZLIB_IDX) {
DBG("tls: init_tls: found zlib compression (%d)\n",
DBG("tls: init_tls: found zlib compression (%d)\n",
SSL_COMP_ZLIB_IDX);
break /* found */;
} else {
@ -438,7 +438,7 @@ static int init_tls_compression(void)
"bug workaround (replacing zlib COMP method with "
"our own version)\n");
/* hack: make sure that the CRYPTO_EX_INDEX_COMP class is empty
* and it does not contain any free_ex_data from the
* and it does not contain any free_ex_data from the
* built-in zlib. This can happen if the current openssl
* zlib malloc fix patch is used (CRYPTO_get_ex_new_index() in
* COMP_zlib()). Unfortunately the only way
@ -447,7 +447,7 @@ static int init_tls_compression(void)
* (only the COMP class is initialized before).
*/
CRYPTO_cleanup_all_ex_data();
if (fixed_c_zlib_init() != 0) {
LOG(L_CRIT, "tls: init_tls: BUG: failed to initialize zlib"
" compression fix, disabling compression...\n");
@ -478,16 +478,23 @@ end:
*/
int tls_pre_init(void)
{
/*
* this has to be called before any function calling CRYPTO_malloc,
* CRYPTO_malloc will set allow_customize in openssl to 0
*/
void *(*mf)(size_t) = NULL;
void *(*rf)(void *, size_t) = NULL;
void (*ff)(void *) = NULL;
/*
* this has to be called before any function calling CRYPTO_malloc,
* CRYPTO_malloc will set allow_customize in openssl to 0
*/
#ifdef TLS_MALLOC_DBG
if (!CRYPTO_set_mem_ex_functions(ser_malloc, ser_realloc, ser_free)) {
#else
if (!CRYPTO_set_mem_functions(ser_malloc, ser_realloc, ser_free)) {
#endif
ERR("Unable to set the memory allocation functions\n");
CRYPTO_get_mem_functions(&mf, &rf, &ff);
ERR("libssl current mem functions - m: %p r: %p f: %p\n", mf, rf, ff);
ERR("Be sure tls module is loaded before any other module using libssl"
" (can be loaded first to be safe)\n");
return -1;
}
@ -509,7 +516,7 @@ int tls_mod_pre_init_h(void)
LM_DBG("already mod pre-initialized\n");
return 0;
}
DBG("============= :preparing tls env for modules initialization\n");
DBG("preparing tls env for modules initialization\n");
SSL_library_init();
SSL_load_error_strings();
tls_mod_preinitialized=1;
@ -578,7 +585,7 @@ int init_tls_h(void)
lib_cflags=SSLeay_version(SSLEAY_CFLAGS);
lib_kerberos=0;
lib_zlib=0;
if ((lib_cflags==0) || strstr(lib_cflags, "not available")){
if ((lib_cflags==0) || strstr(lib_cflags, "not available")){
lib_kerberos=-1;
lib_zlib=-1;
}else{
@ -587,7 +594,7 @@ int init_tls_h(void)
if (strstr(lib_cflags, "-DKRB5_"))
lib_kerberos=1;
}
LOG(L_INFO, "tls: _init_tls_h: compiled with openssl version "
LOG(L_INFO, "tls: _init_tls_h: compiled with openssl version "
"\"%s\" (0x%08lx), kerberos support: %s, compression: %s\n",
OPENSSL_VERSION_TEXT, (long)OPENSSL_VERSION_NUMBER,
kerberos_support?"on":"off", comp_support?"on":"off");
@ -625,7 +632,7 @@ int init_tls_h(void)
/* if openssl compiled with kerberos support, and openssl < 0.9.8e-dev
* or openssl between 0.9.9-dev and 0.9.9-beta1 apply workaround for
* openssl bug #1467 */
if (ssl_version < 0x00908050L ||
if (ssl_version < 0x00908050L ||
(ssl_version >= 0x00909000L && ssl_version < 0x00909001L)){
openssl_kssl_malloc_bug=1;
LOG(L_WARN, "tls: init_tls_h: openssl kerberos malloc bug detected, "
@ -653,7 +660,7 @@ int init_tls_h(void)
" workaround enabled (on low memory tls operations will fail"
" preemptively) with free memory thresholds %d and %d bytes\n",
low_mem_threshold1, low_mem_threshold2);
if (shm_available()==(unsigned long)(-1)){
LOG(L_WARN, "tls: Kamailio is compiled without MALLOC_STATS support:"
" the workaround for low mem. openssl bugs will _not_ "
@ -661,8 +668,9 @@ int init_tls_h(void)
low_mem_threshold1=0;
low_mem_threshold2=0;
}
if ((low_mem_threshold1 != cfg_get(tls, tls_cfg, low_mem_threshold1)) ||
(low_mem_threshold2 != cfg_get(tls, tls_cfg, low_mem_threshold2))) {
if ((low_mem_threshold1 != cfg_get(tls, tls_cfg, low_mem_threshold1))
|| (low_mem_threshold2
!= cfg_get(tls, tls_cfg, low_mem_threshold2))) {
/* ugly hack to set the initial values for the mem tresholds */
if (cfg_register_ctx(&cfg_ctx, 0)) {
ERR("failed to register cfg context\n");
@ -687,7 +695,7 @@ int init_tls_h(void)
return -1;
}
}
init_ssl_methods();
tls_mod_initialized = 1;
return 0;

@ -145,6 +145,10 @@ int tls_init_locks()
n_static_locks=0;
}
if (n_static_locks){
if (CRYPTO_get_locking_callback()!=NULL) {
LM_CRIT("ssl locking callback already set\n");
return -1;
}
static_locks=lock_set_alloc(n_static_locks);
if (static_locks==0){
LOG(L_CRIT, "ERROR: tls_init_locking: could not allocate lockset"

@ -1,7 +1,7 @@
/*
* TLS module
*
* Copyright (C) 2007 iptelorg GmbH
* Copyright (C) 2007 iptelorg GmbH
* Copyright (C) Motorola Solutions, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
@ -84,7 +84,7 @@ MODULE_VERSION
str sr_tls_xavp_cfg = {0, 0};
/*
* Default settings when modparams are used
* Default settings when modparams are used
*/
static tls_domain_t mod_params = {
TLS_DOMAIN_DEF | TLS_DOMAIN_SRV, /* Domain Type */
@ -193,11 +193,11 @@ static param_export_t params[] = {
{"session_id", PARAM_STR, &default_tls_cfg.session_id },
{"config", PARAM_STR, &default_tls_cfg.config_file },
{"tls_disable_compression", PARAM_INT,
&default_tls_cfg.disable_compression},
&default_tls_cfg.disable_compression},
{"ssl_release_buffers", PARAM_INT, &default_tls_cfg.ssl_release_buffers},
{"ssl_freelist_max_len", PARAM_INT, &default_tls_cfg.ssl_freelist_max},
{"ssl_max_send_fragment", PARAM_INT,
&default_tls_cfg.ssl_max_send_fragment},
&default_tls_cfg.ssl_max_send_fragment},
{"ssl_read_ahead", PARAM_INT, &default_tls_cfg.ssl_read_ahead},
{"send_close_notify", PARAM_INT, &default_tls_cfg.send_close_notify},
{"con_ct_wq_max", PARAM_INT, &default_tls_cfg.con_ct_wq_max},
@ -253,11 +253,11 @@ static struct tls_hooks tls_h = {
static tls_domains_cfg_t* tls_use_modparams(void)
{
tls_domains_cfg_t* ret;
ret = tls_new_cfg();
if (!ret) return;
}
#endif
@ -333,8 +333,8 @@ static int mod_init(void)
goto error;
}
/* if (init_tls() < 0) return -1; */
/* if (init_tls() < 0) return -1; */
tls_domains_cfg_lock = lock_alloc();
if (tls_domains_cfg_lock == 0) {
ERR("Unable to create TLS configuration lock\n");
@ -350,7 +350,7 @@ static int mod_init(void)
goto error;
}
if (cfg_get(tls, tls_cfg, config_file).s) {
*tls_domains_cfg =
*tls_domains_cfg =
tls_load_config(&cfg_get(tls, tls_cfg, config_file));
if (!(*tls_domains_cfg)) goto error;
} else {
@ -379,7 +379,7 @@ static int mod_child(int rank)
{
if (tls_disable || (tls_domains_cfg==0))
return 0;
/* fix tls config only from the main proc/PROC_INIT., when we know
/* fix tls config only from the main proc/PROC_INIT., when we know
* the exact process number and before any other process starts*/
if (rank == PROC_INIT){
if (cfg_get(tls, tls_cfg, config_file).s){
@ -399,7 +399,7 @@ static int mod_child(int rank)
static void destroy(void)
{
/* tls is destroyed via the registered destroy_tls_h callback
=> nothing to do here */
* => nothing to do here */
}

@ -127,7 +127,9 @@ int t_append_branches(void) {
found = 0;
for (i=0; i<outgoings; i++) {
if (t->uac[i].ruid.len == ruid.len
&& !memcmp(t->uac[i].ruid.s, ruid.s, ruid.len)) {
&& !memcmp(t->uac[i].ruid.s, ruid.s, ruid.len)
&& t->uac[i].uri.len == current_uri.len
&& !memcmp(t->uac[i].uri.s, current_uri.s, current_uri.len)) {
LM_DBG("branch already added [%.*s]\n", ruid.len, ruid.s);
found = 1;
break;

@ -1333,6 +1333,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
drop_replies = failure_reply_mode;
replies_dropped = 0;
tm_ctx_set_branch_index(picked_branch);
/* run ON_FAILURE handlers ( route and callbacks) */
if (unlikely(has_tran_tmcbs( Trans, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE)
|| Trans->uac[picked_branch].on_failure )) {

@ -22,6 +22,7 @@
#include "../../action.h"
#include "../../script_cb.h"
#include "../../dset.h"
#include "../../cfg/cfg_struct.h"
#include "config.h"
#include "sip_msg.h"
@ -178,6 +179,8 @@ int t_continue(unsigned int hash_index, unsigned int label,
struct hdr_field *hdr, *prev = 0, *tmp = 0;
int route_type_bk;
cfg_update();
if (t_lookup_ident(&t, hash_index, label) < 0) {
LM_ERR("transaction not found\n");
return -1;

@ -16,8 +16,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -112,11 +112,11 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
enum sip_protos uri_proto;
if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
LOG(L_ERR, "ERROR: uri2proxy: bad_uri: %.*s\n",
uri->len, uri->s );
LOG(L_ERR, "ERROR: uri2proxy: bad_uri: [%.*s]\n",
uri->len, uri->s );
return 0;
}
if (parsed_uri.type==SIPS_URI_T){
if (parsed_uri.proto==PROTO_UDP) {
LOG(L_ERR, "ERROR: uri2proxy: bad transport for sips uri: %d\n",
@ -130,9 +130,9 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
uri_proto=parsed_uri.proto;
#ifdef HONOR_MADDR
if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
p = mk_proxy(&parsed_uri.maddr_val,
parsed_uri.port_no,
get_proto(proto, uri_proto));
p = mk_proxy(&parsed_uri.maddr_val,
parsed_uri.port_no,
get_proto(proto, uri_proto));
if (p == 0) {
LOG(L_ERR, "ERROR: uri2proxy: bad maddr param in URI <%.*s>\n",
uri->len, ZSW(uri->s));
@ -140,15 +140,15 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
}
} else
#endif
p = mk_proxy(&parsed_uri.host,
parsed_uri.port_no,
get_proto(proto, uri_proto));
p = mk_proxy(&parsed_uri.host,
parsed_uri.port_no,
get_proto(proto, uri_proto));
if (p == 0) {
LOG(L_ERR, "ERROR: uri2proxy: bad host name in URI <%.*s>\n",
uri->len, ZSW(uri->s));
uri->len, ZSW(uri->s));
return 0;
}
return p;
}
@ -160,7 +160,7 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
* host - filled with the uri host part
* port - filled with the uri port
* proto - if != PROTO_NONE, this protocol will be forced over the
* uri_proto, otherwise the uri proto will be used
* uri_proto, otherwise the uri proto will be used
* (value/return)
* comp - compression (if used)
* returns 0 on success, < 0 on error
@ -170,13 +170,13 @@ inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
{
struct sip_uri parsed_uri;
enum sip_protos uri_proto;
if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
LOG(L_ERR, "ERROR: get_uri_send_info: bad_uri: %.*s\n",
uri->len, uri->s );
return -1;
}
if (parsed_uri.type==SIPS_URI_T){
if (parsed_uri.proto==PROTO_UDP) {
LOG(L_ERR, "ERROR: get_uri_send_info: bad transport for"
@ -188,7 +188,7 @@ inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
uri_proto=PROTO_WS;
}else
uri_proto=parsed_uri.proto;
*proto= get_proto(*proto, uri_proto);
#ifdef USE_COMP
*comp=parsed_uri.comp;
@ -196,7 +196,7 @@ inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
#ifdef HONOR_MADDR
if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
*host=parsed_uri.maddr_val;
DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len,
DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len,
parsed_uri.maddr_val.s, parsed_uri.port_no);
} else
#endif
@ -210,7 +210,7 @@ inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
/*
* Convert a URI into a dest_info structure.
* Same as uri2dst, but uses directly force_send_socket instead of msg.
* If the uri host resolves to multiple ips and dns_h!=0 the first ip for
* If the uri host resolves to multiple ips and dns_h!=0 the first ip for
* which a send socket is found will be used. If no send_socket are found,
* the first ip is selected.
*
@ -218,8 +218,8 @@ inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
* null. If null or use_dns_failover==0 normal dns lookup will
* be performed (no failover).
* dst - will be filled
* force_send_sock - if 0 dst->send_sock will be set to the default
* (see get_send_socket2())
* force_send_sock - if 0 dst->send_sock will be set to the default
* (see get_send_socket2())
* sflags - send flags
* uri - uri in str form
* proto - if != PROTO_NONE, this protocol will be forced over the
@ -250,11 +250,11 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
#endif
if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
LOG(L_ERR, "ERROR: uri2dst: bad_uri: %.*s\n",
uri->len, uri->s );
LOG(L_ERR, "ERROR: uri2dst: bad_uri: [%.*s]\n",
uri->len, uri->s );
return 0;
}
if (parsed_uri.type==SIPS_URI_T){
if (parsed_uri.proto==PROTO_UDP) {
LOG(L_ERR, "ERROR: uri2dst: bad transport for sips uri: %d\n",
@ -266,7 +266,7 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
uri_proto=PROTO_WS;
}else
uri_proto=parsed_uri.proto;
init_dest_info(dst);
dst->proto= get_proto(proto, uri_proto);
#ifdef USE_COMP
@ -276,7 +276,7 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
#ifdef HONOR_MADDR
if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
host=&parsed_uri.maddr_val;
DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len,
DBG("maddr dst: [%.*s:%d]\n", parsed_uri.maddr_val.len,
parsed_uri.maddr_val.s, parsed_uri.port_no);
} else
#endif
@ -309,7 +309,7 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
return dst; /* found a good one */
}
}while(dns_srv_handle_next(dns_h, err));
ERR("no corresponding socket for \"%.*s\" af %d\n", host->len,
ERR("no corresponding socket for \"%.*s\" af %d\n", host->len,
ZSW(host->s), dst->to.s.sa_family);
/* try to continue */
return dst;
@ -335,7 +335,7 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
/*
* Convert a URI into a dest_info structure
* If the uri host resolves to multiple ips and dns_h!=0 the first ip for
* If the uri host resolves to multiple ips and dns_h!=0 the first ip for
* which a send socket is found will be used. If no send_socket are found,
* the first ip is selected.
*
@ -344,8 +344,8 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
* be performed (no failover).
* dst - will be filled
* msg - sip message used to set dst->send_sock and dst->send_flags,
* if 0 dst->send_sock will be set to the default w/o using
* msg->force_send_socket (see get_send_socket()) and the
* if 0 dst->send_sock will be set to the default w/o using
* msg->force_send_socket (see get_send_socket()) and the
* send_flags will be set to 0.
* uri - uri in str form
* proto - if != PROTO_NONE, this protocol will be forced over the
@ -356,7 +356,7 @@ inline static struct dest_info *uri2dst2(struct dest_info* dst,
#ifdef USE_DNS_FAILOVER
inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
struct dest_info* dst,
struct sip_msg *msg, str *uri,
struct sip_msg *msg, str *uri,
int proto )
{
snd_flags_t sflags;
@ -368,7 +368,7 @@ inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
}
#else
inline static struct dest_info *uri2dst(struct dest_info* dst,
struct sip_msg *msg, str *uri,
struct sip_msg *msg, str *uri,
int proto )
{
snd_flags_t sflags;

@ -396,7 +396,7 @@ int pv_get_tm_branch_idx(struct sip_msg *msg, pv_param_t *param,
return -1;
/* statefull replies have the branch_index set */
if(msg->first_line.type == SIP_REPLY && route_type != CORE_ONREPLY_ROUTE) {
if(msg->first_line.type == SIP_REPLY) {
tcx = _tmx_tmb.tm_ctx_get();
if(tcx != NULL)
idx = tcx->branch_index;

@ -112,6 +112,9 @@ modparam("topos", "db_url", "dbdriver://username:password@dbhost/dbname")
3.2. mask_callid (int)
Note: this functionality is not implemented yet - the parameter is
present in order to be in pair with topoh module.
Whether to replace or not the Call-ID with another unique id generated
by Kamailio.

@ -89,6 +89,11 @@ modparam("topos", "db_url", "&exampledb;")
</section>
<section id="topos.p.mask_callid">
<title><varname>mask_callid</varname> (int)</title>
<para>
Note: this functionality is not implemented yet - the
parameter is present in order to be in pair with topoh
module.
</para>
<para>
Whether to replace or not the Call-ID with another
unique id generated by &kamailio;.

@ -121,7 +121,7 @@ int tps_remove_headers(sip_msg_t *msg, uint32_t hdr)
continue;
l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
if (l==0) {
LM_ERR("no memory\n");
LM_ERR("failed to remove the header\n");
return -1;
}
}
@ -166,7 +166,7 @@ int tps_add_headers(sip_msg_t *msg, str *hname, str *hbody, int hpos)
memcpy(hs.s + hname->len + 2, hbody->s, hbody->len);
/* add end of header if not present */
if(hs.s[hname->len + 2 + hbody->len]!='\n') {
if(hs.s[hname->len + 2 + hbody->len - 1]!='\n') {
hs.s[hname->len + 2 + hbody->len] = '\r';
hs.s[hname->len + 2 + hbody->len+1] = '\n';
hs.len += 2;
@ -296,6 +296,7 @@ int tps_pack_message(sip_msg_t *msg, tps_data_t *ptsd)
int i;
int vlen;
int r2;
int isreq;
if(ptsd->cp==NULL) {
ptsd->cp = ptsd->cbuf;
@ -344,6 +345,7 @@ int tps_pack_message(sip_msg_t *msg, tps_data_t *ptsd)
ptsd->s_rr.len = 0;
i = 0;
r2 = 0;
isreq = (msg->first_line.type==SIP_REQUEST)?1:0;
for(hdr=msg->record_route; hdr; hdr=next_sibling_hdr(hdr)) {
if (parse_rr(hdr) < 0) {
LM_ERR("failed to parse RR\n");
@ -356,67 +358,84 @@ int tps_pack_message(sip_msg_t *msg, tps_data_t *ptsd)
LM_ERR("no more spage to pack rr headers\n");
return -1;
}
if(i>1) {
if(i==2 &&r2==0) {
ptsd->s_rr.len = ptsd->a_rr.len;
if(isreq==1) {
/* sip request - get a+s-side record route */
if(i>1) {
if(i==2 &&r2==0) {
ptsd->s_rr.len = ptsd->a_rr.len;
}
if(i==3 &&r2==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
}
*ptsd->cp = ',';
ptsd->cp++;
ptsd->a_rr.len++;
}
if(i==3 &&r2==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
*ptsd->cp = '<';
if(i==1) {
ptsd->a_rr.s = ptsd->cp;
ptsd->s_rr.s = ptsd->cp;
}
*ptsd->cp = ',';
if(i==2 && r2==0) {
ptsd->a_rr.s = ptsd->cp;
ptsd->a_rr.len = 0;
}
if(i==3 && r2==1) {
ptsd->a_rr.s = ptsd->cp;
ptsd->a_rr.len = 0;
}
ptsd->cp++;
ptsd->a_rr.len++;
}
*ptsd->cp = '<';
if(i==1) {
ptsd->a_rr.s = ptsd->cp;
ptsd->s_rr.s = ptsd->cp;
}
if(i==2 && r2==0) {
ptsd->a_rr.s = ptsd->cp;
ptsd->a_rr.len = 0;
}
if(i==3 && r2==1) {
ptsd->a_rr.s = ptsd->cp;
ptsd->a_rr.len = 0;
}
ptsd->cp++;
ptsd->a_rr.len++;
memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
if(i==1) {
ptsd->bs_contact.s = ptsd->cp;
ptsd->bs_contact.len = rr->nameaddr.uri.len;
if(_strnstr(ptsd->bs_contact.s, ";r2=on",
ptsd->bs_contact.len)==0) {
LM_DBG("single record routing by proxy\n");
ptsd->as_contact.s = ptsd->cp;
ptsd->as_contact.len = rr->nameaddr.uri.len;
memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
if(i==1) {
ptsd->bs_contact.s = ptsd->cp;
ptsd->bs_contact.len = rr->nameaddr.uri.len;
if(_strnstr(ptsd->bs_contact.s, ";r2=on",
ptsd->bs_contact.len)==0) {
LM_DBG("single record routing by proxy\n");
ptsd->as_contact.s = ptsd->cp;
ptsd->as_contact.len = rr->nameaddr.uri.len;
} else {
r2 = 1;
}
} else {
r2 = 1;
if(i==2 && ptsd->as_contact.len==0) {
LM_DBG("double record routing by proxy\n");
ptsd->as_contact.s = ptsd->cp;
ptsd->as_contact.len = rr->nameaddr.uri.len;
}
}
ptsd->a_rr.len += rr->nameaddr.uri.len;
ptsd->cp += rr->nameaddr.uri.len;
*ptsd->cp = '>';
ptsd->cp++;
ptsd->a_rr.len++;
} else {
if(i==2 && ptsd->as_contact.len==0) {
LM_DBG("double record routing by proxy\n");
ptsd->as_contact.s = ptsd->cp;
ptsd->as_contact.len = rr->nameaddr.uri.len;
}
/* sip response - get b-side record route */
*ptsd->cp = '<';
ptsd->b_rr.s = ptsd->cp;
ptsd->cp++;
ptsd->b_rr.len++;
memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
ptsd->cp += rr->nameaddr.uri.len;
ptsd->b_rr.len += rr->nameaddr.uri.len;
*ptsd->cp = '>';
ptsd->cp++;
ptsd->b_rr.len++;
}
ptsd->a_rr.len += rr->nameaddr.uri.len;
ptsd->cp += rr->nameaddr.uri.len;
*ptsd->cp = '>';
ptsd->cp++;
ptsd->a_rr.len++;
}
}
if(i==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
ptsd->a_rr.len = 0;
}
if(i==2 && r2==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
ptsd->a_rr.len = 0;
if(isreq==1) {
if(i==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
ptsd->a_rr.len = 0;
}
if(i==2 && r2==1) {
ptsd->s_rr.len = ptsd->a_rr.len;
ptsd->a_rr.len = 0;
}
}
LM_DBG("compacted headers - a_rr: [%.*s](%d) - b_rr: [%.*s](%d)"
" - s_rr: [%.*s](%d)\n",
@ -618,7 +637,7 @@ int tps_reappend_route(sip_msg_t *msg, tps_data_t *ptsd, str *hbody, int rev)
int c;
str sb;
if(hbody==NULL || hbody->s==NULL || hbody->len<=0)
if(hbody==NULL || hbody->s==NULL || hbody->len<=0 || hbody->s[0]=='\0')
return 0;
if(rev==1) {
@ -629,6 +648,7 @@ int tps_reappend_route(sip_msg_t *msg, tps_data_t *ptsd, str *hbody, int rev)
c = 1;
if(sb.len>0) {
sb.s = hbody->s + i + 1;
if(sb.s[sb.len-1]==',') sb.len--;
if(tps_add_headers(msg, &hname, &sb, 0)<0) {
return -1;
}
@ -640,6 +660,7 @@ int tps_reappend_route(sip_msg_t *msg, tps_data_t *ptsd, str *hbody, int rev)
if(c==1) {
if(sb.len>0) {
sb.s = hbody->s;
if(sb.s[sb.len-1]==',') sb.len--;
if(tps_add_headers(msg, &hname, &sb, 0)<0) {
return -1;
}
@ -648,7 +669,12 @@ int tps_reappend_route(sip_msg_t *msg, tps_data_t *ptsd, str *hbody, int rev)
}
}
if(tps_add_headers(msg, &hname, hbody, 0)<0) {
sb = *hbody;
if(sb.len>0 && sb.s[sb.len-1]==',') sb.len--;
trim_zeros_lr(&sb);
trim(&sb);
if(sb.len>0 && sb.s[sb.len-1]==',') sb.len--;
if(tps_add_headers(msg, &hname, &sb, 0)<0) {
return -1;
}

@ -298,8 +298,8 @@ int tps_storage_link_msg(sip_msg_t *msg, tps_data_t *td, int dir)
/* extract the contact address */
if(parse_headers(msg, HDR_CONTACT_F, 0)<0 || msg->contact==NULL) {
if(td->s_method_id == METHOD_MESSAGE) {
/* no contact required for MESSAGE - done */
if(td->s_method_id != METHOD_INVITE) {
/* no mandatory contact unless is INVITE - done */
return 0;
}
LM_ERR("bad sip message or missing Contact hdr\n");
@ -871,7 +871,7 @@ int tps_storage_load_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd)
return -1;
if(md->a_uuid.len<=0 && md->b_uuid.len<=0) {
LM_ERR("no dlg uuid provided\n");
LM_DBG("no dlg uuid provided\n");
return -1;
}
@ -1015,6 +1015,7 @@ int tps_storage_update_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd)
return 0;
}
ret = tps_storage_link_msg(msg, md, md->direction);
if(ret<0) return -1;
@ -1044,15 +1045,18 @@ int tps_storage_update_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd)
db_uvals[nr_ucols].val.str_val = TPS_STRZ(md->b_contact);
nr_ucols++;
db_ucols[nr_ucols] = &td_col_b_rr;
db_uvals[nr_ucols].type = DB1_STR;
db_uvals[nr_ucols].val.str_val = TPS_STRZ(md->b_rr);
nr_ucols++;
if(msg->first_line.type==SIP_REPLY) {
if(sd->b_tag.len<=0
&& msg->first_line.u.reply.statuscode>=200
&& msg->first_line.u.reply.statuscode<300) {
if((sd->iflags&TPS_IFLAG_DLGON) == 0) {
db_ucols[nr_ucols] = &td_col_b_rr;
db_uvals[nr_ucols].type = DB1_STR;
db_uvals[nr_ucols].val.str_val = TPS_STRZ(md->b_rr);
nr_ucols++;
}
db_ucols[nr_ucols] = &td_col_b_tag;
db_uvals[nr_ucols].type = DB1_STR;
db_uvals[nr_ucols].val.str_val = TPS_STRZ(md->b_tag);
@ -1060,7 +1064,7 @@ int tps_storage_update_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd)
db_ucols[nr_ucols] = &td_col_iflags;
db_uvals[nr_ucols].type = DB1_INT;
db_uvals[nr_ucols].val.int_val = 1;
db_uvals[nr_ucols].val.int_val = sd->iflags|TPS_IFLAG_DLGON;
nr_ucols++;
}
}

@ -34,6 +34,9 @@
#define TPS_DIR_DOWNSTREAM 0
#define TPS_DIR_UPSTREAM 1
#define TPS_IFLAG_INIT 1
#define TPS_IFLAG_DLGON 2
#define TPS_DATA_SIZE 8192
typedef struct tps_data {
char cbuf[TPS_DATA_SIZE];

@ -836,9 +836,8 @@ event_route[uac:reply] {
8.6. uac.reg_refresh
Load one record by l_uuid from database for remote registrations. If
the record exists in memory, its authentication password, flags and
proxy are updated, otherwise a new record is added. The command has a
parameter, which is the value of l_uuid field.
the record exists in memory, it will be replaced with the new values
loaded from database.
Example 1.33. uac.reg_refresh usage
...

@ -30,6 +30,8 @@
#include "../../mem/mem.h"
#include "../../hashes.h"
#include "../../dset.h"
#include "../../srapi.h"
#include "../../parser/parse_cseq.h"
#include "../../modules/tm/tm_load.h"
#include "auth.h"
@ -369,7 +371,7 @@ error:
int uac_auth( struct sip_msg *msg)
int uac_auth(sip_msg_t *msg)
{
static struct authenticate_body auth;
struct uac_credential *crd;
@ -379,6 +381,7 @@ int uac_auth( struct sip_msg *msg)
struct hdr_field *hdr;
HASHHEX response;
str *new_hdr;
sr_cfgenv_t *cenv = NULL;
/* get transaction */
t = uac_tmb.t_gett();
@ -465,7 +468,15 @@ int uac_auth( struct sip_msg *msg)
/* mark request in T with uac auth for increase of cseq via dialog
* - this function is executed in failure route, msg_flags will be
* reset afterwards by tm fake env */
if(t->uas.request) t->uas.request->msg_flags |= FL_UAC_AUTH;
if(t->uas.request) {
t->uas.request->msg_flags |= FL_UAC_AUTH;
cenv = sr_cfgenv_get();
if(cenv->cb_cseq_update != NULL) {
if(cenv->cb_cseq_update(msg)<0) {
goto error;
}
}
}
return 0;
error:

@ -995,9 +995,8 @@ event_route[uac:reply] {
</title>
<para>
Load one record by l_uuid from database for remote registrations.
If the record exists in memory, its authentication password, flags
and proxy are updated, otherwise a new record is added.
The command has a parameter, which is the value of l_uuid field.
If the record exists in memory, it will be replaced with the new
values loaded from database.
</para>
<example>
<title><function>uac.reg_refresh</function> usage</title>

@ -663,7 +663,7 @@ reg_uac_t *reg_ht_get_byuser(str *user, str *domain)
it = _reg_htable->entries[slot].byuser;
while(it)
{
if((it->r->h_uuid==hash) && (it->r->l_username.len==user->len)
if((it->r->h_user==hash) && (it->r->l_username.len==user->len)
&& (strncmp(it->r->l_username.s, user->s, user->len)==0))
{
if(domain!=NULL && domain->s!=NULL)

@ -8,7 +8,6 @@ include ../../Makefile.defs
auto_gen=
NAME=uid_avp_db.so
LIBS=
DEFS += -Wall
DEFS+=-DSER_MOD_INTERFACE

@ -13,8 +13,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@ -42,7 +42,8 @@
extern int match_mode;
int db_build_userbl_tree(const str *username, const str *domain, const str *table, struct dtrie_node_t *root, int use_domain)
int db_build_userbl_tree(const str *username, const str *domain,
const str *dbtable, struct dtrie_node_t *root, int use_domain)
{
db_key_t columns[2] = { &userblacklist_prefix_col, &userblacklist_whitelist_col };
db_key_t key[2] = { &userblacklist_username_col, &userblacklist_domain_col };
@ -59,13 +60,14 @@ int db_build_userbl_tree(const str *username, const str *domain, const str *tabl
VAL_STR(val + 1).s = domain->s;
VAL_STR(val + 1).len = domain->len;
if (userblacklist_dbf.use_table(userblacklist_dbh, table) < 0) {
LM_ERR("cannot use table '%.*s'.\n", table->len, table->s);
if (userblacklist_dbf.use_table(userblacklist_dbh, dbtable) < 0) {
LM_ERR("cannot use db table '%.*s'.\n", dbtable->len, dbtable->s);
return -1;
}
if (userblacklist_dbf.query(userblacklist_dbh, key, 0, val, columns, (!use_domain) ? (1) : (2), 2, 0, &res) < 0) {
LM_ERR("error while executing query.\n");
if (userblacklist_dbf.query(userblacklist_dbh, key, 0, val, columns,
(!use_domain) ? (1) : (2), 2, 0, &res) < 0) {
LM_ERR("error while executing query on db table '%.*s'\n",
dbtable->len, dbtable->s);
return -1;
}
@ -85,8 +87,12 @@ int db_build_userbl_tree(const str *username, const str *domain, const str *tabl
} else {
nodeflags=(void *)MARK_WHITELIST;
}
if (dtrie_insert(root, RES_ROWS(res)[i].values[0].val.string_val, strlen(RES_ROWS(res)[i].values[0].val.string_val),
nodeflags, match_mode) < 0) LM_ERR("could not insert values into trie.\n");
if (dtrie_insert(root, RES_ROWS(res)[i].values[0].val.string_val,
strlen(RES_ROWS(res)[i].values[0].val.string_val),
nodeflags, match_mode) < 0)
LM_ERR("could not insert values into trie.\n");
n++;
}
else {
@ -105,20 +111,22 @@ int db_build_userbl_tree(const str *username, const str *domain, const str *tabl
* Rebuild d-tree using database entries
* \return negative on failure, positive on success, indicating the number of d-tree entries
*/
int db_reload_source(const str *table, struct dtrie_node_t *root)
int db_reload_source(const str *dbtable, struct dtrie_node_t *root)
{
db_key_t columns[2] = { &globalblacklist_prefix_col, &globalblacklist_whitelist_col };
db1_res_t *res;
int i;
int n = 0;
void *nodeflags;
if (userblacklist_dbf.use_table(userblacklist_dbh, table) < 0) {
LM_ERR("cannot use table '%.*s'.\n", table->len, table->s);
if (userblacklist_dbf.use_table(userblacklist_dbh, dbtable) < 0) {
LM_ERR("cannot use db table '%.*s'\n", dbtable->len, dbtable->s);
return -1;
}
if (userblacklist_dbf.query(userblacklist_dbh, NULL, NULL, NULL, columns, 0, 2, NULL, &res) < 0) {
LM_ERR("error while executing query.\n");
if (userblacklist_dbf.query(userblacklist_dbh, NULL, NULL, NULL,
columns, 0, 2, NULL, &res) < 0) {
LM_ERR("error while executing query on db table '%.*s'\n",
dbtable->len, dbtable->s);
return -1;
}
@ -133,10 +141,17 @@ int db_reload_source(const str *table, struct dtrie_node_t *root)
/* LM_DBG("insert into tree prefix %s, whitelist %d",
RES_ROWS(res)[i].values[0].val.string_val,
RES_ROWS(res)[i].values[1].val.int_val); */
if (RES_ROWS(res)[i].values[1].val.int_val == 0) nodeflags=(void *) MARK_BLACKLIST;
else nodeflags=(void *)MARK_WHITELIST;
if (dtrie_insert(root, RES_ROWS(res)[i].values[0].val.string_val, strlen(RES_ROWS(res)[i].values[0].val.string_val),
nodeflags, match_mode) < 0) LM_ERR("could not insert values into trie.\n");
if (RES_ROWS(res)[i].values[1].val.int_val == 0) {
nodeflags=(void *)MARK_BLACKLIST;
} else {
nodeflags=(void *)MARK_WHITELIST;
}
if (dtrie_insert(root, RES_ROWS(res)[i].values[0].val.string_val,
strlen(RES_ROWS(res)[i].values[0].val.string_val),
nodeflags, match_mode) < 0)
LM_ERR("could not insert values into trie.\n");
n++;
}
else {

@ -89,15 +89,19 @@ static int check_user_blacklist_fixup(void** param, int param_no);
static int check_globalblacklist_fixup(void** param, int param_no);
/* ---- exported commands: */
static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4);
static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4);
static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2);
static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2);
static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3);
static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3);
static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1);
static int check_whitelist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1);
static int check_globalblacklist(struct sip_msg *msg);
static int check_user_blacklist(sip_msg_t *msg, char* puser,
char* pdomain, char* pnumber, char* ptable);
static int check_user_whitelist(sip_msg_t *msg, char* puser,
char* pdomain, char* pnumber, char* ptable);
static int check_user_blacklist2(sip_msg_t *msg, char* puser, char* pdomain);
static int check_user_whitelist2(sip_msg_t *msg, char* puser, char* pdomain);
static int check_user_blacklist3(sip_msg_t *msg, char* puser, char* pdomain,
char* pnumber);
static int check_user_whitelist3(sip_msg_t *msg, char* puser, char* pdomain,
char* pnumber);
static int check_blacklist(sip_msg_t *msg, struct check_blacklist_fs_t *arg1);
static int check_whitelist(sip_msg_t *msg, struct check_blacklist_fs_t *arg1);
static int check_globalblacklist(sip_msg_t *msg);
/* ---- module init functions: */
@ -116,15 +120,24 @@ struct mi_root * mi_check_userwhitelist(struct mi_root* cmd, void* param); /* u
static cmd_export_t cmds[]={
{ "check_user_blacklist", (cmd_function)check_user_blacklist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_blacklist", (cmd_function)check_user_blacklist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_blacklist", (cmd_function)check_user_blacklist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_blacklist", (cmd_function)check_blacklist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_whitelist", (cmd_function)check_whitelist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_blacklist", (cmd_function)check_globalblacklist, 0, check_globalblacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_blacklist", (cmd_function)check_user_blacklist2, 2,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist2, 2,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_blacklist", (cmd_function)check_user_blacklist3, 3,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist3, 3,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_blacklist", (cmd_function)check_user_blacklist, 4,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_user_whitelist", (cmd_function)check_user_whitelist, 4,
check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_blacklist", (cmd_function)check_blacklist, 1,
check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_whitelist", (cmd_function)check_whitelist, 1,
check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ "check_blacklist", (cmd_function)check_globalblacklist, 0,
check_globalblacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
{ 0, 0, 0, 0, 0, 0}
};
@ -205,8 +218,8 @@ static int check_user_blacklist_fixup(void** param, int param_no)
}
static int check_user_list(sip_msg_t *msg, char* str1, char* str2,
char* str3, char* str4, int listtype)
static int check_user_list(sip_msg_t *msg, char* puser, char* pdomain,
char* pnumber, char* ptable, int listtype)
{
str user = { .len = 0, .s = NULL };
str domain = { .len = 0, .s = NULL};
@ -218,26 +231,26 @@ static int check_user_list(sip_msg_t *msg, char* str1, char* str2,
char req_number[MAXNUMBERLEN+1];
/* user */
if(fixup_get_svalue(msg, (gparam_t*)str1, &user)!=0) {
if(fixup_get_svalue(msg, (gparam_t*)puser, &user)!=0) {
LM_ERR("cannot print user pseudo-variable\n");
return -1;
}
/* domain */
if(fixup_get_svalue(msg, (gparam_t*)str2, &domain)!=0) {
if(fixup_get_svalue(msg, (gparam_t*)pdomain, &domain)!=0) {
LM_ERR("cannot print domain pseudo-variable\n");
return -1;
}
/* source number */
if(str3 != NULL) {
if(fixup_get_svalue(msg, (gparam_t*)str3, &number)!=0) {
if(pnumber != NULL) {
if(fixup_get_svalue(msg, (gparam_t*)pnumber, &number)!=0) {
LM_ERR("cannot print number pseudo-variable\n");
return -1;
}
}
/* table name */
if(str4 != NULL) {
if(fixup_get_svalue(msg, (gparam_t*)str3, &table)!=0) {
LM_ERR("cannot print number pseudo-variable\n");
if(ptable != NULL) {
if(fixup_get_svalue(msg, (gparam_t*)ptable, &table)!=0) {
LM_ERR("cannot print table pseudo-variable\n");
return -1;
}
}
@ -304,37 +317,41 @@ static int check_user_list(sip_msg_t *msg, char* str1, char* str2,
}
static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4)
static int check_user_whitelist(sip_msg_t *msg, char* puser,
char* pdomain, char* pnumber, char* ptable)
{
return check_user_list(msg, str1, str2, str3, str4, 1);
return check_user_list(msg, puser, pdomain, pnumber, ptable, 1);
}
static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4)
static int check_user_blacklist(sip_msg_t *msg, char* puser,
char* pdomain, char* pnumber, char* ptable)
{
return check_user_list(msg, str1, str2, str3, str4, 0);
return check_user_list(msg, puser, pdomain, pnumber, ptable, 0);
}
static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2)
static int check_user_whitelist2(sip_msg_t *msg, char* puser, char* pdomain)
{
return check_user_list(msg, str1, str2, NULL, NULL, 1);
return check_user_list(msg, puser, pdomain, NULL, NULL, 1);
}
static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2)
static int check_user_blacklist2(sip_msg_t *msg, char* puser, char* pdomain)
{
return check_user_list(msg, str1, str2, NULL, NULL, 0);
return check_user_list(msg, puser, pdomain, NULL, NULL, 0);
}
static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3)
static int check_user_whitelist3(sip_msg_t *msg, char* puser, char* pdomain,
char* pnumber)
{
return check_user_list(msg, str1, str2, str3, NULL, 1);
return check_user_list(msg, puser, pdomain, pnumber, NULL, 1);
}
static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3)
static int check_user_blacklist3(sip_msg_t *msg, char* puser, char* pdomain,
char* pnumber)
{
return check_user_list(msg, str1, str2, str3, NULL, 0);
return check_user_list(msg, puser, pdomain, pnumber, NULL, 0);
}
@ -426,7 +443,7 @@ static int check_globalblacklist_fixup(void** param, int param_no)
return 0;
}
static int check_globalblacklist(struct sip_msg* msg)
static int check_globalblacklist(sip_msg_t* msg)
{
static struct check_blacklist_fs_t* arg = NULL;
if(!arg){
@ -482,7 +499,7 @@ static int check_blacklist_fixup(void **arg, int arg_no)
}
static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1)
static int check_blacklist(sip_msg_t *msg, struct check_blacklist_fs_t *arg1)
{
void **nodeflags;
char *ptr;
@ -528,7 +545,7 @@ static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg
return ret;
}
static int check_whitelist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1)
static int check_whitelist(sip_msg_t *msg, struct check_blacklist_fs_t *arg1)
{
void **nodeflags;
char *ptr;

@ -243,7 +243,7 @@ modparam("utils", "xcap_table", "pres_xcap")
# GET-Request
http_query("http://tutpro.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(fu{s
.escape.param})",
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}
@ -252,7 +252,7 @@ switch ($retcode) {
# POST-Request
http_query("http://tutpro.com/index.php", "r_uri=$(ru{s.escape.param})&f_uri=$(f
u{s.escape.param})",
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}
@ -261,7 +261,7 @@ switch ($retcode) {
# GET-Request with additional headers and Post-Data.
http_query("http://tutpro.com/index.php", "{ "alert": "Alert text goes here" }",
"Content-Type: application/json"
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}

@ -237,7 +237,7 @@ modparam("utils", "xcap_table", "pres_xcap")
...
# GET-Request
http_query("http://tutpro.com/index.php?r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}
@ -247,7 +247,7 @@ switch ($retcode) {
...
# POST-Request
http_query("http://tutpro.com/index.php", "r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}
@ -257,7 +257,7 @@ switch ($retcode) {
...
# GET-Request with additional headers and Post-Data.
http_query("http://tutpro.com/index.php", "{ "alert": "Alert text goes here" }", "Content-Type: application/json"
"$var(result)")
"$var(result)");
switch ($retcode) {
...
}

@ -211,6 +211,7 @@ void free_hdr_field_lst(struct hdr_field* hf)
hf=hf->next;
clean_hdr_field(foo);
pkg_free(foo);
foo = 0;
}
}

@ -93,14 +93,14 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
tmp=parse_hname(buf, end, hdr);
if (hdr->type==HDR_ERROR_T){
LOG(L_ERR, "ERROR: get_hdr_field: bad header\n");
ERR("bad header\n");
goto error;
}
/* eliminate leading whitespace */
tmp=eat_lws_end(tmp, end);
if (tmp>=end) {
LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n");
ERR("HF empty\n");
goto error;
}
@ -115,14 +115,14 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
via_cnt++;
vb=pkg_malloc(sizeof(struct via_body));
if (vb==0){
LOG(L_ERR, "get_hdr_field: out of memory\n");
ERR("out of memory\n");
goto error;
}
memset(vb,0,sizeof(struct via_body));
hdr->body.s=tmp;
tmp=parse_via(tmp, end, vb);
if (vb->error==PARSE_ERROR){
LOG(L_ERR, "ERROR: get_hdr_field: bad via\n");
ERR("bad via\n");
free_via_list(vb);
goto error;
}
@ -134,69 +134,64 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
case HDR_CSEQ_T:
cseq_b=pkg_malloc(sizeof(struct cseq_body));
if (cseq_b==0){
LOG(L_ERR, "get_hdr_field: out of memory\n");
ERR("out of memory\n");
goto error;
}
memset(cseq_b, 0, sizeof(struct cseq_body));
hdr->body.s=tmp;
tmp=parse_cseq(tmp, end, cseq_b);
if (cseq_b->error==PARSE_ERROR){
LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n");
ERR("bad cseq\n");
free_cseq(cseq_b);
goto error;
}
hdr->parsed=cseq_b;
hdr->body.len=tmp-hdr->body.s;
DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n",
hdr->name.len, ZSW(hdr->name.s),
cseq_b->number.len, ZSW(cseq_b->number.s),
cseq_b->method.len, cseq_b->method.s);
DBG("cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s),
cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len,
cseq_b->method.s);
break;
case HDR_TO_T:
to_b=pkg_malloc(sizeof(struct to_body));
if (to_b==0){
LOG(L_ERR, "get_hdr_field: out of memory\n");
ERR("out of memory\n");
goto error;
}
memset(to_b, 0, sizeof(struct to_body));
hdr->body.s=tmp;
tmp=parse_to(tmp, end,to_b);
if (to_b->error==PARSE_ERROR){
LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n");
ERR("bad to header\n");
free_to(to_b);
goto error;
}
hdr->parsed=to_b;
hdr->body.len=tmp-hdr->body.s;
DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n",
hdr->name.len, ZSW(hdr->name.s),
hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s));
DBG("DEBUG: to body [%.*s]\n",to_b->body.len,
ZSW(to_b->body.s));
DBG("<%.*s> [%d]; uri=[%.*s]\n", hdr->name.len, ZSW(hdr->name.s),
hdr->body.len, to_b->uri.len, ZSW(to_b->uri.s));
DBG("to body [%.*s]\n", to_b->body.len, ZSW(to_b->body.s));
break;
case HDR_CONTENTLENGTH_T:
hdr->body.s=tmp;
tmp=parse_content_length(tmp,end, &integer);
if (tmp==0){
LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n");
ERR("bad content_length header\n");
goto error;
}
hdr->parsed=(void*)(long)integer;
hdr->body.len=tmp-hdr->body.s;
DBG("DEBUG: get_hdr_body : content_length=%d\n",
(int)(long)hdr->parsed);
DBG("content_length=%d\n", (int)(long)hdr->parsed);
break;
case HDR_RETRY_AFTER_T:
hdr->body.s=tmp;
tmp=parse_retry_after(tmp,end, &uval, &err);
if (err){
LOG(L_ERR, "ERROR:get_hdr_field: bad retry_after header\n");
ERR("bad retry_after header\n");
goto error;
}
hdr->parsed=(void*)(unsigned long)uval;
hdr->body.len=tmp-hdr->body.s;
DBG("DEBUG: get_hdr_body : retry_after=%d\n",
(unsigned)(long)hdr->parsed);
DBG("retry_after=%d\n", (unsigned)(long)hdr->parsed);
break;
case HDR_IDENTITY_T:
case HDR_DATE_T:
@ -255,9 +250,7 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
if (match){
match++;
}else {
LOG(L_ERR,
"ERROR: get_hdr_field: bad body for <%s>(%d)\n",
hdr->name.s, hdr->type);
ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type);
/* abort(); */
tmp=end;
goto error;
@ -268,8 +261,7 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
hdr->body.len=match-hdr->body.s;
break;
default:
LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n",
hdr->type);
BUG("unknown header type %d\n", hdr->type);
goto error;
}
/* jku: if \r covered by current length, shrink it */
@ -277,7 +269,7 @@ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hd
hdr->len=tmp-hdr->name.s;
return tmp;
error:
DBG("get_hdr_field: error exit\n");
DBG("error exit\n");
STATS_BAD_MSG_HDR();
hdr->type=HDR_ERROR_T;
hdr->len=tmp-hdr->name.s;
@ -319,14 +311,14 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
orig_flag=0;
#ifdef EXTRA_DEBUG
DBG("parse_headers: flags=%llx\n", (unsigned long long)flags);
DBG("flags=%llx\n", (unsigned long long)flags);
#endif
while( tmp<end && (flags & msg->parsed_flag) != flags){
prefetch_loc_r(tmp+64, 1);
hf=pkg_malloc(sizeof(struct hdr_field));
if (unlikely(hf==0)){
ser_error=E_OUT_OF_MEM;
LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
ERR("memory allocation error\n");
goto error;
}
memset(hf,0, sizeof(struct hdr_field));
@ -334,8 +326,7 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
rest=get_hdr_field(tmp, end, hf);
switch (hf->type){
case HDR_ERROR_T:
LOG(L_INFO,"ERROR: bad header field [%.*s]\n",
(end-tmp>20)?20:(int)(end-tmp), tmp);
ERR("bad header field [%.*s]\n", (end-tmp>20)?20:(int)(end-tmp), tmp);
goto error;
case HDR_EOH_T:
msg->eoh=tmp; /* or rest?*/
@ -492,10 +483,9 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
break;
case HDR_VIA_T:
msg->parsed_flag|=HDR_VIA_F;
DBG("parse_headers: Via found, flags=%llx\n",
(unsigned long long)flags);
DBG("Via found, flags=%llx\n", (unsigned long long)flags);
if (msg->via1==0) {
DBG("parse_headers: this is the first via\n");
DBG("this is the first via\n");
msg->h_via1=hf;
msg->via1=hf->parsed;
if (msg->via1->next){
@ -506,7 +496,7 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
msg->h_via2=hf;
msg->via2=hf->parsed;
msg->parsed_flag|=HDR_VIA2_F;
DBG("parse_headers: this is the second via\n");
DBG("this is the second via\n");
}
break;
case HDR_DATE_T:
@ -541,8 +531,7 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
msg->parsed_flag|=HDR_REASON_F;
break;
default:
LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
hf->type);
BUG("unknown header type %d\n", hf->type);
goto error;
}
/* add the header to the list*/
@ -554,10 +543,8 @@ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int
msg->last_header=hf;
}
#ifdef EXTRA_DEBUG
DBG("header field type %d, name=<%.*s>, body=<%.*s>\n",
hf->type,
hf->name.len, ZSW(hf->name.s),
hf->body.len, ZSW(hf->body.s));
DBG("header field type %d, name=<%.*s>, body=<%.*s>\n", hf->type,
hf->name.len, ZSW(hf->name.s), hf->body.len, ZSW(hf->body.s));
#endif
tmp=rest;
}
@ -601,22 +588,22 @@ int parse_msg(char* const buf, const unsigned int len, struct sip_msg* const msg
tmp=rest;
switch(fl->type){
case SIP_INVALID:
DBG("parse_msg: invalid message\n");
DBG("invalid message\n");
goto error;
break;
case SIP_REQUEST:
DBG("SIP Request:\n");
DBG(" method: <%.*s>\n",fl->u.request.method.len,
ZSW(fl->u.request.method.s));
DBG(" uri: <%.*s>\n",fl->u.request.uri.len,
ZSW(fl->u.request.uri.s));
DBG(" version: <%.*s>\n",fl->u.request.version.len,
ZSW(fl->u.request.version.s));
DBG(" method: <%.*s>\n", fl->u.request.method.len,
ZSW(fl->u.request.method.s));
DBG(" uri: <%.*s>\n", fl->u.request.uri.len,
ZSW(fl->u.request.uri.s));
DBG(" version: <%.*s>\n", fl->u.request.version.len,
ZSW(fl->u.request.version.s));
flags=HDR_VIA_F;
break;
case SIP_REPLY:
DBG("SIP Reply (status):\n");
DBG(" version: <%.*s>\n",fl->u.reply.version.len,
DBG(" version: <%.*s>\n", fl->u.reply.version.len,
ZSW(fl->u.reply.version.s));
DBG(" status: <%.*s>\n", fl->u.reply.status.len,
ZSW(fl->u.reply.status.s));
@ -627,7 +614,7 @@ int parse_msg(char* const buf, const unsigned int len, struct sip_msg* const msg
flags=HDR_VIA_F;
break;
default:
DBG("unknown type %d\n",fl->type);
DBG("unknown type %d\n", fl->type);
goto error;
}
msg->unparsed=tmp;
@ -638,41 +625,30 @@ int parse_msg(char* const buf, const unsigned int len, struct sip_msg* const msg
/* dump parsed data */
if (msg->via1){
DBG("first via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
msg->via1->name.len,
ZSW(msg->via1->name.s),
msg->via1->version.len,
ZSW(msg->via1->version.s),
msg->via1->transport.len,
ZSW(msg->via1->transport.s),
msg->via1->host.len,
ZSW(msg->via1->host.s),
msg->via1->port_str.len,
ZSW(msg->via1->port_str.s),
msg->via1->port);
if (msg->via1->params.s) DBG(";<%.*s>",
msg->via1->params.len, ZSW(msg->via1->params.s));
msg->via1->name.len, ZSW(msg->via1->name.s),
msg->via1->version.len, ZSW(msg->via1->version.s),
msg->via1->transport.len, ZSW(msg->via1->transport.s),
msg->via1->host.len, ZSW(msg->via1->host.s),
msg->via1->port_str.len, ZSW(msg->via1->port_str.s),
msg->via1->port);
if (msg->via1->params.s)
DBG(";<%.*s>", msg->via1->params.len, ZSW(msg->via1->params.s));
if (msg->via1->comment.s)
DBG(" <%.*s>",
msg->via1->comment.len, ZSW(msg->via1->comment.s));
DBG(" <%.*s>", msg->via1->comment.len, ZSW(msg->via1->comment.s));
DBG ("\n");
}
if (msg->via2){
DBG("second via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
msg->via2->name.len,
ZSW(msg->via2->name.s),
msg->via2->version.len,
ZSW(msg->via2->version.s),
msg->via2->transport.len,
ZSW(msg->via2->transport.s),
msg->via2->host.len,
ZSW(msg->via2->host.s),
msg->via2->port_str.len,
ZSW(msg->via2->port_str.s),
msg->via2->port);
if (msg->via2->params.s) DBG(";<%.*s>",
msg->via2->params.len, ZSW(msg->via2->params.s));
if (msg->via2->comment.s) DBG(" <%.*s>",
msg->via2->comment.len, ZSW(msg->via2->comment.s));
msg->via2->name.len, ZSW(msg->via2->name.s),
msg->via2->version.len, ZSW(msg->via2->version.s),
msg->via2->transport.len, ZSW(msg->via2->transport.s),
msg->via2->host.len, ZSW(msg->via2->host.s),
msg->via2->port_str.len, ZSW(msg->via2->port_str.s),
msg->via2->port);
if (msg->via2->params.s)
DBG(";<%.*s>", msg->via2->params.len, ZSW(msg->via2->params.s));
if (msg->via2->comment.s)
DBG(" <%.*s>", msg->via2->comment.len, ZSW(msg->via2->comment.s));
DBG ("\n");
}
#endif
@ -748,7 +724,7 @@ int set_dst_uri(struct sip_msg* const msg, const str* const uri)
char* ptr;
if (unlikely(!msg || !uri)) {
LOG(L_ERR, "set_dst_uri: Invalid parameter value\n");
ERR("Invalid parameter value\n");
return -1;
}
@ -760,7 +736,7 @@ int set_dst_uri(struct sip_msg* const msg, const str* const uri)
} else {
ptr = (char*)pkg_malloc(uri->len);
if (!ptr) {
LOG(L_ERR, "set_dst_uri: Not enough memory\n");
ERR("Not enough memory\n");
return -1;
}
@ -787,7 +763,7 @@ int set_path_vector(struct sip_msg* msg, str* path)
char* ptr;
if (unlikely(!msg || !path)) {
LM_ERR("invalid parameter value\n");
ERR("invalid parameter value\n");
return -1;
}
@ -799,7 +775,7 @@ int set_path_vector(struct sip_msg* msg, str* path)
} else {
ptr = (char*)pkg_malloc(path->len);
if (!ptr) {
LM_ERR("not enough pkg memory\n");
ERR("not enough pkg memory\n");
return -1;
}
@ -829,7 +805,7 @@ int set_instance(struct sip_msg* msg, str* instance)
char* ptr;
if (unlikely(!msg || !instance)) {
LM_ERR("invalid instance parameter value\n");
ERR("invalid instance parameter value\n");
return -1;
}
@ -841,7 +817,7 @@ int set_instance(struct sip_msg* msg, str* instance)
} else {
ptr = (char*)pkg_malloc(instance->len);
if (!ptr) {
LM_ERR("not enough pkg memory for instance\n");
ERR("not enough pkg memory for instance\n");
return -1;
}
memcpy(ptr, instance->s, instance->len);
@ -868,7 +844,7 @@ int set_ruid(struct sip_msg* msg, str* ruid)
char* ptr;
if (unlikely(!msg || !ruid)) {
LM_ERR("invalid ruid parameter value\n");
ERR("invalid ruid parameter value\n");
return -1;
}
@ -880,7 +856,7 @@ int set_ruid(struct sip_msg* msg, str* ruid)
} else {
ptr = (char*)pkg_malloc(ruid->len);
if (!ptr) {
LM_ERR("not enough pkg memory for ruid\n");
ERR("not enough pkg memory for ruid\n");
return -1;
}
memcpy(ptr, ruid->s, ruid->len);
@ -907,7 +883,7 @@ int set_ua(struct sip_msg* msg, str* location_ua)
char* ptr;
if (unlikely(!msg || !location_ua)) {
LM_ERR("invalid location_ua parameter value\n");
ERR("invalid location_ua parameter value\n");
return -1;
}
@ -919,7 +895,7 @@ int set_ua(struct sip_msg* msg, str* location_ua)
} else {
ptr = (char*)pkg_malloc(location_ua->len);
if (!ptr) {
LM_ERR("not enough pkg memory for location_ua\n");
ERR("not enough pkg memory for location_ua\n");
return -1;
}
memcpy(ptr, location_ua->s, location_ua->len);
@ -1049,7 +1025,7 @@ int get_src_uri(sip_msg_t *m, int tmode, str *uri)
str proto;
if (!uri || !m) {
LM_ERR("invalid parameter value\n");
ERR("invalid parameter value\n");
return -1;
}
@ -1062,13 +1038,13 @@ int get_src_uri(sip_msg_t *m, int tmode, str *uri)
break;
default:
if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
LM_ERR("unknown transport protocol\n");
ERR("unknown transport protocol\n");
return -1;
}
}
} else {
if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
LM_ERR("unknown transport protocol\n");
ERR("unknown transport protocol\n");
return -1;
}
}
@ -1085,7 +1061,7 @@ int get_src_uri(sip_msg_t *m, int tmode, str *uri)
}
if (len > MAX_URI_SIZE) {
LM_ERR("buffer too small\n");
ERR("buffer too small\n");
return -1;
}

@ -52,6 +52,11 @@ int parse_disposition( str *s, struct disposition *disp)
char *tmp;
char *end;
if(s==NULL || s->s==NULL || s->len<=0) {
LM_ERR("invalid parameters\n");
return -1;
}
state = saved_state = FIND_TYPE;
end = s->s + s->len;
disp_p = 0;
@ -114,8 +119,7 @@ int parse_disposition( str *s, struct disposition *disp)
state=F_CRLF;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), s->s);
goto error;
}
@ -143,15 +147,13 @@ int parse_disposition( str *s, struct disposition *disp)
state=F_CR;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
break;
case 0:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("nexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
break;
@ -180,8 +182,7 @@ int parse_disposition( str *s, struct disposition *disp)
state = FIND_PARAM;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
@ -202,8 +203,7 @@ int parse_disposition( str *s, struct disposition *disp)
state = FIND_VAL;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
@ -222,8 +222,7 @@ int parse_disposition( str *s, struct disposition *disp)
state = END_VAL;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
@ -241,8 +240,7 @@ int parse_disposition( str *s, struct disposition *disp)
state = SKIP_QUOTED_VAL;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
@ -270,8 +268,7 @@ int parse_disposition( str *s, struct disposition *disp)
case QUOTED_VAL:
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: unexpected "
"char [%c] in status %d: <<%.*s>> .\n",
LM_ERR("unexpected char [%c] in status %d: <<%.*s>>.\n",
*tmp,state, (int)(tmp-s->s), ZSW(s->s));
goto error;
}
@ -290,8 +287,7 @@ int parse_disposition( str *s, struct disposition *disp)
new_p=(struct disposition_param*)pkg_malloc
(sizeof(struct disposition_param));
if (new_p==0) {
LOG(L_ERR,"ERROR:parse_disposition: no more "
"pkg mem\n");
LM_ERR("no more pkg mem\n");
goto error;
}
memset(new_p,0,sizeof(struct disposition_param));
@ -331,7 +327,7 @@ int parse_disposition( str *s, struct disposition *disp)
disp_p->body.len = tmp - disp_p->body.s;
break;
default:
LOG(L_ERR,"ERROR:parse_disposition: wrong final state (%d)\n",
LM_ERR("wrong final state (%d)\n",
state);
goto error;
}
@ -375,7 +371,7 @@ int parse_content_disposition( struct sip_msg *msg )
if (parse_headers(msg, HDR_CONTENTDISPOSITION_F, 0)==-1)
goto error;
if (msg->content_disposition==0) {
DBG("DEBUG:parse_content_disposition: hdr not found\n");
DBG("hdr not found\n");
return 1;
}
}
@ -389,7 +385,7 @@ int parse_content_disposition( struct sip_msg *msg )
/* parse the body */
disp = (struct disposition*)pkg_malloc(sizeof(struct disposition));
if (disp==0) {
LOG(L_ERR,"ERROR:parse_content_disposition: no more pkg memory\n");
LM_ERR("no more pkg memory\n");
goto error;
}
memset(disp,0,sizeof(struct disposition));

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save