/** * Create a new peer. * - All the memory from parameters is duplicated. * @param fqdn - FQDN of the peer * @param realm - Realm of the peer * @param port - port of the peer to connect to * @returns the new peer* if ok, NULL on error */ peer* new_peer(str fqdn,str realm,int port) { peer *x; x = shm_malloc(sizeof(peer)); if (!x){ LOG_NO_MEM("shm",sizeof(peer)); goto error; } memset(x,0,sizeof(peer)); shm_str_dup(x->fqdn,fqdn); if (!x->fqdn.s) goto error; shm_str_dup(x->realm,realm); if (!x->realm.s) goto error; x->port = port; x->lock = lock_alloc(); x->lock = lock_init(x->lock); x->state = Closed; x->I_sock = -1; x->R_sock = -1; x->activity = time(0)-500; x->next = 0; x->prev = 0; return x; error: return 0; }
/** * Adds a failure route rule to rt. prefix, host, reply_code, and comment * must not contain NULL pointers. * * @param failure_tree the current route tree node * @param prefix the whole scan prefix * @param host the hostname last tried * @param reply_code the reply code * @param flags user defined flags * @param mask mask for user defined flags * @param next_domain continue routing with this domain * @param comment a comment for the route rule * * @return 0 on success, -1 on failure * * @see add_failure_route_to_tree() */ int add_failure_route_rule(struct failure_route_tree_item * failure_tree, const str * prefix, const str * host, const str * reply_code, flag_t flags, flag_t mask, const int next_domain, const str * comment) { struct failure_route_rule * shm_rr; struct failure_route_rule * rr; struct failure_route_rule * prev; if ((shm_rr = shm_malloc(sizeof(struct failure_route_rule))) == NULL) { LM_ERR("out of shared memory\n"); return -1; } memset(shm_rr, 0, sizeof(struct failure_route_rule)); if (shm_str_dup(&shm_rr->host, host) != 0) { goto mem_error; } if (shm_str_dup(&shm_rr->reply_code, reply_code) != 0) { goto mem_error; } shm_rr->flags = flags; shm_rr->mask = mask; shm_rr->next_domain = next_domain; if (shm_str_dup(&shm_rr->comment, comment) != 0) { goto mem_error; } /* before inserting into list, check priorities! */ rr=failure_tree->rule_list; prev=NULL; while ((rr != NULL) && (rule_prio_cmp(shm_rr, rr) > 0)) { prev=rr; rr=rr->next; } if(prev){ shm_rr->next = prev->next; prev->next = shm_rr; } else { shm_rr->next = failure_tree->rule_list; failure_tree->rule_list = shm_rr; } return 0; mem_error: LM_ERR("out of shared memory\n"); destroy_failure_route_rule(shm_rr); return -1; }
int dlg_add_extra(dlg_t* _d, str* _ldname, str* _rdname) { if(!_d || !_ldname || !_rdname) { LM_ERR("Invalid parameters\n"); return -1; } /* Make a copy of local Display Name */ if(shm_str_dup(&_d->loc_dname, _ldname) < 0) return -2; /* Make a copy of remote Display Name */ if(shm_str_dup(&_d->rem_dname, _rdname) < 0) return -3; return 0; }
/** * @brief duplicate dmq node */ dmq_node_t *shm_dup_node(dmq_node_t *node) { dmq_node_t *newnode; if(!node) { LM_ERR("node is null\n"); return NULL; } if(!node->orig_uri.s) { LM_ERR("nod->orig_uri.s is null\n"); return NULL; } newnode = shm_malloc(sizeof(dmq_node_t)); if(newnode == NULL) { LM_ERR("no more shm\n"); return NULL; } memcpy(newnode, node, sizeof(dmq_node_t)); newnode->orig_uri.s = NULL; if(shm_str_dup(&newnode->orig_uri, &node->orig_uri) < 0) { goto error; } if(parse_uri(newnode->orig_uri.s, newnode->orig_uri.len, &newnode->uri) < 0) { LM_ERR("error in parsing node uri\n"); goto error; } return newnode; error: destroy_dmq_node(newnode, 1); return NULL; }
/** * Create a new route tree root in shared memory and set it up. * * @param domain the domain name of the route tree * @param id the domain id of the route tree * * @return a pointer to the newly allocated route tree or NULL on * error, in which case it LOGs an error message. */ struct route_tree * create_route_tree(const str * domain, int id) { struct route_tree * tmp; if ((tmp = shm_malloc(sizeof(struct route_tree))) == NULL) { LM_ERR("out of shared memory\n"); return NULL; } memset(tmp, 0, sizeof(struct route_tree)); if (shm_str_dup(&tmp->name, domain)!=0) { LM_ERR("cannot duplicate string\n"); shm_free(tmp); return NULL; } tmp->id = id; return tmp; }
/* * Helper to copy input string parameter into a query parameter */ static int set_query_param(str* param, str input) { if (param->s) { shm_free(param->s); param->s = NULL; param->len = 0; } if (input.s && input.len > 0) { if (shm_str_dup(param, &input) < 0) { LM_ERR("Error allocating parameter\n"); return -1; } } return 1; }
/** * Tries to add a domain to the domain map. If the given domain doesn't * exist, it is added. Otherwise, nothing happens. * * @param domain the domain to be added * * @return values: on succcess the numerical index of the given domain, * -1 on failure */ int add_domain(const str * domain) { struct route_map * tmp, * prev = NULL; int id = 0; if (!script_routes) { if ((script_routes = shm_malloc(sizeof(struct route_map *))) == NULL) { LM_ERR("out of shared memory\n"); return -1; } memset(script_routes, 0, sizeof(struct route_map *)); } tmp = *script_routes; while (tmp) { if (str_strcmp(&tmp->name, domain) == 0) { return tmp->no; } id = tmp->no + 1; prev = tmp; tmp = tmp->next; } if ((tmp = shm_malloc(sizeof(struct route_map))) == NULL) { LM_ERR("out of shared memory\n"); return -1; } memset(tmp, 0, sizeof(struct route_map)); if (shm_str_dup(&tmp->name, domain) != 0) { LM_ERR("cannot duplicate string\n"); shm_free(tmp); return -1; } tmp->no = id; if (!prev) { *script_routes = tmp; } else { prev->next = tmp; } LM_INFO("domain %.*s has id %i\n", domain->len, domain->s, id); return id; }
frd_stats_entry_t* get_stats(str user, str prefix, str *shm_user) { rw_lock_t *item_lock; /* First go one level below using the user key */ frd_users_map_item_t **hm = (frd_users_map_item_t **)get_item(&stats_table, user, &item_lock); if (*hm == NULL) { /* First time the user is seen, we must create a hashmap */ *hm = shm_malloc(sizeof(frd_users_map_item_t)); if (*hm == NULL) { lock_stop_write(item_lock); LM_ERR("no more shm memory\n"); return NULL; } lock_stop_write(item_lock); (*hm)->numbers_hm.size = FRD_PREFIX_HASH_SIZE; if (init_hash_map(&(*hm)->numbers_hm) != 0) { LM_ERR("cannot init hashmap\n"); shm_free(*hm); return NULL; } if (shm_str_dup(&(*hm)->user, &user) != 0) { free_hash_map(&(*hm)->numbers_hm, destroy_stats_entry); shm_free(*hm); return NULL; } } lock_stop_write(item_lock); if (shm_user) *shm_user = (*hm)->user; frd_stats_entry_t **stats_entry = (frd_stats_entry_t**)get_item(&(*hm)->numbers_hm, prefix, &item_lock); if (*stats_entry == NULL) { /* First time the prefix is seen for this user */ *stats_entry = shm_malloc(sizeof(frd_stats_entry_t)); if (*stats_entry == NULL) { lock_stop_write(item_lock); LM_ERR("no more shm memory\n"); return NULL; } lock_stop_write(item_lock); /* Now init the auxiliary info for a stats structure */ if (!lock_init(&(*stats_entry)->lock)) { LM_ERR ("cannot init lock\n"); shm_free(*stats_entry); return NULL; } memset(&((*stats_entry)->stats), 0, sizeof(frd_stats_t)); } lock_stop_write(item_lock); return *stats_entry; }
/** * Processes an incoming message. * This actually just puts the message into a message queue. One worker will pick-it-up * and do the actual processing. * \note Must be called with a lock on the peer. * @param p - peer received from * @param msg - the message received */ void Rcv_Process(peer *p, AAAMessage *msg) { AAASession *session=0; unsigned int hash; // we need this here because after the sm_processing , we might end up // with no session any more if (msg->sessionId) session = get_session(msg->sessionId->data); if (session){ hash=session->hash; switch (session->type){ case AUTH_CLIENT_STATEFULL: if (is_req(msg)){ if (msg->commandCode==IMS_ASR) auth_client_statefull_sm_process(session,AUTH_EV_RECV_ASR,msg); else auth_client_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg); }else { if (msg->commandCode==IMS_STA) auth_client_statefull_sm_process(session,AUTH_EV_RECV_STA,msg); else auth_client_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg); } break; case AUTH_SERVER_STATEFULL: if (is_req(msg)) { auth_server_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg); }else{ if (msg->commandCode==IMS_ASA) auth_server_statefull_sm_process(session,AUTH_EV_RECV_ASA,msg); else auth_server_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg); } break; default: break; } sessions_unlock(hash); }else{ if (msg->sessionId){ if (msg->commandCode == IMS_ASR) auth_client_statefull_sm_process(0,AUTH_EV_RECV_ASR,msg); if (msg->commandCode == IMS_AAR) { session=AAACreateAuthSession(0,0,1,0,0); shm_str_dup(session->id,msg->sessionId->data); auth_server_statefull_sm_process(0,AUTH_EV_RECV_REQ,msg); } // Any other cases to think about? } } if (!put_task(p,msg)){ LOG(L_ERR,"ERROR:Rcv_Process(): Queue refused task\n"); AAAFreeMessage(&msg); } LOG(L_DBG,"DBG:Rcv_Process(): task added to queue\n"); // AAAPrintMessage(msg); }
/** * @brief build a dmq node */ dmq_node_t *build_dmq_node(str *uri, int shm) { dmq_node_t *ret = NULL; param_hooks_t hooks; param_t *params; /* For DNS-Lookups */ static char hn[256]; struct hostent *he; LM_DBG("build_dmq_node %.*s with %s memory\n", STR_FMT(uri), shm ? "shm" : "private"); if(shm) { ret = shm_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more shm\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(shm_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } else { ret = pkg_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more pkg\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(pkg_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } set_default_dmq_node_params(ret); if(parse_uri(ret->orig_uri.s, ret->orig_uri.len, &ret->uri) < 0 || ret->uri.host.len > 254) { LM_ERR("error parsing uri\n"); goto error; } /* if any parameters found, parse them */ if(parse_params(&ret->uri.params, CLASS_ANY, &hooks, ¶ms) < 0) { LM_ERR("error parsing params\n"); goto error; } /* if any params found */ if(params) { if(set_dmq_node_params(ret, params) < 0) { free_params(params); LM_ERR("error setting parameters\n"); goto error; } free_params(params); } else { LM_DBG("no dmqnode params found\n"); } /* resolve hostname */ strncpy(hn, ret->uri.host.s, ret->uri.host.len); hn[ret->uri.host.len] = '\0'; he = resolvehost(hn); if(he == 0) { LM_ERR("could not resolve %.*s\n", ret->uri.host.len, ret->uri.host.s); goto error; } hostent2ip_addr(&ret->ip_address, he, 0); return ret; error: if(ret != NULL) { destroy_dmq_node(ret, shm); } return NULL; }
int async_send_query(sip_msg_t *msg, str *query, cfg_action_t *act) { async_query_t *aq; unsigned int tindex = 0; unsigned int tlabel = 0; short suspend = 0; int dsize; int len; tm_cell_t *t = 0; if(query==0) { LM_ERR("invalid parameters\n"); return -1; } t = tmb.t_gett(); if (t==NULL || t==T_UNDEFINED) { LM_DBG("no pre-existing transaction, switching to transaction-less behavior\n"); } else if (!ah_params.suspend_transaction) { LM_DBG("transaction won't be suspended\n"); } else { if(tmb.t_suspend==NULL) { LM_ERR("http async query is disabled - tm module not loaded\n"); return -1; } if(tmb.t_suspend(msg, &tindex, &tlabel)<0) { LM_ERR("failed to suspend request processing\n"); return -1; } suspend = 1; LM_DBG("transaction suspended [%u:%u]\n", tindex, tlabel); } dsize = sizeof(async_query_t); aq = (async_query_t*)shm_malloc(dsize); if(aq==NULL) { LM_ERR("no more shm\n"); goto error; } memset(aq,0,dsize); if(shm_str_dup(&aq->query, query)<0) { goto error; } aq->param = act; aq->tindex = tindex; aq->tlabel = tlabel; aq->query_params.tls_verify_peer = ah_params.tls_verify_peer; aq->query_params.tls_verify_host = ah_params.tls_verify_host; aq->query_params.suspend_transaction = suspend; aq->query_params.timeout = ah_params.timeout; aq->query_params.headers = ah_params.headers; aq->query_params.method = ah_params.method; aq->query_params.authmethod = ah_params.authmethod; q_idx++; snprintf(q_id, MAX_ID_LEN+1, "%u-%u", (unsigned int)getpid(), q_idx); strncpy(aq->id, q_id, strlen(q_id)); aq->query_params.tls_client_cert.s = NULL; aq->query_params.tls_client_cert.len = 0; if (ah_params.tls_client_cert.s && ah_params.tls_client_cert.len > 0) { if (shm_str_dup(&aq->query_params.tls_client_cert, &(ah_params.tls_client_cert)) < 0) { LM_ERR("Error allocating aq->query_params.tls_client_cert\n"); goto error; } } aq->query_params.tls_client_key.s = NULL; aq->query_params.tls_client_key.len = 0; if (ah_params.tls_client_key.s && ah_params.tls_client_key.len > 0) { if (shm_str_dup(&aq->query_params.tls_client_key, &(ah_params.tls_client_key)) < 0) { LM_ERR("Error allocating aq->query_params.tls_client_key\n"); goto error; } } aq->query_params.tls_ca_path.s = NULL; aq->query_params.tls_ca_path.len = 0; if (ah_params.tls_ca_path.s && ah_params.tls_ca_path.len > 0) { if (shm_str_dup(&aq->query_params.tls_ca_path, &(ah_params.tls_ca_path)) < 0) { LM_ERR("Error allocating aq->query_params.tls_ca_path\n"); goto error; } } aq->query_params.body.s = NULL; aq->query_params.body.len = 0; if (ah_params.body.s && ah_params.body.len > 0) { if (shm_str_dup(&aq->query_params.body, &(ah_params.body)) < 0) { LM_ERR("Error allocating aq->query_params.body\n"); goto error; } } aq->query_params.username = NULL; if (ah_params.username) { len = strlen(ah_params.username); aq->query_params.username = shm_malloc(len+1); if(aq->query_params.username == NULL) { LM_ERR("error in shm_malloc\n"); goto error; } strncpy(aq->query_params.username, ah_params.username, len); aq->query_params.username[len] = '\0'; } aq->query_params.password = NULL; if (ah_params.password) { len = strlen(ah_params.password); aq->query_params.password = shm_malloc(len+1); if(aq->query_params.password == NULL) { LM_ERR("error in shm_malloc\n"); goto error; } strncpy(aq->query_params.password, ah_params.password, len); aq->query_params.password[len] = '\0'; } set_query_params(&ah_params); if(async_push_query(aq)<0) { LM_ERR("failed to relay query: %.*s\n", query->len, query->s); goto error; } if (suspend) { /* force exit in config */ return 0; } /* continue route processing */ return 1; error: if (suspend) { tmb.t_cancel_suspend(tindex, tlabel); } free_async_query(aq); return -1; }
void set_query_params(struct query_params *p) { p->headers.len = 0; p->headers.t = NULL; p->tls_verify_host = tls_verify_host; p->tls_verify_peer = tls_verify_peer; p->suspend_transaction = 1; p->timeout = http_timeout; p->method = AH_METH_DEFAULT; p->authmethod = default_authmethod; if (p->tls_client_cert.s && p->tls_client_cert.len > 0) { shm_free(p->tls_client_cert.s); p->tls_client_cert.s = NULL; p->tls_client_cert.len = 0; } if (tls_client_cert.s && tls_client_cert.len > 0) { if (shm_str_dup(&p->tls_client_cert, &tls_client_cert) < 0) { LM_ERR("Error allocating tls_client_cert\n"); return; } } if (p->tls_client_key.s && p->tls_client_key.len > 0) { shm_free(p->tls_client_key.s); p->tls_client_key.s = NULL; p->tls_client_key.len = 0; } if (tls_client_key.s && tls_client_key.len > 0) { if (shm_str_dup(&p->tls_client_key, &tls_client_key) < 0) { LM_ERR("Error allocating tls_client_key\n"); return; } } if (p->tls_ca_path.s && p->tls_ca_path.len > 0) { shm_free(p->tls_ca_path.s); p->tls_ca_path.s = NULL; p->tls_ca_path.len = 0; } if (tls_ca_path.s && tls_ca_path.len > 0) { if (shm_str_dup(&p->tls_ca_path, &tls_ca_path) < 0) { LM_ERR("Error allocating tls_ca_path\n"); return; } } if (p->body.s && p->body.len > 0) { shm_free(p->body.s); p->body.s = NULL; p->body.len = 0; } if (p->username) { shm_free(p->username); p->username = NULL; } if (p->password) { shm_free(p->password); p->password = NULL; } }
void notification_socket_cb(int fd, short event, void *arg) { (void)fd; /* unused */ (void)event; /* unused */ const async_http_worker_t *worker = (async_http_worker_t *) arg; int received; int i, len; async_query_t *aq; http_m_params_t query_params; str query; if ((received = recvfrom(worker->notication_socket[0], &aq, sizeof(async_query_t*), 0, NULL, 0)) < 0) { LM_ERR("failed to read from socket (%d: %s)\n", errno, strerror(errno)); return; } if(received != sizeof(async_query_t*)) { LM_ERR("invalid query size %d\n", received); return; } query = ((str)aq->query); query_params.timeout = aq->query_params.timeout; query_params.tls_verify_peer = aq->query_params.tls_verify_peer; query_params.tls_verify_host = aq->query_params.tls_verify_host; query_params.authmethod = aq->query_params.authmethod; query_params.headers = NULL; for (i = 0 ; i < aq->query_params.headers.len ; i++) { query_params.headers = curl_slist_append(query_params.headers, aq->query_params.headers.t[i]); } query_params.method = aq->query_params.method; query_params.tls_client_cert.s = NULL; query_params.tls_client_cert.len = 0; if (aq->query_params.tls_client_cert.s && aq->query_params.tls_client_cert.len > 0) { if (shm_str_dup(&query_params.tls_client_cert, &(aq->query_params.tls_client_cert)) < 0) { LM_ERR("Error allocating query_params.tls_client_cert\n"); goto done; } } query_params.tls_client_key.s = NULL; query_params.tls_client_key.len = 0; if (aq->query_params.tls_client_key.s && aq->query_params.tls_client_key.len > 0) { if (shm_str_dup(&query_params.tls_client_key, &(aq->query_params.tls_client_key)) < 0) { LM_ERR("Error allocating query_params.tls_client_key\n"); goto done; } } query_params.tls_ca_path.s = NULL; query_params.tls_ca_path.len = 0; if (aq->query_params.tls_ca_path.s && aq->query_params.tls_ca_path.len > 0) { if (shm_str_dup(&query_params.tls_ca_path, &(aq->query_params.tls_ca_path)) < 0) { LM_ERR("Error allocating query_params.tls_ca_path\n"); goto done; } } query_params.body.s = NULL; query_params.body.len = 0; if (aq->query_params.body.s && aq->query_params.body.len > 0) { if (shm_str_dup(&query_params.body, &(aq->query_params.body)) < 0) { LM_ERR("Error allocating query_params.body\n"); goto done; } } query_params.username = NULL; if (aq->query_params.username) { len = strlen(aq->query_params.username); query_params.username = shm_malloc(len+1); if(query_params.username == NULL) { LM_ERR("error in shm_malloc\n"); goto done; } strncpy(query_params.username, aq->query_params.username, len); query_params.username[len] = '\0'; } query_params.password = NULL; if (aq->query_params.password) { len = strlen(aq->query_params.password); query_params.password = shm_malloc(len+1); if(query_params.password == NULL) { LM_ERR("error in shm_malloc\n"); goto done; } strncpy(query_params.password, aq->query_params.password, len); query_params.password[len] = '\0'; } LM_DBG("query received: [%.*s] (%p)\n", query.len, query.s, aq); if (new_request(&query, &query_params, async_http_cb, aq) < 0) { LM_ERR("Cannot create request for %.*s\n", query.len, query.s); free_async_query(aq); } done: if (query_params.tls_client_cert.s && query_params.tls_client_cert.len > 0) { shm_free(query_params.tls_client_cert.s); query_params.tls_client_cert.s = NULL; query_params.tls_client_cert.len = 0; } if (query_params.tls_client_key.s && query_params.tls_client_key.len > 0) { shm_free(query_params.tls_client_key.s); query_params.tls_client_key.s = NULL; query_params.tls_client_key.len = 0; } if (query_params.tls_ca_path.s && query_params.tls_ca_path.len > 0) { shm_free(query_params.tls_ca_path.s); query_params.tls_ca_path.s = NULL; query_params.tls_ca_path.len = 0; } if (query_params.body.s && query_params.body.len > 0) { shm_free(query_params.body.s); query_params.body.s = NULL; query_params.body.len = 0; } if (query_params.username) { shm_free(query_params.username); query_params.username = NULL; } if (query_params.password) { shm_free(query_params.password); query_params.password = NULL; } return; }
/*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; }
/** * Adds a route rule to rf. prefix, rewrite_hostpart, rewrite_local_prefix, * rewrite_local_suffix, and comment must not contain NULL pointers. * * @param rf the current route_flags struct * @param prefix the whole scan prefix * @param max_targets the number of targets * @param prob the weight of the rule * @param rewrite_hostpart the rewrite_host of the rule * @param strip the strip value of the rule * @param rewrite_local_prefix the rewrite prefix * @param rewrite_local_suffix the rewrite suffix * @param status the status of the rule * @param hash_index the hash index of the rule * @param backup indicates if the route is backed up by another. only useful if status==0, if set, it is the hash value of another rule * @param backed_up an NULL-termintated array of hash indices of the route for which this route is backup * @param comment a comment for the route rule * * @return 0 on success, -1 on failure * * @see add_route_to_tree() */ int add_route_rule(struct route_flags *rf, const str * prefix, int max_targets, double prob, const str * rewrite_hostpart, int strip, const str * rewrite_local_prefix, const str * rewrite_local_suffix, int status, int hash_index, int backup, int * backed_up, const str * comment) { struct route_rule * shm_rr, * prev = NULL, * tmp = NULL; struct route_rule_p_list * t_rl; int * t_bu; if (max_targets) { rf->max_targets = max_targets; } else { rf->max_targets++; } if ((shm_rr = shm_malloc(sizeof(struct route_rule))) == NULL) { LM_ERR("out of shared memory\n"); return -1; } memset(shm_rr, 0, sizeof(struct route_rule)); if (shm_str_dup(&shm_rr->host, rewrite_hostpart) != 0) { goto mem_error; } if (shm_str_dup(&shm_rr->prefix, prefix) != 0) { goto mem_error; } shm_rr->strip = strip; if (shm_str_dup(&shm_rr->local_prefix, rewrite_local_prefix) != 0) { goto mem_error; } if (shm_str_dup(&shm_rr->local_suffix, rewrite_local_suffix) != 0) { goto mem_error; } if (shm_str_dup(&shm_rr->comment, comment) != 0) { goto mem_error; } shm_rr->status = status; shm_rr->hash_index = hash_index; shm_rr->orig_prob = prob; if (shm_rr->status || backup != -1) { shm_rr->prob = prob; } else { shm_rr->prob = 0; } if (backup >= 0) { if ((shm_rr->backup = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) { goto mem_error; } memset(shm_rr->backup, 0, sizeof(struct route_rule_p_list)); shm_rr->backup->hash_index = backup; } shm_rr->backed_up = NULL; t_bu = backed_up; if(!backed_up){ LM_INFO("no backed up rules\n"); } while (t_bu && *t_bu != -1) { if ((t_rl = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) { goto mem_error; } memset(t_rl, 0, sizeof(struct route_rule_p_list)); t_rl->hash_index = *t_bu; t_rl->next = shm_rr->backed_up; shm_rr->backed_up = t_rl; t_bu++; } /* rules with a probability of zero are always at the beginning of the list */ tmp = rf->rule_list; while(tmp && tmp->prob == 0){ prev = tmp; tmp = tmp->next; } /* rules with prob > 0 are sorted by hash_index */ while(tmp && (tmp->hash_index < shm_rr->hash_index)){ prev = tmp; tmp = tmp->next; } if(prev){ shm_rr->next = prev->next; prev->next = shm_rr; } else { shm_rr->next = rf->rule_list; rf->rule_list = shm_rr; } return 0; mem_error: LM_ERR("out of shared memory\n"); destroy_route_rule(shm_rr); return -1; }
/*! * \brief Create a new contact structure * \param _dom domain * \param _aor address of record * \param _contact contact string * \param _ci contact informations * \return new created contact on success, 0 on failure */ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci) { ucontact_t *c; c = (ucontact_t*)shm_malloc(sizeof(ucontact_t)); if (!c) { LM_ERR("no more shm memory\n"); return 0; } memset(c, 0, sizeof(ucontact_t)); if (_contact->s && _contact->len > 0) { if (shm_str_dup( &c->c, _contact) < 0) goto error; } if (_ci->callid->s && _ci->callid->len > 0) { if (shm_str_dup( &c->callid, _ci->callid) < 0) goto error; } if (_ci->user_agent->s && _ci->user_agent->len > 0) { if (shm_str_dup( &c->user_agent, _ci->user_agent) < 0) goto error; } if (_ci->received.s && _ci->received.len > 0) { if (shm_str_dup( &c->received, &_ci->received) < 0) goto error; } if (_ci->path && _ci->path->len > 0) { if (shm_str_dup( &c->path, _ci->path) < 0) goto error; } if (_ci->ruid.s && _ci->ruid.len > 0) { if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error; } if (_ci->instance.s && _ci->instance.len > 0) { if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error; } c->domain = _dom; c->aor = _aor; c->expires = _ci->expires; c->q = _ci->q; c->sock = _ci->sock; c->cseq = _ci->cseq; c->state = CS_NEW; c->flags = _ci->flags; c->cflags = _ci->cflags; c->methods = _ci->methods; c->reg_id = _ci->reg_id; c->last_modified = _ci->last_modified; return c; error: LM_ERR("no more shm memory\n"); if (c->path.s) shm_free(c->path.s); if (c->received.s) shm_free(c->received.s); if (c->user_agent.s) shm_free(c->user_agent.s); if (c->callid.s) shm_free(c->callid.s); if (c->c.s) shm_free(c->c.s); if (c->ruid.s) shm_free(c->ruid.s); if (c->instance.s) shm_free(c->instance.s); shm_free(c); return 0; }
/*! * \brief Create a new contact structure * \param _dom domain * \param _aor address of record * \param _contact contact string * \param _ci contact informations * \return new created contact on success, 0 on failure */ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci) { ucontact_t *c; param_t *prev, *curr, *param; int first = 1; c = (ucontact_t*) shm_malloc(sizeof (ucontact_t)); if (!c) { LM_ERR("no more shm memory\n"); return 0; } memset(c, 0, sizeof (ucontact_t)); c->lock = lock_alloc(); c->lock = lock_init(c->lock); //setup callback list c->cbs = (struct ulcb_head_list*) shm_malloc(sizeof (struct ulcb_head_list)); if (c->cbs == 0) { LM_CRIT("no more shared mem\n"); goto error; } c->cbs->first = 0; c->cbs->reg_types = 0; /*Copy parameter list into shm**/ param = _ci->params; while(param) { /*Copy first param in curr*/ curr = shm_malloc(sizeof (param_t)); curr->len = param->len; curr->type = param->type; curr->next = 0; if (shm_str_dup(&curr->body, ¶m->body) < 0) goto error; if (shm_str_dup(&curr->name, ¶m->name) < 0) goto error; if(first) { c->params = curr; first = 0; } else { prev->next = curr; } prev = curr; param = param->next; } if (shm_str_dup(&c->c, _contact) < 0) goto error; if (shm_str_dup(&c->callid, _ci->callid) < 0) goto error; if (shm_str_dup(&c->user_agent, _ci->user_agent) < 0) goto error; if (shm_str_dup(&c->aor, _aor) < 0) goto error; if (shm_str_dup(&c->domain, _dom) < 0) goto error; if (_ci->received.s && _ci->received.len) { if (shm_str_dup(&c->received, &_ci->received) < 0) goto error; } if (_ci->path && _ci->path->len) { if (shm_str_dup(&c->path, _ci->path) < 0) goto error; } LM_DBG("generating hash based on [%.*s]\n", _contact->len, _contact->s); c->contact_hash = core_hash(_contact, 0, contact_list->size); c->ref_count = 1; c->expires = _ci->expires; c->q = _ci->q; c->sock = _ci->sock; c->cseq = _ci->cseq; c->flags = _ci->flags; c->cflags = _ci->cflags; c->methods = _ci->methods; c->last_modified = _ci->last_modified; return c; error: LM_ERR("no more shm memory\n"); if (c->path.s) shm_free(c->path.s); if (c->received.s) shm_free(c->received.s); if (c->user_agent.s) shm_free(c->user_agent.s); if (c->callid.s) shm_free(c->callid.s); if (c->c.s) shm_free(c->c.s); if (c->domain.s) shm_free(c->domain.s); if (c->aor.s) shm_free(c->aor.s); shm_free(c); return 0; }