/*! * \brief Add record-route parameter for dialog tracking * \param req SIP request * \param entry dialog hash entry * \param id dialog hash id * \return 0 on success, -1 on failure */ static inline int add_dlg_rr_param(struct dlg_cell *dlg, struct sip_msg *req, unsigned int entry, unsigned int id) { static char buf[RR_DLG_PARAM_SIZE]; str s; int n; char *p; s.s = p = buf; *(p++) = ';'; memcpy(p, rr_param.s, rr_param.len); p += rr_param.len; *(p++) = '='; char *did = p; n = RR_DLG_PARAM_SIZE - (p - buf); if (int2reverse_hex(&p, &n, entry) == -1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p - buf); if (int2reverse_hex(&p, &n, id) == -1) return -1; s.len = p - buf; if (d_rrb.add_rr_param(req, &s) < 0) { LM_ERR("failed to add rr param\n"); return -1; } //add the did into the dlg structure int did_len = p - did; if (dlg->did.s) { if (dlg->did.len < did_len) { shm_free(dlg->did.s); dlg->did.s = (char*) shm_malloc(did_len); if (dlg->did.s == NULL) { LM_ERR("failed to add did to dlg_cell struct\n"); return -1; } } } else { dlg->did.s = (char*) shm_malloc(did_len); if (dlg->did.s == NULL) { LM_ERR("failed to add did to dlg_cell struct\n"); return -1; } } memcpy(dlg->did.s, did, did_len); dlg->did.len = did_len; return 0; }
/*! * \brief Add record-route parameter for dialog tracking * \param req SIP request * \param entry dialog hash entry * \param id dialog hash id * \return 0 on success, -1 on failure */ static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry, unsigned int id) { static char buf[RR_DLG_PARAM_SIZE]; str s; int n; char *p; s.s = p = buf; *(p++) = ';'; memcpy(p, rr_param.s, rr_param.len); p += rr_param.len; *(p++) = '='; n = RR_DLG_PARAM_SIZE - (p-buf); if (int2reverse_hex( &p, &n, entry)==-1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p-buf); if (int2reverse_hex( &p, &n, id)==-1) return -1; s.len = p-buf; if (d_rrb.add_rr_param( req, &s)<0) { LM_ERR("failed to add rr param\n"); return -1; } return 0; }
void crcitt_string_array( char *dst, str src[], int size ) { register int i; register unsigned short ccitt; register char *c; register int len; int str_len; ccitt = 0xFFFF; str_len=CRC16_LEN; for (i=0; i<size; i++ ) { c=src[i].s; len=src[i].len; while(len) { ccitt = UPDCIT( *c, ccitt ); c++;len--; } } ccitt = ~ccitt; if (int2reverse_hex( &dst, &str_len, ccitt )==-1) { /* bug ... printed ccitt value longer than CRC32_LEN */ LOG(L_CRIT, "ERROR: crcitt_string_array: string conversion incomplete\n"); } /* padding */ while( str_len ) { *dst='0'; dst++; str_len--; } }
static inline void init_synonym_id( struct cell *t ) { struct sip_msg *p_msg; int size; char *c; unsigned int myrand; if (!syn_branch) { p_msg=t->uas.request; if (p_msg) { /* char value of a proxied transaction is calculated out of header-fields forming transaction key */ char_msg_val( p_msg, t->md5 ); } else { /* char value for a UAC transaction is created randomly -- UAC is an originating stateful element which cannot be refreshed, so the value can be anything */ /* HACK : not long enough */ myrand=rand(); c=t->md5; size=MD5_LEN; memset(c, '0', size ); int2reverse_hex( &c, &size, myrand ); } } }
struct cell* build_cell( struct sip_msg* p_msg ) { struct cell* new_cell; unsigned int i; unsigned int myrand; int size; char *c; struct ua_client *uac; /* avoid 'unitialized var use' warning */ myrand=0; /* allocs a new cell */ new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) ); if ( !new_cell ) { ser_error=E_OUT_OF_MEM; return NULL; } /* filling with 0 */ memset( new_cell, 0, sizeof( struct cell ) ); /* UAS */ #ifdef EXTRA_DEBUG new_cell->uas.response.retr_timer.tg=TG_RT; new_cell->uas.response.fr_timer.tg=TG_FR; #endif new_cell->uas.response.fr_timer.payload = new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response); new_cell->uas.response.my_T=new_cell; /* bogdan - debug */ /*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1), via_s(p_msg->via1,p_msg));*/ /* enter callback, which may potentially want to parse some stuff, before the request is shmem-ized */ if (p_msg) callback_event(TMCB_REQUEST_IN, new_cell, p_msg, p_msg->REQ_METHOD ); if (p_msg) { new_cell->uas.request = sip_msg_cloner(p_msg); if (!new_cell->uas.request) goto error; } /* new_cell->uas.to_tag = &( get_to(new_cell->uas.request)->tag_value ); */ new_cell->uas.response.my_T = new_cell; /* UAC */ for(i=0;i<MAX_BRANCHES;i++) { uac=&new_cell->uac[i]; uac->request.my_T = new_cell; uac->request.branch = i; #ifdef EXTRA_DEBUG uac->request.fr_timer.tg = TG_FR; uac->request.retr_timer.tg = TG_RT; #endif uac->request.retr_timer.payload = uac->request.fr_timer.payload = &uac->request; uac->local_cancel=uac->request; } /* global data for transaction */ if (p_msg) { new_cell->hash_index = p_msg->hash_index; } else { /* note: unsatisfactory if RAND_MAX < TABLE_ENTRIES */ myrand = rand(); new_cell->hash_index = myrand % TABLE_ENTRIES ; } new_cell->wait_tl.payload = new_cell; new_cell->dele_tl.payload = new_cell; new_cell->relaied_reply_branch = -1; /* new_cell->T_canceled = T_UNDEFINED; */ #ifdef EXTRA_DEBUG new_cell->wait_tl.tg=TG_WT; new_cell->dele_tl.tg=TG_DEL; #endif if (!syn_branch) { if (p_msg) { /* char value of a proxied transaction is calculated out of header-fileds forming transaction key */ char_msg_val( p_msg, new_cell->md5 ); } else { /* char value for a UAC transaction is created randomly -- UAC is an originating stateful element which cannot be refreshed, so the value can be anything */ /* HACK : not long enough */ c=new_cell->md5; size=MD5_LEN; memset(c, '0', size ); int2reverse_hex( &c, &size, myrand ); } } init_cell_lock( new_cell ); return new_cell; error: shm_free(new_cell); return NULL; }
static int assemble_msg(struct sip_msg* msg, struct tw_info *twi) { static char id_buf[IDBUF_LEN]; static char route_buffer[ROUTE_BUFFER_MAX]; static char append_buf[APPEND_BUFFER_MAX]; static char cmd_buf[CMD_BUFFER_MAX]; static str empty_param = {".",1}; unsigned int hash_index, label; contact_body_t* cb=0; contact_t* c=0; name_addr_t na; rr_t* record_route; struct hdr_field* p_hdr; param_hooks_t hooks; int l; char* s, fproxy_lr; str route, next_hop, append, tmp_s, body, str_uri; if(msg->first_line.type != SIP_REQUEST){ LM_ERR("called for something else then a SIP request\n"); goto error; } /* parse all -- we will need every header field for a UAS */ if ( parse_headers(msg, HDR_EOH_F, 0)==-1) { LM_ERR("parse_headers failed\n"); goto error; } /* find index and hash; (the transaction can be safely used due * to refcounting till script completes) */ if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) { LM_ERR("t_get_trans_ident failed\n"); goto error; } /* parse from header */ if (msg->from->parsed==0 && parse_from_header(msg)<0 ) { LM_ERR("failed to parse <From:> header\n"); goto error; } /* parse the RURI (doesn't make any malloc) */ msg->parsed_uri_ok = 0; /* force parsing */ if (parse_sip_msg_uri(msg)<0) { LM_ERR("uri has not been parsed\n"); goto error; } /* parse contact header */ str_uri.s = 0; str_uri.len = 0; if(msg->contact) { if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) { LM_ERR("failed to parse <Contact:> header\n"); goto error; } cb = (contact_body_t*)msg->contact->parsed; if(cb && (c=cb->contacts)) { str_uri = c->uri; if (find_not_quoted(&str_uri,'<')) { parse_nameaddr(&str_uri,&na); str_uri = na.uri; } } } /* str_uri is taken from caller's contact or from header * for backwards compatibility with pre-3261 (from is already parsed)*/ if(!str_uri.len || !str_uri.s) str_uri = get_from(msg)->uri; /* parse Record-Route headers */ route.s = s = route_buffer; route.len = 0; fproxy_lr = 0; next_hop = empty_param; p_hdr = msg->record_route; if(p_hdr) { if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) { LM_ERR("failed to parse 'Record-Route:' header\n"); goto error; } record_route = (rr_t*)p_hdr->parsed; } else { record_route = 0; } if( record_route ) { if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 && tmp_s.s+1!=record_route->nameaddr.uri.s+ record_route->nameaddr.uri.len) { /* Parse all parameters */ tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s- record_route->nameaddr.uri.s); if (parse_params( &tmp_s, CLASS_URI, &hooks, &record_route->params) < 0) { LM_ERR("failed to parse record route uri params\n"); goto error; } fproxy_lr = (hooks.uri.lr != 0); LM_DBG("record_route->nameaddr.uri: %.*s\n", record_route->nameaddr.uri.len,record_route->nameaddr.uri.s); if(fproxy_lr){ LM_DBG("first proxy has loose routing\n"); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) { /* filter out non-RR hdr and empty hdrs */ if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0) continue; if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){ LM_ERR("failed to parse <Record-route:> header\n"); goto error; } for(record_route=p_hdr->parsed; record_route; record_route=record_route->next){ LM_DBG("record_route->nameaddr.uri: <%.*s>\n", record_route->nameaddr.uri.len, record_route->nameaddr.uri.s); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } if(!fproxy_lr){ copy_route(s,route.len,str_uri.s,str_uri.len); str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } else { next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } } LM_DBG("calculated route: %.*s\n",route.len,route.len ? route.s : ""); LM_DBG("next r-uri: %.*s\n",str_uri.len,str_uri.len ? str_uri.s : ""); if ( REQ_LINE(msg).method_value==METHOD_INVITE || (twi->append && twi->append->add_body) ) { /* get body */ if( (body.s = get_body(msg)) == 0 ){ LM_ERR("get_body failed\n"); goto error; } body.len = msg->len - (body.s - msg->buf); } else { body = empty_param; } /* flags & additional headers */ append.s = s = append_buf; if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) { LM_ERR("buffer overflow while copying flags\n"); goto error; } append_str(s,"P-MsgFlags: ",12); l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/ if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) { LM_ERR("buffer overflow while copying optional header\n"); goto error; } append_chr(s,'\n'); if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg, twi->append->elems))==0) ) goto error; /* body separator */ append_chr(s,'.'); append.len = s-append.s; eol_line(1).s = s = cmd_buf; if(twi->action.len+12 >= CMD_BUFFER_MAX){ LM_ERR("buffer overflow while copying command name\n"); goto error; } append_str(s,"sip_request.",12); append_str(s,twi->action.s,twi->action.len); eol_line(1).len = s-eol_line(1).s; eol_line(2)=REQ_LINE(msg).method; /* method type */ eol_line(3)=msg->parsed_uri.user; /* user from r-uri */ eol_line(4)=msg->parsed_uri.host; /* domain */ eol_line(5)=msg->rcv.bind_address->address_str; /* dst ip */ eol_line(6)=msg->rcv.dst_port==SIP_PORT ? empty_param : msg->rcv.bind_address->port_no_str; /* port */ /* r_uri ('Contact:' for next requests) */ eol_line(7)=*GET_RURI(msg); /* r_uri for subsequent requests */ eol_line(8)=str_uri.len?str_uri:empty_param; eol_line(9)=get_from(msg)->body; /* from */ eol_line(10)=msg->to->body; /* to */ eol_line(11)=msg->callid->body; /* callid */ eol_line(12)=get_from(msg)->tag_value; /* from tag */ eol_line(13)=get_to(msg)->tag_value; /* to tag */ eol_line(14)=get_cseq(msg)->number; /* cseq number */ eol_line(15).s=id_buf; /* hash:label */ s = int2str(hash_index, &l); if (l+1>=IDBUF_LEN) { LM_ERR("too big hash\n"); goto error; } memcpy(id_buf, s, l); id_buf[l]=':'; eol_line(15).len=l+1; s = int2str(label, &l); if (l+1+eol_line(15).len>=IDBUF_LEN) { LM_ERR("too big label\n"); goto error; } memcpy(id_buf+eol_line(15).len, s, l); eol_line(15).len+=l; eol_line(16) = route.len ? route : empty_param; eol_line(17) = next_hop; eol_line(18) = append; eol_line(19) = body; /* success */ return 1; error: /* 0 would lead to immediate script exit -- -1 returns * with 'false' to script processing */ return -1; }
int dlg_replace_contact(struct sip_msg* msg, struct dlg_cell* dlg) { struct lump* lump, *crt, *prev_crt =0, *a, *foo; int offset; int len,n; char *prefix=NULL,*suffix=NULL,*p,*p_init,*ct_username=NULL; int prefix_len,suffix_len,ct_username_len=0; struct sip_uri ctu; str contact; if(!msg->contact) { if(parse_headers(msg, HDR_CONTACT_F, 0)< 0) { LM_ERR("Failed to parse headers\n"); return -1; } if(!msg->contact) return 0; } prefix_len = 5; /* <sip: */ if (dlg->flags & DLG_FLAG_TOPH_KEEP_USER) { if ( parse_contact(msg->contact)<0 || ((contact_body_t *)msg->contact->parsed)->contacts==NULL || ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) { LM_ERR("bad Contact HDR\n"); } else { contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri; if(parse_uri(contact.s, contact.len, &ctu) < 0) { LM_ERR("Bad Contact URI\n"); } else { ct_username = ctu.user.s; ct_username_len = ctu.user.len; LM_DBG("Trying to propagate username [%.*s]\n",ct_username_len, ct_username); if (ct_username_len > 0) prefix_len += 1 + /* @ */ + ct_username_len; } } } prefix = pkg_malloc(prefix_len); if (!prefix) { LM_ERR("no more pkg\n"); goto error; } suffix_len = RR_DLG_PARAM_SIZE+1; /* > */ suffix = pkg_malloc(suffix_len); if (!suffix) { LM_ERR("no more pkg\n"); goto error; } memcpy(prefix,"<sip:",prefix_len); if (dlg->flags & DLG_FLAG_TOPH_KEEP_USER && ct_username_len > 0) { memcpy(prefix+5,ct_username,ct_username_len); prefix[prefix_len-1] = '@'; } p_init = p = suffix; *p++ = ';'; memcpy(p,rr_param.s,rr_param.len); p+=rr_param.len; *p++ = '='; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_entry)==-1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_id)==-1) return -1; *p++ = '>'; suffix_len = p - p_init; offset = msg->contact->body.s - msg->buf; len = msg->contact->body.len; for (crt = msg->add_rm;crt;) { if (crt->type == HDR_CONTACT_T && crt->op == LUMP_DEL && crt->u.offset >= offset && crt->u.offset <= offset + len) { lump = crt; crt = crt->next; a=lump->before; while(a) { LM_DBG("before [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { LM_DBG("after [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if(lump == msg->add_rm) msg->add_rm = lump->next; else prev_crt->next = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); continue; } prev_crt = crt; crt= crt->next; } if ((lump = del_lump(msg, msg->contact->body.s - msg->buf, msg->contact->body.len,HDR_CONTACT_T)) == 0) { LM_ERR("del_lump failed\n"); goto error; } if ((lump = insert_new_lump_after(lump,prefix,prefix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } /* make sure we do not free this string in case of a further error */ prefix = NULL; if ((lump = insert_subst_lump_after(lump, SUBST_SND_ALL, HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting SUBST_SND buf\n"); goto error; } if ((lump = insert_new_lump_after(lump,suffix,suffix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } return 0; error: if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); return -1; }
int dlg_replace_contact(struct sip_msg* msg, struct dlg_cell* dlg) { // str local_contact; struct lump* lump, *crt, *prev_crt =0, *a, *foo; int offset; int len,n; char *prefix=NULL,*suffix=NULL,*p,*p_init; int prefix_len,suffix_len; if(!msg->contact) { if(parse_headers(msg, HDR_CONTACT_F, 0)< 0) { LM_ERR("Failed to parse headers\n"); return -1; } if(!msg->contact) return 0; } prefix_len = 5; /* <sip: */ prefix = pkg_malloc(prefix_len); if (!prefix) { LM_ERR("no more pkg\n"); goto error; } suffix_len = RR_DLG_PARAM_SIZE+1; /* > */ suffix = pkg_malloc(suffix_len); if (!suffix) { LM_ERR("no more pkg\n"); goto error; } memcpy(prefix,"<sip:",prefix_len); p_init = p = suffix; *p++ = ';'; memcpy(p,"did",3); p+=3; *p++ = '='; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_entry)==-1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_id)==-1) return -1; *p++ = '>'; suffix_len = p - p_init; offset = msg->contact->body.s - msg->buf; len = msg->contact->body.len; for (crt = msg->add_rm;crt;) { if (crt->type == HDR_CONTACT_T && crt->op == LUMP_DEL && crt->u.offset >= offset && crt->u.offset <= offset + len) { lump = crt; crt = crt->next; a=lump->before; while(a) { LM_DBG("before [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { LM_DBG("after [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if(lump == msg->add_rm) msg->add_rm = lump->next; else prev_crt->next = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); continue; } prev_crt = crt; crt= crt->next; } if ((lump = del_lump(msg, msg->contact->body.s - msg->buf, msg->contact->body.len,HDR_CONTACT_T)) == 0) { LM_ERR("del_lump failed \n"); goto error; } if ((lump = insert_new_lump_after(lump,prefix,prefix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } if ((lump = insert_subst_lump_after(lump, SUBST_SND_ALL, HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting SUBST_SND buf\n"); goto error; } if ((lump = insert_new_lump_after(lump,suffix,suffix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } // LM_DBG("Replaced contact with [%.*s]\n", local_contact.len, local_contact.s); return 0; error: if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); return -1; }