nwbind: implement NCP 17/4c list object relations
All checks were successful
Source release / source-package (push) Successful in 44s
All checks were successful
Source release / source-package (push) Successful in 44s
Implement the Bindery "List Relations of an Object" endpoint. Parse the NCP 17 subfunction 0x4c request, look up the requested bindery object and set property, and return up to 32 related object IDs from the set property value segments. Support the Novell last-seen cursor convention where 0xffffffff starts a new scan and subsequent calls continue after the last returned object ID. Add a small nwdbm helper for listing set-property members while preserving the existing bindery property read-right checks. Reject wildcard object names with the documented illegal-wildcard completion code.
This commit is contained in:
@@ -206,6 +206,11 @@ extern int nw_delete_obj_from_set(int object_type,
|
||||
int member_type,
|
||||
uint8 *member_name, int member_namlen);
|
||||
|
||||
extern int nw_list_obj_relations(int object_type,
|
||||
uint8 *object_name, int object_namlen,
|
||||
uint8 *prop_name, int prop_namlen,
|
||||
uint32 last_seen,
|
||||
uint32 *relations, int max_relations);
|
||||
|
||||
|
||||
extern int nw_write_prop_value(int object_type,
|
||||
|
||||
29
src/nwbind.c
29
src/nwbind.c
@@ -1466,8 +1466,33 @@ static void handle_fxx(int gelen, int func)
|
||||
break;
|
||||
|
||||
case 0x4c : { /* List Relations of an Object */
|
||||
XDPRINTF((1, 0, "TODO:List Relations of an Object"));
|
||||
completition=0xfb;
|
||||
struct XDATA {
|
||||
uint8 count[2];
|
||||
uint8 relations[32*4];
|
||||
} *xdata = (struct XDATA*) responsedata;
|
||||
uint8 *p = rdata;
|
||||
uint32 last_seen = GET_BE32(p);
|
||||
int object_type = GET_BE16(p+4);
|
||||
int object_namlen = (int)*(p+6);
|
||||
uint8 *object_name = p+7;
|
||||
int prop_namlen = (int)*(p+7+object_namlen);
|
||||
uint8 *prop_name = p+8+object_namlen;
|
||||
uint32 relations[32];
|
||||
int result = nw_list_obj_relations(object_type,
|
||||
object_name, object_namlen,
|
||||
prop_name, prop_namlen,
|
||||
last_seen, relations, 32);
|
||||
if (result > -1) {
|
||||
int k;
|
||||
uint8 *rp = xdata->relations;
|
||||
U16_TO_BE16((uint16)result, xdata->count);
|
||||
for (k=0; k < result; k++) {
|
||||
U32_TO_BE32(relations[k], rp);
|
||||
rp += 4;
|
||||
}
|
||||
data_len = 2 + (result * 4);
|
||||
XDPRINTF((2, 0, "List Relations of an Object count=%d", result));
|
||||
} else completition = (uint8)-result;
|
||||
} break;
|
||||
|
||||
case 0x64 : { /* Create Queue, prehandled by nwconn */
|
||||
|
||||
103
src/nwdbm.c
103
src/nwdbm.c
@@ -999,6 +999,109 @@ int nw_delete_obj_from_set(int object_type,
|
||||
}
|
||||
|
||||
|
||||
static void copy_bindery_packet_name(uint8 *dst, int dst_size,
|
||||
uint8 *src, int src_len)
|
||||
{
|
||||
int len = min(src_len, dst_size - 1);
|
||||
if (len > 0) memcpy(dst, src, len);
|
||||
dst[len] = '\0';
|
||||
}
|
||||
|
||||
static int bindery_packet_name_has_wildcards(uint8 *name, int namlen)
|
||||
{
|
||||
while (namlen-- > 0) {
|
||||
if (*name == '*' || *name == '?') return(1);
|
||||
++name;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int prop_list_members(uint32 obj_id, int prop_id, int prop_security,
|
||||
uint32 last_seen,
|
||||
uint32 *relations, int max_relations)
|
||||
{
|
||||
NETVAL val;
|
||||
int result;
|
||||
int count = 0;
|
||||
int collect = (last_seen == (uint32)0xffffffff);
|
||||
|
||||
if (0 != (result=b_acc(obj_id, prop_security, 0x10))) return(result);
|
||||
|
||||
if (!dbminit(FNVAL)){
|
||||
key.dsize = NETVAL_KEY_SIZE;
|
||||
key.dptr = (char*)&val;
|
||||
val.obj_id = obj_id;
|
||||
val.prop_id = (uint8)prop_id;
|
||||
val.segment = (uint8)0;
|
||||
|
||||
while (val.segment++ < (uint8)255 && count < max_relations) {
|
||||
data = fetch(key);
|
||||
if (data.dptr != NULL){
|
||||
NETVAL *v = (NETVAL*)data.dptr;
|
||||
uint8 *p = v->value;
|
||||
int k = 0;
|
||||
|
||||
while (k++ < 32 && count < max_relations) {
|
||||
uint32 id = GET_BE32(p);
|
||||
|
||||
if (id != 0) {
|
||||
if (collect) {
|
||||
relations[count++] = id;
|
||||
} else if (id == last_seen) {
|
||||
collect = 1;
|
||||
}
|
||||
}
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = count;
|
||||
} else result = -0xff;
|
||||
|
||||
dbmclose();
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
int nw_list_obj_relations(int object_type,
|
||||
uint8 *object_name, int object_namlen,
|
||||
uint8 *prop_name, int prop_namlen,
|
||||
uint32 last_seen,
|
||||
uint32 *relations, int max_relations)
|
||||
{
|
||||
NETOBJ obj;
|
||||
NETPROP prop;
|
||||
int result=-0xff;
|
||||
|
||||
memset(&obj, 0, sizeof(obj));
|
||||
memset(&prop, 0, sizeof(prop));
|
||||
|
||||
if (bindery_packet_name_has_wildcards(object_name, object_namlen))
|
||||
return(-0xf0);
|
||||
|
||||
copy_bindery_packet_name(obj.name, sizeof(obj.name),
|
||||
object_name, object_namlen);
|
||||
copy_bindery_packet_name(prop.name, sizeof(prop.name),
|
||||
prop_name, prop_namlen);
|
||||
obj.type = (uint16)object_type;
|
||||
|
||||
XDPRINTF((2,0, "nw_list_obj_relations obj=%s,0x%x, prop=%s, last=0x%x",
|
||||
obj.name, object_type, prop.name, last_seen));
|
||||
|
||||
if ((result = find_obj_id(&obj)) == 0) {
|
||||
result = find_first_prop_id(&prop, obj.id);
|
||||
if (!result) {
|
||||
if (!(prop.flags & P_FL_SET))
|
||||
result = -0xfb;
|
||||
else
|
||||
result = prop_list_members(obj.id, (int)prop.id, prop.security,
|
||||
last_seen, relations, max_relations);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
int nw_write_prop_value(int object_type,
|
||||
uint8 *object_name, int object_namlen,
|
||||
int segment_nr, int erase_segments,
|
||||
|
||||
Reference in New Issue
Block a user