#include <commonp.h>
#include <com.h>
#include <comp.h>
#include <dce/ep.h>
#include <dce/mgmt.h>
#include <dsm.h>
#include <rpcdp.h>
#include <rpcddb.h>
#include <rpcdepdb.h>
#include <rpcdepdbp.h>
#include <rpcdutil.h>
#include <comtwr.h>
INTERNAL epdb_handle_t epdb_handle = NULL;
#define epdb_c_file_version 8
INTERNAL void epdb_recreate_lists
(
struct db *h,
error_status_t *status
);
INTERNAL void epdb_chk_entry
(
ept_entry_p_t xentry,
twr_fields_p_t tfp,
rpc_addr_p_t addr,
error_status_t *status
);
INTERNAL void epdb_chk_map_entry
(
twr_fields_p_t tfp,
error_status_t *status
);
INTERNAL void epdb_to_ept
(
db_entry_p_t entp,
ept_entry_t *xentry,
error_status_t *status
);
INTERNAL void epdb_insert_entry
(
struct db *h,
ept_entry_p_t xentry,
twr_fields_p_t tfp,
rpc_addr_p_t addr,
db_entry_p_t *entp,
error_status_t *status
);
INTERNAL void epdb_replace_entry
(
struct db *h,
ept_entry_p_t xentry,
db_entry_p_t entp,
error_status_t *status
);
INTERNAL boolean32 epdb_is_replace_candidate
(
db_entry_t *entp,
uuid_p_t object,
twr_fields_p_t tfp,
rpc_addr_p_t addr
);
INTERNAL void epdb_delete_replaceable_entries
(
struct db *h,
uuid_p_t object,
twr_fields_p_t tfp,
rpc_addr_p_t addr,
error_status_t *status
);
INTERNAL void epdb_delete_entries_by_obj_if_addr
(
struct db *h,
boolean32 object_speced,
uuid_p_t object,
rpc_if_id_p_t interface,
rpc_addr_p_t addr,
error_status_t *status
);
INTERNAL db_entry_t *epdb_lookup_entry
(
struct db *h,
ept_entry_p_t xentry
);
INTERNAL void lookup
(
struct db *h,
unsigned32 inquiry_type,
uuid_p_t object,
rpc_if_id_p_t interface,
unsigned32 vers_option,
ept_lookup_handle_t *entry_handle,
unsigned32 max_ents,
unsigned32 *num_ents,
ept_entry_t entries[],
error_status_t *status
);
INTERNAL void lookup_match
(
unsigned32 inquiry_type,
uuid_p_t object,
rpc_if_id_p_t interface,
unsigned32 vers_option,
unsigned32 max_ents,
unsigned32 *num_ents,
ept_entry_t entries[],
unsigned32 list_type,
db_lists_t **lpp,
error_status_t *status
);
INTERNAL void map
(
struct db *h,
uuid_p_t object,
rpc_if_id_p_t interface,
rpc_syntax_id_p_t data_rep,
rpc_protocol_id_t rpc_protocol,
unsigned32 rpc_protocol_vers_major,
unsigned32 rpc_protocol_vers_minor,
rpc_protseq_id_t protseq,
ept_lookup_handle_t *map_handle,
unsigned32 max_ents,
unsigned32 *n_ents,
db_entry_t *db_entries[],
unsigned32 *status
);
INTERNAL void map_match
(
uuid_p_t object,
rpc_if_id_p_t interface,
rpc_syntax_id_p_t data_rep,
rpc_protocol_id_t rpc_protocol,
unsigned32 rpc_protocol_vers_major,
unsigned32 rpc_protocol_vers_minor,
rpc_protseq_id_t protseq,
unsigned32 max_ents,
unsigned32 *n_ents,
db_entry_t *entries[],
ept_lookup_handle_t *map_handle,
unsigned32 pass,
db_list_type_t list,
db_lists_t **lpp,
unsigned32 *status
);
INTERNAL void map_mgmt
(
struct db *h,
uuid_p_t object,
rpc_syntax_id_p_t data_rep,
rpc_protocol_id_t rpc_protocol,
unsigned32 rpc_protocol_vers_major,
unsigned32 rpc_protocol_vers_minor,
rpc_protseq_id_t protseq,
ept_lookup_handle_t *map_handle,
unsigned32 max_ents,
unsigned32 *n_ents,
db_entry_t *db_entries[],
unsigned32 *status
);
INTERNAL void map_mgmt_match
(
uuid_p_t object,
rpc_syntax_id_p_t data_rep,
rpc_protocol_id_t rpc_protocol,
unsigned32 rpc_protocol_vers_major,
unsigned32 rpc_protocol_vers_minor,
rpc_protseq_id_t protseq,
unsigned32 max_ents,
unsigned32 *n_ents,
db_entry_t *entries[],
ept_lookup_handle_t *map_handle,
unsigned32 pass,
db_list_type_t list,
db_lists_t **lpp,
unsigned32 *status
);
INTERNAL boolean32 map_mgmt_endpt_unique
(
rpc_addr_p_t addr,
unsigned32 n_ents,
db_entry_t *entries[]
);
PRIVATE void epdb_handle_from_ohandle(h, epdb_h, status)
handle_t h;
epdb_handle_t *epdb_h;
error_status_t *status;
{
idl_uuid_t obj;
idl_uuid_t epdb_obj;
SET_STATUS(status, rpc_s_ok);
if (h == NULL)
{
*epdb_h = epdb_handle;
return;
}
rpc_binding_inq_object(h, &obj, status);
if (uuid_is_nil(&obj, status))
*epdb_h = epdb_handle;
else
{
epdb_inq_object(epdb_handle, &epdb_obj, status);
if (uuid_equal(&obj, &epdb_obj, status))
*epdb_h = epdb_handle;
else
SET_STATUS(status, ept_s_cant_perform_op);
}
return;
}
PRIVATE epdb_handle_t epdb_inq_handle()
{
return(epdb_handle);
}
PRIVATE epdb_handle_t epdb_init(pathname, status)
unsigned char *pathname;
error_status_t *status;
{
struct db *h;
SET_STATUS_OK(status);
h = (struct db *) malloc(sizeof(struct db));
if (h == NULL) {
SET_STATUS(status, ept_s_cant_perform_op);
return(NULL);
}
h->dsh = NULL;
db_init_lists(h);
db_open(h, pathname, epdb_c_file_version, status);
if (! STATUS_OK(status))
{
unlink(pathname);
db_open(h, pathname, epdb_c_file_version, status);
if (! STATUS_OK(status))
{
return NULL;
}
}
epdb_recreate_lists(h, status);
if (! STATUS_OK(status)) return(NULL);
db_init_lock(h);
sliv_init(h, status);
if (! STATUS_OK(status)) return(NULL);
epdb_handle = (epdb_handle_t) h;
return((epdb_handle_t) h);
}
INTERNAL void epdb_recreate_lists(h, status)
struct db *h;
error_status_t *status;
{
db_entry_t *entp = NULL;
dsm_marker_t marker;
dsm_marker_reset(&marker);
while(true)
{
void* _entp = NULL;
dsm_read(h->dsh,&marker, &_entp,status);
entp = (db_entry_t*) _entp;
if (! STATUS_OK(status))
{
if (*status == dsm_err_no_more_entries)
{
SET_STATUS(status, error_status_ok);
}
else
{
if (dflag)
show_st("Error reading ept database", status);
SET_STATUS(status, ept_s_cant_access);
}
return;
}
tower_to_addr(&entp->tower, &entp->addr, status);
if (! STATUS_OK(status))
{
if (dflag)
show_st("tower_to_addr error for ept entry", status);
SET_STATUS(status, ept_s_invalid_entry);
return;
}
entp->read_nrefs = 0;
entp->ncomm_fails = 0;
db_lists_add(h, entp);
}
}
INTERNAL void epdb_chk_entry(xentry, tfp, addr, status)
ept_entry_p_t xentry;
twr_fields_p_t tfp;
rpc_addr_p_t addr;
error_status_t *status;
{
rpc_binding_handle_t binding_h;
error_status_t tmp_st;
if (uuid_is_nil(&tfp->interface.uuid, &tmp_st) ||
uuid_is_nil(&tfp->data_rep.id, &tmp_st) ||
(addr == NULL) ||
(addr->len == 0))
{
SET_STATUS(status, ept_s_invalid_entry);
return;
}
rpc_tower_to_binding(xentry->tower->tower_octet_string, &binding_h, status);
if (! STATUS_OK(status)) return;
rpc_binding_free(&binding_h, &tmp_st);
}
INTERNAL void epdb_chk_map_entry(tfp, status)
twr_fields_p_t tfp;
error_status_t *status;
{
error_status_t tmp_st;
assert (status != NULL);
if (uuid_is_nil(&tfp->interface.uuid, &tmp_st) ||
uuid_is_nil(&tfp->data_rep.id, &tmp_st) ||
(! RPC_PROTSEQ_INQ_SUPPORTED(tfp->protseq)) )
SET_STATUS(status, ept_s_invalid_entry);
else
SET_STATUS_OK(status);
}
INTERNAL void epdb_to_ept(entp, xentry, status)
db_entry_p_t entp;
ept_entry_t *xentry;
error_status_t *status;
{
xentry->object = entp->object;
memcpy((char *)xentry->annotation, (char *)entp->annotation,
sizeof(xentry->annotation));
tower_ss_copy(&entp->tower, &xentry->tower, status);
}
INTERNAL void epdb_insert_entry(h, xentry, tfp, addr, entp, status)
struct db *h;
ept_entry_p_t xentry;
twr_fields_p_t tfp;
rpc_addr_p_t addr;
db_entry_p_t *entp;
error_status_t *status;
{
db_entry_t *db_entp;
error_status_t tmp_st;
dsm_allocate(h->dsh, sizeof(db_entry_t) + xentry->tower->tower_length,
(void **) entp, status);
if (! STATUS_OK(status)) return;
db_entp = *entp;
db_entp->read_nrefs = 0;
db_entp->ncomm_fails = 0;
db_entp->delete_flag = false;
db_entp->object = xentry->object;
db_entp->interface = tfp->interface;
db_entp->object_nil = uuid_is_nil(&db_entp->object, &tmp_st);
db_entp->if_nil = uuid_is_nil(&db_entp->interface.uuid, &tmp_st);
db_entp->data_rep_id = tfp->data_rep.id;
db_entp->data_rep_vers_major = RPC_IF_VERS_MAJOR(tfp->data_rep.version);
db_entp->data_rep_vers_minor = RPC_IF_VERS_MINOR(tfp->data_rep.version);
db_entp->rpc_protocol = tfp->rpc_protocol;
db_entp->rpc_protocol_vers_major = tfp->rpc_protocol_vers_major;
db_entp->rpc_protocol_vers_minor = tfp->rpc_protocol_vers_minor;
db_entp->addr = addr;
memcpy((char *)db_entp->annotation, (char *)xentry->annotation,
sizeof(db_entp->annotation));
db_entp->tower.tower_length = xentry->tower->tower_length;
memcpy((char *) db_entp->tower.tower_octet_string, (char *) xentry->tower->tower_octet_string,
xentry->tower->tower_length);
dsm_write(h->dsh, (void *) db_entp, status);
if (! STATUS_OK(status)) return;
db_lists_add(h, db_entp);
}
INTERNAL void epdb_replace_entry(h, xentry, entp, status)
struct db *h;
ept_entry_p_t xentry;
db_entry_p_t entp;
error_status_t *status;
{
entp->ncomm_fails = 0;
entp->delete_flag = false;
memcpy((char *)entp->annotation, (char *)xentry->annotation,
sizeof(entp->annotation));
db_update_entry(h, entp, status);
}
PRIVATE void epdb_delete_entry(h, entp, status)
struct db *h;
db_entry_p_t entp;
error_status_t *status;
{
if (entp->read_nrefs == 0)
{
db_lists_remove(h, entp);
rpc__naf_addr_free(&entp->addr, status);
dsm_free(h->dsh, (void *) entp, status);
}
else
{
entp->delete_flag = true;
db_update_entry(h, entp, status);
}
}
INTERNAL boolean32 epdb_is_replace_candidate(entp, object, tfp, addr)
twr_fields_p_t tfp;
uuid_p_t object;
db_entry_t *entp;
rpc_addr_p_t addr;
{
error_status_t tmp_st;
unsigned32 data_rep_vers_major,
data_rep_vers_minor;
data_rep_vers_major = RPC_IF_VERS_MAJOR(tfp->data_rep.version);
data_rep_vers_minor = RPC_IF_VERS_MINOR(tfp->data_rep.version);
return (uuid_equal(object, &entp->object, &tmp_st) &&
uuid_equal(&tfp->interface.uuid, &entp->interface.uuid, &tmp_st) &&
(tfp->interface.vers_major == entp->interface.vers_major) &&
(addr->rpc_protseq_id == entp->addr->rpc_protseq_id) &&
uuid_equal(&tfp->data_rep.id, &entp->data_rep_id, &tmp_st) &&
(data_rep_vers_major == entp->data_rep_vers_major) &&
(data_rep_vers_minor == entp->data_rep_vers_minor) &&
(tfp->rpc_protocol == entp->rpc_protocol) &&
(tfp->rpc_protocol_vers_major == entp->rpc_protocol_vers_major) &&
(tfp->rpc_protocol_vers_minor == entp->rpc_protocol_vers_minor));
}
INTERNAL void epdb_delete_replaceable_entries(h, object, tfp, addr, status)
struct db *h;
uuid_p_t object;
twr_fields_p_t tfp;
rpc_addr_p_t addr;
error_status_t *status;
{
unsigned_char_p_t netaddr,
netaddr2;
db_lists_t *lp,
*lp_first,
*lp_next;
db_list_type_t list_type;
error_status_t tmp_st;
rpc__naf_addr_inq_netaddr(addr, &netaddr, status);
if (! STATUS_OK(status))
{
SET_STATUS(status, ept_s_invalid_entry);
return;
}
if (! uuid_is_nil(object, &tmp_st))
{
list_type = db_c_object_list;
lp_first = db_list_first(&h->lists_mgmt, db_c_object_list, object);
}
else
{
list_type = db_c_interface_list;
lp_first = db_list_first(&h->lists_mgmt, db_c_interface_list, &tfp->interface.uuid);
}
for (lp = lp_first; lp != NULL; lp = db_list_next(list_type, lp))
{
db_entry_t *entp = (db_entry_t *) lp;
if (entp->delete_flag) continue;
if (epdb_is_replace_candidate(entp, object, tfp, addr) &&
entp->interface.vers_minor > tfp->interface.vers_minor)
{
assert(status != NULL);
SET_STATUS(status, ept_s_invalid_entry);
goto DONE;
}
}
for (lp = lp_first; lp != NULL; lp = lp_next)
{
db_entry_t *entp = (db_entry_t *) lp;
lp_next = db_list_next(list_type, lp);
if (entp->delete_flag) continue;
if (epdb_is_replace_candidate(entp, object, tfp, addr))
{
rpc__naf_addr_inq_netaddr(entp->addr, &netaddr2, &tmp_st);
if (! STATUS_OK(&tmp_st)) continue;
if (strcmp((char *) netaddr, (char *) netaddr2) == 0)
{
epdb_delete_entry(h, entp, &tmp_st);
}
rpc_string_free(&netaddr2, &tmp_st);
}
}
assert(status != NULL);
SET_STATUS_OK(status);
DONE:
rpc_string_free(&netaddr, &tmp_st);
}
INTERNAL void epdb_delete_entries_by_obj_if_addr(h, object_speced, object, interface, addr, status)
struct db *h;
boolean32 object_speced;
uuid_p_t object;
rpc_if_id_p_t interface;
rpc_addr_p_t addr;
error_status_t *status;
{
unsigned32 ndelete;
db_lists_t *lp,
*lp_next;
db_entry_t *entp;
error_status_t tmp_st;
ndelete = 0;
for (lp = db_list_first(&h->lists_mgmt, db_c_interface_list, &interface->uuid);
lp != NULL; lp = lp_next)
{
lp_next = db_list_next(db_c_interface_list, lp);
entp = (db_entry_t *) lp;
if (entp->delete_flag) continue;
if (((! object_speced) || uuid_equal(object, &entp->object, &tmp_st)) &&
(uuid_equal(&interface->uuid, &entp->interface.uuid, &tmp_st)) &&
(interface->vers_major == entp->interface.vers_major) &&
(interface->vers_minor == entp->interface.vers_minor) &&
(rpc__naf_addr_compare(addr, entp->addr, &tmp_st)))
{
epdb_delete_entry(h, entp, status);
if (! STATUS_OK(status)) return;
ndelete++;
}
}
assert(status != NULL);
if (ndelete > 0)
SET_STATUS_OK(status);
else
SET_STATUS(status, ept_s_not_registered);
}
INTERNAL db_entry_t *epdb_lookup_entry(h, xentry)
struct db *h;
ept_entry_p_t xentry;
{
db_entry_t *entp;
db_lists_t *lp;
db_list_type_t list_type;
rpc_if_id_t interface;
error_status_t tmp_st;
if (! uuid_is_nil(&xentry->object, &tmp_st))
{
list_type = db_c_object_list;
lp = db_list_first(&h->lists_mgmt, db_c_object_list, &xentry->object);
}
else
{
tower_to_if_id(xentry->tower, &interface, &tmp_st);
list_type = db_c_interface_list;
lp = db_list_first(&h->lists_mgmt, db_c_interface_list, &interface.uuid);
}
for ( ; lp != NULL; lp = db_list_next(list_type, lp))
{
entp = (db_entry_t *) lp;
if (uuid_equal(&xentry->object, &entp->object, &tmp_st) &&
(xentry->tower->tower_length == entp->tower.tower_length) &&
(memcmp((char *) xentry->tower->tower_octet_string,
(char *) entp->tower.tower_octet_string,
xentry->tower->tower_length) == 0))
{
return(entp);
}
}
return(NULL);
}
PRIVATE void epdb_insert(h_, xentry, replace, status)
epdb_handle_t h_;
ept_entry_p_t xentry;
boolean32 replace;
error_status_t *status;
{
struct db *h = (struct db *) h_;
db_entry_t *entp;
twr_fields_t twr_fields;
rpc_addr_p_t addr;
error_status_t tmp_st;
addr = NULL;
SET_STATUS(status, ept_s_invalid_entry);
tower_to_fields(xentry->tower, &twr_fields, &tmp_st);
if (!STATUS_OK(&tmp_st)) return;
tower_to_addr(xentry->tower, &addr, &tmp_st);
if (!STATUS_OK(&tmp_st)) return;
epdb_chk_entry(xentry, &twr_fields, addr, &tmp_st);
if (!STATUS_OK(&tmp_st))
{
if (addr != NULL) rpc__naf_addr_free(&addr, &tmp_st);
return;
}
db_lock(h);
if (replace)
{
epdb_delete_replaceable_entries(h, &xentry->object, &twr_fields, addr, status);
if (! STATUS_OK(status))
{
rpc__naf_addr_free(&addr, &tmp_st);
db_unlock(h);
return;
}
}
entp = epdb_lookup_entry(h, xentry);
if (entp == NULL)
{
epdb_insert_entry(h, xentry, &twr_fields, addr, &entp, status);
}
else
{
rpc__naf_addr_free(&addr, &tmp_st);
epdb_replace_entry(h, xentry, entp, status);
}
db_unlock(h);
if (! STATUS_OK(status))
{
if (addr != NULL) rpc__naf_addr_free(&addr, &tmp_st);
db_to_ept_ecode(status);
}
}
PRIVATE void epdb_delete(h_, xentry, status)
epdb_handle_t h_;
ept_entry_p_t xentry;
error_status_t *status;
{
struct db *h = (struct db *) h_;
db_entry_t *entp;
SET_STATUS_OK(status);
db_lock(h);
entp = epdb_lookup_entry(h, xentry);
if (entp != NULL)
{
if (entp->delete_flag)
SET_STATUS(status, ept_s_not_registered);
else
{
epdb_delete_entry(h, entp, status);
if (! STATUS_OK(status)) db_to_ept_ecode(status);
}
}
else
SET_STATUS(status, ept_s_not_registered);
db_unlock(h);
}
PRIVATE void epdb_mgmt_delete(h_, object_speced, object, tower, status)
epdb_handle_t h_;
boolean32 object_speced;
uuid_p_t object;
twr_p_t tower;
error_status_t *status;
{
struct db *h = (struct db *) h_;
rpc_if_id_t interface;
rpc_addr_p_t addr;
error_status_t tmp_st;
SET_STATUS(status, ept_s_invalid_entry);
tower_to_if_id(tower, &interface, status);
if (! STATUS_OK(status)) return;
tower_to_addr(tower, &addr, status);
if (! STATUS_OK(status)) return;
db_lock(h);
epdb_delete_entries_by_obj_if_addr(h, object_speced, object, &interface, addr, status);
if (! STATUS_OK(status)) db_to_ept_ecode(status);
db_unlock(h);
rpc__naf_addr_free(&addr, &tmp_st);
}
PRIVATE void epdb_lookup(h_, inquiry_type, object, interface, vers_option, entry_handle, max_ents,
num_ents, entries, status)
epdb_handle_t h_;
unsigned32 inquiry_type;
uuid_p_t object;
rpc_if_id_p_t interface;
unsigned32 vers_option;
ept_lookup_handle_t *entry_handle;
unsigned32 max_ents;
unsigned32 *num_ents;
ept_entry_t entries[];
error_status_t *status;
{
struct db *h = (struct db *) h_;
*num_ents = 0;
db_lock(h);
if (entries == NULL)
{
db_delete_context(h, entry_handle);
SET_STATUS(status, ept_s_invalid_entry);
db_unlock(h);
return;
}
lookup(h, inquiry_type, object, interface, vers_option, entry_handle, max_ents, num_ents, entries, status);
db_unlock(h);
}
INTERNAL void lookup(h, inquiry_type, object, interface, vers_option, entry_handle, max_ents,
num_ents, entries, status)
struct db *h;
unsigned32 inquiry_type;
uuid_p_t object;
rpc_if_id_p_t interface;
unsigned32 vers_option;
ept_lookup_handle_t *entry_handle;
unsigned32 max_ents;
unsigned32 *num_ents;
ept_entry_t entries[];
error_status_t *status;
{
unsigned32 pass;
db_list_type_t list_type;
db_lists_t *lp;
unsigned32 i;
SET_STATUS_OK(status);
if ((entry_handle == NULL) || (*entry_handle == NULL))
{
switch ((int)inquiry_type)
{
case rpc_c_ep_all_elts:
pass = 1;
list_type = db_c_entry_list;
lp = db_list_first(&h->lists_mgmt, list_type, NULL);
break;
case rpc_c_ep_match_by_if:
case rpc_c_ep_match_by_both:
pass = 1;
list_type = db_c_interface_list;
lp = db_list_first(&h->lists_mgmt, list_type, &interface->uuid);
break;
case rpc_c_ep_match_by_obj:
pass = 1;
list_type = db_c_object_list;
lp = db_list_first(&h->lists_mgmt, list_type, object);
break;
default:
*status = rpc_s_invalid_inquiry_type;
return;
}
}
else
{
db_get_context(h, entry_handle, &list_type, &lp, &pass, status);
if (! STATUS_OK(status))
{
*entry_handle = NULL;
return;
}
switch ((int)inquiry_type)
{
case rpc_c_ep_all_elts:
if (list_type != db_c_entry_list)
*status = ept_s_invalid_context;
break;
case rpc_c_ep_match_by_if:
case rpc_c_ep_match_by_both:
if (list_type != db_c_interface_list)
*status = ept_s_invalid_context;
break;
case rpc_c_ep_match_by_obj:
if (list_type != db_c_object_list)
*status = ept_s_invalid_context;
break;
default:
*status = rpc_s_invalid_inquiry_type;
break;
}
if (! STATUS_OK(status))
{
db_delete_context(h, entry_handle);
return;
}
}
lookup_match(inquiry_type, object, interface, vers_option, max_ents, num_ents, entries, list_type,
&lp, status);
if (! STATUS_OK(status))
{
db_delete_context(h, entry_handle);
for (i = 0; i < *num_ents; i++)
rpc_ss_free(entries[i].tower);
*num_ents = 0;
return;
}
db_save_context(h, entry_handle, list_type, lp, pass);
if (*num_ents == 0)
{
SET_STATUS(status, ept_s_not_registered);
}
}
INTERNAL void lookup_match(inquiry_type, object, interface, vers_option, max_ents, num_ents, entries, list_type,
lpp, status)
unsigned32 inquiry_type;
uuid_p_t object;
rpc_if_id_p_t interface;
unsigned32 vers_option;
unsigned32 max_ents;
unsigned32 *num_ents;
ept_entry_t entries[];
unsigned32 list_type;
db_lists_t **lpp;
error_status_t *status;
{
boolean32 match;
db_lists_t *lp;
db_entry_t *entp;
error_status_t tmp_st;
for (lp = *lpp; lp != NULL; lp = db_list_next(list_type, lp))
{
entp = (db_entry_t *) lp;
if (entp->delete_flag) continue;
match = false;
switch ((int)inquiry_type)
{
case rpc_c_ep_all_elts:
match = true;
break;
case rpc_c_ep_match_by_if:
if (uuid_equal(&interface->uuid, &entp->interface.uuid, &tmp_st))
match = true;
break;
case rpc_c_ep_match_by_obj:
if (uuid_equal(object, &entp->object, &tmp_st))
match = true;
break;
case rpc_c_ep_match_by_both:
if (uuid_equal(&interface->uuid, &entp->interface.uuid, &tmp_st) &&
uuid_equal(object, &entp->object, &tmp_st))
match = true;
break;
default:
assert(status != NULL);
*status = rpc_s_invalid_inquiry_type;
return;
}
if (match)
{
if ((inquiry_type == rpc_c_ep_match_by_if) || (inquiry_type == rpc_c_ep_match_by_both))
{
match = false;
switch ((int)vers_option)
{
case rpc_c_vers_all:
match = true;
break;
case rpc_c_vers_compatible:
if ((interface->vers_major == entp->interface.vers_major) &&
(interface->vers_minor <= entp->interface.vers_minor))
match = true;
break;
case rpc_c_vers_exact:
if ((interface->vers_major == entp->interface.vers_major) &&
(interface->vers_minor == entp->interface.vers_minor))
match = true;
break;
case rpc_c_vers_major_only:
if (interface->vers_major == entp->interface.vers_major)
match = true;
break;
case rpc_c_vers_upto:
if (interface->vers_major > entp->interface.vers_major)
match = true;
else
if ((interface->vers_major == entp->interface.vers_major) &&
(interface->vers_minor >= entp->interface.vers_minor))
match = true;
break;
default:
assert(status != NULL);
*status = rpc_s_invalid_vers_option;
return;
}
}
}
if (match)
{
if (*num_ents >= max_ents)
{
break;
}
epdb_to_ept(entp, &entries[*num_ents], status);
if (! STATUS_OK(status)) return;
(*num_ents)++;
}
}
*lpp = lp;
SET_STATUS_OK(status);
}
PRIVATE void epdb_fwd(h_, object, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor,
addr, map_handle, max_ents, num_ents, fwd_addrs, status)
epdb_handle_t h_;
uuid_p_t object;
rpc_if_id_p_t interface;
rpc_syntax_id_p_t data_rep;
rpc_protocol_id_t rpc_protocol;
unsigned32 rpc_protocol_vers_major;
unsigned32 rpc_protocol_vers_minor;
rpc_addr_p_t addr;
ept_lookup_handle_t *map_handle;
unsigned32 max_ents;
unsigned32 *num_ents;
rpc_addr_p_t fwd_addrs[];
unsigned32 *status;
{
struct db *h = (struct db *) h_;
rpc_if_rep_p_t mgmt_if_rep;
db_entry_t **db_entries;
unsigned32 start_ent;
unsigned32 i;
error_status_t tmp_st;
mgmt_if_rep = (rpc_if_rep_p_t) mgmt_v1_0_s_ifspec;
if (db_different_context(h, map_handle, status))
return;
db_entries = (db_entry_t **) malloc(max_ents * sizeof(db_entry_p_t));
db_lock(h);
if ((fwd_addrs == NULL) || (db_entries == NULL) || (max_ents == 0) || (*num_ents > max_ents))
{
if (db_entries != NULL) free(db_entries);
db_delete_context(h, map_handle);
SET_STATUS(status, ept_s_cant_perform_op);
db_unlock(h);
return;
}
start_ent = *num_ents;
if (uuid_equal(&interface->uuid, &mgmt_if_rep->id, &tmp_st))
map_mgmt(h, object, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, addr->rpc_protseq_id,
map_handle, max_ents, num_ents, db_entries, status);
else
map(h, object, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, addr->rpc_protseq_id,
map_handle, max_ents, num_ents, db_entries, status);
if (! STATUS_OK(status))
{
free(db_entries);
db_unlock(h);
return;
}
for (i = start_ent; i < *num_ents; i++)
{
rpc__naf_addr_copy(db_entries[i]->addr, &fwd_addrs[i], status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
*num_ents = i;
if (*num_ents > 0)
{
SET_STATUS_OK(status);
}
else
{
SET_STATUS(status, ept_s_cant_perform_op);
}
break;
}
}
free(db_entries);
db_unlock(h);
}
PRIVATE void epdb_map(h_, object, map_tower, map_handle, max_ents, num_ents, fwd_towers, status)
epdb_handle_t h_;
uuid_p_t object;
twr_p_t map_tower;
ept_lookup_handle_t *map_handle;
unsigned32 max_ents;
unsigned32 *num_ents;
twr_t *fwd_towers[];
unsigned32 *status;
{
struct db *h = (struct db *) h_;
twr_fields_t twr_fields, *tfp;
rpc_if_rep_p_t mgmt_if_rep;
db_entry_t **db_entries;
unsigned32 start_ent;
unsigned32 i;
error_status_t tmp_st;
tfp = &twr_fields;
mgmt_if_rep = (rpc_if_rep_p_t) mgmt_v1_0_s_ifspec;
if (db_different_context(h, map_handle, status))
return;
db_lock(h);
tower_to_fields(map_tower, &twr_fields, status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
SET_STATUS(status, ept_s_invalid_entry);
db_unlock(h);
return;
}
epdb_chk_map_entry(&twr_fields, status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
SET_STATUS(status, ept_s_invalid_entry);
db_unlock(h);
return;
}
db_entries = (db_entry_t **) malloc(max_ents * sizeof(db_entry_p_t));
if ((db_entries == NULL) || (fwd_towers == NULL) || (max_ents == 0) || (*num_ents > max_ents))
{
if (db_entries != NULL) free(db_entries);
db_delete_context(h, map_handle);
assert(status != NULL);
SET_STATUS(status, ept_s_cant_perform_op);
db_unlock(h);
return;
}
start_ent = *num_ents;
if (uuid_equal(&tfp->interface.uuid, &mgmt_if_rep->id, &tmp_st))
map_mgmt(h, object, &tfp->data_rep,
tfp->rpc_protocol, tfp->rpc_protocol_vers_major, tfp->rpc_protocol_vers_minor,
tfp->protseq, map_handle, max_ents, num_ents, db_entries, status);
else
map(h, object, &tfp->interface, &tfp->data_rep,
tfp->rpc_protocol, tfp->rpc_protocol_vers_major, tfp->rpc_protocol_vers_minor,
tfp->protseq, map_handle, max_ents, num_ents, db_entries, status);
if (! STATUS_OK(status))
{
free(db_entries);
db_unlock(h);
return;
}
for (i = start_ent; i < *num_ents; i++)
{
tower_ss_copy(&(db_entries[i]->tower), &fwd_towers[i], status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
*num_ents = i;
if (*num_ents > 0)
{
SET_STATUS_OK(status);
}
else
{
SET_STATUS(status, ept_s_cant_perform_op);
}
break;
}
}
free(db_entries);
db_unlock(h);
}
INTERNAL void map(h, object, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
map_handle, max_ents, n_ents, db_entries, status)
struct db *h;
uuid_p_t object;
rpc_if_id_p_t interface;
rpc_syntax_id_p_t data_rep;
rpc_protocol_id_t rpc_protocol;
unsigned32 rpc_protocol_vers_major;
unsigned32 rpc_protocol_vers_minor;
rpc_protseq_id_t protseq;
ept_lookup_handle_t *map_handle;
unsigned32 max_ents;
unsigned32 *n_ents;
db_entry_t *db_entries[];
unsigned32 *status;
{
unsigned32 pass;
db_list_type_t list_type;
db_lists_t *lp;
error_status_t tmp_st;
SET_STATUS_OK(status);
if ((map_handle == NULL) || (*map_handle == NULL))
{
if (uuid_is_nil(object, &tmp_st))
{
pass = 2;
list_type = db_c_interface_list;
lp = db_list_first(&h->lists_mgmt, list_type, &interface->uuid);
}
else
{
pass = 1;
list_type = db_c_object_list;
lp = db_list_first(&h->lists_mgmt, list_type, object);
}
}
else
{
db_get_context(h, map_handle, &list_type, &lp, &pass, status);
if (! STATUS_OK(status)) return;
}
if (pass == 1)
{
map_match(
object, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
max_ents, n_ents, db_entries, map_handle, pass, list_type, &lp, status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
return;
}
if ((*n_ents >= max_ents) && ((lp != NULL) || (map_handle == NULL)))
{
db_save_context(h, map_handle, list_type, lp, pass);
return;
}
pass = 2;
list_type = db_c_interface_list;
lp = db_list_first(&h->lists_mgmt, list_type, &interface->uuid);
}
if (pass == 2)
{
map_match(
&nil_uuid, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
max_ents, n_ents, db_entries, map_handle, pass, list_type, &lp, status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
return;
}
}
db_save_context(h, map_handle, list_type, lp, pass);
if (*n_ents == 0)
{
SET_STATUS(status, ept_s_not_registered);
}
}
INTERNAL void map_match(
object, interface, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
max_ents, n_ents, entries, map_handle, pass, list_type, lpp, status)
uuid_p_t object;
rpc_if_id_p_t interface;
rpc_syntax_id_p_t data_rep;
rpc_protocol_id_t rpc_protocol;
unsigned32 rpc_protocol_vers_major;
unsigned32 rpc_protocol_vers_minor ATTRIBUTE_UNUSED;
rpc_protseq_id_t protseq;
unsigned32 max_ents;
unsigned32 *n_ents;
db_entry_t *entries[];
ept_lookup_handle_t *map_handle;
unsigned32 pass ATTRIBUTE_UNUSED;
db_list_type_t list_type;
db_lists_t **lpp;
unsigned32 *status;
{
boolean32 object_nil;
unsigned32 data_rep_vers_major,
data_rep_vers_minor;
unsigned32 tmp_st;
db_lists_t *lp;
db_entry_t *entp;
SET_STATUS_OK(status);
object_nil = uuid_is_nil(object, &tmp_st);
data_rep_vers_major = RPC_IF_VERS_MAJOR(data_rep->version);
data_rep_vers_minor = RPC_IF_VERS_MINOR(data_rep->version);
for (lp = *lpp; lp != NULL; lp = db_list_next(list_type, lp))
{
entp = (db_entry_t *) lp;
if (entp->delete_flag) continue;
if (((object_nil && entp->object_nil) ||
uuid_equal(object, &entp->object, &tmp_st)) &&
uuid_equal(&interface->uuid, &entp->interface.uuid, &tmp_st) &&
(interface->vers_major == entp->interface.vers_major) &&
(interface->vers_minor <= entp->interface.vers_minor) &&
(protseq == entp->addr->rpc_protseq_id) &&
uuid_equal(&data_rep->id, &entp->data_rep_id, &tmp_st) &&
(data_rep_vers_major == entp->data_rep_vers_major) &&
(data_rep_vers_minor <= entp->data_rep_vers_minor) &&
(rpc_protocol == entp->rpc_protocol) &&
(rpc_protocol_vers_major == entp->rpc_protocol_vers_major))
{
if (*n_ents >= max_ents)
{
*lpp = lp;
return;
}
entries[*n_ents] = entp;
(*n_ents)++;
if ((map_handle == NULL) && (*n_ents >= max_ents))
{
*lpp = lp;
return;
}
}
}
*lpp = lp;
}
INTERNAL void map_mgmt(h, object, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
map_handle, max_ents, n_ents, db_entries, status)
struct db *h;
uuid_p_t object;
rpc_syntax_id_p_t data_rep;
rpc_protocol_id_t rpc_protocol;
unsigned32 rpc_protocol_vers_major;
unsigned32 rpc_protocol_vers_minor;
rpc_protseq_id_t protseq;
ept_lookup_handle_t *map_handle;
unsigned32 max_ents;
unsigned32 *n_ents;
db_entry_t *db_entries[];
unsigned32 *status;
{
unsigned32 pass;
db_list_type_t list_type;
db_lists_t *lp;
error_status_t tmp_st;
if (uuid_is_nil(object, &tmp_st))
{
db_delete_context(h, map_handle);
SET_STATUS(status, ept_s_invalid_entry);
return;
}
if ((map_handle == NULL) || (*map_handle == NULL))
{
pass = 1;
list_type = db_c_object_list;
lp = db_list_first(&h->lists_mgmt, list_type, object);
}
else
{
db_get_context(h, map_handle, &list_type, &lp, &pass, status);
if (! STATUS_OK(status)) return;
}
map_mgmt_match(
object, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
max_ents, n_ents, db_entries, map_handle, pass, list_type, &lp, status);
if (! STATUS_OK(status))
{
db_delete_context(h, map_handle);
return;
}
db_save_context(h, map_handle, list_type, lp, pass);
if (*n_ents == 0)
{
assert(status != NULL);
SET_STATUS(status, ept_s_not_registered);
}
}
INTERNAL void map_mgmt_match(
object, data_rep,
rpc_protocol, rpc_protocol_vers_major, rpc_protocol_vers_minor, protseq,
max_ents, n_ents, entries, map_handle, pass, list_type, lpp, status)
uuid_p_t object;
rpc_syntax_id_p_t data_rep;
rpc_protocol_id_t rpc_protocol;
unsigned32 rpc_protocol_vers_major;
unsigned32 rpc_protocol_vers_minor ATTRIBUTE_UNUSED;
rpc_protseq_id_t protseq;
unsigned32 max_ents;
unsigned32 *n_ents;
db_entry_t *entries[];
ept_lookup_handle_t *map_handle;
unsigned32 pass ATTRIBUTE_UNUSED;
db_list_type_t list_type;
db_lists_t **lpp;
unsigned32 *status;
{
unsigned32 data_rep_vers_major,
data_rep_vers_minor;
unsigned32 tmp_st;
db_lists_t *lp;
db_entry_t *entp;
SET_STATUS_OK(status);
data_rep_vers_major = RPC_IF_VERS_MAJOR(data_rep->version);
data_rep_vers_minor = RPC_IF_VERS_MINOR(data_rep->version);
for (lp = *lpp; lp != NULL; lp = db_list_next(list_type, lp))
{
entp = (db_entry_t *) lp;
if (entp->delete_flag) continue;
if (uuid_equal(object, &entp->object, &tmp_st) &&
(protseq == entp->addr->rpc_protseq_id) &&
uuid_equal(&data_rep->id, &entp->data_rep_id, &tmp_st) &&
(data_rep_vers_major == entp->data_rep_vers_major) &&
(data_rep_vers_minor <= entp->data_rep_vers_minor) &&
(rpc_protocol == entp->rpc_protocol) &&
(rpc_protocol_vers_major == entp->rpc_protocol_vers_major) &&
map_mgmt_endpt_unique(entp->addr, *n_ents, entries) )
{
if (*n_ents >= max_ents)
{
*lpp = lp;
return;
}
entries[*n_ents] = entp;
(*n_ents)++;
if ((map_handle == NULL) && (*n_ents >= max_ents))
{
*lpp = lp;
return;
}
}
}
*lpp = lp;
}
INTERNAL boolean32 map_mgmt_endpt_unique(addr, n_ents, entries)
rpc_addr_p_t addr;
unsigned32 n_ents;
db_entry_t *entries[];
{
unsigned32 i;
error_status_t tmp_st;
for (i = 0; i < n_ents; i++)
{
if (rpc__naf_addr_compare(addr, entries[i]->addr, &tmp_st))
return(false);
}
return(true);
}
PRIVATE void epdb_inq_object(h_, object, status)
epdb_handle_t h_;
idl_uuid_t *object;
error_status_t *status;
{
struct db *h = (struct db *) h_;
SET_STATUS_OK(status);
*object = h->object;
}
PRIVATE void epdb_delete_lookup_handle(h_, entry_handle)
epdb_handle_t h_;
ept_lookup_handle_t *entry_handle;
{
struct db *h = (struct db *) h_;
db_lock(h);
db_delete_context(h, entry_handle);
db_unlock(h);
}