/* * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, char* _t, char* _s) { str uid; urecord_t* r; ucontact_t* ptr; int res; if (get_to_uid(&uid, _m) < 0) return -1; ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &uid, &r); if (res < 0) { ul.unlock_udomain((udomain_t*)_t); LOG(L_ERR, "registered(): Error while querying usrloc\n"); return -1; } if (res == 0) { ptr = r->contacts; while (ptr && !VALID_CONTACT(ptr, act_time)) { ptr = ptr->next; } if (ptr) { ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' found in usrloc\n", uid.len, ZSW(uid.s)); return 1; } } ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' not found in usrloc\n", uid.len, ZSW(uid.s)); return -1; }
int get_presentity_uid(str *uid_dst, struct sip_msg *m) { /* Independently on implementation of get_to_uid this function * gets UID from the message. It never uses dynamic allocation of * data (better to use static buffer instead due to speed)! */ return get_to_uid(uid_dst, m); }
/* * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered2(struct sip_msg* _m, char* _t, char* p2) { str uid, aor; urecord_t* r; ucontact_t* ptr; int res; if (get_str_fparam(&aor, _m, (fparam_t*)p2) != 0) { ERR("Unable to get the AOR value\n"); return -1; } if (get_to_uid(&uid, _m) < 0) return -1; ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &uid, &r); if (res < 0) { ul.unlock_udomain((udomain_t*)_t); LOG(L_ERR, "registered(): Error while querying usrloc\n"); return -1; } if (res == 0) { ptr = r->contacts; while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor))) { ptr = ptr->next; } if (ptr) { ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' found in usrloc\n", uid.len, ZSW(uid.s)); return 1; } } ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' not found in usrloc\n", uid.len, ZSW(uid.s)); return -1; }
/* * Lookup contact in the database and rewrite Request-URI */ int lookup(struct sip_msg* _m, char* _t, char* _s) { urecord_t* r; str uid; ucontact_t* ptr; int res; unsigned int nat; str new_uri; nat = 0; if (get_to_uid(&uid, _m) < 0) return -1; get_act_time(); ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &uid, &r); if (res < 0) { LOG(L_ERR, "lookup(): Error while querying usrloc\n"); ul.unlock_udomain((udomain_t*)_t); return -2; } if (res > 0) { DBG("lookup(): '%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s)); ul.unlock_udomain((udomain_t*)_t); return -3; } ptr = r->contacts; while ((ptr) && !VALID_CONTACT(ptr, act_time)) ptr = ptr->next; if (ptr) { if (ptr->received.s && ptr->received.len) { if (received_to_uri){ if (add_received(&new_uri, &ptr->c, &ptr->received)<0){ LOG(L_ERR, "ERROR: lookup(): out of memory\n"); return -4; } /* replace the msg uri */ if (_m->new_uri.s) pkg_free(_m->new_uri.s); _m->new_uri=new_uri; _m->parsed_uri_ok=0; ruri_mark_new(); goto skip_rewrite_uri; }else if (set_dst_uri(_m, &ptr->received) < 0) { ul.unlock_udomain((udomain_t*)_t); return -4; } } if (rewrite_uri(_m, &ptr->c) < 0) { LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n"); ul.unlock_udomain((udomain_t*)_t); return -4; } if (ptr->sock) { set_force_socket(_m, ptr->sock); } skip_rewrite_uri: set_ruri_q(ptr->q); nat |= ptr->flags & FL_NAT; ptr = ptr->next; } else { /* All contacts expired */ ul.unlock_udomain((udomain_t*)_t); return -5; } /* Append branches if enabled */ if (!append_branches) goto skip; while(ptr) { if (VALID_CONTACT(ptr, act_time)) { if (received_to_uri && ptr->received.s && ptr->received.len){ if (add_received(&new_uri, &ptr->c, &ptr->received)<0){ LOG(L_ERR, "ERROR: lookup(): branch: out of memory\n"); goto cont; /* try to continue */ } if (append_branch(_m, &new_uri, 0, 0, ptr->q, 0, 0) == -1) { LOG(L_ERR, "lookup(): Error while appending a branch\n"); pkg_free(new_uri.s); if (ser_error==E_TOO_MANY_BRANCHES) goto skip; else goto cont; /* try to continue, maybe we have an oversized contact */ } pkg_free(new_uri.s); /* append_branch doesn't free it */ }else{ if (append_branch(_m, &ptr->c, &ptr->received, 0 /* path */, ptr->q, 0 /* brflags*/, ptr->sock) == -1) { LOG(L_ERR, "lookup(): Error while appending a branch\n"); goto skip; /* Return OK here so the function succeeds */ } } nat |= ptr->flags & FL_NAT; } cont: ptr = ptr->next; } skip: ul.unlock_udomain((udomain_t*)_t); if (nat) setflag(_m, load_nat_flag); return 1; }
/* * Lookup contact in the database and rewrite Request-URI, * and filter them by aor */ int lookup2(struct sip_msg* msg, char* table, char* p2) { urecord_t* r; str uid; ucontact_t* ptr; int res; unsigned int nat; str new_uri, aor; fparam_t* fp; nat = 0; fp = (fparam_t*)p2; if (get_str_fparam(&aor, msg, (fparam_t*)p2) != 0) { ERR("Unable to get the AOR value\n"); return -1; } if (get_to_uid(&uid, msg) < 0) return -1; get_act_time(); ul.lock_udomain((udomain_t*)table); res = ul.get_urecord((udomain_t*)table, &uid, &r); if (res < 0) { ERR("Error while querying usrloc\n"); ul.unlock_udomain((udomain_t*)table); return -2; } if (res > 0) { DBG("'%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s)); ul.unlock_udomain((udomain_t*)table); return -3; } ptr = r->contacts; while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor))) ptr = ptr->next; if (ptr) { if (ptr->received.s && ptr->received.len) { if (received_to_uri){ if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) { ERR("Out of memory\n"); return -4; } /* replace the msg uri */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri = new_uri; msg->parsed_uri_ok = 0; ruri_mark_new(); goto skip_rewrite_uri; } else if (set_dst_uri(msg, &ptr->received) < 0) { ul.unlock_udomain((udomain_t*)table); return -4; } } if (rewrite_uri(msg, &ptr->c) < 0) { ERR("Unable to rewrite Request-URI\n"); ul.unlock_udomain((udomain_t*)table); return -4; } if (ptr->sock) { set_force_socket(msg, ptr->sock); } skip_rewrite_uri: set_ruri_q(ptr->q); nat |= ptr->flags & FL_NAT; ptr = ptr->next; } else { /* All contacts expired */ ul.unlock_udomain((udomain_t*)table); return -5; } /* Append branches if enabled */ if (!append_branches) goto skip; while(ptr) { if (VALID_CONTACT(ptr, act_time) && VALID_AOR(ptr, aor)) { if (received_to_uri && ptr->received.s && ptr->received.len) { if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) { ERR("branch: out of memory\n"); goto cont; /* try to continue */ } if (append_branch(msg, &new_uri, 0, 0, ptr->q, 0, 0) == -1) { ERR("Error while appending a branch\n"); pkg_free(new_uri.s); if (ser_error == E_TOO_MANY_BRANCHES) goto skip; else goto cont; /* try to continue, maybe we have an oversized contact */ } pkg_free(new_uri.s); /* append_branch doesn't free it */ } else { if (append_branch(msg, &ptr->c, &ptr->received, 0 /* path */, ptr->q, 0, ptr->sock) == -1) { ERR("Error while appending a branch\n"); goto skip; /* Return OK here so the function succeeds */ } } nat |= ptr->flags & FL_NAT; } cont: ptr = ptr->next; } skip: ul.unlock_udomain((udomain_t*)table); if (nat) setflag(msg, load_nat_flag); return 1; }
/* create an array of str's for accounting using a formatting string; * this is the heart of the accounting module -- it prints whatever * requested in a way, that can be used for syslog, radius, * sql, whatsoever * tm sip_msg_clones does not clone (shmmem-zed) parsed fields, other then Via1,2. Such fields clone now or use from rq_rp */ static int fmt2strar(char *fmt, /* what would you like to account ? */ struct sip_msg *rq, /* accounted message */ str* ouri, /* Outbound Request-URI */ struct hdr_field *to, unsigned int code, time_t req_time) /* Timestamp of the request */ { int cnt; struct to_body* from, *pto; str *cr, *at; struct cseq_body *cseq; cnt = 0; /* we don't care about parsing here; either the function * was called from script, in which case the wrapping function * is supposed to parse, or from reply processing in which case * TM should have preparsed from REQUEST_IN callback; what's not * here is replaced with NA */ while(*fmt) { if (cnt == ALL_LOG_FMT_LEN) { LOG(L_ERR, "ERROR:acc:fmt2strar: Formatting string is too long\n"); return 0; } switch(*fmt) { case 'a': /* attr */ at = print_attrs(avps, avps_n, 0); if (!at) { vals[cnt].nul = 1; } else { vals[cnt].val.str_val = *at; } break; case 'c': /* sip_callid */ if (rq->callid && rq->callid->body.len) { vals[cnt].val.str_val = rq->callid->body; } else { vals[cnt].nul = 1; } break; case 'd': /* to_tag */ if (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) { vals[cnt].val.str_val = pto->tag_value; } else { vals[cnt].nul = 1; } break; case 'f': /* sip_from */ if (rq->from && rq->from->body.len) { vals[cnt].val.str_val = rq->from->body; } else { vals[cnt].nul = 1; } break; case 'g': /* flags */ vals[cnt].val.int_val = rq->flags; break; case 'i': /* inbound_ruri */ vals[cnt].val.str_val = rq->first_line.u.request.uri; break; case 'm': /* sip_method */ vals[cnt].val.str_val = rq->first_line.u.request.method; break; case 'n': /* sip_cseq */ if (rq->cseq && (cseq = get_cseq(rq)) && cseq->number.len) { str2int(&cseq->number, (unsigned int*)&vals[cnt].val.int_val); } else { vals[cnt].nul = 1; } break; case 'o': /* outbound_ruri */ vals[cnt].val.str_val = *ouri; break; case 'p': vals[cnt].val.int_val = rq->rcv.src_ip.u.addr32[0]; break; break; case 'r': /* from_tag */ if (rq->from && (from = get_from(rq)) && from->tag_value.len) { vals[cnt].val.str_val = from->tag_value; } else { vals[cnt].nul = 1; } break; case 't': /* sip_to */ if (to && to->body.len) vals[cnt].val.str_val = to->body; else vals[cnt].nul = 1; break; case 'u': /* digest_username */ cr = cred_user(rq); if (cr) vals[cnt].val.str_val = *cr; else vals[cnt].nul = 1; break; case 'x': /* request_timestamp */ vals[cnt].val.time_val = req_time; break; case 'D': /* to_did */ vals[cnt].nul = 1; break; case 'F': /* from_uri */ if (rq->from && (from = get_from(rq)) && from->uri.len) { vals[cnt].val.str_val = from->uri; } else vals[cnt].nul = 1; break; case 'I': /* from_uid */ if (get_from_uid(&vals[cnt].val.str_val, rq) < 0) { vals[cnt].nul = 1; } break; case 'M': /* from_did */ vals[cnt].nul = 1; break; case 'P': /* source_port */ vals[cnt].val.int_val = rq->rcv.src_port; break; case 'R': /* digest_realm */ cr = cred_realm(rq); if (cr) vals[cnt].val.str_val = *cr; else vals[cnt].nul = 1; break; case 'S': /* sip_status */ if (code > 0) vals[cnt].val.int_val = code; else vals[cnt].nul = 1; break; case 'T': /* to_uri */ if (rq->to && (pto = get_to(rq)) && pto->uri.len) vals[cnt].val.str_val = pto->uri; else vals[cnt].nul = 1; break; case 'U': /* to_uid */ if (get_to_uid(&vals[cnt].val.str_val, rq) < 0) { vals[cnt].nul = 1; } break; case 'X': /* response_timestamp */ vals[cnt].val.time_val = time(0); break; default: LOG(L_CRIT, "BUG:acc:fmt2strar: unknown char: %c\n", *fmt); return 0; } /* switch (*fmt) */ fmt++; cnt++; } /* while (*fmt) */ return cnt; }
/* * Process REGISTER request and save it's contacts */ static inline int save_real(struct sip_msg* _m, udomain_t* _t, char* aor_filt, int doreply) { contact_t* c; int st; str uid, ua, aor_filter; rerrno = R_FINE; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } if (aor_filt) { if (get_str_fparam(&aor_filter, _m, (fparam_t*)aor_filt) != 0) { ERR("registrar:save: Unable to get the AOR value\n"); return -1; } } else { aor_filter.s = 0; aor_filter.len = 0; } get_act_time(); c = get_first_contact(_m); if (get_to_uid(&uid, _m) < 0) goto error; ua.len = 0; if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent && _m->user_agent->body.len > 0) { ua.len = _m->user_agent->body.len; ua.s = _m->user_agent->body.s; } if (ua.len == 0) { ua.len = UA_DUMMY_LEN; ua.s = UA_DUMMY_STR; } if (c == 0) { if (st) { if (star(_t, &uid, &aor_filter) < 0) goto error; } else { if (no_contacts(_t, &uid, &aor_filter) < 0) goto error; } } else { if (contacts(_m, c, _t, &uid, &ua, &aor_filter) < 0) goto error; } if (doreply) { if (send_reply(_m) < 0) return -1; } else { /* No reply sent, create attributes with values * of reply code, reason text, and contacts */ if (setup_attrs(_m) < 0) return -1; } return 1; error: if (doreply) { send_reply(_m); return 0; } return -2; }