/** * Forwards the message to the application server. * - Marks the message * - fills routes * - replaces dst_uri * @param msg - the SIP message * @param m - the isc_match that matched with info about where to forward it * @param mark - the isc_mark that should be used to mark the message * @returns #ISC_RETURN_TRUE if OK, #ISC_RETURN_ERROR if not */ int isc_forward(struct sip_msg *msg, isc_match *m, isc_mark *mark) { struct cell *t; unsigned int hash, label; ticks_t fr_timeout, fr_inv_timeout; LM_DBG("marking for AS <%.*s>\n", m->server_name.len, m->server_name.s); isc_mark_set(msg, m, mark); /* change destination so it forwards to the app server */ if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri.s = pkg_malloc(m->server_name.len); if (!msg->dst_uri.s) { LM_ERR("error allocating %d bytes\n", m->server_name.len); return ISC_RETURN_ERROR; } msg->dst_uri.len = m->server_name.len; memcpy(msg->dst_uri.s, m->server_name.s, m->server_name.len); /* append branch if last trigger failed */ if (is_route_type(FAILURE_ROUTE)) append_branch(msg, &(msg->first_line.u.request.uri), &(msg->dst_uri), 0, Q_UNSPECIFIED, 0, 0, 0, 0, 0, 0); // Determines the tm transaction identifiers. // If no transaction, then creates one if (isc_tmb.t_get_trans_ident(msg, &hash, &label) < 0) { LM_DBG("SIP message without transaction. OK - first request\n"); if (isc_tmb.t_newtran(msg) < 0) LM_INFO("Failed creating SIP transaction\n"); if (isc_tmb.t_get_trans_ident(msg, &hash, &label) < 0) { LM_INFO("SIP message still without transaction\n"); } else { LM_DBG("New SIP message transaction %u %u\n", hash, label); } } else { LM_INFO("Transaction %u %u exists. Retransmission?\n", hash, label); } /* set the timeout timers to a lower value */ t = isc_tmb.t_gett(); fr_timeout = t->fr_timeout; fr_inv_timeout = t->fr_inv_timeout; t->fr_timeout = S_TO_TICKS(isc_fr_timeout) / 1000; t->fr_inv_timeout = S_TO_TICKS(isc_fr_inv_timeout) / 1000; /* send it */ isc_tmb.t_relay(msg, 0, 0); /* recover the timeouts */ t->fr_timeout = fr_timeout; t->fr_inv_timeout = fr_inv_timeout; LM_INFO(">> msg was fwded to AS\n"); return ISC_RETURN_TRUE; }
static int blst_add_f(struct sip_msg* msg, char* to, char* foo) { #ifdef USE_DST_BLACKLIST int t; struct dest_info src; if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){ t=0; if (unlikely( to && (get_int_fparam(&t, msg, (fparam_t*)to)<0))) return -1; if (t==0) t=cfg_get(core, core_cfg, blst_timeout); init_dest_info(&src); src.send_sock=0; src.to=msg->rcv.src_su; src.id=msg->rcv.proto_reserved1; src.proto=msg->rcv.proto; dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg, S_TO_TICKS(t)); return 1; }else{ LOG(L_WARN, "WARNING: blst: blst_add: blacklist support disabled\n"); } #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_add: blacklist support not compiled-in" " - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
/** * Forwards the message to the application server. * - Marks the message * - fills routes * - replaces dst_uri * @param msg - the SIP message * @param m - the isc_match that matched with info about where to forward it * @param mark - the isc_mark that should be used to mark the message * @returns #ISC_RETURN_TRUE if OK, #ISC_RETURN_ERROR if not */ int isc_forward( struct sip_msg *msg, isc_match *m,isc_mark *mark) { struct cell *t; unsigned int hash,label; ticks_t fr_timeout,fr_inv_timeout; DBG( "DEBUG:"M_NAME":isc_forward(): marking for AS <%.*s>\n", m->server_name.len, m->server_name.s ); isc_mark_set(msg,m,mark); /* change destination so it forwards to the app server */ if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri.s = pkg_malloc(m->server_name.len); if (!msg->dst_uri.s) { LOG(L_ERR,"ERR:"M_NAME":isc_forward(): error allocating %d bytes\n",m->server_name.len); return ISC_RETURN_ERROR; } msg->dst_uri.len = m->server_name.len; memcpy(msg->dst_uri.s,m->server_name.s,m->server_name.len); /* append branch if last trigger failed */ if (*isc_tmb.route_mode == MODE_ONFAILURE) append_branch(msg,msg->first_line.u.request.uri.s,msg->first_line.u.request.uri.len, msg->dst_uri.s,msg->dst_uri.len,0,0); /* set the timeout timers to a lower value */ cscf_get_transaction(msg,&hash,&label); t = isc_tmb.t_gett(); fr_timeout = t->fr_timeout; fr_inv_timeout = t->fr_inv_timeout; t->fr_timeout=S_TO_TICKS(isc_fr_timeout)/1000; t->fr_inv_timeout=S_TO_TICKS(isc_fr_inv_timeout)/1000; /* send it */ isc_tmb.t_relay(msg,0,0); /* recover the timeouts */ t->fr_timeout=fr_timeout; t->fr_inv_timeout=fr_inv_timeout; LOG(L_INFO,"INFO:"M_NAME">> msg was fwded to AS\n"); // LOG(L_INFO,"INFO:"M_NAME":isc_forward: fw relayed with marking [%8X]\n",rc->mark.cnt); // DBG( "DEBUG:"M_NAME":isc_forward: Forward sending finished, resuming operation\n" ); return ISC_RETURN_TRUE; }
static int fix_con_lt(void* cfg_h, str* gname, str* name, void** val) { int v; v=S_TO_TICKS((int)(long)*val); fix_timeout("tls.connection_timeout", &v, MAX_TLS_CON_LIFETIME, MAX_TLS_CON_LIFETIME); *val=(void*)(long)v; return 0; }
static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg) { struct sip_msg *shm_msg; unsigned int timeout; /* avp timeout gets stored here (in s) */ shm_msg=new_cell->uas.request; new_cell->from.s=shm_msg->from->name.s; new_cell->from.len=HF_LEN(shm_msg->from); new_cell->to.s=shm_msg->to->name.s; new_cell->to.len=HF_LEN(shm_msg->to); new_cell->callid.s=shm_msg->callid->name.s; new_cell->callid.len=HF_LEN(shm_msg->callid); new_cell->cseq_n.s=shm_msg->cseq->name.s; new_cell->cseq_n.len=get_cseq(shm_msg)->number.s +get_cseq(shm_msg)->number.len -shm_msg->cseq->name.s; new_cell->method=new_cell->uas.request->first_line.u.request.method; if (p_msg->REQ_METHOD==METHOD_INVITE) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->on_negative=get_on_negative(); new_cell->on_reply=get_on_reply(); new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout, p_msg->id, int); new_cell->fr_inv_timeout=(ticks_t)get_msgid_val(user_fr_inv_timeout, p_msg->id, int); if (new_cell->fr_timeout==0){ if (!fr_avp2timer(&timeout)) { DBG("init_new_t: FR__TIMER = %d s\n", timeout); new_cell->fr_timeout=S_TO_TICKS((ticks_t)timeout); }else{ new_cell->fr_timeout=fr_timeout; } } if (new_cell->fr_inv_timeout==0){ if (!fr_inv_avp2timer(&timeout)) { DBG("init_new_t: FR_INV_TIMER = %d s\n", timeout); new_cell->fr_inv_timeout=S_TO_TICKS((ticks_t)timeout); new_cell->flags |= T_NOISY_CTIMER_FLAG; }else{ new_cell->fr_inv_timeout=fr_inv_timeout; } } new_cell->on_branch=get_on_branch(); }
/* Adds a new entry to the blacklist */ void dst_blst_add(rpc_t* rpc, void* ctx) { str ip; int port, proto, flags; unsigned char err_flags; struct ip_addr *ip_addr; if (!cfg_get(core, core_cfg, use_dst_blacklist)){ rpc->fault(ctx, 500, "dst blacklist support disabled"); return; } if (rpc->scan(ctx, "Sddd", &ip, &port, &proto, &flags) < 4) return; err_flags = (unsigned char)flags; /* sanity checks */ if ((unsigned char)proto > PROTO_SCTP) { rpc->fault(ctx, 400, "Unknown protocol"); return; } if (err_flags & BLST_IS_IPV6) { #ifdef USE_IPV6 /* IPv6 address is specified */ ip_addr = str2ip6(&ip); #else /* USE_IPV6 */ rpc->fault(ctx, 400, "IPv6 support disabled"); return; #endif /* USE_IPV6 */ } else { /* try IPv4 first, than IPv6 */ ip_addr = str2ip(&ip); if (!ip_addr) { #ifdef USE_IPV6 ip_addr = str2ip6(&ip); err_flags |= BLST_IS_IPV6; #else /* USE_IPV6 */ rpc->fault(ctx, 400, "Malformed or IPv6 ip address"); return; #endif /* USE_IPV6 */ } } if (!ip_addr) { rpc->fault(ctx, 400, "Malformed ip address"); return; } if (dst_blacklist_add_ip(err_flags, proto, ip_addr, port, S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout)))) rpc->fault(ctx, 400, "Failed to add the entry to the blacklist"); }
/* returns error if no retry_after hdr field is present */ static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max) { #ifdef USE_DST_BLACKLIST int t_min, t_max, t; struct dest_info src; struct hdr_field* hf; if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){ if (unlikely(get_int_fparam(&t_min, msg, (fparam_t*)min)<0)) return -1; if (likely(max)){ if (unlikely(get_int_fparam(&t_max, msg, (fparam_t*)max)<0)) return -1; }else{ t_max=0; } init_dest_info(&src); src.send_sock=0; src.to=msg->rcv.src_su; src.id=msg->rcv.proto_reserved1; src.proto=msg->rcv.proto; t=-1; if ((parse_headers(msg, HDR_RETRY_AFTER_F, 0)==0) && (msg->parsed_flag & HDR_RETRY_AFTER_F)){ for (hf=msg->headers; hf; hf=hf->next) if (hf->type==HDR_RETRY_AFTER_T){ /* found */ t=(unsigned)(unsigned long)hf->parsed; break; } } if (t<0) return -1; t=MAX_unsigned(t, t_min); t=MIN_unsigned(t, t_max); if (likely(t)) dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg, S_TO_TICKS(t)); return 1; }else{ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support disabled\n"); } #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support not compiled-in - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) { if (unlikely(con == NULL)) { LM_CRIT("BUG: con == NULL"); return -1; } if (unlikely(time < 0)) { LM_ERR("Invalid timeout value, %d, must be >= 0\n", time); return -1; } con->lifetime = S_TO_TICKS(time); con->timeout = get_ticks_raw() + con->lifetime; LM_DBG("new connection lifetime for conid=%d: %d\n", con->id, con->timeout); return 1; }
/** fix the tls cfg, prior to registering. * @return < 0 on error, 0 on success */ int fix_tls_cfg(struct cfg_group_tls* cfg) { cfg->con_lifetime = S_TO_TICKS(cfg->con_lifetime); fix_timeout("tls_connection_timeout", &cfg->con_lifetime, MAX_TLS_CON_LIFETIME, MAX_TLS_CON_LIFETIME); /* Update relative paths of files configured through modparams, relative * pathnames will be converted to absolute and the directory of the main * SER configuration file will be used as reference. */ if (fix_initial_pathname(&cfg->config_file, 0) < 0) return -1; if (fix_initial_pathname(&cfg->private_key, TLS_PKEY_FILE) < 0) return -1; if (fix_initial_pathname(&cfg->ca_list, TLS_CA_FILE) < 0 ) return -1; if (fix_initial_pathname(&cfg->crl, TLS_CRL_FILE) < 0 ) return -1; if (fix_initial_pathname(&cfg->certificate, TLS_CERT_FILE) < 0) return -1; return 0; }
/* register a periodic timer; * compatibility mode.w/ the old timer interface... * ret: <0 on error * Hint: if you need it in a module, register it from mod_init or it * won't work otherwise*/ int register_timer(timer_function f, void* param, unsigned int interval) { struct sr_timer* t; t=shm_malloc(sizeof(struct sr_timer)); if (t==0){ SHM_MEM_ERROR; goto error; } t->id=timer_id++; t->timer_f=f; t->t_param=param; timer_init(&t->tl, compat_old_handler, t, 0); /* is slow */ if (timer_add(&t->tl, S_TO_TICKS(interval))!=0){ LM_ERR("timer_add failed\n"); return -1; } return t->id; error: return E_OUT_OF_MEM; }
static int mod_init(void) { int method; if (tls_disable){ LOG(L_WARN, "WARNING: tls: mod_init: tls support is disabled " "(set enable_tls=1 in the config to enable it)\n"); return 0; } if (cfg_get(tcp, tcp_cfg, async) && !tls_force_run){ ERR("tls does not support tcp in async mode, please use" " tcp_async=no in the config file\n"); return -1; } /* Convert tls_method parameter to integer */ method = tls_parse_method(&tls_method); if (method < 0) { ERR("Invalid tls_method parameter value\n"); return -1; } mod_params.method = method; /* Update relative paths of files configured through modparams, relative * pathnames will be converted to absolute and the directory of the main * SER configuration file will be used as reference. */ if (fix_rel_pathnames() < 0) return -1; tls_cfg = (tls_cfg_t**)shm_malloc(sizeof(tls_cfg_t*)); if (!tls_cfg) { ERR("Not enough shared memory left\n"); return -1; } *tls_cfg = NULL; register_tls_hooks(&tls_h); register_select_table(tls_sel); /* if (init_tls() < 0) return -1; */ tls_cfg_lock = lock_alloc(); if (tls_cfg_lock == 0) { ERR("Unable to create TLS configuration lock\n"); return -1; } if (lock_init(tls_cfg_lock) == 0) { lock_dealloc(tls_cfg_lock); ERR("Unable to initialize TLS configuration lock\n"); return -1; } if (tls_cfg_file.s) { *tls_cfg = tls_load_config(&tls_cfg_file); if (!(*tls_cfg)) return -1; } else { *tls_cfg = tls_new_cfg(); if (!(*tls_cfg)) return -1; } if (tls_check_sockets(*tls_cfg) < 0) return -1; /* fix the timeouts from s to ticks */ if (tls_con_lifetime<0){ /* set to max value (~ 1/2 MAX_INT) */ tls_con_lifetime=MAX_TLS_CON_LIFETIME; }else{ if ((unsigned)tls_con_lifetime > (unsigned)TICKS_TO_S(MAX_TLS_CON_LIFETIME)){ LOG(L_WARN, "tls: mod_init: tls_con_lifetime too big (%u s), " " the maximum value is %u\n", tls_con_lifetime, TICKS_TO_S(MAX_TLS_CON_LIFETIME)); tls_con_lifetime=MAX_TLS_CON_LIFETIME; }else{ tls_con_lifetime=S_TO_TICKS(tls_con_lifetime); } } return 0; }
int init_dst_blacklist() { int ret; #ifdef BLST_LOCK_PER_BUCKET int r; #endif if (dst_blacklist_init==0) { /* the dst blacklist is turned off */ default_core_cfg.use_dst_blacklist=0; return 0; } ret=-1; #ifdef DST_BLACKLIST_HOOKS if (init_blacklist_hooks()!=0){ ret=E_OUT_OF_MEM; goto error; } #endif blst_mem_used=shm_malloc(sizeof(*blst_mem_used)); if (blst_mem_used==0){ ret=E_OUT_OF_MEM; goto error; } *blst_mem_used=0; dst_blst_hash=shm_malloc(sizeof(struct dst_blst_lst_head) * DST_BLST_HASH_SIZE); if (dst_blst_hash==0){ ret=E_OUT_OF_MEM; goto error; } memset(dst_blst_hash, 0, sizeof(struct dst_blst_lst_head) * DST_BLST_HASH_SIZE); #ifdef BLST_LOCK_PER_BUCKET for (r=0; r<DST_BLST_HASH_SIZE; r++){ if (lock_init(&dst_blst_hash[r].lock)==0){ ret=-1; goto error; } } #elif defined BLST_LOCK_SET blst_lock_set=lock_set_alloc(DST_BLST_HASH_SIZE); if (blst_lock_set==0){ ret=E_OUT_OF_MEM; goto error; } if (lock_set_init(blst_lock_set)==0){ lock_set_dealloc(blst_lock_set); blst_lock_set=0; ret=-1; goto error; } #else /* BLST_ONE_LOCK */ blst_lock=lock_alloc(); if (blst_lock==0){ ret=E_OUT_OF_MEM; goto error; } if (lock_init(blst_lock)==0){ lock_dealloc(blst_lock); blst_lock=0; ret=-1; goto error; } #endif /* BLST*LOCK*/ blst_timer_h=timer_alloc(); if (blst_timer_h==0){ ret=E_OUT_OF_MEM; goto error; } /* fix options */ default_core_cfg.blst_max_mem<<=10; /* in Kb */ /* TODO: test with 0 */ if (blst_timer_interval){ timer_init(blst_timer_h, blst_timer, 0 ,0); /* slow timer */ if (timer_add(blst_timer_h, S_TO_TICKS(blst_timer_interval))<0){ LOG(L_CRIT, "BUG: init_dst_blacklist: failed to add the timer\n"); timer_free(blst_timer_h); blst_timer_h=0; goto error; } } return 0; error: destroy_dst_blacklist(); return ret; }
/* handle io routine, based on the fd_map type * (it will be called from io_wait_loop* ) * params: fm - pointer to a fd hash entry * idx - index in the fd_array (or -1 if not known) * return: -1 on error, or when we are not interested any more on reads * from this fd (e.g.: we are closing it ) * 0 on EAGAIN or when by some other way it is known that no more * io events are queued on the fd (the receive buffer is empty). * Usefull to detect when there are no more io events queued for * sigio_rt, epoll_et, kqueue. * >0 on successfull read from the fd (when there might be more io * queued -- the receive buffer might still be non-empty) */ inline static int handle_io(struct fd_map* fm, short events, int idx) { int ret; int n; int read_flags; struct tcp_connection* con; int s; long resp; ticks_t t; /* update the local config */ cfg_update(); switch(fm->type){ case F_TCPMAIN: again: ret=n=receive_fd(fm->fd, &con, sizeof(con), &s, 0); LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s); if (unlikely(n<0)){ if (errno == EWOULDBLOCK || errno == EAGAIN){ ret=0; break; }else if (errno == EINTR) goto again; else{ LM_CRIT("read_fd: %s \n", strerror(errno)); abort(); /* big error*/ } } if (unlikely(n==0)){ LM_ERR("0 bytes read\n"); goto error; } if (unlikely(con==0)){ LM_CRIT("null pointer\n"); goto error; } con->fd=s; if (unlikely(s==-1)) { LM_ERR("read_fd: no fd read\n"); goto con_error; } con->reader_pid=my_pid(); if (unlikely(con==tcp_conn_lst)){ LM_CRIT("duplicate connection received: %p, id %d, fd %d, refcnt %d" " state %d (n=%d)\n", con, con->id, con->fd, atomic_get(&con->refcnt), con->state, n); goto con_error; break; /* try to recover */ } if (unlikely(con->state==S_CONN_BAD)){ LM_WARN("received an already bad connection: %p id %d refcnt %d\n", con, con->id, atomic_get(&con->refcnt)); goto con_error; } /* if we received the fd there is most likely data waiting to * be read => process it first to avoid extra sys calls */ read_flags=((con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)) && !(con->flags & F_CONN_OOB_DATA))? RD_CONN_FORCE_EOF :0; #ifdef USE_TLS repeat_1st_read: #endif /* USE_TLS */ resp=tcp_read_req(con, &n, &read_flags); if (unlikely(resp<0)){ /* some error occured, but on the new fd, not on the tcp * main fd, so keep the ret value */ if (unlikely(resp!=CONN_EOF)) con->state=S_CONN_BAD; LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); release_tcpconn(con, resp, tcpmain_sock); break; } #ifdef USE_TLS /* repeat read if requested (for now only tls might do this) */ if (unlikely(read_flags & RD_CONN_REPEAT_READ)) goto repeat_1st_read; #endif /* USE_TLS */ /* must be before io_watch_add, io_watch_add might catch some * already existing events => might call handle_io and * handle_io might decide to del. the new connection => * must be in the list */ tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev); t=get_ticks_raw(); con->timeout=t+S_TO_TICKS(TCP_CHILD_TIMEOUT); /* re-activate the timer */ con->timer.f=tcpconn_read_timeout; local_timer_reinit(&con->timer); local_timer_add(&tcp_reader_ltimer, &con->timer, S_TO_TICKS(TCP_CHILD_TIMEOUT), t); if (unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con)<0)){ LM_CRIT("io_watch_add failed for %p id %d fd %d, state %d, flags %x," " main fd %d, refcnt %d\n", con, con->id, con->fd, con->state, con->flags, con->s, atomic_get(&con->refcnt)); tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); local_timer_del(&tcp_reader_ltimer, &con->timer); goto con_error; } break; case F_TCPCONN: con=(struct tcp_connection*)fm->data; if (unlikely(con->state==S_CONN_BAD)){ resp=CONN_ERROR; if (!(con->send_flags.f & SND_F_CON_CLOSE)) LM_WARN("F_TCPCONN connection marked as bad: %p id %d refcnt %d\n", con, con->id, atomic_get(&con->refcnt)); goto read_error; } read_flags=(( #ifdef POLLRDHUP (events & POLLRDHUP) | #endif /* POLLRDHUP */ (events & (POLLHUP|POLLERR)) | (con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF))) && !(events & POLLPRI))? RD_CONN_FORCE_EOF: 0; #ifdef USE_TLS repeat_read: #endif /* USE_TLS */ resp=tcp_read_req(con, &ret, &read_flags); if (unlikely(resp<0)){ read_error: ret=-1; /* some error occured */ if (unlikely(io_watch_del(&io_w, con->fd, idx, IO_FD_CLOSING) < 0)){ LM_CRIT("io_watch_del failed for %p id %d fd %d," " state %d, flags %x, main fd %d, refcnt %d\n", con, con->id, con->fd, con->state, con->flags, con->s, atomic_get(&con->refcnt)); } tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); local_timer_del(&tcp_reader_ltimer, &con->timer); if (unlikely(resp!=CONN_EOF)) con->state=S_CONN_BAD; LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); release_tcpconn(con, resp, tcpmain_sock); }else{ #ifdef USE_TLS if (unlikely(read_flags & RD_CONN_REPEAT_READ)) goto repeat_read; #endif /* USE_TLS */ /* update timeout */ con->timeout=get_ticks_raw()+S_TO_TICKS(TCP_CHILD_TIMEOUT); /* ret= 0 (read the whole socket buffer) if short read & * !POLLPRI, bytes read otherwise */ ret&=(((read_flags & RD_CONN_SHORT_READ) && !(events & POLLPRI)) - 1); } break; case F_NONE: LM_CRIT("empty fd map %p (%d): {%d, %d, %p}\n", fm, (int)(fm-io_w.fd_hash), fm->fd, fm->type, fm->data); goto error; default: LM_CRIT("uknown fd type %d\n", fm->type); goto error; } return ret; con_error: con->state=S_CONN_BAD; LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); release_tcpconn(con, CONN_ERROR, tcpmain_sock); return ret; error: return -1; }
int rls_mod_init(void) { load_tm_f load_tm; bind_dlg_mod_f bind_dlg; struct timer_ln *i_timer = NULL; DEBUG_LOG("RLS module initialization\n"); /* ??? if other module uses this libraries it might be a problem ??? */ xmlInitParser(); DEBUG_LOG(" ... common libraries\n"); qsa_initialize(); if (time_event_management_init() != 0) { LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n"); return -1; } if (subscription_management_init() != 0) { LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n"); return -1; } /* import the TM auto-loading function */ if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) { LOG(L_ERR, "rls_mod_init(): Can't import tm!\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm(&tmb)==-1) { LOG(L_ERR, "rls_mod_init(): load_tm() failed\n"); return -1; } bind_dlg = (bind_dlg_mod_f)find_export("bind_dlg_mod", -1, 0); if (!bind_dlg) { LOG(L_ERR, "Can't import dlg\n"); return -1; } if (bind_dlg(&dlg_func) != 0) { return -1; } if (rls_init() != 0) { return -1; } if (vs_init() != 0) { return -1; } /* xcap_servers = (ptr_vector_t*)mem_alloc(sizeof(ptr_vector_t)); if (!xcap_servers) { LOG(L_ERR, "rls_mod_init(): can't allocate memory for XCAP servers vector\n"); return -1; } ptr_vector_init(xcap_servers, 8); */ /* set authorization type according to requested "auth type name" * and other (type specific) parameters */ if (set_auth_params(&rls_auth_params, auth_type_str) != 0) return -1; use_db = 0; if (db_mode > 0) { int db_url_len = db_url ? strlen(db_url) : 0; if (!db_url_len) { LOG(L_ERR, "rls_mod_init(): no db_url specified but db_mode > 0\n"); db_mode = 0; } } if (db_mode > 0) { if (bind_dbmod(db_url, &rls_dbf) < 0) { LOG(L_ERR, "rls_mod_init(): Can't bind database module via url %s\n", db_url); return -1; } if (!DB_CAPABILITY(rls_dbf, DB_CAP_ALL)) { /* ? */ LOG(L_ERR, "rls_mod_init(): Database module does not implement all functions needed by the module\n"); return -1; } use_db = 1; } /* once-shot timer for reloading data from DB - * needed because it can trigger database operations * in other modules and they mostly intialize their * database connection in child_init functions */ i_timer = timer_alloc(); if (!i_timer) { ERR("can't allocate memory for DB init timer\n"); return -1; } else { timer_init(i_timer, init_timer_cb, i_timer, 0); timer_add(i_timer, S_TO_TICKS(init_timer_delay)); } fill_xcap_params = (fill_xcap_params_func)find_export("fill_xcap_params", 0, -1); return 0; }