/** * 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; }
/*! \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; }
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 }
/* Actions are composed as follows: * (the action length and type as always= 5 bytes) * * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_sl_msg(as_p the_as,char *action,int len) { struct sip_msg *my_msg; str *uri; struct proxy_l *proxy; rr_t *my_route; int k,retval; unsigned int flags; enum sip_protos proto; my_msg=NULL; k=0; net2hostL(flags,action,k); k++; proxy=0; if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type == SIP_REQUEST) LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); else LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } my_route = (rr_t*)my_msg->route->parsed; uri=&(my_route->nameaddr.uri); }else{ uri = GET_RURI(my_msg); } my_msg->force_send_socket=grep_sock_info(&my_msg->via1->host,my_msg->via1->port,my_msg->via1->proto); /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; /* uri2proxy set it correctly */ //TODO my_msg->recvd if(0>forward_sl_request(my_msg,proxy,proto)) goto error; retval=0; goto exit; error: retval = -1; exit: if(proxy){ free_proxy(proxy); pkg_free(proxy); } if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
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 = strlen(dlg.ruri.s); 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 = strlen(dlg.to_dname.s); 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.contact.s = (char*)row_vals[23].val.string_val; leg.contact.len = leg.contact.s?strlen(leg.contact.s):0; leg.route_set.len = leg.route_set.s?strlen(leg.route_set.s):0; leg.cseq = row_vals[22].val.int_val; 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; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; str host; int port, proto; if(register_mi_mod(exports.name, mi_cmds)!=0) { LM_ERR("failed to register MI commands\n"); return -1; } if(ds_ping_active_init()<0) { return -1; } if(ds_init_rpc()<0) { LM_ERR("failed to register RPC commands\n"); return -1; } if(cfg_declare("dispatcher", dispatcher_cfg_def, &default_dispatcher_cfg, cfg_sizeof(dispatcher), &dispatcher_cfg)){ LM_ERR("Fail to declare the configuration\n"); return -1; } /* Initialize the counter */ ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*)); *ds_ping_reply_codes = 0; ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int)); *ds_ping_reply_codes_cnt = 0; if(ds_ping_reply_codes_str.s) { cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str) = ds_ping_reply_codes_str; if(ds_parse_reply_codes()< 0) { return -1; } } /* copy threshholds to config */ cfg_get(dispatcher, dispatcher_cfg, probing_threshold) = probing_threshold; cfg_get(dispatcher, dispatcher_cfg, inactive_threshold) = inactive_threshold; if (ds_default_socket.s && ds_default_socket.len > 0) { if (parse_phostport( ds_default_socket.s, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s); return -1; } ds_default_sockinfo = grep_sock_info( &host, (unsigned short)port, proto); if (ds_default_sockinfo==0) { LM_WARN("non-local socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s); return -1; } LM_INFO("default dispatcher socket set to <%.*s>\n", ds_default_socket.len, ds_default_socket.s); } if(init_data()!= 0) return -1; if(ds_db_url.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 (dstid_avp_param.s && dstid_avp_param.len > 0) { if (pv_parse_spec(&dstid_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dstid_avp_name, &dstid_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } } else { dstid_avp_name.n = 0; dstid_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 (sock_avp_param.s && sock_avp_param.len > 0) { 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; } } else { sock_avp_name.n = 0; sock_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; } } if(ds_attrs_pvname.s!=0) { if(pv_parse_spec(&ds_attrs_pvname, &ds_attrs_pv)==NULL || !pv_is_w(&ds_attrs_pv)) { LM_ERR("[%s]- invalid attrs_pvname\n", ds_attrs_pvname.s); return -1; } } if (dstid_avp_param.s && dstid_avp_param.len > 0) { if(ds_hash_size>0) { if(ds_hash_load_init(1<<ds_hash_size, ds_hash_expire, ds_hash_initexpire)<0) return -1; if(ds_timer_mode==1) { if(sr_wtimer_add(ds_ht_timer, NULL, ds_hash_check_interval)<0) return -1; } else { if(register_timer(ds_ht_timer, NULL, ds_hash_check_interval)<0) return -1; } } else { LM_ERR("call load dispatching DSTID_AVP set but no size" " for hash table (see ds_hash_size parameter)\n"); return -1; } } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { /***************************************************** * TM-Bindings *****************************************************/ if (load_tm_api( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /***************************************************** * Register the PING-Timer *****************************************************/ if(ds_timer_mode==1) { if(sr_wtimer_add(ds_check_timer, NULL, ds_ping_interval)<0) return -1; } else { if(register_timer(ds_check_timer, NULL, ds_ping_interval)<0) return -1; } } return 0; }
/*! * \brief Convert database values into ucontact_info * * Convert database values into ucontact_info, * expects 12 rows (contact, expirs, q, callid, cseq, flags, * ua, received, path, socket, methods, last_modified) * \param vals database values * \param contact contact * \return pointer to the ucontact_info on success, 0 on failure */ static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact) { static ucontact_info_t ci; static str callid, ua, received, host, path; int port, proto; char *p; memset( &ci, 0, sizeof(ucontact_info_t)); contact->s = (char*)VAL_STRING(vals); if (VAL_NULL(vals) || contact->s==0 || contact->s[0]==0) { LM_CRIT("bad contact\n"); return 0; } contact->len = strlen(contact->s); if (VAL_NULL(vals+1)) { LM_CRIT("empty expire\n"); return 0; } ci.expires = VAL_TIME(vals+1); if (VAL_NULL(vals+2)) { LM_CRIT("empty q\n"); return 0; } ci.q = double2q(VAL_DOUBLE(vals+2)); if (VAL_NULL(vals+4)) { LM_CRIT("empty cseq_nr\n"); return 0; } ci.cseq = VAL_INT(vals+4); callid.s = (char*)VAL_STRING(vals+3); if (VAL_NULL(vals+3) || !callid.s || !callid.s[0]) { LM_CRIT("bad callid\n"); return 0; } callid.len = strlen(callid.s); ci.callid = &callid; if (VAL_NULL(vals+5)) { LM_CRIT("empty flag\n"); return 0; } ci.flags = VAL_BITMAP(vals+5); if (VAL_NULL(vals+6)) { LM_CRIT("empty cflag\n"); return 0; } ci.cflags = VAL_BITMAP(vals+6); ua.s = (char*)VAL_STRING(vals+7); if (VAL_NULL(vals+7) || !ua.s || !ua.s[0]) { ua.s = 0; ua.len = 0; } else { ua.len = strlen(ua.s); } ci.user_agent = &ua; received.s = (char*)VAL_STRING(vals+8); if (VAL_NULL(vals+8) || !received.s || !received.s[0]) { received.len = 0; received.s = 0; } else { received.len = strlen(received.s); } ci.received = received; path.s = (char*)VAL_STRING(vals+9); if (VAL_NULL(vals+9) || !path.s || !path.s[0]) { path.len = 0; path.s = 0; } else { path.len = strlen(path.s); } ci.path= &path; /* socket name */ p = (char*)VAL_STRING(vals+10); if (VAL_NULL(vals+10) || p==0 || p[0]==0) { ci.sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>\n", p); return 0; } ci.sock = grep_sock_info( &host, (unsigned short)port, proto); if (ci.sock==0) { LM_INFO("non-local socket <%s>...ignoring\n", p); } } /* supported methods */ if (VAL_NULL(vals+11)) { ci.methods = ALL_METHODS; } else { ci.methods = VAL_BITMAP(vals+11); } /* last modified time */ if (!VAL_NULL(vals+12)) { ci.last_modified = VAL_TIME(vals+12); } /* record internal uid */ if (!VAL_NULL(vals+13)) { ci.ruid.s = (char*)VAL_STRING(vals+13); ci.ruid.len = strlen(ci.ruid.s); } /* sip instance */ if (!VAL_NULL(vals+14)) { ci.instance.s = (char*)VAL_STRING(vals+14); ci.instance.len = strlen(ci.instance.s); } /* reg-id */ if (!VAL_NULL(vals+15)) { ci.reg_id = VAL_UINT(vals+15); } return &ci; }
static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2) { struct dest_info dst; struct socket_info *si; struct dest_info* dst_fin = NULL; struct proxy_l * p=NULL /* make gcc happy */; void* buffer = NULL; union sockaddr_union from_su; union sockaddr_union to_su; unsigned int len, buflen, proto; struct hep_hdr hdr; struct hep_iphdr hep_ipheader; struct hep_timehdr hep_time; struct timeval tvb; struct timezone tz; struct hep_ip6hdr hep_ip6header; if(body->s==NULL || body->len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; gettimeofday( &tvb, &tz ); /* message length */ len = body->len + sizeof(struct hep_ip6hdr) + sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);; /* The packet is too big for us */ if (unlikely(len>BUF_SIZE)){ goto error; } /* Convert proto:ip:port to sockaddress union SRC IP */ if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1)) goto error; /* check if from and to are in the same family*/ if(from_su.s.sa_family != to_su.s.sa_family) { LM_ERR("interworking detected ?\n"); goto error; } if (!dst2){ init_dest_info(&dst); /* create a temporary proxy*/ dst.proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, dst.proto); if (p==0) { LM_ERR("bad host name in uri\n"); goto error; } hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); LM_DBG("setting up the socket_info\n"); dst_fin = &dst; } else { dst_fin = dst2; } if (force_send_sock_str.s) { LM_DBG("force_send_sock activated, grep for the sock_info\n"); si = grep_sock_info(&force_send_sock_uri->host, (force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT, PROTO_UDP); if (!si) { LM_WARN("cannot grep socket info\n"); } else { LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s); dst_fin->send_sock = si; } } if (dst_fin->send_sock == 0) { dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto); if (dst_fin->send_sock == 0) { LM_ERR("can't forward to af %d, proto %d no corresponding" " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto); goto error; } } /* Version && proto && length */ hdr.hp_l = sizeof(struct hep_hdr); hdr.hp_v = hep_version; hdr.hp_p = proto; /* AND the last */ if (from_su.s.sa_family==AF_INET){ /* prepare the hep headers */ hdr.hp_f = AF_INET; hdr.hp_sport = htons(from_su.sin.sin_port); hdr.hp_dport = htons(to_su.sin.sin_port); hep_ipheader.hp_src = from_su.sin.sin_addr; hep_ipheader.hp_dst = to_su.sin.sin_addr; len = sizeof(struct hep_iphdr); } else if (from_su.s.sa_family==AF_INET6){ /* prepare the hep6 headers */ hdr.hp_f = AF_INET6; hdr.hp_sport = htons(from_su.sin6.sin6_port); hdr.hp_dport = htons(to_su.sin6.sin6_port); hep_ip6header.hp6_src = from_su.sin6.sin6_addr; hep_ip6header.hp6_dst = to_su.sin6.sin6_addr; len = sizeof(struct hep_ip6hdr); } else { LM_ERR("Unsupported protocol family\n"); goto error;; } hdr.hp_l +=len; if (hep_version == 2){ len += sizeof(struct hep_timehdr); } len += sizeof(struct hep_hdr) + body->len; buffer = (void *)pkg_malloc(len+1); if (buffer==0){ LM_ERR("out of memory\n"); goto error; } /* Copy job */ memset(buffer, '\0', len+1); /* copy hep_hdr */ memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr)); buflen = sizeof(struct hep_hdr); /* hep_ip_hdr */ if(from_su.s.sa_family==AF_INET) { memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } else { memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } if(hep_version == 2) { hep_time.tv_sec = tvb.tv_sec; hep_time.tv_usec = tvb.tv_usec; hep_time.captid = hep_capture_id; memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); } /* PAYLOAD */ memcpy((void*)(buffer + buflen) , (void*)body->s, body->len); buflen +=body->len; if (msg_send_buffer(dst_fin, buffer, buflen, 1)<0) { LM_ERR("cannot send hep duplicate message\n"); goto error; } if (p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } pkg_free(buffer); return 0; error: if(p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } if(buffer) pkg_free(buffer); return -1; }
/*! * \brief Previous hop was a strict router, handle this case * \param _m SIP message * \return -1 on error, 1 on success */ static inline int after_strict(struct sip_msg* _m) { int res, rem_len; struct hdr_field* hdr; struct sip_uri puri; rr_t* rt, *prev; char* rem_off; str uri; struct socket_info *si; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; routed_params.s = NULL; routed_params.len = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("searching next route failed\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("after_strict: No next URI found\n"); return NOT_RR_DRIVEN; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; /* parse the new found uri */ uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return RR_ERROR; } } /* set the hooks for the param * important note: RURI is already parsed by the above function, so * we just used it without any checking */ routed_msg_id = _m->id; routed_params = _m->parsed_uri.params; if (is_strict(&puri.params)) { LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s)); /* Previous hop was a strict router and the next hop is strict * router too. There is no need to save R-URI again because it * is saved already. In fact, in this case we will behave exactly * like a strict router. */ /* Note: when there is only one Route URI left (endpoint), it will * always be a strict router because endpoints don't use ;lr parameter * In this case we will simply put the URI in R-URI and forward it, * which will work perfectly */ if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite request URI\n"); return RR_ERROR; } if (rt->next) { rem_off = hdr->body.s; rem_len = rt->next->nameaddr.name.s - hdr->body.s; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } else { LM_DBG("Next hop: '%.*s' is loose router\n", uri.len, ZSW(uri.s)); if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* Next hop is a loose router - Which means that is is not endpoint yet * In This case we have to recover from previous strict routing, that * means we have to find the last Route URI and put in in R-URI and * remove the last Route URI. */ if (rt != hdr->parsed) { /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ rem_off = hdr->body.s; rem_len = rt->nameaddr.name.s - hdr->body.s; if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } res = find_rem_target(_m, &hdr, &rt, &prev); if (res < 0) { LM_ERR("searching for last Route URI failed\n"); return RR_ERROR; } else if (res > 0) { /* No remote target is an error */ return RR_ERROR; } uri = rt->nameaddr.uri; if(get_maddr_uri(&uri, 0)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite R-URI\n"); return RR_ERROR; } /* The first character if uri will be either '<' when it is the * only URI in a Route header field or ',' if there is more than * one URI in the header field */ LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); if (prev) { rem_off = prev->nameaddr.name.s + prev->len; rem_len = rt->nameaddr.name.s + rt->len - rem_off; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return RR_DRIVEN; }
/*! * \brief Previous hop was a loose router, handle this case * \param _m SIP message * \param preloaded do we have a preloaded route set * \return -1 on failure, 1 on success */ static inline int after_loose(struct sip_msg* _m, int preloaded) { struct hdr_field* hdr; struct sip_uri puri; rr_t* rt; int res; int status = RR_DRIVEN; str uri; struct socket_info *si; int uri_is_myself, next_is_strict; int use_ob = 0; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } next_is_strict = is_strict(&puri.params); routed_params = puri.params; uri_is_myself = is_myself(&puri); /* IF the URI was added by me, remove it */ if (uri_is_myself>0) { LM_DBG("Topmost route URI: '%.*s' is me\n", uri.len, ZSW(uri.s)); /* set the hooks for the params */ routed_msg_id = _m->id; if ((use_ob = process_outbound(_m, puri.user)) < 0) { LM_INFO("failed to process outbound flow-token\n"); return FLOW_TOKEN_BROKEN; } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("No next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LM_ERR("failed to parse the double route URI\n"); return RR_ERROR; } if (!use_ob) { si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("no next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } } else { #ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(uri_is_myself < 0) return NOT_RR_DRIVEN; #endif LM_DBG("Topmost URI is NOT myself\n"); routed_params.s = NULL; routed_params.len = 0; } LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s)); if (next_is_strict) { LM_DBG("Next URI is a strict router\n"); if (handle_sr(_m, hdr, rt) < 0) { LM_ERR("failed to handle strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ LM_DBG("Next URI is a loose router\n"); if (!use_ob) { if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* dst_uri changed, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } } done: if (use_ob == 1) status = RR_OB_DRIVEN; /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return status; }
/*load groups of destinations from DB*/ int ds_load_db(void) { int i, id, nr_rows, setn, cnt; int flags; int weight; struct socket_info *sock; str uri; str attrs; str host; int port, proto; db_res_t * res; db_val_t * values; db_row_t * rows; db_key_t query_cols[6] = {&ds_set_id_col, &ds_dest_uri_col, &ds_dest_sock_col, &ds_dest_flags_col, &ds_dest_weight_col, &ds_dest_attrs_col}; if( (*crt_idx) != (*next_idx)) { LM_WARN("load command already generated, aborting reload...\n"); return 0; } if(ds_db_handle == NULL){ LM_ERR("invalid DB handler\n"); return -1; } if (ds_dbf.use_table(ds_db_handle, &ds_table_name) < 0) { LM_ERR("error in use_table\n"); return -1; } /*select the whole table and all the columns*/ if(ds_dbf.query(ds_db_handle,0,0,0,query_cols,0,6,0,&res) < 0) { LM_ERR("error while querying database\n"); return -1; } *next_idx = (*crt_idx + 1)%2; destroy_list(*next_idx); nr_rows = RES_ROW_N(res); rows = RES_ROWS(res); if(nr_rows == 0) { LM_WARN("no dispatching data in the db -- empty destination set\n"); goto load_done; } setn = 0; cnt = 0; for(i=0; i<nr_rows; i++) { values = ROW_VALUES(rows+i); /* id */ if (VAL_NULL(values)) { LM_ERR("ds ID column cannot be NULL -> skipping\n"); continue; } id = VAL_INT(values); /* uri */ get_str_from_dbval( "URI", values+1, 1/*not_null*/, 1/*not_empty*/, uri, err2); /* sock */ get_str_from_dbval( "SOCKET", values+2, 0/*not_null*/, 0/*not_empty*/, attrs, err2); if ( attrs.len ) { if (parse_phostport( attrs.s, attrs.len, &host.s, &host.len, &port, &proto)!=0){ LM_ERR("socket description <%.*s> is not valid -> ignoring\n", attrs.len,attrs.s); sock = NULL; } else { sock = grep_sock_info( &host, port, proto); if (sock == NULL) { LM_ERR("socket <%.*s> is not local to opensips (we must " "listen on it) -> ignoring it\n", attrs.len, attrs.s); } } } else { sock = NULL; } /* flags */ if (VAL_NULL(values+3)) { flags = 0; } else { flags = VAL_INT(values+3); } /* weight */ if (VAL_NULL(values+4)) { weight = 1; } else { weight = VAL_INT(values+4); } /* attrs */ get_str_from_dbval( "ATTRIBUTES", values+5, 0/*not_null*/, 0/*not_empty*/, attrs, err2); if(add_dest2list(id, uri, sock, flags, weight, attrs, *next_idx, &setn) != 0) { LM_WARN("failed to add destination <%.*s> in group %d\n",uri.len,uri.s,id); continue; } else { cnt ++; } } if (cnt==0) { LM_WARN("No record loaded from db, running on empty set\n"); } else { if(reindex_dests(*next_idx, setn)!=0) { LM_ERR("error on reindex\n"); goto err2; } } load_done: /*update data*/ _ds_list_nr = setn; *crt_idx = *next_idx; ds_dbf.free_result(ds_db_handle, res); return 0; err2: destroy_list(*next_idx); ds_dbf.free_result(ds_db_handle, res); *next_idx = *crt_idx; return -1; }
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 (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(0, 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 */ if (parse_phostport(val.s.s, val.s.len, &(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) { _msg->force_send_socket = 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(0, 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(0, 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(0, 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(0, 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(0, 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)); set_dst_uri(_msg, &duri_str); return 1; }
/** rpc t_uac version- * It expects the following list of strings as parameters: * method * request_uri * dst_uri (next hop) -- can be empty (either "" or ".", which is still * supported for backwards compatibility with fifo) * send_socket (socket from which the message will be sent) * headers (message headers separated by CRLF, at least From and To * must be present) * body (optional, might be null or completely missing) * * If all the parameters are ok it will call t_uac() using them. * Note: this version will wait for the transaction final reply * only if reply_wait is set to 1. Otherwise the rpc reply will be sent * immediately and it will be success if the paremters were ok and t_uac did * not report any error. * Note: reply waiting (reply_wait==1) is not yet supported. * @param rpc - rpc handle * @param c - rpc current context * @param reply_wait - if 1 do not generate a rpc reply until final response * for the transaction arrives, if 0 immediately send * an rpc reply (see above). */ static void rpc_t_uac(rpc_t* rpc, void* c, int reply_wait) { /* rpc params */ str method, ruri, nexthop, send_socket, headers, body; /* other internal vars.*/ str hfb, callid; struct sip_uri p_uri, pnexthop; struct sip_msg faked_msg; struct socket_info* ssock; str saddr; int sport, sproto; int ret, sip_error, err_ret, fromtag, cseq_is, cseq; char err_buf[MAX_REASON_LEN]; dlg_t dlg; uac_req_t uac_req; rpc_delayed_ctx_t* dctx; body.s=0; body.len=0; dctx=0; if (reply_wait && (rpc->capabilities == 0 || !(rpc->capabilities(c) & RPC_DELAYED_REPLY))) { rpc->fault(c, 600, "Reply wait/async mode not supported" " by this rpc transport"); return; } ret=rpc->scan(c, "SSSSS*S", &method, &ruri, &nexthop, &send_socket, &headers, &body); if (ret<5 && ! (-ret == 5)){ rpc->fault(c, 400, "too few parameters (%d/5)", ret?ret:-ret); return; } /* check and parse parameters */ if (method.len==0){ rpc->fault(c, 400, "Empty method"); return; } if (parse_uri(ruri.s, ruri.len, &p_uri)<0){ rpc->fault(c, 400, "Invalid request uri \"%s\"", ruri.s); return; } /* old fifo & unixsock backwards compatibility for nexthop: '.' is still allowed */ if (nexthop.len==1 && nexthop.s[0]=='.'){ /* empty nextop */ nexthop.len=0; nexthop.s=0; }else if (nexthop.len==0){ nexthop.s=0; }else if (parse_uri(nexthop.s, nexthop.len, &pnexthop)<0){ rpc->fault(c, 400, "Invalid next-hop uri \"%s\"", nexthop.s); return; } /* kamailio backwards compatibility for send_socket: '.' is still allowed for an empty socket */ ssock=0; saddr.s=0; saddr.len=0; if (send_socket.len==1 && send_socket.s[0]=='.'){ /* empty send socket */ send_socket.len=0; }else if (send_socket.len && (parse_phostport(send_socket.s, &saddr.s, &saddr.len, &sport, &sproto)!=0 || /* check also if it's not a MH addr. */ saddr.len==0 || saddr.s[0]=='(') ){ rpc->fault(c, 400, "Invalid send socket \"%s\"", send_socket.s); return; }else if (saddr.len && (ssock=grep_sock_info(&saddr, sport, sproto))==0){ rpc->fault(c, 400, "No local socket for \"%s\"", send_socket.s); return; } /* check headers using the SIP parser to look in the header list */ memset(&faked_msg, 0, sizeof(struct sip_msg)); faked_msg.len=headers.len; faked_msg.buf=faked_msg.unparsed=headers.s; if (parse_headers(&faked_msg, HDR_EOH_F, 0)==-1){ rpc->fault(c, 400, "Invalid headers"); return; } /* at this moment all the parameters are parsed => more sanity checks */ if (rpc_uac_check_msg(rpc, c, &faked_msg, &method, &body, &fromtag, &cseq_is, &cseq, &callid)<0) goto error; hfb.s=get_hfblock(nexthop.len? &nexthop: &ruri, faked_msg.headers, PROTO_NONE, ssock, &hfb.len); if (hfb.s==0){ rpc->fault(c, 500, "out of memory"); goto error; } /* proceed to transaction creation */ memset(&dlg, 0, sizeof(dlg_t)); /* fill call-id if call-id present or else generate a callid */ if (callid.s && callid.len) dlg.id.call_id=callid; else generate_callid(&dlg.id.call_id); /* We will not fill in dlg->id.rem_tag because * if present it will be printed within To HF */ /* Generate fromtag if not present */ if (!fromtag) { generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id); } /* Fill in CSeq */ if (cseq_is) dlg.loc_seq.value = cseq; else dlg.loc_seq.value = DEFAULT_CSEQ; dlg.loc_seq.is_set = 1; dlg.loc_uri = faked_msg.from->body; dlg.rem_uri = faked_msg.to->body; dlg.rem_target = ruri; dlg.dst_uri = nexthop; dlg.send_sock=ssock; memset(&uac_req, 0, sizeof(uac_req)); uac_req.method=&method; uac_req.headers=&hfb; uac_req.body=body.len?&body:0; uac_req.dialog=&dlg; if (reply_wait){ dctx=rpc->delayed_ctx_new(c); if (dctx==0){ rpc->fault(c, 500, "internal error: failed to create context"); return; } uac_req.cb=rpc_uac_callback; uac_req.cbp=dctx; uac_req.cb_flags=TMCB_LOCAL_COMPLETED; /* switch to dctx, in case adding the callback fails and we want to still send a reply */ rpc=&dctx->rpc; c=dctx->reply_ctx; } ret = t_uac(&uac_req); if (ret <= 0) { err_ret = err2reason_phrase(ret, &sip_error, err_buf, sizeof(err_buf), "RPC/UAC") ; if (err_ret > 0 ) { rpc->fault(c, sip_error, "%s", err_buf); } else { rpc->fault(c, 500, "RPC/UAC error"); } if (dctx) rpc->delayed_ctx_close(dctx); goto error01; } error01: if (hfb.s) pkg_free(hfb.s); error: if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers); }
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; db_res_t* res = NULL; db_row_t *row; dlist_t *dom; char *p, *p1; char now_s[25]; int now_len; int port, proto, p_len, p1_len; str host; int i; void *cp; int shortage, needed; cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(p_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; } for (dom = root; dom!=NULL ; dom=dom->next) { /* build query */ i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s," #ifdef ORACLE_USRLOC " %.*s, %.*s from %s where %.*s > %.*s and " "bitand(%.*s, %d) = %d and mod(id, %u) = %u", #else " %.*s, %.*s from %s where %.*s > %.*s and %.*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, 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 */ p = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || p==0 || p[0]==0 ) { /* contact */ p = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || p==0 || p[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } } p_len = strlen(p); /* path */ p1 = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || p1==0 || p1[0]==0){ p1 = NULL; p1_len = 0; } else { p1_len = strlen(p1); } needed = (int)(sizeof(p_len)+p_len+sizeof(sock)+sizeof(dbflags)+ sizeof(p1_len)+p1_len); if (len < needed) { shortage += needed ; continue; } /* write received/contact */ memcpy(cp, &p_len, sizeof(p_len)); cp = (char*)cp + sizeof(p_len); memcpy(cp, p, p_len); cp = (char*)cp + p_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, strlen(p), &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...ignoring\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...ignoring\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, &p1_len, sizeof(p1_len)); cp = (char*)cp + sizeof(p1_len); memcpy(cp, p1, p1_len); cp = (char*)cp + p1_len; 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(p_len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
static 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; static struct sip_uri puri; struct socket_info *sock; struct proxy_l next_hop; db_res_t *res = NULL; db_row_t *row; db_val_t *val; dlist_t *dom; str uri, host, flag_list; int i, no_rows = 10; int now_len; char now_s[25]; char *p, *p1; int port, proto, p_len, p1_len; unsigned int dbflags; int needed; int shortage = 0; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof p_len; /* get the current time in DB format */ now_len = 25; if (db_time2str(time(NULL), now_s, &now_len) != 0) { LM_ERR("failed to print now time\n"); return -1; } LM_DBG("buf: %p. flags: %d\n", buf, flags); /* for each table */ for (dom = root; dom; dom = dom->next) { if (db_check_table_version(&ul_dbf, ul_dbh, dom->d->name, UL_TABLE_VERSION)) goto error; /* read the destinations */ if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) { LM_ERR("cannot select table \"%.*s\"\n", dom->d->name->len, dom->d->name->s); goto error; } i = snprintf(query_buf, sizeof query_buf, "select %.*s, %.*s, %.*s," #ifdef ORACLE_USRLOC " %.*s, %.*s from %s where %.*s > %.*s and mod(id, %u) = %u", #else " %.*s, %.*s from %s where %.*s > %.*s 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, dom->d->name->s, expires_col.len, expires_col.s, now_len, now_s, part_max, part_idx); LM_DBG("query: %.*s\n", (int)(sizeof query_buf), query_buf); if (i >= sizeof query_buf) { LM_ERR("DB query too long\n"); goto error; } query_str.s = query_buf; query_str.len = i; if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if (ul_dbf.raw_query(ul_dbh, &query_str, 0) < 0) { LM_ERR("raw_query failed\n"); goto error; } no_rows = estimate_available_rows(20+128+20+128+64, 5); if (no_rows == 0) no_rows = 10; LM_DBG("fetching %d rows\n", no_rows); if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) { LM_ERR("Error fetching rows\n"); goto error; } } else if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { LM_ERR("raw_query failed\n"); goto error; } do { for (i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; val = ROW_VALUES(row) + 3; /* cflags */ flag_list.s = (char *)VAL_STRING(val); flag_list.len = strlen(flag_list.s); LM_DBG("contact cflags: '%.*s'\n", flag_list.len, flag_list.s); /* contact is not flagged at all */ if (flags && (val->nul || !flag_list.s)) continue; dbflags = flag_list_to_bitmask(&flag_list, FLAG_TYPE_BRANCH, FLAG_DELIM); LM_DBG("masks: param: %d --- %d :db\n", flags, dbflags); /* check if contact flags match the given bitmask */ if ((dbflags & flags) != flags) continue; /* received */ p = (char*)VAL_STRING(ROW_VALUES(row)); if (VAL_NULL(ROW_VALUES(row)) || !p || !p[0]) { /* contact */ p = (char*)VAL_STRING(ROW_VALUES(row) + 1); if (VAL_NULL(ROW_VALUES(row) + 1) || !p || *p == '\0') { LM_ERR("empty contact -> skipping\n"); continue; } } p_len = strlen(p); /* path */ p1 = (char*)VAL_STRING(ROW_VALUES(row) + 4); if (VAL_NULL(ROW_VALUES(row) + 4) || !p1 || *p1 == '\0') { p1 = NULL; p1_len = 0; } else p1_len = strlen(p1); needed = (int)(p_len + sizeof p_len + p1_len + sizeof p1_len + sizeof sock + sizeof dbflags + sizeof next_hop); LM_DBG("len: %d, needed: %d\n", len, needed); if (len < needed) { shortage += needed; continue; } /* determine and parse the URI of this contact's next hop */ if (p1_len > 0) { /* send to first URI in path */ host.s = p1; host.len = p1_len; if (get_path_dst_uri(&host, &uri) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse path URI of next hop: '%*.s'\n", p1_len, p1); return -1; } } else { if (parse_uri(p, p_len, &puri) < 0) { LM_ERR("failed to parse contact of next hop: '%*.s'\n", p_len, p); return -1; } } /* write received/contact */ memcpy(buf, &p_len, sizeof p_len); buf += sizeof p_len; memcpy(buf, p, p_len); buf += p_len; /* write path */ memcpy(buf, &p1_len, sizeof p1_len); buf += sizeof p1_len; memcpy(buf, p1, p1_len); buf += p1_len; /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || !p || *p == '\0') { sock = NULL; } else { if (parse_phostport(p, strlen(p), &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%s>...ignoring\n", p); sock = NULL; } else { sock = grep_sock_info(&host, (unsigned short)port, proto); if (!sock) LM_DBG("non-local socket <%s>...ignoring\n", p); } } /* write sock and flags */ memcpy(buf, &sock, sizeof sock); buf += sizeof sock; memcpy(buf, &dbflags, sizeof dbflags); buf += sizeof dbflags; memset(&next_hop, 0, sizeof next_hop); next_hop.port = puri.port_no; next_hop.proto = puri.proto; next_hop.name = puri.host; /* write the next hop */ memcpy(buf, &next_hop, sizeof next_hop); buf += sizeof next_hop; len -= needed; } if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) { LM_ERR("fetching rows (1)\n"); goto error; } } else break; } while (RES_ROW_N(res) > 0); ul_dbf.free_result(ul_dbh, res); } /* len < 0 is possible, if size of the buffer < sizeof c->c.len */ if (len >= 0) memset(buf, 0, sizeof p_len); /* Shouldn't happen */ if (shortage > 0 && len > shortage) abort(); shortage -= len; return shortage > 0 ? shortage : 0; error: if (res) ul_dbf.free_result(ul_dbh, res); return -1; }