/* reads Identity header field from msg Return value: 1: success 0: Identity header field does not exist 1: else identityHF must point to an array with at least MAX_IDENTITY bytes */ static int getIdentityHF(char * identityHF, struct sip_msg * msg) { struct hdr_field * identity = NULL; if(!identityHF || !msg) { LM_ERR("identityHF or msg not set\n"); return -1; } identity = get_header_by_static_name(msg, "Identity"); if (!identity) { /* Identity header field does not exist */ return 0; } if(((identity->body.len) - 2) >= MAX_IDENTITY) { LM_ERR("identity header to long\n"); return -1; } /* " at the beginning and at the end are cutted */ memcpy( identityHF, identity->body.s+1, identity->body.len-2); identityHF[(identity->body.len) - 2] = '\0'; return 1; }
void get_cancel_reason(struct sip_msg *msg, int flags, str *reason) { #define CANCEL_REASON_SIP_487 \ "Reason: SIP;cause=487;text=\"ORIGINATOR_CANCEL\"" CRLF int_str avp_reason; struct hdr_field *hdr; reason->s = NULL; reason->len = 0; if (search_first_avp( AVP_VAL_STR, _reason_avp_id, &avp_reason, NULL)) { *reason = avp_reason.s; } else { /* propagate the REASON flag ? */ if ( flags&T_CANCEL_REASON_FLAG ) { /* look for the Reason header */ if (parse_headers(msg, HDR_EOH_F, 0)<0) { LM_ERR("failed to parse all hdrs - ignoring Reason hdr\n"); } else { hdr = get_header_by_static_name(msg, "Reason"); if (hdr!=NULL) { reason->s = hdr->name.s; reason->len = hdr->len; } } } } /* if no reason, use NORMAL CLEARING */ if (reason->s == NULL) { reason->s = CANCEL_REASON_SIP_487; reason->len = sizeof(CANCEL_REASON_SIP_487) - 1; } }
void cancel_invite(struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite ) { #define CANCEL_REASON_SIP_487 \ "Reason: SIP;cause=487;text=\"ORIGINATOR_CANCEL\"" CRLF branch_bm_t cancel_bitmap; branch_bm_t dummy_bm; str reason; unsigned int i; struct hdr_field *hdr; cancel_bitmap=0; /* send back 200 OK as per RFC3261 */ reason.s = CANCELING; reason.len = sizeof(CANCELING)-1; t_reply( t_cancel, cancel_msg, 200, &reason ); reason.s = NULL; reason.len = 0; /* propagate the REASON flag ? */ if ( t_cancel->flags&T_CANCEL_REASON_FLAG ) { /* look for the Reason header */ if (parse_headers(cancel_msg, HDR_EOH_F, 0)<0) { LM_ERR("failed to parse all hdrs - ignoring Reason hdr\n"); } else { hdr = get_header_by_static_name(cancel_msg, "Reason"); if (hdr!=NULL) { reason.s = hdr->name.s; reason.len = hdr->len; } } } /* if no reason, use NORMAL CLEARING */ if (reason.s == NULL) { reason.s = CANCEL_REASON_SIP_487; reason.len = sizeof(CANCEL_REASON_SIP_487) - 1; } /* generate local cancels for all branches */ which_cancel(t_invite, &cancel_bitmap ); set_cancel_extra_hdrs( reason.s, reason.len); cancel_uacs(t_invite, cancel_bitmap ); set_cancel_extra_hdrs( NULL, 0); /* internally cancel branches with no received reply */ for (i=t_invite->first_branch; i<t_invite->nr_of_outgoings; i++) { if (t_invite->uac[i].last_received==0){ /* reset the "request" timers */ reset_timer(&t_invite->uac[i].request.retr_timer); reset_timer(&t_invite->uac[i].request.fr_timer); LOCK_REPLIES( t_invite ); relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm); } } }
/* reads the Date header field of msg return value: -1: error 0: Date header field does not exist 1: success dateHF must point to an array with at least MAX_TIME bytes */ static int getDate(char * dateHF, time_t * dateHFValue, struct sip_msg * msg) { struct hdr_field * date = NULL; struct tm tmDate; if(!dateHF || !dateHFValue || !msg) { LM_ERR("dateHF, dateHFValue or msg not set\n"); return -1; } date = get_header_by_static_name(msg, "Date"); if (!date) { return 0; } if(date->body.len >= MAX_TIME) { LM_ERR("Date header field to long\n"); return -1; } /* date->body.len < MAX_TIME */ strncpy(dateHF, date->body.s, date->body.len); dateHF[date->body.len] = '\0'; if(!strptime(dateHF, DATE_FORMAT, &tmDate)) { LM_ERR("error while parsing Date header field\n"); return -1; } /* covert struct tm to time_t */ *dateHFValue = my_timegm(&tmDate); if(*dateHFValue == -1) { LM_ERR("error while converting timestamp\n"); return -1; } 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; }
/* Take headers to pass on the other side: * Content-Type: * Allow: * Supported: * Require * RSeq * Session-Expires * Min-SE */ int b2b_extra_headers(struct sip_msg* msg, str* b2bl_key, str* custom_hdrs, str* extra_headers) { char* p; struct hdr_field* require_hdr; struct hdr_field* rseq_hdr; struct hdr_field* subscription_state_hdr; struct hdr_field* hdr; struct hdr_field* hdrs[HDR_LST_LEN + HDR_DEFAULT_LEN]; int hdrs_no = 0; int len = 0; int i; int custom_hdrs_len = 0; if(msg->content_type) hdrs[hdrs_no++] = msg->content_type; if(msg->supported) hdrs[hdrs_no++] = msg->supported; if(msg->allow) hdrs[hdrs_no++] = msg->allow; if(msg->proxy_require) hdrs[hdrs_no++] = msg->proxy_require; if(msg->session_expires) hdrs[hdrs_no++] = msg->session_expires; if(msg->min_se) hdrs[hdrs_no++] = msg->min_se; if(msg->maxforwards) hdrs[hdrs_no++] = msg->maxforwards; if(msg->event) hdrs[hdrs_no++] = msg->event; require_hdr = get_header_by_static_name( msg, "Require"); if(require_hdr) hdrs[hdrs_no++] = require_hdr; rseq_hdr = get_header_by_static_name( msg, "RSeq"); if(rseq_hdr) hdrs[hdrs_no++] = rseq_hdr; subscription_state_hdr = get_header_by_static_name( msg, "Subscription-state"); if(subscription_state_hdr) hdrs[hdrs_no++] = subscription_state_hdr; /* add also the custom headers */ for(i = 0; i< custom_headers_lst_len; i++) { hdr = get_header_by_name( msg, custom_headers_lst[i].s, custom_headers_lst[i].len); if(hdr) { hdrs[hdrs_no++] = hdr; } } /* calculate the length*/ for(i = 0; i< hdrs_no; i++) len += hdrs[i]->len; if(init_callid_hdr.len && msg && msg->callid) len+= init_callid_hdr.len + msg->callid->len; if(len == 0) return 0; if(custom_hdrs && custom_hdrs->s && custom_hdrs->len) { custom_hdrs_len = custom_hdrs->len; len += custom_hdrs_len; } extra_headers->s = (char*)pkg_malloc(len); if(extra_headers->s == NULL) { LM_ERR("No more memory\n"); return -1; } p = extra_headers->s; /* construct the headers string */ for(i = 0; i< hdrs_no; i++) { memcpy(p, hdrs[i]->name.s, hdrs[i]->len); p += hdrs[i]->len; } if(custom_hdrs_len) { memcpy(p, custom_hdrs->s, custom_hdrs_len); p += custom_hdrs_len; } if(init_callid_hdr.s && msg && msg->callid) { memcpy(p, init_callid_hdr.s, init_callid_hdr.len); p += init_callid_hdr.len; len = sprintf(p, ": %.*s", (int)(msg->callid->name.s +msg->callid->len -msg->callid->body.s), msg->callid->body.s); p += len; } extra_headers->len = p - extra_headers->s; return 0; }
void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps) { struct hdr_field* hdr= NULL; struct sip_msg* msg= NULL; ua_pres_t* presentity= NULL; unsigned int lexpire= 0; str etag; unsigned int hash_index, local_index; unsigned long pres_id; if(ps->param == NULL) { LM_ERR("NULL parameter\n"); return; } msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n"); return; } LM_DBG("cback param = %lu\n", (unsigned long)*ps->param); pres_id = (unsigned long)*ps->param; PUA_PARSE_PRES_ID(pres_id, hash_index, local_index); LM_DBG("hash_index= %u, local_index= %u\n", hash_index, local_index); if(!find_htable(hash_index, local_index)) { LM_ERR("No record found\n"); return; } if(msg== FAKED_REPLY) { LM_DBG("FAKED_REPLY\n"); goto done; } if( ps->code>= 300 ) { delete_htable(hash_index, local_index); goto done; } if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return; } if(msg->expires== NULL || msg->expires->body.len<= 0) { LM_ERR("No Expires header found\n"); return; } if (!msg->expires->parsed && (parse_expires(msg->expires) < 0)) { LM_ERR("cannot parse Expires header\n"); return; } lexpire = ((exp_body_t*)msg->expires->parsed)->val; LM_DBG("lexpire= %u\n", lexpire); if(lexpire == 0) { delete_htable(hash_index, local_index); goto done; } hdr = get_header_by_static_name( msg, "SIP-ETag"); if( hdr==NULL ) /* must find SIP-Etag header field in 200 OK msg*/ { LM_ERR("no SIP-ETag header field found\n"); return; } etag= hdr->body; update_htable(hash_index, local_index, lexpire, &etag, 0); done: lock_get(&HashT->p_records[hash_index].lock); presentity = get_htable_safe(hash_index, local_index); if(!presentity) { LM_DBG("Record not found\n"); lock_release(&HashT->p_records[hash_index].lock); return; } if(presentity->ua_flag == REQ_OTHER) { run_pua_callbacks(presentity, msg); presentity->cb_param = NULL; } presentity->waiting_reply = 0; while(presentity->pending_publ) { publ_t* pending_publ = presentity->pending_publ; publ_info_t* publ = construct_pending_publ(presentity); if(publ == NULL) { LM_ERR("Failed to create publish record\n"); lock_release(&HashT->p_records[hash_index].lock); presentity->pending_publ = pending_publ->next; shm_free(pending_publ); continue; } LM_DBG("Found pending publish\n"); presentity->pending_publ = 0; presentity->waiting_reply = 1; send_publish_int(presentity, publ, get_event(presentity->event), presentity->hash_index); pkg_free(publ); presentity->pending_publ = pending_publ->next; shm_free(pending_publ); break; } lock_release(&HashT->p_records[hash_index].lock); }
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; }
int Notify2Xmpp(struct sip_msg* msg, char* s1, char* s2) { struct to_body *pto, *pfrom= NULL; str to_uri; str from_uri={0, 0}; struct hdr_field* hdr= NULL; str body; xmlDocPtr doc= NULL; int is_terminated= 0; str id; ua_pres_t dialog; int event_flag= 0; char buf_to[256]; memset(&dialog, 0, sizeof(ua_pres_t)); LM_DBG("start...\n\n"); if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return -1; } dialog.watcher_uri= &pto->uri; URI_ADD_NULL_TERM(to_uri, buf_to, dialog.watcher_uri); if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); goto error; } id= pto->tag_value; dialog.from_tag= id; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("ERROR cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("ERROR cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; from_uri.s = xmpp_uri_sip2xmpp(dialog.pres_uri); if(from_uri.s == 0) { LM_ERR("Failed to translate uri from sip to xmpp [%.*s]\n", dialog.pres_uri->len, dialog.pres_uri->s); goto error; } from_uri.len= strlen(from_uri.s); if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } dialog.to_tag= pfrom->tag_value; dialog.flag|= XMPP_SUBSCRIBE; if(msg->event->body.len== 8 && (strncasecmp(msg->event->body.s,"presence",8 )==0)) event_flag|= PRESENCE_EVENT; else if(msg->event->body.len== 14 && (strncasecmp(msg->event->body.s,"presence.winfo",14 )==0)) event_flag|= PWINFO_EVENT; else { LM_ERR("wrong event\n"); goto error; } dialog.event= event_flag; if(pua_is_dialog(&dialog)< 0) // verify if within a stored dialog { LM_ERR("Notify in a non existing dialog\n"); goto error; } /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { body.s= NULL; body.len= 0; } else { if ( get_body(msg,&body)!=0 || body.len==0) { LM_ERR("cannot extract body from msg\n"); goto error; } } /* treat the two cases: event= presence & event=presence.winfo */ if(event_flag & PRESENCE_EVENT) { LM_DBG("PRESENCE\n"); hdr = get_header_by_static_name( msg, "Subscription-State" ); if(hdr && strncasecmp(hdr->body.s,"terminated", 10)== 0) { /* chack if reason timeout => don't send notification */ if(strncasecmp(hdr->body.s+11,"reason=timeout", 14)== 0) { LM_DBG("Received Notification with state" "terminated; reason= timeout=> don't send notification\n"); return 1; } is_terminated= 1; } if(build_xmpp_content(&to_uri, &from_uri, &body, &id, is_terminated)< 0) { LM_ERR("in function build_xmpp_content\n"); goto error; } xmlFreeDoc(doc); } else { if(event_flag & PWINFO_EVENT) { LM_DBG("PRESENCE.WINFO\n"); hdr = get_header_by_static_name( msg, "Subscription-State" ); if(hdr && strncasecmp(hdr->body.s,"terminated", 10)== 0) { LM_DBG("Notify for presence.winfo with" " Subscription-State terminated- should not translate\n"); goto error; } if(winfo2xmpp(&to_uri, &body, &id)< 0) { LM_ERR("while sending subscription\n"); goto error; } } else { LM_ERR("Missing or unsupported event header field value\n"); goto error; } } return 1; error: if(doc) xmlFreeDoc(doc); return 0; }
int b2b_extra_headers(struct sip_msg* msg, str* b2bl_key, str* custom_hdrs, str* extra_headers) { char* p; struct hdr_field* require_hdr; struct hdr_field* rseq_hdr; struct hdr_field* subscription_state_hdr; struct hdr_field* hdr; struct hdr_field* hdrs[HDR_LST_LEN + HDR_DEFAULT_LEN]; regmatch_t pmatch; int hdrs_no = 0; int len = 0; int i; int custom_hdrs_len = 0; char tmp; if(msg->content_type) hdrs[hdrs_no++] = msg->content_type; if(msg->supported) hdrs[hdrs_no++] = msg->supported; if(msg->allow) hdrs[hdrs_no++] = msg->allow; if(msg->proxy_require) hdrs[hdrs_no++] = msg->proxy_require; if(msg->session_expires) hdrs[hdrs_no++] = msg->session_expires; if(msg->min_se) hdrs[hdrs_no++] = msg->min_se; if(msg->event) hdrs[hdrs_no++] = msg->event; require_hdr = get_header_by_static_name( msg, "Require"); if(require_hdr) hdrs[hdrs_no++] = require_hdr; rseq_hdr = get_header_by_static_name( msg, "RSeq"); if(rseq_hdr) hdrs[hdrs_no++] = rseq_hdr; subscription_state_hdr = get_header_by_static_name( msg, "Subscription-state"); if(subscription_state_hdr) hdrs[hdrs_no++] = subscription_state_hdr; /* add also the custom headers */ for(i = 0; i< custom_headers_lst_len; i++) { hdr = get_header_by_name( msg, custom_headers_lst[i].s, custom_headers_lst[i].len); if(hdr) { hdrs[hdrs_no++] = hdr; } } if (custom_headers_re) { for (hdr=msg->headers; hdr; hdr=hdr->next) { tmp = hdr->name.s[hdr->name.len]; hdr->name.s[hdr->name.len] = '\0'; i = regexec(custom_headers_re, hdr->name.s, 1, &pmatch, 0); hdr->name.s[hdr->name.len] = tmp; if (i == 0) { /* check if added twice */ for(i = 0; i < hdrs_no; i++) { if ( hdrs[i]->name.len == hdr->name.len && strncmp(hdrs[i]->name.s, hdr->name.s, hdr->name.len)==0 ) break; } if (i == hdrs_no) /* Doubles not found -> add it */ hdrs[hdrs_no++] = hdr; } } } /* calculate the length*/ for(i = 0; i< hdrs_no; i++) len += hdrs[i]->len; if(init_callid_hdr.len && msg && msg->callid) len+= init_callid_hdr.len + msg->callid->len; if(custom_hdrs && custom_hdrs->s && custom_hdrs->len) { custom_hdrs_len = custom_hdrs->len; len += custom_hdrs_len; } if(len == 0) return 0; extra_headers->s = (char*)pkg_malloc(len); if(extra_headers->s == NULL) { LM_ERR("No more memory\n"); return -1; } p = extra_headers->s; /* construct the headers string */ for(i = 0; i< hdrs_no; i++) { memcpy(p, hdrs[i]->name.s, hdrs[i]->len); p += hdrs[i]->len; } if(custom_hdrs_len) { memcpy(p, custom_hdrs->s, custom_hdrs_len); p += custom_hdrs_len; } if(init_callid_hdr.s && msg && msg->callid) { memcpy(p, init_callid_hdr.s, init_callid_hdr.len); p += init_callid_hdr.len; len = sprintf(p, ": %.*s", (int)(msg->callid->name.s +msg->callid->len -msg->callid->body.s), msg->callid->body.s); p += len; } extra_headers->len = p - extra_headers->s; return 0; }
/* * Send Radius request to verify source. */ int verify_source(struct sip_msg* _msg, char* s1, char* s2) { aaa_message *send = NULL, *received = NULL; struct hdr_field *hf; uint32_t service; /* Add Request-URI host A_USER_NAME and user as A_SIP_URI_USER */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing Request-URI\n"); return -1; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth\n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _msg->parsed_uri.host.s, _msg->parsed_uri.host.len, 0)) { LM_ERR("error adding PW_USER_NAME\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], _msg->parsed_uri.user.s, _msg->parsed_uri.user.len, 0)) { LM_ERR("error adding PW_SIP_URI_USER\n"); goto err; } /* Add From Tag */ if (parse_from_header(_msg) < 0) { LM_ERR("error while parsing From header field\n"); goto err; } if (_msg->from == NULL || get_from(_msg) == NULL || get_from(_msg)->tag_value.s == NULL || get_from(_msg)->tag_value.len <= 0) { LM_ERR("error while accessing From header tag\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_FROM_TAG], get_from(_msg)->tag_value.s, get_from(_msg)->tag_value.len, 0)) { LM_ERR("error adding PW_SIP_FROM_TAG\n"); goto err; } /* Add Call-Id */ if (parse_headers(_msg, HDR_CALLID_F, 0) == -1 || _msg->callid == NULL || _msg->callid->body.s == NULL || _msg->callid->body.len <= 0) { LM_ERR("error while accessing Call-Id\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_CALL_ID], _msg->callid->body.s, _msg->callid->body.len, 0)) { LM_ERR("error adding PW_SIP_CALL_ID\n"); goto err; } /* Add P-Request-Hash header body */ if (parse_headers(_msg, HDR_EOH_F, 0) < 0) { LM_ERR("cannot pase message!\n"); goto err; } hf = get_header_by_static_name( _msg, "P-Request-Hash"); if (!hf) { LM_ERR("no P-Request-Hash header field\n"); goto err; } if (hf->body.s == NULL || hf->body.len <= 0) { LM_ERR("error while accessing P-Request-Hash body\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_REQUEST_HASH], hf->body.s, hf->body.len, 0)) { LM_ERR("error adding PW_SIP_REQUEST_HASH\n"); goto err; } /* Add Service-Type */ service = vals[V_SIP_VERIFY_SOURCE].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { LM_ERR("error adding PW_SERVICE_TYPE\n"); goto err; } /* Send Request and generate AVPs of positive reply */ if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } LM_DBG("failure\n"); err: if (send) proto.destroy_aaa_message(conn, send); if (received) proto.destroy_aaa_message(conn, received); return -1; }
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2) { struct to_body *pto, *pfrom= NULL; str body= {0, 0}; ua_pres_t dialog; str* res_id= NULL; db_key_t query_cols[9], result_cols[1]; db_val_t query_vals[9]; db_res_t* result= NULL; int n_query_cols= 0; str auth_state= {0, 0}; str* reason= NULL; int auth_flag; struct hdr_field* hdr= NULL; int n, expires= -1; str ctype= {0, 0}; int err_ret = -1; LM_DBG("start\n"); /* extract the dialog information and check if an existing dialog*/ if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return -1; } memset(&dialog, 0, sizeof(ua_pres_t)); dialog.watcher_uri= &pto->uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); goto error; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { LM_DBG("'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } dialog.to_tag= pfrom->tag_value; dialog.flag|= RLS_SUBSCRIBE; dialog.event= get_event_flag(&msg->event->body); if(dialog.event< 0) { LM_ERR("unrecognized event package\n"); goto error; } if(pua_get_record_id(&dialog, &res_id)< 0) // verify if within a stored dialog { LM_ERR("error occured while trying to get dialog record id\n"); goto error; } if(res_id== 0) { LM_DBG("no dialog match found in hash table\n"); err_ret = 2; goto error; } /* extract the subscription state */ hdr = get_header_by_static_name( msg, "Subscription-State"); if( hdr==NULL ) { LM_ERR("'Subscription-State' header not found\n"); goto error; } auth_state = hdr->body; /* extract state and reason */ auth_flag= parse_subs_state(auth_state, &reason, &expires); if(auth_flag< 0) { LM_ERR("while parsing 'Subscription-State' header\n"); goto error; } if(msg->content_type== NULL || msg->content_type->body.s== NULL) { LM_DBG("cannot find content type header\n"); } else ctype= msg->content_type->body; LM_DBG("NOTIFY for [user]= %.*s\n",dialog.pres_uri->len, dialog.pres_uri->s); /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { LM_DBG("null body\n"); goto done; } else { if(ctype.s== 0) { LM_ERR("content length != 0 and no content type header found\n"); goto error; } if ( get_body(msg,&body)!=0 || body.len==0) { LM_ERR("cannot extract body from msg\n"); goto error; } LM_DBG("[body]= %.*s\n", body.len, body.s); } /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/ query_cols[n_query_cols]= &str_rlsubs_did_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *res_id; n_query_cols++; query_cols[n_query_cols]= &str_resource_uri_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *dialog.pres_uri; n_query_cols++; query_cols[n_query_cols]= &str_updated_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= UPDATED_TYPE; n_query_cols++; query_cols[n_query_cols]= &str_auth_state_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= auth_flag; n_query_cols++; if(reason) { query_cols[n_query_cols]= &str_reason_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *reason; n_query_cols++; } query_cols[n_query_cols]= &str_content_type_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= ctype; n_query_cols++; query_cols[n_query_cols]= &str_presence_state_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= body; n_query_cols++; query_cols[n_query_cols]= &str_expires_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL); n_query_cols++; if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) { LM_ERR("in use_table\n"); goto error; } /* query-> if not present insert // else update */ result_cols[0]= &str_updated_col; if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols, 2, 1, 0, &result)< 0) { LM_ERR("in sql query\n"); if(result) rls_dbf.free_result(rls_db, result); goto error; } if(result== NULL) goto error; n= result->n; rls_dbf.free_result(rls_db, result); if(n<= 0) { if(rls_dbf.insert(rls_db, query_cols, query_vals, n_query_cols)< 0) { LM_ERR("in sql insert\n"); goto error; } } else { if(expires!= 0) { if(rls_dbf.update(rls_db, query_cols, 0, query_vals, query_cols+2, query_vals+2, 2, n_query_cols-2)< 0) { LM_ERR("in sql update\n"); goto error; } } else /* if terminated - delete from rls_presentity table */ { if(rls_dbf.delete(rls_db, query_cols, 0, query_vals, 2)< 0) { LM_ERR("sql delete failed\n"); goto error; } } } done: if( rls_sigb.reply(msg, 200, &su_200_rpl, 0) < 0) { LM_ERR("failed to send SIP reply\n"); goto error; } pkg_free(res_id->s); pkg_free(res_id); return 1; error: if(res_id) { pkg_free(res_id->s); pkg_free(res_id); } return err_ret; }