int unregister_watcher(str* _f, str* _t, notcb_t _c, void* _data) { udomain_t* d; urecord_t* r; if (find_domain(&dom, &d) > 0) { LOG(L_ERR, "unregister_watcher(): Domain '%.*s' not found\n", dom.len, ZSW(dom.s)); return -1; } lock_udomain(d); if (get_urecord(d, _t, &r) > 0) { unlock_udomain(d); DBG("unregister_watcher(): Record not found\n"); return 0; } remove_watcher(r, _c, _data); release_urecord(r); unlock_udomain(d); return 0; }
int timer_udomain(udomain_t* _d) { struct urecord* ptr, *t; lock_udomain(_d); ptr = _d->d_ll.first; while(ptr) { if (timer_urecord(ptr) < 0) { LOG(L_ERR, "timer_udomain(): Error in timer_urecord\n"); unlock_udomain(_d); return -1; } /* Remove the entire record * if it is empty */ if (ptr->contacts == 0) { t = ptr; ptr = ptr->d_ll.next; mem_delete_urecord(_d, t); } else { ptr = ptr->d_ll.next; } } unlock_udomain(_d); /* process_del_list(_d->name); */ /* process_ins_list(_d->name); */ return 0; }
/** * Note: prevents the creation of any duplicate AoR */ static int receive_urecord_insert(bin_packet_t *packet) { str d, aor; urecord_t *r; udomain_t *domain; bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto out_err; } lock_udomain(domain, &aor); if (get_urecord(domain, &aor, &r) == 0) goto out; if (insert_urecord(domain, &aor, &r, 1) != 0) { unlock_udomain(domain, &aor); goto out_err; } out: unlock_udomain(domain, &aor); return 0; out_err: LM_ERR("failed to replicate event locally. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
static int receive_urecord_delete(bin_packet_t *packet) { str d, aor; udomain_t *domain; bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto out_err; } lock_udomain(domain, &aor); if (delete_urecord(domain, &aor, NULL, 1) != 0) { unlock_udomain(domain, &aor); goto out_err; } unlock_udomain(domain, &aor); return 0; out_err: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
int register_watcher(str* _f, str* _t, notcb_t _c, void* _data) { udomain_t* d; urecord_t* r; if (find_domain(&dom, &d) > 0) { LOG(L_ERR, "register_watcher(): Domain '%.*s' not found\n", dom.len, ZSW(dom.s)); return -1; } lock_udomain(d); if (get_urecord(d, _t, &r) > 0) { if (insert_urecord(d, _t, &r) < 0) { unlock_udomain(d); LOG(L_ERR, "register_watcher(): Error while creating a new record\n"); return -2; } } if (add_watcher(r, _c, _data) < 0) { LOG(L_ERR, "register_watcher(): Error while adding a watcher\n"); release_urecord(r); unlock_udomain(d); return -3; } unlock_udomain(d); return 0; }
/*! * \brief Delete a address of record including its contacts * \param cmd mi_root containing the parameter * \param param not used * \note expects 2 nodes: the table name and the AOR * \return mi_root with the result */ struct mi_root* mi_usrloc_rm_aor(struct mi_root *cmd, void *param) { struct mi_node *node; udomain_t *dom; str *aor; node = cmd->node.kids; if (node==NULL || node->next==NULL || node->next->next!=NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); /* look for table */ dom = mi_find_domain( &node->value ); if (dom==NULL) return init_mi_tree( 404, "Table not found", 15); /* process the aor */ aor = &node->next->value; if ( mi_fix_aor(aor)!=0 ) return init_mi_tree( 400, "Domain missing in AOR", 21); lock_udomain( dom, aor); if (delete_urecord( dom, aor, 0) < 0) { unlock_udomain( dom, aor); return init_mi_tree( 500, "Failed to delete AOR", 20); } unlock_udomain( dom, aor); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); }
static void rpc_add_contact(rpc_t* rpc, void* c) { udomain_t* d; int expires, flags, sid; double q; qvalue_t qval; str table, uid, contact; if (rpc->scan(c, "SSSdfd", &table, &uid, &contact, &expires, &q, &flags) < 6) return; qval = double2q(q); if (rpc->scan(c, "d", &sid) < 1) sid = -1; rpc_find_domain(&table, &d); if (d) { lock_udomain(d); if (add_contact(d, &uid, &contact, expires, qval, flags, sid) < 0) { unlock_udomain(d); ERR("Error while adding contact ('%.*s','%.*s') in table '%.*s'\n", uid.len, ZSW(uid.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s)); rpc->fault(c, 500, "Error while adding Contact"); return; } unlock_udomain(d); } else { rpc->fault(c, 400, "Table Not Found"); } }
static int receive_ucontact_delete(bin_packet_t *packet) { udomain_t *domain; urecord_t *record; ucontact_t *contact; str d, aor, contact_str, callid; int cseq, rc; bin_pop_str(packet, &d); bin_pop_str(packet,&aor); bin_pop_str(packet,&contact_str); bin_pop_str(packet,&callid); bin_pop_int(packet,&cseq); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } lock_udomain(domain, &aor); /* failure in retrieving a urecord may be ok, because packet order in UDP * is not guaranteed, so urecord_delete commands may arrive before * ucontact_delete's */ if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - ignoring request " "(ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); return 0; } /* simply specify a higher cseq and completely avoid any complications */ rc = get_ucontact(record, &contact_str, &callid, cseq + 1, &contact); if (rc != 0 && rc != 2) { LM_ERR("contact '%.*s' not found: (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } if (skip_replicated_db_ops) contact->flags |= FL_MEM; if (delete_ucontact(record, contact, 1) != 0) { LM_ERR("failed to delete ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
/*! * \brief Delete a contact from an AOR record * \param cmd mi_root containing the parameter * \param param not used * \note expects 3 nodes: the table name, the AOR and contact * \return mi_root with the result or 0 on failure */ struct mi_root* mi_usrloc_rm_contact(struct mi_root *cmd, void *param) { struct mi_node *node; udomain_t *dom; urecord_t *rec; ucontact_t* con; str *aor, *contact; int ret; node = cmd->node.kids; if (node==NULL || node->next==NULL || node->next->next==NULL || node->next->next->next!=NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); /* look for table */ dom = mi_find_domain( &node->value ); if (dom==NULL) return init_mi_tree( 404, "Table not found", 15); /* process the aor */ aor = &node->next->value; if ( mi_fix_aor(aor)!=0 ) return init_mi_tree( 400, "Domain missing in AOR", 21); lock_udomain( dom, aor); ret = get_urecord( dom, aor, &rec); if (ret == 1) { unlock_udomain( dom, aor); return init_mi_tree( 404, "AOR not found", 13); } contact = &node->next->next->value; set_mi_ul_cid(); ret = get_ucontact( rec, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &con); if (ret < 0) { unlock_udomain( dom, aor); return 0; } if (ret > 0) { unlock_udomain( dom, aor); return init_mi_tree( 404, "Contact not found", 17); } if (delete_ucontact(rec, con) < 0) { unlock_udomain( dom, aor); return 0; } release_urecord(rec); unlock_udomain( dom, aor); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); }
void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) { LM_DBG("Deleting subscriber"); impurecord_t* urec; LM_DBG("Updating reg subscription in IMPU record"); if(lock_domain) lock_udomain(_t, &s->presentity_uri); int res = get_impurecord(_t, &s->presentity_uri, &urec); if (res != 0) { if(lock_domain) unlock_udomain(_t, &s->presentity_uri); return; } delete_subscriber(urec, s); if(lock_domain) unlock_udomain(_t, &s->presentity_uri); }
static void rpc_delete_uid(rpc_t* rpc, void* c) { udomain_t* d; str uid, t; if (rpc->scan(c, "SS", &t, &uid) < 2) return; rpc_find_domain(&t, &d); if (d) { lock_udomain(d); if (delete_urecord(d, &uid) < 0) { ERR("Error while deleting user %.*s\n", uid.len, uid.s); unlock_udomain(d); rpc->fault(c, 500, "Error While Deleting Record"); return; } unlock_udomain(d); } else { rpc->fault(c, 400, "Table Not Found"); } }
static void rpc_show_contacts(rpc_t* rpc, void* c) { udomain_t* d; urecord_t* r; int res; str t, uid; if (rpc->scan(c, "SS", &t, &uid) < 2) return; rpc_find_domain(&t, &d); if (d) { lock_udomain(d); res = get_urecord(d, &uid, &r); if (res < 0) { rpc->fault(c, 500, "Error While Searching AOR"); ERR("Error while looking for username %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s); unlock_udomain(d); return; } if (res > 0) { rpc->fault(c, 404, "AOR Not Found"); unlock_udomain(d); return; } get_act_time(); if (!print_contacts(rpc, c, r->contacts)) { unlock_udomain(d); rpc->fault(c, 404, "No Registered Contacts Found"); return; } unlock_udomain(d); } else { rpc->fault(c, 400, "Table Not Found"); } }
void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) { LM_DBG("Deleting subscriber"); impurecord_t* urec; LM_DBG("Updating reg subscription in IMPU record"); if(lock_domain) lock_udomain(_t, &s->presentity_uri); int res = get_impurecord(_t, &s->presentity_uri, &urec); if (res != 0) { if(lock_domain) unlock_udomain(_t, &s->presentity_uri); return; } if (urec->shead == s) urec->shead = s->next; else s->prev->next = s->next; if (urec->stail == s) urec->stail = s->prev; else s->next->prev = s->prev; LM_DBG("About to free subscriber memory"); free_subscriber(s); if(lock_domain) unlock_udomain(_t, &s->presentity_uri); }
int read_reg_avps(struct sip_msg *m, char* _domain, char* fp) { urecord_t* r = NULL; struct ucontact *contact = NULL; udomain_t *d; str uid; if (!use_reg_avps()) return 1; d = (udomain_t*)_domain; if (get_str_fparam(&uid, m, (fparam_t*)fp) < 0) { ERR("invalid parameter\n"); return -1; } /* INFO("reading avps for uid=%.*s\n", uid.len, ZSW(uid.s)); */ lock_udomain(d); if (get_urecord(d, &uid, &r) != 0) { unlock_udomain(d); WARN("urecord not found\n"); return -1; } if (get_ucontact(r, &m->new_uri, &contact) != 0) { unlock_udomain(d); WARN("ucontact not found\n"); return -1; } load_reg_avps(contact); unlock_udomain(d); return 1; }
/* * Free all memory allocated for * the domain */ void free_udomain(udomain_t* _d) { int i; lock_udomain(_d); if (_d->table) { for(i = 0; i < UDOMAIN_HASH_SIZE; i++) { deinit_slot(_d->table + i); } shm_free(_d->table); } unlock_udomain(_d); lock_destroy(&_d->lock);/* destroy the lock (required for SYSV sems!)*/ shm_free(_d); }
static void rpc_delete_contact(rpc_t* rpc, void* ctx) { udomain_t* d; urecord_t* r; ucontact_t* con; str uid, t, c; int res; if (rpc->scan(ctx, "SSS", &t, &uid, &c) < 3) return; rpc_find_domain(&t, &d); if (d) { lock_udomain(d); res = get_urecord(d, &uid, &r); if (res < 0) { rpc->fault(ctx, 500, "Error While Searching Table"); ERR("Error while looking for uid %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s); unlock_udomain(d); return; } if (res > 0) { rpc->fault(ctx, 404, "AOR Not Found"); unlock_udomain(d); return; } res = get_ucontact(r, &c, &con); if (res < 0) { rpc->fault(ctx, 500, "Error While Searching for Contact"); ERR("Error while looking for contact %.*s\n", c.len, c.s); unlock_udomain(d); return; } if (res > 0) { rpc->fault(ctx, 404, "Contact Not Found"); unlock_udomain(d); return; } if (delete_ucontact(r, con) < 0) { rpc->fault(ctx, 500, "Error While Deleting Contact"); unlock_udomain(d); return; } release_urecord(r); unlock_udomain(d); } else { rpc->fault(ctx, 404, "Table Not Found"); } }
static void ul_rpc_show_impu(rpc_t* rpc, void* ctx) { int i, j; str impu; int res; udomain_t* domain; struct impurecord* impu_rec; ucontact_t* contact; void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi; char numstr[21+16]; //enough for all numbers up to 64bits + longest length of field name (16) if (rpc->scan(ctx, "S", &impu) < 1) { rpc->fault(ctx, 400, "required IMPU argument"); return; } LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s); res = get_udomain("location", &domain); if (res != 0) { LM_ERR("Failed to get domain\n"); return; } lock_udomain(domain, &impu); res = get_impurecord(domain, &impu, &impu_rec); if (res != 0) { unlock_udomain(domain, &impu); return; } //now print the data for this IMPU record if (rpc->add(ctx, "{", &ah) < 0) { rpc->fault(ctx, 500, "Internal error creating IMPU struct"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "SsdSSSS", "impu", &impu, "state", get_impu_regstate_as_string(impu_rec->reg_state), "barring", impu_rec->barring, "ccf1", &impu_rec->ccf1, "ccf2", &impu_rec->ccf2, "ecf1", &impu_rec->ecf1, "ecf2", &impu_rec->ecf2 ) < 0) { rpc->fault(ctx, 500, "Internal error adding impu data"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); unlock_udomain(domain, &impu); return; } ims_subscription* subscription = impu_rec->s; lock_get(subscription->lock); //add subscription data if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } //add subscription detail information for (i=0; i<subscription->service_profiles_cnt; i++) { sprintf(numstr, "%d", i+1); if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } for (j=0; j<subscription->service_profiles[i].public_identities_cnt; j++) { sprintf(numstr, "%d", j+1); if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } } } lock_release(subscription->lock); //add contact data if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } contact = impu_rec->contacts; while (contact) { //contact is not null terminated so we need to create a null terminated version if (!contact_buf.s || (contact_buf.len <= contact->c.len)) { if (contact_buf.s && contact_buf.len <= contact->c.len){ pkg_free(contact_buf.s); } contact_buflen = contact->c.len + 1; contact_buf.s = (char*)pkg_malloc(contact_buflen); if (!contact_buf.s) { LM_ERR("no more pkg memory"); rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } } memcpy(contact_buf.s, contact->c.s, contact->c.len); contact_buf.s[contact->c.len] = '\0'; contact_buf.len = contact->c.len; LM_DBG("contact is %s\n", contact_buf.s); if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(cdh, "dS", "expires", contact->expires - time(NULL), "client", &contact->user_agent) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } contact = contact->next; } unlock_udomain(domain, &impu); }
static int ul_rm_contact(FILE* pipe, char* response_file) { char table[MAX_TABLE]; char user[MAX_USER]; char contact[MAX_CONTACT_LEN]; udomain_t* d; urecord_t* r; ucontact_t* con; str aor, t, c; int res; char* at; if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) { fifo_reply(response_file, "400 ul_rm_contact: table name expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: table name expected\n"); return 1; } if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) { fifo_reply(response_file, "400 ul_rm_contact: user name expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: user name expected\n"); return 1; } at = memchr(user, '@', aor.len); if (use_domain) { if (!at) { fifo_reply(response_file, "400 ul_rm_contact: user@domain expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: Domain missing\n"); return 1; } } else { if (at) { aor.len = at - user; } } if (!read_line(contact, MAX_CONTACT_LEN, pipe, &c.len) || c.len == 0) { fifo_reply(response_file, "400 ul_rm_contact: contact expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: contact expected\n"); return 1; } aor.s = user; strlower(&aor); t.s = table; c.s = contact; fifo_find_domain(&t, &d); LOG(L_INFO, "INFO: deleting user-loc contact (%s,%s,%s)\n", table, user, contact ); if (d) { lock_udomain(d); res = get_urecord(d, &aor, &r); if (res < 0) { fifo_reply(response_file, "500 Error while looking for username %s in table %s\n", user, table); LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for username %s in table %s\n", user, table); unlock_udomain(d); return 1; } if (res > 0) { fifo_reply(response_file, "404 Username %s in table %s not found\n", user, table); unlock_udomain(d); return 1; } res = get_ucontact(r, &c, &con); if (res < 0) { fifo_reply(response_file, "500 Error while looking for contact %s\n", contact); LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for contact %s\n", contact); unlock_udomain(d); return 1; } if (res > 0) { fifo_reply(response_file, "404 Contact %s in table %s not found\n", contact, table); unlock_udomain(d); return 1; } if (delete_ucontact(r, con) < 0) { fifo_reply(response_file, "500 ul_rm_contact: Error while deleting contact %s\n", contact); unlock_udomain(d); return 1; } release_urecord(r); unlock_udomain(d); fifo_reply(response_file, "200 Contact (%s, %s) deleted from table %s\n", user, contact, table); return 1; } else { fifo_reply(response_file, "400 table (%s) not found\n", table); return 1; } }
/*! * \brief Dumps the contacts of an AOR * \param cmd mi_root containing the parameter * \param param not used * \note expects 2 nodes: the table name and the AOR * \return mi_root with the result or 0 on failure */ struct mi_root* mi_usrloc_show_contact(struct mi_root *cmd, void *param) { struct mi_root *rpl_tree; struct mi_node *rpl, *node; udomain_t *dom; urecord_t *rec; ucontact_t* con; str *aor; int ret; node = cmd->node.kids; if (node==NULL || node->next==NULL || node->next->next!=NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); /* look for table */ dom = mi_find_domain( &node->value ); if (dom==NULL) return init_mi_tree( 404, "Table not found", 15); /* process the aor */ aor = &node->next->value; if ( mi_fix_aor(aor)!=0 ) return init_mi_tree( 400, "Domain missing in AOR", 21); lock_udomain( dom, aor); ret = get_urecord( dom, aor, &rec); if (ret == 1) { unlock_udomain( dom, aor); return init_mi_tree( 404, "AOR not found", 13); } get_act_time(); rpl_tree = 0; rpl = 0; for( con=rec->contacts ; con ; con=con->next) { if (VALID_CONTACT( con, act_time)) { if (rpl_tree==0) { rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) goto error; rpl = &rpl_tree->node; } node = addf_mi_node_child( rpl, 0, "Contact", 7, "<%.*s>;q=%s;expires=%d;flags=0x%X;cflags=0x%X;socket=<%.*s>;" "methods=0x%X" "%s%.*s%s" /*received*/ "%s%.*s%s" /*user-agent*/ "%s%.*s%s" /*path*/ "%s%.*s" /*instance*/ ";reg-id=%u", con->c.len, ZSW(con->c.s), q2str(con->q, 0), (int)(con->expires - act_time), con->flags, con->cflags, con->sock?con->sock->sock_str.len:3, con->sock?con->sock->sock_str.s:"NULL", con->methods, con->received.len?";received=<":"",con->received.len, ZSW(con->received.s), con->received.len?">":"", con->user_agent.len?";user_agent=<":"",con->user_agent.len, ZSW(con->user_agent.s), con->user_agent.len?">":"", con->path.len?";path=<":"", con->path.len, ZSW(con->path.s), con->path.len?">":"", con->instance.len?";+sip.instance=":"", con->instance.len, ZSW(con->instance.s), con->reg_id ); if (node==0) goto error; } } unlock_udomain( dom, aor); if (rpl_tree==0) return init_mi_tree( 404 , "AOR has no contacts", 18); return rpl_tree; error: if (rpl_tree) free_mi_tree( rpl_tree ); unlock_udomain( dom, aor); return 0; }
static inline int ul_show_contact(FILE* pipe, char* response_file) { char table[MAX_TABLE]; char user[MAX_USER]; FILE* reply_file; udomain_t* d; urecord_t* r; int res; str t, aor; char* at; if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) { fifo_reply(response_file, "400 ul_show_contact: table name expected\n"); LOG(L_ERR, "ERROR: ul_show_contact: table name expected\n"); return 1; } if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) { fifo_reply(response_file, "400 ul_show_contact: user name expected\n"); LOG(L_ERR, "ERROR: ul_show_contact: user name expected\n"); return 1; } at = memchr(user, '@', aor.len); if (use_domain) { if (!at) { fifo_reply(response_file, "400 ul_show_contact: user@domain expected\n"); LOG(L_ERR, "ERROR: ul_show_contact: Domain missing\n"); return 1; } } else { if (at) { aor.len = at - user; } } aor.s = user; strlower(&aor); t.s = table; fifo_find_domain(&t, &d); if (d) { lock_udomain(d); res = get_urecord(d, &aor, &r); if (res < 0) { fifo_reply(response_file, "500 Error while looking for username %s in table %s\n", user, table); LOG(L_ERR, "ERROR: ul_show_contact: Error while looking for username %s in table %s\n", user, table); unlock_udomain(d); return 1; } if (res > 0) { fifo_reply(response_file, "404 Username %s in table %s not found\n", user, table); unlock_udomain(d); return 1; } get_act_time(); reply_file=open_reply_pipe(response_file); if (reply_file==0) { LOG(L_ERR, "ERROR: ul_show_contact: file not opened\n"); unlock_udomain(d); return 1; } if (!print_contacts(reply_file, r->contacts)) { unlock_udomain(d); fprintf(reply_file, "404 No registered contacts found\n"); fclose(reply_file); return 1; } fclose(reply_file); unlock_udomain(d); return 1; } else { fifo_reply(response_file, "400 table (%s) not found\n", table); return 1; } }
/*! * \brief Add a new contact for an address of record * \param cmd mi_root containing the parameter * \param param not used * \note Expects 7 nodes: table name, AOR, contact, expires, Q, * useless - backward compatible, flags, cflags, methods * \return mi_root with the result */ struct mi_root* mi_usrloc_add(struct mi_root *cmd, void *param) { ucontact_info_t ci; urecord_t* r; ucontact_t* c; struct mi_node *node; udomain_t *dom; str *aor, *contact; unsigned int ui_val; int n; for( n=0,node = cmd->node.kids; n<9 && node ; n++,node=node->next ); if (n!=9 || node!=0) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); node = cmd->node.kids; /* look for table (param 1) */ dom = mi_find_domain( &node->value ); if (dom==NULL) return init_mi_tree( 404, "Table not found", 15); /* process the aor (param 2) */ node = node->next; aor = &node->value; if ( mi_fix_aor(aor)!=0 ) return init_mi_tree( 400, "Domain missing in AOR", 21); /* contact (param 3) */ node = node->next; contact = &node->value; memset( &ci, 0, sizeof(ucontact_info_t)); /* expire (param 4) */ node = node->next; if (str2int( &node->value, &ui_val) < 0) goto bad_syntax; ci.expires = ui_val; /* q value (param 5) */ node = node->next; if (str2q( &ci.q, node->value.s, node->value.len) < 0) goto bad_syntax; /* unused value (param 6) FIXME */ node = node->next; /* flags value (param 7) */ node = node->next; if (str2int( &node->value, (unsigned int*)&ci.flags) < 0) goto bad_syntax; /* branch flags value (param 8) */ node = node->next; if (str2int( &node->value, (unsigned int*)&ci.cflags) < 0) goto bad_syntax; /* methods value (param 9) */ node = node->next; if (str2int( &node->value, (unsigned int*)&ci.methods) < 0) goto bad_syntax; if(sruid_next(&_ul_sruid)<0) goto error; ci.ruid = _ul_sruid.uid; lock_udomain( dom, aor); n = get_urecord( dom, aor, &r); if ( n==1) { if (insert_urecord( dom, aor, &r) < 0) goto lock_error; c = 0; } else { if (get_ucontact( r, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &c) < 0) goto lock_error; } get_act_time(); ci.callid = &mi_ul_cid; ci.user_agent = &mi_ul_ua; ci.cseq = MI_UL_CSEQ; /* 0 expires means permanent contact */ if (ci.expires!=0) ci.expires += act_time; if (c) { if (update_ucontact( r, c, &ci) < 0) goto release_error; } else { if ( insert_ucontact( r, contact, &ci, &c) < 0 ) goto release_error; } release_urecord(r); unlock_udomain( dom, aor); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); release_error: release_urecord(r); lock_error: unlock_udomain( dom, aor); error: return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); }
static int receive_ucontact_insert(bin_packet_t *packet) { static ucontact_info_t ci; static str d, aor, host, contact_str, callid, user_agent, path, attr, st, sock; udomain_t *domain; urecord_t *record; ucontact_t *contact; int rc, port, proto; memset(&ci, 0, sizeof ci); bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } bin_pop_str(packet, &contact_str); bin_pop_str(packet, &st); memcpy(&ci.contact_id, st.s, sizeof ci.contact_id); bin_pop_str(packet, &callid); ci.callid = &callid; bin_pop_str(packet, &user_agent); ci.user_agent = &user_agent; bin_pop_str(packet, &path); ci.path = &path; bin_pop_str(packet, &attr); ci.attr = &attr; bin_pop_str(packet, &ci.received); bin_pop_str(packet, &ci.instance); bin_pop_str(packet, &st); memcpy(&ci.expires, st.s, sizeof ci.expires); bin_pop_str(packet, &st); memcpy(&ci.q, st.s, sizeof ci.q); bin_pop_str(packet, &sock); if (sock.s && sock.s[0]) { if (parse_phostport(sock.s, sock.len, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%.*s>\n", sock.len, sock.s); goto error; } ci.sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); if (!ci.sock) LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s); } else { ci.sock = NULL; } bin_pop_int(packet, &ci.cseq); bin_pop_int(packet, &ci.flags); bin_pop_int(packet, &ci.cflags); bin_pop_int(packet, &ci.methods); bin_pop_str(packet, &st); memcpy(&ci.last_modified, st.s, sizeof ci.last_modified); if (skip_replicated_db_ops) ci.flags |= FL_MEM; lock_udomain(domain, &aor); if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - creating new one " "(ci: '%.*s') \n", callid.len, callid.s); if (insert_urecord(domain, &aor, &record, 1) != 0) { LM_ERR("failed to insert new record\n"); unlock_udomain(domain, &aor); goto error; } } rc = get_ucontact(record, &contact_str, &callid, ci.cseq, &contact); switch (rc) { case -2: /* received data is consistent with what we have */ case -1: /* received data is older than what we have */ break; case 0: /* received data is newer than what we have */ if (update_ucontact(record, contact, &ci, 1) != 0) { LM_ERR("failed to update ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } break; case 1: if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } break; } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
/*! * \brief Load all records from a udomain * * Load all records from a udomain, useful to populate the * memory cache on startup. * \param _c database connection * \param _d loaded domain * \return 0 on success, -1 on failure */ int preload_udomain(db1_con_t* _c, udomain_t* _d) { pcontact_info_t *ci; db_row_t *row; db_key_t columns[18]; db1_res_t* res = NULL; str aor, contact; int i, n; pcontact_t* c; LM_DBG("pre-loading domain from DB\n"); columns[0] = &domain_col; columns[1] = &aor_col; columns[2] = &contact_col; columns[3] = &received_col; columns[4] = &rx_session_id_col; columns[5] = ®_state_col; columns[6] = &expires_col; columns[7] = &socket_col; columns[8] = &service_routes_col; columns[9] = &public_ids_col; columns[10] = &path_col; if (ul_dbf.use_table(_c, _d->name) < 0) { LM_ERR("sql use_table failed\n"); return -1; } #ifdef EXTRA_DEBUG LM_NOTICE("load start time [%d]\n", (int)time(NULL)); #endif if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, 0) < 0) { LM_ERR("db_query (1) failed\n"); return -1; } if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) { LM_ERR("fetching rows failed\n"); return -1; } } else { if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) { LM_ERR("db_query failed\n"); return -1; } } if (RES_ROW_N(res) == 0) { LM_DBG("table is empty\n"); ul_dbf.free_result(_c, res); return 0; } LM_DBG("%d rows returned in preload\n", RES_ROW_N(res)); n = 0; do { LM_DBG("loading records - cycle [%d]\n", ++n); for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; aor.s = (char*) VAL_STRING(ROW_VALUES(row) + 1); if (VAL_NULL(ROW_VALUES(row) + 1) || aor.s == 0 || aor.s[0] == 0) { LM_CRIT("empty aor record in table %s...skipping\n", _d->name->s); continue; } aor.len = strlen(aor.s); ci = dbrow2info( ROW_VALUES(row)+1, &contact); if (ci==0) { LM_ERR("usrloc record for %.*s in table %s\n", aor.len, aor.s, _d->name->s); continue; } lock_udomain(_d, &aor); if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) { LM_ERR("inserting contact failed\n"); unlock_udomain(_d, &aor); goto error1; } unlock_udomain(_d, &aor); } if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) { LM_ERR("fetching rows (1) failed\n"); ul_dbf.free_result(_c, res); return -1; } } else { break; } } while(RES_ROW_N(res)>0); ul_dbf.free_result(_c, res); #ifdef EXTRA_DEBUG LM_NOTICE("load end time [%d]\n", (int)time(NULL)); #endif return 0; error1: free_pcontact(c); ul_dbf.free_result(_c, res); return -1; }
/* update an existing impurecord. if one doesnt exist it will be created. * make sure yuo lock the domain before calling this and unlock it afterwards * return: 0 on success, -1 on failure */ int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) { int res; res = get_impurecord(_d, public_identity, _r); if (res != 0) { if (reg_state != IMPU_NOT_REGISTERED && s) { LM_DBG("No existing impu record for <%.*s>.... creating new one\n", public_identity->len, public_identity->s); res = insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r); //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored) (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn if (reg_state == IMPU_UNREGISTERED) { //update unreg expiry so the unreg record is not stored 'forever' (*_r)->expires = time(NULL) + unreg_validity; } if (res != 0) { LM_ERR("Unable to insert new IMPU for <%.*s>\n", public_identity->len, public_identity->s); return -1; } else { run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL); return 0; } } else { LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n"); return 0; } } //if we get here, we have a record to update LM_DBG("updating IMPU record with public identity for <%.*s>\n", public_identity->len, public_identity->s); (*_r)->reg_state = reg_state; if (reg_state == IMPU_UNREGISTERED) { //update unreg expiry so the unreg record is not stored 'forever' (*_r)->expires = time(NULL) + unreg_validity; } if (barring >= 0) (*_r)->barring = barring; if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete; if (ccf1) { if ((*_r)->ccf1.s) shm_free((*_r)->ccf1.s); STR_SHM_DUP((*_r)->ccf1, *ccf1, "SHM CCF1"); } if (ccf2) { if ((*_r)->ccf2.s) shm_free((*_r)->ccf2.s); STR_SHM_DUP((*_r)->ccf2, *ccf2, "SHM CCF2"); } if (ecf1) { if ((*_r)->ecf1.s) shm_free((*_r)->ecf1.s); STR_SHM_DUP((*_r)->ecf1, *ecf1, "SHM ECF1"); } if (ecf2) { if ((*_r)->ecf2.s) shm_free((*_r)->ecf2.s); STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2"); } if (s) { LM_DBG("we have a new ims_subscription\n"); if ((*_r)->s) { lock_get((*_r)->s->lock); if ((*_r)->s->ref_count == 1) { LM_DBG("freeing user data as no longer referenced\n"); free_ims_subscription_data((*_r)->s); //no need to release lock after this. its gone ;) (*_r)->s = 0; } else { (*_r)->s->ref_count--; LM_DBG("new ref count for ims sub is %d\n", (*_r)->s->ref_count); lock_release((*_r)->s->lock); } } (*_r)->s = *s; lock_get((*_r)->s->lock); (*_r)->s->ref_count++; lock_release((*_r)->s->lock); } run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL); return 0; out_of_memory: unlock_udomain(_d, public_identity); return -1; }
static int receive_ucontact_update(bin_packet_t *packet) { static ucontact_info_t ci; static str d, aor, host, contact_str, callid, user_agent, path, attr, st, sock; udomain_t *domain; urecord_t *record; ucontact_t *contact; int port, proto; int rc; memset(&ci, 0, sizeof ci); bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } bin_pop_str(packet, &contact_str); bin_pop_str(packet, &callid); ci.callid = &callid; bin_pop_str(packet, &user_agent); ci.user_agent = &user_agent; bin_pop_str(packet, &path); ci.path = &path; bin_pop_str(packet, &attr); ci.attr = &attr; bin_pop_str(packet, &ci.received); bin_pop_str(packet, &ci.instance); bin_pop_str(packet, &st); memcpy(&ci.expires, st.s, sizeof ci.expires); bin_pop_str(packet, &st); memcpy(&ci.q, st.s, sizeof ci.q); bin_pop_str(packet, &sock); if (sock.s && sock.s[0]) { if (parse_phostport(sock.s, sock.len, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%.*s>\n", sock.len, sock.s); goto error; } ci.sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); if (!ci.sock) LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s); } else { ci.sock = NULL; } bin_pop_int(packet, &ci.cseq); bin_pop_int(packet, &ci.flags); bin_pop_int(packet, &ci.cflags); bin_pop_int(packet, &ci.methods); bin_pop_str(packet, &st); memcpy(&ci.last_modified, st.s, sizeof ci.last_modified); bin_pop_str(packet, &st); ci.packed_kv_storage = &st; if (skip_replicated_db_ops) ci.flags |= FL_MEM; lock_udomain(domain, &aor); /* failure in retrieving a urecord may be ok, because packet order in UDP * is not guaranteed, so update commands may arrive before inserts */ if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - create new record and contact" " (ci: '%.*s')\n", callid.len, callid.s); if (insert_urecord(domain, &aor, &record, 1) != 0) { LM_ERR("failed to insert urecord\n"); unlock_udomain(domain, &aor); goto error; } if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } else { rc = get_ucontact(record, &contact_str, &callid, ci.cseq + 1, &contact); if (rc == 1) { LM_INFO("contact '%.*s' not found, inserting new (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } else if (rc == 0) { if (update_ucontact(record, contact, &ci, 1) != 0) { LM_ERR("failed to update ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } /* XXX: for -2 and -1, the master should have already handled these errors - so we can skip them - razvanc */ } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
/*! * \brief release the lock on the impurecord - effectively the domain slot * \param _d domain * \param _r impurecord to release (unlock) */ void release_impurecord(udomain_t* _d, struct impurecord* _r) { unlock_udomain(_d, &_r->public_identity); }
int static ul_rm( FILE *pipe, char *response_file ) { char table[MAX_TABLE]; char user[MAX_USER]; udomain_t* d; str aor, t; char* at; if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) { fifo_reply(response_file, "400 ul_rm: table name expected\n"); LOG(L_ERR, "ERROR: ul_rm: table name expected\n"); return 1; } if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) { fifo_reply(response_file, "400 ul_rm: user name expected\n"); LOG(L_ERR, "ERROR: ul_rm: user name expected\n"); return 1; } at = memchr(user, '@', aor.len); if (use_domain) { if (!at) { fifo_reply(response_file, "400 ul_rm: username@domain expected\n"); LOG(L_ERR, "ERROR: ul_rm: Domain missing\n"); return 1; } } else { if (at) { aor.len = at - user; } } aor.s = user; strlower(&aor); t.s = table; fifo_find_domain(&t, &d); LOG(L_INFO, "INFO: deleting user-loc (%s,%s)\n", table, user ); if (d) { lock_udomain(d); if (delete_urecord(d, &aor) < 0) { LOG(L_ERR, "ul_rm(): Error while deleting user %s\n", user); unlock_udomain(d); fifo_reply(response_file, "500 Error while deleting user %s\n", user); return 1; } unlock_udomain(d); fifo_reply(response_file, "200 user (%s, %s) deleted\n", table, user); return 1; } else { fifo_reply(response_file, "400 table (%s) not found\n", table); return 1; } }
/* * Return list of all contacts for all currently registered * users in all domains. Caller must provide buffer of * sufficient length for fitting all those contacts. In the * case when buffer was exhausted, the function returns * estimated amount of additional space needed, in this * case the caller is expected to repeat the call using * this value as the hint. * * Information is packed into the buffer as follows: * * +------------+----------+------------+----------- * |contact1.len|contact1.s|contact2.len|contact2.s| * +------------+----------+------------+----------- * |.......................|contactN.len|contactN.s| * +------------+----------+------------+----------+ * |000000000000| * +------------+ */ int get_all_ucontacts(void *buf, int len, unsigned int flags) { dlist_t *p; urecord_t *r; ucontact_t *c; void *cp; int shortage; cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(c->c.len); for (p = root; p != NULL; p = p->next) { lock_udomain(p->d); if (p->d->d_ll.n <= 0) { unlock_udomain(p->d); continue; } for (r = p->d->d_ll.first; r != NULL; r = r->d_ll.next) { for (c = r->contacts; c != NULL; c = c->next) { if (c->c.len <= 0) continue; /* * List only contacts that have all requested * flags set */ if ((c->flags & flags) != flags) continue; if (c->received.s) { if (len >= (int)(sizeof(c->received.len) + c->received.len)) { memcpy(cp, &c->received.len, sizeof(c->received.len)); cp = (char*)cp + sizeof(c->received.len); memcpy(cp, c->received.s, c->received.len); cp = (char*)cp + c->received.len; len -= sizeof(c->received.len) + c->received.len; } else { shortage += sizeof(c->received.len) + c->received.len; } } else { if (len >= (int)(sizeof(c->c.len) + c->c.len)) { memcpy(cp, &c->c.len, sizeof(c->c.len)); cp = (char*)cp + sizeof(c->c.len); memcpy(cp, c->c.s, c->c.len); cp = (char*)cp + c->c.len; len -= sizeof(c->c.len) + c->c.len; } else { shortage += sizeof(c->c.len) + c->c.len; } } } } unlock_udomain(p->d); } /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(c->c.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
int preload_udomain(db_con_t* _c, udomain_t* _d) { char b[256]; db_key_t columns[11]; db_res_t* res; db_row_t* row; int i, cseq; unsigned int flags; struct socket_info* sock; str uid, contact, callid, ua, received, instance, aor; str* rec; time_t expires; qvalue_t q; urecord_t* r; ucontact_t* c; columns[0] = uid_col.s; columns[1] = contact_col.s; columns[2] = expires_col.s; columns[3] = q_col.s; columns[4] = callid_col.s; columns[5] = cseq_col.s; columns[6] = flags_col.s; columns[7] = user_agent_col.s; columns[8] = received_col.s; columns[9] = instance_col.s; columns[10] = aor_col.s; memcpy(b, _d->name->s, _d->name->len); b[_d->name->len] = '\0'; if (ul_dbf.use_table(_c, b) < 0) { LOG(L_ERR, "preload_udomain(): Error in use_table\n"); return -1; } if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) { LOG(L_ERR, "preload_udomain(): Error while doing db_query\n"); return -1; } if (RES_ROW_N(res) == 0) { DBG("preload_udomain(): Table is empty\n"); ul_dbf.free_result(_c, res); return 0; } lock_udomain(_d); for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; uid.s = (char*)VAL_STRING(ROW_VALUES(row)); if (uid.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad uid " "record in table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { uid.len = strlen(uid.s); } contact.s = (char*)VAL_STRING(ROW_VALUES(row) + 1); if (contact.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad contact " "record in table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s\n", uid.len, uid.s); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { contact.len = strlen(contact.s); } expires = VAL_TIME (ROW_VALUES(row) + 2); q = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3)); cseq = VAL_INT (ROW_VALUES(row) + 5); callid.s = (char*)VAL_STRING(ROW_VALUES(row) + 4); if (callid.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad callid record in" " table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s," " contact %.*s\n", uid.len, uid.s, contact.len, contact.s); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { callid.len = strlen(callid.s); } flags = VAL_BITMAP(ROW_VALUES(row) + 6); ua.s = (char*)VAL_STRING(ROW_VALUES(row) + 7); if (ua.s) { ua.len = strlen(ua.s); } else { ua.len = 0; } if (!VAL_NULL(ROW_VALUES(row) + 8)) { received.s = (char*)VAL_STRING(ROW_VALUES(row) + 8); if (received.s) { received.len = strlen(received.s); rec = &received; sock = find_socket(&received); } else { received.len = 0; rec = 0; sock = 0; } } else { received.s = 0; received.len = 0; rec = 0; sock = 0; } if (!VAL_NULL(ROW_VALUES(row) + 9)) { instance.s = (char*)VAL_STRING(ROW_VALUES(row) + 9); if (instance.s) { instance.len = strlen(instance.s); } else { instance.len = 0; } } else { instance.s = 0; instance.len = 0; } if (!VAL_NULL(ROW_VALUES(row) + 10)) { aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 10); if (aor.s) { aor.len = strlen(aor.s); } else { aor.len = 0; } } else { aor.s = 0; aor.len = 0; } if (get_urecord(_d, &uid, &r) > 0) { if (mem_insert_urecord(_d, &uid, &r) < 0) { LOG(L_ERR, "preload_udomain(): Can't create a record\n"); ul_dbf.free_result(_c, res); unlock_udomain(_d); return -2; } } if (mem_insert_ucontact(r, &aor, &contact, expires, q, &callid, cseq, flags, &c, &ua, rec, sock, &instance) < 0) { LOG(L_ERR, "preload_udomain(): Error while inserting contact\n"); ul_dbf.free_result(_c, res); unlock_udomain(_d); return -3; } db_read_reg_avps(_c, c); /* We have to do this, because insert_ucontact sets state to CS_NEW * and we have the contact in the database already * we also store zombies in database so we have to restore * the correct state */ c->state = CS_SYNC; } ul_dbf.free_result(_c, res); unlock_udomain(_d); return 0; }
static int ul_add(FILE* pipe, char* response_file) { char table_s[MAX_TABLE]; char user_s[MAX_USER]; char contact_s[MAX_CONTACT_LEN]; char expires_s[MAX_EXPIRES_LEN]; char q_s[MAX_Q_LEN]; char rep_s[MAX_REPLICATE_LEN]; char flags_s[MAX_FLAGS_LEN]; udomain_t* d; int exp_i, flags_i; char* at; qvalue_t qval; str table, user, contact, expires, q, rep, flags; if (!read_line(table_s, MAX_TABLE, pipe, &table.len) || table.len == 0) { fifo_reply(response_file, "400 ul_add: table name expected\n"); LOG(L_ERR, "ERROR: ul_add: table name expected\n"); return 1; } if (!read_line(user_s, MAX_USER, pipe, &user.len) || user.len == 0) { fifo_reply(response_file, "400 ul_add: aor name expected\n"); LOG(L_ERR, "ERROR: ul_add: aor expected\n"); return 1; } at = memchr(user_s, '@', user.len); if (use_domain) { if (!at) { fifo_reply(response_file, "400 ul_add: username@domain expected\n"); LOG(L_ERR, "ERROR: ul_add: Domain missing\n"); return 1; } } else { if (at) { user.len = at - user_s; } } if (!read_line(contact_s, MAX_CONTACT_LEN, pipe, &contact.len) || contact.len == 0) { fifo_reply(response_file, "400 ul_add: contact expected\n"); LOG(L_ERR, "ERROR: ul_add: contact expected\n"); return 1; } if (!read_line(expires_s, MAX_EXPIRES_LEN, pipe, &expires.len) || expires.len == 0) { fifo_reply(response_file, "400 ul_add: expires expected\n"); LOG(L_ERR, "ERROR: ul_add: expires expected\n"); return 1; } if (!read_line(q_s, MAX_Q, pipe, &q.len) || q.len == 0) { fifo_reply(response_file, "400 ul_add: q expected\n"); LOG(L_ERR, "ERROR: ul_add: q expected\n"); return 1; } /* Kept for backwards compatibility */ if (!read_line(rep_s, MAX_REPLICATE_LEN, pipe, &rep.len) || rep.len == 0) { fifo_reply(response_file, "400 ul_add: replicate expected\n"); LOG(L_ERR, "ERROR: ul_add: replicate expected\n"); return 1; } if (!read_line(flags_s, MAX_FLAGS_LEN, pipe, &flags.len) || flags.len == 0) { fifo_reply(response_file, "400 ul_add: flags expected\n"); LOG(L_ERR, "ERROR: ul_add: flags expected\n"); return 1; } table.s = table_s; user.s = user_s; strlower(&user); contact.s = contact_s; expires.s = expires_s; q.s = q_s; flags.s = flags_s; fifo_find_domain(&table, &d); if (d) { if (str2int(&expires, (unsigned int*)&exp_i) < 0) { fifo_reply(response_file, "400 Invalid expires format\n"); return 1; } if (str2q(&qval, q.s, q.len) < 0) { fifo_reply(response_file, "400 Invalid q value\n"); return 1; } if (str2int(&flags, (unsigned int*)&flags_i) < 0) { fifo_reply(response_file, "400 Invalid flags format\n"); return 1; } lock_udomain(d); if (add_contact(d, &user, &contact, exp_i, qval, flags_i) < 0) { unlock_udomain(d); LOG(L_ERR, "ul_add(): Error while adding contact ('%.*s','%.*s') in table '%.*s'\n", user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s)); fifo_reply(response_file, "500 Error while adding contact\n" " ('%.*s','%.*s') in table '%.*s'\n", user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s)); return 1; } unlock_udomain(d); fifo_reply(response_file, "200 Added to table\n" "('%.*s','%.*s') to '%.*s'\n", user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s)); return 1; } else { fifo_reply(response_file, "400 Table '%.*s' not found in memory, use save(\"%.*s\") or lookup(\"%.*s\") in the configuration script first\n", table.len, ZSW(table.s), table.len, ZSW(table.s), table.len, ZSW(table.s)); return 1; } }