/* * Matches from uri against patterns returned from database. Returns number * of matches or -1 if none of the patterns match. */ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r) { int i, tag_avp_type; str uri; char uri_string[MAX_URI_SIZE+1]; db_row_t* row; db_val_t* val; regex_t preg; int_str tag_avp, avp_val; int count = 0; if (IS_SIP(msg)) { if (parse_from_header(msg) < 0) return -1; uri = get_from(msg)->uri; if (uri.len > MAX_URI_SIZE) { LM_ERR("message has From URI too large\n"); return -1; } memcpy(uri_string, uri.s, uri.len); uri_string[uri.len] = (char)0; } get_tag_avp(&tag_avp, &tag_avp_type); row = RES_ROWS(_r); for(i = 0; i < RES_ROW_N(_r); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row + i) == 3) && (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) && match_proto(VAL_STRING(val), proto) && (VAL_NULL(val + 1) || ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1))) && (VAL_NULL(val + 2) || ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2)))) { if (!VAL_NULL(val + 1) && IS_SIP(msg)) { if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) { LM_ERR("invalid regular expression\n"); continue; } if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) { regfree(&preg); continue; } regfree(&preg); } /* Found a match */ if (tag_avp.n && !VAL_NULL(val + 2)) { avp_val.s.s = (char *)VAL_STRING(val + 2); avp_val.s.len = strlen(avp_val.s.s); if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) { LM_ERR("failed to set of tag_avp failed\n"); return -1; } } if (!peer_tag_mode) return 1; count++; } } if (!count) return -1; else return count; }
/*! \brief * Insert manually created Record-Route header, no checks, no restrictions, * always adds lr parameter, only fromtag is added automatically when requested */ int record_route_preset(struct sip_msg* _m, str* _data) { str user; struct to_body* from; struct lump* l, *lp, *ap; struct lump* l2; char *hdr, *suffix, *p, *term; int hdr_len, suffix_len; from = 0; user.len = 0; user.s = 0; if (add_username) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; } hdr_len = RR_PREFIX_LEN; if (user.len) hdr_len += user.len + 1; /* @ */ hdr_len += _data->len; suffix_len = 0; if (append_fromtag && from->tag_value.len) { suffix_len += RR_FROMTAG_LEN + from->tag_value.len; } suffix_len += RR_LR_LEN; hdr = pkg_malloc(hdr_len); term = pkg_malloc(RR_TERM_LEN); suffix = pkg_malloc(suffix_len); if (!hdr || !term || !suffix) { LM_ERR("no pkg memory left\n"); return -4; } /* header */ p = hdr; memcpy(p, RR_PREFIX, RR_PREFIX_LEN); p += RR_PREFIX_LEN; if (user.len) { memcpy(p, user.s, user.len); p += user.len; *p = '@'; p++; } memcpy(p, _data->s, _data->len); p += _data->len; /*suffix*/ p = suffix; if (append_fromtag && from->tag_value.len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, from->tag_value.s, from->tag_value.len); p += from->tag_value.len; } memcpy(p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; memcpy(term, RR_TERM, RR_TERM_LEN); l = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); if (!l || !l2) { LM_ERR("failed to create lump anchor\n"); goto error; } if (!(l=insert_new_lump_after(l, hdr, hdr_len, 0))) { LM_ERR("failed to insert new lump\n"); goto error; } hdr = NULL; l2 = insert_new_lump_before(l2, suffix, suffix_len, HDR_RECORDROUTE_T); if (l2==NULL) { LM_ERR("failed to insert suffix lump\n"); goto error; } suffix = NULL; /* look for pending RR params */ for( lp=NULL,ap=_m->add_rm ; ap ; ap=ap->next ) { if (ap->type==HDR_RECORDROUTE_T && ap->op==LUMP_NOP && ap->before && ap->before->op==LUMP_ADD_OPT && ap->before->u.cond==COND_FALSE) { /* found our phony anchor lump */ /* jump over the anchor and conditional lumps */ lp = ap->before->before; /* unlink it */ ap->before->before = NULL; ap->type = 0; /* link the pending buffered params and go at the end of the list*/ for ( l2->before = lp ; l2 && l2->before ; l2=l2->before); break; } } if (!(l2=insert_new_lump_before(l2, term, RR_TERM_LEN, 0))) { LM_ERR("failed to insert term lump"); goto error; } term = NULL; return 1; error: if (hdr) pkg_free(hdr); if (term) pkg_free(term); if (suffix) pkg_free(suffix); return -1; }
/* * function that simply prints the parameters passed */ static int siprec_start_rec(struct sip_msg *msg, str *srs, str *group, str *_cA, str *_cB, str *rtp, str *m_ip) { int ret; str *aor, *display, *xml_val; struct src_sess *ss; struct dlg_cell *dlg; /* create the dialog, if does not exist yet */ dlg = srec_dlg.get_dlg(); if (!dlg) { if (srec_dlg.create_dlg(msg, 0) < 0) { LM_ERR("cannot create dialog!\n"); return -2; } dlg = srec_dlg.get_dlg(); } /* XXX: if there is a forced send socket in the message, use it * this is the only way to provide a different socket for SRS, but * we might need to take a different approach */ /* check if the current dialog has a siprec session ongoing */ if (!(ss = src_new_session(srs, rtp, m_ip, group, msg->force_send_socket))) { LM_ERR("cannot create siprec session!\n"); return -2; } /* we ref the dialog to make sure it does not dissapear until we receive * the reply from the SRS */ srec_dlg.ref_dlg(dlg, 1); ss->dlg = dlg; ret = -2; /* caller info */ if (_cA) { xml_val = _cA; display = aor = NULL; } else { if (parse_from_header(msg) < 0) { LM_ERR("cannot parse from header!\n"); goto session_cleanup; } aor = &get_from(msg)->uri; display = (get_from(msg)->display.s ? &get_from(msg)->display : NULL); xml_val = NULL; } if (src_add_participant(ss, aor, display, xml_val, NULL) < 0) { LM_ERR("cannot add caller participant!\n"); goto session_cleanup; } if (srs_fill_sdp_stream(msg, ss, &ss->participants[0], 0) < 0) { LM_ERR("cannot add SDP for caller!\n"); goto session_cleanup; } /* caller info */ if (_cB) { xml_val = _cB; } else { if ((!msg->to && parse_headers(msg, HDR_TO_F, 0) < 0) || !msg->to) { LM_ERR("inexisting or invalid to header!\n"); goto session_cleanup; } aor = &get_to(msg)->uri; display = (get_to(msg)->display.s ? &get_to(msg)->display : NULL); xml_val = NULL; } if (src_add_participant(ss, aor, display, xml_val, NULL) < 0) { LM_ERR("cannot add callee pariticipant!\n"); goto session_cleanup; } SIPREC_REF_UNSAFE(ss); if (srec_tm.register_tmcb(msg, 0, TMCB_RESPONSE_OUT, tm_start_recording, ss, src_unref_session) <= 0) { LM_ERR("cannot register tm callbacks\n"); SIPREC_UNREF_UNSAFE(ss); goto session_cleanup; } return 1; session_cleanup: src_free_session(ss); return ret; }
void dlg_bridge_tm_callback(struct cell *t, int type, struct tmcb_params *ps) { struct sip_msg *msg = NULL; dlg_transfer_ctx_t *dtc = NULL; struct dlg_cell *dlg = NULL; str s; str cseq; str empty = {"", 0}; if(ps->param==NULL || *ps->param==0) { LM_DBG("message id not received\n"); return; } dtc = *((dlg_transfer_ctx_t**)ps->param); if(dtc==NULL) return; LM_DBG("completed with status %d\n", ps->code); if(ps->code>=300) goto error; /* 2xx - build dialog/send refer */ msg = ps->rpl; if((msg->cseq==NULL || parse_headers(msg,HDR_CSEQ_F,0)<0) || msg->cseq==NULL || msg->cseq->parsed==NULL) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); goto error; } cseq = (get_cseq(msg))->number; if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL) { LM_ERR("bad request or missing TO hdr\n"); goto error; } if(parse_from_header(msg)) { LM_ERR("bad request or missing FROM hdr\n"); goto error; } if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0) || msg->callid==NULL){ LM_ERR("bad request or missing CALLID hdr\n"); goto error; } s = msg->callid->body; trim(&s); /* some sanity checks */ if (s.len==0 || get_from(msg)->tag_value.len==0) { LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n", s.len, get_from(msg)->tag_value.len); goto error; } dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/, &(get_to(msg)->uri) /*to uri*/, &(get_from(msg)->tag_value)/*from_tag*/, &(get_to(msg)->uri) /*use to as r-uri*/ ); if (dlg==0) { LM_ERR("failed to create new dialog\n"); goto error; } dtc->dlg = dlg; if (dlg_set_leg_info(dlg, &(get_from(msg)->tag_value), &empty, &dlg_bridge_controller, &cseq, DLG_CALLER_LEG)!=0) { LM_ERR("dlg_set_leg_info failed\n"); goto error; } if (populate_leg_info(dlg, msg, t, DLG_CALLEE_LEG, &(get_to(msg)->tag_value)) !=0) { LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); goto error; } if(dlg_refer_callee(dtc)!=0) goto error; return; error: dlg_transfer_ctx_free(dtc); return; }
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2) { struct to_body *pto, TO = {0}, *pfrom = NULL; str body= {0, 0}; ua_pres_t dialog; str* res_id= NULL; db_key_t query_cols[8]; db_val_t query_vals[8]; int n_query_cols= 0; str auth_state= {0, 0}; int found= 0; str reason = {0, 0}; int auth_flag; struct hdr_field* hdr= NULL; int expires= -1; str content_type= {0, 0}; int reply_code = 500; str reply_str = pu_500_rpl; 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"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); reply_code = 400; reply_str = pu_400_rpl; 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"); reply_code = 400; reply_str = pu_400_rpl; goto error; } pto = &TO; } 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"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); reply_code = 400; reply_str = pu_400_rpl; 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"); reply_code = 400; reply_str = pu_400_rpl; 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"); reply_code = 400; reply_str = pu_400_rpl; 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"); reply_code = 489; reply_str = pu_489_rpl; goto error; } /* extract the subscription state */ hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0) { found = 1; break; } hdr = hdr->next; } if(found==0 ) { 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(pua_get_record_id(&dialog, &res_id)< 0) /* verify if within a stored dialog */ { LM_ERR("occured when trying to get record id\n"); goto error; } if(res_id==0) { LM_DBG("presence dialog record not found\n"); /* if it is a NOTIFY for a terminated SUBSCRIBE dialog in RLS, then * the module might not have the dialog structure anymore * - just send 200ok, it is harmless */ if(auth_flag==TERMINATED_STATE) goto done; LM_INFO("no presence dialog record for non-TERMINATED state uri pres_uri = %.*s watcher_uri = %.*s\n", dialog.pres_uri->len, dialog.pres_uri->s, dialog.watcher_uri->len, dialog.watcher_uri->s); reply_code = 481; reply_str = pu_481_rpl; goto error; } if(msg->content_type== NULL || msg->content_type->body.s== NULL) { LM_DBG("cannot find content type header header\n"); } else content_type= msg->content_type->body; /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { goto done; } else { if(content_type.s== 0) { LM_ERR("content length != 0 and no content type header found\n"); goto error; } body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); goto error; } body.len = get_content_length( msg ); } /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/ LM_DBG("body= %.*s\n", body.len, body.s); query_cols[n_query_cols]= &str_rlsubs_did_col; query_vals[n_query_cols].type = DB1_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 = DB1_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 = DB1_INT; query_vals[n_query_cols].nul = 0; if (dbmode == RLS_DB_ONLY) query_vals[n_query_cols].val.int_val= core_hash(res_id, NULL, 0) % (waitn_time * rls_notifier_poll_rate * rls_notifier_processes); else 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 = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= auth_flag; n_query_cols++; query_cols[n_query_cols]= &str_reason_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; if(reason.len > 0) { query_vals[n_query_cols].val.str_val.s= reason.s; query_vals[n_query_cols].val.str_val.len= reason.len; } else { query_vals[n_query_cols].val.str_val.s = ""; query_vals[n_query_cols].val.str_val.len = 0; } n_query_cols++; query_cols[n_query_cols]= &str_content_type_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= content_type; n_query_cols++; query_cols[n_query_cols]= &str_presence_state_col; query_vals[n_query_cols].type = DB1_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 = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL); n_query_cols++; if (rlpres_dbf.use_table(rlpres_db, &rlpres_table) < 0) { LM_ERR("in use_table\n"); goto error; } if (dbmode == RLS_DB_ONLY && rlpres_dbf.start_transaction) { if (rlpres_dbf.start_transaction(rlpres_db) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (rlpres_dbf.replace != NULL) { if(rlpres_dbf.replace(rlpres_db, query_cols, query_vals, n_query_cols, 2, 0)< 0) { LM_ERR("in sql replace\n"); goto error; } LM_DBG("Inserted/replace in database table new record\n"); } else { if(rlpres_dbf.update(rlpres_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; } if (rlpres_dbf.affected_rows(rlpres_db) == 0) { if(rlpres_dbf.insert(rlpres_db, query_cols, query_vals, n_query_cols)< 0) { LM_ERR("in sql insert\n"); goto error; } LM_DBG("Inserted in database table new record\n"); } } if (dbmode == RLS_DB_ONLY && rlpres_dbf.end_transaction) { if (rlpres_dbf.end_transaction(rlpres_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } LM_DBG("Updated rlpres_table\n"); /* reply 200OK */ done: if(slb.freply(msg, 200, &su_200_rpl) < 0) { LM_ERR("while sending reply\n"); goto error; } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); return 1; error: if(slb.freply(msg, reply_code, &reply_str) < 0) { LM_ERR("failed sending reply\n"); } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); if (dbmode == RLS_DB_ONLY && rlpres_dbf.abort_transaction) { if (rlpres_dbf.abort_transaction(rlpres_db) < 0) LM_ERR("in abort_transaction\n"); } return -1; }
/** * manage SIP message */ int xjab_manage_sipmsg(struct sip_msg *msg, int type) { str body, dst, from_uri; xj_sipmsg jsmsg; int pipe, fl; t_xj_jkey jkey, *p; int mime; body.len = 0; body.s = 0; // extract message body - after that whole SIP MESSAGE is parsed if (type==XJ_SEND_MESSAGE) { /* get the message's body */ body.s = get_body( msg ); if(body.s==0) { LM_ERR("cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ if(!msg->content_length) { LM_ERR("no Content-Length header found!\n"); goto error; } body.len = get_content_length(msg); /* parse the content-type header */ if((mime=parse_content_type_hdr(msg))<1) { LM_ERR("cannot parse Content-Type header\n"); goto error; } /* check the content-type value */ if(mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM) { LM_ERR("invalid content-type for" " a message request! type found=%d\n", mime); goto error; } } // check for TO and FROM headers - if is not SIP MESSAGE if(parse_headers(msg,HDR_TO_F|HDR_FROM_F,0)==-1 || !msg->to || !msg->from) { LM_ERR("cannot find TO or FROM HEADERS!\n"); goto error; } /* parsing from header */ if ( parse_from_header( msg )<0 || msg->from->parsed==NULL) { LM_DBG("cannot get FROM header\n"); goto error; } from_uri.s = ((struct to_body*)msg->from->parsed)->uri.s; from_uri.len = ((struct to_body*)msg->from->parsed)->uri.len; if(xj_extract_aor(&from_uri, 0)) { LM_DBG("cannot get AoR from FROM header\n"); goto error; } jkey.hash = xj_get_hash(&from_uri, NULL); jkey.id = &from_uri; // get the communication pipe with the worker switch(type) { case XJ_SEND_MESSAGE: case XJ_JOIN_JCONF: case XJ_GO_ONLINE: if((pipe = xj_wlist_get(jwl, &jkey, &p)) < 0) { LM_DBG("cannot find pipe of the worker!\n"); goto error; } break; case XJ_EXIT_JCONF: case XJ_GO_OFFLINE: if((pipe = xj_wlist_check(jwl, &jkey, &p)) < 0) { LM_DBG("no open Jabber session for" " <%.*s>!\n", from_uri.len, from_uri.s); goto error; } break; default: LM_DBG("ERROR:strange SIP msg type!\n"); goto error; } // if is for going ONLINE/OFFLINE we do not need the destination if(type==XJ_GO_ONLINE || type==XJ_GO_OFFLINE) goto prepare_job; // determination of destination // - try to get it from new_uri, r-uri or to hdr, but check it against // jdomain and aliases dst.len = 0; if( msg->new_uri.len > 0) { dst.s = msg->new_uri.s; dst.len = msg->new_uri.len; if(xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using NEW URI for destination\n"); #endif } if (dst.len == 0 && msg->first_line.u.request.uri.s != NULL && msg->first_line.u.request.uri.len > 0 ) { dst.s = msg->first_line.u.request.uri.s; dst.len = msg->first_line.u.request.uri.len; if(xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using R-URI for destination\n"); #endif } if(dst.len == 0 && msg->to->parsed) { dst.s = ((struct to_body*)msg->to->parsed)->uri.s; dst.len = ((struct to_body*)msg->to->parsed)->uri.len; if(dst.s == NULL || xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using TO-URI for destination\n"); #endif } if(dst.len == 0) { LM_DBG("destination not found in SIP message\n"); goto error; } /** skip 'sip:' and parameters in destination address */ if(xj_extract_aor(&dst, 1)) { LM_ERR("cannot get AoR for destination\n"); goto error; } #ifdef XJ_EXTRA_DEBUG LM_DBG("destination after correction [%.*s].\n", dst.len, dst.s); #endif prepare_job: //putting the SIP message parts in share memory to be accessible by workers jsmsg = (xj_sipmsg)shm_malloc(sizeof(t_xj_sipmsg)); memset(jsmsg, 0, sizeof(t_xj_sipmsg)); if(jsmsg == NULL) return -1; switch(type) { case XJ_SEND_MESSAGE: jsmsg->msg.len = body.len; if((jsmsg->msg.s = (char*)shm_malloc(jsmsg->msg.len+1)) == NULL) { shm_free(jsmsg); goto error; } strncpy(jsmsg->msg.s, body.s, jsmsg->msg.len); break; case XJ_GO_ONLINE: case XJ_GO_OFFLINE: dst.len = 0; dst.s = 0; case XJ_JOIN_JCONF: case XJ_EXIT_JCONF: jsmsg->msg.len = 0; jsmsg->msg.s = NULL; break; default: LM_DBG("this SHOULD NOT appear\n"); shm_free(jsmsg); goto error; } if(dst.len>0) { jsmsg->to.len = dst.len; if((jsmsg->to.s = (char*)shm_malloc(jsmsg->to.len+1))==NULL) { if(type == XJ_SEND_MESSAGE) shm_free(jsmsg->msg.s); shm_free(jsmsg); goto error; } strncpy(jsmsg->to.s, dst.s, jsmsg->to.len); } else { jsmsg->to.len = 0; jsmsg->to.s = 0; } jsmsg->jkey = p; jsmsg->type = type; //jsmsg->jkey->hash = jkey.hash; LM_DBG("sending <%p> to worker through <%d>\n", jsmsg, pipe); // sending the SHM pointer of SIP message to the worker fl = write(pipe, &jsmsg, sizeof(jsmsg)); if(fl != sizeof(jsmsg)) { LM_ERR("failed to write to worker pipe!\n"); if(type == XJ_SEND_MESSAGE) shm_free(jsmsg->msg.s); shm_free(jsmsg->to.s); shm_free(jsmsg); goto error; } return 1; error: return -1; }
/* * determines the permission to an uri * return values: * -1: deny * 1: allow */ static int allow_uri(struct sip_msg* msg, char* _idx, char* _sp) { struct hdr_field *from; int idx, len; static char from_str[EXPRESSION_LENGTH+1]; static char uri_str[EXPRESSION_LENGTH+1]; pv_spec_t *sp; pv_value_t pv_val; idx = (int)(long)_idx; sp = (pv_spec_t *)_sp; /* turn off control, allow any uri */ if ((!allow[idx].rules) && (!deny[idx].rules)) { LM_DBG("no rules => allow any uri\n"); return 1; } /* looking for FROM HF */ if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) { LM_ERR("failed to parse message\n"); return -1; } if (!msg->from) { LM_ERR("FROM header field not found\n"); return -1; } /* we must call parse_from_header explicitly */ if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) { LM_ERR("failed to parse From body\n"); return -1; } from = msg->from; len = ((struct to_body*)from->parsed)->uri.len; if (len > EXPRESSION_LENGTH) { LM_ERR("From header field is too long: %d chars\n", len); return -1; } strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len); from_str[len] = '\0'; if (sp && (pv_get_spec_value(msg, sp, &pv_val) == 0)) { if (pv_val.flags & PV_VAL_STR) { if (pv_val.rs.len > EXPRESSION_LENGTH) { LM_ERR("pseudo variable value is too " "long: %d chars\n", pv_val.rs.len); return -1; } strncpy(uri_str, pv_val.rs.s, pv_val.rs.len); uri_str[pv_val.rs.len] = '\0'; } else { LM_ERR("pseudo variable value is not string\n"); return -1; } } else { LM_ERR("cannot get pseudo variable value\n"); return -1; } LM_DBG("looking for From: %s URI: %s\n", from_str, uri_str); /* rule exists in allow file */ if (search_rule(allow[idx].rules, from_str, uri_str)) { LM_DBG("allow rule found => URI is allowed\n"); return 1; } /* rule exists in deny file */ if (search_rule(deny[idx].rules, from_str, uri_str)) { LM_DBG("deny rule found => URI is denied\n"); return -1; } LM_DBG("neither allow nor deny rule found => URI is allowed\n"); return 1; }
static int sip_trace(struct sip_msg *msg, char *s1, char *s2) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+6]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+6]; int_str avp_value; struct usr_avp *avp; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return -1; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) { LM_DBG("trace off...\n"); return -1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse call-id\n"); goto error; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; if(msg->first_line.type==SIP_REQUEST) { db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; } else { db_vals[2].val.str_val.s = ""; db_vals[2].val.str_val.len = 0; } db_keys[3] = status_column; db_vals[3].type = DB_STR; db_vals[3].nul = 0; if(msg->first_line.type==SIP_REPLY) { db_vals[3].val.str_val.s = msg->first_line.u.reply.status.s; db_vals[3].val.str_val.len = msg->first_line.u.reply.status.len; } else { db_vals[3].val.str_val.s = ""; db_vals[3].val.str_val.len = 0; } db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if(trace_on_flag!=NULL && *trace_on_flag!=0) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS if(msg->first_line.type==SIP_REPLY) { update_stat(siptrace_rpl, 1); } else { update_stat(siptrace_req, 1); } #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return 1; error: return -1; }
static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps) { struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; if(t==NULL || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } msg = ps->req; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(msg)) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); return; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } if (msg->REQ_METHOD==METHOD_INVITE) { LM_DBG("noisy_timer set for tracing\n"); t->flags |= T_NOISY_CTIMER_FLAG; } if(tmb.register_tmcb( 0, t, TMCB_REQUEST_BUILT, trace_onreq_out, 0) <=0) { LM_ERR("can't register trace_onreq_out\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_IN, trace_onreply_in, 0) <=0) { LM_ERR("can't register trace_onreply_in\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_OUT, trace_onreply_out, 0) <=0) { LM_ERR("can't register trace_onreply_out\n"); return; } }
/* look for subscriber cell using callid and to_tag of Notify*/ struct sm_subscriber* get_subs_cell(struct sip_msg *msg, str callid_event) { str callid; str method; struct to_body *pto= NULL, *pfrom = NULL; struct sm_subscriber* s; unsigned int hash_code; method.s = msg->first_line.u.request.method.s; method.len = msg->first_line.u.request.method.len; if ( parse_headers(msg,HDR_EOH_F, 0) == -1 ){ LM_ERR("error in parsing headers\n"); return NULL; } // get callid from Notify if( msg->callid==NULL || msg->callid->body.s==NULL){ LM_ERR("reply without callid header\n"); return NULL; } callid = msg->callid->body; LM_DBG("CALLID: %.*s \n ", callid.len, callid.s ); if (msg->from->parsed == NULL){ if ( parse_from_header( msg )<0 ){ LM_ERR("reply without From header\n"); return NULL; } } //get From header from Notify pfrom = get_from(msg); LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s ); if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){ LM_ERR("reply without tag value \n"); return NULL; } if( msg->to==NULL || msg->to->body.s==NULL){ LM_ERR("error in parse TO header\n"); return NULL; } // get To header from Notify pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return NULL; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0){ LM_ERR("reply without tag value \n"); } LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s ); LM_DBG("PTO_TAG: %.*s \n ", pto->tag_value.len, pto->tag_value.s ); LM_DBG("********************************************CALLID_STR%.*s\n", callid_event.len, callid_event.s); hash_code= core_hash(&callid_event, 0, subst_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); s= search_shtable(subs_htable, &callid, &pfrom->tag_value, hash_code, &method); if (s == NULL) { LM_ERR(" ---FAILURE SUB_CELL NOT FOUND IN SHTABLE\n"); } return s; }
static void trace_sl_onreply_out( unsigned int types, struct sip_msg* req, struct sl_cb_param *sl_param) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; int faked = 0; struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[5]; if(req==NULL || sl_param==NULL) { LM_ERR("bad parameters\n"); goto error; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } msg = req; faked = 1; if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = (sl_param->buffer)?sl_param->buffer->s:""; db_vals[0].val.blob_val.len = (sl_param->buffer)?sl_param->buffer->len:0; /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(sl_param->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); if(sl_param->dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, sl_param->dst); siptrace_copy_proto(req->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(sl_param->dst), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(msg) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
/* Get some fields necessary to pass in function_cb*/ int build_params_cb(struct sip_msg* msg, char* callidHeader, struct parms_cb* params_cb ){ char *dialog_aux; str from_tag; int size_callid; int size_dialog; char *dialog; if (parse_from_header(msg) != 0) { LM_ERR(" REQUEST WITHOUT FROM HEADER\n"); } from_tag = get_from(msg)->tag_value; LM_DBG("FROM_TAG: %.*s\n", from_tag.len, from_tag.s); LM_DBG("CALLID = %s \n", callidHeader); size_callid = strlen(callidHeader); size_dialog= size_callid + from_tag.len + 26; dialog_aux = shm_malloc (sizeof (char)* size_dialog + 1); if (dialog_aux == NULL) { LM_ERR("--------------------------------------------------no more pkg memory\n"); return 0; } memset(dialog_aux, 0, size_dialog + 1); dialog = dialog_aux; memcpy(dialog_aux, "dialog; call-id=", 16); dialog_aux += 16; memcpy(dialog_aux, callidHeader, size_callid); dialog_aux += size_callid; memcpy(dialog_aux, ";from-tag=", 10); dialog_aux += 10; memcpy(dialog_aux, from_tag.s, from_tag.len); LM_DBG("dialog: %s\n", dialog); char *call_aux = shm_malloc (size_callid + 1); if (call_aux == NULL) { LM_ERR("--------------------------------------------------no more pkg memory\n"); return 0; } call_aux[size_callid] = 0; memcpy(call_aux, callidHeader, size_callid); char *ftag = shm_malloc (from_tag.len + 1); if (ftag == NULL) { LM_ERR("--------------------------------------------------no more pkg memory\n"); return 0; } ftag[from_tag.len] = 0; memcpy(ftag, from_tag.s, from_tag.len); params_cb->callid_ori.s = call_aux; params_cb->callid_ori.len = size_callid; params_cb->from_tag.s = ftag; params_cb->from_tag.len = from_tag.len; params_cb->event.s = dialog; params_cb->event.len = size_dialog; 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) { LM_ERR("no more share memory\n"); goto mem_error; } 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) { LM_ERR("no more share memory\n"); goto mem_error; } 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->extra_headers.s) shm_free(hentity->extra_headers.s); shm_free(hentity); return; mem_error: if(presentity->extra_headers.s) shm_free(presentity->extra_headers.s); if(presentity->remote_contact.s) shm_free(presentity->remote_contact.s); shm_free(presentity); if(hentity->extra_headers.s) shm_free(hentity->extra_headers.s); shm_free(hentity); }
/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */ static int eval_elem(struct expr* e, struct sip_msg* msg) { struct sip_uri uri; int ret; ret=E_BUG; if (e->type!=ELEM_T){ LOG(L_CRIT," BUG: eval_elem: invalid type\n"); goto error; } switch(e->l.operand){ case METHOD_O: ret=comp_strstr(&msg->first_line.u.request.method, e->r.param, e->op, e->subtype); break; case URI_O: if(msg->new_uri.s){ if (e->subtype==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&msg->new_uri, e->r.param, e->op, e->subtype); } }else{ if (e->subtype==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&msg->first_line.u.request.uri, e->r.param, e->op, e->subtype); } } break; case FROM_URI_O: if (parse_from_header(msg)!=0){ LOG(L_ERR, "ERROR: eval_elem: bad or missing" " From: header\n"); goto error; } if (e->subtype==MYSELF_ST){ if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len, &uri) < 0){ LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&get_from(msg)->uri, e->r.param, e->op, e->subtype); } break; case TO_URI_O: if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) || (msg->to==0))){ LOG(L_ERR, "ERROR: eval_elem: bad or missing" " To: header\n"); goto error; } /* to content is parsed automatically */ if (e->subtype==MYSELF_ST){ if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len, &uri) < 0){ LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&get_to(msg)->uri, e->r.param, e->op, e->subtype); } break; case SRCIP_O: ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype); break; case DSTIP_O: ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype); break; case NUMBER_O: ret=!(!e->r.intval); /* !! to transform it in {0,1} */ break; case ACTION_O: ret=run_action_list( (struct action*)e->r.param, msg); if (ret<=0) ret=(ret==0)?EXPR_DROP:0; else ret=1; break; case SRCPORT_O: ret=comp_no(msg->rcv.src_port, e->r.param, /* e.g., 5060 */ e->op, /* e.g. == */ e->subtype /* 5060 is number */); break; case DSTPORT_O: ret=comp_no(msg->rcv.dst_port, e->r.param, e->op, e->subtype); break; case PROTO_O: ret=comp_no(msg->rcv.proto, e->r.param, e->op, e->subtype); break; case AF_O: ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype); break; case RETCODE_O: ret=comp_no(return_code, e->r.param, e->op, e->subtype); break; case MSGLEN_O: ret=comp_no(msg->len, e->r.param, e->op, e->subtype); break; default: LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n", e->l.operand); } return ret; error: return -1; }
/*Actions are composed as follows: * (the action length and type as always= 5 bytes) * 4:uac_id * * int request(str* method, str* req_uri, str* to, str* from, str* headers, str* body, transaction_cb c, void* cp) * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int cseq; char err_buf[MAX_REASON_LEN]; struct sip_msg *my_msg; struct to_body *fb,*tb; struct cseq_body *cseqb; struct as_uac_param *the_param; dlg_t *my_dlg; int k,retval,uac_id,sip_error,ret,err_ret; long clen; str headers,body,fake_uri; uac_req_t uac_r; headers.s=body.s=fake_uri.s=NULL; my_dlg=NULL; my_msg=NULL; the_param=NULL; k=clen=0; net2hostL(uac_id,action,k); if(!(headers.s=pkg_malloc(MAX_HEADER))){ LM_ERR("Out of Memory!!"); goto error; } headers.len=0; LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id); if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type==SIP_REPLY){ LM_ERR("trying to create a UAC with a SIP response!!\n"); goto error; } if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); goto error; } if(parse_from_header(my_msg)<0){ LM_ERR("parsing from header ! \n"); goto error; } if(check_transaction_quadruple(my_msg)==0){ as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0); LM_ERR("Headers missing (to,from,call-id,cseq)?"); goto error; } if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || !(get_from(my_msg)->tag_value.len)){ as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0); LM_ERR("From tag missing"); goto error; } fb=my_msg->from->parsed; tb=my_msg->to->parsed; cseqb=my_msg->cseq->parsed; if(0!=(str2int(&cseqb->number,&cseq))){ LM_DBG("unable to parse CSeq\n"); goto error; } if(my_msg->first_line.u.request.method_value != METHOD_ACK && my_msg->first_line.u.request.method_value != METHOD_CANCEL) { /** we trick req_within */ cseq--; } if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\ &(fb->uri),&(tb->uri),&my_dlg) < 0) { as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0); LM_ERR("Error while creating new dialog\n"); goto error; } if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) { as_action_fail_resp(uac_id,SE_UAC, "Error adding the display names to the new dialog",0); LM_ERR("failed to add display names to the new dialog\n"); goto error; } if(tb->tag_value.s && tb->tag_value.len) shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value); /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have * to use req_within instead of req_outside (it sets it's own CSeq,Call-ID * and ftag), so we have to simulate that the dialog is already in completed * state so... */ server_signature=0; my_dlg->state = DLG_CONFIRMED; if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { LM_ERR("Unable to extract allowed headers!!\n"); goto error; } headers.s[headers.len]=0; /*let's get the body*/ if(my_msg->content_length) clen=(long)get_content_length(my_msg); if(clen!=0){ if(!(body.s=pkg_malloc(clen))){ LM_ERR("Out of Memory!"); goto error; } memcpy(body.s,get_body(my_msg),clen); body.len=clen; body.s[clen]=0; LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\ body.len,body.len,body.s,headers.len,headers.len,headers.s); /*t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ }else{ body.s=NULL; body.len=0; } /*Now... create the UAC !! * it would be great to know the hash_index and the label that have been assigned * to our newly created cell, but t_uac does not leave any way for us to know... * only that when that transaction transitions its state (ie. a response is received, * a timeout is reached, etc...) the callback will be called with the given parameter. * * So the only way we have to know who we are, is passing as a parameter a structure with * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id). * */ if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("out of shared memory\n"); goto error; } the_param->who=my_as; the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } /* TODO route_set should be a shm copy of my_msg->route->parsed */ my_dlg->route_set=(rr_t*)my_msg->route->parsed; /** this SHOULD be: shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed); * but it will last more... */ } calculate_hooks(my_dlg); if(flags & SPIRAL_FLAG){ memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); if(fake_uri.len<0){ LM_ERR("printing local uri\n"); goto error; } my_dlg->hooks.next_hop=&fake_uri; } /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events notified to UACs. Let's see if kamailio gets it right by now, if not this is a TODO: check PASS_PROVISIONAL my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ; this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio */ set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb, (void*)the_param); ret=seas_f.tmb.t_request_within(&uac_r); /** now undo all the fakes we have put in my_dlg*/ /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ my_dlg->route_set=(rr_t *)0; if (ret < 0) { err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC"); LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s); LM_ERR("Error on request_within %s\n",err_buf ); if(err_ret > 0) { as_action_fail_resp(uac_id,ret,err_buf,0); }else{ as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0); } goto error; } retval=0; goto exit; error: retval = -1; if(the_param) shm_free(the_param); exit: seas_f.tmb.free_dlg(my_dlg); if(headers.s) pkg_free(headers.s); if(body.s) pkg_free(body.s); if(fake_uri.s) pkg_free(fake_uri.s); if(my_msg){ if(my_msg->headers) free_hdr_field_lst(my_msg->headers); pkg_free(my_msg); } return retval; }
static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; char statusbuf[8]; if(t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || req==NULL) { LM_DBG("no reply\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; if(trace_local_ip) db_vals[5].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info ...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
/** * store message * mode = "0" -- look for outgoing URI starting with new_uri * = "1" -- look for outgoing URI starting with r-uri * = "2" -- look for outgoing URI only at to header */ static int m_store(struct sip_msg* msg, char* mode, char* str2) { str body, str_hdr, sruri, ctaddr; struct to_body to, *pto, *pfrom; db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; int nr_keys = 0, val, lexpire; t_content_type ctype; char buf[512], buf1[1024], *p; int mime; DBG("MSILO: m_store: ------------ start ------------\n"); // extract message body - after that whole SIP MESSAGE is parsed /* get the message's body */ body.s = get_body( msg ); if (body.s==0) { LOG(L_ERR,"MSILO:m_store: ERROR cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ if (!msg->content_length) { LOG(L_ERR,"MSILO:m_store: ERROR no Content-Length header found!\n"); goto error; } body.len = get_content_length( msg ); // check if the body of message contains something if(body.len <= 0) { DBG("MSILO:m_store: body of the message is empty!\n"); goto error; } // check TO header if(!msg->to || !msg->to->body.s) { DBG("MSILO:m_store: cannot find 'to' header!\n"); goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; DBG("MSILO:m_store: 'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { DBG("MSILO:m_store: 'To' header NOT PARSED ->parsing ...\n"); memset( &to , 0, sizeof(to) ); parse_to(msg->to->body.s, msg->to->body.s+msg->to->body.len+1, &to); if(to.uri.len > 0) // && to.error == PARSE_OK) { DBG("MSILO:m_store: 'To' parsed OK <%.*s>.\n", to.uri.len, to.uri.s); pto = &to; } else { DBG("MSILO:m_store: ERROR 'To' cannot be parsed\n"); goto error; } } if(pto->uri.len == reg_addr.len && !strncasecmp(pto->uri.s, reg_addr.s, reg_addr.len)) { DBG("MSILO:m_store: message to MSILO REGISTRAR!\n"); goto error; } db_keys[nr_keys] = DB_KEY_TO; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = pto->uri.s; db_vals[nr_keys].val.str_val.len = pto->uri.len; nr_keys++; // check FROM header if(!msg->from || !msg->from->body.s) { DBG("MSILO:m_store: ERROR cannot find 'from' header!\n"); goto error; } if(msg->from->parsed != NULL) DBG("MSILO:m_store: 'From' header ALREADY PARSED\n"); else { DBG("MSILO:m_store: 'From' header NOT PARSED\n"); /* parsing from header */ if ( parse_from_header( msg )==-1 ) { DBG("MSILO:m_store: ERROR cannot parse FROM header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; DBG("MSILO:m_store: 'From' header: <%.*s>\n",pfrom->uri.len,pfrom->uri.s); if(reg_addr.s && pfrom->uri.len == reg_addr.len && !strncasecmp(pfrom->uri.s, reg_addr.s, reg_addr.len)) { DBG("MSILO:m_store: message from MSILO REGISTRAR!\n"); goto error; } db_keys[nr_keys] = DB_KEY_FROM; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = pfrom->uri.s; db_vals[nr_keys].val.str_val.len = pfrom->uri.len; nr_keys++; // chech for RURI sruri.len = 0; if(mode && mode[0]=='0' && msg->new_uri.len > 0) { DBG("MSILO:m_store: NEW R-URI found - check if is AoR!\n"); p = msg->new_uri.s; while((p < msg->new_uri.s+msg->new_uri.len) && *p!='@') p++; if(p < msg->new_uri.s+msg->new_uri.len && p > msg->new_uri.s) { DBG("MSILO:m_store: NEW R-URI used\n"); sruri.s = msg->new_uri.s; // check for parameters while((p < msg->new_uri.s+msg->new_uri.len) && *p!=';') p++; sruri.len = p - msg->new_uri.s; } } if(mode && mode[0]<='1' && sruri.len == 0 && msg->first_line.u.request.uri.len > 0 ) { DBG("MSILO:m_store: R-URI found - check if is AoR!\n"); p = msg->first_line.u.request.uri.s; while((p < msg->first_line.u.request.uri.s+ msg->first_line.u.request.uri.len) && *p!='@') p++; if(p<msg->first_line.u.request.uri.s+msg->first_line.u.request.uri.len && p > msg->first_line.u.request.uri.s) { DBG("MSILO:m_store: R-URI used\n"); sruri.s = msg->first_line.u.request.uri.s; // check for parameters while((p < msg->first_line.u.request.uri.s + msg->first_line.u.request.uri.len) && *p!=';') p++; sruri.len = p - msg->first_line.u.request.uri.s; } } if (sruri.len == 0) { DBG("MSILO:m_store: TO used as R-URI\n"); sruri.s = pto->uri.s; sruri.len = pto->uri.len; } db_keys[nr_keys] = DB_KEY_RURI; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = sruri.s; db_vals[nr_keys].val.str_val.len = sruri.len; nr_keys++; /* add the message's body in SQL query */ db_keys[nr_keys] = DB_KEY_BODY; db_vals[nr_keys].type = DB_BLOB; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.blob_val.s = body.s; db_vals[nr_keys].val.blob_val.len = body.len; nr_keys++; lexpire = expire_time; // add 'content-type' /* parse the content-type header */ if ((mime=parse_content_type_hdr(msg))<1 ) { LOG(L_ERR,"MSILO:m_store: ERROR cannot parse Content-Type header\n"); goto error; } /** check the content-type value */ if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) { if(m_extract_content_type(msg->content_type->body.s, msg->content_type->body.len, &ctype, CT_TYPE) != -1) { DBG("MSILO:m_store: 'content-type' found\n"); db_keys[nr_keys] = DB_KEY_CTYPE; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = ctype.type.s; db_vals[nr_keys].val.str_val.len = ctype.type.len; nr_keys++; } } // check 'expires' // no more parseing - already done by get_body() // if(parse_headers(msg, HDR_EXPIRES,0)!=-1) if(msg->expires && msg->expires->body.len > 0) { DBG("MSILO:m_store: 'expires' found\n"); val = atoi(msg->expires->body.s); if(val > 0) lexpire = (expire_time<=val)?expire_time:val; } /** current time */ val = (int)time(NULL); /** add expiration time */ db_keys[nr_keys] = DB_KEY_EXP_TIME; db_vals[nr_keys].type = DB_INT; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.int_val = val+lexpire; nr_keys++; /** add incoming time */ db_keys[nr_keys] = DB_KEY_INC_TIME; db_vals[nr_keys].type = DB_INT; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.int_val = val; nr_keys++; if(db_insert(db_con, db_keys, db_vals, nr_keys) < 0) { LOG(L_ERR, "MSILO:m_store: error storing message\n"); goto error; } DBG("MSILO:m_store: message stored. T:<%.*s> F:<%.*s>\n", pto->uri.len, pto->uri.s, pfrom->uri.len, pfrom->uri.s); if(reg_addr.len > 0 && reg_addr.len+33+2*CRLF_LEN < 1024) { DBG("MSILO:m_store: sending info message.\n"); strcpy(buf1,"Content-Type: text/plain"CRLF"Contact: "); str_hdr.len = 24 + CRLF_LEN + 9; strncat(buf1,reg_addr.s,reg_addr.len); str_hdr.len += reg_addr.len; strcat(buf1, CRLF); str_hdr.len += CRLF_LEN; str_hdr.s = buf1; strncpy(buf, "User [", 6); body.len = 6; if(pto->uri.len+75 < 512) { strncpy(buf+body.len, pto->uri.s, pto->uri.len); body.len += pto->uri.len; } strncpy(buf+body.len, "] is offline.", 13); body.len += 12; strncpy(buf+body.len, " The message will be delivered", 30); body.len += 30; strncpy(buf+body.len, " when user goes online.", 23); body.len += 23; body.s = buf; // look for Contact header ctaddr.s = NULL; if(use_contact && parse_headers(msg,HDR_CONTACT,0)!=-1 && msg->contact && msg->contact->body.s && msg->contact->body.len>0) { ctaddr.s = msg->contact->body.s; ctaddr.len = msg->contact->body.len; p = ctaddr.s; while(p<ctaddr.s+ctaddr.len && *p!='<') p++; if(*p == '<') { p++; ctaddr.s = p; while(p<ctaddr.s+ctaddr.len && *p!='>') p++; if(p<ctaddr.s+ctaddr.len) ctaddr.len = p-ctaddr.s; } if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4) || ctaddr.s[4]==' ') ctaddr.s = NULL; else DBG("MSILO:m_store: feedback contact [%.*s]\n", ctaddr.len,ctaddr.s); } // tmb.t_uac(&msg_type,&pfrom->uri,&str_hdr,&body,®_addr,0,0,0); tmb.t_request(&msg_type, /* Type of the message */ (ctaddr.s)?&ctaddr:&pfrom->uri, /* Request-URI */ &pfrom->uri, /* To */ ®_addr, /* From */ &str_hdr, /* Optional headers including CRLF */ &body, /* Message body */ NULL, /* Callback function */ NULL /* Callback parameter */ ); } return 1; error: return -1; }
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; int faked = 0; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[8]; str *sbuf; struct dest_info *dst; if (t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(t->uas.request)) { LM_DBG("trace off...\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || msg==FAKED_REPLY) { msg = t->uas.request; faked = 1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; sbuf = (str*)ps->extra1; if(faked==0) { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s!=NULL) { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } else if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } } else { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s==NULL) { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } else { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = (struct dest_info*)ps->extra2; if(dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, &dst->to); siptrace_copy_proto(dst->proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(&dst->to), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
/* * determines the permission of the call * return values: * -1: deny * 1: allow */ static int check_routing(struct sip_msg* msg, int idx) { struct hdr_field *from; int len, q; static char from_str[EXPRESSION_LENGTH+1]; static char ruri_str[EXPRESSION_LENGTH+1]; char* uri_str; str branch; int br_idx; /* turn off control, allow any routing */ if ((!allow[idx].rules) && (!deny[idx].rules)) { LM_DBG("no rules => allow any routing\n"); return 1; } /* looking for FROM HF */ if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) { LM_ERR("failed to parse message\n"); return -1; } if (!msg->from) { LM_ERR("FROM header field not found\n"); return -1; } /* we must call parse_from_header explicitly */ if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) { LM_ERR("failed to parse From body\n"); return -1; } from = msg->from; len = ((struct to_body*)from->parsed)->uri.len; if (len > EXPRESSION_LENGTH) { LM_ERR("From header field is too long: %d chars\n", len); return -1; } strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len); from_str[len] = '\0'; /* looking for request URI */ if (parse_sip_msg_uri(msg) < 0) { LM_ERR("uri parsing failed\n"); return -1; } len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5; if (len > EXPRESSION_LENGTH) { LM_ERR("Request URI is too long: %d chars\n", len); return -1; } strcpy(ruri_str, "sip:"); memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len); ruri_str[msg->parsed_uri.user.len + 4] = '@'; memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len); ruri_str[len] = '\0'; LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str); /* rule exists in allow file */ if (search_rule(allow[idx].rules, from_str, ruri_str)) { if (check_all_branches) goto check_branches; LM_DBG("allow rule found => routing is allowed\n"); return 1; } /* rule exists in deny file */ if (search_rule(deny[idx].rules, from_str, ruri_str)) { LM_DBG("deny rule found => routing is denied\n"); return -1; } if (!check_all_branches) { LM_DBG("neither allow nor deny rule found => routing is allowed\n"); return 1; } check_branches: for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0,0,0,0))!=0 ; br_idx++ ) { uri_str = get_plain_uri(&branch); if (!uri_str) { LM_ERR("failed to extract plain URI\n"); return -1; } LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str); if (search_rule(allow[idx].rules, from_str, uri_str)) { continue; } if (search_rule(deny[idx].rules, from_str, uri_str)) { LM_DBG("deny rule found for one of branches => routing" "is denied\n"); return -1; } } LM_DBG("check of branches passed => routing is allowed\n"); return 1; }
/* get data from Subscriber and save in list link with notify information: . dialog id of emergency call . dialog id of subscribe . local uri . remote uri . contact . expires . time to expire subscriber - status . cell next . cell previus */ struct sm_subscriber* build_notify_cell(struct sip_msg *msg, int expires){ char *subs_callid, *subs_fromtag; str callid_event; str fromtag_event; str callid; struct to_body *pto= NULL, *pfrom = NULL; int size_notify_cell; int vsp_addr_len; char *vsp_addr = "@vsp.com"; int vsp_port = 5060; int size_vsp_port = 4; char* str_vsp_port; struct sm_subscriber *notify_cell = NULL; time_t rawtime; int time_now; char *p; unsigned int hash_code; static str msg489={"Bad Event",sizeof("Bad Event")-1}; // get data from SUBSCRIBE request // get callid from Subscribe if( msg->callid==NULL || msg->callid->body.s==NULL){ LM_ERR("subscribe without callid header\n"); return NULL; } callid = msg->callid->body; LM_DBG("CALLID: %.*s \n ", callid.len, callid.s ); //get From header from Subscribe if (msg->from->parsed == NULL){ if ( parse_from_header( msg )<0 ){ LM_ERR("subscribe without From header\n"); return NULL; } } pfrom = get_from(msg); LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s ); LM_DBG("PFROM_TAG: %.*s \n ", pfrom->tag_value.len, pfrom->tag_value.s ); if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){ LM_ERR("subscribe without from_tag value \n"); return NULL; } if( msg->to==NULL || msg->to->body.s==NULL){ LM_ERR("error in parse TO header\n"); return NULL; } // get To header from Subscribe pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return NULL; } LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s ); LM_DBG("PTO_TAG: %.*s \n ", pto->tag_value.len, pto->tag_value.s ); /* get in event header: callid and from_tag */ if(get_event_header(msg, &subs_callid, &subs_fromtag) != 1){ LM_ERR("failed to parse Event header\n"); return NULL; } LM_DBG("SUBS_CALLID: %s\n ", subs_callid); LM_DBG("SUBS_FROMTAG: %s\n ", subs_fromtag); callid_event.s = subs_callid; callid_event.len = strlen(subs_callid); fromtag_event.s = subs_fromtag; fromtag_event.len = strlen(subs_fromtag); hash_code= core_hash(&callid_event, 0, emet_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); // search call hash with hash_code, callidHeader and from/to_tag params if (search_ehtable(call_htable, subs_callid, subs_fromtag, hash_code, 0) == NULL) { LM_ERR(" ---CALLID NOT FOUND IN SHTABLE\n"); if(!eme_tm.t_reply(msg,489,&msg489)){ LM_DBG("t_reply (489)\n"); } pkg_free(callid_event.s); pkg_free(fromtag_event.s); return 0; } LM_DBG("CALLID OK in subs_hash\n"); time(&rawtime); time_now = (int)rawtime; LM_DBG("TIME : %d \n", (int)rawtime ); // get source ip address that send INVITE vsp_addr = ip_addr2a(&msg->rcv.src_ip); vsp_addr_len = strlen(vsp_addr); vsp_port = msg->rcv.src_port; str_vsp_port= int2str(vsp_port, &size_vsp_port); LM_DBG("SRC_PORT : %s \n", str_vsp_port); /* build notifier cell */ size_notify_cell = sizeof(struct sm_subscriber) + (2 * sizeof(struct dialog_id)) + callid.len + pfrom->tag_value.len + pto->tag_value.len + pfrom->uri.len + pto->uri.len + callid_event.len + fromtag_event.len + vsp_addr_len + size_vsp_port + 11 ; notify_cell = pkg_malloc(size_notify_cell + 1); if (!notify_cell) { LM_ERR("no more shm\n"); return NULL; } memset(notify_cell, 0, size_notify_cell + 1); notify_cell->expires = expires; LM_DBG("EXPIRES: %d \n ", notify_cell->expires ); notify_cell->timeout = TIMER_N + time_now; LM_DBG("SUBS_TIMEOUT: %d \n ", notify_cell->timeout ); notify_cell->version = 0; LM_DBG("SUBS_VERSION: %d \n ", notify_cell->version ); notify_cell->dlg_id = (struct dialog_id*)(notify_cell + 1); notify_cell->dlg_id->callid.len = callid.len; notify_cell->dlg_id->callid.s = (char *) (notify_cell->dlg_id + 1); memcpy(notify_cell->dlg_id->callid.s, callid.s, callid.len); LM_DBG("SUBS_CALLID: %.*s \n ", notify_cell->dlg_id->callid.len, notify_cell->dlg_id->callid.s ); notify_cell->dlg_id->rem_tag.len = pfrom->tag_value.len; notify_cell->dlg_id->rem_tag.s = (char *) (notify_cell->dlg_id + 1) + callid.len; memcpy(notify_cell->dlg_id->rem_tag.s, pfrom->tag_value.s, pfrom->tag_value.len); LM_DBG("SUBS_FROM_TAG: %.*s \n ", notify_cell->dlg_id->rem_tag.len, notify_cell->dlg_id->rem_tag.s ); p = (char *)(notify_cell->dlg_id + 1) + callid.len + pfrom->tag_value.len; notify_cell->call_dlg_id = (struct dialog_id*)p; notify_cell->call_dlg_id->callid.len= callid_event.len; notify_cell->call_dlg_id->callid.s = (char *) (notify_cell->call_dlg_id + 1); memcpy(notify_cell->call_dlg_id->callid.s, callid_event.s, callid_event.len); LM_DBG("SUBS_CALLID_event: %.*s \n ", notify_cell->call_dlg_id->callid.len, notify_cell->call_dlg_id->callid.s ); notify_cell->call_dlg_id->rem_tag.len= fromtag_event.len; notify_cell->call_dlg_id->rem_tag.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len; memcpy(notify_cell->call_dlg_id->rem_tag.s, fromtag_event.s, fromtag_event.len); LM_DBG("SUBS_FROMTAG_event: %.*s \n ", notify_cell->call_dlg_id->rem_tag.len, notify_cell->call_dlg_id->rem_tag.s ); notify_cell->loc_uri.len = pto->uri.len; notify_cell->loc_uri.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len + fromtag_event.len; memcpy(notify_cell->loc_uri.s,pto->uri.s,pto->uri.len); LM_DBG("SUBS_LOC_URI: %.*s \n ", notify_cell->loc_uri.len, notify_cell->loc_uri.s ); notify_cell->rem_uri.len= pfrom->uri.len; notify_cell->rem_uri.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len + fromtag_event.len + pto->uri.len; memcpy(notify_cell->rem_uri.s, pfrom->uri.s, pfrom->uri.len); LM_DBG("SUBS_REM_URI: %.*s \n ", notify_cell->rem_uri.len, notify_cell->rem_uri.s ); notify_cell->contact.len = vsp_addr_len + size_vsp_port +11; notify_cell->contact.s = (char *) (notify_cell->call_dlg_id + 1) + pfrom->uri.len + pto->uri.len + callid_event.len + fromtag_event.len; memcpy(notify_cell->contact.s, "sip:teste@", 10); memcpy(notify_cell->contact.s + 10, vsp_addr, vsp_addr_len); memcpy(notify_cell->contact.s + 10 + vsp_addr_len, ":", 1); memcpy(notify_cell->contact.s + 11 + vsp_addr_len, str_vsp_port, size_vsp_port); LM_DBG("SUBS_CONTACT: %.*s \n ", notify_cell->contact.len, notify_cell->contact.s ); notify_cell->dlg_id->status = RESP_WAIT; pkg_free(callid_event.s); pkg_free(fromtag_event.s); return notify_cell; }
/*! \brief * \return 0/1 (false/true) or -1 on error, -127 EXPR_DROP */ static int eval_elem(struct expr* e, struct sip_msg* msg, pv_value_t *val) { struct sip_uri uri; int ret; int retl; int retr; int ival; pv_value_t lval; pv_value_t rval; char *p; int i,n; ret=E_BUG; if (e->type!=ELEM_T){ LM_CRIT("invalid type\n"); goto error; } if(val) memset(val, 0, sizeof(pv_value_t)); switch(e->left.type){ case METHOD_O: ret=comp_strval(msg, e->op, &msg->first_line.u.request.method, &e->right); break; case URI_O: if(msg->new_uri.s){ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->new_uri, &e->right); } }else{ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->first_line.u.request.uri, &e->right); } } break; case FROM_URI_O: if (parse_from_header(msg)<0){ LM_ERR("bad or missing From: header\n"); goto error; } if (e->right.type==MYSELF_ST){ if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in From:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_from(msg)->uri, &e->right); } break; case TO_URI_O: if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) || (msg->to==0))){ LM_ERR("bad or missing To: header\n"); goto error; } /* to content is parsed automatically */ if (e->right.type==MYSELF_ST){ if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in To:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_to(msg)->uri, &e->right); } break; case SRCIP_O: ret=comp_ip(msg, e->op, &msg->rcv.src_ip, &e->right); break; case DSTIP_O: ret=comp_ip(msg, e->op, &msg->rcv.dst_ip, &e->right); break; case NUMBER_O: ret=!(!e->right.v.n); /* !! to transform it in {0,1} */ break; case ACTION_O: ret=run_action_list( (struct action*)e->right.v.data, msg); if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ret; } if (ret<=0) ret=(ret==0)?EXPR_DROP:0; else ret=1; return ret; case EXPR_O: retl = retr = 0; memset(&lval, 0, sizeof(pv_value_t)); memset(&rval, 0, sizeof(pv_value_t)); if(e->left.v.data) retl=eval_expr((struct expr*)e->left.v.data,msg,&lval); if(lval.flags == PV_VAL_NONE) { pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->op == BNOT_OP) { if(lval.flags&PV_VAL_INT) { if(val!=NULL) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ~lval.ri; } pv_value_destroy(&lval); pv_value_destroy(&rval); return (val->ri)?1:0; } LM_ERR("binary NOT on non-numeric value\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->right.v.data) retr=eval_expr((struct expr*)e->right.v.data,msg,&rval); if(lval.flags&PV_TYPE_INT) { if( (rval.flags&PV_VAL_NULL) ) { rval.ri = 0; } else if(!(rval.flags&PV_VAL_INT)) { LM_ERR("invalid numeric operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(val!=NULL) val->flags = PV_TYPE_INT|PV_VAL_INT; ival = 0; switch(e->op) { case PLUS_OP: ival = lval.ri + rval.ri; break; case MINUS_OP: ival = lval.ri - rval.ri; break; case DIV_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri / rval.ri; break; case MULT_OP: ival = lval.ri * rval.ri; break; case MODULO_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri % rval.ri; break; case BAND_OP: ival = lval.ri & rval.ri; break; case BOR_OP: ival = lval.ri | rval.ri; break; case BXOR_OP: ival = lval.ri ^ rval.ri; break; case BLSHIFT_OP: ival = lval.ri << rval.ri; break; case BRSHIFT_OP: ival = lval.ri >> rval.ri; break; default: LM_ERR("invalid int op %d\n", e->op); val->ri = 0; pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } pv_value_destroy(&lval); pv_value_destroy(&rval); if(val!=NULL) val->ri = ival; return (ival)?1:0; } else if (e->op == PLUS_OP) { if( (rval.flags&PV_VAL_NULL) || (val==NULL)) { if (val) val->flags|=PV_VAL_STR; ret = (lval.rs.len>0 || rval.rs.len>0); pv_value_destroy(&lval); pv_value_destroy(&rval); return ret; } if(!(rval.flags&PV_VAL_STR)) { LM_ERR("invalid string operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->rs.s=(char*)pkg_malloc((lval.rs.len+rval.rs.len+1) *sizeof(char)); if(val->rs.s==0) { LM_ERR("no more memory\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->flags = PV_VAL_PKG|PV_VAL_STR; memcpy(val->rs.s, lval.rs.s, lval.rs.len); memcpy(val->rs.s+lval.rs.len, rval.rs.s, rval.rs.len); val->rs.len = lval.rs.len + rval.rs.len; val->rs.s[val->rs.len] = '\0'; pv_value_destroy(&lval); pv_value_destroy(&rval); return 1; } else if ((lval.flags & PV_VAL_STR) && (rval.flags & PV_VAL_STR)) { if (lval.rs.len != rval.rs.len) { LM_ERR("Different length string operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } n = lval.rs.len; val->rs.s = pkg_malloc(n+1); if (!val->rs.s) { LM_ERR("no more memory\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } switch(e->op) { case BAND_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] & rval.rs.s[i]; break; case BOR_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] | rval.rs.s[i]; break; case BXOR_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] ^ rval.rs.s[i]; break; default: LM_ERR("Only bitwise operations can be applied on strings\n"); val->ri = 0; pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->flags = PV_VAL_PKG|PV_VAL_STR; val->rs.len = n; val->rs.s[n] = '\0'; pv_value_destroy(&lval); pv_value_destroy(&rval); return 1; } else { LM_ERR("Invalid operator : %d \n",e->op); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } break; case SRCPORT_O: ret=comp_no(msg->rcv.src_port, e->right.v.data, /* e.g., 5060 */ e->op, /* e.g. == */ e->right.type /* 5060 is number */); break; case DSTPORT_O: ret=comp_no(msg->rcv.dst_port, e->right.v.data, e->op, e->right.type); break; case PROTO_O: ret=comp_no(msg->rcv.proto, e->right.v.data, e->op, e->right.type); break; case AF_O: ret=comp_no(msg->rcv.src_ip.af, e->right.v.data, e->op, e->right.type); break; case RETCODE_O: ret=comp_no(return_code, e->right.v.data, e->op, e->right.type); break; case MSGLEN_O: ret=comp_no(msg->len, e->right.v.data, e->op, e->right.type); break; case STRINGV_O: if(val) { val->flags = PV_VAL_STR; val->rs = e->left.v.s; } /* optimization for no dup ?!?! */ return (e->left.v.s.len>0)?1:0; case NUMBERV_O: if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = e->left.v.n; } ret=!(!e->left.v.n); /* !! to transform it in {0,1} */ return ret; case SCRIPTVAR_O: if(e->op==NO_OP) { memset(&rval, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, e->right.v.spec, &rval)==0) { if(rval.flags==PV_VAL_NONE || (rval.flags&PV_VAL_NULL) || (rval.flags&PV_VAL_EMPTY) || ((rval.flags&PV_TYPE_INT)&&rval.ri==0)) { pv_value_destroy(&rval); return 0; } if(rval.flags&PV_TYPE_INT) { pv_value_destroy(&rval); return 1; } if(rval.rs.len!=0) { pv_value_destroy(&rval); return 1; } pv_value_destroy(&rval); } return 0; } if(e->op==VALUE_OP) { if(pv_get_spec_value(msg, e->left.v.spec, &lval)==0) { if(val!=NULL) memcpy(val, &lval, sizeof(pv_value_t)); if(lval.flags&PV_VAL_STR) { if(!((lval.flags&PV_VAL_PKG) || (lval.flags&PV_VAL_SHM))) { if(val!=NULL) { /* do pkg duplicate */ p = (char*)pkg_malloc((val->rs.len+1) *sizeof(char)); if(p==0) { LM_ERR("no more pkg memory\n"); memset(val, 0, sizeof(pv_value_t)); return 0; } memcpy(p, val->rs.s, val->rs.len); p[val->rs.len] = 0; val->rs.s = p; val->flags|= PV_VAL_PKG; } } return 1; } if(lval.flags==PV_VAL_NONE || (lval.flags & PV_VAL_NULL) || (lval.flags & PV_VAL_EMPTY)) return 0; if(lval.flags&PV_TYPE_INT) return (lval.ri!=0); else return (lval.rs.len>0); } return 0; } ret=comp_scriptvar(msg, e->op, &e->left, &e->right); break; default: LM_CRIT("invalid operand %d\n", e->left.type); }
int tps_request_received(sip_msg_t *msg, int dialog) { tps_data_t mtsd; tps_data_t stsd; str lkey; str ftag; str nuri; uint32_t direction = TPS_DIR_DOWNSTREAM; int ret; LM_DBG("handling incoming request\n"); if(dialog==0) { /* nothing to do for initial request */ return 0; } memset(&mtsd, 0, sizeof(tps_data_t)); memset(&stsd, 0, sizeof(tps_data_t)); if(tps_pack_message(msg, &mtsd)<0) { LM_ERR("failed to extract and pack the headers\n"); return -1; } ret = tps_dlg_message_update(msg, &mtsd); if(ret<0) { LM_ERR("failed to update on dlg message\n"); return -1; } lkey = msg->callid->body; tps_storage_lock_get(&lkey); if(tps_storage_load_dialog(msg, &mtsd, &stsd)<0) { goto error; } /* detect direction - get from-tag */ if(parse_from_header(msg)<0 || msg->from==NULL) { LM_ERR("failed getting 'from' header!\n"); goto error; } ftag = get_from(msg)->tag_value; if(stsd.a_tag.len!=ftag.len) { direction = TPS_DIR_UPSTREAM; } else { if(memcmp(stsd.a_tag.s, ftag.s, ftag.len)==0) { direction = TPS_DIR_DOWNSTREAM; } else { direction = TPS_DIR_UPSTREAM; } } mtsd.direction = direction; tps_storage_lock_release(&lkey); if(direction == TPS_DIR_UPSTREAM) { nuri = stsd.a_contact; } else { nuri = stsd.b_contact; } if(nuri.len>0) { if(rewrite_uri(msg, &nuri)<0) { LM_ERR("failed to update r-uri\n"); return -1; } } if(tps_reappend_route(msg, &stsd, &stsd.s_rr, (direction==TPS_DIR_UPSTREAM)?0:1)<0) { LM_ERR("failed to reappend s-route\n"); return -1; } if(direction == TPS_DIR_UPSTREAM) { if(tps_reappend_route(msg, &stsd, &stsd.a_rr, 0)<0) { LM_ERR("failed to reappend a-route\n"); return -1; } } else { if(tps_reappend_route(msg, &stsd, &stsd.b_rr, 0)<0) { LM_ERR("failed to reappend b-route\n"); return -1; } } if(dialog!=0) { tps_append_xuuid(msg, &stsd.a_uuid); } return 0; error: tps_storage_lock_release(&lkey); return -1; }
static int cmd_send_message(struct sip_msg* msg, char* _foo, char* _bar) { str body, from_uri, dst, tagid; int mime; LM_DBG("cmd_send_message\n"); /* extract body */ if (get_body(msg,&body)!=0 || body.len==0) { LM_ERR("failed to extract body\n"); return -1; } if ((mime = parse_content_type_hdr(msg)) < 1) { LM_ERR("failed parse content-type\n"); return -1; } if (mime != (TYPE_TEXT << 16) + SUBTYPE_PLAIN && mime != (TYPE_MESSAGE << 16) + SUBTYPE_CPIM) { LM_ERR("invalid content-type 0x%x\n", mime); return -1; } /* extract sender */ if (parse_headers(msg, HDR_TO_F | HDR_FROM_F, 0) == -1 || !msg->to || !msg->from) { LM_ERR("no To/From headers\n"); return -1; } if (parse_from_header(msg) < 0 || !msg->from->parsed) { LM_ERR("failed to parse From header\n"); return -1; } from_uri.s = uri_sip2xmpp(&((struct to_body *) msg->from->parsed)->uri); from_uri.len = strlen(from_uri.s); tagid = ((struct to_body *) msg->from->parsed)->tag_value; LM_DBG("message from <%.*s>\n", from_uri.len, from_uri.s); /* extract recipient */ dst.len = 0; if (msg->new_uri.len > 0) { LM_DBG("using new URI as destination\n"); dst = msg->new_uri; } else if (msg->first_line.u.request.uri.s && msg->first_line.u.request.uri.len > 0) { LM_DBG("using R-URI as destination\n"); dst = msg->first_line.u.request.uri; } else if (msg->to->parsed) { LM_DBG("using TO-URI as destination\n"); dst = ((struct to_body *) msg->to->parsed)->uri; } else { LM_ERR("failed to find a valid destination\n"); return -1; } dst.s = dst.s + 4; dst.len = dst.len - 4; if (!xmpp_send_pipe_cmd(XMPP_PIPE_SEND_MESSAGE, &from_uri, &dst, &body, &tagid)) return 1; return -1; }
int tps_response_received(sip_msg_t *msg) { tps_data_t mtsd; tps_data_t stsd; tps_data_t btsd; str lkey; str ftag; uint32_t direction; LM_DBG("handling incoming response\n"); if(msg->first_line.u.reply.statuscode==100) { /* nothing to do - it should be absorbed */ return 0; } memset(&mtsd, 0, sizeof(tps_data_t)); memset(&stsd, 0, sizeof(tps_data_t)); memset(&btsd, 0, sizeof(tps_data_t)); lkey = msg->callid->body; if(tps_pack_message(msg, &mtsd)<0) { LM_ERR("failed to extract and pack the headers\n"); return -1; } tps_storage_lock_get(&lkey); if(tps_storage_load_branch(msg, &mtsd, &btsd)<0) { goto error; } LM_DBG("loaded dialog a_uuid [%.*s]\n", btsd.a_uuid.len, ZSW(btsd.a_uuid.s)); if(tps_storage_load_dialog(msg, &btsd, &stsd)<0) { goto error; } /* detect direction - get from-tag */ if(parse_from_header(msg)<0 || msg->from==NULL) { LM_ERR("failed getting 'from' header!\n"); goto error; } ftag = get_from(msg)->tag_value; if(stsd.a_tag.len!=ftag.len) { direction = TPS_DIR_UPSTREAM; } else { if(memcmp(stsd.a_tag.s, ftag.s, ftag.len)==0) { direction = TPS_DIR_DOWNSTREAM; } else { direction = TPS_DIR_UPSTREAM; } } mtsd.direction = direction; if(tps_storage_update_branch(msg, &mtsd, &btsd)<0) { goto error; } if(tps_storage_update_dialog(msg, &mtsd, &stsd)<0) { goto error; } tps_storage_lock_release(&lkey); tps_reappend_via(msg, &btsd, &btsd.x_via); tps_reappend_rr(msg, &btsd, &btsd.s_rr); tps_reappend_rr(msg, &btsd, &btsd.x_rr); tps_append_xbranch(msg, &mtsd.x_vbranch1); return 0; error: tps_storage_lock_release(&lkey); return -1; }
/*! \brief * Insert a new Record-Route header field * And also 2nd one if it is enabled and realm changed so * the 2nd record-route header will be necessary */ int record_route(struct sip_msg* _m, str *params) { struct lump* l, *l2, *lp, *lp2, *ap; str user; struct to_body* from; str* tag; from = 0; /* Makes gcc happy */ user.len = 0; lp = lp2 = NULL; if (add_username) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; tag = &from->tag_value; } else { tag = 0; } l = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -3; } /* look for pending RR params */ for( lp2=NULL,lp=NULL,ap=_m->add_rm ; ap ; ap=ap->next ) { if (ap->type==HDR_RECORDROUTE_T && ap->op==LUMP_NOP && ap->before && ap->before->op==LUMP_ADD_OPT && ap->before->u.cond==COND_FALSE) { /* found our phony anchor lump */ /* jump over the anchor and conditional lumps */ lp = ap->before->before; /* unlink it */ ap->before->before = NULL; ap->type = 0; /* if double routing, make a copy of the buffered lumps for the second route hdr. */ if (enable_double_rr) lp2 = dup_lump_list(lp); break; } } if (build_rr(l, l2, &user, tag, params, lp, OUTBOUND) < 0) { LM_ERR("failed to insert inbound Record-Route\n"); return -4; } if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -5; } l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0); l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); return -6; } if (build_rr(l, l2, &user, tag, params, lp2, INBOUND) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); return -7; } } 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; }
/* 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; }
int push_on_network(struct sip_msg *msg, int net) { str body; struct sip_uri uri; struct sms_msg *sms_messg; struct to_body *from; char *p; int len; int mime; /* get the message's body * anyhow we have to call this function, so let's do it at the beginning * to force the parsing of all the headers - like this we avoid separate * calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs */ body.s = get_body( msg ); if (body.s==0) { LM_ERR("failed to extract body from msg!\n"); goto error; } /* content-length (if present) must be already parsed */ if (!msg->content_length) { LM_ERR("no Content-Length header found!\n"); goto error; } body.len = get_content_length( msg ); /* parse the content-type header */ if ( (mime=parse_content_type_hdr(msg))<1 ) { LM_ERR("failed to parse Content-Type header\n"); goto error; } /* check the content-type value */ if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) { LM_ERR("invalid content-type for a message request! type found=%d\n", mime); goto error; } /* we try to get the user name (phone number) first from the RURI (in our case means from new_uri or from first_line.u.request.uri); if it's missing there (like in requests generated by MSN MESSENGER), we go for "to" header */ LM_DBG("string to get user from new_uri\n"); if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri) || !uri.user.len ) { LM_DBG("string to get user from R_uri\n"); if ( parse_uri( msg->first_line.u.request.uri.s, msg->first_line.u.request.uri.len ,&uri)||!uri.user.len ) { LM_DBG("string to get user from To\n"); if ( (!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1) || !msg->to)) || parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1 || !uri.user.len) { LM_ERR("unable to extract user name from RURI and To header!\n"); goto error; } } } /* check the uri.user format = '+(inter code)(number)' */ if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1' || uri.user.s[1]>'9') { LM_ERR("user tel number [%.*s] does not respect international format\n" ,uri.user.len,uri.user.s); goto error; } /* parsing from header */ if ( parse_from_header( msg )==-1 ) { LM_ERR("failed to get FROM header\n"); goto error; } from = (struct to_body*)msg->from->parsed; #if 0 /* adds contact header into reply */ if (add_contact(msg,&(uri.user))==-1) { LM_ERR("can't build contact for reply\n"); goto error; } #endif /*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/ /* computes the amount of memory needed */ len = SMS_HDR_BF_ADDR_LEN + from->uri.len + SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/ + from->uri.len /* from */ + uri.user.len-1 /* to user (without '+') */ + sizeof(struct sms_msg) ; /* the sms_msg structure */ /* allocs a new sms_msg structure in shared memory */ sms_messg = (struct sms_msg*)shm_malloc(len); if (!sms_messg) { LM_ERR("failed to get shm memory!\n"); goto error; } p = (char*)sms_messg + sizeof(struct sms_msg); /* copy "from" into sms struct */ sms_messg->from.len = from->uri.len; sms_messg->from.s = p; append_str(p,from->uri.s,from->uri.len); /* copy "to.user" - we have to strip out the '+' */ sms_messg->to.len = uri.user.len-1; sms_messg->to.s = p; append_str(p,uri.user.s+1,sms_messg->to.len); /* copy (and composing) sms body */ sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len + SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN; sms_messg->text.s = p; append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN); append_str(p, sms_messg->from.s, sms_messg->from.len); append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN); append_str(p, body.s, body.len); append_str(p, SMS_FOOTER, SMS_FOOTER_LEN); if (*queued_msgs>MAX_QUEUED_MESSAGES) goto error; (*queued_msgs)++; if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!= sizeof(sms_messg) ) { LM_ERR("error when writing for net %d to pipe [%d] : %s\n", net,net_pipes_in[net],strerror(errno) ); shm_free(sms_messg); (*queued_msgs)--; goto error; } return 1; error: return -1; }
/* * Check if an entry exists in hash table that has given src_ip and protocol * value and pattern that matches to From URI. If an entry exists and tag_avp * has been defined, tag of the entry is added as a value to tag_avp. * Returns number of matches or -1 if none matched. */ int match_hash_table(struct trusted_list** table, struct sip_msg* msg, char *src_ip_c_str, int proto) { str uri, ruri; char uri_string[MAX_URI_SIZE + 1]; char ruri_string[MAX_URI_SIZE + 1]; regex_t preg; struct trusted_list *np; str src_ip; int_str val; int count = 0; src_ip.s = src_ip_c_str; src_ip.len = strlen(src_ip.s); if (IS_SIP(msg)) { if (parse_from_header(msg) < 0) return -1; uri = get_from(msg)->uri; if (uri.len > MAX_URI_SIZE) { LM_ERR("from URI too large\n"); return -1; } memcpy(uri_string, uri.s, uri.len); uri_string[uri.len] = (char)0; ruri = msg->first_line.u.request.uri; if (ruri.len > MAX_URI_SIZE) { LM_ERR("message has Request URI too large\n"); return -1; } memcpy(ruri_string, ruri.s, ruri.len); ruri_string[ruri.len] = (char)0; } for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) { if ((np->src_ip.len == src_ip.len) && (strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) && ((np->proto == PROTO_NONE) || (proto == PROTO_NONE) || (np->proto == proto))) { if (IS_SIP(msg)) { if (np->pattern) { if (regcomp(&preg, np->pattern, REG_NOSUB)) { LM_ERR("invalid regular expression\n"); if (!np->ruri_pattern) { continue; } } if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) { regfree(&preg); continue; } regfree(&preg); } if (np->ruri_pattern) { if (regcomp(&preg, np->ruri_pattern, REG_NOSUB)) { LM_ERR("invalid regular expression\n"); continue; } if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) { regfree(&preg); continue; } regfree(&preg); } } /* Found a match */ if (tag_avp.n && np->tag.s) { val.s = np->tag; if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) { LM_ERR("setting of tag_avp failed\n"); return -1; } } if (!peer_tag_mode) return 1; count++; } } if (!count) return -1; else return count; }
/* * Check if from user is a valid enum based user, and check to make sure * that the src_ip == an srv record that maps to the enum from user. */ int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service) { struct ip_addr addr; struct hostent* he; unsigned short zp; char proto; char *user_s; int user_len, i, j; char name[MAX_DOMAIN_SIZE]; char uri[MAX_URI_SIZE]; struct sip_uri *furi; struct sip_uri luri; struct rdata* head; str* suffix; str* service; struct rdata* l; struct naptr_rdata* naptr; str pattern, replacement, result; char string[MAX_NUM_LEN]; if (parse_from_header(_msg) < 0) { LM_ERR("Failed to parse From header\n"); return -1; } if(_msg->from==NULL || get_from(_msg)==NULL) { LM_DBG("No From header\n"); return -1; } if ((furi = parse_from_uri(_msg)) == NULL) { LM_ERR("Failed to parse From URI\n"); return -1; } suffix = (str*)_suffix; service = (str*)_service; if (is_e164(&(furi->user)) == -1) { LM_ERR("From URI user is not an E164 number\n"); return -1; } /* assert: the from user is a valid formatted e164 string */ user_s = furi->user.s; user_len = furi->user.len; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_NAPTR, RES_ONLY_TYPE); if (head == 0) { LM_DBG("No NAPTR record found for %s.\n", name); return -3; } /* we have the naptr records, loop and find an srv record with */ /* same ip address as source ip address, if we do then true is returned */ for (l = head; l; l = l->next) { if (l->type != T_NAPTR) continue; /*should never happen*/ naptr = (struct naptr_rdata*)l->rdata; if (naptr == 0) { LM_ERR("Null rdata in DNS response\n"); free_rdata_list(head); return -4; } LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags " "'%.*s', slen %u, services '%.*s', rlen %u, " "regexp '%.*s'\n", name, naptr->order, naptr->pref, naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len, (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len, (int)(naptr->regexp_len), ZSW(naptr->regexp)); if (sip_match(naptr, service) != 0) { if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern, &replacement) < 0) { free_rdata_list(head); /*clean up*/ LM_ERR("Parsing of NAPTR regexp failed\n"); return -5; } #ifdef LATER if ((pattern.len == 4) && (strncmp(pattern.s, "^.*$", 4) == 0)) { LM_DBG("Resulted in replacement: '%.*s'\n", replacement.len, ZSW(replacement.s)); retval = set_uri(_msg, replacement.s, replacement.len); free_rdata_list(head); /*clean up*/ return retval; } #endif result.s = &(uri[0]); result.len = MAX_URI_SIZE; /* Avoid making copies of pattern and replacement */ pattern.s[pattern.len] = (char)0; replacement.s[replacement.len] = (char)0; /* We have already checked the size of _msg->parsed_uri.user.s */ memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; if (reg_replace(pattern.s, replacement.s, &(string[0]), &result) < 0) { pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; LM_ERR("Regexp replace failed\n"); free_rdata_list(head); /*clean up*/ return -6; } LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s)); if(parse_uri(result.s, result.len, &luri) < 0) { LM_ERR("Parsing of URI <%.*s> failed\n", result.len, result.s); free_rdata_list(head); /*clean up*/ return -7; } pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; zp = 0; proto = PROTO_NONE; he = sip_resolvehost(&luri.host, &zp, &proto); hostent2ip_addr(&addr, he, 0); if(ip_addr_cmp(&addr, &_msg->rcv.src_ip)) { free_rdata_list(head); return(1); } } } free_rdata_list(head); /*clean up*/ LM_DBG("FAIL\n"); /* must not have found the record */ return(-8); }