Implement protocol version 4.2 86/69986/14
authorVitaliy Cherepanov <v.cherepanov@samsung.com>
Fri, 4 Mar 2016 13:03:44 +0000 (16:03 +0300)
committerAnatolii Nikulin <nikulin.a@samsung.com>
Mon, 8 Aug 2016 14:15:04 +0000 (17:15 +0300)
Depends on manager: Implement protocol version 4.2

add sockets info to MSG_PROCESS_STATUS_INFO

Change-Id: I92fe298dd54188793f3da9d9dff7da206eae776e
Signed-off-by: Vitaliy Cherepanov <v.cherepanov@samsung.com>
parser/usm_msg.c

index 958ebef..801e57c 100644 (file)
 
 
 #include <linux/fs.h>
+#include <linux/net.h>
 #include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/dcache.h>
 #include <linux/fdtable.h>
+#include <linux/file.h>
 #include <linux/version.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/net.h>
 #include <writer/swap_msg.h>
 #include <master/swap_deps.h>
 #include <us_manager/sspt/sspt.h>      /* ... check_vma() */
@@ -492,6 +497,12 @@ struct ofile {
        char path[0];
 } __packed;
 
+struct osock {
+       u32 fd;
+       u32 ip;
+       u32 port;
+} __packed;
+
 static int pack_ofile(void *data, size_t size, int fd, struct file *file,
                      loff_t fsize)
 {
@@ -512,29 +523,84 @@ static int pack_ofile(void *data, size_t size, int fd, struct file *file,
        return sizeof(*ofile) + ret;
 }
 
-static int pack_status_info(void *data, size_t size, struct task_struct *task)
+static int is_file_mode(umode_t mode)
 {
-       int ret, fd;
-       u32 *file_cnt;
-       struct files_struct *files;
-       const size_t old_size = size;
+       return S_ISREG(mode);
+}
 
-       files = swap_get_files_struct(task);
-       if (files == NULL)
-               return -EIO;
+static int pack_osock(void *data, size_t size, int fd, struct file *file,
+                     loff_t fsize)
+{
+       struct osock *pack_sock;
+       struct socket *sock;
+       struct sockaddr_storage addr;
+       struct sockaddr *saddr = (struct sockaddr *)&addr;
+       struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+       int ret_size = sizeof(*pack_sock);
+       int addrlen;
+       int err;
+
+       if (size < sizeof(*pack_sock))
+               return -ENOMEM;
 
-       /* pack pid */
-       *((u32 *)data) = (u32)task->tgid;
-       data += 4;
-       size -= 4;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+       sock = sockfd_lookup(fd, &err);
+#else
+       sock = sock_from_file(file, &err);
+#endif  /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */
+       if (!sock)
+               return 0;
+
+       kernel_getsockname(sock, saddr, &addrlen);
+
+       pack_sock = (struct osock *)data;
+       pack_sock->fd = (u32)fd;
+       pack_sock->ip = (u32)0x0;
+       pack_sock->port = 0;
+
+       switch (saddr->sa_family) {
+       case AF_INET:
+               pack_sock->ip = (u32)(sin->sin_addr.s_addr);
+               pack_sock->port = ntohs(sin->sin_port);
+               break;
+       default:
+               pr_info("[USM] ignored unknown address type: %u\n",
+                       (unsigned int)saddr->sa_family);
+               ret_size = 0;
+               break;
+       }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+       sockfd_put(sock);
+#endif  /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */
+
+       return ret_size;
+}
+
+static int is_sock_mode(umode_t mode)
+{
+       return S_ISSOCK(mode);
+}
+
+typedef int (*pack_func_t)(void *data, size_t size, int fd, struct file *file,
+                           loff_t fsize);
+typedef int (*check_mode_func_t)(umode_t mode);
+
+static int pack_descriptors(void *data, size_t size, pack_func_t pack_func,
+                           check_mode_func_t check_mode,
+                           struct files_struct *files)
+{
+       int ret, fd;
+       const size_t old_size = size;
+       u32 *desc_cnt;
 
-       /* pack file count */
-       file_cnt = (u32 *)data;
-       *file_cnt = 0;
+       /* pack descriptor count */
+       desc_cnt = (u32 *)data;
+       *desc_cnt = 0;
        data += 4;
        size -= 4;
 
-       /* pack file list */
+       /* pack descriptors list */
        rcu_read_lock();
        for (fd = 0; fd < files_fdtable(files)->max_fds; ++fd) {
                struct file *file;
@@ -543,29 +609,67 @@ static int pack_status_info(void *data, size_t size, struct task_struct *task)
 
                file = fcheck_files(files, fd);
                if (file == NULL)
-                        continue;
+                       continue;
 
                inode = file->f_path.dentry->d_inode;
                /* check inode and if it is a regular file */
-               if (inode == NULL || !S_ISREG(inode->i_mode))
+               if (!inode || !check_mode(inode->i_mode))
                        continue;
 
                fsize = inode->i_size;
                rcu_read_unlock();
 
-               ret = pack_ofile(data, size, fd, file, fsize);
-               if (ret < 0)
-                       goto put_fstruct;
-
-               data += ret;
-               size -= ret;
-               ++(*file_cnt);
+               ret = pack_func(data, size, fd, file, fsize);
+               if (ret < 0) {
+                       goto exit;
+               } else if (ret > 0) {
+                       /* increment if data packed only */
+                       data += ret;
+                       size -= ret;
+                       ++(*desc_cnt);
+               }
 
                rcu_read_lock();
        }
+
        rcu_read_unlock();
        ret = old_size - size;
 
+exit:
+       return ret;
+}
+
+static int pack_status_info(void *data, size_t size, struct task_struct *task)
+{
+       int ret;
+       const size_t old_size = size;
+       struct files_struct *files;
+
+       files = swap_get_files_struct(task);
+       if (!files)
+               return -EIO;
+
+       /* pack pid */
+       *((u32 *)data) = (u32)task->tgid;
+       data += 4;
+       size -= 4;
+
+       /* pack file descriptors */
+       ret = pack_descriptors(data, size, pack_ofile, is_file_mode, files);
+       if (ret < 0)
+               goto put_fstruct;
+       data += ret;
+       size -= ret;
+
+       /* pack sock descriptors */
+       ret = pack_descriptors(data, size, pack_osock, is_sock_mode, files);
+       if (ret < 0)
+               goto put_fstruct;
+       data += ret;
+       size -= ret;
+
+       ret = old_size - size;
+
 put_fstruct:
        swap_put_files_struct(files);
        return ret;