rmnetctl: Added support for creating VNDs with a custom prefix

Adding support for creating virtual RmNet Data device nodes with
a custom name prefix. Required to support reverse RmNet naming
conventions.

CRs-Fixed: 555507
Change-Id: Ie2b8d25fd9575a00c246061e0deb2aa1d541457b
diff --git a/rmnetctl/cli/rmnetcli.c b/rmnetctl/cli/rmnetcli.c
index 7fe8a60..405626d 100644
--- a/rmnetctl/cli/rmnetcli.c
+++ b/rmnetctl/cli/rmnetcli.c
@@ -166,12 +166,21 @@
 	printf(_5TABS" larger than 15 ");
 	printf(_5TABS" characters. Returns the");
 	printf(_5TABS" status code\n\n");
-	printf("rmnetcli newvnd <dev_name>               Creates a new");
+	printf("rmnetcli newvnd <dev_id>                 Creates a new");
 	printf(_5TABS" virtual network device node.");
-	printf(_5TABS" dev_name cannot be");
-	printf(_5TABS" larger than 15. Returns");
+	printf(_5TABS" dev_id is an int");
+	printf(_5TABS" less than 32. Returns");
 	printf(_5TABS" the status code\n\n");
-	printf("rmnetcli freevnd <dev_name>              Removes virtual");
+	printf("rmnetcli newvndprefix <dev_id> <name_prefix>   Creates");
+	printf(_5TABS" virtual network device node.");
+	printf(_5TABS" dev_id is an int");
+	printf(_5TABS" less than 32. Prefix");
+	printf(_5TABS" must be less than");
+	printf(_5TABS" 15 chars. Returns");
+	printf(_5TABS" the status code\n\n");
+	printf("rmnetcli getvndname <dev_id>              Get name of");
+	printf(_5TABS" network device node from id");
+	printf("rmnetcli freevnd <dev_id>              Removes virtual");
 	printf(_5TABS" network device node. dev_name");
 	printf(_5TABS" cannot be larger than 15.");
 	printf(_5TABS" Returns the status code\n\n");
@@ -280,10 +289,24 @@
 		if (return_code == RMNETCTL_SUCCESS) {
 			printf("ingress_flags is %u\n", ingress_flags);
 		}
+	} else if (!strcmp(*argv, "newvndprefix")) {
+		_RMNETCLI_CHECKNULL(argv[1]);
+		_RMNETCLI_CHECKNULL(argv[2]);
+		return_code = rmnet_new_vnd_prefix(handle,
+		_STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND, argv[2]);
 	} else if (!strcmp(*argv, "newvnd")) {
 		_RMNETCLI_CHECKNULL(argv[1]);
 		return_code = rmnet_new_vnd(handle,
 		_STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
+	} else if (!strcmp(*argv, "getvndname")) {
+		char buffer[32];
+		memset(buffer, 0, 32);
+		_RMNETCLI_CHECKNULL(argv[1]);
+		return_code = rmnet_get_vnd_name(handle, _STRTOUI32(argv[1]),
+			           &error_number, buffer, 32);
+		if (return_code == RMNETCTL_SUCCESS) {
+			printf("VND name: %s\n", buffer);
+		}
 	} else if (!strcmp(*argv, "freevnd")) {
 		_RMNETCLI_CHECKNULL(argv[1]);
 		return_code = rmnet_new_vnd(handle,
diff --git a/rmnetctl/inc/librmnetctl.h b/rmnetctl/inc/librmnetctl.h
index c686165..29ce442 100644
--- a/rmnetctl/inc/librmnetctl.h
+++ b/rmnetctl/inc/librmnetctl.h
@@ -316,8 +316,8 @@
 * @brief Public API to create a new virtual device node
 * @details Message type is RMNET_NETLINK_NEW_VND or
 * RMNETCTL_FREE_VND based on the flag for new_vnd
-* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
-* @param node_number Node number to create the virtual network device node
+* @param hndl RmNet handle for the Netlink message
+* @param id Node number to create the virtual network device node
 * @param error_code Status code of this operation returned from the kernel
 * @param new_vnd creates a new virtual network device if  RMNETCTL_NEW_VND or
 * frees the device if RMNETCTL_FREE_VND
@@ -332,5 +332,47 @@
 		  uint16_t *error_code,
 		  uint8_t new_vnd);
 
+/*!
+ * @brief Public API to create a new virtual device node with a custom prefix
+ * @details Message type is RMNET_NETLINK_NEW_VND or
+ * RMNETCTL_FREE_VND based on the flag for new_vnd
+ * @param hndl RmNet handle for the Netlink message
+ * @param id Node number to create the virtual network device node
+ * @param error_code Status code of this operation returned from the kernel
+ * @param new_vnd creates a new virtual network device if  RMNETCTL_NEW_VND or
+ * frees the device if RMNETCTL_FREE_VND
+ * @param prefix Prefix to be used when naming the network interface
+ * @return RMNETCTL_SUCCESS if successful
+ * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
+ * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
+ * Check error_code
+ * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
+ */
+int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
+			 uint32_t id,
+			 uint16_t *error_code,
+			 uint8_t new_vnd,
+			 const char *prefix);
+/*!
+ * @brief API to get the ASCII name of a virtual network device from its ID
+ * @param hndl RmNet handle for the Netlink message
+ * @param id Node number to create the virtual network device node
+ * @param error_code Status code of this operation returned from the kernel
+ * @param buf Buffer to store ASCII representation of device name
+ * @param buflen Length of the buffer
+ * @param prefix Prefix to be used when naming the network interface
+ * @return RMNETCTL_SUCCESS if successful
+ * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
+ * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
+ * Check error_code
+ * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
+ */
+
+int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
+                      uint32_t id,
+                      uint16_t *error_code,
+                      char *buf,
+                      uint32_t buflen);
+
 #endif /* not defined LIBRMNETCTL_H */
 
diff --git a/rmnetctl/src/librmnetctl.c b/rmnetctl/src/librmnetctl.c
index ea94d06..2975103 100644
--- a/rmnetctl/src/librmnetctl.c
+++ b/rmnetctl/src/librmnetctl.c
@@ -660,22 +660,37 @@
 	return return_code;
 }
 
-int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
-		  uint32_t id,
-		  uint16_t *error_code,
-		  uint8_t new_vnd) {
+int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
+			 uint32_t id,
+			 uint16_t *error_code,
+			 uint8_t new_vnd,
+			 const char *prefix)
+{
 	struct rmnet_nl_msg_s request, response;
 	int return_code = RMNETCTL_LIB_ERR;
+	int str_len = -1;
 	do {
 	if ((!hndl) || (!error_code) ||
 	((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
 		return_code = RMNETCTL_INVALID_ARG;
 		break;
 	}
-	if (new_vnd ==  RMNETCTL_NEW_VND)
-		request.message_type = RMNET_NETLINK_NEW_VND;
-	else
+
+	memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
+	if (new_vnd ==  RMNETCTL_NEW_VND) {
+		if (prefix) {
+			request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
+			str_len = strlcpy((char *)request.vnd.vnd_name,
+					  prefix, RMNET_MAX_STR_LEN);
+			if (_rmnetctl_check_len(str_len, error_code)
+						!= RMNETCTL_SUCCESS)
+				break;
+		} else {
+			request.message_type = RMNET_NETLINK_NEW_VND;
+		}
+	} else {
 		request.message_type = RMNET_NETLINK_FREE_VND;
+	}
 
 	request.arg_length = sizeof(uint32_t);
 	request.vnd.id = id;
@@ -690,3 +705,51 @@
 	} while(0);
 	return return_code;
 }
+
+int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
+		  uint32_t id,
+		  uint16_t *error_code,
+		  uint8_t new_vnd)
+{
+	return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
+}
+
+int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
+		       uint32_t id,
+		       uint16_t *error_code,
+		       char *buf,
+		       uint32_t buflen)
+{
+	struct rmnet_nl_msg_s request, response;
+	uint32_t str_len;
+	int return_code = RMNETCTL_LIB_ERR;
+	do {
+	if ((!hndl) || (!error_code)) {
+		return_code = RMNETCTL_INVALID_ARG;
+		break;
+	}
+
+	request.message_type = RMNET_NETLINK_GET_VND_NAME;
+	request.arg_length = sizeof(uint32_t);
+	request.vnd.id = id;
+
+
+	if ((*error_code = rmnetctl_transact(hndl, &request, &response))
+		!= RMNETCTL_SUCCESS)
+		break;
+	if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
+		break;
+
+	str_len = strlcpy(buf,
+			  (char *)(response.vnd.vnd_name),
+			  buflen);
+	if (str_len >= buflen) {
+		*error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
+		break;
+	}
+
+	return_code = RMNETCTL_SUCCESS;
+	} while (0);
+	return return_code;
+}
+