int rl_add_repl_dst(modparam_t type, void *val) { char *host; int hlen, port; int proto; struct hostent *he; str st; rl_dests = pkg_realloc(rl_dests, (rl_dests_nr + 1) * sizeof(rl_repl_dst_t)); if (!rl_dests) { LM_ERR("oom\n"); return -1; } if (parse_phostport(val, strlen(val), &host, &hlen, &port, &proto) < 0) { LM_ERR("Bad replication destination IP!\n"); return -1; } if (proto == PROTO_NONE) proto = PROTO_UDP; st.s = host; st.len = hlen; he = sip_resolvehost(&st, (unsigned short *)&port, (unsigned short *)&proto, 0, 0); if (!he) { LM_ERR("Cannot resolve host: %.*s\n", hlen, host); return -1; } if (!port) { LM_ERR("no port specified for host %.*s\n", hlen, host); return -1; } rl_dests[rl_dests_nr].id = rl_dests_nr; rl_dests[rl_dests_nr].dst.s = (char *)val; rl_dests[rl_dests_nr].dst.len = strlen(rl_dests[rl_dests_nr].dst.s); hostent2su(&rl_dests[rl_dests_nr].to, he, 0, port); LM_DBG("Added destination <%.*s>\n", rl_dests[rl_dests_nr].dst.len, rl_dests[rl_dests_nr].dst.s); /* init done */ rl_dests_nr++; return 1; }
/*! \brief */ static int set_sock_hdr(struct sip_msg *msg, ucontact_info_t *ci, unsigned int reg_flags) { struct socket_info *sock; struct hdr_field *hf; str socks; str hosts; int port; int proto; if (!msg || !(reg_flags & REG_SAVE_SOCKET_FLAG)) return 1; if (parse_headers( msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse message\n"); return 1; } hf = get_header_by_name( msg, sock_hdr_name.s, sock_hdr_name.len); if (hf==0) return 1; trim_len( socks.len, socks.s, hf->body ); if (socks.len==0) return 1; if (parse_phostport( socks.s, socks.len, &hosts.s, &hosts.len, &port, &proto)!=0) { LM_ERR("bad socket <%.*s> in \n", socks.len, socks.s); return 1; } set_sip_defaults( port, proto); sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto); if (sock==0) { LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s); return 1; } LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port,sock ); ci->sock = sock; return 0; }
static int ki_set_socket_helper(sip_msg_t *msg, str *ssock, int smode) { socket_info_t *si; int port, proto; str host; if(msg==NULL) { LM_ERR("bad parameters\n"); return -1; } if(ssock==NULL || ssock->len<=0) { reset_force_socket(msg); return 1; } if (parse_phostport(ssock->s, &host.s, &host.len, &port, &proto) < 0) { LM_ERR("invalid socket specification [%.*s] (%d)\n", ssock->len, ssock->s, smode); goto error; } si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (si!=NULL) { if(smode==0) { /* send socket */ set_force_socket(msg, si); } else { /* recv socket */ msg->rcv.bind_address = si; msg->rcv.dst_port = si->port_no; msg->rcv.dst_ip = si->address; msg->rcv.proto = si->proto; msg->rcv.proto_reserved1 = 0; msg->rcv.proto_reserved2 = 0; } } else { LM_WARN("no socket found to match [%.*s] (%d)\n", ssock->len, ssock->s, smode); } return 1; error: return -1; }
struct socket_info *msrp_get_local_socket(str *sockaddr) { int port, proto; str host; char backup; struct socket_info *si; backup = sockaddr->s[sockaddr->len]; sockaddr->s[sockaddr->len] = '\0'; if (parse_phostport(sockaddr->s, &host.s, &host.len, &port, &proto) < 0) { LM_ERR("invalid socket specification\n"); sockaddr->s[sockaddr->len] = backup; return NULL; } sockaddr->s[sockaddr->len] = backup; si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); return si; }
static int add_replication_dest(modparam_t type, void *val) { struct replication_dest *rd; char *host; int hlen, port; int proto; struct hostent *he; str st; rd = pkg_malloc(sizeof(*rd)); memset(rd, 0, sizeof(*rd)); if (parse_phostport(val, strlen(val), &host, &hlen, &port, &proto) < 0) { LM_ERR("Bad replication destination IP!\n"); return -1; } if (proto == PROTO_NONE) proto = PROTO_UDP; if (proto != PROTO_UDP) { LM_ERR("Dialog replication only supports UDP packets!\n"); return -1; } st.s = host; st.len = hlen; he = sip_resolvehost(&st, (unsigned short *)&port, (unsigned short *)&proto, 0, 0); if (!he) { LM_ERR("Cannot resolve host: %.*s\n", hlen, host); return -1; } hostent2su(&rd->to, he, 0, port); rd->next = replication_dests; replication_dests = rd; return 1; }
/*! \brief */ static struct socket_info *get_sock_hdr(struct sip_msg *msg) { struct socket_info *sock; struct hdr_field *hf; str socks; str hosts; int port; int proto; if (parse_headers( msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse message\n"); return 0; } hf = get_header_by_name( msg, sock_hdr_name.s, sock_hdr_name.len); if (hf==0) return 0; trim_len( socks.len, socks.s, hf->body ); if (socks.len==0) return 0; if (parse_phostport( socks.s, socks.len, &hosts.s, &hosts.len, &port, &proto)!=0) { LM_ERR("bad socket <%.*s> in \n", socks.len, socks.s); return 0; } set_sip_defaults( port, proto); sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto); if (sock==0) { LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s); return 0; } LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock ); return sock; }
static struct socket_info * fetch_socket_info(str *addr) { struct socket_info *sock; int port, proto; str host; if (!addr->s || addr->s[0] == 0) return NULL; if (parse_phostport(addr->s, addr->len, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%.*s>\n", addr->len, addr->s); return NULL; } sock = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (!sock) { LM_WARN("non-local socket <%.*s>...ignoring\n", addr->len, addr->s); } return sock; }
/*! * \brief Get all contacts from the database, in partitions if wanted * \see get_all_ucontacts * \param buf target buffer * \param len length of buffer * \param flags contact flags * \param part_idx part index * \param part_max maximal part * \param options options * \return 0 on success, positive if buffer size was not sufficient, negative on failure */ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max, int options) { struct socket_info *sock; unsigned int dbflags; db1_res_t* res = NULL; db_row_t *row; dlist_t *dom; int port, proto; char *p; str addr; str recv; str path; str ruid; str host; unsigned int aorhash; int i; void *cp; int shortage, needed; db_key_t keys1[4]; /* where */ db_val_t vals1[4]; db_op_t ops1[4]; db_key_t keys2[6]; /* select */ int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */ cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(addr.len); aorhash = 0; /* select fields */ keys2[0] = &received_col; keys2[1] = &contact_col; keys2[2] = &sock_col; keys2[3] = &cflags_col; keys2[4] = &path_col; keys2[5] = &ruid_col; /* where fields */ keys1[0] = &expires_col; ops1[0] = OP_GT; vals1[0].nul = 0; UL_DB_EXPIRES_SET(&vals1[0], time(0)); keys1[1] = &partition_col; ops1[1] = OP_EQ; vals1[1].type = DB1_INT; vals1[1].nul = 0; if(_ul_max_partition>0) vals1[1].val.int_val = part_idx; else vals1[1].val.int_val = 0; if (flags & nat_bflag) { keys1[n[0]] = &keepalive_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = 1; n[0]++; } if(options&GAU_OPT_SERVER_ID) { keys1[n[0]] = &srv_id_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = server_id; n[0]++; } /* TODO: use part_idx and part_max on keys1 */ for (dom = root; dom!=NULL ; dom=dom->next) { if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) { LM_ERR("sql use_table failed\n"); return -1; } if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2, n[0], n[1], NULL, &res) <0 ) { LM_ERR("query error\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ recv.s = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) { recv.s = NULL; recv.len = 0; } else { recv.len = strlen(recv.s); } /* contact */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } else { addr.len = strlen(addr.s); } /* path */ path.s = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){ path.s = NULL; path.len = 0; } else { path.len = strlen(path.s); } /* ruid */ ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5); if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){ ruid.s = NULL; ruid.len = 0; } else { ruid.len = strlen(ruid.s); } needed = (int)(sizeof(addr.len) + addr.len + sizeof(recv.len) + recv.len + sizeof(sock) + sizeof(dbflags) + sizeof(path.len) + path.len + sizeof(ruid.len) + ruid.len + sizeof(aorhash)); if (len < needed) { shortage += needed ; continue; } /* write contact */ memcpy(cp, &addr.len, sizeof(addr.len)); cp = (char*)cp + sizeof(addr.len); memcpy(cp, addr.s, addr.len); cp = (char*)cp + addr.len; /* write received */ memcpy(cp, &recv.len, sizeof(recv.len)); cp = (char*)cp + sizeof(recv.len); /* copy received only if exist */ if(recv.len){ memcpy(cp, recv.s, recv.len); cp = (char*)cp + recv.len; } /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...set to 0\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...set to 0\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &path.len, sizeof(path.len)); cp = (char*)cp + sizeof(path.len); /* copy path only if exist */ if(path.len){ memcpy(cp, path.s, path.len); cp = (char*)cp + path.len; } /* write ruid */ memcpy(cp, &ruid.len, sizeof(ruid.len)); cp = (char*)cp + sizeof(ruid.len); /* copy ruid only if exist */ if(ruid.len){ memcpy(cp, ruid.s, ruid.len); cp = (char*)cp + ruid.len; } /* aorhash not used for db-only records, but it is added * (as 0) to match the struct used for mem records */ memcpy(cp, &aorhash, sizeof(aorhash)); cp = (char*)cp + sizeof(aorhash); len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(addr.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
static void core_sctp_options(rpc_t *rpc, void *c) { #ifdef USE_SCTP void *handle; struct cfg_group_sctp t; char *param; struct socket_info *si; char *host; str hs; int hlen; int port; int proto; param = 0; if(!sctp_disable) { /* look for optional socket parameter */ if(rpc->scan(c, "*s", ¶m) > 0) { si = 0; if(strcasecmp(param, "default") == 0) { si = sendipv4_sctp ? sendipv4_sctp : sendipv6_sctp; } else if(strcasecmp(param, "first") == 0) { si = sctp_listen; } else { if(parse_phostport(param, &host, &hlen, &port, &proto) != 0) { rpc->fault(c, 500, "bad param (use address, address:port," " default or first)"); return; } if(proto && proto != PROTO_SCTP) { rpc->fault(c, 500, "bad protocol in param (only SCTP" " allowed)"); return; } hs.s = host; hs.len = hlen; si = grep_sock_info(&hs, port, PROTO_SCTP); if(si == 0) { rpc->fault(c, 500, "not listening on sctp %s", param); return; } } if(si == 0 || si->socket == -1) { rpc->fault(c, 500, "could not find a sctp socket"); return; } memset(&t, 0, sizeof(t)); if(sctp_get_cfg_from_sock(si->socket, &t) != 0) { rpc->fault(c, 500, "failed to get socket options"); return; } } else { sctp_options_get(&t); } rpc->add(c, "{", &handle); rpc->struct_add(handle, "ddddddddddddddddddd", "sctp_socket_rcvbuf", t.so_rcvbuf, "sctp_socket_sndbuf", t.so_sndbuf, "sctp_autoclose", t.autoclose, "sctp_send_ttl", t.send_ttl, "sctp_send_retries", t.send_retries, "sctp_assoc_tracking", t.assoc_tracking, "sctp_assoc_reuse", t.assoc_reuse, "sctp_max_assocs", t.max_assocs, "sctp_srto_initial", t.srto_initial, "sctp_srto_max", t.srto_max, "sctp_srto_min", t.srto_min, "sctp_asocmaxrxt", t.asocmaxrxt, "sctp_init_max_attempts", t.init_max_attempts, "sctp_init_max_timeo", t.init_max_timeo, "sctp_hbinterval", t.hbinterval, "sctp_pathmaxrxt", t.pathmaxrxt, "sctp_sack_delay", t.sack_delay, "sctp_sack_freq", t.sack_freq, "sctp_max_burst", t.max_burst); } else { rpc->fault(c, 500, "sctp support disabled"); } #else rpc->fault(c, 500, "sctp support not compiled"); #endif }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; LM_DBG("initializing ...\n"); /* Load stuff from DB */ init_db_url( ds_db_url , 0 /*cannot be null*/); ds_table_name.len = strlen(ds_table_name.s); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_sock_col.len = strlen(ds_dest_sock_col.s); ds_dest_state_col.len = strlen(ds_dest_state_col.s); ds_dest_weight_col.len = strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); /* handle AVPs spec */ dst_avp_param.len = strlen(dst_avp_param.s); if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name,&dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } grp_avp_param.len=strlen(grp_avp_param.s); if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name,&grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } cnt_avp_param.len=strlen(cnt_avp_param.s); if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name,&cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } sock_avp_param.len=strlen(sock_avp_param.s); if (pv_parse_spec(&sock_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name,&sock_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } if (attrs_avp_param.s && (attrs_avp_param.len=strlen(attrs_avp_param.s)) > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name = -1; attrs_avp_type = 0; } if (hash_pvar_param.s && (hash_pvar_param.len=strlen(hash_pvar_param.s))>0 ) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if (ds_setid_pvname.s && (ds_setid_pvname.len=strlen(ds_setid_pvname.s))>0 ) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } pvar_algo_param.len = strlen(pvar_algo_param.s); if (pvar_algo_param.len) ds_pvar_parse_pattern(pvar_algo_param); if (init_ds_bls()!=0) { LM_ERR("failed to init DS blacklists\n"); return E_CFG; } if (init_ds_data()!=0) { LM_ERR("failed to init DS data holder\n"); return -1; } /* open DB connection to load provisioning data */ if (init_ds_db()!= 0) { LM_ERR("failed to init database support\n"); return -1; } /* do the actula data load */ if (ds_reload_db()!=0) { LM_ERR("failed to load data from DB\n"); return -1; } /* close DB connection */ ds_disconnect_db(); /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); /* parse the list of reply codes to be counted as success */ if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes( &options_reply_codes_str, &options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } /* parse and look for the socket to ping from */ if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer("ds-pinger",ds_check_timer,NULL,ds_ping_interval)<0){ LM_ERR("failed to register timer for probing!\n"); return -1; } } /* register timer to flush the state of destination back to DB */ if (register_timer("ds-flusher",ds_flusher_routine,NULL, 30)<0){ LM_ERR("failed to register timer for DB flushing!\n"); return -1; } dispatch_evi_id = evi_publish_event(dispatcher_event); if (dispatch_evi_id == EVI_ERROR) LM_ERR("cannot register dispatcher event\n"); return 0; }
int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param, int op, pv_value_t *val, int btype) { int idx = 0; int idxf = 0; branch_t *br; struct socket_info *si; int port, proto; str host; char backup; if(msg==NULL || param==NULL) { LM_ERR("bad parameters\n"); return -1; } if(btype==1) { br = &_pv_sbranch; } else { /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return -1; } if(idx<0) { if((int)nr_branches + idx >= 0) { idx += nr_branches; } else { LM_ERR("index too low: %d (%u)\n", idx, nr_branches); return -1; } } LM_DBG("managing branch index %d (%u)\n", idx, nr_branches); br = get_sip_branch(idx); } if(br==NULL) { LM_DBG("no branch to operate on\n"); return -1; } switch(param->pvn.u.isname.name.n) { case 1: /* dst uri */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->dst_uri[0] = '\0'; br->dst_uri_len = 0; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch dst uri\n"); return -1; } if(val->rs.len<=0) { br->dst_uri[0] = '\0'; br->dst_uri_len = 0; break; } if (unlikely(val->rs.len > MAX_URI_SIZE - 1)) { LM_ERR("too long dst uri: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->dst_uri, val->rs.s, val->rs.len); br->dst_uri[val->rs.len] = 0; br->dst_uri_len = val->rs.len; break; case 2: /* path */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->path[0] = '\0'; br->path_len = 0; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch path\n"); return -1; } if(val->rs.len<=0) { br->path[0] = '\0'; br->path_len = 0; break; } if (unlikely(val->rs.len > MAX_PATH_SIZE - 1)) { LM_ERR("path too long: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->path, val->rs.s, val->rs.len); br->path[val->rs.len] = 0; br->path_len = val->rs.len; break; case 3: /* Q */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->q = Q_UNSPECIFIED; break; } if(!(val->flags&PV_VAL_INT)) { LM_ERR("int value required to set branch q\n"); return -1; } br->q = val->ri; break; case 4: /* send socket */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->force_send_socket = NULL; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch send sock\n"); return -1; } if(val->rs.len<=0) { br->force_send_socket = NULL; break; } backup = val->rs.s[val->rs.len]; val->rs.s[val->rs.len] = '\0'; if (parse_phostport(val->rs.s, &host.s, &host.len, &port, &proto) < 0) { LM_ERR("invalid socket specification\n"); val->rs.s[val->rs.len] = backup; return -1; } val->rs.s[val->rs.len] = backup; si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (si!=NULL) { br->force_send_socket = si; } else { LM_WARN("no socket found to match [%.*s]\n", val->rs.len, val->rs.s); br->force_send_socket = NULL; } break; case 5: /* count */ /* do nothing - cannot set the branch counter */ break; case 6: /* flags */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->flags = 0; break; } if(!(val->flags&PV_VAL_INT)) { LM_ERR("int value required to set branch flags\n"); return -1; } br->flags = val->ri; break; case 7: /* ruid */ /* do nothing - cannot set the ruid */ break; case 8: /* location_ua */ /* do nothing - cannot set the location_ua */ break; default: /* 0 - uri */ if(val==NULL || (val->flags&PV_VAL_NULL)) { if(btype==1) { memset(br, 0, sizeof(branch_t)); } else { drop_sip_branch(idx); } } else { if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch uri\n"); return -1; } if(val->rs.len<=0) { if(btype==1) { memset(br, 0, sizeof(branch_t)); } else { drop_sip_branch(idx); } } else { if (unlikely(val->rs.len > MAX_URI_SIZE - 1)) { LM_ERR("too long r-uri: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->uri, val->rs.s, val->rs.len); br->uri[val->rs.len] = 0; br->len = val->rs.len; } } } return 0; }
int add_node_info(node_info_t **new_info, cluster_info_t **cl_list, int *int_vals, char **str_vals) { char *host; int hlen, port; int proto; struct hostent *he; int cluster_id; cluster_info_t *cluster = NULL; struct timeval t; str st; str seed_flag = str_init(SEED_NODE_FLAG_STR); cluster_id = int_vals[INT_VALS_CLUSTER_ID_COL]; /* new_info is checked whether it is initialized or not in case of error, * so we have to initialize it as soon as possible */ *new_info = NULL; for (cluster = *cl_list; cluster && cluster->cluster_id != cluster_id; cluster = cluster->next) ; if (!cluster) { cluster = shm_malloc(sizeof *cluster); if (!cluster) { LM_ERR("no more shm memory\n"); goto error; } memset(cluster, 0, sizeof *cluster); cluster->cluster_id = cluster_id; cluster->next = *cl_list; if ((cluster->lock = lock_alloc()) == NULL) { LM_CRIT("Failed to allocate lock\n"); goto error; } if (!lock_init(cluster->lock)) { lock_dealloc(cluster->lock); LM_CRIT("Failed to init lock\n"); goto error; } *cl_list = cluster; } *new_info = shm_malloc(sizeof **new_info); if (!*new_info) { LM_ERR("no more shm memory\n"); goto error; } memset(*new_info, 0, sizeof **new_info); (*new_info)->flags = 0; (*new_info)->id = int_vals[INT_VALS_ID_COL]; (*new_info)->node_id = int_vals[INT_VALS_NODE_ID_COL]; if (int_vals[INT_VALS_STATE_COL]) (*new_info)->flags |= NODE_STATE_ENABLED; else (*new_info)->flags &= ~NODE_STATE_ENABLED; if (int_vals[INT_VALS_NODE_ID_COL] != current_id) (*new_info)->link_state = LS_RESTART_PINGING; else (*new_info)->link_state = LS_UP; if (str_vals[STR_VALS_DESCRIPTION_COL] && strlen(str_vals[STR_VALS_DESCRIPTION_COL]) != 0) { (*new_info)->description.len = strlen(str_vals[STR_VALS_DESCRIPTION_COL]); (*new_info)->description.s = shm_malloc((*new_info)->description.len * sizeof(char)); if ((*new_info)->description.s == NULL) { LM_ERR("no more shm memory\n"); goto error; } memcpy((*new_info)->description.s, str_vals[STR_VALS_DESCRIPTION_COL], (*new_info)->description.len); } else { (*new_info)->description.s = NULL; (*new_info)->description.len = 0; } if (str_vals[STR_VALS_SIP_ADDR_COL] && strlen(str_vals[STR_VALS_SIP_ADDR_COL]) != 0) { (*new_info)->sip_addr.len = strlen(str_vals[STR_VALS_SIP_ADDR_COL]); (*new_info)->sip_addr.s = shm_malloc((*new_info)->sip_addr.len * sizeof(char)); if ((*new_info)->sip_addr.s == NULL) { LM_ERR("no more shm memory\n"); goto error; } memcpy((*new_info)->sip_addr.s, str_vals[STR_VALS_SIP_ADDR_COL], (*new_info)->sip_addr.len); } else { (*new_info)->sip_addr.s = NULL; (*new_info)->sip_addr.len = 0; } if (str_vals[STR_VALS_FLAGS_COL] && strlen(str_vals[STR_VALS_FLAGS_COL]) != 0) if (memcmp(str_vals[STR_VALS_FLAGS_COL], seed_flag.s, seed_flag.len) == 0) (*new_info)->flags |= NODE_IS_SEED; if (str_vals[STR_VALS_URL_COL] == NULL) { LM_ERR("no url specified in DB\n"); return 1; } (*new_info)->url.len = strlen(str_vals[STR_VALS_URL_COL]); (*new_info)->url.s = shm_malloc(strlen(str_vals[STR_VALS_URL_COL]) * sizeof(char)); if (!(*new_info)->url.s) { LM_ERR("no more shm memory\n"); goto error; } memcpy((*new_info)->url.s, str_vals[STR_VALS_URL_COL], (*new_info)->url.len); if (int_vals[INT_VALS_NODE_ID_COL] != current_id) { if (parse_phostport((*new_info)->url.s, (*new_info)->url.len, &host, &hlen, &port, &proto) < 0) { LM_ERR("Bad URL!\n"); return 1; } if (proto == PROTO_NONE) proto = clusterer_proto; if (proto != clusterer_proto) { LM_ERR("Clusterer currently supports only BIN protocol, but node: %d " "has proto=%d\n", int_vals[INT_VALS_NODE_ID_COL], proto); return 1; } st.s = host; st.len = hlen; he = sip_resolvehost(&st, (unsigned short *) &port, (unsigned short *)&proto, 0, 0); if (!he) { LM_ERR("Cannot resolve host: %.*s\n", hlen, host); return 1; } hostent2su(&((*new_info)->addr), he, 0, port); t.tv_sec = 0; t.tv_usec = 0; (*new_info)->last_ping = t; (*new_info)->last_pong = t; } (*new_info)->priority = int_vals[INT_VALS_PRIORITY_COL]; (*new_info)->no_ping_retries = int_vals[INT_VALS_NO_PING_RETRIES_COL]; (*new_info)->cluster = cluster; (*new_info)->ls_seq_no = -1; (*new_info)->top_seq_no = -1; (*new_info)->ls_timestamp = 0; (*new_info)->top_timestamp = 0; (*new_info)->sp_info = shm_malloc(sizeof(struct node_search_info)); if (!(*new_info)->sp_info) { LM_ERR("no more shm memory\n"); goto error; } (*new_info)->sp_info->node = *new_info; if (int_vals[INT_VALS_NODE_ID_COL] != current_id) { (*new_info)->next = cluster->node_list; cluster->node_list = *new_info; cluster->no_nodes++; if (cluster->no_nodes > MAX_NO_NODES) { LM_ERR("Defined: %d nodes for cluster: %d, maximum number of nodes " "supported(%d) exceeded\n", cluster->no_nodes, cluster->cluster_id, MAX_NO_NODES); goto error; } } else { (*new_info)->next = NULL; cluster->current_node = *new_info; } if (((*new_info)->lock = lock_alloc()) == NULL) { LM_CRIT("Failed to allocate lock\n"); goto error; } if (!lock_init((*new_info)->lock)) { lock_dealloc((*new_info)->lock); LM_CRIT("Failed to init lock\n"); goto error; } return 0; error: if (*new_info) { if ((*new_info)->sip_addr.s) shm_free((*new_info)->sip_addr.s); if ((*new_info)->description.s) shm_free((*new_info)->description.s); if ((*new_info)->url.s) shm_free((*new_info)->url.s); if ((*new_info)->sp_info) shm_free((*new_info)->sp_info); shm_free(*new_info); } return -1; }
static int add_uac_params(modparam_t type, void *val) { regmatch_t m[UAC_MAX_PARAMS_NO]; char *p, *line = (char *)val; char *_s; int _l; unsigned int size; uac_reg_map_t *uac_param; str host; int port, proto; if (!params_inited && init_params()) return -1; if (regexec(&uac_params_regex, line, UAC_MAX_PARAMS_NO, m, 0)) { LM_ERR("invalid param: %s\n", (char *)val); return -1; } LM_DBG("registrar=[%.*s] AOR=[%.*s] auth_user=[%.*s] password=[%.*s]" " expire=[%.*s] proxy=[%.*s] contact=[%.*s] third_party=[%.*s]\n", RXLS(m, line, UAC_REGISTRAR_URI_PARAM), RXLS(m, line, UAC_AOR_URI_PARAM), RXLS(m, line, UAC_AUTH_USER_PARAM), RXLS(m, line, UAC_AUTH_PASSWORD_PARAM), RXLS(m, line, UAC_EXPIRES_PARAM), RXLS(m, line, UAC_PROXY_URI_PARAM), RXLS(m, line, UAC_CONTACT_URI_PARAM), RXLS(m, line, UAC_THIRD_PARTY_REGISTRANT_URI_PARAM)); size = sizeof(uac_reg_map_t) + RXL(m, line, 0); uac_param = (uac_reg_map_t *)pkg_malloc(size); if (!uac_param) { LM_ERR("oom\n"); return -1; } memset(uac_param, 0, size); p = (char*)(uac_param + 1); RX_L_S(m, line, UAC_REGISTRAR_URI_PARAM); if (parse_uri(_s, _l, &uri)<0) { LM_ERR("cannot parse registrar uri [%.*s]\n", _l, _s); return -1; } if (uri.user.s && uri.user.len) { LM_ERR("registrant uri must not have user [%.*s]\n", uri.user.len, uri.user.s); return -1; } uac_param->registrar_uri.len = _l; uac_param->registrar_uri.s = p; memcpy(p, _s, _l); p += _l; RX_L_S(m, line, UAC_PROXY_URI_PARAM); if (_l != 0) { if (parse_uri(_s, _l, &uri)<0) { LM_ERR("cannot parse proxy uri [%.*s]\n", _l, _s); return -1; } if (uri.user.s && uri.user.len) { LM_ERR("proxy uri must not have user [%.*s]\n", uri.user.len, uri.user.s); return -1; } uac_param->proxy_uri.len = _l; uac_param->proxy_uri.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_AOR_URI_PARAM); if (parse_uri(_s, _l, &uri)<0) { LM_ERR("cannot parse aor uri [%.*s]\n", _l, _s); return -1; } uac_param->to_uri.len = _l; uac_param->to_uri.s = p; memcpy(p, _s, _l); p += _l; uac_param->hash_code = core_hash(&uac_param->to_uri, NULL, reg_hsize); RX_L_S(m, line, UAC_THIRD_PARTY_REGISTRANT_URI_PARAM); if (_l != 0) { if (parse_uri(_s, _l, &uri)<0) { LM_ERR("cannot parse third party registrant uri [%.*s]\n", _l, _s); return -1; } uac_param->from_uri.len = _l; uac_param->from_uri.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_CONTACT_URI_PARAM); if (parse_uri(_s, _l, &uri)<0) { LM_ERR("cannot parse contact uri [%.*s]\n", _l, _s); return -1; } uac_param->contact_uri.len = _l; uac_param->contact_uri.s = p; memcpy(p, _s, _l); p += _l; RX_L_S(m, line, UAC_AUTH_USER_PARAM); if (_l) { uac_param->auth_user.len = _l; uac_param->auth_user.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_AUTH_PASSWORD_PARAM); if (_l) { uac_param->auth_password.len = _l; uac_param->auth_password.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_CONTACT_PARAMS_PARAM); if (_l) { if (*p == ';') { LM_ERR("contact params must start with ';'\n"); return -1; } uac_param->contact_params.len = _l; uac_param->contact_params.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_EXPIRES_PARAM); if (_l) { uac_param->expires.len = _l; uac_param->expires.s = p; memcpy(p, _s, _l); p += _l; } RX_L_S(m, line, UAC_FORCED_SOCKET_PARAM); if (_l) { if (parse_phostport(_s, _l, &host.s, &host.len, &port, &proto)<0) { LM_ERR("cannot parse forced socket [%.*s]\n", _l, _s); return -1; } uac_param->send_sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); } if (uac_params) uac_param->next = uac_params; uac_params = uac_param; return 0; }
static int ul_contact_event_to_msg(struct sip_msg *req) { static enum ul_attrs { UL_URI, UL_RECEIVED, UL_PATH, UL_QVAL, UL_SOCKET, UL_BFLAGS, UL_ATTR, UL_MAX } ul_attr; /* keep the names of the AVPs aligned with the contact-related events * from USRLOC module !!!! */ static str ul_names[UL_MAX]= {str_init("uri"),str_init("received"), str_init("path"),str_init("qval"), str_init("socket"),str_init("bflags"), str_init("attr") }; static int avp_ids[UL_MAX] = { -1, -1, -1, -1, -1, -1, -1}; int_str vals[UL_MAX]; int proto, port; str host; str path_dst; if (avp_ids[0]==-1) { /* init the avp IDs mapping us on the UL event */ for( ul_attr=0 ; ul_attr<UL_MAX ; ul_attr++ ){ if (parse_avp_spec( &ul_names[ul_attr], &avp_ids[ul_attr])<0) { LM_ERR("failed to init UL AVP %d/%s\n", ul_attr,ul_names[ul_attr].s); avp_ids[0] = -1; return -1; } } } /* fetch the AVP values one by one */ for( ul_attr=0 ; ul_attr<UL_MAX ; ul_attr++ ) { if (search_first_avp(0, avp_ids[ul_attr], &vals[ul_attr], NULL)==NULL){ LM_ERR("cannot find AVP(%d) for event attr %d/%s\n", avp_ids[ul_attr], ul_attr, ul_names[ul_attr].s); return -1; } } /* OK, we have the values, lets inject them into the SIP msg */ LM_DBG("injecting new branch: uri=<%.*s>, received=<%.*s>," "path=<%.*s>, qval=%d, socket=<%.*s>, bflags=%X, attr=<%.*s>\n", vals[UL_URI].s.len, vals[UL_URI].s.s, vals[UL_RECEIVED].s.len, vals[UL_RECEIVED].s.s, vals[UL_PATH].s.len, vals[UL_PATH].s.s, vals[UL_QVAL].n, vals[UL_SOCKET].s.len, vals[UL_SOCKET].s.s, vals[UL_BFLAGS].n, vals[UL_ATTR].s.len, vals[UL_ATTR].s.s); /* contact URI goes as RURI */ if (set_ruri( req, &vals[UL_URI].s)<0) { LM_ERR("failed to set new RURI\n"); return -1; } /* contact PATH goes as path */ if (vals[UL_PATH].s.len) { if (get_path_dst_uri(&vals[UL_PATH].s, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); return -1; } if (set_dst_uri( req, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); return -1; } if (set_path_vector( req, &vals[UL_PATH].s)<0) { LM_ERR("failed to set PATH\n"); return -1; } } else /* contact RECEIVED goes as DURI */ if (vals[UL_RECEIVED].s.len) { if (set_dst_uri( req, &vals[UL_RECEIVED].s)<0) { LM_ERR("failed to set DST URI\n"); return -1; } } /* contact Qval goes as RURI Qval */ set_ruri_q( req, vals[UL_QVAL].n); /* contact BFLAGS goes as RURI bflags */ setb0flags( req, vals[UL_BFLAGS].n); /* socket info */ if (vals[UL_SOCKET].s.len) { if ( parse_phostport( vals[UL_SOCKET].s.s, vals[UL_SOCKET].s.len, &host.s, &host.len, &port, &proto) < 0) { LM_ERR("failed to parse socket from Event attr <%.*s>\n", vals[UL_SOCKET].s.len, vals[UL_SOCKET].s.s); } else { req->force_send_socket = grep_sock_info( &host, (unsigned short)port, (unsigned short)proto); } } return 0; }
/** * 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; /*init pkg mallocs (before parsing cfg or cmd line !)*/ if (init_pkg_mallocs()==-1) goto error00; init_route_lists(); /* process command line (get port no, cfg. file path etc) */ opterr=0; options="f:cCm:b:l:n:N:rRvdDETSVhw:t:u:g:P:G:W:o:"; 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 '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){ 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; } /* 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_POOL_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 %i Mb private memory per process\n", ((PKG_MEM_POOL_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; } /* 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 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 /* 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; }
/*! \brief */ static struct socket_info *get_sock_val(struct sip_msg *msg) { struct socket_info *sock; struct hdr_field *hf; str xsockname = str_init("socket"); sr_xavp_t *vavp = NULL; str socks; str hosts; int port; int proto; char c = 0; if(sock_hdr_name.len>0) { if (parse_headers( msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse message\n"); return 0; } for (hf=msg->headers; hf; hf=hf->next) { if (cmp_hdrname_str(&hf->name, &sock_hdr_name)==0) break; } /* hdr found? */ if (hf==0) return 0; trim_len( socks.len, socks.s, hf->body ); if (socks.len==0) return 0; /*FIXME: This is a hack */ c = socks.s[socks.len]; socks.s[socks.len] = '\0'; } else { /* xavp */ if(reg_xavp_cfg.s!=NULL) vavp = xavp_get_child_with_sval(®_xavp_cfg, &xsockname); if(vavp==NULL || vavp->val.v.s.len<=0) return 0; socks = vavp->val.v.s; } if (parse_phostport( socks.s, &hosts.s, &hosts.len, &port, &proto)!=0) { socks.s[socks.len] = c; LM_ERR("bad socket <%.*s> in \n", socks.len, socks.s); return 0; } if(sock_hdr_name.len>0 && c!=0) { socks.s[socks.len] = c; } sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto); if (sock==0) { LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s); return 0; } LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock ); return sock; }
int main(int argc, char** argv) { 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; /*init pkg mallocs (before parsing cfg or cmd line !)*/ if (init_pkg_mallocs()==-1) goto error; #ifdef DBG_MSG_QA fprintf(stderr, "WARNING: ser startup: " "DBG_MSG_QA enabled, ser may exit abruptly\n"); #endif /* process command line (get port no, cfg. file path etc) */ opterr=0; options= #ifdef STATS "s:" #endif "f:cm:b:l:n:N:rRvdDETVhw:t:u:g:P:G:i:x:"; while((c=getopt(argc,argv,options))!=-1){ switch(c){ case 'f': cfg_file=optarg; break; case 'c': config_check=1; log_stderr=1; /* force stderr logging */ break; case 's': #ifdef STATS stat_file=optarg; #endif break; case 'm': shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024; if (tmp &&(*tmp)){ fprintf(stderr, "bad shmem size number: -m %s\n", optarg); goto error; }; LOG(L_INFO, "ser: shared memory: %ld bytes\n", shm_mem_size ); break; case 'b': maxbuffer=strtol(optarg, &tmp, 10); if (tmp &&(*tmp)){ fprintf(stderr, "bad max buffer size number: -p %s\n", optarg); goto error; } break; case 'l': if (parse_phostport(optarg, &tmp, &tmp_len, &port, &proto)<0){ fprintf(stderr, "bad -l address specifier: %s\n", optarg); goto error; } 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){ fprintf(stderr, "failed to add new listen address\n"); goto error; } break; case 'n': children_no=strtol(optarg, &tmp, 10); if ((tmp==0) ||(*tmp)){ fprintf(stderr, "bad process number: -n %s\n", optarg); goto error; } break; case 'v': check_via=1; break; case 'r': received_dns|=DO_DNS; break; case 'R': received_dns|=DO_REV_DNS; case 'd': debug++; break; case 'D': dont_fork=1; break; case 'E': log_stderr=1; break; case 'T': #ifdef USE_TCP tcp_disable=1; #else fprintf(stderr,"WARNING: tcp support not compiled in\n"); #endif break; case 'N': #ifdef USE_TCP tcp_children_no=strtol(optarg, &tmp, 10); if ((tmp==0) ||(*tmp)){ fprintf(stderr, "bad process number: -N %s\n", optarg); goto error; } #else fprintf(stderr,"WARNING: 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 'i': fifo=optarg; break; case 'x': unixsock_name=optarg; break; case '?': if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c´.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x´.\n", optopt); goto error; case ':': fprintf(stderr, "Option `-%c´ requires an argument.\n", optopt); goto error; default: abort(); } } /* 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){ fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file, strerror(errno)); goto error; } /* seed the prng */ /* try to use /dev/urandom if possible */ 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 */ LOG(L_WARN, "WARNING: could not read from /dev/urandom (%d)\n", errno); } DBG("read %u from /dev/urandom\n", seed); close(rfd); }else{ LOG(L_WARN, "WARNING: could not open /dev/urandom (%d)\n", errno); } seed+=getpid()+time(0); DBG("seeding PRNG with %u\n", seed); srand(seed); DBG("test random number %u\n", rand()); /* register a diagnostic FIFO command - moved to fifo server - bogdan if (register_core_fifo()<0) { LOG(L_CRIT, "unable to register core FIFO commands\n"); goto error; }*/ /*register builtin modules*/ register_builtin_modules(); yyin=cfg_stream; if ((yyparse()!=0)||(cfg_errors)){ fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors); goto error; } print_rl(); /* 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){ fprintf(stderr, "bad user name/uid number: -u %s\n", user); goto error; } } if (group){ if (group2gid(&gid, group)<0){ fprintf(stderr, "bad group name/gid number: -u %s\n", group); goto error; } } /* fix sock/fifo uid/gid */ if (sock_user){ if (user2uid(&sock_uid, 0, sock_user)<0){ fprintf(stderr, "bad socket user name/uid number %s\n", user); goto error; } } if (sock_group){ if (group2gid(&sock_gid, sock_group)<0){ fprintf(stderr, "bad group name/gid number: -u %s\n", group); goto error; } } if (fix_all_socket_lists()!=0){ fprintf(stderr, "failed to initialize list addresses\n"); goto error; } /* 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){ fprintf(stderr, "WARNING: no fork mode %s\n", (udp_listen)?( (udp_listen->next)?" and more than one listen address found" "(will use only the the first one)":"" ):"and no udp listen address found" ); } if (config_check){ fprintf(stderr, "config file ok, exiting...\n"); goto error; } /*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){ LOG(L_CRIT, "could not initialize timer, exiting...\n"); goto error; } #ifdef USE_TCP if (!tcp_disable){ /*init tcp*/ if (init_tcp()<0){ LOG(L_CRIT, "could not initialize tcp, exiting...\n"); goto error; } } #ifdef USE_TLS if (!tls_disable){ /* init tls*/ if (init_tls()<0){ LOG(L_CRIT, "could not initialize tls, exiting...\n"); goto error; } } #endif /* USE_TLS */ #endif /* USE_TCP */ /* init_daemon? */ if (!dont_fork){ if ( daemonize(argv[0]) <0 ) goto error; } if (install_sigs() != 0){ fprintf(stderr, "ERROR: could not install the signal handlers\n"); goto error; } /*alloc pids*/ #ifdef SHM_MEM pt=shm_malloc(sizeof(struct process_table)*process_count()); #else pt=pkg_malloc(sizeof(struct process_table)*process_count()); #endif if (pt==0){ fprintf(stderr, "ERROR: out of memory\n"); goto error; } memset(pt, 0, sizeof(struct process_table)*process_count()); if (disable_core_dump) set_core_dump(0, 0); else set_core_dump(1, shm_mem_size+PKG_MEM_POOL_SIZE+4*1024*1024); if (open_files_limit>0){ if(increase_open_fds(open_files_limit)<0){ fprintf(stderr, "ERROR: error could not increase file limits\n"); goto error; } } if (init_modules() != 0) { fprintf(stderr, "ERROR: error while initializing modules\n"); goto error; } /* fix routing lists */ if ( (r=fix_rls())!=0){ fprintf(stderr, "ERROR: error %d while trying to fix configuration\n", r); goto error; }; #ifdef STATS if (init_stats( dont_fork ? 1 : children_no )==-1) goto error; #endif ret=main_loop(); /*kill everything*/ kill_all_children(SIGTERM); /*clean-up*/ cleanup(0); return ret; error: /*kill everything*/ kill_all_children(SIGTERM); /*clean-up*/ cleanup(0); return -1; }
/* returns 0 if ok, <0 on error */ static int fix_actions(struct action* a) { struct action *t; int ret; cmd_export_t* cmd; struct hostent* he; struct ip_addr ip; struct socket_info* si; str host; int proto=PROTO_NONE, port; struct proxy_l *p; struct bl_head *blh; if (a==0){ LM_CRIT("null pointer\n"); return E_BUG; } for(t=a; t!=0; t=t->next){ switch(t->type){ case FORWARD_T: if (t->elem[0].type==NOSUBTYPE) break; case SEND_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("invalid type %d (should be string)\n", t->type); return E_BUG; } ret = parse_phostport( t->elem[0].u.string, strlen(t->elem[0].u.string), &host.s, &host.len, &port, &proto); if (ret!=0) { LM_ERR("ERROR:fix_actions: FORWARD/SEND bad " "argument\n"); return E_CFG; } p = add_proxy( &host,(unsigned short)port, proto); if (p==0) { LM_ERR("forward/send failed to add proxy"); return E_CFG; } t->elem[0].type = PROXY_ST; t->elem[0].u.data = (void*)p; break; case IF_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for if (should be expr)\n", t->elem[0].type); return E_BUG; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {...} (should be" "action)\n", t->elem[1].type); return E_BUG; }else if( (t->elem[2].type!=ACTIONS_ST) &&(t->elem[2].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {} else{...}(should" "be action)\n", t->elem[2].type); return E_BUG; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){ if((ret=fix_actions((struct action*)t->elem[2].u.data))<0) return ret; } break; case WHILE_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for while (should be expr)\n", t->elem[0].type); return E_BUG; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for while() {...} (should be" "action)\n", t->elem[1].type); return E_BUG; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case SWITCH_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case CASE_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case DEFAULT_T: if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0) return ret; } break; case MODULE_T: cmd = (cmd_export_t*)t->elem[0].u.data; LM_DBG("fixing %s, line %d\n", cmd->name, t->line); if (cmd->fixup){ if (cmd->param_no>0){ ret=cmd->fixup(&t->elem[1].u.data, 1); t->elem[1].type=MODFIXUP_ST; if (ret<0) goto error; } if (cmd->param_no>1){ ret=cmd->fixup(&t->elem[2].u.data, 2); t->elem[2].type=MODFIXUP_ST; if (ret<0) goto error; } if (cmd->param_no==0){ ret=cmd->fixup( 0, 0); if (ret<0) goto error; } } break; case FORCE_SEND_SOCKET_T: if (t->elem[0].type!=SOCKID_ST){ LM_CRIT("invalid subtype %d for force_send_socket\n", t->elem[0].type); return E_BUG; } he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0); if (he==0){ LM_ERR(" could not resolve %s\n", ((struct socket_id*)t->elem[0].u.data)->name); ret = E_BAD_ADDRESS; goto error; } hostent2ip_addr(&ip, he, 0); si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port, ((struct socket_id*)t->elem[0].u.data)->proto); if (si==0){ LM_ERR("bad force_send_socket" " argument: %s:%d (ser doesn't listen on it)\n", ((struct socket_id*)t->elem[0].u.data)->name, ((struct socket_id*)t->elem[0].u.data)->port); ret = E_BAD_ADDRESS; goto error; } t->elem[0].u.data=si; t->elem[0].type=SOCKETINFO_ST; break; case SET_DEBUG_T: if (t->elem[0].type==NOSUBTYPE) break; if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("fix_actions: BUG in setdebug() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } /* normalize the value */ if (t->elem[0].u.number>L_DBG) t->elem[0].u.number = L_DBG; else if (t->elem[0].u.number<L_ALERT) t->elem[0].u.number = L_ALERT; break; case SETFLAG_T: case RESETFLAG_T: case ISFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } if (!flag_in_range( t->elem[0].u.number )) { ret=E_CFG; goto error; } break; case SETSFLAG_T: case RESETSFLAG_T: case ISSFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } t->elem[0].u.number = fixup_flag( t->elem[0].u.number ); if (t->elem[0].u.data==0) { ret=E_CFG; goto error; } break; case SETBFLAG_T: case RESETBFLAG_T: case ISBFLAGSET_T: if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) { LM_CRIT("bad xxxbflag() type " "%d,%d\n", t->elem[0].type, t->elem[0].type); ret=E_BUG; goto error; } t->elem[1].u.number = fixup_flag( t->elem[1].u.number ); if (t->elem[1].u.data==0) { ret=E_CFG; goto error; } break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: if (t->elem[1].u.data){ if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0) return ret; } break; case USE_BLACKLIST_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("bad USE_BLACKLIST type %d\n", t->elem[0].type); ret=E_BUG; goto error; } host.s = t->elem[0].u.string; host.len = strlen(host.s); blh = get_bl_head_by_name(&host); if (blh==NULL) { LM_ERR("USE_BLACKLIST - list " "%s not configured\n", t->elem[0].u.string); ret=E_CFG; goto error; } t->elem[0].type = BLACKLIST_ST; t->elem[0].u.data = blh; break; } } return 0; error: LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line); return ret; }
/* Encode branch info from str */ static inline int decode_branch_info(char *info, str *uri, str *dst, str *path, struct socket_info **sock, unsigned int *flags) { str s, host; int port, proto; char *pos, *at, *tmp; if (info == NULL) { ERR("decode_branch_info: Invalid input string.\n"); return 0; } /* Reset or return arguments to sane defaults */ uri->s = 0; uri->len = 0; dst->s = 0; dst->len = 0; path->s = 0; path->len = 0; *sock = NULL; *flags = 0; /* Make sure that we have at least a non-empty URI string, it is fine if * everything else is missing, but we need at least the URI. */ uri->s = info; if ((pos = strchr(info, '\n')) == NULL) { uri->len = strlen(info); /* We don't even have the URI string, this is bad, report an * error. */ if (uri->len == 0) goto uri_missing; return 1; } uri->len = pos - info; if (uri->len == 0) goto uri_missing; /* If we get here we have at least the branch URI, now try to parse as * much as you can. All output variable have been initialized above, so it * is OK if any of the fields are missing from now on. */ dst->s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { dst->len = strlen(dst->s); return 1; } dst->len = pos - at; path->s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { path->len = strlen(path->s); return 1; } path->len = pos - at; s.s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { /* No LF found, that means we take the string till the final zero * termination character and pass it directly to parse_phostport * without making a zero-terminated copy. */ tmp = s.s; s.len = strlen(s.s); } else { /* Our string is terminated by LF, so we need to make a * zero-terminated copy of the string before we pass it to * parse_phostport. */ s.len = pos - at; if ((tmp = as_asciiz(&s)) == NULL) { ERR("No memory left\n"); return 0; } } if (s.len) { if (parse_phostport(tmp, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("parsing of socket info <%s> failed\n", tmp); if (pos) pkg_free(tmp); return 0; } *sock = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (*sock == 0) { LM_ERR("invalid socket <%s>\n", tmp); if (pos) pkg_free(tmp); return 0; } } if (pos) pkg_free(tmp); else return 1; s.s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) s.len = strlen(s.s); else s.len = pos - s.s; if (s.len) { if (str2int(&s, flags) != 0) { LM_ERR("failed to decode flags <%.*s>\n", STR_FMT(&s)); return 0; } } return 1; uri_missing: ERR("decode_branch_info: Cannot decode branch URI.\n"); return 0; }
int load_reg_info_from_db(unsigned int plist) { db_res_t * res = NULL; db_val_t * values; db_row_t * rows; int i, nr_rows, ret; unsigned int n_result_cols = 0; unsigned int registrar_col; unsigned int proxy_col; unsigned int aor_col; unsigned int third_party_registrant_col; unsigned int username_col; unsigned int password_col; unsigned int binding_URI_col; unsigned int binding_params_col; unsigned int expiry_col; unsigned int forced_socket_col; db_key_t q_cols[REG_TABLE_TOTAL_COL_NO]; char *p = NULL; int len = 0; str now = {NULL, 0}; struct sip_uri uri; str forced_socket, host; int port, proto; uac_reg_map_t uac_param; p = int2str((unsigned long)(time(0)), &len); if (p && len>0) { now.s = (char *)pkg_malloc(len); if(now.s) { memcpy(now.s, p, len); now.len = len; } else { LM_ERR("oom\n"); return -1; } } if(use_reg_table()) return -1; q_cols[registrar_col = n_result_cols++] = ®istrar_column; q_cols[proxy_col = n_result_cols++] = &proxy_column; q_cols[aor_col = n_result_cols++] = &aor_column; q_cols[third_party_registrant_col = n_result_cols++] = &third_party_registrant_column; q_cols[username_col = n_result_cols++] = &username_column; q_cols[password_col = n_result_cols++] = &password_column; q_cols[binding_URI_col = n_result_cols++] = &binding_URI_column; q_cols[binding_params_col = n_result_cols++] = &binding_params_column; q_cols[expiry_col = n_result_cols++] = &expiry_column; q_cols[forced_socket_col = n_result_cols++] = &forced_socket_column; /* select the whole tabel and all the columns */ if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { if(reg_dbf.query(reg_db_handle, 0, 0, 0, q_cols, 0, REG_TABLE_TOTAL_COL_NO, 0, 0) < 0) { LM_ERR("Error while querying (fetch) database\n"); return -1; } if(reg_dbf.fetch_result(reg_db_handle, &res, REG_FETCH_SIZE)<0){ LM_ERR("fetching rows failed\n"); return -1; } } else { if(reg_dbf.query(reg_db_handle, 0, 0, 0, q_cols, 0, REG_TABLE_TOTAL_COL_NO, 0, &res) < 0) { LM_ERR("Error while querying database\n"); return -1; } } nr_rows = RES_ROW_N(res); do { LM_INFO("loading [%i] records from db\n", nr_rows); rows = RES_ROWS(res); /* for every row/record */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values+registrar_col) || VAL_NULL(values+aor_col) || VAL_NULL(values+binding_URI_col)) { LM_ERR("columns [%.*s] or/and [%.*s] or/and [%.*s]" " cannot be null -> skipping\n", registrar_column.len, registrar_column.s, aor_column.len, aor_column.s, binding_URI_column.len, binding_URI_column.s); continue; } memset(&uac_param, 0, sizeof(uac_reg_map_t)); /* Get the registrar (mandatory parameter) */ uac_param.registrar_uri.s = (char*)values[registrar_col].val.string_val; if (uac_param.registrar_uri.s) uac_param.registrar_uri.len = strlen(uac_param.registrar_uri.s); else { LM_ERR("ignoring empty registrar\n"); continue; } if (parse_uri(uac_param.registrar_uri.s, uac_param.registrar_uri.len, &uri)<0) { LM_ERR("cannot parse registrar uri [%.*s]\n", uac_param.registrar_uri.len, uac_param.registrar_uri.s); continue; } if (uri.user.s && uri.user.len) { LM_ERR("registrant uri must not have user [%.*s]\n", uri.user.len, uri.user.s); continue; } /* Get the proxy */ uac_param.proxy_uri.s = (char*)values[proxy_col].val.string_val; if (uac_param.proxy_uri.s) uac_param.proxy_uri.len = strlen(uac_param.proxy_uri.s); if (uac_param.proxy_uri.len) { if (parse_uri(uac_param.proxy_uri.s, uac_param.proxy_uri.len, &uri)<0) { LM_ERR("cannot parse proxy uri [%.*s]\n", uac_param.proxy_uri.len, uac_param.proxy_uri.s); continue; } if (uri.user.s && uri.user.len) { LM_ERR("proxy uri must not have user [%.*s]\n", uri.user.len, uri.user.s); continue; } } else { uac_param.proxy_uri.s = NULL; } /* Get the AOR (mandatory parameter) */ uac_param.to_uri.s = (char*)values[aor_col].val.string_val; if (uac_param.to_uri.s) uac_param.to_uri.len = strlen(uac_param.to_uri.s); else { LM_ERR("ignoring empty AOR\n"); continue; } if (parse_uri(uac_param.to_uri.s,uac_param.to_uri.len,&uri)<0) { LM_ERR("cannot parse aor uri [%.*s]\n", uac_param.to_uri.len, uac_param.to_uri.s); continue; } uac_param.hash_code = core_hash(&uac_param.to_uri, NULL, reg_hsize); /* Get the third party registrant */ uac_param.from_uri.s = (char*)values[third_party_registrant_col].val.string_val; if (uac_param.from_uri.s) uac_param.from_uri.len = strlen(uac_param.from_uri.s); if (uac_param.from_uri.len) { if (parse_uri(uac_param.from_uri.s, uac_param.from_uri.len, &uri)<0) { LM_ERR("cannot parse third party registrant" " uri [%.*s]\n", uac_param.from_uri.len, uac_param.from_uri.s); continue; } } else { uac_param.from_uri.s = NULL; } /* Get the binding (manadatory parameter) */ uac_param.contact_uri.s = (char*)values[binding_URI_col].val.string_val; if (uac_param.contact_uri.s) uac_param.contact_uri.len = strlen(uac_param.contact_uri.s); else { LM_ERR("ignoring empty binding\n"); continue; } if (parse_uri(uac_param.contact_uri.s, uac_param.contact_uri.len, &uri)<0) { LM_ERR("cannot parse contact uri [%.*s]\n", uac_param.contact_uri.len, uac_param.contact_uri.s); continue; } /* Get the authentication user */ uac_param.auth_user.s = (char*)values[username_col].val.string_val; if (uac_param.auth_user.s) uac_param.auth_user.len = strlen(uac_param.auth_user.s); if (uac_param.auth_user.len == 0) uac_param.auth_user.s = NULL; /* Get the authentication password */ uac_param.auth_password.s = (char*)values[password_col].val.string_val; if (uac_param.auth_password.s) uac_param.auth_password.len = strlen(uac_param.auth_password.s); if (uac_param.auth_password.len == 0) uac_param.auth_password.s = NULL; /* Get the binding params */ uac_param.contact_params.s = (char*)values[binding_params_col].val.string_val; if (uac_param.contact_params.s) uac_param.contact_params.len = strlen(uac_param.contact_params.s); if (uac_param.contact_params.len == 0) uac_param.contact_params.s = NULL; /* Get the expiration param */ uac_param.expires = values[expiry_col].val.int_val; if (uac_param.expires <= timer_interval) { LM_ERR("Please decrease timer_interval=[%u]" " - requested expires=[%u] to small for AOR=[%.*s]\n", timer_interval, uac_param.expires, uac_param.to_uri.len, uac_param.to_uri.s); continue; } /* Get the socket */ if (values[forced_socket_col].val.string_val && (forced_socket.s = (char*)values[forced_socket_col].val.string_val)) { if((forced_socket.len = strlen(forced_socket.s))){ if (parse_phostport(forced_socket.s, forced_socket.len, &host.s, &host.len, &port, &proto)<0) { LM_ERR("cannot parse forced socket [%.*s]\n", forced_socket.len, forced_socket.s); continue; } uac_param.send_sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); if (uac_param.send_sock==NULL) { LM_ERR("invalid forced socket [%.*s]\n", forced_socket.len, forced_socket.s); continue; } } } LM_DBG("registrar=[%.*s] AOR=[%.*s] auth_user=[%.*s] " "password=[%.*s] expire=[%d] proxy=[%.*s] " "contact=[%.*s] third_party=[%.*s]\n", uac_param.registrar_uri.len, uac_param.registrar_uri.s, uac_param.to_uri.len, uac_param.to_uri.s, uac_param.auth_user.len, uac_param.auth_user.s, uac_param.auth_password.len, uac_param.auth_password.s, uac_param.expires, uac_param.proxy_uri.len, uac_param.proxy_uri.s, uac_param.contact_uri.len, uac_param.contact_uri.s, uac_param.from_uri.len, uac_param.from_uri.s); lock_get(®_htable[uac_param.hash_code].lock); ret = add_record(&uac_param, &now, plist); lock_release(®_htable[uac_param.hash_code].lock); if(ret<0) { LM_ERR("can't load registrant\n"); continue; } } /* any more data to be fetched ?*/ if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { if (reg_dbf.fetch_result(reg_db_handle, &res, REG_FETCH_SIZE)<0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); reg_dbf.free_result(reg_db_handle, res); if (now.s) pkg_free(now.s); return 0; error: reg_dbf.free_result(reg_db_handle, res); if (now.s) pkg_free(now.s); return -1; }
rt_data_t* dr_load_routing_info( db_func_t *dr_dbf, db_con_t* db_hdl, str *drd_table, str *drc_table, str* drr_table, int persistent_state) { int int_vals[5]; char * str_vals[6]; str tmp; db_key_t columns[10]; db_res_t* res; db_row_t* row; rt_info_t *ri; rt_data_t *rdata; tmrec_t *time_rec; int i,n; int no_rows = 10; int db_cols; struct socket_info *sock; str s_sock, host; int proto, port; res = 0; ri = 0; rdata = 0; /* init new data structure */ if ( (rdata=build_rt_data())==0 ) { LM_ERR("failed to build rdata\n"); goto error; } if (db_check_table_version(dr_dbf, db_hdl, drd_table, 6/*version*/ )!= 0) goto error; /* read the destinations */ if (dr_dbf->use_table( db_hdl, drd_table) < 0) { LM_ERR("cannot select table \"%.*s\"\n", drd_table->len,drd_table->s); goto error; } columns[0] = &id_drd_col; columns[1] = &gwid_drd_col; columns[2] = &address_drd_col; columns[3] = &strip_drd_col; columns[4] = &prefix_drd_col; columns[5] = &type_drd_col; columns[6] = &attrs_drd_col; columns[7] = &probe_drd_col; columns[8] = &sock_drd_col; if (persistent_state) { columns[9] = &state_drd_col; db_cols = 10; } else { db_cols = 9; } if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, db_cols, 0, 0 ) < 0) { LM_ERR("DB query failed\n"); goto error; } no_rows = estimate_available_rows( 4+32+15+4+32+4+128+4+32+4, db_cols); if (no_rows==0) no_rows = 10; if(dr_dbf->fetch_result(db_hdl, &res, no_rows )<0) { LM_ERR("Error fetching rows\n"); goto error; } } else { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, db_cols, 0, &res) < 0) { LM_ERR("DB query failed\n"); goto error; } } LM_DBG("%d records found in %.*s\n", RES_ROW_N(res), drd_table->len,drd_table->s); n = 0; do { for(i=0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* DB ID column */ check_val( id_drd_col, ROW_VALUES(row), DB_INT, 1, 0); int_vals[INT_VALS_ID_DRD_COL] = VAL_INT(ROW_VALUES(row)); /* GW ID column */ check_val( gwid_drd_col, ROW_VALUES(row)+1, DB_STRING, 1, 1); str_vals[STR_VALS_GWID_DRD_COL] = (char*)VAL_STRING(ROW_VALUES(row)+1); /* ADDRESS column */ check_val( address_drd_col, ROW_VALUES(row)+2, DB_STRING, 1, 1); str_vals[STR_VALS_ADDRESS_DRD_COL] = (char*)VAL_STRING(ROW_VALUES(row)+2); /* STRIP column */ check_val( strip_drd_col, ROW_VALUES(row)+3, DB_INT, 1, 0); int_vals[INT_VALS_STRIP_DRD_COL] = VAL_INT (ROW_VALUES(row)+3); /* PREFIX column */ check_val( prefix_drd_col, ROW_VALUES(row)+4, DB_STRING, 0, 0); str_vals[STR_VALS_PREFIX_DRD_COL] = (char*)VAL_STRING(ROW_VALUES(row)+4); /* TYPE column */ check_val( type_drd_col, ROW_VALUES(row)+5, DB_INT, 1, 0); int_vals[INT_VALS_TYPE_DRD_COL] = VAL_INT(ROW_VALUES(row)+5); /* ATTRS column */ check_val( attrs_drd_col, ROW_VALUES(row)+6, DB_STRING, 0, 0); str_vals[STR_VALS_ATTRS_DRD_COL] = (char*)VAL_STRING(ROW_VALUES(row)+6); /*PROBE_MODE column */ check_val( probe_drd_col, ROW_VALUES(row)+7, DB_INT, 1, 0); int_vals[INT_VALS_PROBE_DRD_COL] = VAL_INT(ROW_VALUES(row)+7); /*SOCKET column */ check_val( sock_drd_col, ROW_VALUES(row)+8, DB_STRING, 0, 0); if ( !VAL_NULL(ROW_VALUES(row)+8) && (s_sock.s=(char*)VAL_STRING(ROW_VALUES(row)+8))[0]!=0 ) { s_sock.len = strlen(s_sock.s); if (parse_phostport( s_sock.s, s_sock.len, &host.s, &host.len, &port, &proto)!=0){ LM_ERR("GW <%s>(%d): socket description <%.*s> " "is not valid -> ignoring socket\n", str_vals[STR_VALS_GWID_DRD_COL], int_vals[INT_VALS_ID_DRD_COL], s_sock.len,s_sock.s); sock = NULL; } else { sock = grep_sock_info( &host, port, proto); if (sock == NULL) { LM_ERR("GW <%s>(%d): socket <%.*s> is not local to" " OpenSIPS (we must listen on it) -> ignoring socket\n", str_vals[STR_VALS_GWID_DRD_COL], int_vals[INT_VALS_ID_DRD_COL], s_sock.len,s_sock.s); } } } else { sock = NULL; } /*STATE column */ if (persistent_state) { check_val( state_drd_col, ROW_VALUES(row)+9, DB_INT, 1, 0); int_vals[INT_VALS_STATE_DRD_COL] = VAL_INT(ROW_VALUES(row)+9); } else { int_vals[INT_VALS_STATE_DRD_COL] = 0; /* by default enabled */ } /* add the destinaton definition in */ if ( add_dst( rdata, str_vals[STR_VALS_GWID_DRD_COL], str_vals[STR_VALS_ADDRESS_DRD_COL], int_vals[INT_VALS_STRIP_DRD_COL], str_vals[STR_VALS_PREFIX_DRD_COL], int_vals[INT_VALS_TYPE_DRD_COL], str_vals[STR_VALS_ATTRS_DRD_COL], int_vals[INT_VALS_PROBE_DRD_COL], sock, int_vals[INT_VALS_STATE_DRD_COL] )<0 ) { LM_ERR("failed to add destination <%s>(%d) -> skipping\n", str_vals[STR_VALS_GWID_DRD_COL],int_vals[INT_VALS_ID_DRD_COL]); continue; } n++; } if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if(dr_dbf->fetch_result(db_hdl, &res, no_rows)<0) { LM_ERR( "fetching rows (1)\n"); goto error; } } else { break; } } while(RES_ROW_N(res)>0); dr_dbf->free_result(db_hdl, res); res = 0; /* read the carriers, if any */ if (dr_dbf->use_table( db_hdl, drc_table) < 0) { LM_ERR("cannot select table \"%.*s\"\n", drc_table->len,drc_table->s); goto error; } columns[0] = &id_drc_col; columns[1] = &cid_drc_col; columns[2] = &flags_drc_col; columns[3] = &gwlist_drc_col; columns[4] = &attrs_drc_col; if (persistent_state) { columns[5] = &state_drc_col; db_cols = 6; } else { db_cols = 5; } if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, db_cols, 0, 0 ) < 0) { LM_ERR("DB query failed\n"); goto error; } no_rows = estimate_available_rows( 4+4+32+64+64, db_cols); if (no_rows==0) no_rows = 10; if(dr_dbf->fetch_result(db_hdl, &res, no_rows)<0) { LM_ERR("Error fetching rows\n"); goto error; } } else { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, db_cols, 0, &res) < 0) { LM_ERR("DB query failed\n"); goto error; } } if (RES_ROW_N(res) == 0) { LM_DBG("table \"%.*s\" empty\n", drc_table->len,drc_table->s ); } else { LM_DBG("%d records found in %.*s\n", RES_ROW_N(res), drc_table->len,drc_table->s); do { for(i=0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* ID column */ check_val( id_drc_col, ROW_VALUES(row), DB_INT, 1, 0); int_vals[INT_VALS_ID_DRC_COL] = VAL_INT(ROW_VALUES(row)); /* CARRIER_ID column */ check_val( cid_drc_col, ROW_VALUES(row)+1, DB_STRING, 1, 1); str_vals[STR_VALS_CID_DRC_COL] = (char*)VAL_STRING(ROW_VALUES(row)+1); /* flags column */ check_val( flags_drc_col, ROW_VALUES(row)+2, DB_INT, 1, 0); int_vals[INT_VALS_FLAGS_DRC_COL] = VAL_INT(ROW_VALUES(row)+2); /* GWLIST column */ check_val( gwlist_drc_col, ROW_VALUES(row)+3, DB_STRING, 1, 1); str_vals[STR_VALS_GWLIST_DRC_COL] = (char*)VAL_STRING(ROW_VALUES(row)+3); /* ATTRS column */ check_val( attrs_drc_col, ROW_VALUES(row)+4, DB_STRING, 0, 0); str_vals[STR_VALS_ATTRS_DRC_COL] = (char*)VAL_STRING(ROW_VALUES(row)+4); /* STATE column */ if (persistent_state) { check_val( state_drc_col, ROW_VALUES(row)+5, DB_INT, 1, 0); int_vals[INT_VALS_STATE_DRC_COL] = VAL_INT(ROW_VALUES(row)+5); } else { int_vals[INT_VALS_STATE_DRC_COL] = 0; /* by default enabled */ } /* add the new carrier */ if ( add_carrier( str_vals[STR_VALS_CID_DRC_COL], int_vals[INT_VALS_FLAGS_DRC_COL], str_vals[STR_VALS_GWLIST_DRC_COL], str_vals[STR_VALS_ATTRS_DRC_COL], int_vals[INT_VALS_STATE_DRC_COL], rdata) != 0 ) { LM_ERR("failed to add carrier db_id %d -> skipping\n", int_vals[INT_VALS_ID_DRC_COL]); continue; } } if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if(dr_dbf->fetch_result(db_hdl, &res, no_rows)<0) { LM_ERR( "fetching rows (1)\n"); goto error; } } else { break; } } while(RES_ROW_N(res)>0); } dr_dbf->free_result(db_hdl, res); res = 0; /* read the routing rules */ if (dr_dbf->use_table( db_hdl, drr_table) < 0) { LM_ERR("cannot select table \"%.*s\"\n", drr_table->len, drr_table->s); goto error; } columns[0] = &rule_id_drr_col; columns[1] = &group_drr_col; columns[2] = &prefix_drr_col; columns[3] = &time_drr_col; columns[4] = &priority_drr_col; columns[5] = &routeid_drr_col; columns[6] = &dstlist_drr_col; columns[7] = &attrs_drr_col; if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 8, 0, 0) < 0) { LM_ERR("DB query failed\n"); goto error; } no_rows = estimate_available_rows( 4+32+32+128+32+64+128, 8/*cols*/); if (no_rows==0) no_rows = 10; if(dr_dbf->fetch_result(db_hdl, &res, no_rows)<0) { LM_ERR("Error fetching rows\n"); goto error; } } else { if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 8, 0, &res) < 0) { LM_ERR("DB query failed\n"); goto error; } } if (RES_ROW_N(res) == 0) { LM_WARN("table \"%.*s\" is empty\n", drr_table->len, drr_table->s); } LM_DBG("initial %d records found in %.*s\n", RES_ROW_N(res), drr_table->len, drr_table->s); n = 0; do { for(i=0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* RULE_ID column */ check_val( rule_id_drr_col, ROW_VALUES(row), DB_INT, 1, 0); int_vals[INT_VALS_RULE_ID_DRR_COL] = VAL_INT (ROW_VALUES(row)); /* GROUP column */ check_val( group_drr_col, ROW_VALUES(row)+1, DB_STRING, 1, 1); str_vals[STR_VALS_GROUP_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+1); /* PREFIX column - it may be null or empty */ check_val( prefix_drr_col, ROW_VALUES(row)+2, DB_STRING, 0, 0); if ((ROW_VALUES(row)+2)->nul || VAL_STRING(ROW_VALUES(row)+2)==0){ tmp.s = NULL; tmp.len = 0; } else { str_vals[STR_VALS_PREFIX_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+2); tmp.s = str_vals[STR_VALS_PREFIX_DRR_COL]; tmp.len = strlen(str_vals[STR_VALS_PREFIX_DRR_COL]); } /* TIME column */ check_val( time_drr_col, ROW_VALUES(row)+3, DB_STRING, 0, 0); str_vals[STR_VALS_TIME_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+3); /* PRIORITY column */ check_val( priority_drr_col, ROW_VALUES(row)+4, DB_INT, 1, 0); int_vals[INT_VALS_PRIORITY_DRR_COL] = VAL_INT (ROW_VALUES(row)+4); /* ROUTE_ID column */ check_val( routeid_drr_col, ROW_VALUES(row)+5, DB_STRING, 0, 0); str_vals[STR_VALS_ROUTEID_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+5); /* DSTLIST column */ check_val( dstlist_drr_col, ROW_VALUES(row)+6, DB_STRING, 1, 1); str_vals[STR_VALS_DSTLIST_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+6); /* ATTRS column */ check_val( attrs_drr_col, ROW_VALUES(row)+7, DB_STRING, 0, 0); str_vals[STR_VALS_ATTRS_DRR_COL] = (char*)VAL_STRING(ROW_VALUES(row)+7); /* parse the time definition */ if (str_vals[STR_VALS_TIME_DRR_COL] == NULL || *(str_vals[STR_VALS_TIME_DRR_COL]) == 0) time_rec = NULL; else if ((time_rec=parse_time_def(str_vals[STR_VALS_TIME_DRR_COL]))==0) { LM_ERR("bad time definition <%s> for rule id %d -> skipping\n", str_vals[STR_VALS_TIME_DRR_COL], int_vals[INT_VALS_RULE_ID_DRR_COL]); continue; } /* lookup for the script route ID */ if (str_vals[STR_VALS_ROUTEID_DRR_COL] && str_vals[STR_VALS_ROUTEID_DRR_COL][0]) { int_vals[INT_VALS_SCRIPT_ROUTE_ID] = get_script_route_ID_by_name( str_vals[STR_VALS_ROUTEID_DRR_COL], rlist, RT_NO); if (int_vals[INT_VALS_SCRIPT_ROUTE_ID]==-1) { LM_WARN("route <%s> does not exist\n", str_vals[STR_VALS_ROUTEID_DRR_COL]); int_vals[INT_VALS_SCRIPT_ROUTE_ID] = 0; } } else { int_vals[INT_VALS_SCRIPT_ROUTE_ID] = 0; } /* build the routing rule */ if ((ri = build_rt_info( int_vals[INT_VALS_RULE_ID_DRR_COL], int_vals[INT_VALS_PRIORITY_DRR_COL], time_rec, int_vals[INT_VALS_SCRIPT_ROUTE_ID], str_vals[STR_VALS_DSTLIST_DRR_COL], str_vals[STR_VALS_ATTRS_DRR_COL], rdata))== 0 ) { LM_ERR("failed to add routing info for rule id %d -> " "skipping\n", int_vals[INT_VALS_RULE_ID_DRR_COL]); tmrec_free( time_rec ); continue; } /* add the rule */ if (add_rule( rdata, str_vals[STR_VALS_GROUP_DRR_COL], &tmp, ri)!=0) { LM_ERR("failed to add rule id %d -> skipping\n", int_vals[INT_VALS_RULE_ID_DRR_COL]); free_rt_info( ri ); continue; } n++; } if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) { if(dr_dbf->fetch_result(db_hdl, &res, no_rows)<0) { LM_ERR( "fetching rows (1)\n"); goto error; } LM_DBG("additional %d records found in %.*s\n", RES_ROW_N(res), drr_table->len, drr_table->s); } else { break; } } while(RES_ROW_N(res)>0); dr_dbf->free_result(db_hdl, res); res = 0; LM_DBG("%d total records loaded from table %.*s\n", n, drr_table->len, drr_table->s); return rdata; error: if (res) dr_dbf->free_result(db_hdl, res); if (rdata) free_rt_data( rdata, 1 ); rdata = NULL; return 0; }
/* add a new information in the backend list*/ int add_info(table_entry_t **data, int *int_vals, unsigned long last_attempt, char **str_vals) { char *host; int hlen, port; struct hostent *he; struct module_list *module; struct module_timestamp *new_timestamp; uint64_t ctime; int proto; int cluster_id; table_entry_t *head = NULL; table_entry_info_t *info_head = NULL; table_entry_value_t *value = NULL; str st; char *url; char *description; if (int_vals[INT_VALS_MACHINE_ID_COL] == server_id) { return 0; } url = str_vals[STR_VALS_URL_COL]; if (url == NULL) { LM_ERR("no path specified\n"); goto error; } if (parse_phostport(url, strlen(url), &host, &hlen, &port, &proto) < 0) { LM_ERR("Bad replication destination IP!\n"); goto error; } if (proto == PROTO_NONE) proto = PROTO_UDP; cluster_id = int_vals[INT_VALS_CLUSTER_ID_COL]; for (head = *data; head; head = head->next) { if (head->cluster_id == cluster_id) { info_head = head->info; while (info_head && info_head->proto != proto) info_head = info_head->next; if (!info_head) { info_head = shm_malloc(sizeof *info_head); if (!info_head) { LM_ERR("no more shm memory\n"); goto error; } info_head->proto = proto; info_head->next = head->info; info_head->value = NULL; head->info = info_head; } break; } } if (!head) { head = shm_malloc(sizeof *head); if (!head) { LM_ERR("no more shm memory\n"); goto error; } head->cluster_id = cluster_id; head->info = shm_malloc(sizeof(table_entry_info_t)); if (!head->info) { LM_ERR("no more shm memory\n"); goto error; } head->info->proto = proto; head->info->next = NULL; head->info->value = NULL; info_head = head->info; info_head->proto = proto; head->next = *data; *data = head; } /* allocating memory*/ value = shm_malloc(sizeof *value); if (!value) { LM_ERR("no more shm memory\n"); goto error; } value->machine_id = int_vals[INT_VALS_MACHINE_ID_COL]; value->id = int_vals[INT_VALS_CLUSTERER_ID_COL]; value->state = int_vals[INT_VALS_STATE_COL]; value->last_attempt = last_attempt; value->duration = int_vals[INT_VALS_DURATION_COL]; value->failed_attempts = int_vals[INT_VALS_FAILED_ATTEMPTS_COL]; value->no_tries = int_vals[INT_VALS_NO_TRIES_COL]; value->dirty_bit = 0; value->prev_no_tries = -1; value->in_timestamps = NULL; description = str_vals[STR_VALS_DESCRIPTION_COL]; value->path.s = shm_malloc(strlen(url) * sizeof(char)); if (!value->path.s) { LM_ERR("insufficient shm memory\n"); goto error; } st.s = host; st.len = hlen; he = sip_resolvehost(&st, (unsigned short *) &port, (unsigned short *) &proto, 0, 0); if (!he) { LM_ERR("Cannot resolve host: %.*s\n", hlen, host); goto error; } hostent2su(&value->addr, he, 0, port); value->path.len = strlen(url); memcpy(value->path.s, url, value->path.len); if (strlen(description) != 0) { value->description.len = strlen(description); value->description.s = shm_malloc(value->description.len * sizeof(char)); if (value->description.s == NULL) { LM_ERR("no more shm memory\n"); goto error; } memcpy(value->description.s, description, value->description.len); } else { value->description.s = NULL; value->description.len = 0; } ctime = time(0); for (module = clusterer_modules; module; module = module->next) { if (cluster_id == module->accept_cluster_id && proto == module->proto) { new_timestamp = create_module_timestamp(ctime, module); if (new_timestamp == NULL) break; new_timestamp->next = value->in_timestamps; value->in_timestamps = new_timestamp; } } value->next = info_head->value; info_head->value = value; /* everything ok */ return 0; error: if (value) { if (value->description.s) shm_free(value->description.s); if (value->path.s) shm_free(value->path.s); shm_free(value); } if (info_head) { if (info_head->value == NULL) { if (head != NULL) head->info = head->info->next; shm_free(info_head); } } if (head) { if (head->info == NULL) { *tdata = (*tdata)->next; shm_free(head); } } return -1; }
static int receive_ucontact_update(bin_packet_t *packet) { static ucontact_info_t ci; static str d, aor, host, contact_str, callid, user_agent, path, attr, st, sock; udomain_t *domain; urecord_t *record; ucontact_t *contact; int port, proto; int rc; memset(&ci, 0, sizeof ci); bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } bin_pop_str(packet, &contact_str); bin_pop_str(packet, &callid); ci.callid = &callid; bin_pop_str(packet, &user_agent); ci.user_agent = &user_agent; bin_pop_str(packet, &path); ci.path = &path; bin_pop_str(packet, &attr); ci.attr = &attr; bin_pop_str(packet, &ci.received); bin_pop_str(packet, &ci.instance); bin_pop_str(packet, &st); memcpy(&ci.expires, st.s, sizeof ci.expires); bin_pop_str(packet, &st); memcpy(&ci.q, st.s, sizeof ci.q); bin_pop_str(packet, &sock); if (sock.s && sock.s[0]) { if (parse_phostport(sock.s, sock.len, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%.*s>\n", sock.len, sock.s); goto error; } ci.sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); if (!ci.sock) LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s); } else { ci.sock = NULL; } bin_pop_int(packet, &ci.cseq); bin_pop_int(packet, &ci.flags); bin_pop_int(packet, &ci.cflags); bin_pop_int(packet, &ci.methods); bin_pop_str(packet, &st); memcpy(&ci.last_modified, st.s, sizeof ci.last_modified); bin_pop_str(packet, &st); ci.packed_kv_storage = &st; if (skip_replicated_db_ops) ci.flags |= FL_MEM; lock_udomain(domain, &aor); /* failure in retrieving a urecord may be ok, because packet order in UDP * is not guaranteed, so update commands may arrive before inserts */ if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - create new record and contact" " (ci: '%.*s')\n", callid.len, callid.s); if (insert_urecord(domain, &aor, &record, 1) != 0) { LM_ERR("failed to insert urecord\n"); unlock_udomain(domain, &aor); goto error; } if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } else { rc = get_ucontact(record, &contact_str, &callid, ci.cseq + 1, &contact); if (rc == 1) { LM_INFO("contact '%.*s' not found, inserting new (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } else if (rc == 0) { if (update_ucontact(record, contact, &ci, 1) != 0) { LM_ERR("failed to update ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } } /* XXX: for -2 and -1, the master should have already handled these errors - so we can skip them - razvanc */ } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
static int receive_ucontact_insert(bin_packet_t *packet) { static ucontact_info_t ci; static str d, aor, host, contact_str, callid, user_agent, path, attr, st, sock; udomain_t *domain; urecord_t *record; ucontact_t *contact; int rc, port, proto; memset(&ci, 0, sizeof ci); bin_pop_str(packet, &d); bin_pop_str(packet, &aor); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } bin_pop_str(packet, &contact_str); bin_pop_str(packet, &st); memcpy(&ci.contact_id, st.s, sizeof ci.contact_id); bin_pop_str(packet, &callid); ci.callid = &callid; bin_pop_str(packet, &user_agent); ci.user_agent = &user_agent; bin_pop_str(packet, &path); ci.path = &path; bin_pop_str(packet, &attr); ci.attr = &attr; bin_pop_str(packet, &ci.received); bin_pop_str(packet, &ci.instance); bin_pop_str(packet, &st); memcpy(&ci.expires, st.s, sizeof ci.expires); bin_pop_str(packet, &st); memcpy(&ci.q, st.s, sizeof ci.q); bin_pop_str(packet, &sock); if (sock.s && sock.s[0]) { if (parse_phostport(sock.s, sock.len, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%.*s>\n", sock.len, sock.s); goto error; } ci.sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); if (!ci.sock) LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s); } else { ci.sock = NULL; } bin_pop_int(packet, &ci.cseq); bin_pop_int(packet, &ci.flags); bin_pop_int(packet, &ci.cflags); bin_pop_int(packet, &ci.methods); bin_pop_str(packet, &st); memcpy(&ci.last_modified, st.s, sizeof ci.last_modified); if (skip_replicated_db_ops) ci.flags |= FL_MEM; lock_udomain(domain, &aor); if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - creating new one " "(ci: '%.*s') \n", callid.len, callid.s); if (insert_urecord(domain, &aor, &record, 1) != 0) { LM_ERR("failed to insert new record\n"); unlock_udomain(domain, &aor); goto error; } } rc = get_ucontact(record, &contact_str, &callid, ci.cseq, &contact); switch (rc) { case -2: /* received data is consistent with what we have */ case -1: /* received data is older than what we have */ break; case 0: /* received data is newer than what we have */ if (update_ucontact(record, contact, &ci, 1) != 0) { LM_ERR("failed to update ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } break; case 1: if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } break; } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
/** * init module function */ static int mod_init(void) { LM_DBG("initializing ...\n"); if (check_if_default_head_is_ok()) { default_db_head.next = ds_db_heads; ds_db_heads = &default_db_head; } set_default_head_values(&default_db_head); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_sock_col.len = strlen(ds_dest_sock_col.s); ds_dest_state_col.len = strlen(ds_dest_state_col.s); ds_dest_weight_col.len = strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); if(hash_pvar_param.s && (hash_pvar_param.len=strlen(hash_pvar_param.s))>0){ if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s && (ds_setid_pvname.len=strlen(ds_setid_pvname.s))>0){ if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } pvar_algo_param.len = strlen(pvar_algo_param.s); if (pvar_algo_param.len) ds_pvar_parse_pattern(pvar_algo_param); if (init_ds_bls()!=0) { LM_ERR("failed to init DS blacklists\n"); return E_CFG; } /* Creating partitions from head */ ds_db_head_t *head_it = ds_db_heads; while (head_it){ if (inherit_from_default_head(head_it) != 0) return -1; ds_partition_t *partition = shm_malloc (sizeof(ds_partition_t)); if (partition_init(head_it, partition) != 0) return -1; partition->next = partitions; partitions = partition; if (init_ds_data(partition)!=0) { LM_ERR("failed to init DS data holder\n"); return -1; } /* open DB connection to load provisioning data */ if (init_ds_db(partition)!= 0) { LM_ERR("failed to init database support\n"); return -1; } /* do the actual data load */ if (ds_reload_db(partition)!=0) { LM_ERR("failed to load data from DB\n"); return -1; } /* close DB connection */ ds_disconnect_db(partition); ds_db_head_t *aux = head_it; /* We keep track of corespondig default parition */ if (head_it == &default_db_head) default_partition = partition; head_it = head_it->next; if (aux != &default_db_head) pkg_free(aux); } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); /* parse the list of reply codes to be counted as success */ if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes(&options_reply_codes_str,&options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } /* parse and look for the socket to ping from */ if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer("ds-pinger", ds_check_timer, NULL, ds_ping_interval, TIMER_FLAG_DELAY_ON_DELAY)<0) { LM_ERR("failed to register timer for probing!\n"); return -1; } } /* register timer to flush the state of destination back to DB */ if (ds_persistent_state && register_timer("ds-flusher", ds_flusher_routine, NULL, 30 , TIMER_FLAG_SKIP_ON_DELAY)<0) { LM_ERR("failed to register timer for DB flushing!\n"); return -1; } dispatch_evi_id = evi_publish_event(dispatcher_event); if (dispatch_evi_id == EVI_ERROR) LM_ERR("cannot register dispatcher event\n"); return 0; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; LM_DBG("initializing ...\n"); if (dst_avp_param.s) dst_avp_param.len = strlen(dst_avp_param.s); if (grp_avp_param.s) grp_avp_param.len = strlen(grp_avp_param.s); if (cnt_avp_param.s) cnt_avp_param.len = strlen(cnt_avp_param.s); if (attrs_avp_param.s) attrs_avp_param.len = strlen(attrs_avp_param.s); if (hash_pvar_param.s) hash_pvar_param.len = strlen(hash_pvar_param.s); if (ds_setid_pvname.s) ds_setid_pvname.len = strlen(ds_setid_pvname.s); if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes( &options_reply_codes_str, &options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } if(init_data()!= 0) return -1; if(ds_db_url.s) { ds_db_url.len = strlen(ds_db_url.s); ds_table_name.len = strlen(ds_table_name.s); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_flags_col.len = strlen(ds_dest_flags_col.s); ds_dest_weight_col.len= strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); if(init_ds_db()!= 0) { LM_ERR("could not initiate a connect to the database\n"); return -1; } } else { if(ds_load_list(dslistfile)!=0) { LM_ERR("no dispatching list loaded from file\n"); return -1; } else { LM_DBG("loaded dispatching list\n"); } } if (dst_avp_param.s && dst_avp_param.len > 0) { if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name,&dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } } else { dst_avp_name.n = 0; dst_avp_type = 0; } if (grp_avp_param.s && grp_avp_param.len > 0) { if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name,&grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } } else { grp_avp_name.n = 0; grp_avp_type = 0; } if (cnt_avp_param.s && cnt_avp_param.len > 0) { if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name,&cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } } else { cnt_avp_name.n = 0; cnt_avp_type = 0; } if (attrs_avp_param.s && attrs_avp_param.len > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name.n = 0; attrs_avp_type = 0; } if (hash_pvar_param.s && *hash_pvar_param.s) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s!=0) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer(ds_check_timer, NULL, ds_ping_interval)<0) { LM_ERR("failed to register timer for probing!\n"); return -1; } } return 0; }
/*! * \brief Apply DP-DDDS policy to current SIP message * * Apply DP-DDDS policy to current SIP message. This means * build a new destination URI from the policy AVP and export it * as AVP. Then in kamailio.cfg this new target AVP can be pushed * into the destination URI $duri * \param _msg SIP message * \param _s1 unused * \param _s2 unused * \return negative on failure, positive on succes */ int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) { str *domain; int_str val; struct usr_avp *avp; char duri[MAX_URI_SIZE]; str duri_str; int len, didsomething; char *at; /* pointer to current location inside duri */ str host; int port, proto; struct socket_info* si; if (!is_route_type(REQUEST_ROUTE)) { LM_ERR("unsupported route type\n"); return -1; } /* * set the send_socket */ /* search for send_socket AVP */ avp = search_first_avp(send_socket_avp_name_str, send_socket_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string send_socket_avp, " "return with error ...\n"); return -1; } LM_DBG("send_socket_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); /* parse phostport - AVP str val is asciiz */ /* FIXME: This code relies on the fact that the string value of an AVP * is zero terminated, which may or may not be true in the future */ if (parse_phostport(val.s.s, &(host.s), &(host.len), &port, &proto)) { LM_ERR("could not parse send_socket, return with error ...\n"); return -1; } si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto); if (si) { set_force_socket(_msg, si); } else { LM_WARN("could not find socket for" "send_socket '%.*s'\n", val.s.len, ZSW(val.s.s)); } } else { LM_DBG("send_socket_avp not found\n"); } /* * set the destination URI */ didsomething = 0; /* if no AVP is set, there is no need to set the DURI in the end */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("failed to parse R-URI\n"); return -1; } at = (char *)&(duri[0]); len = 0; if ( (len + 4) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add uri schema\n"); return -1; } memcpy(at, "sip:", 4); at = at + 4; len = len + 4; domain = &(_msg->parsed_uri.host); LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s)); /* search for prefix and add it to duri buffer */ avp = search_first_avp(domain_prefix_avp_name_str, domain_prefix_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n"); return -1; } LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); if ( (len + val.s.len +1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain prefix\n"); return -1; } memcpy(at, val.s.s, val.s.len); at = at + val.s.len; *at = '.'; at = at + 1; /* add . as delimiter between prefix and domain */ didsomething = 1; } else { LM_DBG("domain_prefix_avp not found\n"); } /* add domain to duri buffer */ avp = search_first_avp(domain_replacement_avp_name_str, domain_replacement_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_replacement_avp, return with" "error ...\n"); return -1; } LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s)); if ( (len + val.s.len +1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain replacement\n"); return -1; } memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("domain_replacement_avp not found, using original domain '" "%.*s'\n",domain->len, domain->s); if ( (len + domain->len) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain\n"); return -1; } memcpy(at, domain->s, domain->len); at = at + domain->len; } /* search for suffix and add it to duri buffer */ avp = search_first_avp(domain_suffix_avp_name_str, domain_suffix_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_suffix_avp,return with error .." "\n"); return -1; } LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); if ( (len + val.s.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain suffix\n"); return -1; } *at = '.'; at = at + 1; /* add . as delimiter between domain and suffix */ memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("domain_suffix_avp not found\n"); } /* search for port override and add it to duri buffer */ avp = search_first_avp(port_override_avp_name_str, port_override_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string port_override_avp, return with error ...\n"); return -1; } LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); /* We do not check if the port is valid */ if ( (len + val.s.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain suffix\n"); return -1; } *at = ':'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("port_override_avp not found, using original port\n"); if (_msg->parsed_uri.port.len) { LM_DBG("port found in RURI, reusing it for DURI\n"); if ( (len + _msg->parsed_uri.port.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to copy port\n"); return -1; } *at = ':'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len); at = at + _msg->parsed_uri.port.len; } else { LM_DBG("port not found in RURI, no need to copy it to DURI\n"); } } /* search for transport override and add it to duri buffer */ avp = search_first_avp(transport_override_avp_name_str, transport_override_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string transport_override_avp, " "return with error ...\n"); return -1; } LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s)); if ( (len + val.s.len + 11) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add transport override\n"); return -1; } /* add : as transport parameter to duri; NOTE: no checks if transport parameter is valid */ memcpy(at, ";transport=", 11); at = at + 11; memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("transport_override_avp not found, using original transport\n"); if (_msg->parsed_uri.transport.len) { LM_DBG("transport found in RURI, reusing it for DURI\n"); if ( (len + _msg->parsed_uri.transport.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to copy transport\n"); return -1; } *at = ';'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len; } else { LM_DBG("transport not found in RURI, no need to copy it to DURI\n"); } } /* write new target DURI into DURI */ if (didsomething == 0) { LM_DBG("no domainpolicy AVP set, no need to push new DURI\n"); return 2; } duri_str.s = (char *)&(duri[0]); duri_str.len = at - duri_str.s; LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s)); if(set_dst_uri(_msg, &duri_str)<0) { LM_ERR("failed to se dst uri\n"); return -1; } /* dst_uri changes, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ return 1; }
/*! * \brief Get all contacts from the database, in partitions if wanted * \see get_all_ucontacts * \param buf target buffer * \param len length of buffer * \param flags contact flags * \param part_idx part index * \param part_max maximal part * \return 0 on success, positive if buffer size was not sufficient, negative on failure */ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max) { static char query_buf[512]; static str query_str; struct socket_info *sock; unsigned int dbflags; db1_res_t* res = NULL; db_row_t *row; dlist_t *dom; char now_s[25]; int now_len; int port, proto; char *p; str addr; str path; str ruid; str host; unsigned int aorhash; int i; void *cp; int shortage, needed; if(ul_dbf.raw_query==NULL) { LM_WARN("DB raw query support is required, but not implemented\n"); return -1; } cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(addr.len); /* get the current time in DB format */ now_len = 25; if (db_time2str( time(0), now_s, &now_len)!=0) { LM_ERR("failed to print now time\n"); return -1; } aorhash = 0; for (dom = root; dom!=NULL ; dom=dom->next) { /* build query */ i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s," " %.*s, %.*s, %.*s from %s where %.*s > %.*s and" #ifdef ORACLE_USRLOC " bitand(%.*s, %d) = %d and mod(id, %u) = %u", #else " %.*s & %d = %d and id %% %u = %u", #endif received_col.len, received_col.s, contact_col.len, contact_col.s, sock_col.len, sock_col.s, cflags_col.len, cflags_col.s, path_col.len, path_col.s, ruid_col.len, ruid_col.s, dom->d->name->s, expires_col.len, expires_col.s, now_len, now_s, cflags_col.len, cflags_col.s, flags, flags, part_max, part_idx); if ( i>=sizeof(query_buf) ) { LM_ERR("DB query too long\n"); return -1; } query_str.s = query_buf; query_str.len = i; if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) { LM_ERR("raw_query failed\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || addr.s==0 || addr.s[0]==0 ) { /* contact */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } } addr.len = strlen(addr.s); /* path */ path.s = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){ path.s = NULL; path.len = 0; } else { path.len = strlen(path.s); } /* ruid */ ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5); if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){ ruid.s = NULL; ruid.len = 0; } else { ruid.len = strlen(ruid.s); } needed = (int)(sizeof(addr.len) + addr.len + sizeof(sock) + sizeof(dbflags) + sizeof(path.len) + path.len + sizeof(ruid.len) + ruid.len + sizeof(aorhash)); if (len < needed) { shortage += needed ; continue; } /* write received/contact */ memcpy(cp, &addr.len, sizeof(addr.len)); cp = (char*)cp + sizeof(addr.len); memcpy(cp, addr.s, addr.len); cp = (char*)cp + addr.len; /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...set to 0\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...set to 0\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &path.len, sizeof(path.len)); cp = (char*)cp + sizeof(path.len); /* copy path only if exist */ if(path.len){ memcpy(cp, path.s, path.len); cp = (char*)cp + path.len; } /* write ruid */ memcpy(cp, &ruid.len, sizeof(ruid.len)); cp = (char*)cp + sizeof(ruid.len); /* copy ruid only if exist */ if(ruid.len){ memcpy(cp, ruid.s, ruid.len); cp = (char*)cp + ruid.len; } /* aorhash not used for db-only records, but it is added * (as 0) to match the struct used for mem records */ memcpy(cp, &aorhash, sizeof(aorhash)); cp = (char*)cp + sizeof(aorhash); len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(addr.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
int b2b_entities_restore(void) { db_res_t *result= NULL; db_row_t *rows = NULL; db_val_t *row_vals= NULL; int i; dlg_leg_t leg, *new_leg; b2b_dlg_t dlg, *shm_dlg= NULL; unsigned int hash_index, local_index; int nr_rows; str* b2b_key; str sockinfo_str; str host; int port, proto; b2b_table htable; int type; int no_rows = 10; if(b2be_db == NULL) { LM_DBG("NULL database connection\n"); return 0; } if(b2be_dbf.use_table(b2be_db, &b2be_dbtable)< 0) { LM_ERR("sql use table failed\n"); return -1; } if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH)) { if(b2be_dbf.query(b2be_db,0,0,0,qcols, 0, DB_COLS_NO, 0, 0) < 0) { LM_ERR("Error while querying (fetch) database\n"); return -1; } no_rows = estimate_available_rows( DB_COLS_NO*128, DB_COLS_NO); if (no_rows==0) no_rows = 10; if(b2be_dbf.fetch_result(b2be_db,&result,no_rows)<0) { LM_ERR("fetching rows failed\n"); return -1; } } else { if (b2be_dbf.query (b2be_db, 0, 0, 0,qcols,0, DB_COLS_NO, 0, &result) < 0) { LM_ERR("querying presentity\n"); return -1; } } nr_rows = RES_ROW_N(result); do { LM_DBG("loading information from database %i records\n", nr_rows); rows = RES_ROWS(result); /* for every row */ for(i=0; i<nr_rows; i++) { row_vals = ROW_VALUES(rows +i); memset(&dlg, 0, sizeof(b2b_dlg_t)); type = row_vals[0].val.int_val; dlg.tag[1].s = (char*)row_vals[2].val.string_val; dlg.tag[1].len = dlg.tag[1].s?strlen(dlg.tag[1].s):0; dlg.callid.s = (char*)row_vals[3].val.string_val; dlg.callid.len = dlg.callid.s?strlen(dlg.callid.s):0; if(type == B2B_SERVER)/* extract hash and local index */ { htable = server_htable; if(b2b_parse_key(&dlg.tag[1], &hash_index, &local_index) < 0) { LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.tag[1].len, dlg.tag[1].s); goto error; } } else { htable = client_htable; if(b2b_parse_key(&dlg.callid, &hash_index, &local_index) < 0) { LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.callid.len, dlg.callid.s); goto error; } } dlg.id = local_index; dlg.state = row_vals[13].val.int_val; dlg.ruri.s = (char*)row_vals[4].val.string_val; dlg.ruri.len = dlg.ruri.s?strlen(dlg.ruri.s):0; dlg.from_uri.s = (char*)row_vals[5].val.string_val; dlg.from_uri.len = strlen(dlg.from_uri.s); dlg.from_dname.s = (char*)row_vals[6].val.string_val; dlg.from_dname.len = strlen(dlg.from_dname.s); dlg.to_uri.s = (char*)row_vals[7].val.string_val; dlg.to_uri.len = strlen(dlg.to_uri.s); dlg.to_dname.s = (char*)row_vals[8].val.string_val; dlg.to_dname.len = dlg.to_dname.s?strlen(dlg.to_dname.s):0; dlg.tag[0].s = (char*)row_vals[1].val.string_val; dlg.tag[0].len = dlg.tag[0].s?strlen(dlg.tag[0].s):0; dlg.cseq[0] = row_vals[14].val.int_val; dlg.cseq[1] = row_vals[15].val.int_val; dlg.route_set[0].s = (char*)row_vals[9].val.string_val; dlg.route_set[0].len = dlg.route_set[0].s?strlen(dlg.route_set[0].s):0; dlg.route_set[1].s = (char*)row_vals[10].val.string_val; dlg.route_set[1].len = dlg.route_set[1].s?strlen(dlg.route_set[1].s):0; dlg.contact[0].s = (char*)row_vals[19].val.string_val; dlg.contact[0].len = dlg.contact[0].s?strlen(dlg.contact[0].s):0; dlg.contact[1].s = (char*)row_vals[20].val.string_val; dlg.contact[1].len = dlg.contact[1].s?strlen(dlg.contact[1].s):0; dlg.last_method = row_vals[16].val.int_val; dlg.last_reply_code = row_vals[17].val.int_val; dlg.last_invite_cseq = row_vals[18].val.int_val; dlg.param.s = (char*)row_vals[12].val.string_val; dlg.param.len = strlen(dlg.param.s); sockinfo_str.s = (char*)row_vals[11].val.string_val; if(sockinfo_str.s) { sockinfo_str.len = strlen(sockinfo_str.s); if(sockinfo_str.len) { if (parse_phostport (sockinfo_str.s, sockinfo_str.len, &host.s, &host.len, &port, &proto )< 0) { LM_ERR("bad format for stored sockinfo string [%.*s]\n", sockinfo_str.len, sockinfo_str.s); goto error; } dlg.send_sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); } } dlg.db_flag = NO_UPDATEDB_FLAG; shm_dlg = b2b_dlg_copy(&dlg); if(shm_dlg == NULL) { LM_ERR("Failed to create new dialog structure\n"); goto error; } b2b_key= b2b_htable_insert(htable,shm_dlg,hash_index,type, 1); if(b2b_key == NULL) { LM_ERR("Failed to insert new record\n"); goto error; } pkg_free(b2b_key); memset(&leg, 0, sizeof(dlg_leg_t)); leg.tag.s= (char*)row_vals[21].val.string_val; if(!leg.tag.s) continue; leg.tag.len = strlen(leg.tag.s); leg.cseq = row_vals[22].val.int_val; leg.contact.s = (char*)row_vals[23].val.string_val; leg.contact.len = leg.contact.s?strlen(leg.contact.s):0; leg.route_set.s = (char*)row_vals[24].val.string_val; leg.route_set.len = leg.route_set.s?strlen(leg.route_set.s):0; new_leg = b2b_dup_leg(&leg, SHM_MEM_TYPE); if(new_leg== NULL) { LM_ERR("Failed to construct b2b leg structure\n"); goto error; } shm_dlg->legs = new_leg; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH)) { if (b2be_dbf.fetch_result( b2be_db, &result, no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(result); } else { nr_rows = 0; } }while (nr_rows>0); b2be_dbf.free_result(b2be_db, result); return 0; error: if(result) b2be_dbf.free_result(b2be_db, result); return -1; }
/*! \brief Adds the proxies in the proxy list & resolves the hostnames * \return 0 if ok, <0 on error */ static int fix_actions(struct action* a) { struct action *t; int ret; cmd_export_t* cmd; struct hostent* he; struct ip_addr ip; struct socket_info* si; str host; int proto=PROTO_NONE, port; struct proxy_l *p; struct bl_head *blh; int i; str s; pv_elem_t *model=NULL; pv_elem_t *models[5]; xl_level_p xlp; if (a==0){ LM_CRIT("null pointer\n"); return E_BUG; } for(t=a; t!=0; t=t->next){ switch(t->type){ case ROUTE_T: if (t->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in route() type %d\n", t->elem[0].type); ret = E_BUG; goto error; } if ((t->elem[0].u.number>RT_NO)||(t->elem[0].u.number<0)){ LM_ALERT("invalid routing table number in" "route(%lu)\n", t->elem[0].u.number); ret = E_CFG; goto error; } if ( rlist[t->elem[0].u.number].a==NULL ) { LM_ERR("called route %d is not defined\n", (int)t->elem[0].u.number); ret = E_CFG; goto error; } break; case FORWARD_T: if (sl_fwd_disabled>0) { LM_ERR("stateless forwarding disabled, but forward() " "is used!!\n"); ret = E_CFG; goto error; } sl_fwd_disabled = 0; if (t->elem[0].type==NOSUBTYPE) break; case SEND_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("invalid type %d (should be string)\n", t->type); ret = E_BUG; goto error; } ret = parse_phostport( t->elem[0].u.string, strlen(t->elem[0].u.string), &host.s, &host.len, &port, &proto); if (ret!=0) { LM_ERR("ERROR:fix_actions: FORWARD/SEND bad " "argument\n"); ret = E_CFG; goto error; } p = add_proxy( &host,(unsigned short)port, proto); if (p==0) { LM_ERR("forward/send failed to add proxy"); ret = E_CFG; goto error; } t->elem[0].type = PROXY_ST; t->elem[0].u.data = (void*)p; break; case IF_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for if (should be expr)\n", t->elem[0].type); ret = E_BUG; goto error; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {...} (should be" "action)\n", t->elem[1].type); ret = E_BUG; goto error; }else if( (t->elem[2].type!=ACTIONS_ST) &&(t->elem[2].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {} else{...}(should" "be action)\n", t->elem[2].type); ret = E_BUG; goto error; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){ if((ret=fix_actions((struct action*)t->elem[2].u.data))<0) return ret; } break; case WHILE_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for while (should be expr)\n", t->elem[0].type); ret = E_BUG; goto error; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for while() {...} (should be" "action)\n", t->elem[1].type); ret = E_BUG; goto error; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case SWITCH_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case CASE_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case DEFAULT_T: if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0) return ret; } break; case MODULE_T: cmd = (cmd_export_t*)t->elem[0].u.data; LM_DBG("fixing %s, line %d\n", cmd->name, t->line); if (cmd->fixup){ if (cmd->param_no==0){ ret=cmd->fixup( 0, 0); if (ret<0) goto error; } else { for (i=1; i<=cmd->param_no; i++) { ret=cmd->fixup(&t->elem[i].u.data, i); t->elem[i].type=MODFIXUP_ST; if (ret<0) goto error; } } } break; case FORCE_SEND_SOCKET_T: if (t->elem[0].type!=SOCKID_ST){ LM_CRIT("invalid subtype %d for force_send_socket\n", t->elem[0].type); ret = E_BUG; goto error; } he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0); if (he==0){ LM_ERR(" could not resolve %s\n", ((struct socket_id*)t->elem[0].u.data)->name); ret = E_BAD_ADDRESS; goto error; } hostent2ip_addr(&ip, he, 0); si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port, ((struct socket_id*)t->elem[0].u.data)->proto); if (si==0){ LM_ERR("bad force_send_socket" " argument: %s:%d (opensips doesn't listen on it)\n", ((struct socket_id*)t->elem[0].u.data)->name, ((struct socket_id*)t->elem[0].u.data)->port); ret = E_BAD_ADDRESS; goto error; } t->elem[0].u.data=si; t->elem[0].type=SOCKETINFO_ST; break; case SET_DEBUG_T: if (t->elem[0].type==NOSUBTYPE) break; if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("fix_actions: BUG in setdebug() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } /* normalize the value */ if (t->elem[0].u.number>L_DBG) t->elem[0].u.number = L_DBG; else if (t->elem[0].u.number<L_ALERT) t->elem[0].u.number = L_ALERT; break; case SETFLAG_T: case RESETFLAG_T: case ISFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } if (!flag_in_range( t->elem[0].u.number )) { ret=E_CFG; goto error; } break; case SETSFLAG_T: case RESETSFLAG_T: case ISSFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } t->elem[0].u.number = fixup_flag( t->elem[0].u.number ); if (t->elem[0].u.data==0) { ret=E_CFG; goto error; } break; case SETBFLAG_T: case RESETBFLAG_T: case ISBFLAGSET_T: if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) { LM_CRIT("bad xxxbflag() type " "%d,%d\n", t->elem[0].type, t->elem[0].type); ret=E_BUG; goto error; } t->elem[1].u.number = fixup_flag( t->elem[1].u.number ); if (t->elem[1].u.data==0) { ret=E_CFG; goto error; } break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: if (t->elem[1].u.data){ if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0) return ret; } break; case USE_BLACKLIST_T: case UNUSE_BLACKLIST_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("bad [UN]USE_BLACKLIST type %d\n",t->elem[0].type); ret=E_BUG; goto error; } host.s = t->elem[0].u.string; host.len = strlen(host.s); if ( strcasecmp(host.s,"all")==0 ) { blh = NULL; } else { blh = get_bl_head_by_name(&host); if (blh==NULL) { LM_ERR("[UN]USE_BLACKLIST - list " "%s not configured\n", t->elem[0].u.string); ret=E_CFG; goto error; } } t->elem[0].type = BLACKLIST_ST; t->elem[0].u.data = blh; break; case CACHE_STORE_T: case CACHE_FETCH_T: case CACHE_REMOVE_T: /* attr name */ s.s = (char*)t->elem[1].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param 2 is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); ret=E_BUG; goto error; } t->elem[1].u.data = (void*)model; if (t->type==CACHE_REMOVE_T) break; /* value */ if (t->type==CACHE_FETCH_T) { if(((pv_spec_p)t->elem[2].u.data)->type!= PVT_AVP) { LM_ERR("Wrong type for the third argument - " "must be an AVP\n"); ret=E_BUG; goto error; } } else { s.s = (char*)t->elem[2].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param 2 is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n",s.s); ret=E_BUG; goto error; } t->elem[2].u.data = (void*)model; } break; case XDBG_T: case XLOG_T: s.s = (char*)t->elem[1].u.data; if (s.s == NULL) { /* commands have only one parameter */ s.s = (char *)t->elem[0].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); ret=E_BUG; goto error; } t->elem[0].u.data = (void*)model; t->elem[0].type = SCRIPTVAR_ELEM_ST; } else { /* there are two parameters */ s.s = (char *)t->elem[0].u.data; s.len = strlen(s.s); if (s.len == 0) { LM_ERR("param is empty string\n"); return E_CFG; } xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t)); if(xlp == NULL) { LM_ERR("no more memory\n"); return E_UNSPEC; } memset(xlp, 0, sizeof(xl_level_t)); if(s.s[0]==PV_MARKER) { xlp->type = 1; if(pv_parse_spec(&s, &xlp->v.sp)==NULL) { LM_ERR("invalid level param\n"); return E_UNSPEC; } } else { xlp->type = 0; switch(s.s[2]) { case 'A': xlp->v.level = L_ALERT; break; case 'C': xlp->v.level = L_CRIT; break; case 'E': xlp->v.level = L_ERR; break; case 'W': xlp->v.level = L_WARN; break; case 'N': xlp->v.level = L_NOTICE; break; case 'I': xlp->v.level = L_INFO; break; case 'D': xlp->v.level = L_DBG; break; default: LM_ERR("unknown log level\n"); return E_UNSPEC; } } t->elem[0].u.data = xlp; s.s = t->elem[1].u.data; s.len = strlen(s.s); if (pv_parse_format(&s, &model) || model == NULL) { LM_ERR("wrong fomat [%s] for value param\n",s.s); ret=E_BUG; goto error; } t->elem[1].u.data = model; t->elem[1].type = SCRIPTVAR_ELEM_ST; } break; case CONSTRUCT_URI_T: for (i=0;i<5;i++) { s.s = (char*)t->elem[i].u.data; s.len = strlen(s.s); if(s.len==0) continue; if(pv_parse_format(&s ,&(models[i])) || models[i]==NULL) { LM_ERR("wrong format [%s] for value param!\n",s.s); ret=E_BUG; goto error; } t->elem[i].u.data = (void*)models[i]; } if (((pv_spec_p)t->elem[5].u.data)->type != PVT_AVP) { LM_ERR("Wrong type for the third argument - " "must be an AVP\n"); ret=E_BUG; goto error; } break; } } return 0; error: LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line); return ret; }