librmnetctl: introduce and use rta_put() helper

Every single time we add an RTA to a netlink message in the current code,
we copy-paste the same code. This is very messy and not very maintainable.
This patch adds a function to handle adding the RTA to the netlink
message, and updates the code to call this function in each case.

Change-Id: I4276b31ab8e6c61da299c6d2edf15a38c1370d37
Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
diff --git a/rmnetctl/src/librmnetctl.c b/rmnetctl/src/librmnetctl.c
index 9624b07..a4912d5 100644
--- a/rmnetctl/src/librmnetctl.c
+++ b/rmnetctl/src/librmnetctl.c
@@ -2,7 +2,7 @@
 
 			L I B R M N E T C T L . C
 
-Copyright (c) 2013-2015, 2017-2018 The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2015, 2017-2019 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -1006,6 +1006,29 @@
 /*
  *                       NEW DRIVER API
  */
+
+ /* @brief Add a Routing Attribute to a Netlink message
+  * @param *req The Netlink message we're adding to
+  * @param *reqsize The remaining space within the Netlink message
+  * @param type The type of the RTA to add
+  * @param len The length of the RTA data to add
+  * @param *data A pointer to the RTA data to add
+  * @return RMNETCTL_LIB_ERR if there is not enough space to add the RTA
+  * @return RMNETCTL_SUCCESS if we added the RTA successfully
+  */
+static int rta_put(struct nlmsg *req, size_t *reqsize, int type, int len,
+		   void *data)
+{
+	struct rtattr *attr = NLMSG_TAIL(&req->nl_addr);
+
+	attr->rta_type = type;
+	attr->rta_len = RTA_LENGTH(len);
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attr), reqsize, data, len));
+	req->nl_addr.nlmsg_len = NLMSG_ALIGN(req->nl_addr.nlmsg_len) +
+				 RTA_ALIGN(attr->rta_len);
+
+	return RMNETCTL_SUCCESS;
+}
 /* @brief Synchronous method to receive messages to and from the kernel
  * using netlink sockets
  * @details Receives the ack response from the kernel.
@@ -1128,20 +1151,21 @@
 		       uint16_t *error_code, uint8_t  index,
 		       uint32_t flagconfig)
 {
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct rtattr *datainfo, *linkinfo;
 	struct ifla_vlan_flags flags;
 	unsigned int devindex = 0, val = 0;
 	char *kind = "rmnet";
 	struct nlmsg req;
 	short id;
 	size_t reqsize;
+	int rc;
 
 	if (!hndl || !devname || !vndname || !error_code ||
 	   _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
 		return RMNETCTL_INVALID_ARG;
 
 	memset(&req, 0, sizeof(req));
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL |
@@ -1157,80 +1181,50 @@
 	}
 
 	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	val = RMNETCTL_NUM_TX_QUEUES;
+	rc = rta_put(&req, &reqsize, RMNET_IFLA_NUM_TX_QUEUES, sizeof(val),
+		     &val);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type = RMNET_IFLA_NUM_TX_QUEUES;
-	attrinfo->rta_len = RTA_LENGTH(4);
-	*(int *)RTA_DATA(attrinfo) = RMNETCTL_NUM_TX_QUEUES;
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH((4)));
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	id = index;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_ID;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(id));
-	*(short *)RTA_DATA(attrinfo) = id;
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(id)));
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_ID, sizeof(id), &id);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	if (flagconfig != 0) {
 		flags.mask  = flagconfig;
 		flags.flags = flagconfig;
 
-		attrinfo = (struct rtattr *)(((char *)&req) +
-					     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-		attrinfo->rta_type =  IFLA_VLAN_FLAGS;
-		attrinfo->rta_len = RTA_LENGTH(sizeof(flags));
-		CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flags,
-			       sizeof(flags)));
-		req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-					RTA_ALIGN(RTA_LENGTH(sizeof(flags)));
+		rc = rta_put(&req, &reqsize, IFLA_VLAN_FLAGS, sizeof(flags),
+			     &flags);
+		if (rc != RMNETCTL_SUCCESS)
+			return rc;
 	}
 
 	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
@@ -1283,13 +1277,14 @@
 			  uint16_t *error_code, uint8_t  index,
 			  uint32_t flagconfig)
 {
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct rtattr *datainfo, *linkinfo;
 	struct ifla_vlan_flags flags;
 	char *kind = "rmnet";
 	struct nlmsg req;
-	unsigned int devindex = 0, val = 0;
+	unsigned int devindex = 0;
 	size_t reqsize;
 	short id;
+	int rc;
 
 	memset(&req, 0, sizeof(req));
 
@@ -1297,7 +1292,7 @@
 	    _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
 		return RMNETCTL_INVALID_ARG;
 
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1312,72 +1307,44 @@
 	}
 
 	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	id = index;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_ID;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(id));
-	*(short *)RTA_DATA(attrinfo) = id;
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(id)));
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_ID, sizeof(id), &id);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	if (flagconfig != 0) {
 		flags.mask  = flagconfig;
 		flags.flags = flagconfig;
 
-		attrinfo = (struct rtattr *)(((char *)&req) +
-					     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-		attrinfo->rta_type =  IFLA_VLAN_FLAGS;
-		attrinfo->rta_len = RTA_LENGTH(sizeof(flags));
-		CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flags,
-			       sizeof(flags)));
-		req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-					RTA_ALIGN(RTA_LENGTH(sizeof(flags)));
+		rc = rta_put(&req, &reqsize, IFLA_VLAN_FLAGS, sizeof(flags),
+			     &flags);
+		if (rc != RMNETCTL_SUCCESS)
+			return rc;
 	}
 
 	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
@@ -1396,15 +1363,15 @@
 			  uint16_t *error_code)
 {
 	unsigned int devindex = 0, vndindex = 0;
-	struct rtattr *masterinfo;
 	struct nlmsg req;
 	size_t reqsize;
+	int rc;
 
 	if (!hndl || !vndname || !devname || !error_code || _rmnetctl_check_dev_name(vndname))
 		return RMNETCTL_INVALID_ARG;
 
 	memset(&req, 0, sizeof(req));
-	reqsize = NLMSG_DATA_SIZE - sizeof(*masterinfo);
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1426,14 +1393,11 @@
 
 	/* Setup index attribute */
 	req.ifmsg.ifi_index = devindex;
-	masterinfo = (struct rtattr *)(((char *)&req) +
-				       NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	masterinfo->rta_type =  IFLA_MASTER;
-	masterinfo->rta_len = RTA_LENGTH(sizeof(vndindex));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(masterinfo), &reqsize, &vndindex, sizeof(vndindex)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(vndindex)));
+	rc = rta_put(&req, &reqsize, IFLA_MASTER, sizeof(vndindex), &vndindex);
+	if (rc != RMNETCTL_SUCCESS) {
+		*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+		return rc;
+	}
 
 	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
 		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
@@ -1453,13 +1417,13 @@
 			  uint32_t tcm_handle,
 			  uint16_t *error_code)
 {
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct rtattr *datainfo, *linkinfo;
 	struct tcmsg  flowinfo;
 	char *kind = "rmnet";
 	struct nlmsg req;
 	unsigned int devindex = 0;
-	unsigned int val = 0;
 	size_t reqsize =0;
+	int rc;
 
 	memset(&req, 0, sizeof(req));
 	memset(&flowinfo, 0, sizeof(flowinfo));
@@ -1469,7 +1433,7 @@
 		_rmnetctl_check_dev_name(vndname))
 		return RMNETCTL_INVALID_ARG;
 
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1484,50 +1448,30 @@
 	}
 
 	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	flowinfo.tcm_handle = tcm_handle;
 	flowinfo.tcm_family = 0x1;
@@ -1535,13 +1479,10 @@
 	flowinfo.tcm_ifindex = ip_type;
 	flowinfo.tcm_parent = flow_id;
 
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_EGRESS_QOS, sizeof(flowinfo),
+		     &flowinfo);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
 
@@ -1564,340 +1505,13 @@
 			  int ip_type,
 			  uint16_t *error_code)
 {
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct rtattr *datainfo, *linkinfo;
 	struct tcmsg  flowinfo;
 	char *kind = "rmnet";
 	struct nlmsg req;
 	unsigned int devindex = 0;
-	unsigned int val = 0;
 	size_t reqsize;
-
-	memset(&req, 0, sizeof(req));
-	memset(&flowinfo, 0, sizeof(flowinfo));
-
-	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
-		_rmnetctl_check_dev_name(vndname))
-		return RMNETCTL_INVALID_ARG;
-
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
-	req.nl_addr.nlmsg_type = RTM_NEWLINK;
-	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	req.nl_addr.nlmsg_seq = hndl->transaction_id;
-	hndl->transaction_id++;
-
-	/* Get index of devname*/
-	devindex = if_nametoindex(devname);
-	if (devindex == 0) {
-		*error_code = errno;
-		return RMNETCTL_KERNEL_ERR;
-	}
-
-	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-
-	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	flowinfo.tcm_family = 0x2;
-	flowinfo.tcm_ifindex = ip_type;
-	flowinfo.tcm__pad1 = bearer_id;
-	flowinfo.tcm_parent = flow_id;
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
-
-
-	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
-
-	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
-
-	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
-		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
-		return RMNETCTL_LIB_ERR;
-	}
-
-	return rmnet_get_ack(hndl, error_code);
-}
-
-int rtrmnet_control_flow(rmnetctl_hndl_t *hndl,
-			  char *devname,
-			  char *vndname,
-			  uint8_t bearer_id,
-			  uint16_t sequence,
-			  uint32_t grantsize,
-			  uint8_t ack,
-			  uint16_t *error_code)
-{
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
-	struct tcmsg  flowinfo;
-	char *kind = "rmnet";
-	struct nlmsg req;
-	unsigned int devindex = 0;
-	unsigned int val = 0;
-	size_t reqsize;
-
-	memset(&req, 0, sizeof(req));
-	memset(&flowinfo, 0, sizeof(flowinfo));
-
-	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
-		_rmnetctl_check_dev_name(vndname))
-		return RMNETCTL_INVALID_ARG;
-
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
-	req.nl_addr.nlmsg_type = RTM_NEWLINK;
-	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	req.nl_addr.nlmsg_seq = hndl->transaction_id;
-	hndl->transaction_id++;
-
-	/* Get index of devname*/
-	devindex = if_nametoindex(devname);
-	if (devindex == 0) {
-		*error_code = errno;
-		return RMNETCTL_KERNEL_ERR;
-	}
-
-	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-
-	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	flowinfo.tcm_family = 0x3;
-	flowinfo.tcm__pad1 = bearer_id;
-	flowinfo.tcm__pad2 = sequence;
-	flowinfo.tcm_parent = ack;
-	flowinfo.tcm_info = grantsize;
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
-
-	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
-	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
-
-	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
-		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
-		return RMNETCTL_LIB_ERR;
-	}
-
-	return rmnet_get_ack(hndl, error_code);
-}
-
-
-int rtrmnet_flow_state_up(rmnetctl_hndl_t *hndl,
-			  char *devname,
-			  char *vndname,
-			  uint32_t instance,
-			  uint32_t ep_type,
-			  uint32_t ifaceid,
-			  int flags,
-			  uint16_t *error_code)
-{
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
-	struct tcmsg  flowinfo;
-	char *kind = "rmnet";
-	struct nlmsg req;
-	unsigned int devindex = 0;
-	unsigned int val = 0;
-	size_t reqsize;
-
-	memset(&req, 0, sizeof(req));
-	memset(&flowinfo, 0, sizeof(flowinfo));
-
-	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
-		_rmnetctl_check_dev_name(vndname))
-		return RMNETCTL_INVALID_ARG;
-
-	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
-	req.nl_addr.nlmsg_type = RTM_NEWLINK;
-	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	req.nl_addr.nlmsg_seq = hndl->transaction_id;
-	hndl->transaction_id++;
-
-	/* Get index of devname*/
-	devindex = if_nametoindex(devname);
-	if (devindex == 0) {
-		*error_code = errno;
-		return RMNETCTL_KERNEL_ERR;
-	}
-
-	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-
-	/* Set up IFLA info kind  RMNET that has linkinfo and type */
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
-
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
-
-	flowinfo.tcm_handle = instance;
-	flowinfo.tcm_family = 0x4;
-	flowinfo.tcm_ifindex = flags;
-	flowinfo.tcm_parent = ifaceid;
-	flowinfo.tcm_info = ep_type;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
-
-	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
-	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
-
-	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
-		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
-		return RMNETCTL_LIB_ERR;
-	}
-
-	return rmnet_get_ack(hndl, error_code);
-}
-
-
-int rtrmnet_flow_state_down(rmnetctl_hndl_t *hndl,
-			  char *devname,
-			  char *vndname,
-			  uint32_t instance,
-			  uint16_t *error_code)
-{
-	struct rtattr *attrinfo, *datainfo, *linkinfo;
-	struct tcmsg  flowinfo;
-	char *kind = "rmnet";
-	struct nlmsg req;
-	unsigned int devindex = 0;
-	unsigned int val = 0;
-	size_t reqsize;
+	int rc;
 
 	memset(&req, 0, sizeof(req));
 	memset(&flowinfo, 0, sizeof(flowinfo));
@@ -1921,63 +1535,295 @@
 	}
 
 	/* Setup link attr with devindex as data */
-	val = devindex;
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo->rta_type = IFLA_LINK;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_IFNAME;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	linkinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	flowinfo.tcm_family = 0x2;
+	flowinfo.tcm_ifindex = ip_type;
+	flowinfo.tcm__pad1 = bearer_id;
+	flowinfo.tcm_parent = flow_id;
 
-	linkinfo->rta_type = IFLA_LINKINFO;
-	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_EGRESS_QOS, sizeof(flowinfo),
+		     &flowinfo);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
 
-	attrinfo->rta_type =  IFLA_INFO_KIND;
-	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
 
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
 
-	datainfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	return rmnet_get_ack(hndl, error_code);
+}
 
-	datainfo->rta_type =  IFLA_INFO_DATA;
-	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(0));
+int rtrmnet_control_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint16_t sequence,
+			  uint32_t grantsize,
+			  uint8_t ack,
+			  uint16_t *error_code)
+{
+	struct rtattr *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	unsigned int devindex = 0;
+	size_t reqsize;
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex == 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	flowinfo.tcm_family = 0x3;
+	flowinfo.tcm__pad1 = bearer_id;
+	flowinfo.tcm__pad2 = sequence;
+	flowinfo.tcm_parent = ack;
+	flowinfo.tcm_info = grantsize;
+
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_EGRESS_QOS, sizeof(flowinfo),
+		     &flowinfo);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+
+int rtrmnet_flow_state_up(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint32_t ep_type,
+			  uint32_t ifaceid,
+			  int flags,
+			  uint16_t *error_code)
+{
+	struct rtattr *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	unsigned int devindex = 0;
+	size_t reqsize;
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex == 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	flowinfo.tcm_handle = instance;
+	flowinfo.tcm_family = 0x4;
+	flowinfo.tcm_ifindex = flags;
+	flowinfo.tcm_parent = ifaceid;
+	flowinfo.tcm_info = ep_type;
+
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_EGRESS_QOS, sizeof(flowinfo),
+		     &flowinfo);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+
+int rtrmnet_flow_state_down(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint16_t *error_code)
+{
+	struct rtattr *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	unsigned int devindex = 0;
+	size_t reqsize;
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex == 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	*error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+	rc = rta_put(&req, &reqsize, IFLA_LINK, sizeof(devindex), &devindex);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_IFNAME, strlen(vndname) + 1,
+		     vndname);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	linkinfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_LINKINFO, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	rc = rta_put(&req, &reqsize, IFLA_INFO_KIND, strlen(kind) + 1, kind);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
+
+	datainfo = NLMSG_TAIL(&req.nl_addr);
+	rc = rta_put(&req, &reqsize, IFLA_INFO_DATA, 0, NULL);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 	flowinfo.tcm_handle = instance;
 	flowinfo.tcm_family = 0x5;
 
-	attrinfo = (struct rtattr *)(((char *)&req) +
-				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
-	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
-	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
-	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
-				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+	rc = rta_put(&req, &reqsize, IFLA_VLAN_EGRESS_QOS, sizeof(flowinfo),
+		     &flowinfo);
+	if (rc != RMNETCTL_SUCCESS)
+		return rc;
 
 
 	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;