/* * destroy function */ static void destroy(void) { LM_NOTICE("destroy module ...\n"); close(sockets.unix_sock); close(sockets.udp_sock); }
/*! \brief * Init module function */ static int mod_init(void) { if(register_mi_mod(exports.name, mi_cmds)!=0) { LM_ERR("failed to register MI commands\n"); return -1; } /* Group matching feature */ if (file == NULL) { LM_NOTICE("'file' parameter is not set, group matching disabled\n"); } else { /* Create and init the lock */ reload_lock = lock_alloc(); if (reload_lock == NULL) { LM_ERR("cannot allocate reload_lock\n"); goto err; } if (lock_init(reload_lock) == NULL) { LM_ERR("cannot init the reload_lock\n"); lock_dealloc(reload_lock); goto err; } /* PCRE options */ if (pcre_caseless != 0) { LM_DBG("PCRE CASELESS enabled\n"); pcre_options = pcre_options | PCRE_CASELESS; } if (pcre_multiline != 0) { LM_DBG("PCRE MULTILINE enabled\n"); pcre_options = pcre_options | PCRE_MULTILINE; } if (pcre_dotall != 0) { LM_DBG("PCRE DOTALL enabled\n"); pcre_options = pcre_options | PCRE_DOTALL; } if (pcre_extended != 0) { LM_DBG("PCRE EXTENDED enabled\n"); pcre_options = pcre_options | PCRE_EXTENDED; } LM_DBG("PCRE options: %i\n", pcre_options); /* Pointer to pcres */ if ((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { LM_ERR("no memory for pcres_addr\n"); goto err; } /* Integer containing the number of pcres */ if ((num_pcres = shm_malloc(sizeof(int))) == 0) { LM_ERR("no memory for num_pcres\n"); goto err; } /* Load the pcres */ LM_DBG("loading pcres...\n"); if (load_pcres(START)) { LM_ERR("failed to load pcres\n"); goto err; } } return 0; err: free_shared_memory(); return -1; }
int is_other_contact_f(struct sip_msg* msg, char* _d, char *_s) { pv_spec_p spec = (pv_spec_p)_s; struct usr_avp *avp = NULL; urecord_t *r = NULL; str ip, contact; str uri, aor; ucontact_t *c; contact_t* ct; int exp, found; udomain_t* ud = (udomain_t*)_d; if (parse_message(msg) < 0) { LM_ERR("unable to parse message\n"); return -2; } if (!ud) { LM_ERR("no location specified\n"); return -2; } /* msg doesn't have contacts */ if (!msg->contact || !(ct = (((contact_body_t*)msg->contact->parsed)->contacts))) return -1; while (ct) { /* if expires is 0 */ calc_contact_expires(msg, ct->expires, &exp, NULL); if (exp) break; ct = ct->next; } if (!ct) { LM_DBG("contact has expire 0\n"); return -1; } uri = get_to(msg)->uri; if (extract_aor(&uri, &aor,0,0) < 0) { LM_ERR("failed to extract AOR record\n"); return -2; } ul.lock_udomain(ud, &aor); ul.get_urecord(ud, &aor, &r); if (!r) { /* dont't test anything */ LM_DBG("no contact found for aor=<%.*s>\n", aor.len, aor.s); found = -1; goto end; } else { c = r->contacts; } while (c) { if (!c->received.len || !c->received.s || c->received.len < 4 /* sip:*/) { c = c->next; continue; } contact.s = c->received.s + 4; /* check for "sips:" */ if (*contact.s == ':') { contact.len = c->received.len - 5; contact.s++; } else { /* skip "sip:" */ contact.len = c->received.len - 4; } avp = NULL; found = 0; /* the ip should always be a string */ while ((avp = search_first_avp(spec->pvp.pvn.u.isname.type, spec->pvp.pvn.u.isname.name.n, (int_str *)&ip, avp))!=0) { if (!(avp->flags & AVP_VAL_STR)) { LM_NOTICE("avp value should be string\n"); continue; } if ((contact.len == ip.len || (contact.len>ip.len && contact.s[ip.len]==':')) && !memcmp(contact.s, ip.s, ip.len)) { found = 1; break; } } if (!found) { LM_DBG("no contact <%.*s> registered earlier\n", contact.len, contact.s); found = 1; goto end; } c = c->next; } found = -1; end: ul.unlock_udomain(ud, &aor); return found; }
/** * Main routine, start of the program execution. * \param argc the number of arguments * \param argv pointer to the arguments array * \return don't return on sucess, -1 on error * \see main_loop */ int main(int argc, char** argv) { /* configure by default logging to syslog */ int cfg_log_stderr = 0; FILE* cfg_stream; int c,r; char *tmp; int tmp_len; int port; int proto; char *options; int ret; unsigned int seed; int rfd; /*init*/ ret=-1; my_argc=argc; my_argv=argv; /* process pkg mem size from command line */ opterr=0; options="f:cCm:M:b:l:n:N:rRvdDETSVhw:t:u:g:P:G:W:o:"; while((c=getopt(argc,argv,options))!=-1){ switch(c){ case 'M': pkg_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024; if (tmp &&(*tmp)){ LM_ERR("bad pkgmem size number: -m %s\n", optarg); goto error00; }; break; } } /*init pkg mallocs (before parsing cfg but after parsing cmd line !)*/ if (init_pkg_mallocs()==-1) goto error00; init_route_lists(); /* process command line (get port no, cfg. file path etc) */ /* first reset getopt */ optind = 1; while((c=getopt(argc,argv,options))!=-1){ switch(c){ case 'f': cfg_file=optarg; break; case 'C': config_check |= 2; case 'c': if (config_check==3) break; config_check |= 1; cfg_log_stderr=1; /* force stderr logging */ break; case 'm': shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024; if (tmp &&(*tmp)){ LM_ERR("bad shmem size number: -m %s\n", optarg); goto error00; }; break; case 'M': /* ignoring it, parsed previously */ break; case 'b': maxbuffer=strtol(optarg, &tmp, 10); if (tmp &&(*tmp)){ LM_ERR("bad max buffer size number: -b %s\n", optarg); goto error00; } break; case 'l': if (parse_phostport(optarg, strlen(optarg), &tmp, &tmp_len, &port, &proto)<0){ LM_ERR("bad -l address specifier: %s\n", optarg); goto error00; } tmp[tmp_len]=0; /* null terminate the host */ /* add a new addr. to our address list */ if (add_listen_iface(tmp, port, proto, 0, 0, 0,0 )!=0){ LM_ERR("failed to add new listen address\n"); goto error00; } break; case 'n': children_no=strtol(optarg, &tmp, 10); if ((tmp==0) ||(*tmp)){ LM_ERR("bad process number: -n %s\n", optarg); goto error00; } break; case 'v': check_via=1; break; case 'r': received_dns|=DO_DNS; break; case 'R': received_dns|=DO_REV_DNS; case 'd': #ifdef CHANGEABLE_DEBUG_LEVEL (*debug)++; #else debug++; #endif break; case 'D': dont_fork=1; break; case 'E': cfg_log_stderr=1; break; case 'T': #ifdef USE_TCP tcp_disable=1; #else LM_WARN("tcp support not compiled in\n"); #endif break; case 'S': #ifdef USE_SCTP sctp_disable=1; #else LM_WARN("sctp support not compiled in\n"); #endif break; case 'N': #ifdef USE_TCP tcp_children_no=strtol(optarg, &tmp, 10); if ((tmp==0) ||(*tmp)){ LM_ERR("bad process number: -N %s\n", optarg); goto error00; } #else LM_WARN("tcp support not compiled in\n"); #endif break; case 'W': #ifdef USE_TCP tcp_poll_method=get_poll_type(optarg); if (tcp_poll_method==POLL_NONE){ LM_ERR("bad poll method name: -W %s\ntry " "one of %s.\n", optarg, poll_support); goto error00; } #else LM_WARN("tcp support not compiled in\n"); #endif break; case 'V': printf("version: %s\n", version); printf("flags: %s\n", flags ); print_ct_constants(); printf("%s\n",id); printf("%s compiled on %s with %s\n", __FILE__, compiled, COMPILER ); exit(0); break; case 'h': printf("version: %s\n", version); printf("%s",help_msg); exit(0); break; case 'w': working_dir=optarg; break; case 't': chroot_dir=optarg; break; case 'u': user=optarg; break; case 'g': group=optarg; break; case 'P': pid_file=optarg; break; case 'G': pgid_file=optarg; break; case 'o': if (add_arg_var(optarg) < 0) LM_ERR("cannot add option %s\n", optarg); break; case '?': if (isprint(optopt)) LM_ERR("Unknown option `-%c`.\n", optopt); else LM_ERR("Unknown option character `\\x%x`.\n", optopt); goto error00; case ':': LM_ERR("Option `-%c` requires an argument.\n", optopt); goto error00; default: abort(); } } log_stderr = cfg_log_stderr; /* fill missing arguments with the default values*/ if (cfg_file==0) cfg_file=CFG_FILE; /* load config file or die */ cfg_stream=fopen (cfg_file, "r"); if (cfg_stream==0){ LM_ERR("loading config file(%s): %s\n", cfg_file, strerror(errno)); goto error00; } /* seed the prng, try to use /dev/urandom if possible */ /* no debugging information is logged, because the standard log level prior the config file parsing is L_NOTICE */ seed=0; if ((rfd=open("/dev/urandom", O_RDONLY))!=-1){ try_again: if (read(rfd, (void*)&seed, sizeof(seed))==-1){ if (errno==EINTR) goto try_again; /* interrupted by signal */ LM_WARN("could not read from /dev/urandom (%d)\n", errno); } LM_DBG("initialize the pseudo random generator from " "/dev/urandom\n"); LM_DBG("read %u from /dev/urandom\n", seed); close(rfd); }else{ LM_WARN("could not open /dev/urandom (%d)\n", errno); LM_WARN("using a unsafe seed for the pseudo random number generator"); } seed+=getpid()+time(0); LM_DBG("seeding PRNG with %u\n", seed); srand(seed); LM_DBG("test random number %u\n", rand()); /*register builtin modules*/ register_builtin_modules(); #ifdef USE_TLS /* initialize default TLS domains, must be done before reading the config */ if (pre_init_tls()<0){ LM_CRIT("could not pre_init_tls, exiting...\n"); goto error00; } #endif /* USE_TLS */ if (preinit_black_lists()!=0) { LM_CRIT("failed to alloc black list's anchor\n"); goto error00; } /* init avps */ if (init_global_avps() != 0) { LM_ERR("error while initializing avps\n"); goto error; } /* parse the config file, prior to this only default values e.g. for debugging settings will be used */ yyin=cfg_stream; if ((yyparse()!=0)||(cfg_errors)){ LM_ERR("bad config file (%d errors)\n", cfg_errors); goto error00; } if (config_check>1 && check_rls()!=0) { LM_ERR("bad function call in config file\n"); return ret; } #ifdef EXTRA_DEBUG print_rl(); #endif /* init the resolver, before fixing the config */ resolv_init(); /* fix parameters */ if (port_no<=0) port_no=SIP_PORT; #ifdef USE_TLS if (tls_port_no<=0) tls_port_no=SIPS_PORT; #endif if (children_no<=0) children_no=CHILD_NO; #ifdef USE_TCP if (!tcp_disable){ if (tcp_children_no<=0) tcp_children_no=children_no; } #endif if (working_dir==0) working_dir="/"; /* get uid/gid */ if (user){ if (user2uid(&uid, &gid, user)<0){ LM_ERR("bad user name/uid number: -u %s\n", user); goto error00; } } if (group){ if (group2gid(&gid, group)<0){ LM_ERR("bad group name/gid number: -u %s\n", group); goto error00; } } if (fix_all_socket_lists()!=0){ LM_ERR("failed to initialize list addresses\n"); goto error00; } /* print all the listen addresses */ printf("Listening on \n"); print_all_socket_lists(); printf("Aliases: \n"); /*print_aliases();*/ print_aliases(); printf("\n"); if (dont_fork){ LM_WARN("no fork mode %s\n", (udp_listen)?( (udp_listen->next)?" and more than one listen address found" "(will use only the first one)":"" ):"and no udp listen address found" ); } if (config_check){ LM_NOTICE("config file ok, exiting...\n"); return 0; } time(&startup_time); /*init shm mallocs * this must be here * -to allow setting shm mem size from the command line * => if shm_mem should be settable from the cfg file move * everything after * -it must be also before init_timer and init_tcp * -it must be after we know uid (so that in the SYSV sems case, * the sems will have the correct euid) * --andrei */ if (init_shm_mallocs()==-1) goto error; /*init timer, before parsing the cfg!*/ if (init_timer()<0){ LM_CRIT("could not initialize timer, exiting...\n"); goto error; } #ifdef USE_TCP if (!tcp_disable){ /*init tcp*/ if (init_tcp()<0){ LM_CRIT("could not initialize tcp, exiting...\n"); goto error; } } #ifdef USE_TLS if (!tls_disable){ /* init tls*/ if (init_tls()<0){ LM_CRIT("could not initialize tls, exiting...\n"); goto error; } } #endif /* USE_TLS */ #endif /* USE_TCP */ /* init_daemon? */ if (!dont_fork){ if ( daemonize((log_name==0)?argv[0]:log_name, &own_pgid) <0 ) goto error; } /* install signal handlers */ if (install_sigs() != 0){ LM_ERR("could not install the signal handlers\n"); goto error; } #ifdef CHANGEABLE_DEBUG_LEVEL #ifdef SHM_MEM debug=shm_malloc(sizeof(int)); if (debug==0) { LM_ERR("ERROR: out of memory\n"); goto error; } *debug = debug_init; #else LM_WARN("no shm mem support compiled -> changeable debug " "level turned off\n"); #endif #endif if (disable_core_dump) set_core_dump(0, 0); else set_core_dump(1, shm_mem_size+pkg_mem_size+4*1024*1024); if (open_files_limit>0){ if(increase_open_fds(open_files_limit)<0){ LM_ERR("ERROR: error could not increase file limits\n"); goto error; } } /* print OpenSIPS version to log for history tracking */ LM_NOTICE("version: %s\n", version); /* print some data about the configuration */ #ifdef SHM_MEM LM_INFO("using %ld Mb shared memory\n", ((shm_mem_size/1024)/1024)); #endif LM_INFO("using %ld Mb private memory per process\n", ((pkg_mem_size/1024)/1024)); /* init serial forking engine */ if (init_serialization()!=0) { LM_ERR("failed to initialize serialization\n"); goto error; } /* Init statistics */ if (init_stats_collector()<0) { LM_ERR("failed to initialize statistics\n"); goto error; } /* Init MI */ if (init_mi_core()<0) { LM_ERR("failed to initialize MI core\n"); goto error; } /* Register core events */ if (evi_register_core() != 0) { LM_ERR("failed register core events\n"); goto error; } /* init black list engine */ if (init_black_lists()!=0) { LM_CRIT("failed to init black lists\n"); goto error; } /* init resolver's blacklist */ if (resolv_blacklist_init()!=0) { LM_CRIT("failed to create DNS blacklist\n"); goto error; } /* init modules */ if (init_modules() != 0) { LM_ERR("error while initializing modules\n"); goto error; } /* register route timers */ if(register_route_timers() < 0) { LM_ERR("Failed to register timer\n"); goto error; } /* check pv context list */ if(pv_contextlist_check() != 0) { LM_ERR("used pv context that was not defined\n"); goto error; } /* init query list now in shm * so all processes that will be forked from now on * will have access to it * * if it fails, give it a try and carry on */ if (init_ql_support() != 0) { LM_ERR("failed to initialise buffering query list\n"); query_buffer_size = 0; *query_list = NULL; } /* init multi processes support */ if (init_multi_proc_support()!=0) { LM_ERR("failed to init multi-proc support\n"); goto error; } #ifdef PKG_MALLOC /* init stats support for pkg mem */ if (init_pkg_stats(counted_processes)!=0) { LM_ERR("failed to init stats for pkg\n"); goto error; } #endif /* init avps */ if (init_extra_avps() != 0) { LM_ERR("error while initializing avps\n"); goto error; } /* fix routing lists */ if ( (r=fix_rls())!=0){ LM_ERR("failed to fix configuration with err code %d\n", r); goto error; }; ret=main_loop(); error: /*kill everything*/ kill_all_children(SIGTERM); /*clean-up*/ cleanup(0); error00: return ret; }
/* * destroy function */ static void destroy(void) { LM_NOTICE("destroy module cachedb_redis ...\n"); cachedb_end_connections(&cache_mod_name); return; }
int worker_reg_send_impl(ei_cnode *ec, int s,int wpid) { str server = STR_NULL; ei_x_buff emsg; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&emsg,0,sizeof(emsg)); memset((void*)&msgh,0,sizeof(msgh)); /* server name length */ cnt[0].iov_base = &server.len; cnt[0].iov_len = sizeof(int); /* Erlang args size */ cnt[1].iov_base = &emsg.buffsz; cnt[1].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 2; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); return -1; } /* allocate space */ server.s = (char*)pkg_malloc(server.len+1); if (!server.s) { LM_ERR("not enough memory\n"); goto err; } emsg.buff = (char*)malloc(emsg.buffsz); if (!emsg.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[2].iov_base = server.s; cnt[2].iov_len = server.len; cnt[3].iov_base = emsg.buff; cnt[3].iov_len = emsg.buffsz; /* get whole data */ msgh.msg_iovlen = 4; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ server.s[server.len] = 0; if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); goto err; } LM_DBG(">> {%.*s,'%s'} ! emsg\n",STR_FMT(&server),enode->conn.nodename); EI_X_BUFF_PRINT(&emsg); /* do ERL_REG_SEND */ if ((rc = ei_reg_send(ec,enode->sockfd,server.s,emsg.buff,emsg.buffsz)) == ERL_ERROR) { if (erl_errno) { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } pkg_free(server.s); free(emsg.buff); return 0; err: pkg_free(server.s); free(emsg.buff); return -1; }
void evapi_recv_client(struct ev_loop *loop, struct ev_io *watcher, int revents) { #define CLIENT_BUFFER_SIZE 4096 char rbuffer[CLIENT_BUFFER_SIZE]; ssize_t rlen; int i, k; evapi_env_t evenv; str frame; if(EV_ERROR & revents) { perror("received invalid event\n"); return; } /* read message from client */ rlen = recv(watcher->fd, rbuffer, CLIENT_BUFFER_SIZE-1, 0); if(rlen < 0) { LM_ERR("cannot read the client message\n"); return; } for(i=0; i<EVAPI_MAX_CLIENTS; i++) { if(_evapi_clients[i].connected==1 && _evapi_clients[i].sock==watcher->fd) { break; } } if(i==EVAPI_MAX_CLIENTS) { LM_ERR("cannot lookup client socket %d\n", watcher->fd); return; } evapi_env_reset(&evenv); if(rlen == 0) { /* client is gone */ evenv.eset = 1; evenv.conidx = i; evapi_run_cfg_route(&evenv, _evapi_rts.con_closed); _evapi_clients[i].connected = 0; _evapi_clients[i].sock = 0; ev_io_stop(loop, watcher); free(watcher); LM_INFO("client closing connection - pos [%d] addr [%s:%d]\n", i, _evapi_clients[i].src_addr, _evapi_clients[i].src_port); return; } rbuffer[rlen] = '\0'; LM_NOTICE("{%d} [%s:%d] - received [%.*s]\n", i, _evapi_clients[i].src_addr, _evapi_clients[i].src_port, (int)rlen, rbuffer); evenv.conidx = i; evenv.eset = 1; if(_evapi_netstring_format) { /* netstring decapsulation */ k = 0; while(k<rlen) { frame.len = 0; while(k<rlen) { if(rbuffer[k]==' ' || rbuffer[k]=='\t' || rbuffer[k]=='\r' || rbuffer[k]=='\n') k++; else break; } if(k==rlen) return; while(k<rlen) { if(rbuffer[k]>='0' && rbuffer[k]<='9') { frame.len = frame.len*10 + rbuffer[k] - '0'; } else { if(rbuffer[k]==':') break; /* invalid character - discard the rest */ return; } k++; } if(k==rlen || frame.len<=0) return; if(frame.len + k>=rlen) return; k++; frame.s = rbuffer + k; if(frame.s[frame.len]!=',') return; frame.s[frame.len] = '\0'; k += frame.len ; evenv.msg.s = frame.s; evenv.msg.len = frame.len; evapi_run_cfg_route(&evenv, _evapi_rts.msg_received); k++; } } else { evenv.msg.s = rbuffer; evenv.msg.len = rlen; evapi_run_cfg_route(&evenv, _evapi_rts.msg_received); } }
int pv_add_json ( pv_param_t* pvp, json_t * obj ) { json_t *dest; json_name * id; pv_json_t * var; json_tag * tag; int poz; id = (json_name *) pvp->pvn.u.dname; var = get_pv_json(pvp); if( var == NULL ) { if( id->tags ) { LM_ERR("Object is not initialized yet\n"); return -1; } var = (pv_json_t *) pkg_malloc(sizeof(pv_json_t)); if( var == NULL ) { LM_ERR("Out of memory\n"); return -1; } memset(var,0,sizeof(pv_json_t)); var->name = id->name; var->next = all; var->data = obj; all = var; return 0; } if( id ->tags == NULL) { if( var->data ) json_object_put(var->data); var->data = obj; return 0; } dest = get_object(var, pvp, &tag, 1); if( dest == NULL ) { LM_NOTICE("Could not find object with that path\n"); return -1; } if( tag->type & TAG_KEY ) { memcpy(buff,tag->key.s,tag->key.len); buff[tag->key.len] = 0; if( obj == NULL ) json_object_object_del(dest,buff); else json_object_object_add(dest,buff,obj); } if( tag->type & TAG_IDX ) { poz = tag->idx; if( tag->type & TAG_END ) { if( obj == NULL) { LM_ERR("Invalid parameter for deletion\n"); return -1; } json_object_array_add(dest,obj); return 0; } if( poz < 0 ) poz += json_object_array_length(dest); if( poz<0 || poz >= json_object_array_length(dest)) { LM_ERR("Attempting to replace at invalid index in array:%d\n", poz); return -1; } if( obj == NULL) { if( poz >= json_object_array_length(dest)) { LM_ERR("Index out of bounds for deletion\n"); return -1; } json_object_array_del(dest,poz); } else json_object_array_put_idx(dest,poz,obj); } return 0; }
/* it checks if a user is member of a group */ int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain, uri; dig_cred_t* cred = 0; int hf_type; struct hdr_field* h; struct sip_uri puri; AAAMessage *req; AAA_AVP *avp; int ret; unsigned int tmp; grp = (str*)_group; /* via fixup */ hf_type = (int)(long)_hf; uri.s = 0; uri.len = 0; /* extract the uri according with the _hf parameter */ switch(hf_type) { case 1: /* Request-URI */ uri = *(GET_RURI(_m)); break; case 2: /* To */ if (get_to_uri(_m, &uri) < 0) { LM_ERR("failed to extract To\n"); return -2; } break; case 3: /* From */ if (get_from_uri(_m, &uri) < 0) { LM_ERR("failed to extract From URI\n"); return -3; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LM_ERR("no authorized credentials found " "(error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return -5; } user = puri.user; domain = puri.host; } else { user = cred->username.user; domain = cred->realm; } /* user@domain mode */ if (use_domain) { user_name.s = 0; user_name.len = user.len + domain.len; if(user_name.len>0) { user_name.len++; user_name.s = (char*)pkg_malloc(user_name.len); if (!user_name.s) { LM_ERR("no pkg memory left\n"); return -6; } memcpy(user_name.s, user.s, user.len); if(user.len>0) { user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else memcpy(user_name.s, domain.s, domain.len); } } else user_name = user; if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("can't create new AAA message!\n"); return -1; } /* Username AVP */ if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Usergroup AVP */ if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s, grp->len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* SIP_MSGID AVP */ LM_DBG("******* m_id=%d\n", _m->id); tmp = _m->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(tmp), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* ServiceType AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Destination-Realm AVP */ uri = *(GET_RURI(_m)); parse_uri(uri.s, uri.len, &puri); if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed." "It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != AAA_USER_IN_GROUP) { LM_ERR("message sending to the DIAMETER backend authorization server" "failed or user is not in group\n"); goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }
static int mod_init(void) { JavaVMInitArgs vm_args; jint res; JavaVMOption *options; char **opts; int nOptions; if (force_cmd_exec < 0 || force_cmd_exec > 1) { LM_ERR("Parameter force_cmd_exec should be either 0 or 1\n"); return -1; } if (force_cmd_exec) { LM_NOTICE("%s: Parameter force_cmd_exec may cause a memory leaks if used from embedded languages\n", APP_NAME); } options = (JavaVMOption *)pkg_malloc(sizeof(JavaVMOption)); if (!options) { LM_ERR("pkg_malloc() failed: Couldn't initialize Java VM: Not enough memory\n"); return -1; } memset(options, 0, sizeof(JavaVMOption)); LM_INFO("Initializing Java VM with options: %s\n", java_options_str.s); opts = split(java_options_str.s, " "); for (nOptions=0; opts[nOptions] != NULL; nOptions++) { options[nOptions].optionString = opts[nOptions]; } /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */ vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = nOptions; vm_args.ignoreUnrecognized = JNI_FALSE; vm_args.options = options; res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args); if (res < 0) { handle_VM_init_failure(res); return -1; } LM_INFO("%s: Java VM initialization OK\n", APP_NAME); // attach to current thread (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); if ((*env)->ExceptionCheck(env)) { handle_exception(); return -1; } KamailioClass = (*env)->FindClass(env, class_name.s); if (!KamailioClass || (*env)->ExceptionCheck(env)) { handle_exception(); (*jvm)->DetachCurrentThread(jvm); return -1; } KamailioClassRef = (*env)->NewGlobalRef(env, KamailioClass); if (!KamailioClassRef || (*env)->ExceptionCheck(env)) { handle_exception(); (*jvm)->DetachCurrentThread(jvm); return -1; } KamailioID = (*env)->GetMethodID(env, KamailioClass, "<init>", "()V"); if (!KamailioID || (*env)->ExceptionCheck(env)) { handle_exception(); (*jvm)->DetachCurrentThread(jvm); return -1; } // calling constructor KamailioClassInstance = (*env)->NewObject(env, KamailioClass, KamailioID); if (!KamailioClassInstance || (*env)->ExceptionCheck(env)) { handle_exception(); (*jvm)->DetachCurrentThread(jvm); return -1; } // keep a reference to kamailio class instance KamailioClassInstanceRef = (*env)->NewGlobalRef(env, KamailioClassInstance); if (!KamailioClassInstanceRef || (*env)->ExceptionCheck(env)) { handle_exception(); (*jvm)->DetachCurrentThread(jvm); return -1; } LM_INFO("%s: module initialization OK\n", APP_NAME); if (jvm != NULL) (*jvm)->DetachCurrentThread(jvm); return 0; }
json_t * get_object(pv_json_t * var, pv_param_t* pvp , json_tag ** tag, int report_err ) { json_name * id = (json_name *) pvp->pvn.u.dname; json_t * cur_obj, * last_obj = 0; json_tag * cur_tag, * last_tag = 0; int poz; cur_tag = id->tags; cur_obj = var->data; while( cur_tag ) { last_tag = cur_tag; last_obj = cur_obj; if( cur_tag->type & TAG_KEY ) { memcpy( buff, cur_tag->key.s, cur_tag->key.len ); buff[cur_tag->key.len] = 0; if( cur_obj == NULL || !json_object_is_type( cur_obj, json_type_object ) ) goto error; #if JSON_LIB_VERSION < 10 cur_obj = json_object_object_get( cur_obj, buff ); if( cur_obj == NULL && tag == NULL) goto error; #else if (!json_object_object_get_ex( cur_obj,buff, &cur_obj ) && tag == NULL) goto error; #endif } if( cur_tag->type & TAG_IDX ) { if( cur_obj == NULL || !json_object_is_type( cur_obj, json_type_array ) ) goto error; poz = cur_tag->idx; if( cur_tag->type & TAG_END ) { poz = json_object_array_length(cur_obj); } else { if( poz < 0 ) poz += json_object_array_length(cur_obj); } if( poz < 0 ) goto error; cur_obj = json_object_array_get_idx( cur_obj, poz ); if( cur_obj == NULL && tag == NULL) goto error; } cur_tag = cur_tag->next; } if( tag == NULL ) { return cur_obj; } else { *tag = last_tag; return last_obj; } error: if( report_err) { LM_NOTICE("Trying to get a value from a json of incorrect type\n"); if(var->data) LM_NOTICE("Object is:\n%s\n", json_object_to_json_string(var->data)); else LM_NOTICE("Object is null\n"); print_tag_list( id->tags, cur_tag->next, 1); } return NULL; }
static int backup_config(void) { FILE * from, * to; char * backup_file, ch; LM_INFO("start configuration backup\n"); if((backup_file = pkg_malloc(strlen(config_file) + strlen (".bak") + 1)) == NULL){ PKG_MEM_ERROR; return -1; } if(!strcpy(backup_file, config_file)){ LM_ERR("can't copy filename\n"); goto errout; } if(!strcat(backup_file, ".bak")){ LM_ERR("can't attach suffix\n"); goto errout; } /* open source file */ if ((from = fopen(config_file, "rb"))==NULL) { LM_ERR("Cannot open source file.\n"); goto errout; } /* open destination file */ if ((to = fopen(backup_file, "wb"))==NULL) { LM_ERR("Cannot open destination file.\n"); fclose(from); goto errout; } /* copy the file */ while (!feof(from)) { ch = fgetc(from); if (ferror(from)) { LM_ERR("Error reading source file.\n"); goto errclose; } if (!feof(from)) fputc(ch, to); if (ferror(to)) { LM_ERR("Error writing destination file.\n"); goto errclose; } } if (fclose(from)==EOF) { LM_ERR("Error closing source file.\n"); fclose(to); goto errout; } if (fclose(to)==EOF) { LM_ERR("Error closing destination file.\n"); goto errout; } LM_NOTICE("backup written to %s\n", backup_file); pkg_free(backup_file); return 0; errclose: /* close the files so that resource leak is prevented ; ignore errors*/ fclose(from); fclose(to); errout: pkg_free(backup_file); 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; }
/** Receive message * WARNING: buf must be 0 terminated (buf[len]=0) or some things might * break (e.g.: modules/textops) */ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) { struct sip_msg* msg; struct run_act_ctx ctx; struct run_act_ctx *bctx; int ret; #ifdef STATS int skipped = 1; int stats_on = 1; #else int stats_on = 0; #endif struct timeval tvb, tve; struct timezone tz; unsigned int diff = 0; str inb; sr_net_info_t netinfo; sr_kemi_eng_t *keng = NULL; if(sr_event_enabled(SREV_NET_DATA_RECV)) { if(sip_check_fline(buf, len)==0) { memset(&netinfo, 0, sizeof(sr_net_info_t)); netinfo.data.s = buf; netinfo.data.len = len; netinfo.rcv = rcv_info; sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo); } } inb.s = buf; inb.len = len; sr_event_exec(SREV_NET_DATA_IN, (void*)&inb); len = inb.len; msg=pkg_malloc(sizeof(struct sip_msg)); if (msg==0) { LM_ERR("no mem for sip_msg\n"); goto error00; } msg_no++; /* number of vias parsed -- good for diagnostic info in replies */ via_cnt=0; memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */ /* fill in msg */ msg->buf=buf; msg->len=len; /* zero termination (termination of orig message bellow not that * useful as most of the work is done with scratch-pad; -jiri */ /* buf[len]=0; */ /* WARNING: zero term removed! */ msg->rcv=*rcv_info; msg->id=msg_no; msg->pid=my_pid(); msg->set_global_address=default_global_address; msg->set_global_port=default_global_port; if(likely(sr_msg_time==1)) msg_set_time(msg); if (parse_msg(buf,len, msg)!=0){ if((ret=sr_event_exec(SREV_RCV_NOSIP, (void*)msg))<NONSIP_MSG_DROP) { LOG(cfg_get(core, core_cfg, corelog), "core parsing of SIP message failed (%s:%d/%d)\n", ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port, (int)msg->rcv.proto); sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR); } else if(ret == NONSIP_MSG_DROP) goto error02; } parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F, 0); LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n", (msg->first_line.type==SIP_REQUEST)?"request":"reply", (msg->callid && msg->callid->body.s)?msg->callid->body.len:0, (msg->callid && msg->callid->body.s)?msg->callid->body.s:"", (msg->cseq && msg->cseq->body.s)?msg->cseq->body.len:0, (msg->cseq && msg->cseq->body.s)?msg->cseq->body.s:""); /* set log prefix */ log_prefix_set(msg); /* ... clear branches from previous message */ clear_branches(); if (msg->first_line.type==SIP_REQUEST){ ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */ if (!IS_SIP(msg)){ if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){ if (unlikely(ret==NONSIP_MSG_ERROR)) goto error03; goto end; /* drop the message */ } } /* sanity checks */ if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){ /* no via, send back error ? */ LM_ERR("no via found in request\n"); STATS_BAD_MSG(); goto error02; } /* check if necessary to add receive?->moved to forward_req */ /* check for the alias stuff */ #ifdef USE_TCP if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && (((rcv_info->proto==PROTO_TCP) && !tcp_disable) #ifdef USE_TLS || ((rcv_info->proto==PROTO_TLS) && !tls_disable) #endif ) ){ if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port, rcv_info->proto)!=0){ LM_ERR("tcp alias failed\n"); /* continue */ } } #endif /* skip: */ LM_DBG("preparing to run routing scripts...\n"); if(is_printable(cfg_get(core, core_cfg, latency_cfg_log)) || stats_on==1) { gettimeofday( & tvb, &tz ); } /* execute pre-script callbacks, if any; -jiri */ /* if some of the callbacks said not to continue with * script processing, don't do so * if we are here basic sanity checks are already done * (like presence of at least one via), so you can count * on via1 being parsed in a pre-script callback --andrei */ if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 ) { STATS_REQ_FWD_DROP(); goto end; /* drop the request */ } set_route_type(REQUEST_ROUTE); /* exec the routing script */ if(unlikely(main_rt.rlist[DEFAULT_RT]==NULL)) { keng = sr_kemi_eng_get(); if(keng==NULL) { LM_ERR("no config routing engine registered\n"); goto error_req; } if(keng->froute(msg, REQUEST_ROUTE, NULL, NULL)<0) { LM_NOTICE("negative return code from engine function\n"); } } else { if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){ LM_WARN("error while trying script\n"); goto error_req; } } if(is_printable(cfg_get(core, core_cfg, latency_cfg_log)) || stats_on==1) { gettimeofday( & tve, &tz ); diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec); LOG(cfg_get(core, core_cfg, latency_cfg_log), "request-route executed in: %d usec\n", diff); #ifdef STATS stats->processed_requests++; stats->acc_req_time += diff; STATS_RX_REQUEST( msg->first_line.u.request.method_value ); #endif } /* execute post request-script callbacks */ exec_post_script_cb(msg, REQUEST_CB_TYPE); }else if (msg->first_line.type==SIP_REPLY){ /* sanity checks */ if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){ /* no via, send back error ? */ LM_ERR("no via found in reply\n"); STATS_BAD_RPL(); goto error02; } if(is_printable(cfg_get(core, core_cfg, latency_cfg_log)) || stats_on==1) { gettimeofday( & tvb, &tz ); } #ifdef STATS STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 ); #endif /* execute pre-script callbacks, if any; -jiri */ /* if some of the callbacks said not to continue with * script processing, don't do so * if we are here basic sanity checks are already done * (like presence of at least one via), so you can count * on via1 being parsed in a pre-script callback --andrei */ if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 ) { STATS_RPL_FWD_DROP(); goto end; /* drop the reply */ } /* exec the onreply routing script */ keng = sr_kemi_eng_get(); if (onreply_rt.rlist[DEFAULT_RT]!=NULL || keng!=NULL){ set_route_type(CORE_ONREPLY_ROUTE); ret = 1; if(unlikely(keng!=NULL)) { bctx = sr_kemi_act_ctx_get(); init_run_actions_ctx(&ctx); sr_kemi_act_ctx_set(&ctx); ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL, NULL); sr_kemi_act_ctx_set(bctx); } else { ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx); } #ifndef NO_ONREPLY_ROUTE_ERROR if (unlikely(ret<0)){ LM_WARN("error while trying onreply script\n"); goto error_rpl; }else #endif /* NO_ONREPLY_ROUTE_ERROR */ if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){ STATS_RPL_FWD_DROP(); goto skip_send_reply; /* drop the message, no error */ } } /* send the msg */ forward_reply(msg); skip_send_reply: if(is_printable(cfg_get(core, core_cfg, latency_cfg_log)) || stats_on==1) { gettimeofday( & tve, &tz ); diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec); LOG(cfg_get(core, core_cfg, latency_cfg_log), "reply-route executed in: %d usec\n", diff); #ifdef STATS stats->processed_responses++; stats->acc_res_time+=diff; #endif } /* execute post reply-script callbacks */ exec_post_script_cb(msg, ONREPLY_CB_TYPE); } end: #ifdef STATS skipped = 0; #endif /* free possible loaded avps -bogdan */ reset_avps(); #ifdef WITH_XAVP xavp_reset_list(); #endif LM_DBG("cleaning up\n"); free_sip_msg(msg); pkg_free(msg); #ifdef STATS if (skipped) STATS_RX_DROPS; #endif /* reset log prefix */ log_prefix_set(NULL); return 0; #ifndef NO_ONREPLY_ROUTE_ERROR error_rpl: /* execute post reply-script callbacks */ exec_post_script_cb(msg, ONREPLY_CB_TYPE); reset_avps(); #ifdef WITH_XAVP xavp_reset_list(); #endif goto error02; #endif /* NO_ONREPLY_ROUTE_ERROR */ error_req: LM_DBG("error:...\n"); /* execute post request-script callbacks */ exec_post_script_cb(msg, REQUEST_CB_TYPE); error03: /* free possible loaded avps -bogdan */ reset_avps(); #ifdef WITH_XAVP xavp_reset_list(); #endif error02: free_sip_msg(msg); pkg_free(msg); error00: STATS_RX_DROPS; /* reset log prefix */ log_prefix_set(NULL); return -1; }
int _impl_api_rpc_call(ei_x_buff *reply, const str *module,const str *function, const ei_x_buff *args) { struct msghdr msgh; struct iovec cnt[8]; int pid_no = my_pid(); eapi_t api = API_RPC_CALL; int buffsz=0; int rc; if (!csockfd) { if (!enode) { LM_NOTICE("there is no connected Erlang node\n"); /* reply up with error */ ei_x_format(reply, "{error,cnode,~a}", "no_erlang_node"); return -1; } if (rex_call_in_progress) { LM_ERR("RPC loop detected\n"); ei_x_format(reply, "{badrpc,cnode,~a}", "rpc_loop_detected"); return -1; } /* do RPC from event route */ if (ei_rpc(&enode->ec,enode->sockfd,module->s,function->s,args->buff,args->index,reply) == ERL_ERROR) { reply->index = 0; /* re-use reply buffer */ if (erl_errno) { ei_x_format(reply, "{error,cnode,~s}", strerror(erl_errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { ei_x_format(reply, "{error,cnode,~s}", strerror(errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { ei_x_format(reply, "{error,cnode,~s}", "Unknown error."); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd); } return -1; } /* reset response */ enode->response.index = 0; return 0; } memset(&msgh, 0, sizeof(msgh)); memset(&cnt, 0, sizeof(cnt)); /* Kamailio PID */ cnt[0].iov_base = (void*)&pid_no; cnt[0].iov_len = sizeof(pid_no); /* method */ cnt[1].iov_base = (void*)&api; cnt[1].iov_len = sizeof(api); /* put size of following data */ cnt[2].iov_base = (void*)&module->len; cnt[2].iov_len = sizeof(int); cnt[3].iov_base = (void*)&function->len; cnt[3].iov_len = sizeof(int); buffsz = args->index; /* occupied size */ cnt[4].iov_base = (void*) &buffsz; cnt[4].iov_len = sizeof(buffsz); /* module name */ cnt[5].iov_base = (void*)module->s; cnt[5].iov_len = module->len; /* function name */ cnt[6].iov_base = (void*)function->s; cnt[6].iov_len = function->len; /* Erlang arguments content */ cnt[7].iov_base = (void*)args->buff; cnt[7].iov_len = buffsz; /* occupied size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 8; while ((rc = sendmsg(csockfd, &msgh, 0)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("sendmsg failed: %s\n",strerror(errno)); return -1; } /*receive into reply buffer */ cnt[1].iov_base = &buffsz; cnt[1].iov_len = sizeof(buffsz); /* peek reply size safe */ msgh.msg_iovlen = 2; while ((rc = recvmsg(csockfd, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("recvmsg failed: %s\n",strerror(errno)); return -1; } if (reply->buffsz < buffsz) { ei_x_free(reply); reply->buffsz = buffsz + 1; reply->buff = (char*)malloc(reply->buffsz); } cnt[2].iov_base = (void*)reply->buff; cnt[2].iov_len = buffsz; msgh.msg_iovlen = 3; while ((rc = recvmsg(csockfd, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("recvmsg failed: %s\n",strerror(errno)); return -1; } if(pid_no != my_pid()) { /* should never happened */ LM_CRIT("BUG: got other process reply (pid_no=%d)\n",pid_no); return -1; } return 0; }
/* This callback is called during each verification process, at each step during the chain of certificates (this function is not the certificate_verification one!). */ int verify_callback(int pre_verify_ok, X509_STORE_CTX *ctx) { char buf[256]; X509 *err_cert; int err, depth; depth = X509_STORE_CTX_get_error_depth(ctx); LM_NOTICE("depth = %d\n",depth); if ( depth > VERIFY_DEPTH_S ) { LM_NOTICE("cert chain too long ( depth > VERIFY_DEPTH_S)\n"); pre_verify_ok=0; } if( pre_verify_ok ) { LM_NOTICE("preverify is good: verify return: %d\n", pre_verify_ok); return pre_verify_ok; } err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof buf); LM_NOTICE("subject = %s\n", buf); LM_NOTICE("verify error:num=%d:%s\n", err, X509_verify_cert_error_string(err)); LM_NOTICE("error code is %d\n", ctx->error); switch (ctx->error) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf,sizeof buf); LM_NOTICE("issuer= %s\n",buf); break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_CERT_NOT_YET_VALID: LM_NOTICE("notBefore\n"); break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_CERT_HAS_EXPIRED: LM_NOTICE("notAfter\n"); break; case X509_V_ERR_CERT_SIGNATURE_FAILURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: LM_NOTICE("unable to decrypt cert " "signature\n"); break; case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: LM_NOTICE("unable to decode issuer " "public key\n"); break; case X509_V_ERR_OUT_OF_MEM: LM_NOTICE("out of memory \n"); break; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: LM_NOTICE("Self signed certificate " "issue\n"); break; case X509_V_ERR_CERT_CHAIN_TOO_LONG: LM_NOTICE("certificate chain too long\n"); break; case X509_V_ERR_INVALID_CA: LM_NOTICE("invalid CA\n"); break; case X509_V_ERR_PATH_LENGTH_EXCEEDED: LM_NOTICE("path length exceeded\n"); break; case X509_V_ERR_INVALID_PURPOSE: LM_NOTICE("invalid purpose\n"); break; case X509_V_ERR_CERT_UNTRUSTED: LM_NOTICE("certificate untrusted\n"); break; case X509_V_ERR_CERT_REJECTED: LM_NOTICE("certificate rejected\n"); break; default: LM_NOTICE("something wrong with the cert" " ... error code is %d (check x509_vfy.h)\n", ctx->error); break; } LM_NOTICE("verify return:%d\n", pre_verify_ok); return(pre_verify_ok); }
/** * internal implementation */ int worker_rpc_impl(ei_cnode *ec, int s,int wpid) { str module = STR_NULL; str function = STR_NULL; ei_x_buff args; ei_x_buff reply; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&args,0,sizeof(args)); memset((void*)&reply,0,sizeof(reply)); memset((void*)&msgh,0,sizeof(msgh)); /* module name length */ cnt[0].iov_base = &module.len; cnt[0].iov_len = sizeof(int); /* function name length */ cnt[1].iov_base = &function.len; cnt[1].iov_len = sizeof(int); /* Erlang args size */ cnt[2].iov_base = &args.buffsz; cnt[2].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 3; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* allocate space */ module.s = (char*)pkg_malloc(module.len+1); if (!module.s) { LM_ERR("not enough memory\n"); goto err; } function.s = (char*)pkg_malloc(function.len+1); if (!function.s) { LM_ERR("not enough memory\n"); goto err; } args.buff = (char*)malloc(args.buffsz); if (!args.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[3].iov_base = module.s; cnt[3].iov_len = module.len; cnt[4].iov_base = function.s; cnt[4].iov_len = function.len; cnt[5].iov_base = args.buff; cnt[5].iov_len = args.buffsz; /* get whole data */ msgh.msg_iovlen = 6; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ module.s[module.len] = 0; function.s[function.len] = 0; LM_DBG("rpc: %.*s:%.*s(args)\n",STR_FMT(&module),STR_FMT(&function)); EI_X_BUFF_PRINT(&args); if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); /* reply up with error */ ei_x_format(&reply, "{error,cnode,~a}", "no_erlang_node"); goto reply; } /* do RPC */ if ((rc = ei_rpc(ec,enode->sockfd,module.s,function.s,args.buff,args.buffsz,&reply)) == ERL_ERROR) { reply.index = 0; /* re-use reply buffer */ if (erl_errno) { ei_x_format(&reply, "{error,cnode,~s}", strerror(erl_errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { ei_x_format(&reply, "{error,cnode,~s}", strerror(errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { ei_x_format(&reply, "{error,cnode,~s}", "Unknown error."); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } reply: EI_X_BUFF_PRINT(&reply); cnt[0].iov_base = (void*)&wpid; cnt[0].iov_len = sizeof(int); /* send reply to Kamailio worker */ cnt[1].iov_base = (void*)&reply.buffsz; cnt[1].iov_len = sizeof(int); cnt[2].iov_base = (void*)reply.buff; cnt[2].iov_len = reply.buffsz; msgh.msg_iovlen = 3; while ((rc = sendmsg(s, &msgh, 0)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("sendmsg failed on socket=%d rpid_no=%d; %s\n",s, wpid, strerror(errno)); goto err; }; pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); return 0; err: pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); abort(); /* cant't recover */ return -1; }
/* * Setup default SSL_CTX (and SSL * ) behavior: * verification, cipherlist, acceptable versions, ... */ static int init_ssl_ctx_behavior( struct tls_domain *d ) { int verify_mode; #if (OPENSSL_VERSION_NUMBER > 0x10001000L) /* * set dh params */ if (!d->tmp_dh_file) { LM_DBG("no DH params file for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_tmp_dh_file); d->tmp_dh_file = tls_tmp_dh_file; } if (d->tmp_dh_file && set_dh_params(d->ctx, d->tmp_dh_file) < 0) return -1; if (d->tls_ec_curve) { if (set_ec_params(d->ctx, d->tls_ec_curve) < 0) { return -1; } } else { LM_NOTICE("No EC curve defined\n"); } #else if (d->tmp_dh_file || tls_tmp_dh_file) LM_WARN("DH params file discarded as not supported by your openSSL version\n"); if (d->tls_ec_curve) LM_WARN("EC params file discarded as not supported by your openSSL version\n"); #endif if( d->ciphers_list != 0 ) { if( SSL_CTX_set_cipher_list(d->ctx, d->ciphers_list) == 0 ) { LM_ERR("failure to set SSL context " "cipher list '%s'\n", d->ciphers_list); return -1; } else { LM_NOTICE("cipher list set to %s\n", d->ciphers_list); } } else { LM_DBG( "cipher list null ... setting default\n"); } /* Set a bunch of options: * do not accept SSLv2 / SSLv3 * no session resumption * choose cipher according to server's preference's*/ SSL_CTX_set_options(d->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE); /* Set verification procedure * The verification can be made null with SSL_VERIFY_NONE, or * at least easier with SSL_VERIFY_CLIENT_ONCE instead of * SSL_VERIFY_FAIL_IF_NO_PEER_CERT. * For extra control, instead of 0, we can specify a callback function: * int (*verify_callback)(int, X509_STORE_CTX *) * Also, depth 2 may be not enough in some scenarios ... though no need * to increase it much further */ if (d->type & TLS_DOMAIN_SRV) { /* Server mode: * SSL_VERIFY_NONE * the server will not send a client certificate request to the * client, so the client will not send a certificate. * SSL_VERIFY_PEER * the server sends a client certificate request to the client. * The certificate returned (if any) is checked. If the verification * process fails, the TLS/SSL handshake is immediately terminated * with an alert message containing the reason for the verification * failure. The behaviour can be controlled by the additional * SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE flags. * SSL_VERIFY_FAIL_IF_NO_PEER_CERT * if the client did not return a certificate, the TLS/SSL handshake * is immediately terminated with a ``handshake failure'' alert. * This flag must be used together with SSL_VERIFY_PEER. * SSL_VERIFY_CLIENT_ONCE * only request a client certificate on the initial TLS/SSL * handshake. Do not ask for a client certificate again in case of * a renegotiation. This flag must be used together with * SSL_VERIFY_PEER. */ if( d->verify_cert ) { verify_mode = SSL_VERIFY_PEER; if( d->require_client_cert ) { LM_WARN("client verification activated. Client " "certificates are mandatory.\n"); verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } else LM_WARN("client verification activated. Client " "certificates are NOT mandatory.\n"); } else { verify_mode = SSL_VERIFY_NONE; LM_WARN("client verification NOT activated. Weaker security.\n"); } } else { /* Client mode: * SSL_VERIFY_NONE * if not using an anonymous cipher (by default disabled), the * server will send a certificate which will be checked. The result * of the certificate verification process can be checked after the * TLS/SSL handshake using the SSL_get_verify_result(3) function. * The handshake will be continued regardless of the verification * result. * SSL_VERIFY_PEER * the server certificate is verified. If the verification process * fails, the TLS/SSL handshake is immediately terminated with an * alert message containing the reason for the verification failure. * If no server certificate is sent, because an anonymous cipher is * used, SSL_VERIFY_PEER is ignored. * SSL_VERIFY_FAIL_IF_NO_PEER_CERT * ignored * SSL_VERIFY_CLIENT_ONCE * ignored */ if( d->verify_cert ) { verify_mode = SSL_VERIFY_PEER; LM_WARN("server verification activated.\n"); } else { verify_mode = SSL_VERIFY_NONE; LM_WARN("server verification NOT activated. Weaker security.\n"); } } SSL_CTX_set_verify( d->ctx, verify_mode, verify_callback); SSL_CTX_set_verify_depth( d->ctx, VERIFY_DEPTH_S); SSL_CTX_set_session_cache_mode( d->ctx, SSL_SESS_CACHE_SERVER ); SSL_CTX_set_session_id_context( d->ctx, OS_SSL_SESS_ID, OS_SSL_SESS_ID_LEN ); return 0; }
int worker_send_impl(ei_cnode *ec, int s,int wpid) { erlang_pid pid; ei_x_buff emsg; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&emsg,0,sizeof(emsg)); memset((void*)&msgh,0,sizeof(msgh)); /* Erlang args size */ cnt[0].iov_base = &emsg.buffsz; cnt[0].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 1; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); return -1; } emsg.buff = (char*)malloc(emsg.buffsz); if (!emsg.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[1].iov_base = &pid; cnt[1].iov_len = sizeof(erlang_pid); cnt[2].iov_base = emsg.buff; cnt[2].iov_len = emsg.buffsz; /* get whole data */ msgh.msg_iovlen = 3; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); goto err; } LM_DBG(">> <%s.%d.%d> ! emsg\n",pid.node,pid.num,pid.serial); EI_X_BUFF_PRINT(&emsg); /* do ERL_SEND */ if ((rc = ei_send(enode->sockfd,&pid,emsg.buff,emsg.buffsz)) == ERL_ERROR) { if (erl_errno) { LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_send failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } free(emsg.buff); return 0; err: free(emsg.buff); return -1; }
/* * initialize tls virtual domains */ static int init_tls_domains(struct tls_domain *d) { struct tls_domain *dom; dom = d; while (d) { if (d->name.len) { LM_INFO("Processing TLS domain '%.*s'\n", d->name.len, ZSW(d->name.s)); } else { LM_INFO("Processing TLS domain [%s:%d]\n", ip_addr2a(&d->addr), d->port); } /* * set method */ if (d->method == TLS_METHOD_UNSPEC) { LM_DBG("no method for tls[%s:%d], using default\n", ip_addr2a(&d->addr), d->port); d->method = tls_default_method; } /* * create context */ d->ctx = SSL_CTX_new(ssl_methods[d->method - 1]); if (d->ctx == NULL) { LM_ERR("cannot create ssl context for " "tls[%s:%d]\n", ip_addr2a(&d->addr), d->port); return -1; } if (init_ssl_ctx_behavior( d ) < 0) return -1; /* * load certificate */ if (!d->cert_file) { LM_NOTICE("no certificate for tls[%s:%d] defined, using default" "'%s'\n", ip_addr2a(&d->addr), d->port, tls_cert_file); d->cert_file = tls_cert_file; } if (load_certificate(d->ctx, d->cert_file) < 0) return -1; /** * load crl from directory */ if (!d->crl_directory) { LM_NOTICE("no crl for tls, using none"); } else { if(load_crl(d->ctx, d->crl_directory, d->crl_check_all) < 0) return -1; } /* * load ca */ if (!d->ca_file) { LM_NOTICE("no CA for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_ca_file); d->ca_file = tls_ca_file; } if (d->ca_file && load_ca(d->ctx, d->ca_file) < 0) return -1; /* * load ca from directory */ if (!d->ca_directory) { LM_NOTICE("no CA for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_ca_dir); d->ca_directory = tls_ca_dir; } if (d->ca_directory && load_ca_dir(d->ctx, d->ca_directory) < 0) return -1; d = d->next; } /* * load all private keys as the last step (may prompt for password) */ d = dom; while (d) { if (!d->pkey_file) { LM_NOTICE("no private key for tls[%s:%d] defined, using default" "'%s'\n", ip_addr2a(&d->addr), d->port, tls_pkey_file); d->pkey_file = tls_pkey_file; } if (load_private_key(d->ctx, d->pkey_file) < 0) return -1; d = d->next; } return 0; }
int mt_add_to_tree(m_tree_t *pt, str *sp, str *svalue) { int l, ivalue = 0; mt_node_t *itn, *itn0; mt_is_t *tvalues; if(pt==NULL || sp==NULL || sp->s==NULL || svalue==NULL || svalue->s==NULL) { LM_ERR("bad parameters\n"); return -1; } if(sp->len>=MT_MAX_DEPTH) { LM_ERR("max prefix len exceeded\n"); return -1; } if ((pt->type == MT_TREE_IVAL) && (str2sint(svalue, &ivalue) != 0)) { LM_ERR("bad integer string <%.*s>\n", svalue->len, svalue->s); return -1; } l = 0; if(pt->head == NULL) { pt->head = (mt_node_t*)shm_malloc(MT_NODE_SIZE*sizeof(mt_node_t)); if(pt->head == NULL) { LM_ERR("no more shm memory for tree head\n"); return -1; } memset(pt->head, 0, MT_NODE_SIZE*sizeof(mt_node_t)); pt->nrnodes++; pt->memsize += MT_NODE_SIZE*sizeof(mt_node_t); } itn0 = pt->head; if(_mt_char_table[(unsigned int)sp->s[l]]==255) { LM_ERR("invalid char %d in prefix [%c (0x%x)]\n", l, sp->s[l], sp->s[l]); return -1; } itn = itn0[_mt_char_table[(unsigned int)sp->s[l]]].child; while(l < sp->len-1) { if(itn == NULL) { itn = (mt_node_t*)shm_malloc(MT_NODE_SIZE*sizeof(mt_node_t)); if(itn == NULL) { LM_ERR("no more shm mem\n"); return -1; } memset(itn, 0, MT_NODE_SIZE*sizeof(mt_node_t)); pt->nrnodes++; pt->memsize += MT_NODE_SIZE*sizeof(mt_node_t); itn0[_mt_char_table[(unsigned int)sp->s[l]]].child = itn; } l++; if(_mt_char_table[(unsigned int)sp->s[l]]==255) { LM_ERR("invalid char %d in prefix [%c (0x%x)]\n", l, sp->s[l], sp->s[l]); return -1; } itn0 = itn; itn = itn0[_mt_char_table[(unsigned int)sp->s[l]]].child; } if(itn0[_mt_char_table[(unsigned int)sp->s[l]]].tvalues != NULL) { if(_mt_ignore_duplicates != 0) { LM_NOTICE("prefix already allocated [%.*s/%.*s]\n", sp->len, sp->s, svalue->len, svalue->s); return 1; } else if (_mt_allow_duplicates == 0) { LM_ERR("prefix already allocated [%.*s/%.*s]\n", sp->len, sp->s, svalue->len, svalue->s); return -1; } } tvalues = (mt_is_t *)shm_malloc(sizeof(mt_is_t)); if (tvalues == NULL) { LM_ERR("no more shm mem for tvalue\n"); return -1; } memset(tvalues, 0, sizeof(mt_is_t)); if (pt->type == MT_TREE_IVAL) { tvalues->tvalue.n = ivalue; } else { /* pt->type == MT_TREE_SVAL or MT_TREE_DW */ tvalues->tvalue.s.s = (char*)shm_malloc((svalue->len+1)*sizeof(char)); if (tvalues->tvalue.s.s == NULL) { LM_ERR("no more shm mem for string\n"); return -1; } tvalues->tvalue.s.len = svalue->len; pt->memsize += (svalue->len+1)*sizeof(char); pt->nritems++; strncpy(tvalues->tvalue.s.s, svalue->s, svalue->len); tvalues->tvalue.s.s[svalue->len] = '\0'; } tvalues->next = itn0[_mt_char_table[(unsigned int)sp->s[l]]].tvalues; itn0[_mt_char_table[(unsigned int)sp->s[l]]].tvalues = tvalues; mt_node_set_payload(&itn0[_mt_char_table[(unsigned int)sp->s[l]]], pt->type); return 0; }
/* * Send an SQL query to the server */ static int db_oracle_submit_query(const db_con_t* _h, const str* _s) { OCIBind* bind[MAX_BIND_HANDLES]; OCIDate odt[sizeof(bind)/sizeof(bind[0])]; str tmps; sword status; int pass; ora_con_t* con = CON_ORA(_h); query_data_t* pqd = con->pqdata; size_t hc = pqd->_n + pqd->_nw; OCIStmt *stmthp; if (hc >= sizeof(bind)/sizeof(bind[0])) { LM_ERR("too many bound. Rebuild with MAX_BIND_HANDLES >= %u\n", (unsigned)hc); return -1; } if (!pqd->_rs) { /* * This method is at ~25% faster as set OCI_COMMIT_ON_SUCCESS * in StmtExecute */ tmps.len = snprintf(st_buf, sizeof(st_buf), "begin %.*s; commit write batch nowait; end;", _s->len, _s->s); if ((unsigned)tmps.len >= sizeof(st_buf)) return sql_buf_small(); tmps.s = st_buf; _s = &tmps; } pass = 1; if (!con->connected) { status = db_oracle_reconnect(con); if (status != OCI_SUCCESS) { LM_ERR("can't restore connection: %s\n", db_oracle_error(con, status)); return -2; } LM_INFO("connection restored\n"); --pass; } repeat: stmthp = NULL; status = OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&stmthp, OCI_HTYPE_STMT, 0, NULL); if (status != OCI_SUCCESS) goto ora_err; status = OCIStmtPrepare(stmthp, con->errhp, (text*)_s->s, _s->len, OCI_NTV_SYNTAX, OCI_DEFAULT); if (status != OCI_SUCCESS) goto ora_err; if (hc) { bmap_t bmap; size_t pos = 1; int i; memset(bind, 0, hc*sizeof(bind[0])); for (i = 0; i < pqd->_n; i++) { if (db_oracle_val2bind(&bmap, &pqd->_v[i], &odt[pos]) < 0) goto bind_err; status = OCIBindByPos(stmthp, &bind[pos], con->errhp, pos, bmap.addr, bmap.size, bmap.type, NULL, NULL, NULL, 0, NULL, OCI_DEFAULT); if (status != OCI_SUCCESS) goto ora_err; ++pos; } for (i = 0; i < pqd->_nw; i++) { if (db_oracle_val2bind(&bmap, &pqd->_w[i], &odt[pos]) < 0) { bind_err: OCIHandleFree(stmthp, OCI_HTYPE_STMT); LM_ERR("can't map values\n"); return -3; } status = OCIBindByPos(stmthp, &bind[pos], con->errhp, pos, bmap.addr, bmap.size, bmap.type, NULL, NULL, NULL, 0, NULL, OCI_DEFAULT); if (status != OCI_SUCCESS) goto ora_err; ++pos; } } // timelimited operation status = begin_timelimit(con, 0); if (status != OCI_SUCCESS) goto ora_err; do status = OCIStmtExecute(con->svchp, stmthp, con->errhp, !pqd->_rs, 0, NULL, NULL, pqd->_rs ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT); while (wait_timelimit(con, status)); if (done_timelimit(con, status)) goto stop_exec; switch (status) { case OCI_SUCCESS_WITH_INFO: LM_WARN("driver: %s\n", db_oracle_errorinfo(con)); //PASS THRU case OCI_SUCCESS: if (pqd->_rs) *pqd->_rs = stmthp; else OCIHandleFree(stmthp, OCI_HTYPE_STMT); return 0; default: pass = -pass; break; } ora_err: LM_ERR("driver: %s\n", db_oracle_error(con, status)); stop_exec: if (stmthp) OCIHandleFree(stmthp, OCI_HTYPE_STMT); if (pass == -1 && !con->connected) { /* Attemtp to reconnect */ if (db_oracle_reconnect(con) == OCI_SUCCESS) { LM_NOTICE("attempt repeat after reconnect\n"); pass = 0; goto repeat; } LM_ERR("connection loss\n"); } return -4; }
/* UPDATED + CHECKED */ static inline char *run_log( struct cpl_interpreter *intr ) { char *p; unsigned short attr_name; unsigned short n; str name = {0,0}; str comment = {0,0}; str user; int i; /* sanity check */ if (NR_OF_KIDS(intr->ip)>1) { LM_ERR("LOG node suppose to have max one child" ", not %d!\n",NR_OF_KIDS(intr->ip)); goto script_error; } /* is logging enabled? */ if ( cpl_env.log_dir==0 ) goto done; /* read the attributes of the LOG node*/ p = ATTR_PTR(intr->ip); for( i=NR_OF_ATTR(intr->ip); i>0 ; i-- ) { get_basic_attr( p, attr_name, n, intr, script_error); switch (attr_name) { case NAME_ATTR: get_str_attr( p, name.s, n, intr, script_error,1); name.len = n; break; case COMMENT_ATTR: get_str_attr( p, comment.s, n, intr, script_error,1); comment.len = n; break; default: LM_ERR("unknown attribute " "(%d) in LOG node\n",attr_name); goto script_error; } } if (comment.len==0) { LM_NOTICE("LOG node has no comment attr -> skipping\n"); goto done; } user.len = intr->user.len + name.len + comment.len; /* duplicate the attrs in shm memory */ user.s = p = (char*)shm_malloc( user.len ); if (!user.s) { LM_ERR("no more shm memory!\n"); goto runtime_error; } /* copy the user name */ memcpy( p, intr->user.s, intr->user.len); user.len = intr->user.len; p += intr->user.len; /* copy the log name */ if (name.len) { memcpy( p, name.s, name.len ); name.s = p; p += name.len; } /* copy the comment */ memcpy( p, comment.s, comment.len); comment.s = p; /* send the command */ write_cpl_cmd( CPL_LOG_CMD, &user, &name, &comment ); done: return get_first_child(intr->ip); runtime_error: return CPL_RUNTIME_ERROR; script_error: return CPL_SCRIPT_ERROR; }
/* * destroy function */ static void destroy(void) { LM_NOTICE("destroy module ...\n"); /* closing sockets */ rmq_destroy_pipe(); }
int k_sd_journal_send_xavp(str *rname) { struct _sr_xavp *rxavp, *nxavp; int cnt, buflen, i, ret; struct iovec *logv; rxavp = xavp_get(rname, NULL); if (!rxavp || rxavp->val.type != SR_XTYPE_XAVP) { LM_ERR("not a valid xavp: %.*s?\n", rname->len, rname->s); } /* first, count xavp nodes */ for (nxavp = rxavp->val.v.xavp, cnt = 0; nxavp; nxavp = nxavp->next, cnt++); if (cnt == 0) { /* nothing to log? */ LM_NOTICE("empty xavp: %.*s?, no log event was sent to journald\n", rname->len, rname->s); return 1; } logv = pkg_malloc(cnt * sizeof (struct iovec)); if (!logv) { LM_ERR("failed to allocate pkg memory\n"); return -1; } ret = -1; for (nxavp = rxavp->val.v.xavp, cnt = 0; nxavp; nxavp = nxavp->next, cnt++) { if (nxavp->val.type == SR_XTYPE_INT) { buflen = snprintf(NULL, 0, "%.*s=%d", nxavp->name.len, nxavp->name.s, nxavp->val.v.i); logv[cnt].iov_base = pkg_malloc(buflen + 1/*snprintf's trailing \0*/); if (!logv[cnt].iov_base ) { LM_ERR("failed to allocate pkg memory\n"); goto free; } logv[cnt].iov_len = buflen; snprintf(logv[cnt].iov_base, buflen + 1, "%.*s=%d", nxavp->name.len, nxavp->name.s, nxavp->val.v.i); } else if (nxavp->val.type == SR_XTYPE_STR) { buflen = nxavp->name.len + 1 + nxavp->val.v.s.len; logv[cnt].iov_base = pkg_malloc(buflen); if (!logv[cnt].iov_base) { LM_ERR("failed to allocate pkg memory\n"); goto free; } logv[cnt].iov_len = buflen; memcpy(logv[cnt].iov_base, nxavp->name.s, nxavp->name.len); ((char*)logv[cnt].iov_base)[nxavp->name.len] = '='; memcpy(((char*)(logv[cnt].iov_base)) + nxavp->name.len + 1, nxavp->val.v.s.s, nxavp->val.v.s.len); } else { LM_NOTICE("unsupported type %d for field %.*s, skipped...\n", nxavp->val.type, nxavp->name.len, nxavp->name.s); logv[cnt].iov_len = 0; logv[cnt].iov_base = NULL; } LM_DBG("added io slice %d: %.*s\n", cnt, (int)logv[cnt].iov_len, (char*)logv[cnt].iov_base); } if (sd_journal_sendv(logv, cnt) != 0) { LM_ERR("sd_journal_sendv() failed\n"); } else { ret = 1; } free: for (i = 0 ; i < cnt ; i++) { if (logv[i].iov_base) pkg_free(logv[i].iov_base); } pkg_free(logv); return ret; }
static int cpl_init(void) { bind_usrloc_t bind_usrloc; struct stat stat_t; char *ptr; int val; init_db_url( db_url , 0 /*cannot be null*/); db_table.len = strlen(db_table.s); LM_INFO("initializing...\n"); if (proxy_route && proxy_route[0]) { cpl_env.proxy_route = get_script_route_ID_by_name( proxy_route, rlist, RT_NO); if (cpl_env.proxy_route==-1) { LM_ERR("route <%s> does not exist\n",proxy_route); return -1; } } if (cpl_env.proxy_recurse>MAX_PROXY_RECURSE) { LM_CRIT("value of proxy_recurse param (%d) exceeds " "the maximum safety value (%d)\n", cpl_env.proxy_recurse,MAX_PROXY_RECURSE); goto error; } if (dtd_file==0) { LM_CRIT("mandatory parameter \"cpl_dtd_file\" found empty\n"); goto error; } else { /* check if the dtd file exists */ if (stat( dtd_file, &stat_t)==-1) { LM_ERR("checking file \"%s\" status failed; stat returned %s\n", dtd_file,strerror(errno)); goto error; } if ( !S_ISREG( stat_t.st_mode ) ) { LM_ERR("dir \"%s\" is not a regular file!\n", dtd_file); goto error; } if (access( dtd_file, R_OK )==-1) { LM_ERR("checking file \"%s\" for permissions " "failed; access returned %s\n",dtd_file,strerror(errno)); goto error; } } if (cpl_env.log_dir==0) { LM_INFO("log_dir param found empty -> logging disabled!\n"); } else { if ( strlen(cpl_env.log_dir)>MAX_LOG_DIR_SIZE ) { LM_ERR("dir \"%s\" has a too long name :-(!\n", cpl_env.log_dir); goto error; } /* check if the dir exists */ if (stat( cpl_env.log_dir, &stat_t)==-1) { LM_ERR("checking dir \"%s\" status failed;" " stat returned %s\n",cpl_env.log_dir,strerror(errno)); goto error; } if ( !S_ISDIR( stat_t.st_mode ) ) { LM_ERR("dir \"%s\" is not a directory!\n", cpl_env.log_dir); goto error; } if (access( cpl_env.log_dir, R_OK|W_OK )==-1) { LM_ERR("checking dir \"%s\" for permissions failed; access " "returned %s\n", cpl_env.log_dir, strerror(errno)); goto error; } } /* bind to the mysql module */ if (cpl_db_bind(&db_url, &db_table)<0) goto error; /* load TM API */ if (load_tm_api(&cpl_fct.tmb)!=0) { LM_ERR("can't load TM API\n"); goto error; } /* load SIGNALING API */ if(load_sig_api(&cpl_fct.sigb)< 0) { LM_ERR("can't load signaling functions\n"); return -1; } /* bind to usrloc module if requested */ if (lookup_domain) { /* import all usrloc functions */ bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0); if (!bind_usrloc) { LM_ERR("can't bind usrloc\n"); goto error; } if (bind_usrloc( &(cpl_fct.ulb) ) < 0) { LM_ERR("importing usrloc failed\n"); goto error; } /* convert lookup_domain from char* to udomain_t* pointer */ if (cpl_fct.ulb.register_udomain( lookup_domain, &cpl_env.lu_domain) < 0) { LM_ERR("failed to register domain <%s>\n",lookup_domain); goto error; } } else { LM_NOTICE("no lookup_domain given -> disable lookup node\n"); } /* build a pipe for sending commands to aux process */ if ( pipe( cpl_env.cmd_pipe )==-1 ) { LM_CRIT("cannot create command pipe: %s!\n", strerror(errno) ); goto error; } /* set the writing non blocking */ if ( (val=fcntl(cpl_env.cmd_pipe[1], F_GETFL, 0))<0 ) { LM_ERR("getting flags from pipe[1] failed: fcntl said %s!\n", strerror(errno)); goto error; } if ( fcntl(cpl_env.cmd_pipe[1], F_SETFL, val|O_NONBLOCK) ) { LM_ERR("setting flags to pipe[1] failed: fcntl said %s!\n", strerror(errno)); goto error; } /* init the CPL parser */ if (init_CPL_parser( dtd_file )!=1 ) { LM_ERR("init_CPL_parser failed!\n"); goto error; } /* make a copy of the original TZ env. variable */ ptr = getenv("TZ"); cpl_env.orig_tz.len = 3/*"TZ="*/ + (ptr?(strlen(ptr)+1):0); if ( (cpl_env.orig_tz.s=shm_malloc( cpl_env.orig_tz.len ))==0 ) { LM_ERR("no more shm mem. for saving TZ!\n"); goto error; } memcpy(cpl_env.orig_tz.s,"TZ=",3); if (ptr) strcpy(cpl_env.orig_tz.s+3,ptr); /* convert realm_prefix from string null terminated to str */ if (cpl_env.realm_prefix.s) { cpl_env.realm_prefix.len = strlen(cpl_env.realm_prefix.s); /* convert the realm_prefix to lower cases */ strlower( &cpl_env.realm_prefix ); } return 0; error: return -1; }
/*! \brief send a message over an already opened TCP connection */ int tcp_send_recv(int sockfd, char* buf, int len, rd_buf_t* rb, unsigned int waited_id) { int n, number_of_tries; fd_set active_fd_set, read_fd_set; struct timeval tv; unsigned long int result_code; AAAMessage *msg; AAA_AVP *avp; char serviceType; unsigned int m_id; /* try to write the message to the Diameter client */ while( (n=write(sockfd, buf, len))==-1 ) { if (errno==EINTR) continue; LM_ERR("write returned error: %s\n", strerror(errno)); return AAA_ERROR; } if (n!=len) { LM_ERR("write gave no error but wrote less than asked\n"); return AAA_ERROR; } /* wait for the answer a limited amount of time */ tv.tv_sec = MAX_WAIT_SEC; tv.tv_usec = MAX_WAIT_USEC; /* Initialize the set of active sockets. */ FD_ZERO (&active_fd_set); FD_SET (sockfd, &active_fd_set); number_of_tries = 0; while(number_of_tries<MAX_TRIES) { read_fd_set = active_fd_set; if (select (sockfd+1, &read_fd_set, NULL, NULL, &tv) < 0) { LM_ERR("select function failed\n"); return AAA_ERROR; } /* if (!FD_ISSET (sockfd, &read_fd_set)) { LM_ERR("no response received\n"); // return AAA_ERROR; } */ /* Data arriving on a already-connected socket. */ reset_read_buffer(rb); switch( do_read(sockfd, rb) ) { case CONN_ERROR: LM_ERR("failed to read from socket\n"); return AAA_CONN_CLOSED; case CONN_CLOSED: LM_ERR("failed to read from socket\n"); return AAA_CONN_CLOSED; } /* obtain the structure corresponding to the message */ msg = AAATranslateMessage(rb->buf, rb->buf_len, 0); if(!msg) { LM_ERR("message structure not obtained\n"); return AAA_ERROR; } avp = AAAFindMatchingAVP(msg, NULL, AVP_SIP_MSGID, vendorID, AAA_FORWARD_SEARCH); if(!avp) { LM_ERR("AVP_SIP_MSGID not found\n"); return AAA_ERROR; } m_id = *((unsigned int*)(avp->data.s)); LM_DBG("######## m_id=%d\n", m_id); if(m_id!=waited_id) { number_of_tries ++; LM_NOTICE("old message received\n"); continue; } goto next; } LM_ERR("too many old messages received\n"); return AAA_TIMEOUT; next: /* Finally die correct answer */ avp = AAAFindMatchingAVP(msg, NULL, AVP_Service_Type, vendorID, AAA_FORWARD_SEARCH); if(!avp) { LM_ERR("AVP_Service_Type not found\n"); return AAA_ERROR; } serviceType = avp->data.s[0]; result_code = ntohl(*((unsigned long int*)(msg->res_code->data.s))); switch(result_code) { case AAA_SUCCESS: /* 2001 */ return ACC_SUCCESS; default: /* error */ return ACC_FAILURE; } }
int _impl_reg_send(const str *server, const ei_x_buff *msg) { struct msghdr msgh; struct iovec cnt[6]; int pid_no = my_pid(); eapi_t api = API_REG_SEND; int buffsz; int rc; int i=0,version; memset(&msgh, 0, sizeof(msgh)); memset(&cnt, 0, sizeof(cnt)); if (ei_decode_version(msg->buff,&i,&version)) { LM_ERR("msg must be encoded with version\n"); return -1; } if (!csockfd) { if (!enode) { LM_NOTICE("there is no connected Erlang node\n"); return -1; } if (rex_call_in_progress) { LM_ERR("RPC in progress detected\n"); return -1; } /* do ERL_REG_SEND in event route */ if ((rc = ei_reg_send(&enode->ec,enode->sockfd,server->s,msg->buff,msg->buffsz)) == ERL_ERROR) { if (erl_errno) { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd); } } /* reset response */ enode->response.index = 0; return 0; } /* Kamailio PID */ cnt[0].iov_base = (void*)&pid_no; cnt[0].iov_len = sizeof(pid_no); /* method */ cnt[1].iov_base = (void*)&api; cnt[1].iov_len = sizeof(api); /* put size of following data */ cnt[2].iov_base = (void*)&server->len; cnt[2].iov_len = sizeof(int); buffsz = msg->index; /* occupied size */ cnt[3].iov_base = (void*)&buffsz; cnt[3].iov_len = sizeof(buffsz); /* module name */ cnt[4].iov_base = (void*)server->s; cnt[4].iov_len = server->len; /* Erlang arguments content */ cnt[5].iov_base = (void*)msg->buff; cnt[5].iov_len = buffsz; /* occupied size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 6; while ((rc = sendmsg(csockfd, &msgh, 0)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("sendmsg failed: %s\n",strerror(errno)); return -1; } /* no reply */ return 0; }
int acc_diam_request( struct sip_msg *req, struct sip_msg *rpl) { int attr_cnt; int cnt; AAAMessage *send = NULL; AAA_AVP *avp; struct sip_uri puri; str *uri; int ret; int i; int status; char tmp[2]; unsigned int mid; attr_cnt = core2strar( req, val_arr); /* last value is not used */ attr_cnt--; if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("failed to create new AAA request\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(req, acc_env.code))<0) { LM_ERR("status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ mid = req->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* also the extra attributes */ attr_cnt += extra2strar( dia_extra, rpl, req, val_arr, 0); /* add attributes */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } /* and the leg attributes */ if ( leg_info ) { cnt = legs2strar(leg_info,req,val_arr,1); do { for (i=0; i<cnt; i++) { if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } } while ( (cnt=legs2strar(leg_info,req,val_arr,0))!=0 ); } if (get_uri(req, &uri) < 0) { LM_ERR("failed to get uri, From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, req->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed.It will be " "reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) { /* a transmission error occurred */ LM_ERR("message sending to the DIAMETER backend authorization " "server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&send); return -1; }
static int w_handle_call(struct sip_msg *msg, char *flow_var) { struct cc_flow *flow; struct cc_call *call; str leg = {NULL,0}; str *dn; str val; int dec; int ret = -1; call = NULL; dec = 0; /* get the flow name */ if (fixup_get_svalue(msg, (gparam_p)flow_var, &val)!=0) { LM_ERR("failed to avaluate the flow name variable\n"); return -1; } /* parse FROM URI */ if (parse_from_uri(msg)==NULL) { LM_ERR("failed to parse from hdr\n"); return -2; } lock_get( data->lock ); /* get the flow ID */ flow = get_flow_by_name(data, &val); if (flow==NULL) { LM_ERR("flow <%.*s> does not exists\n", val.len, val.s); ret = -3; goto error; } LM_DBG("using call flow %p\n", flow); if (flow->logged_agents==0 /* no logged agents */ ) { LM_NOTICE("flow <%.*s> closed\n",flow->id.len,flow->id.s); ret = -4; goto error; } update_stat(stg_incalls, 1); update_stat(flow->st_incalls, 1); if (flow->cid.len) { dn = build_displayname(&flow->cid, get_from(msg)); } else if (get_from(msg)->display.len) { dn = &get_from(msg)->display; } else { dn = &get_from(msg)->parsed_uri.user; } LM_DBG("cid=<%.*s>\n",dn->len,dn->s); call = new_cc_call(data, flow, dn, &get_from(msg)->parsed_uri.user); if (call==NULL) { LM_ERR("failed to create new call\n"); ret = -5; goto error; } call->fst_flags |= FSTAT_INCALL; /* get estimated wait time */ call->eta = (unsigned int) (( flow->avg_call_duration * (float)get_stat_val(flow->st_queued_calls) ) / (float)flow->logged_agents); LM_DBG("avg_call_duration=%.2f queued_calls=%lu logedin_agents=%u\n", flow->avg_call_duration, get_stat_val(flow->st_queued_calls), flow->logged_agents); LM_DBG("ETA for new call(%p) is %d\n", call, call->eta); /* one more call to process */ flow->ongoing_calls++; /* there is no need to lock the call here as it is not * yet sharead at all - just we have a ref to it */ /* get the first state */ if (cc_call_state_machine( data, call, &leg )!=0) { LM_ERR("failed to get first call destination \n"); ret = -5; goto error; } lock_release( data->lock ); LM_DBG("new destination for call(%p) is %.*s (state=%d)\n", call, leg.len, leg.s, call->state); /* call still waits for agent ? */ if (call->state!=CC_CALL_TOAGENT) { LM_DBG("** onhold++ Not to agent [%p]\n", call); update_stat( stg_onhold_calls, +1); update_stat( flow->st_onhold_calls, +1); dec = 1; } /* send call to selected destination */ if (set_call_leg( msg, call, &leg)< 0 ) { LM_ERR("failed to set new destination for call\n"); if (dec) { LM_DBG("** onhold-- Error [%p]\n", call); update_stat( stg_onhold_calls, -1); update_stat( flow->st_onhold_calls, -1); } pkg_free(leg.s); goto error1; } pkg_free(leg.s); if(cc_db_insert_call(call) < 0) { LM_ERR("Failed to insert call record in db\n"); } return 1; error: lock_release( data->lock ); error1: if (call) { free_cc_call( data, call); flow->ongoing_calls--; } return ret; }