Add getmtu and setmtu interface commands

Bug: 9372485

Change-Id: I0dfa6b1f973426d67f976a9c79be8de90e3d9c19
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 3002da6..40d3637 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -522,6 +522,31 @@
                         "Failed to change IPv6 state", true);
             }
             return 0;
+        } else if (!strcmp(argv[1], "getmtu")) {
+            char *msg = NULL;
+            int mtu = 0;
+            if (sInterfaceCtrl->getMtu(argv[2], &mtu) == 0) {
+                asprintf(&msg, "MTU = %d", mtu);
+                cli->sendMsg(ResponseCode::InterfaceGetMtuResult, msg, false);
+                free(msg);
+            } else {
+                cli->sendMsg(ResponseCode::OperationFailed,
+                        "Failed to get MTU", true);
+            }
+            return 0;
+        } else if (!strcmp(argv[1], "setmtu")) {
+            if (argc != 4) {
+                cli->sendMsg(ResponseCode::CommandSyntaxError,
+                        "Usage: interface setmtu <interface> <val>", false);
+                return 0;
+            }
+            if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
+                cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
+            } else {
+                cli->sendMsg(ResponseCode::OperationFailed,
+                        "Failed to get MTU", true);
+            }
+            return 0;
         } else {
             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
             return 0;
diff --git a/InterfaceController.cpp b/InterfaceController.cpp
index 0d8f121..c305be9 100644
--- a/InterfaceController.cpp
+++ b/InterfaceController.cpp
@@ -46,6 +46,8 @@
 
 const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
 
+const char sys_net_path[] = "/sys/class/net";
+
 InterfaceController::InterfaceController()
 	: sendCommand_(NULL) {
 	// Initial IPv6 settings.
@@ -163,3 +165,26 @@
 	closedir(dir);
 	return 0;
 }
+
+int InterfaceController::getMtu(const char *interface, int *mtu)
+{
+	char buf[16];
+	int size = sizeof(buf);
+	char *path;
+	asprintf(&path, "%s/%s/mtu", sys_net_path, interface);
+	int success = readFile(path, buf, &size);
+	if (!success && mtu)
+		*mtu = atoi(buf);
+	free(path);
+	return success;
+
+}
+
+int InterfaceController::setMtu(const char *interface, const char *mtu)
+{
+	char *path;
+	asprintf(&path, "%s/%s/mtu", sys_net_path, interface);
+	int success = writeFile(path, mtu, strlen(mtu));
+	free(path);
+	return success;
+}
diff --git a/InterfaceController.h b/InterfaceController.h
index 5943a9a..b8bbc92 100644
--- a/InterfaceController.h
+++ b/InterfaceController.h
@@ -35,6 +35,8 @@
 	int interfaceCommand(int argc, char *argv[], char **rbuf);
 	int setEnableIPv6(const char *interface, const int on);
 	int setIPv6PrivacyExtensions(const char *interface, const int on);
+	int getMtu(const char *interface, int *mtu);
+	int setMtu(const char *interface, const char *mtu);
 
  private:
 	void *libh_;
diff --git a/NetdConstants.cpp b/NetdConstants.cpp
index 1ab09a5..c3c16eb 100644
--- a/NetdConstants.cpp
+++ b/NetdConstants.cpp
@@ -122,3 +122,24 @@
     close(fd);
     return 0;
 }
+
+int readFile(const char *path, char *buf, int *sizep)
+{
+    int fd = open(path, O_RDONLY);
+    int size;
+
+    if (fd < 0) {
+        ALOGE("Failed to open %s: %s", path, strerror(errno));
+        return -1;
+    }
+
+    size = read(fd, buf, *sizep);
+    if (size < 0) {
+        ALOGE("Failed to write %s: %s", path, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    *sizep = size;
+    close(fd);
+    return 0;
+}
diff --git a/NetdConstants.h b/NetdConstants.h
index eb59af2..d686968 100644
--- a/NetdConstants.h
+++ b/NetdConstants.h
@@ -34,6 +34,7 @@
 int execIptables(IptablesTarget target, ...);
 int execIptablesSilently(IptablesTarget target, ...);
 int writeFile(const char *path, const char *value, int size);
+int readFile(const char *path, char *buf, int *sizep);
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
diff --git a/ResponseCode.h b/ResponseCode.h
index 7689ef8..85f183a 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -45,6 +45,7 @@
     static const int TetheringStatsResult      = 221;
     static const int DnsProxyQueryResult       = 222;
     static const int ClatdStatusResult         = 223;
+    static const int InterfaceGetMtuResult     = 224;
 
     // 400 series - The command was accepted but the requested action
     // did not take place.