Index: usr/config.h
===================================================================
--- usr/config.h	(revision 768)
+++ usr/config.h	(working copy)
@@ -193,6 +193,7 @@
 #define ISCSI_TRANSPORT_NAME_MAXLEN 16
 
 typedef struct node_rec {
+	int			id;
 	int			dbversion;
 	char			name[TARGET_NAME_MAXLEN];
 	char			transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
Index: usr/idbm.c
===================================================================
--- usr/idbm.c	(revision 768)
+++ usr/idbm.c	(working copy)
@@ -40,6 +40,9 @@
 #define IDBM_SHOW	1    /* Show parameter when print. */
 #define IDBM_MASKED	2    /* Show "stars" instead of real value when print */
 
+/* Access is protected by db lock */
+static char idbm_hash[HASH_MAXLEN];
+
 #define __recinfo_str(_key, _info, _rec, _name, _show, _n) do { \
 	_info[_n].type = TYPE_STR; \
 	strncpy(_info[_n].name, _key, NAME_MAXVAL); \
@@ -149,6 +152,22 @@
 	return get_global_string_param(pathname, "InitiatorAlias=");
 }
 
+static int
+idbm_uniq_id(char *name)
+{
+	unsigned long h = 0, g;
+	static int M = 0xFFFFFF;
+
+	while (*name) {
+		h = ( h << 4 ) + *name++;
+		if ((g = h & 0xF0000000L))
+			h ^= g >> 23;
+
+		h &= ~g;
+	}
+	return h % M;
+}
+
 static void
 idbm_recinfo_discovery(discovery_rec_t *r, recinfo_t *ri)
 {
@@ -606,7 +625,47 @@
 			strlen((char*)db->nrec.session.auth.password_in);
 }
 
+static int
+idbm_hash_discovery(char *address, unsigned int port)
+{
+	int hash = -1;
+
+	snprintf(idbm_hash, HASH_MAXLEN, "%s:%d",
+		 address, port);
+	hash = idbm_uniq_id(idbm_hash);
+
+	return hash;
+}
+
+static int
+idbm_hash_node(node_rec_t *nrec)
+{
+	int hash = -1;
+
+	snprintf(idbm_hash, HASH_MAXLEN, "%s:%d,%d#%s",
+		 nrec->conn[0].address,
+		 nrec->conn[0].port,
+		 nrec->tpgt,
+		 nrec->name);
+	hash = idbm_uniq_id(idbm_hash);
+
+	return hash;
+}
+
 int
+idbm_hash_session(char *address, int port, int tpgt, char *targetname)
+{
+	char rec_hash[HASH_MAXLEN];
+	int hash = -1;
+
+	snprintf(rec_hash, HASH_MAXLEN, "%s:%d,%d#%s",
+		 address, port, tpgt, targetname);
+	hash = idbm_uniq_id(rec_hash);
+
+	return hash;
+}
+
+int
 idbm_print_discovery(idbm_t *db, discovery_rec_t *rec, int show)
 {
 	idbm_print(PRINT_TYPE_DISCOVERY, rec, show, stdout);
@@ -620,11 +679,12 @@
 	return 1;
 }
 
-int idbm_print_all_discovery(idbm_t *db)
+int idbm_print_all_discovery(idbm_t *db, int compat_mode)
 {
 	DIR *entity_dirfd;
 	struct dirent *entity_dent;
 	char *tmp_port;
+	int port;
 	int found = 0;
 
 	entity_dirfd = opendir(ST_CONFIG_DIR);
@@ -642,9 +702,17 @@
 		if (!tmp_port)
 			continue;
 		*tmp_port++ = '\0';
-
-		printf("%s:%d via sendtargets\n", entity_dent->d_name,
-		       atoi(tmp_port));
+		port = atoi(tmp_port);
+		if (compat_mode) {
+			printf("[%06x] %s:%d via sendtargets\n",
+			       idbm_hash_discovery(entity_dent->d_name, port),
+			       entity_dent->d_name,
+			       port);
+		} else {
+			printf("%s:%d via sendtargets\n",
+			       entity_dent->d_name,
+			       port);
+		}
 		found++;
 	}
 	closedir(entity_dirfd);
@@ -721,7 +789,7 @@
 
 	if (access(LOCK_DIR, F_OK) != 0) {
 		if (mkdir(LOCK_DIR, 0660) != 0) {
-			log_error("Could not open %s. Exiting\n", LOCK_DIR);
+			log_error("Could not open %s. Exiting", LOCK_DIR);
 			exit(-1);
 		}
 	}
@@ -735,6 +803,8 @@
 		if (ret == 0)
 			break;
 
+		log_debug(5, "Waiting for lock on %s ...", LOCK_FILE);
+
 		usleep(10000);
 	}
 
@@ -754,6 +824,61 @@
 }
 
 int
+idbm_discovery_read_by_rid(idbm_t *db, discovery_rec_t *out_rec, int rid)
+{
+	char *portal;
+	char *addr, *ptr, *eptr;
+	int port;
+	DIR *dirfd;
+	struct dirent *dirent;
+
+	memset(out_rec, 0, sizeof(discovery_rec_t));
+
+	portal = malloc(PATH_MAX);
+	if (!portal)
+		return -ENOMEM;
+
+	addr = malloc(NI_MAXHOST);
+	if (!addr)
+		return -ENOMEM;
+
+	snprintf(portal, PATH_MAX, "%s", ST_CONFIG_DIR);
+
+	log_debug(5, "Looking for config file in %s", portal);
+
+	idbm_lock(db);
+
+	if (!(dirfd = opendir(portal))) {
+		log_error("could not read database in %s", portal);
+		idbm_unlock(db);
+		return -EACCES;
+	}
+
+	while ( (dirent = readdir(dirfd)) ) {
+		strcpy(eptr, dirent->d_name);
+
+		log_debug(5, "Checking config file %s", dirent->d_name);
+
+		ptr = strchr(dirent->d_name, ',');
+		if (!ptr)
+			continue;
+		strncpy(addr, dirent->d_name, ptr - dirent->d_name);
+		port = strtoul(ptr + 1, &eptr, 0);
+		if (ptr == eptr) {
+			log_debug(5, "Invalid port number %s", ptr);
+			continue;
+		}
+		if (idbm_hash_discovery(addr, port) == rid) {
+			idbm_unlock(db);
+			return idbm_discovery_read(db, out_rec, addr, port);
+		}
+	}
+	idbm_unlock(db);
+
+	return -ENOENT;
+}
+
+int
 idbm_discovery_read(idbm_t *db, discovery_rec_t *out_rec, char *addr, int port)
 {
 	char *portal;
@@ -817,6 +942,7 @@
 
 	idbm_recinfo_config(db->ninfo, f);
 	memcpy(out_rec, &db->nrec, sizeof(node_rec_t));
+	out_rec->id = idbm_hash_node(out_rec);
 	fclose(f);
 
 free_portal:
@@ -825,6 +951,94 @@
 	return rc;
 }
 
+/*
+ * Inefficient as hell. But then, it's only for compability.
+ */
+int
+idbm_node_read_by_rid(idbm_t *db, node_rec_t *out_rec, int rid)
+{
+	char *portal;
+	char *addr, *ptr, *eptr, *nptr;
+	int port;
+	DIR *tgtdir, *nodedir;
+	struct dirent *tgtent, *nodeent;
+	node_rec_t tmp_rec;
+
+	memset(out_rec, 0, sizeof(discovery_rec_t));
+
+	portal = malloc(PATH_MAX);
+	if (!portal)
+		return -ENOMEM;
+
+	addr = malloc(NI_MAXHOST);
+	if (!addr)
+		return -ENOMEM;
+
+	snprintf(portal, PATH_MAX, "%s", NODE_CONFIG_DIR);
+	nptr = portal + strlen(NODE_CONFIG_DIR);
+
+	log_debug(5, "Looking for config file in %s", portal);
+
+	idbm_lock(db);
+
+	if (!(tgtdir = opendir(portal))) {
+		log_error("could not read database in %s", portal);
+		idbm_unlock(db);
+		return -EACCES;
+	}
+
+	while ( (tgtent = readdir(tgtdir)) ) {
+		if (strncmp(tgtent->d_name, "iqn.", 4))
+			continue;
+
+		log_debug(5, "Checking target %s",
+			  tgtent->d_name);
+		strcpy(tmp_rec.name, tgtent->d_name);
+		tmp_rec.tpgt = 1;
+		strcpy(nptr,"/");
+		strcat(nptr,tgtent->d_name);
+
+		if (!(nodedir = opendir( portal ))) {
+			log_error("could not read database in %s", portal);
+			continue;
+		}
+
+		while ((nodeent = readdir(nodedir))) {
+			strcpy(nptr, nodeent->d_name);
+
+			log_debug(5, "Checking config file %s",
+				  nodeent->d_name);
+
+			ptr = strchr(nodeent->d_name, ',');
+			if (!ptr)
+				continue;
+			strncpy(addr, nodeent->d_name,
+				ptr - nodeent->d_name);
+			port = strtoul(ptr + 1, &eptr, 0);
+			if (ptr == eptr) {
+				log_debug(5, "Invalid port number %s", ptr);
+				continue;
+			}
+			
+			idbm_unlock(db);
+			if (idbm_node_read(db, out_rec, tgtent->d_name,
+					   addr, port))
+				continue;
+
+			if (idbm_hash_node(out_rec) == rid)
+				return 0;
+
+		}
+
+		closedir(nodedir);
+	}
+	closedir(tgtdir);
+	idbm_unlock(db);
+	memset(out_rec, 0, sizeof(discovery_rec_t));
+
+	return -ENOENT;
+}
+
 static int
 idbm_node_write(idbm_t *db, node_rec_t *rec)
 {
@@ -959,7 +1173,13 @@
 int
 idbm_new_node(idbm_t *db, node_rec_t *newrec)
 {
-	return idbm_node_write(db, newrec);
+	int rc;
+
+	idbm_lock(db);
+	rc = idbm_node_write(db, newrec);
+	idbm_unlock(db);
+
+	return rc;
 }
 
 discovery_rec_t*
Index: usr/idbm.h
===================================================================
--- usr/idbm.h	(revision 768)
+++ usr/idbm.h	(working copy)
@@ -65,11 +65,12 @@
 extern char* get_iscsi_initiatoralias(char *pathname);
 extern idbm_t* idbm_init(char *configfile);
 extern void idbm_terminate(idbm_t *db);
+extern int idbm_hash_session(char *address, int port, int tpgt, char *targetname);
 extern int idbm_print_node(idbm_t *db, node_rec_t *rec, int show);
 extern int idbm_for_each_node(idbm_t *db, void *data,
 			     int (* fn)(void *data, node_rec_t *rec));
 extern int idbm_print_discovery(idbm_t *db, discovery_rec_t *rec, int show);
-extern int idbm_print_all_discovery(idbm_t *db);
+extern int idbm_print_all_discovery(idbm_t *db, int compat_mode);
 extern int idbm_delete_discovery(idbm_t *db, discovery_rec_t *rec);
 extern void idbm_node_setup_defaults(node_rec_t *rec);
 extern int idbm_delete_node(idbm_t *db, node_rec_t *rec);
@@ -82,8 +83,11 @@
 extern void idbm_slp_defaults(idbm_t *db, struct iscsi_slp_config *cfg);
 extern int idbm_discovery_read(idbm_t *db, discovery_rec_t *rec, char *addr,
 				int port);
+extern int idbm_discovery_read_by_rid(idbm_t *db, discovery_rec_t *out_rec,
+				      int rid);
 extern int idbm_node_read(idbm_t *db, node_rec_t *out_rec, char *target_name,
 			 char *addr, int port);
+extern int idbm_node_read_by_rid(idbm_t *db, node_rec_t *out_rec, int rid);
 extern int idbm_node_set_param(idbm_t *db, node_rec_t *rec, char *name,
 			       char *value);
 #endif /* IDBM_H */
Index: usr/iscsiadm.c
===================================================================
--- usr/iscsiadm.c	(revision 768)
+++ usr/iscsiadm.c	(working copy)
@@ -47,6 +47,7 @@
 struct iscsi_ipc *ipc = NULL; /* dummy */
 static int ipc_fd = -1;
 static char program_name[] = "iscsiadm";
+static int compat_mode = 1;
 
 char initiator_name[TARGET_NAME_MAXLEN];
 char initiator_alias[TARGET_NAME_MAXLEN];
@@ -67,6 +68,7 @@
 
 static struct option const long_options[] =
 {
+	{"compat", required_argument, NULL, 'c'},
 	{"mode", required_argument, NULL, 'm'},
 	{"portal", required_argument, NULL, 'p'},
 	{"targetname", required_argument, NULL, 'T'},
@@ -86,9 +88,10 @@
 	{"show", no_argument, NULL, 'S'},
 	{"version", no_argument, NULL, 'V'},
 	{"help", no_argument, NULL, 'h'},
+	{"session", required_argument, NULL, 'P'},
 	{NULL, 0, NULL, 0},
 };
-static char *short_options = "iRlVhm:p:T:U:L:d:r:n:v:o:sSt:u";
+static char *short_options = "ciRlVhm:p:T:U:L:d:r:n:v:o:sSt:uP:";
 
 static void usage(int status)
 {
@@ -97,11 +100,11 @@
 			program_name);
 	else {
 		printf("\
-iscsiadm -m discovery [ -dhV ] [ -t type -p ip:port [ -l ] ] | [ -p ip:port ] \
+iscsiadm -m discovery [ -cdhV ] [ -t type -p ip:port [ -l ] ] | [ -p ip:port ] \
 [ -o operation ] [ -n name ] [ -v value ]\n\
-iscsiadm -m node [ -dhV ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port | -M sysdir ] [ -l | -u ] ] \
+iscsiadm -m node [ -cdhV ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port | -P sysdir | -r recordid ] [ -l | -u ] ] \
 [ [ -o  operation  ] [ -n name ] [ -v value ] [ -p ip:port ] ]\n\
-iscsiadm -m session [ -dhV ] [ -r sessionid [ -i | -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n");
+iscsiadm -m session [ -dhV ] [ [ -r recordid:sessionid | -P sysdir ] [ -i | -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n");
 	}
 	exit(status == 0 ? 0 : -1);
 }
@@ -161,6 +164,29 @@
 }
 
 static int
+str_to_ridsid(char *str, int *sid)
+{
+	char *ptr, *eptr;
+	int rid;
+
+	if ((ptr = strchr(str, ':'))) {
+		*ptr = '\0';
+		ptr++;
+		*sid = strtoul(str, &eptr, 10);
+		if (eptr == str)
+			*sid = -1;
+	} else {
+		*sid = -1;
+		ptr = str;
+	}
+
+	rid = strtoul(ptr, &eptr, 16);
+	if (eptr == ptr)
+		rid = -1;
+	return rid;
+}
+
+static int
 session_login(node_rec_t *rec)
 {
 	iscsiadm_req_t req;
@@ -381,8 +407,15 @@
 static int
 print_node_info(void *data, node_rec_t *rec)
 {
-	printf("%s:%d,%d %s\n", rec->conn[0].address, rec->conn[0].port,
-	       rec->tpgt, rec->name);
+	if (compat_mode) {
+		printf("[%06x] %s:%d,%d %s\n", rec->id,
+		       rec->conn[0].address, rec->conn[0].port,
+		       rec->tpgt, rec->name);
+	} else {
+		printf("%s:%d,%d %s\n",
+		       rec->conn[0].address, rec->conn[0].port,
+		       rec->tpgt, rec->name);
+	}
 	return 0;
 }
 
@@ -480,9 +513,18 @@
 	provider = get_transport_by_sid(sid);
 
 	if (!extended) {
-		printf("%s: [%d] %s:%d,%d %s\n",
-			provider ? provider->name : "NA",
-			sid, address, port, tpgt, targetname);
+		if (compat_mode) {
+			int rid;
+
+			rid = idbm_hash_session(address, port, tpgt, targetname);
+
+			printf("%s: [%d:%06x] %s:%d,%d %s\n",
+			       provider ? provider->name : "NA", sid,
+			       rid, address, port, tpgt, targetname);
+		} else
+			printf("%s: [%d] %s:%d,%d %s\n",
+			       provider ? provider->name : "NA",
+			       sid, address, port, tpgt, targetname);
 		return 0;
 	}
 
@@ -776,88 +818,100 @@
 	exit(1);
 }
 
-static int exec_node_op(idbm_t *db, int op, int do_login, int do_logout,
-			int do_show, char *targetname,
-			char *ip, int port, char *name, char *value)
+static int exec_node_op_common(idbm_t *db, int op, int do_login, int do_logout,
+			int do_show, node_rec_t *rec, char *name, char *value)
 {
 	int rc = 0;
-	node_rec_t rec;
 
-	memset(&rec, 0, sizeof(node_rec_t));
+	if (do_login && do_logout) {
+		log_error("either login or "
+			  "logout at the time allowed!");
+		rc = -1;
+		goto out;
+	}
 
-	if (targetname && ip && op != OP_NEW) {
-		log_debug(2, "%s: node [%s,%s,%d]", __FUNCTION__,
-			  targetname, ip, port);
-		if (idbm_node_read(db, &rec, targetname, ip, port)) {
-			log_error("node [%s, %s, %d] not found!",
-				  targetname, ip, port);
+	if ((do_login || do_logout) && op >= 0) {
+		log_error("either operation or login/logout "
+			  "at the time allowed!");
+		rc = -1;
+		goto out;
+	}
+
+	if (!do_login && !do_logout && op < 0) {
+		if (!idbm_print_node(db, rec, do_show)) {
+			log_error("no records found!");
 			rc = -1;
-			goto out;
 		}
+		goto out;
+	}
 
-		if (do_login && do_logout) {
-			log_error("either login or "
-				  "logout at the time allowed!");
+	if (do_login) {
+		if ((rc = session_login(rec)) > 0) {
+			iscsid_handle_error(rc);
 			rc = -1;
-			goto out;
 		}
+		goto out;
+	}
 
-		if ((do_login || do_logout) && op >= 0) {
-			log_error("either operation or login/logout "
-				  "at the time allowed!");
+	if (do_logout) {
+		if ((rc = session_logout(rec)) > 0) {
+			iscsid_handle_error(rc);
 			rc = -1;
-			goto out;
 		}
+		goto out;
+	}
 
-		if (!do_login && !do_logout && op < 0) {
-			if (!idbm_print_node(db, &rec, do_show)) {
-				log_error("no records found!");
-				rc = -1;
-			}
+	if (op == OP_UPDATE) {
+		if (!name || !value) {
+			log_error("update require name and "
+				  "value");
+			rc = -1;
 			goto out;
-
 		}
-
-		if (do_login) {
-			if ((rc = session_login(&rec)) > 0) {
-				iscsid_handle_error(rc);
-				rc = -1;
-			}
+		
+		if ((rc = idbm_node_set_param(db, rec,
+					      name, value))) {
+			log_error("can not set parameter");
 			goto out;
 		}
-
-		if (do_logout) {
-			if ((rc = session_logout(&rec)) > 0) {
-				iscsid_handle_error(rc);
-				rc = -1;
-			}
+	} else if (op == OP_DELETE) {
+		if (idbm_delete_node(db, rec)) {
+			log_error("can not delete record");
+			rc = -1;
 			goto out;
 		}
+	} else {
+		log_error("operation is not supported.");
+		rc = -1;
+		goto out;
+	}
 
-		if (op == OP_UPDATE) {
-			if (!name || !value) {
-				log_error("update require name and "
-					  "value");
-				rc = -1;
-				goto out;
-			}
+out:
+	return rc;
+}
 
-			if ((rc = idbm_node_set_param(db, &rec,
-				      name, value))) {
-				log_error("can not set parameter");
-				goto out;
-			}
-		} else if (op == OP_DELETE) {
-			if (idbm_delete_node(db, &rec)) {
-				log_error("can not delete record");
-				rc = -1;
-				goto out;
-			}
-		} else {
-			log_error("operation is not supported.");
+static int exec_node_op(idbm_t *db, int op, int do_login, int do_logout,
+			int do_show, char *targetname,
+			char *ip, int port, char *name, char *value)
+{
+	int rc = 0;
+	node_rec_t rec;
+
+	memset(&rec, 0, sizeof(node_rec_t));
+
+	if (targetname && ip && op != OP_NEW) {
+		log_debug(2, "%s: node [%s,%s,%d]", __FUNCTION__,
+			  targetname, ip, port);
+		if (idbm_node_read(db, &rec, targetname, ip, port)) {
+			log_error("node [%s, %s, %d] not found!",
+				  targetname, ip, port);
 			rc = -1;
 			goto out;
 		}
+		
+		rc = exec_node_op_common(db, op, do_login, do_logout, do_show,
+					 &rec, name, value);
+
 	} else if (op < 0 || op == OP_SHOW) {
 		if (!idbm_for_each_node(db, NULL, print_node_info)) {
 			log_error("no records found!");
@@ -883,7 +937,8 @@
 		}
 		printf("new iSCSI node record added\n");
 	} else if (op == OP_DELETE) {
-		log_error("--record required for delete operation");
+		log_error("portal and target required to delete "
+			  "a node record");
 		rc = -1;
 		goto out;
 	} else {
@@ -896,8 +951,48 @@
 	return rc;
 }
 
-static int parse_sid(char *session)
+static int exec_node_op_by_rid(idbm_t *db, int op, int do_login, int do_logout,
+			       int do_show, int rid, char *name, char *value)
 {
+	int rc = 0;
+	node_rec_t rec;
+
+	memset(&rec, 0, sizeof(node_rec_t));
+
+	if (rid >= 0 && op != OP_NEW) {
+		log_debug(2, "%s: node [%06x]", __FUNCTION__, rid);
+		if (idbm_node_read_by_rid(db, &rec, rid)) {
+			log_error("node [%06x] not found!", rid);
+			rc = -1;
+			goto out;
+		}
+		
+		rc = exec_node_op_common(db, op, do_login, do_logout, do_show,
+					 &rec, name, value);
+
+	} else if (op < 0 || op == OP_SHOW) {
+		if (!idbm_for_each_node(db, NULL, print_node_info)) {
+			log_error("no records found!");
+			rc = -1;
+			goto out;
+		}
+	} else if (op == OP_DELETE) {
+		log_error("record id is required to delete "
+			  "a node record");
+		rc = -1;
+		goto out;
+	} else {
+		log_error("operation is not supported.");
+		rc = -1;
+		goto out;
+	}
+
+out:
+	return rc;
+}
+
+static int parse_sysfs_session(char *session)
+{
 	struct stat statb;
 	char sys_session[64], *start, *last;
 	int sid = -1, len;
@@ -953,7 +1048,7 @@
 	char *ip = NULL, *name = NULL, *value = NULL;
 	char *targetname = NULL, *group_session_mgmt_mode = NULL;
 	int ch, longindex, mode=-1, port=-1, do_login=0, do_rescan=0, do_info=0;
-	int rc=0, sid=-1, op=-1, type=-1, do_logout=0, do_stats=0, do_show=0;
+	int rc=0, rid=-1, sid=-1, op=-1, type=-1, do_logout=0, do_stats=0, do_show=0;
 	int do_login_all=0, do_logout_all=0;
 	idbm_t *db;
 	struct sigaction sa_old;
@@ -981,6 +1076,9 @@
 	while ((ch = getopt_long(argc, argv, short_options,
 				 long_options, &longindex)) >= 0) {
 		switch (ch) {
+		case 'c':
+			compat_mode = atoi(optarg);
+			break;
 		case 't':
 			type = str_to_type(optarg);
 			break;
@@ -999,7 +1097,15 @@
 			value = optarg;
 			break;
 		case 'r':
-			sid = parse_sid(optarg);
+			rid = str_to_ridsid(optarg, &sid);
+			if (rid < 0) {
+				log_error("invalid record '%s'",
+					  optarg);
+				return -1;
+			}
+			break;
+		case 'P':
+			sid = parse_sysfs_session(optarg);
 			if (sid < 0) {
 				log_error("invalid sid '%s'",
 					  optarg);
@@ -1068,7 +1174,7 @@
 	}
 
 	if (mode == MODE_DISCOVERY) {
-		if ((rc = verify_mode_params(argc, argv, "dmtplo", 0))) {
+		if ((rc = verify_mode_params(argc, argv, "cdmtplor", 0))) {
 			log_error("discovery mode: option '-%c' is not "
 				  "allowed/supported", rc);
 			rc = -1;
@@ -1148,9 +1254,50 @@
 					rc = -1;
 					goto out;
 				}
+			} else if (rid >= 0) {
+				discovery_rec_t rec;
 
+				if (idbm_discovery_read_by_rid(db, &rec, rid)) {
+					log_error("discovery record [%06x] "
+						  "not found!", rid);
+					rc = -1;
+					goto out;
+				}
+				if (do_login &&
+				    rec.type == DISCOVERY_TYPE_SENDTARGETS) {
+					do_sendtargets(db, &rec.u.sendtargets);
+				} else if (do_login &&
+					   rec.type == DISCOVERY_TYPE_SLP) {
+					log_error("SLP discovery is not fully "
+						  "implemented yet.");
+					rc = -1;
+					goto out;
+				} else if (do_login &&
+					   rec.type == DISCOVERY_TYPE_ISNS) {
+					log_error("iSNS discovery is not fully "
+						  "implemented yet.");
+					rc = -1;
+					goto out;
+				} else if (op < 0 || op == OP_SHOW) {
+					if (!idbm_print_discovery(db, &rec,
+								  do_show)) {
+						log_error("no records found!");
+						rc = -1;
+					}
+				} else if (op == OP_DELETE) {
+					if (idbm_delete_discovery(db, &rec)) {
+						log_error("unable to delete "
+							   "record!");
+						rc = -1;
+					}
+				} else {
+					log_error("operation is not supported.");
+					rc = -1;
+					goto out;
+				}
+
 			} else if (op < 0 || op == OP_SHOW) {
-				if (!idbm_print_all_discovery(db)) {
+				if (!idbm_print_all_discovery(db, compat_mode)) {
 					log_error("no records found!");
 					rc = -1;
 				}
@@ -1168,7 +1315,7 @@
 			}
 		}
 	} else if (mode == MODE_NODE) {
-		if ((rc = verify_mode_params(argc, argv, "dmlSonvupTUL",
+		if ((rc = verify_mode_params(argc, argv, "cdmlSonvupTULr",
 					     0))) {
 			log_error("node mode: option '-%c' is not "
 				  "allowed/supported", rc);
@@ -1186,11 +1333,15 @@
 			goto out;
 		}
 
-		rc = exec_node_op(db, op, do_login, do_logout, do_show,
-				  targetname, ip, port, name, value);
+		if (rid >= 0) 
+			rc = exec_node_op_by_rid(db, op, do_login, do_logout,
+						 do_show, rid, name, value);
+		else
+			rc = exec_node_op(db, op, do_login, do_logout, do_show,
+					  targetname, ip, port, name, value);
 		goto out;
 	} else if (mode == MODE_SESSION) {
-		if ((rc = verify_mode_params(argc, argv, "iRdrmusonuSv", 1))) {
+		if ((rc = verify_mode_params(argc, argv, "ciRdrmusonuSv", 1))) {
 			log_error("session mode: option '-%c' is not "
 				  "allowed or supported", rc);
 			rc = -1;
