/*! \brief * Calculate contact q value as follows: * 1) If xavp_cfg q has been defined, use it * 2) If q parameter exists in contact, use it * 3) If the parameter doesn't exist in contact, use the default value */ int calc_contact_q(param_t* _q, qvalue_t* _r) { sr_xavp_t *vavp = NULL; str xqname = str_init("q"); if (reg_xavp_cfg.s != NULL) vavp = xavp_get_child_with_ival(®_xavp_cfg, &xqname); if (vavp != NULL) { if ((vavp->val.v.i >= 0) && (vavp->val.v.i <= 1000)) { *_r = vavp->val.v.i; return 0; } else { rerrno = R_INV_Q; /* Invalid q parameter */ LM_ERR("invalid q parameter\n"); return -1; } } if (!_q || (_q->body.len == 0)) { *_r = cfg_get(registrar, registrar_cfg, default_q); } else { if (str2q(_r, _q->body.s, _q->body.len) < 0) { rerrno = R_INV_Q; /* Invalid q parameter */ LM_ERR("invalid q parameter\n"); return -1; } } return 0; }
/** * append new branches with generic parameters */ int corex_append_branch(sip_msg_t *msg, gparam_t *pu, gparam_t *pq) { str uri = {0}; str qv = {0}; int ret = 0; qvalue_t q = Q_UNSPECIFIED; flag_t branch_flags = 0; if (pu!=NULL) { if(fixup_get_svalue(msg, pu, &uri)!=0) { LM_ERR("cannot get the URI parameter\n"); return -1; } } if (pq!=NULL) { if(fixup_get_svalue(msg, pq, &qv)!=0) { LM_ERR("cannot get the Q parameter\n"); return -1; } if(qv.len>0 && str2q(&q, qv.s, qv.len)<0) { LM_ERR("cannot parse the Q parameter\n"); return -1; } } getbflagsval(0, &branch_flags); ret = append_branch(msg, (uri.len>0)?&uri:0, &msg->dst_uri, &msg->path_vec, q, branch_flags, msg->force_send_socket, 0, 0, 0, 0); if(uri.len<=0) { /* reset all branch attributes if r-uri was shifted to branch */ reset_force_socket(msg); setbflagsval(0, 0); if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; /* if this is a cloned message, don't free the path vector as it was copied into shm memory and will be freed as contiguous block*/ if (!(msg->msg_flags&FL_SHM_CLONE)) { if(msg->path_vec.s!=0) pkg_free(msg->path_vec.s); msg->path_vec.s = 0; msg->path_vec.len = 0; } } return ret; }
/* returns the number of contacts put in the sorted array */ static int sort_contacts(hdr_field_t *chdr, contact_t **ct_array, qvalue_t *q_array) { param_t *q_para; qvalue_t q; int n; int i,j; char backup; contact_t *ct_list; hdr_field_t *hdr; n = 0; /* number of sorted contacts */ for(hdr=chdr; hdr; hdr=hdr->next) { if(hdr->type != HDR_CONTACT_T) continue; ct_list = ((contact_body_t*)hdr->parsed)->contacts; for( ; ct_list ; ct_list = ct_list->next ) { /* check the filters first */ backup = ct_list->uri.s[ct_list->uri.len]; ct_list->uri.s[ct_list->uri.len] = 0; if ( run_filters( ct_list->uri.s )==-1 ){ ct_list->uri.s[ct_list->uri.len] = backup; continue; } ct_list->uri.s[ct_list->uri.len] = backup; /* does the contact has a q val? */ q_para = ct_list->q; if (q_para==0 || q_para->body.len==0) { q = DEFAULT_Q_VALUE; } else { if (str2q( &q, q_para->body.s, q_para->body.len)!=0) { LM_ERR("invalid q param\n"); /* skip this contact */ continue; } } LM_DBG("sort_contacts: <%.*s> q=%d\n", ct_list->uri.len,ct_list->uri.s,q); /*insert the contact into the sorted array */ for(i=0;i<n;i++) { /* keep in mind that the contact list is reversed */ if (q_array[i]<=q) continue; break; } if (i!=MAX_CONTACTS_PER_REPLY) { /* insert the contact at this position */ for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) { ct_array[j+1] = ct_array[j]; q_array[j+1] = q_array[j]; } ct_array[j+1] = ct_list; q_array[j+1] = q; if (n!=MAX_CONTACTS_PER_REPLY) n++; } } } return n; }
/* * Read in a literal real number and add it to the table of constant numbers, * creating a new entry if necessary. The incoming number is a string * value which must have a correct format. * Returns the index of the number in the constant table. * * given: * str string representation of number */ long addnumber(char *str) { NUMBER *q; q = str2q(str); return addqconstant(q); }
/** * append new branches with generic parameters */ int corex_append_branch(sip_msg_t *msg, gparam_t *pu, gparam_t *pq) { str uri = {0}; str qv = {0}; int ret = 0; qvalue_t q = Q_UNSPECIFIED; flag_t branch_flags = 0; if (pu!=NULL) { if(fixup_get_svalue(msg, pu, &uri)!=0) { LM_ERR("cannot get the URI parameter\n"); return -1; } } if (pq!=NULL) { if(fixup_get_svalue(msg, pq, &qv)!=0) { LM_ERR("cannot get the Q parameter\n"); return -1; } if(qv.len>0 && str2q(&q, qv.s, qv.len)<0) { LM_ERR("cannot parse the Q parameter\n"); return -1; } } getbflagsval(0, &branch_flags); ret = append_branch(msg, (uri.len>0)?&uri:0, &msg->dst_uri, &msg->path_vec, q, branch_flags, msg->force_send_socket, 0, 0); if(uri.len<=0) { /* reset all branch attributes if r-uri was shifted to branch */ reset_force_socket(msg); setbflagsval(0, 0); if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; if(msg->path_vec.s!=0) pkg_free(msg->path_vec.s); msg->path_vec.s = 0; msg->path_vec.len = 0; } return ret; }
int regapi_set_q_override(sip_msg_t *msg, str *new_q) { int _q; if (str2q(&_q, new_q->s, new_q->len) < 0) { LM_ERR("invalid q parameter\n"); return -1; } return set_q_override(msg, _q); }
/* returns the number of contacts put in the sorted array */ static int sort_contacts(contact_t *ct_list, contact_t **ct_array) { static qvalue_t q_array[MAX_CONTACTS_PER_REPLY]; param_t *q_para; qvalue_t q; int n; int i,j; char backup; n = 0; /* number of sorted contacts */ for( ; ct_list ; ct_list = ct_list->next ) { /* check the filters first */ backup = ct_list->uri.s[ct_list->uri.len]; ct_list->uri.s[ct_list->uri.len] = 0; if ( run_filters( ct_list->uri.s )==-1 ){ ct_list->uri.s[ct_list->uri.len] = backup; continue; } ct_list->uri.s[ct_list->uri.len] = backup; /* does the contact has a q val? */ q_para = ct_list->q; if (q_para==0 || q_para->body.len==0) { q = DEFAULT_Q_VALUE; } else { if (str2q( &q, q_para->body.s, q_para->body.len)!=0) { LOG(L_ERR, "ERROR:uac_redirect:sort_contacts: " "invalid q param\n"); /* skip this contact */ continue; } } DBG("DEBUG:uac_redirect:sort_contacts: <%.*s> q=%d\n", ct_list->uri.len,ct_list->uri.s,q); /*insert the contact into the sorted array */ for(i=0;i<n;i++) { /* keep in mind that the contact list is reversts */ if (q_array[i]<q) continue; break; } if (i!=MAX_CONTACTS_PER_REPLY) { /* insert the contact at this position */ for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) { ct_array[j+1] = ct_array[j]; q_array[j+1] = q_array[j]; } ct_array[j+1] = ct_list; q_array[j+1] = q; if (n!=MAX_CONTACTS_PER_REPLY) n++; } } return n; }
/*! \brief * Calculate contact q value as follows: * 1) If q parameter exists, use it * 2) If the parameter doesn't exist, use the default value */ int calc_contact_q(param_t* _q, qvalue_t* _r) { if (!_q || (_q->body.len == 0)) { *_r = cfg_get(registrar, registrar_cfg, default_q); } else { if (str2q(_r, _q->body.s, _q->body.len) < 0) { rerrno = R_INV_Q; /* Invalid q parameter */ LM_ERR("invalid q parameter\n"); return -1; } } return 0; }
/* returns the number of contacts put in the sorted array */ static void sort_contacts(contact_t *ct_list, str *ct_array, qvalue_t *q_array, int *n) { param_t *q_para; qvalue_t q; int i, j, rc; char backup; for( ; ct_list ; ct_list = ct_list->next ) { /* check the filters first */ backup = ct_list->uri.s[ct_list->uri.len]; ct_list->uri.s[ct_list->uri.len] = 0; if ( run_filters( ct_list->uri.s )==-1 ){ ct_list->uri.s[ct_list->uri.len] = backup; continue; } ct_list->uri.s[ct_list->uri.len] = backup; /* does the contact has a q val? */ q_para = ct_list->q; if (q_para==0 || q_para->body.len==0) { q = DEFAULT_Q_VALUE; } else { rc = str2q( &q, q_para->body.s, q_para->body.len); if (rc != 0) { LM_ERR("invalid qvalue (%.*s): %s\n", q_para->body.len, q_para->body.s, qverr2str(rc)); /* skip this contact */ continue; } } LM_DBG("sort_contacts: <%.*s> q=%d\n", ct_list->uri.len,ct_list->uri.s,q); /*insert the contact into the sorted array */ for(i=0;i<*n;i++) { /* keep in mind that the contact list is reversts */ if (q_array[i]<=q) continue; break; } if (i!=MAX_CONTACTS_PER_REPLY) { /* insert the contact at this position */ for( j=(*n)-1-1*((*n)==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) { ct_array[j+1] = ct_array[j]; q_array[j+1] = q_array[j]; } ct_array[j+1] = ct_list->uri; q_array[j+1] = q; if ((*n)!=MAX_CONTACTS_PER_REPLY) (*n)++; } } }
/* * Calculate contact q value as follows: * 1) If q parameter exists, use it * 2) If the parameter doesn't exist, use the default value */ int calc_contact_q(param_t* _q, qvalue_t* _r) { if (!_q || (_q->body.len == 0)) { *_r = default_q; } else { if (str2q(_r, _q->body.s, _q->body.len) < 0) { rerrno = R_INV_Q; /* Invalid q parameter */ LOG(L_ERR, "calc_contact_q(): Invalid q parameter\n"); return -1; } } return 0; }
/*! * \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 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; } }