/*! \brief * Parse the whole message and bodies of all header fields * that will be needed by registrar */ int parse_message_for_register(struct sip_msg* _m) { struct hdr_field* ptr; if (parse_headers(_m, HDR_EOH_F, 0) == -1) { rerrno = R_PARSE; LM_ERR("failed to parse headers\n"); return -1; } if (!_m->to) { rerrno = R_TO_MISS; LM_ERR("To not found\n"); return -2; } if (!_m->callid) { rerrno = R_CID_MISS; LM_ERR("Call-ID not found\n"); return -3; } if (!_m->cseq) { rerrno = R_CS_MISS; LM_ERR("CSeq not found\n"); return -4; } if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) { rerrno = R_PARSE_EXP; LM_ERR("failed to parse expires body\n"); return -5; } if (_m->contact) { ptr = _m->contact; while (ptr) { if (ptr->type == HDR_CONTACT_T) { if (!ptr->parsed && (parse_contact(ptr) < 0)) { rerrno = R_PARSE_CONT; LM_ERR("failed to parse Contact body\n"); return -6; } } ptr = ptr->next; } } return 0; }
/* * Parse the whole message and bodies of all header fields * that will be needed by registrar */ int parse_message(struct sip_msg* _m) { struct hdr_field* ptr; if (parse_headers(_m, HDR_EOH_F, 0) == -1) { rerrno = R_PARSE; LOG(L_ERR, "parse_message(): Error while parsing headers\n"); return -1; } if (!_m->to) { rerrno = R_TO_MISS; LOG(L_ERR, "parse_message(): To not found\n"); return -2; } if (!_m->callid) { rerrno = R_CID_MISS; LOG(L_ERR, "parse_message(): Call-ID not found\n"); return -3; } if (!_m->cseq) { rerrno = R_CS_MISS; LOG(L_ERR, "parse_message(): CSeq not found\n"); return -4; } if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) { rerrno = R_PARSE_EXP; LOG(L_ERR, "parse_message(): Error while parsing expires body\n"); return -5; } if (_m->contact) { ptr = _m->contact; while(ptr) { if (ptr->type == HDR_CONTACT_T) { if (!ptr->parsed && (parse_contact(ptr) < 0)) { rerrno = R_PARSE_CONT; LOG(L_ERR, "parse_message(): Error while parsing Contact body\n"); return -6; } } ptr = ptr->next; } } return 0; }
int sca_get_msg_contact_uri( sip_msg_t *msg, str *contact_uri ) { contact_body_t *contact_body; assert( msg != NULL ); assert( contact_uri != NULL ); if ( SCA_HEADER_EMPTY( msg->contact )) { LM_DBG( "Empty Contact header" ); contact_uri->s = NULL; contact_uri->len = 0; return( 0 ); } if ( parse_contact( msg->contact ) < 0 ) { LM_ERR( "Failed to parse Contact header: %.*s", STR_FMT( &msg->contact->body )); return( -1 ); } if (( contact_body = (contact_body_t *)msg->contact->parsed ) == NULL ) { LM_ERR( "Invalid Contact header: %.*s", STR_FMT( &msg->contact->body )); return( -1 ); } if ( contact_body->star ) { LM_ERR( "Invalid Contact header: SCA Contact must not be \"*\"" ); return( -1 ); } if ( contact_body->contacts == NULL ) { LM_ERR( "Invalid Contact header: parser found no contacts" ); return( -1 ); } if ( contact_body->contacts->next ) { LM_ERR( "Invalid Contact header: Contact may only contain one URI" ); return( -1 ); } contact_uri->s = contact_body->contacts->uri.s; contact_uri->len = contact_body->contacts->uri.len; return( 1 ); }
/** * Extract URI from the Contact header field * @param _m - the SIP message * @param uri - URI to fill * @param _c - contact to fill * @returns 0 on success, -1 on error */ static inline int get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c) { if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact) return -1; if (!_m->contact->parsed && parse_contact(_m->contact) < 0) { LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n"); return -1; } *_c = ((contact_body_t*)_m->contact->parsed)->contacts; if (*_c == NULL) { LOG(L_DBG, "get_contact_uri: Error while parsing Contact body or star contact\n"); return -1; } if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { LOG(L_ERR, "get_contact_uri: Error while parsing Contact URI\n"); return -1; } return 0; }
static inline void get_routing_info(struct sip_msg *msg, int is_req, unsigned int *skip_rrs, str *contact, str *rr_set) { /* extract the contact address */ if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){ //LM_ERR("bad sip message or missing Contact hdr\n"); contact->s = NULL; contact->len = 0; } else { 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"); contact->s = NULL; contact->len = 0; } else { *contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri; } } /* extract the RR parts - parse all headers as we can have multiple RR headers in the same message */ if( parse_headers(msg,HDR_EOH_F,0)<0 ){ LM_ERR("failed to parse record route header\n"); rr_set->s = 0; rr_set->len = 0; } else { if(msg->record_route){ if( print_rr_body(msg->record_route, rr_set, !is_req, skip_rrs) != 0 ){ LM_ERR("failed to print route records \n"); rr_set->s = 0; rr_set->len = 0; } } else { rr_set->s = 0; rr_set->len = 0; } } }
/* * Extract URI from the Contact header field */ int get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c) { if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact) return -1; if (!_m->contact->parsed && parse_contact(_m->contact) < 0) { LM_ERR("failed to parse Contact body\n"); return -1; } *_c = ((contact_body_t*)_m->contact->parsed)->contacts; if (*_c == NULL) /* no contacts found */ return -1; if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { LM_ERR("failed to parse Contact URI [%.*s]\n", (*_c)->uri.len, ((*_c)->uri.s)?(*_c)->uri.s:""); return -1; } return 0; }
/* * Parse Contact header field body and extract URI * Does not parse headers ! */ static inline int get_contact_uri(struct sip_msg* msg, str* uri) { contact_t* c; uri->len = 0; if (!msg->contact) return 1; if (parse_contact(msg->contact) < 0) { LM_ERR("error while parsing Contact body\n"); return -1; } c = ((contact_body_t*)msg->contact->parsed)->contacts; if (!c) { LM_ERR("empty body or * contact\n"); return -2; } *uri = c->uri; return 0; }
//#define DEBUG int encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip) { contact_body_t *cb; contact_t *c; str uri; str newUri; int res; char separator; /* * I have a list of contacts in contact->parsed which is of type contact_body_t * inside i have a contact->parsed->contact which is the head of the list of contacts * inside it is a * str uri; * struct contact *next; * I just have to visit each uri and encode each uri according to a scheme */ if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact == NULL) )) { LM_ERR("no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; /* we visit each contact */ if (c != NULL) { uri = c->uri; res = encode_uri (uri, encoding_prefix, public_ip,separator, &newUri); if (res != 0) { LM_ERR("failed encoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LM_ERR("lumping failed in mangling port \n"); return -2; } /* encoding next contacts too?*/ #ifdef ENCODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = c->uri; res = encode_uri (uri, encoding_prefix,public_ip,separator,&newUri); if (res != 0) { LM_ERR("failed encode_uri.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len)< 0) { LM_ERR("lumping failed in mangling port \n"); return -3; } } /* while */ #endif /* ENCODE_ALL_CONTACTS */ } /* if c != NULL */ } /* end if */ else /* after parsing still NULL */ { LM_ERR("unable to parse Contact header\n"); return -4; } return 1; }
int decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2) { contact_body_t *cb; contact_t *c; str uri; str newUri; char separator; int res; #ifdef DEBUG str* ruri; fprintf (stdout,"---START--------DECODE CONTACT HEADER-----------------\n"); #endif if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact== NULL) )) { LM_ERR("no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; #ifdef DEBUG fprintf (stdout,"Using separator %c\n",separator); ruri = GET_RURI(msg); fprintf (stdout,"[len = %d]New uri is->%.*s\n", ruri->len,ruri->len,ruri->s); ruri = &msg->first_line.u.request.uri; fprintf (stdout, "INITIAL.s=[%.*s]\n", ruri->len, ruri->s); #endif if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; // we visit each contact if (c != NULL) { uri = c->uri; res = decode_uri (uri, separator, &newUri); #ifdef DEBUG fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s); #endif if (res != 0) { LM_ERR("failed decoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LM_ERR("lumping failed in mangling port \n"); return -2; } #ifdef DECODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = c->uri; res = decode_uri (uri, separator, &newUri); if (res != 0) { LM_ERR("failed decoding contact.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LM_ERR("lumping failed in mangling port \n"); return -3; } } // end while #endif } // if c!= NULL } // end if else // after parsing still NULL { LM_ERR("unable to parse Contact header\n"); return -4; } #ifdef DEBUG fprintf (stdout,"---END--------DECODE CONTACT HEADER-----------------\n");fflush(stdout); #endif return 1; }
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps) { struct sip_msg* msg= NULL; int lexpire= 0; unsigned int cseq; ua_pres_t* presentity= NULL, *hentity= NULL; struct to_body *pto= NULL, *pfrom = NULL; int size= 0; int flag ; str record_route= {0, 0}; int rt; str contact; int initial_request = 0; if(ps==NULL || ps->param== NULL || *ps->param== NULL ) { LM_ERR("null callback parameter\n"); return; } LM_DBG("completed with status %d\n",ps->code) ; hentity= (ua_pres_t*)(*ps->param); flag= hentity->flag; if(hentity->flag & XMPP_INITIAL_SUBS) hentity->flag= XMPP_SUBSCRIBE; /* get dialog information from reply message: callid, to_tag, from_tag */ msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n "); goto error; } if(msg== FAKED_REPLY) { /* delete record from hash_table and call registered functions */ if(hentity->call_id.s== NULL) /* if a new requets failed-> do nothing*/ { LM_DBG("initial Subscribe request failed\n"); goto done; } lock_get(&HashT->p_records[hentity->hash_index].lock); presentity = get_htable_safe(hentity->hash_index, hentity->local_index); if(presentity) { delete_htable_safe(presentity, hentity->hash_index); lock_release(&HashT->p_records[hentity->hash_index].lock); } lock_release(&HashT->p_records[hentity->hash_index].lock); goto done; } if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); goto done; } /*if initial request */ if(hentity->call_id.s== NULL) { initial_request = 1; if(ps->code>= 300) { LM_DBG("initial Subscribe request failed\n"); goto done; } if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto done; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto done; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto done; } } pfrom = (struct to_body*)msg->from->parsed; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto done; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); goto done; } pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); goto done; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no to tag value present\n"); goto done; } hentity->call_id= msg->callid->body; hentity->to_tag= pto->tag_value; hentity->from_tag= pfrom->tag_value; } /* extract the other necesary information for inserting a new record */ if(ps->rpl->expires && msg->expires->body.len > 0) { if (!msg->expires->parsed && (parse_expires(msg->expires) < 0)) { LM_ERR("cannot parse Expires header\n"); goto done; } lexpire = ((exp_body_t*)msg->expires->parsed)->val; LM_DBG("lexpire= %d\n", lexpire); } if(ps->code >= 300 ) { /* if an error code and a stored dialog delete it and try to send a subscription with type= INSERT_TYPE, else return*/ if(!initial_request) { subs_info_t subs; lock_get(&HashT->p_records[hentity->hash_index].lock); presentity = get_htable_safe(hentity->hash_index, hentity->local_index); if(presentity) { hentity->event= presentity->event; delete_htable_safe(presentity, hentity->hash_index); lock_release(&HashT->p_records[hentity->hash_index].lock); } lock_release(&HashT->p_records[hentity->hash_index].lock); memset(&subs, 0, sizeof(subs_info_t)); subs.pres_uri= hentity->pres_uri; subs.to_uri = hentity->to_uri; subs.watcher_uri= hentity->watcher_uri; subs.contact= &hentity->contact; if(hentity->remote_contact.s) subs.remote_target= &hentity->remote_contact; if(hentity->desired_expires== 0) subs.expires= -1; else if(hentity->desired_expires< (int)time(NULL)) subs.expires= 0; else subs.expires= hentity->desired_expires- (int)time(NULL)+ 3; subs.flag= INSERT_TYPE; subs.source_flag= flag; subs.event= hentity->event; subs.id= hentity->id; subs.outbound_proxy= hentity->outbound_proxy; subs.extra_headers= &hentity->extra_headers; subs.cb_param= hentity->cb_param; if(send_subscribe(&subs)< 0) { LM_ERR("when trying to send SUBSCRIBE\n"); goto done; } } goto done; } /*if a 2XX reply handle the two cases- an existing dialog and a new one*/ /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); goto error; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); goto error; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); goto error; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; if(!initial_request) { /* do not delete the dialog - allow Notifies to be recognized as * inside a known dialog */ if (lexpire == 0) lexpire = 5; LM_DBG("*** Update expires\n"); update_htable(hentity->hash_index, hentity->local_index, lexpire, NULL, &contact); goto done; } /* if a new dialog -> insert */ if(lexpire== 0) { LM_DBG("expires= 0: no not insert\n"); goto done; } if( msg->cseq==NULL || msg->cseq->body.s==NULL) { LM_ERR("cannot parse cseq header\n"); goto done; } if( str2int( &(get_cseq(msg)->number), &cseq)< 0) { LM_ERR("while converting str to int\n"); goto done; } /*process record route and add it to a string*/ if (msg->record_route!=NULL) { rt = print_rr_body(msg->record_route, &record_route, 1, 0); if(rt != 0) { LM_ERR("parsing record route [%d]\n", rt); record_route.s=NULL; record_route.len=0; } } size= sizeof(ua_pres_t)+ 2*sizeof(str)+(hentity->pres_uri->len+ pto->uri.len+ pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len +msg->callid->body.len+ record_route.len+ hentity->contact.len+ hentity->id.len )*sizeof(char); presentity= (ua_pres_t*)shm_malloc(size); if(presentity== NULL) { LM_ERR("no more share memory\n"); if(record_route.s) pkg_free(record_route.s); goto done; } memset(presentity, 0, size); size= sizeof(ua_pres_t); presentity->pres_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->pres_uri->s= (char*)presentity+ size; memcpy(presentity->pres_uri->s, hentity->pres_uri->s, hentity->pres_uri->len); presentity->pres_uri->len= hentity->pres_uri->len; size+= hentity->pres_uri->len; presentity->to_uri.s= (char*)presentity+ size; memcpy(presentity->to_uri.s, pto->uri.s, pto->uri.len); presentity->to_uri.len= pto->uri.len; size+= pto->uri.len; presentity->watcher_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->watcher_uri->s= (char*)presentity+ size; memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len); presentity->watcher_uri->len= pfrom->uri.len; size+= pfrom->uri.len; presentity->call_id.s= (char*)presentity + size; memcpy(presentity->call_id.s,msg->callid->body.s, msg->callid->body.len); presentity->call_id.len= msg->callid->body.len; size+= presentity->call_id.len; presentity->to_tag.s= (char*)presentity + size; memcpy(presentity->to_tag.s,pto->tag_value.s, pto->tag_value.len); presentity->to_tag.len= pto->tag_value.len; size+= pto->tag_value.len; presentity->from_tag.s= (char*)presentity + size; memcpy(presentity->from_tag.s,pfrom->tag_value.s, pfrom->tag_value.len); presentity->from_tag.len= pfrom->tag_value.len; size+= pfrom->tag_value.len; if(record_route.len && record_route.s) { presentity->record_route.s= (char*)presentity + size; memcpy(presentity->record_route.s, record_route.s, record_route.len); presentity->record_route.len= record_route.len; size+= record_route.len; pkg_free(record_route.s); } presentity->contact.s= (char*)presentity + size; memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len); presentity->contact.len= hentity->contact.len; size+= hentity->contact.len; if(hentity->id.s) { presentity->id.s=(char*)presentity+ size; memcpy(presentity->id.s, hentity->id.s, hentity->id.len); presentity->id.len= hentity->id.len; size+= presentity->id.len; } if(hentity->extra_headers.s && hentity->extra_headers.len) { presentity->extra_headers.s= (char*)shm_malloc(hentity->extra_headers.len* sizeof(char)); if(presentity->extra_headers.s== NULL) { ERR_MEM(SHARE_MEM); } memcpy(presentity->extra_headers.s, hentity->extra_headers.s, hentity->extra_headers.len); presentity->extra_headers.len= hentity->extra_headers.len; } /* write the remote contact filed */ presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(presentity->remote_contact.s== NULL) { ERR_MEM(SHARE_MEM); } memcpy(presentity->remote_contact.s, contact.s, contact.len); presentity->remote_contact.len= contact.len; presentity->event|= hentity->event; presentity->flag= hentity->flag; presentity->etag.s= NULL; presentity->cseq= cseq; presentity->desired_expires= hentity->desired_expires; presentity->expires= lexpire+ (int)time(NULL); if(BLA_SUBSCRIBE & presentity->flag) { LM_DBG("BLA_SUBSCRIBE FLAG inserted\n"); } LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n", presentity->watcher_uri->len, presentity->watcher_uri->s, presentity->pres_uri->len, presentity->pres_uri->s); insert_htable(presentity); done: if(hentity->ua_flag == REQ_OTHER) { hentity->flag= flag; run_pua_callbacks( hentity, msg); } error: if(hentity) { if(presentity) { if(presentity->extra_headers.s) shm_free(presentity->extra_headers.s); if(presentity->remote_contact.s) shm_free(presentity->remote_contact.s); } shm_free(hentity); hentity= NULL; } return; }
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; }
void reg_tm_cback(struct cell *t, int type, struct tmcb_params *ps) { struct sip_msg *msg; reg_tm_cb_t *cb_param; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; time_t now; if(ps==NULL || ps->rpl==NULL) { LM_ERR("wrong ps parameter\n"); return; } if(ps->param==NULL || *ps->param==NULL) { LM_ERR("null callback parameter\n"); return; } cb_param = (reg_tm_cb_t *)*ps->param; if(cb_param->uac == NULL) { LM_ERR("null record\n"); return; } statuscode = ps->code; now = time(0); LM_DBG("tm [%p] notification cb for %s [%d] reply at [%d]\n", t, (ps->rpl==FAKED_REPLY)?"FAKED_REPLY":"", statuscode, (unsigned int)now); if(statuscode<200) return; lock_get(®_htable[cb_param->hash_index].lock); rec = reg_htable[cb_param->hash_index].first; while(rec) { if (rec==cb_param->uac) { break; } rec = rec->next; } if(!rec) { LM_ERR("record [%p] not found on hash index [%d]\n", cb_param->uac, cb_param->hash_index); lock_release(®_htable[cb_param->hash_index].lock); return; } reg_print_record(rec); switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } else { rec->expires = exp; } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_ERR("Wrong credentials for \n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } lock_release(®_htable[cb_param->hash_index].lock); return; done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; lock_release(®_htable[cb_param->hash_index].lock); return; }
static int l_siplua_getContact(lua_State *L) { struct sipapi_object *o; struct hdr_field *_p; contact_t *_c; int n = 1; int found_hf_no_star = 0; int found_hf_star = 0; int expires; o = luaL_checkudata(L, 1, "siplua.api"); if (!o->msg->contact) { lua_pushnil(L); return 1; } lua_newtable(L); _p = o->msg->contact; for (_p = o->msg->contact; _p; _p = _p->next) { /* siplua_log(L_DBG, "l_siplua_getContact _p/%p", _p); */ if (_p->type == HDR_CONTACT_T) { if (parse_contact(_p) < 0) { return luaL_error(L, "failed to parse Contact body"); } if (((contact_body_t *)_p->parsed)->star) { lua_pushinteger(L, n++); lua_newtable(L); lua_pushstring(L, "star"); lua_pushboolean(L, 1); lua_rawset(L, -3); lua_pushstring(L, "name"); lua_pushstring(L, "*"); lua_rawset(L, -3); lua_pushstring(L, "uri"); lua_pushstring(L, "*"); lua_rawset(L, -3); lua_rawset(L, -3); found_hf_star = 1; } for (_c = ((contact_body_t *)_p->parsed)->contacts; _c; _c = _c->next) { /* siplua_log(L_DBG, "l_siplua_getContact _c/%p", _c); */ if (!_c) break; lua_pushinteger(L, n++); lua_newtable(L); lua_pushstring(L, "name"); lua_pushlstring(L, _c->name.s, _c->name.len); lua_rawset(L, -3); lua_pushstring(L, "uri"); lua_pushlstring(L, _c->uri.s, _c->uri.len); lua_rawset(L, -3); /* siplua_log(L_DBG, "contact q/%p expires/%p", _c->q, _c->expires); */ if (_c->q) { lua_pushstring(L, "q"); lua_pushlstring(L, _c->q->body.s, _c->q->body.len); lua_pushnumber(L, lua_tonumber(L, -1)); lua_remove(L, -2); lua_rawset(L, -3); } if (_c->expires) { lua_pushstring(L, "expires"); lua_pushlstring(L, _c->expires->body.s, _c->expires->body.len); lua_pushnumber(L, lua_tonumber(L, -1)); lua_remove(L, -2); lua_rawset(L, -3); } lua_rawset(L, -3); found_hf_no_star = 1; } } } if (found_hf_star) { if (found_hf_no_star) { lua_remove(L, -1); lua_pushnil(L); siplua_log(L_DBG, "l_siplua_getContact Found Contact HF with both star and no star."); } else { /* siplua_log(L_DBG, "BEFORE"); */ expires = sipapi_getExpires(o->msg); /* siplua_log(L_DBG, "AFTER"); */ if (expires != 0 && expires != -1) { lua_remove(L, -1); lua_pushnil(L); siplua_log(L_DBG, "l_siplua_getContact Found Contact HF star with unvalid expires."); } } } /* siplua_log(L_DBG, "l_siplua_getContact returned."); */ return 1; }
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; }
/* returns : -1 - error * 0 - ok, but no contact added * n - ok and n contacts added */ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl, long max, struct acc_param *reason, unsigned int bflags) { static struct sip_msg dup_rpl; static contact_t *scontacts[MAX_CONTACTS_PER_REPLY]; static qvalue_t sqvalues[MAX_CONTACTS_PER_REPLY]; struct hdr_field *hdr; struct hdr_field *contact_hdr; contact_t *contacts; int n,i; int added; int dup; int ret; /* dup can be: * 0 - sh reply but nothing duplicated * 1 - sh reply but only contact body parsed * 2 - sh reply and contact header and body parsed * 3 - private reply */ dup = 0; /* sh_rpl not duplicated */ ret = 0; /* success and no contact added */ contact_hdr = 0; if (sh_rpl==0 || sh_rpl==FAKED_REPLY) return 0; if (sh_rpl->contact==0) { /* contact header is not parsed */ if ( sh_rpl->msg_flags&FL_SHM_CLONE ) { /* duplicate the reply into private memory to be able * to parse it and afterwards to free the parsed mems */ memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) ); dup = 2; /* ok -> force the parsing of contact header */ if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) { LM_ERR("dup_rpl parse failed\n"); ret = -1; goto restore; } if (dup_rpl.contact==0) { LM_DBG("contact hdr not found in dup_rpl\n"); goto restore; } contact_hdr = dup_rpl.contact; } else { dup = 3; /* force the parsing of contact header */ if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) { LM_ERR("sh_rpl parse failed\n"); ret = -1; goto restore; } if (sh_rpl->contact==0) { LM_DBG("contact hdr not found in sh_rpl\n"); goto restore; } contact_hdr = sh_rpl->contact; } } else { contact_hdr = sh_rpl->contact; } /* parse the body of contact headers */ hdr = contact_hdr; while(hdr) { if (hdr->type == HDR_CONTACT_T) { if (hdr->parsed==0) { if(parse_contact(hdr) < 0) { LM_ERR("failed to parse Contact body\n"); ret = -1; goto restore; } if (dup==0) dup = 1; } } hdr = hdr->next; } /* we have the contact header and its body parsed -> sort the contacts * based on the q value */ contacts = ((contact_body_t*)contact_hdr->parsed)->contacts; if (contacts==0) { LM_DBG("contact hdr has no contacts\n"); goto restore; } n = sort_contacts(contact_hdr, scontacts, sqvalues); if (n==0) { LM_DBG("no contacts left after filtering\n"); goto restore; } i=0; /* more branches than requested in the parameter * - add only the last ones from sorted array, * because the order is by increasing q */ if (max!=-1 && n>max) i = n - max; added = 0; /* add the sortet contacts as branches in dset and log this! */ for ( ; i<n ; i++ ) { LM_DBG("adding contact <%.*s>\n", scontacts[i]->uri.len, scontacts[i]->uri.s); if(sruid_next(&_redirect_sruid)==0) { if(append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i], bflags, 0, &_redirect_sruid.uid, 0, &_redirect_sruid.uid, &_redirect_sruid.uid)<0) { LM_ERR("failed to add contact to dset\n"); } else { added++; if (rd_acc_fct!=0 && reason) { /* log the redirect */ req->new_uri = scontacts[i]->uri; //FIXME rd_acc_fct( req, (char*)reason, acc_db_table); } } } else { LM_ERR("failed to generate ruid for a new branch\n"); } } ret = (added==0)?-1:added; restore: if (dup==1) { free_contact( (contact_body_t**)(void*)(&contact_hdr->parsed) ); } else if (dup==2) { /* are any new headers found? */ if (dup_rpl.last_header!=sh_rpl->last_header) { /* identify in the new headere list (from dup_rpl) * the sh_rpl->last_header and start remove everything after */ hdr = sh_rpl->last_header; free_hdr_field_lst(hdr->next); hdr->next=0; } } return ret; }
/* * This function encodes an arbitrary header into a chunk of bytes, * ready to be sent to the Application Server. * * The header codes start with this encoded-bytes: * 2: SIP-MSG-START based pointer to the header (including header name) * 2: length of the header * 1: length of the header name */ int encode_header(struct sip_msg *sipmsg,struct hdr_field *hdr,unsigned char *payload,int paylen) { int len=0; unsigned int integer,*methods=0; char *hdrstart,*tmp; unsigned short int ptr; struct to_body *tobody=0; struct via_body *viabody=0; struct cseq_body *cseqbody=0; char *msg,*myerror; int mlen; msg=sipmsg->buf; mlen=sipmsg->len; hdrstart = hdr->name.s; if(hdrstart-msg<0){ LM_ERR("header(%.*s) does not belong to sip_msg(hdrstart<msg)\n", hdr->name.len,hdr->name.s); return -1; } ptr=htons((short int)(hdrstart-msg)); if((hdrstart-msg)>mlen){ LM_ERR("out of the sip_msg bounds (%d>%d)\n",ntohs(ptr),mlen); return -1; } if(hdr->len>(1<<16)){ LM_ERR("length of header too long\n"); return -1; } memcpy(payload,&ptr,2); ptr=htons((short int)(hdr->len)); memcpy(payload+HEADER_LEN_IDX,&ptr,2); payload[HEADER_NAME_LEN_IDX]=(unsigned char)hdr->name.len; switch(hdr->type){ case HDR_FROM_T: case HDR_TO_T: case HDR_REFER_TO_T: case HDR_RPID_T: if(!hdr->parsed){ if((tobody=pkg_malloc(sizeof(struct to_body)))==0){ myerror="Out of memory !!\n"; goto error; } parse_to(hdr->body.s,hdr->body.s+hdr->body.len+1,tobody); if (tobody->error == PARSE_ERROR) { myerror="bad (REFER,TO,FROM,RPID) header\n"; pkg_free(tobody); return 5; goto error; } hdr->parsed=(struct to_body*)tobody; }else tobody=(struct to_body*)hdr->parsed; if((len=encode_to_body(hdr->name.s,hdr->len,tobody,payload+5))<0){ myerror="parsing from or to header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTACT_T: if(!hdr->parsed) if(parse_contact(hdr)<0){ myerror="parsing contact\n"; goto error; } if((len=encode_contact_body(hdr->name.s,hdr->len,(contact_body_t*)hdr->parsed,payload+5))<0){ myerror="encoding contact header\n"; goto error; }else{ return 5+len; } break; case HDR_ROUTE_T: case HDR_RECORDROUTE_T: if(!hdr->parsed) if(parse_rr(hdr)<0){ myerror="encoding route or recordroute\n"; goto error; } if((len=encode_route_body(hdr->name.s,hdr->len,(rr_t*)hdr->parsed,payload+5))<0){ myerror="encoding route or recordroute header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTLENGTH_T: if(!hdr->parsed){ tmp=parse_content_length(hdr->body.s,hdr->body.s+hdr->body.len+1,(int*)&integer); if (tmp==0){ myerror="bad content_length header\n"; goto error; } hdr->parsed=(void*)(long)integer; } if((len=encode_contentlength(hdr->name.s,hdr->len,(long int)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding content-length header\n"; goto error; }else{ return 5+len; } break; case HDR_VIA_T: if(!hdr->parsed){ if((viabody=pkg_malloc(sizeof(struct via_body)))==0){ myerror="out of memory\n"; goto error; } memset(viabody,0,sizeof(struct via_body)); if(parse_via(hdr->body.s,hdr->body.s+hdr->body.len+1,viabody)==0){ myerror="encoding via \n"; goto error; } hdr->parsed=viabody; } if((len=encode_via_body(hdr->name.s,hdr->len,(struct via_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_ACCEPT_T: if(!hdr->parsed){ if(parse_accept_hdr(sipmsg)<0){ return 5; } } if((len=encode_accept(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTTYPE_T: if(!hdr->parsed){ if(parse_content_type_hdr(sipmsg)<0){ myerror="encoding content-type header\n"; goto error; } } if((len=encode_content_type(hdr->name.s,hdr->len,(unsigned int)get_content_type(sipmsg),(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CSEQ_T: if(!hdr->parsed){ if((cseqbody=pkg_malloc(sizeof(struct cseq_body)))==0){ myerror="out of memory\n"; goto error; } memset(cseqbody,0,sizeof(struct cseq_body)); if(parse_cseq(hdr->name.s,hdr->body.s+hdr->body.len+1,cseqbody)==0){ myerror="encoding cseq header\n"; goto error; } hdr->parsed=cseqbody; } if((len=encode_cseq(hdr->name.s,hdr->len,(struct cseq_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_EXPIRES_T: if(!hdr->parsed){ if(parse_expires(hdr)<0){ myerror="encoding expires header\n"; goto error; } } if((len=encode_expires(hdr->name.s,hdr->len,(exp_body_t *)hdr->parsed,payload+5))<0){ myerror="encoding expires header\n"; goto error; }else{ return 5+len; } break; case HDR_ALLOW_T: if(!hdr->parsed){ if((methods=pkg_malloc(sizeof(unsigned int)))==0){ myerror="out of memory\n"; goto error; } *methods=0; if(parse_methods(&hdr->body,methods)!=0){ myerror="encoding allow header\n"; pkg_free(methods); return 5; /*goto error;*/ } hdr->parsed=methods; } if((len=encode_allow(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; case HDR_AUTHORIZATION_T: case HDR_PROXYAUTH_T: if(!hdr->parsed){ if(parse_credentials(hdr)<0){ myerror="encoding a digest header\n"; goto error; } } if((len=encode_digest(hdr->name.s,hdr->len,(dig_cred_t*)(&(((auth_body_t*)hdr->parsed)->digest)),payload+5))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; default: return 5; } return 1; error: if(tobody) pkg_free(tobody); if(cseqbody) pkg_free(cseqbody); if(viabody) free_via_list(viabody); if(methods) pkg_free(methods); LM_ERR("%s",myerror); return -1; }
int decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2) { contact_body_t *cb; contact_t *c; str* uri; str newUri; char separator; int res; if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact== NULL) )) { LOG(L_ERR,"ERROR: decode_contact_header: no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; // we visit each contact if (c != NULL) { uri = &c->uri; res = decode_uri (uri, separator, &newUri, 0); if (res != 0) { LOG (L_ERR,"ERROR: decode_contact_header:Failed decoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0) { LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n"); return -2; } #ifdef DECODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = &c->uri; res = decode_uri (uri, separator, &newUri, 0); if (res != 0) { LOG (L_ERR,"ERROR: decode_contact: Failed decoding contact.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0) { LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n"); return -3; } } // end while #endif } // if c!= NULL } // end if else // after parsing still NULL { LOG(L_ERR,"ERROR: decode_contact: Unable to parse Contact header\n"); return -4; } return 1; }
//#define DEBUG int encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip) { contact_body_t *cb; contact_t *c; str uri; str newUri; int res; char separator; /* * I have a list of contacts in contact->parsed which is of type contact_body_t * inside i have a contact->parsed->contact which is the head of the list of contacts * inside it is a * str uri; * struct contact *next; * I just have to visit each uri and encode each uri according to a scheme */ #ifdef DEBUG fprintf (stdout,"---START--------ENCODE CONTACT-----------------\n"); fprintf (stdout,"%.*s\n",50,msg->buf); #endif if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact == NULL) )) { LOG(L_ERR,"ERROR: encode_contact: no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; #ifdef DEBUG fprintf (stdout,"Using separator %c\n",separator); #endif if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; /* we visit each contact */ if (c != NULL) { uri = c->uri; #ifdef DEBUG fprintf (stdout, "olduri.s=[%.*s]\n", uri.len, uri.s); #endif res = encode_uri (uri, encoding_prefix, public_ip,separator, &newUri); if (res != 0) { LOG (L_ERR,"ERROR: encode_contact: Failed encoding contact.Code %d\n", res); #ifdef DEBUG fprintf (stdout, "Encoding uri failed with code %d\n",res); #endif #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n"); return -2; } #ifdef DEBUG if (res == 0) fprintf (stdout, "newuri.s=[%.*s]\nnewlen=%d\n", newUri.len, newUri.s,newUri.len); #endif /* encoding next contacts too?*/ #ifdef ENCODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = c->uri; res = encode_uri (uri, encoding_prefix,public_ip,separator,&newUri); if (res != 0) { LOG(L_ERR,"ERROR: encode_contact: Failed encode_uri.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len)< 0) { LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n"); return -3; } } /* while */ #endif /* ENCODE_ALL_CONTACTS */ } /* if c != NULL */ } /* end if */ else /* after parsing still NULL */ { LOG(L_ERR,"ERROR: encode_contact: Unable to parse Contact header\n"); #ifdef DEBUG printf("ERROR: encode_contact: Unable to parse Contact header\n"); #endif return -4; } #ifdef DEBUG fprintf (stdout,"---END--------ENCODE CONTACT-----------------\n"); #endif return 1; }
int run_reg_tm_cback(void *e_data, void *data, void *r_data) { struct sip_msg *msg; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec = (reg_record_t*)e_data; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data; struct cell *t; struct tmcb_params *ps; time_t now; reg_tm_cb_t *cb_param; cb_param = tm_cback_data->cb_param; if (rec!=cb_param->uac) { /* no action on current list elemnt */ return 0; /* continue list traversal */ } t = tm_cback_data->t; ps = tm_cback_data->ps; now = tm_cback_data->now; reg_print_record(rec); if (ps->rpl==FAKED_REPLY) memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union)); else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC) rec->td.forced_to_su = t->uac[0].request.dst.to; statuscode = ps->code; switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; if (exp) rec->expires = exp; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_WARN("Wrong credentials for [%.*s]\n", rec->td.rem_uri.len, rec->td.rem_uri.s); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } pkg_free(new_hdr->s); new_hdr->s = NULL; new_hdr->len = 0; break; case 423: /* Interval Too Brief */ msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (0 == parse_min_expires(msg)) { rec->expires = (unsigned int)(long)msg->min_expires->parsed; if(send_register(cb_param->hash_index, rec, NULL)==1) rec->state = REGISTERING_STATE; else rec->state = INTERNAL_ERROR_STATE; } else { rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } break; case 408: /* Interval Too Brief */ rec->state = REGISTER_TIMEOUT_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } /* action successfuly completed on current list element */ return 1; /* exit list traversal */ done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; return -1; /* exit list traversal */ }
/* * Test of REGISTER messages. Creates To-Contact pairs and compares them * against rules in allow and deny files passed as parameters. The function * iterates over all Contacts and creates a pair with To for each contact * found. That allows to restrict what IPs may be used in registrations, for * example */ static int check_register(struct sip_msg* msg, int idx) { int len; static char to_str[EXPRESSION_LENGTH + 1]; char* contact_str; contact_t* c; /* turn off control, allow any routing */ if ((!allow[idx].rules) && (!deny[idx].rules)) { LM_DBG("no rules => allow any registration\n"); return 1; } /* * Note: We do not parse the whole header field here although the message can * contain multiple Contact header fields. We try contacts one by one and if one * of them causes reject then we don't look at others, this could improve performance * a little bit in some situations */ if (parse_headers(msg, HDR_TO_F | HDR_CONTACT_F, 0) == -1) { LM_ERR("failed to parse headers\n"); return -1; } if (!msg->to) { LM_ERR("To or Contact not found\n"); return -1; } if (!msg->contact) { /* REGISTER messages that contain no Contact header field * are allowed. Such messages do not modify the contents of * the user location database anyway and thus are not harmful */ LM_DBG("no Contact found, allowing\n"); return 1; } /* Check if the REGISTER message contains start Contact and if * so then allow it */ if (parse_contact(msg->contact) < 0) { LM_ERR("failed to parse Contact HF\n"); return -1; } if (((contact_body_t*)msg->contact->parsed)->star) { LM_DBG("* Contact found, allowing\n"); return 1; } len = ((struct to_body*)msg->to->parsed)->uri.len; if (len > EXPRESSION_LENGTH) { LM_ERR("To header field is too long: %d chars\n", len); return -1; } strncpy(to_str, ((struct to_body*)msg->to->parsed)->uri.s, len); to_str[len] = '\0'; if (contact_iterator(&c, msg, 0) < 0) { return -1; } while(c) { contact_str = get_plain_uri(&c->uri); if (!contact_str) { LM_ERR("can't extract plain Contact URI\n"); return -1; } LM_DBG("looking for To: %s Contact: %s\n", to_str, contact_str); /* rule exists in allow file */ if (search_rule(allow[idx].rules, to_str, contact_str)) { if (check_all_branches) goto skip_deny; } /* rule exists in deny file */ if (search_rule(deny[idx].rules, to_str, contact_str)) { LM_DBG("deny rule found => Register denied\n"); return -1; } skip_deny: if (contact_iterator(&c, msg, c) < 0) { return -1; } } LM_DBG("no contact denied => Allowed\n"); return 1; }
/* builds digest string of msg Return value: 1: success 0: else digestString must point to an array with at least MAX_DIGEST bytes */ static int makeDigestString(char * digestString, char * dateHF, struct sip_msg * msg) { struct to_body * from = NULL; struct to_body * to = NULL; struct cseq_body * cseq = NULL; struct hdr_field * date = NULL; contact_t * contact = NULL; unsigned int l; str tmp; if(!digestString || !msg) { LM_ERR("not all parameters set\n"); return 0; } l = 0; /* ###from### */ if(parse_from_header(msg) != 0) { LM_ERR("error parsing from header\n"); return 0; } from = get_from(msg); if(!from) { LM_ERR("error getting from header\n"); return 0; } if (l+from->uri.len+1>MAX_DIGEST) { LM_ERR("buffer to short 1\n"); return 0; } memcpy( digestString+l, from->uri.s, from->uri.len); l += from->uri.len; *(digestString+(l++)) = '|'; /* ###To### */ to = get_to(msg); if(!to) { LM_ERR("error getting to header\n"); return 0; } if (l+to->uri.len+1>MAX_DIGEST) { LM_ERR("buffer to short 2\n"); return 0; } memcpy( digestString+l, to->uri.s, to->uri.len); l += to->uri.len; *(digestString+(l++)) = '|'; /* ###callid### */ if(!msg->callid) { LM_ERR("error getting callid header\n"); return 0; } if (l+msg->callid->body.len+1>MAX_DIGEST) { LM_ERR("buffer to short 3\n"); return 0; } memcpy( digestString+l, msg->callid->body.s, msg->callid->body.len); l += msg->callid->body.len; *(digestString+(l++)) = '|'; /* ###CSeq### */ cseq = (struct cseq_body *)msg->cseq->parsed; if (!cseq) { LM_ERR("error getting cseq header\n"); return 0; } tmp.s = cseq->number.s; tmp.len = cseq->number.len; /* strip leading zeros */ while((*(tmp.s) == '0') && (tmp.len > 1)) { (tmp.s)++; (tmp.len)--; } if (l+tmp.len+cseq->method.len+2>MAX_DIGEST) { LM_ERR("buffer to short 4\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = ' '; memcpy( digestString+l, cseq->method.s, cseq->method.len); l += cseq->method.len; *(digestString+(l++)) = '|'; /* ###Date### */ if(!dateHF) { /* Date header field is taken from msg: verifier */ date = get_header_by_static_name(msg,"Date"); if (!date) { LM_ERR("error getting date header\n"); return 0; } tmp = date->body; } else { /* Date header field is taken from dateHF: authentication service */ tmp.s = dateHF; tmp.len = strlen(tmp.s); } if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 5\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = '|'; /* ###Contact### */ if(msg->contact) { if(parse_contact(msg->contact) != 0) { LM_ERR("error parsing contact header\n"); return 0; } /* first contact in list */ contact = ((contact_body_t *)(msg->contact->parsed))->contacts; tmp = contact->uri; } else { tmp.len = 0; tmp.s = 0; } if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 6\n"); return 0; } if (tmp.len) { memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; } *(digestString+(l++)) = '|'; /* ###body### */ if ( get_body(msg,&tmp)!=0 ) { LM_ERR("failed to inspect body\n"); return 0; } if (tmp.len != 0) { if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 7\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = 0; } LM_DBG("Digest-String=>%s<\n", digestString); return 1; }
void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) { char *uuid; str suuid; reg_uac_t *ri = NULL; contact_t* c; int expires; struct sip_uri puri; struct hdr_field *hdr; HASHHEX response; str *new_auth_hdr = NULL; static struct authenticate_body auth; struct uac_credential cred; char b_ruri[MAX_URI_SIZE]; str s_ruri; #ifdef UAC_OLD_AUTH char b_turi[MAX_URI_SIZE]; str s_turi; #endif char b_hdrs[MAX_UACH_SIZE]; str s_hdrs; uac_req_t uac_r; str method = {"REGISTER", 8}; int ret; dlg_t tmdlg; if(ps->param==NULL || *ps->param==0) { LM_DBG("uuid not received\n"); return; } uuid = *((char**)ps->param); LM_DBG("completed with status %d [uuid: %s]\n", ps->code, uuid); suuid.s = uuid; suuid.len = strlen(suuid.s); ri = reg_ht_get_byuuid(&suuid); if(ri==NULL) { LM_DBG("no user with uuid %s\n", uuid); goto done; } if(ps->code == 200) { if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto error; } if (ps->rpl->contact==NULL) { LM_ERR("no Contact found\n"); goto error; } if (parse_contact(ps->rpl->contact) < 0) { LM_ERR("failed to parse Contact HF\n"); goto error; } if (((contact_body_t*)ps->rpl->contact->parsed)->star) { LM_DBG("* Contact found\n"); goto done; } if (contact_iterator(&c, ps->rpl, 0) < 0) goto done; while(c) { if(parse_uri(c->uri.s, c->uri.len, &puri)!=0) { LM_ERR("failed to parse c-uri\n"); goto error; } if(suuid.len==puri.user.len && (strncmp(puri.user.s, suuid.s, suuid.len)==0)) { /* calculate expires */ expires=0; if(c->expires==NULL || c->expires->body.len<=0) { if(ps->rpl->expires!=NULL && ps->rpl->expires->body.len>0) expires = atoi(ps->rpl->expires->body.s); } else { str2int(&c->expires->body, (unsigned int*)(&expires)); } ri->timer_expires = ri->timer_expires + expires; ri->flags |= UAC_REG_ONLINE; goto done; } if (contact_iterator(&c, ps->rpl, c) < 0) { LM_DBG("local contact not found\n"); goto done; } } } if(ps->code == 401 || ps->code == 407) { if(ri->flags & UAC_REG_AUTHSENT) { LM_ERR("authentication failed for <%.*s>\n", ri->l_uuid.len, ri->l_uuid.s); goto error; } hdr = get_autenticate_hdr(ps->rpl, ps->code); if (hdr==0) { LM_ERR("failed to extract authenticate hdr\n"); goto error; } LM_DBG("auth header body [%.*s]\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body(&hdr->body, &auth)<0) { LM_ERR("failed to parse auth hdr body\n"); goto error; } if (ri->realm.len>0) { /* only check if realms match if it is non-empty */ if(auth.realm.len!=ri->realm.len || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0) { LM_ERR("realms do not match. requested realm: [%.*s]\n", auth.realm.len, auth.realm.s); goto error; } } cred.realm = auth.realm; cred.user = ri->auth_username; cred.passwd = ri->auth_password; cred.next = NULL; snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s", ri->r_domain.len, ri->r_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); do_uac_auth(&method, &s_ruri, &cred, &auth, response); new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred, &auth, response); if (new_auth_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } #ifdef UAC_OLD_AUTH snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s", ri->r_username.len, ri->r_username.s, ri->r_domain.len, ri->r_domain.s); s_turi.s = b_turi; s_turi.len = strlen(s_turi.s); #endif snprintf(b_hdrs, MAX_UACH_SIZE, "Contact: <sip:%.*s@%.*s>\r\n" "Expires: %d\r\n" "%.*s", ri->l_uuid.len, ri->l_uuid.s, reg_contact_addr.len, reg_contact_addr.s, ri->expires, new_auth_hdr->len, new_auth_hdr->s); s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s); pkg_free(new_auth_hdr->s); memset(&uac_r, 0, sizeof(uac_r)); if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0) { LM_ERR("failed to build tm dialog\n"); goto error; } tmdlg.rem_target = s_ruri; if(ri->auth_proxy.len) tmdlg.dst_uri = ri->auth_proxy; uac_r.method = &method; uac_r.headers = &s_hdrs; uac_r.dialog = &tmdlg; uac_r.cb_flags = TMCB_LOCAL_COMPLETED; /* Callback function */ uac_r.cb = uac_reg_tm_callback; /* Callback parameter */ uac_r.cbp = (void*)uuid; #ifdef UAC_OLD_AUTH ret = uac_tmb.t_request(&uac_r, /* UAC Req */ &s_ruri, /* Request-URI */ &s_turi, /* To */ &s_turi, /* From */ (ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */ ); #endif ret = uac_tmb.t_request_within(&uac_r); if(ret<0) { LM_ERR("failed to send request with authentication for [%.*s]", ri->l_uuid.len, ri->l_uuid.s); goto error; } ri->flags |= UAC_REG_AUTHSENT; return; } else { LM_ERR("got sip response %d while registering [%.*s]\n", ps->code, ri->l_uuid.len, ri->l_uuid.s); goto error; } error: ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT); if(reg_retry_interval) { ri->timer_expires = time(NULL) + reg_retry_interval; } else { ri->flags |= UAC_REG_DISABLED; counter_inc(regdisabled); } done: if(ri) ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT); shm_free(uuid); counter_inc(regactive); }
/* returns : -1 - error * 0 - ok, but no contact added * n - ok and n contacts added */ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl, long max, pv_elem_t *reason) { static struct sip_msg dup_rpl; static str scontacts[MAX_CONTACTS_PER_REPLY]; static qvalue_t sqvalues[MAX_CONTACTS_PER_REPLY]; struct hdr_field *hdr; struct hdr_field *contact_hdr; contact_t *contacts; str backup_uri; int n,i; int added; int dup; int ret; dup = 0; /* sh_rpl not duplicated */ ret = 0; /* success and no contact added */ contact_hdr = NULL; hdr = NULL; if (sh_rpl==0 || sh_rpl==FAKED_REPLY) return 0; if ( sh_rpl->msg_flags&FL_SHM_CLONE ) { /* duplicate the reply into private memory to be able * to parse it and after words to free the parsed mems */ memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) ); LM_DBG("duplicating shm reply\n"); dup = 1; /* ok -> force the parsing of contact header */ if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) { LM_ERR("dup_rpl parse failed\n"); ret = -1; goto restore; } if (dup_rpl.contact==0) { LM_DBG("contact hdr not found in dup_rpl\n"); goto restore; } contact_hdr = dup_rpl.contact; } else { /* parse directly the current copy */ /* force the parsing of contact header */ if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) { LM_ERR("sh_rpl parse failed\n"); ret = -1; goto restore; } if (sh_rpl->contact==0) { LM_DBG("contact hdr not found in sh_rpl\n"); goto restore; } contact_hdr = sh_rpl->contact; } /* iterate through all contact headers and extract the URIs */ for( n=0,hdr=contact_hdr ; hdr ; hdr=hdr->sibling ) { /* parse the body of contact header */ if (hdr->parsed==0) { if ( parse_contact(hdr)<0 ) { LM_ERR("contact hdr parse failed\n"); ret = -1; goto restore; } } /* we have the contact header and its body parsed -> sort the contacts * based on the q value */ contacts = ((contact_body_t*)hdr->parsed)->contacts; if (contacts==0) { LM_DBG("contact hdr has no contacts\n"); } else { sort_contacts( contacts, scontacts, sqvalues, &n); } /* clean currently added contact */ if (dup) free_contact( (contact_body_t**)(void*)(&hdr->parsed) ); } if (n==0) { LM_DBG("no contacts left after filtering\n"); goto restore; } /* to many branches ? */ if (max!=-1 && n>max) n = max; LM_DBG("%d contacts remaining after filtering and sorting\n",n); added = 0; /* add the sorted contacts as branches in dset and log this! */ for ( i=0 ; i<n ; i++ ) { LM_DBG("adding contact <%.*s>\n", scontacts[i].len, scontacts[i].s); if (i==0) { /* set RURI*/ if ( set_ruri( req, &scontacts[i])==-1 ) { LM_ERR("failed to set new RURI\n"); goto restore; } set_ruri_q(req, sqvalues[i]); } else { if (append_branch(0,&scontacts[i],0,0,sqvalues[i],0,0)<0) { LM_ERR("failed to add contact to dset\n"); continue; } } added++; if (rd_acc_fct!=0 && reason) { /* log the redirect */ backup_uri = req->new_uri; req->new_uri = scontacts[i]; //FIXME rd_acc_fct( req, (char*)reason, acc_db_table, NULL, NULL, NULL, NULL); req->new_uri = backup_uri; } } ret = (added==0)?-1:added; restore: if (dup==1) { /* free current parsed contact header */ if (hdr && hdr->parsed) free_contact( (contact_body_t**)(void*)(&hdr->parsed) ); /* are any new headers found? */ if (dup_rpl.last_header!=sh_rpl->last_header) { /* identify in the new headere list (from dup_rpl) * the sh_rpl->last_header and start remove everything after */ hdr = sh_rpl->last_header; free_hdr_field_lst(hdr->next); hdr->next=0; } } return ret; }
/*! * \brief Function that is registered as TM callback and called on replies * * Function that is registered as TM callback and called on replies. It * parses the reply and set the appropriate event. This is then used to * update the dialog state, run eventual dialog callbacks and save or * update the necessary informations about the dialog. * \see next_state_dlg * \param t transaction, unused * \param type type of the entered callback * \param param saved dialog structure in the callback */ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) { struct dlg_cell *dlg; struct dlg_cell_out *dlg_out = 0; int new_state, old_state, unref, event; str to_tag, to_uri; struct sip_msg *req = param->req; struct sip_msg *rpl = param->rpl; struct dlg_entry_out* dlg_entry_out = 0; if (t && t->fwded_totags) LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s); else LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type); dlg = (struct dlg_cell *) (*param->param); if (shutdown_done || dlg == 0) return; if (t) { dlg->transaction = t; } LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id); if (type == TMCB_RESPONSE_FWDED) { // The state does not change, but the msg is mutable in this callback LM_DBG("TMCB_RESPONSE_FWDED from TM received"); run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } if (type == TMCB_RESPONSE_OUT) { LM_DBG("TMCB_RESPONSE_OUT\n"); return; } if (type == TMCB_RESPONSE_READY) { if (rpl == FAKED_REPLY) { LM_DBG("Faked reply\n"); return; } // get to tag LM_DBG("Extracting to-tag from reply"); if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) { LM_ERR("bad reply or missing TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; } else { //populate to uri for this branch. to_uri = get_to(rpl)->uri; to_tag = get_to(rpl)->tag_value; if (to_tag.s == 0 || to_tag.len == 0) { LM_ERR("missing TAG param in TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; //Here we assume that the transaction module timer will remove any early dialogs return; } } LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s); } if (type == TMCB_DESTROY) event = DLG_EVENT_TDEL; else if (param->code < 200) event = DLG_EVENT_RPL1xx; else if (param->code < 300) event = DLG_EVENT_RPL2xx; else event = DLG_EVENT_RPL3xx; LM_DBG("Calling next_state_dlg and event is %i\n", event); next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag); if (type == TMCB_RESPONSE_READY) { LM_DBG("Checking if there is an existing dialog_out entry with same to-tag"); dlg_entry_out = &dlg->dlg_entry_out; lock_get(dlg->dlg_out_entries_lock); dlg_out = dlg_entry_out->first; LM_DBG("Scanning dlg_entry_out list for dlg_out"); while (dlg_out) { //Check if there is an already dialog_out entry with same To-tag if (dlg_out->to_tag.len == to_tag.len && memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) { //Found a dialog_out entry with same to_tag! LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s); break; } dlg_out = dlg_out->next; } lock_release(dlg->dlg_out_entries_lock); if (!dlg_out) { LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg); dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag); link_dlg_out(dlg, dlg_out, 0); /* save callee's cseq, caller cseq, callee contact and callee record route*/ if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) { LM_ERR("could not add further info to the dlg out\n"); } if (!dlg_out) { LM_ERR("failed to create new dialog out structure\n"); //TODO do something on this error! } } else { //This dlg_out already exists, update cseq and contact if present LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s); if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq || !rpl->cseq->parsed) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); } dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag)); /* extract the contact address to update if present*/ if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) { LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n"); } else if (parse_contact(rpl->contact) < 0 || ((contact_body_t *) rpl->contact->parsed)->contacts == NULL || ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) { LM_ERR("Can not update callee contact: bad Contact HDR\n"); } else { str contact; contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri; dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag)); } } } if (new_state == DLG_STATE_EARLY) { run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } LM_DBG("new state is %i and old state is %i\n", new_state, old_state); if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) { LM_DBG("dialog %p confirmed \n", dlg); //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction //(not before in order to absorb late in-early-dialog requests). //remove all other dlg_out objects if (dlg_out) { if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) { LM_ERR("failed to register deletion delay function\n"); LM_DBG("Removing all other DLGs"); dlg_remove_dlg_out(dlg_out, dlg, 0); } else { //mark the outs for deletion dlg_remove_dlg_out(dlg_out, dlg, 1); } } else { LM_ERR("There is no dlg_out structure - this is bad\n"); //TODO: add error handling here } /* set start time */ dlg->start_ts = (unsigned int) (time(0)); /* save the settings to the database, * if realtime saving mode configured- save dialog now * else: the next time the timer will fire the update*/ dlg->dflags |= DLG_FLAG_NEW; if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) { LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] " "with clid '%.*s' and tags '%.*s' \n", dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state, dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); } else { ref_dlg(dlg, 1); } run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); if (unref) unref_dlg(dlg, unref); return; } if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) { //This is a concurrently confirmed call LM_DBG("This is a concurrently confirmed call."); //Create a new Dialog ID token “X” //Not sure how to do this so just going to use existing Did and add an X character to it str new_did; create_concurrent_did(dlg, &new_did); //assign new did to the created or updated dialog_out entry. update_dlg_out_did(dlg_out, &new_did); //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires struct dlg_cell *new_dlg = 0; new_dlg = build_new_dlg(&(dlg->callid) /*callid*/, &(dlg->from_uri) /*from uri*/, &(dlg->from_tag)/*from_tag*/, &(dlg->req_uri) /*r-uri*/); //assign new did to dlg_in update_dlg_did(new_dlg, &new_did); if (new_dlg == 0) { LM_ERR("failed to create new dialog\n"); return; } //link the new_dlg with dlg_out object link_dlg_out(new_dlg, dlg_out, 0); } if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) { LM_DBG("dialog %p failed (negative reply)\n", dlg); /* dialog setup not completed (3456XX) */ run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); /* do unref */ if (unref) unref_dlg(dlg, unref); return; } if (unref) unref_dlg(dlg, unref); return; }
/* * Contact header field iterator, returns next contact if any, it doesn't * parse message header if not absolutely necessary */ int contact_iterator(contact_t** c, struct sip_msg* msg, contact_t* prev) { static struct hdr_field* hdr = 0; struct hdr_field* last; contact_body_t* cb; if (!msg) { LOG(L_ERR, "Invalid parameter value\n"); return -1; } if (!prev) { /* No pointer to previous contact given, find topmost * contact and return pointer to the first contact * inside that header field */ hdr = msg->contact; if (!hdr) { if (parse_headers(msg, HDR_CONTACT_F, 0) == -1) { LOG(L_ERR, "Error while parsing headers\n"); return -1; } hdr = msg->contact; } if (hdr) { if (parse_contact(hdr) < 0) { LOG(L_ERR, "Error while parsing Contact\n"); return -1; } } else { *c = 0; return 1; } cb = (contact_body_t*)hdr->parsed; *c = cb->contacts; return 0; } else { /* Check if there is another contact in the * same header field and if so then return it */ if (prev->next) { *c = prev->next; return 0; } if(hdr==NULL) { LOG(L_ERR, "contact iterator not initialized\n"); return -1; } /* Try to find and parse another Contact * header field */ last = hdr; hdr = hdr->next; /* Search another already parsed Contact * header field */ while(hdr && hdr->type != HDR_CONTACT_T) { hdr = hdr->next; } if (!hdr) { /* Look for another Contact HF in unparsed * part of the message header */ if (parse_headers(msg, HDR_CONTACT_F, 1) == -1) { LOG(L_ERR, "Error while parsing message header\n"); return -1; } /* Check if last found header field is Contact * and if it is not the same header field as the * previous Contact HF (that indicates that the previous * one was the last header field in the header) */ if ((msg->last_header->type == HDR_CONTACT_T) && (msg->last_header != last)) { hdr = msg->last_header; } else { *c = 0; return 1; } } if (parse_contact(hdr) < 0) { LOG(L_ERR, "Error while parsing Contact HF body\n"); return -1; } /* And return first contact within that * header field */ cb = (contact_body_t*)hdr->parsed; *c = cb->contacts; return 0; } }
int bla_handle_notify(struct sip_msg* msg, char* s1, char* s2) { publ_info_t publ; struct to_body *pto= NULL, TO, *pfrom = NULL; str body; ua_pres_t dialog; unsigned int expires= 0; struct hdr_field* hdr; str subs_state; str extra_headers= {0, 0}; static char buf[255]; str contact; memset(&publ, 0, sizeof(publ_info_t)); memset(&dialog, 0, sizeof(ua_pres_t)); if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } /* examine the to header */ if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_DBG("'To' header NOT parsed\n"); return -1; } pto = &TO; } publ.pres_uri= &pto->uri; dialog.watcher_uri= publ.pres_uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("NULL to_tag value\n"); return -1; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); return -1; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); return -1; } if (msg->from->parsed == NULL) { LM_DBG(" 'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_DBG(" ERROR cannot parse From header\n"); return -1; } } pfrom = (struct to_body*)msg->from->parsed; dialog.to_uri= pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); return -1; } if ( get_content_length(msg) == 0 ) { LM_DBG("content length= 0\n"); return 1; } else { body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); return -1; } body.len = get_content_length( msg ); if (!bla_body_is_valid( &body )) { LM_ERR("bad XML body!"); return -1; } } if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); return -1; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); return -1; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); return -1; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; dialog.to_tag= pfrom->tag_value; dialog.event= BLA_EVENT; dialog.flag= BLA_SUBSCRIBE; if(pua_is_dialog(&dialog)< 0) { LM_ERR("Notify in a non existing dialog\n"); return -2; } /* parse Subscription-State and extract expires if existing */ hdr = get_header_by_static_name( msg, "Subscription-State"); if( hdr==NULL ) { LM_ERR("No Subscription-State header found\n"); return -1; } subs_state= hdr->body; if(strncasecmp(subs_state.s, "terminated", 10)== 0) expires= 0; else { if(strncasecmp(subs_state.s, "active", 6)== 0 || strncasecmp(subs_state.s, "pending", 7)==0 ) { expires = DEFAULT_EXPIRES; char* sep= NULL; str exp= {NULL, 0}; sep= strchr(subs_state.s, ';'); if(sep) { if(strncasecmp(sep+1, "expires=", 8)== 0) { exp.s= sep+ 9; sep= exp.s; while((*sep)>='0' && (*sep)<='9') { sep++; exp.len++; } if( str2int(&exp, &expires)< 0) { LM_ERR("while parsing int\n"); return -1; } } } } else { LM_ERR("unknown Subscription-state token\n"); return -1; } } /* +2 for ": " between header name and value */ if ((header_name.len + 2 + contact.len + CRLF_LEN) >= sizeof(buf)) { LM_ERR("Sender header too large"); return -1; } /* build extra_headers with Sender*/ extra_headers.s= buf; memcpy(extra_headers.s, header_name.s, header_name.len); extra_headers.len= header_name.len; memcpy(extra_headers.s+extra_headers.len,": ",2); extra_headers.len+= 2; memcpy(extra_headers.s+ extra_headers.len, contact.s, contact.len); extra_headers.len+= contact.len; memcpy(extra_headers.s+ extra_headers.len, CRLF, CRLF_LEN); extra_headers.len+= CRLF_LEN; publ.id= contact; publ.body= &body; publ.source_flag= BLA_PUBLISH; publ.expires= expires; publ.event= BLA_EVENT; publ.extra_headers= &extra_headers; publ.outbound_proxy = presence_server; if(pua_send_publish(&publ)< 0) { LM_ERR("failed to send Publish message\n"); return -1; } return 1; }
/*! * \brief Parse SIP message and populate leg informations * * Parse SIP message and populate leg informations. * \param dlg the dialog to add cseq, contact & record_route * \param msg sip message * \param t transaction * \param leg type of the call leg * \param tag SIP To tag * \return 0 on success, -1 on failure * \note for a request: get record route in normal order, for a reply get * in reverse order, skipping the ones from the request and the proxies' own */ int populate_leg_info(struct dlg_cell *dlg, struct sip_msg *msg, struct cell* t, unsigned int leg, str *tag) { unsigned int skip_recs; str cseq; str contact; str rr_set; struct socket_info* callee_bind_address = NULL; if (leg == DLG_CALLER_LEG) dlg->caller_bind_addr = msg->rcv.bind_address; else callee_bind_address = msg->rcv.bind_address; /* extract the cseq number as string from the request or response*/ //TO DO - can pair the cseqs here to make sure that the response and request are in sync if ((!msg->cseq && (parse_headers(msg, HDR_CSEQ_F, 0) < 0 || !msg->cseq)) || !msg->cseq->parsed) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); goto error0; } cseq = (get_cseq(msg))->number; /* extract the contact address */ if (!msg->contact && (parse_headers(msg, HDR_CONTACT_F, 0) < 0 || !msg->contact)) { LM_ERR("bad sip message or missing Contact hdr\n"); goto error0; } 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"); goto error0; } contact = ((contact_body_t *) msg->contact->parsed)->contacts->uri; /* extract the RR parts */ if (!msg->record_route && (parse_headers(msg, HDR_EOH_F, 0) < 0)) { LM_ERR("failed to parse record route header\n"); goto error0; } if (leg == DLG_CALLER_LEG) { skip_recs = 0; } else { skip_recs = 0; /* was the 200 OK received or local generated */ /*skip_recs = dlg->from_rr_nb + ((t->relayed_reply_branch >= 0) ? ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_R2) ? 2 : ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_RR) ? 1 : 0)) : 0); * */ } if (msg->record_route) { if (print_rr_body(msg->record_route, &rr_set, leg, &skip_recs) != 0) { LM_ERR("failed to print route records \n"); goto error0; } } else { rr_set.s = 0; rr_set.len = 0; } if (leg == DLG_CALLER_LEG) dlg->from_rr_nb = skip_recs; LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n", rr_set.len, rr_set.s, contact.len, contact.s, cseq.len, cseq.s, msg->rcv.bind_address->sock_str.len, msg->rcv.bind_address->sock_str.s); if (dlg_set_leg_info(dlg, tag, &rr_set, &contact, &cseq, callee_bind_address, leg) != 0) { LM_ERR("dlg_set_leg_info failed\n"); if (rr_set.s) pkg_free(rr_set.s); goto error0; } if (rr_set.s) pkg_free(rr_set.s); return 0; error0: return -1; }
/* returns : -1 - error * 0 - ok, but no contact added * n - ok and n contacts added */ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl, long max, str *reason) { static struct sip_msg dup_rpl; static contact_t *scontacts[MAX_CONTACTS_PER_REPLY]; struct hdr_field *hdr; struct hdr_field *contact_hdr; contact_t *contacts; int n,i; int added; int dup; int ret; /* dup can be: * 0 - sh reply but nothing duplicated * 1 - sh reply but only contact body parsed * 2 - sh reply and contact header and body parsed * 3 - private reply */ dup = 0; /* sh_rpl not duplicated */ ret = 0; /* success and no contact added */ if (sh_rpl==0 || sh_rpl==FAKED_REPLY) return 0; if (sh_rpl->contact==0) { /* contact header is not parsed */ if ( sh_rpl->msg_flags&FL_SHM_CLONE ) { /* duplicate the reply into private memory to be able * to parse it and after words to free the parsed mems */ memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) ); dup = 2; /* ok -> force the parsing of contact header */ if ( parse_headers( &dup_rpl, HDR_CONTACT_T, 0)<0 ) { LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: dup_rpl " "parse failed\n"); ret = -1; goto restore; } if (dup_rpl.contact==0) { DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr not " "found in dup_rpl\n"); goto restore; } contact_hdr = dup_rpl.contact; } else { dup = 3; /* force the parsing of contact header */ if ( parse_headers( sh_rpl, HDR_CONTACT_T, 0)<0 ) { LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: sh_rpl " "parse failed\n"); ret = -1; goto restore; } if (sh_rpl->contact==0) { DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr not " "found in sh_rpl\n"); goto restore; } contact_hdr = sh_rpl->contact; } } else { contact_hdr = sh_rpl->contact; } /* parse the body of contact header */ if (contact_hdr->parsed==0) { if ( parse_contact(contact_hdr)<0 ) { LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: contact hdr " "parse failed\n"); ret = -1; goto restore; } if (dup==0) dup = 1; } /* we have the contact header and its body parsed -> sort the contacts * based on the q value */ contacts = ((contact_body_t*)contact_hdr->parsed)->contacts; if (contacts==0) { DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr " "has no contacts\n"); goto restore; } n = sort_contacts( contacts, scontacts); /* to many branches ? */ if (max!=-1 && n>max) n = max; added = 0; /* add the sortet contacts as branches in dset and log this! */ for ( i=0 ; i<n ; i++ ) { DBG("DEBUG:uac_redirect:shmcontact2dset: adding contact <%.*s>\n", scontacts[i]->uri.len, scontacts[i]->uri.s); if (append_branch( 0, &scontacts[i]->uri, 0, Q_UNSPECIFIED, 0, 0)<0 ) { LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: failed to add " "contact to dset\n"); } else { added++; if (rd_acc_fct!=0 && reason) { /* log the redirect */ req->new_uri = scontacts[i]->uri; rd_acc_fct( req, (char*)reason, acc_db_table); } } } ret = (added==0)?-1:added; restore: if (dup==1) { free_contact( (contact_body_t**)(&contact_hdr->parsed) ); } else if (dup==2) { /* are any new headers found? */ if (dup_rpl.last_header!=sh_rpl->last_header) { /* identify in the new headere list (from dup_rpl) * the sh_rpl->last_header and start remove everything after */ hdr = sh_rpl->last_header; free_hdr_field_lst(hdr->next); hdr->next=0; } } return ret; }
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps) { struct sip_msg* msg= NULL; int lexpire= 0; unsigned int cseq; ua_pres_t* presentity= NULL, *hentity= NULL; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; int size= 0; unsigned int hash_code; int flag ; str record_route= {0, 0}; int rt; str contact; int initial_request = 0; int end_transaction = 1; if( ps->param== NULL || *ps->param== NULL ) { LM_ERR("null callback parameter\n"); return; } if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } LM_DBG("completed with status %d\n",ps->code) ; hentity= (ua_pres_t*)(*ps->param); hash_code= core_hash(hentity->pres_uri,hentity->watcher_uri, HASH_SIZE); flag= hentity->flag; if(hentity->flag & XMPP_INITIAL_SUBS) hentity->flag= XMPP_SUBSCRIBE; /* get dialog information from reply message: callid, to_tag, from_tag */ msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n "); goto error; } if(msg== FAKED_REPLY) { struct hdr_field *callid = NULL, *from = NULL; struct to_body FROM = {0}; callid = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (callid == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(callid, 0, sizeof(struct hdr_field)); get_hdr_field(t->callid.s, t->callid.s + t->callid.len, callid); hentity->call_id = callid->body; from = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (from == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(from, 0, sizeof(struct hdr_field)); get_hdr_field(t->from.s, t->from.s + t->from.len, from); parse_to(from->body.s, from->body.s + from->body.len + 1, &FROM); if(FROM.uri.len <= 0) { LM_ERR("'From' header NOT parsed\n"); goto faked_error; } hentity->call_id = callid->body; hentity->from_tag = (&FROM)->tag_value; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); faked_error: if (callid) pkg_free(callid); free_to_params(&FROM); if (from) pkg_free(from); goto done; } if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); goto error; } if(ps->rpl->expires && msg->expires->body.len > 0) { if (!msg->expires->parsed && (parse_expires(msg->expires) < 0)) { LM_ERR("cannot parse Expires header\n"); goto error; } lexpire = ((exp_body_t*)msg->expires->parsed)->val; LM_DBG("lexpire= %d\n", lexpire); } /*if initial request */ if(hentity->call_id.s== NULL) { initial_request = 1; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } hentity->call_id= msg->callid->body; hentity->from_tag= pfrom->tag_value; if(ps->code >= 300 || lexpire == 0) { hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); goto done; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_ERR("'To' header NOT parsed\n"); goto error; } pto = &TO; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no to tag value present\n"); goto error; } hentity->to_tag= pto->tag_value; } if(ps->code >= 300 ) { /* if an error code and a stored dialog delete it and try to send a subscription with type= INSERT_TYPE, else return*/ subs_info_t subs; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } end_transaction = 0; /* Redirect if the response 3XX */ memset(&subs, 0, sizeof(subs_info_t)); subs.pres_uri= hentity->pres_uri; subs.watcher_uri= hentity->watcher_uri; subs.contact= &hentity->contact; if(hentity->remote_contact.s) subs.remote_target= &hentity->remote_contact; if(hentity->desired_expires== 0) subs.expires= -1; else if(hentity->desired_expires< (int)time(NULL)) subs.expires= 0; else subs.expires= hentity->desired_expires- (int)time(NULL)+ 3; subs.flag= INSERT_TYPE; subs.source_flag= flag; subs.event= hentity->event; subs.id= hentity->id; subs.outbound_proxy= hentity->outbound_proxy; subs.extra_headers= hentity->extra_headers; subs.cb_param= hentity->cb_param; if(send_subscribe(&subs)< 0) { LM_ERR("when trying to send SUBSCRIBE\n"); goto error; } goto done; } if(lexpire== 0 ) { LM_DBG("lexpire= 0 Delete from hash table"); find_and_delete_dialog(hentity, hash_code); goto done; } /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); goto error; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); goto error; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); goto error; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; if( msg->cseq==NULL || msg->cseq->body.s==NULL) { LM_ERR("cannot parse cseq header\n"); goto error; } if( str2int( &(get_cseq(msg)->number), &cseq)< 0) { LM_ERR("while converting str to int\n"); goto error; } if(initial_request == 0) { hentity->cseq = cseq; find_and_update_dialog(hentity, hash_code, lexpire, &contact); goto done; } /*process record route and add it to a string*/ if (msg->record_route!=NULL) { rt = print_rr_body(msg->record_route, &record_route, 1, 0); if(rt != 0) { LM_ERR("parsing record route [%d]\n", rt); record_route.s=NULL; record_route.len=0; } } size= sizeof(ua_pres_t)+ 2*sizeof(str)+( pto->uri.len+ pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len +msg->callid->body.len+ record_route.len+ hentity->contact.len+ hentity->id.len )*sizeof(char); if(hentity->extra_headers) size+= sizeof(str)+ hentity->extra_headers->len*sizeof(char); presentity= (ua_pres_t*)shm_malloc(size); if(presentity== NULL) { LM_ERR("no more share memory\n"); goto error; } memset(presentity, 0, size); size= sizeof(ua_pres_t); presentity->pres_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->pres_uri->s= (char*)presentity+ size; memcpy(presentity->pres_uri->s, pto->uri.s, pto->uri.len); presentity->pres_uri->len= pto->uri.len; size+= pto->uri.len; presentity->watcher_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->watcher_uri->s= (char*)presentity+ size; memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len); presentity->watcher_uri->len= pfrom->uri.len; size+= pfrom->uri.len; presentity->call_id.s= (char*)presentity + size; memcpy(presentity->call_id.s,msg->callid->body.s, msg->callid->body.len); presentity->call_id.len= msg->callid->body.len; size+= presentity->call_id.len; presentity->to_tag.s= (char*)presentity + size; memcpy(presentity->to_tag.s,pto->tag_value.s, pto->tag_value.len); presentity->to_tag.len= pto->tag_value.len; size+= pto->tag_value.len; presentity->from_tag.s= (char*)presentity + size; memcpy(presentity->from_tag.s,pfrom->tag_value.s, pfrom->tag_value.len); presentity->from_tag.len= pfrom->tag_value.len; size+= pfrom->tag_value.len; if(record_route.len && record_route.s) { presentity->record_route.s= (char*)presentity + size; memcpy(presentity->record_route.s, record_route.s, record_route.len); presentity->record_route.len= record_route.len; size+= record_route.len; pkg_free(record_route.s); record_route.s = NULL; } presentity->contact.s= (char*)presentity + size; memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len); presentity->contact.len= hentity->contact.len; size+= hentity->contact.len; if(hentity->id.s) { presentity->id.s=(char*)presentity+ size; memcpy(presentity->id.s, hentity->id.s, hentity->id.len); presentity->id.len= hentity->id.len; size+= presentity->id.len; } if(hentity->extra_headers) { presentity->extra_headers= (str*)((char*)presentity+ size); size+= sizeof(str); presentity->extra_headers->s=(char*)presentity+ size; memcpy(presentity->extra_headers->s, hentity->extra_headers->s, hentity->extra_headers->len); presentity->extra_headers->len= hentity->extra_headers->len; size+= hentity->extra_headers->len; } /* write the remote contact filed */ presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(presentity->remote_contact.s==NULL) { ERR_MEM(SHARE_MEM); } memcpy(presentity->remote_contact.s, contact.s, contact.len); presentity->remote_contact.len= contact.len; presentity->event|= hentity->event; presentity->flag= hentity->flag; presentity->etag.s= NULL; presentity->cseq= cseq; presentity->desired_expires= hentity->desired_expires; presentity->expires= lexpire+ (int)time(NULL); if(BLA_SUBSCRIBE & presentity->flag) { LM_DBG("BLA_SUBSCRIBE FLAG inserted\n"); } LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n", presentity->watcher_uri->len, presentity->watcher_uri->s, presentity->pres_uri->len, presentity->pres_uri->s); if (dbmode==PUA_DB_ONLY) { if (pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } if (pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (convert_temporary_dialog_puadb(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } else { if (convert_temporary_dialog(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } done: if(hentity->ua_flag == REQ_OTHER) { hentity->flag= flag; run_pua_callbacks( hentity, msg); } if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction && end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } goto end; error: if (presentity) { if (presentity->remote_contact.s) shm_free(presentity->remote_contact.s); shm_free(presentity); } if(record_route.s) pkg_free(record_route.s); if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction) { if (pua_dbf.abort_transaction(pua_db) < 0) LM_ERR("in abort_transaction\n"); } end: if(hentity) { shm_free(hentity); hentity= NULL; } free_to_params(&TO); return; }
int th_mask_contact(sip_msg_t *msg) { struct lump* l; str out; str in; char *p; contact_t *c; if(msg->contact==NULL) { LM_DBG("no contact header\n"); return 0; } if(parse_contact(msg->contact) < 0) { LM_ERR("failed parsing contact header\n"); return -1; } c = ((contact_body_t*)msg->contact->parsed)->contacts; in = c->uri; out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len); if(out.s==NULL) { LM_ERR("cannot encode contact uri\n"); return -1; } if(*(in.s-1)!='<') { /* add < > around contact uri if not there */ p = (char*)pkg_malloc(out.len+3); if(p==NULL) { LM_ERR("failed to get more pkg\n"); pkg_free(out.s); return -1; } *p = '<'; strncpy(p+1, out.s, out.len); p[out.len+1] = '>'; p[out.len+2] = '\0'; pkg_free(out.s); out.s = p; out.len += 2; } l=del_lump(msg, in.s-msg->buf, in.len, 0); if (l==0) { LM_ERR("failed deleting contact uri\n"); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0) { LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } return 0; }