Browse Source

[SAL] Update SAL,Add socketpair sendmsg recvmsg function (#8293)

rcitachi 1 year ago
parent
commit
c06f4e98fc

+ 1 - 1
components/dfs/dfs_v2/include/dfs_file.h

@@ -174,7 +174,7 @@ int dfs_file_isdir(const char *path);
 int dfs_file_access(const char *path, mode_t mode);
 int dfs_file_chdir(const char *path);
 char *dfs_file_getcwd(char *buf, size_t size);
-
+char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode);
 #ifdef RT_USING_SMART
 int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
 

+ 1 - 1
components/dfs/dfs_v2/src/dfs_file.c

@@ -207,7 +207,7 @@ struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry)
  *
  * @return new path.
  */
-static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
+char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
 {
     int index = 0;
     char *path = RT_NULL;

+ 123 - 180
components/libc/posix/io/epoll/epoll.c

@@ -24,8 +24,6 @@
 #define EPOLLEXCLUSIVE_BITS (EPOLLINOUT_BITS | EPOLLERR | EPOLLHUP | \
                 EPOLLET | EPOLLEXCLUSIVE)
 
-static struct rt_spinlock spinlock;
-
 struct rt_eventpoll;
 
 /* Monitor queue */
@@ -36,15 +34,10 @@ struct rt_fd_list
     rt_pollreq_t req;
     struct rt_eventpoll *ep;
     struct rt_wqueue_node wqn;
+    int exclusive;/* If triggered horizontally, a check is made to see if the data has been read, and if there is any data left to read, the readability event is returned in the next epoll_wait */
     int fd;
     struct rt_fd_list *next;
-};
-
-struct rt_ready_list
-{
-    int exclusive;/* If triggered horizontally, a check is made to see if the data has been read, and if there is any data left to read, the readability event is returned in the next epoll_wait */
-    struct rt_fd_list *rdl_event; /* rdl: ready list */
-    struct rt_ready_list *next;
+    rt_slist_t rdl_node;
 };
 
 struct rt_eventpoll
@@ -56,7 +49,8 @@ struct rt_eventpoll
     struct rt_fd_list *fdlist;  /* Monitor list */
     int eventpoll_num;          /* Number of ready lists */
     rt_pollreq_t req;
-    struct rt_ready_list *rdlist; /* ready list */
+    struct rt_spinlock spinlock;
+    rt_slist_t rdl_head;
 };
 
 static int epoll_close(struct dfs_file *file);
@@ -80,32 +74,14 @@ static int epoll_close_fdlist(struct rt_fd_list *fdlist)
         while (list->next != RT_NULL)
         {
             fre_node = list->next;
-            rt_wqueue_remove(&fre_node->wqn);
-            list->next = fre_node->next;
-            rt_free(fre_node);
-        }
-
-        rt_free(fdlist);
-    }
-
-    return 0;
-}
+            if (fre_node->wqn.wqueue)
+                rt_wqueue_remove(&fre_node->wqn);
 
-static int epoll_close_rdlist(struct rt_ready_list *rdlist)
-{
-    struct rt_ready_list *list, *fre_node;
-
-    list = rdlist;
-    if (list)
-    {
-        while (list->next != RT_NULL)
-        {
-            fre_node = list->next;
             list->next = fre_node->next;
             rt_free(fre_node);
         }
 
-        rt_free(rdlist);
+        rt_free(fdlist);
     }
 
     return 0;
@@ -131,11 +107,6 @@ static int epoll_close(struct dfs_file *file)
                     epoll_close_fdlist(ep->fdlist);
                 }
 
-                if (ep->rdlist)
-                {
-                    epoll_close_rdlist(ep->rdlist);
-                }
-
                 rt_mutex_release(&ep->lock);
                 rt_mutex_detach(&ep->lock);
                 rt_free(ep);
@@ -149,8 +120,6 @@ static int epoll_close(struct dfs_file *file)
 static int epoll_poll(struct dfs_file *file, struct rt_pollreq *req)
 {
     struct rt_eventpoll *ep;
-    struct rt_fd_list *fdlist;
-    int mask;
     int events = 0;
 
     if (file->vnode->data)
@@ -158,101 +127,41 @@ static int epoll_poll(struct dfs_file *file, struct rt_pollreq *req)
         ep = file->vnode->data;
         ep->req._key = req->_key;
 
+        rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
         rt_poll_add(&ep->epoll_read, req);
 
-        fdlist = ep->fdlist;
-        if (fdlist)
-        {
-            while (fdlist->next != RT_NULL)
-            {
-                fdlist = fdlist->next;
-                mask = epoll_get_event(fdlist, &fdlist->req);
-
-                if (mask & fdlist->revents)
-                {
-                    events |= mask | POLLIN | EPOLLRDNORM;
-                    break;
-                }
-            }
-        }
-    }
-
-    return events;
-}
-
-static int epoll_rdlist_add(struct rt_fd_list *fdl, rt_uint32_t revents)
-{
-    struct rt_ready_list *rdlist = RT_NULL;
-    struct rt_eventpoll *ep;
-    int isexist = 0;
-    int res = -1;
-
-    ep = fdl->ep;
-
-    if (revents & ep->req._key)
-    {
-        rt_wqueue_wakeup(&ep->epoll_read, (void*)POLLIN);
-    }
+        rt_spin_lock(&ep->spinlock);
 
-    rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
+        if (!rt_slist_isempty(&ep->rdl_head))
+            events |= POLLIN | EPOLLRDNORM | POLLOUT;
 
-    if (ep->rdlist == RT_NULL)
-    {
-        ep->rdlist = (struct rt_ready_list *)rt_malloc(sizeof(struct rt_ready_list));
-        if (ep->rdlist == RT_NULL)
-        {
-            return -1;
-        }
-        ep->rdlist->next = RT_NULL;
-    }
-
-    rdlist = ep->rdlist;
-    while (rdlist->next != RT_NULL)
-    {
-        rdlist = rdlist->next;
-        if (rdlist->rdl_event->fd == fdl->fd)
-        {
-            isexist = 1;
-            res = 0;
-            break;
-        }
-    }
-
-    if (!isexist)
-    {
-        rdlist = RT_NULL;
-        rdlist = (struct rt_ready_list *)rt_malloc(sizeof(struct rt_ready_list));
-        if (rdlist != RT_NULL)
-        {
-            rdlist->rdl_event = fdl;
-            rdlist->rdl_event->epev.events = fdl->revents & revents;
-            rdlist->next = ep->rdlist->next;
-            rdlist->exclusive = 0;
-            ep->rdlist->next = rdlist;
-            ep->eventpoll_num ++;
-            res = 0;
-        }
+        rt_spin_unlock(&ep->spinlock);
+        rt_mutex_release(&ep->lock);
     }
 
-    ep->tirggered = 1;
-
-    rt_mutex_release(&ep->lock);
-
-    return res;
+    return events;
 }
 
 static int epoll_wqueue_callback(struct rt_wqueue_node *wait, void *key)
 {
     struct rt_fd_list *fdlist;
+    struct rt_eventpoll *ep;
 
     if (key && !((rt_ubase_t)key & wait->key))
         return -1;
 
     fdlist = rt_container_of(wait, struct rt_fd_list, wqn);
 
-    if (fdlist->revents)
+    ep = fdlist->ep;
+    if (ep)
     {
-        epoll_rdlist_add(fdlist, (rt_ubase_t)key);
+        rt_spin_lock(&ep->spinlock);
+        rt_slist_append(&ep->rdl_head, &fdlist->rdl_node);
+        fdlist->exclusive = 0;
+        ep->tirggered = 1;
+        ep->eventpoll_num ++;
+        rt_wqueue_wakeup(&ep->epoll_read, (void *)POLLIN);
+        rt_spin_unlock(&ep->spinlock);
     }
 
     return __wqueue_default_wake(wait, key);
@@ -285,7 +194,17 @@ static void epoll_ctl_install(struct rt_fd_list *fdlist, struct rt_eventpoll *ep
 
     if (mask & fdlist->revents)
     {
-        epoll_rdlist_add(fdlist, mask);
+        if (ep)
+        {
+            rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
+            rt_spin_lock(&ep->spinlock);
+            rt_slist_append(&ep->rdl_head, &fdlist->rdl_node);
+            fdlist->exclusive = 0;
+            ep->tirggered = 1;
+            ep->eventpoll_num ++;
+            rt_spin_unlock(&ep->spinlock);
+            rt_mutex_release(&ep->lock);
+        }
     }
 }
 
@@ -294,11 +213,12 @@ static void epoll_member_init(struct rt_eventpoll *ep)
     ep->tirggered = 0;
     ep->eventpoll_num = 0;
     ep->polling_thread = rt_thread_self();
-    ep->rdlist = RT_NULL;
     ep->fdlist = RT_NULL;
     ep->req._key = 0;
+    rt_slist_init(&(ep->rdl_head));
     rt_wqueue_init(&ep->epoll_read);
-    rt_spin_lock_init(&spinlock);
+    rt_mutex_init(&ep->lock, EPOLL_MUTEX_NAME, RT_IPC_FLAG_FIFO);
+    rt_spin_lock_init(&ep->spinlock);
 }
 
 static int epoll_epf_init(int fd)
@@ -316,8 +236,6 @@ static int epoll_epf_init(int fd)
         {
             epoll_member_init(ep);
 
-            rt_mutex_init(&ep->lock, EPOLL_MUTEX_NAME, RT_IPC_FLAG_FIFO);
-
             #ifdef RT_USING_DFS_V2
             df->fops = &epoll_fops;
             #endif
@@ -331,8 +249,10 @@ static int epoll_epf_init(int fd)
                     ep->fdlist->next = RT_NULL;
                     ep->fdlist->fd = fd;
                     ep->fdlist->ep = ep;
+                    ep->fdlist->exclusive = 0;
                     dfs_vnode_init(df->vnode, FT_REGULAR, &epoll_fops);
                     df->vnode->data = ep;
+                    rt_slist_init(&ep->fdlist->rdl_node);
                 }
                 else
                 {
@@ -400,26 +320,33 @@ static int epoll_ctl_add(struct dfs_file *df, int fd, struct epoll_event *event)
         fdlist = ep->fdlist;
         ret = 0;
 
+        rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
         while (fdlist->next != RT_NULL)
         {
             if (fdlist->next->fd == fd)
             {
+                rt_mutex_release(&ep->lock);
                 return 0;
             }
             fdlist = fdlist->next;
         }
+        rt_mutex_release(&ep->lock);
 
         fdlist = (struct rt_fd_list *)rt_malloc(sizeof(struct rt_fd_list));
         if (fdlist)
         {
             fdlist->fd = fd;
             memcpy(&fdlist->epev.data, &event->data, sizeof(event->data));
-            fdlist->epev.events = event->events;
+            fdlist->epev.events = 0;
             fdlist->ep = ep;
+            fdlist->exclusive = 0;
             fdlist->req._proc = epoll_wqueue_add_callback;
-            fdlist->next = ep->fdlist->next;
             fdlist->revents = event->events;
+            rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
+            fdlist->next = ep->fdlist->next;
             ep->fdlist->next = fdlist;
+            rt_mutex_release(&ep->lock);
+            rt_slist_init(&fdlist->rdl_node);
 
             epoll_ctl_install(fdlist, ep);
         }
@@ -434,53 +361,48 @@ static int epoll_ctl_add(struct dfs_file *df, int fd, struct epoll_event *event)
 
 static int epoll_ctl_del(struct dfs_file *df, int fd)
 {
-    struct rt_fd_list *fdlist, *fre_fd;
+    struct rt_fd_list *fdlist, *fre_fd, *rdlist;
     struct rt_eventpoll *ep = RT_NULL;
-    struct rt_ready_list *rdlist, *fre_rdl;
+    rt_slist_t *node = RT_NULL;
     rt_err_t ret = -EINVAL;
 
     if (df->vnode->data)
     {
         ep = df->vnode->data;
 
-        fdlist = ep->fdlist;
-        while (fdlist->next != RT_NULL)
+        if (ep)
         {
-            if (fdlist->next->fd == fd)
+            rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
+            rt_spin_lock(&ep->spinlock);
+            rt_slist_for_each(node, &ep->rdl_head)
             {
-                fre_fd = fdlist->next;
-                fdlist->next = fdlist->next->next;
-                if (fre_fd->epev.events != 0)
-                {
-                    rt_wqueue_remove(&fre_fd->wqn);
-                }
-                rt_free(fre_fd);
-                break;
+                rdlist = rt_slist_entry(node, struct rt_fd_list, rdl_node);
+                if (rdlist->fd == fd)
+                    rt_slist_remove(&ep->rdl_head, node);
             }
-            else
-            {
-                fdlist = fdlist->next;
-            }
-        }
+            rt_spin_unlock(&ep->spinlock);
 
-        if (ep->rdlist)
-        {
-            rdlist = ep->rdlist;
-            while (rdlist->next != RT_NULL)
+            fdlist = ep->fdlist;
+            while (fdlist->next != RT_NULL)
             {
-                if (rdlist->next->rdl_event->fd == fd)
+                if (fdlist->next->fd == fd)
                 {
-                    fre_rdl = rdlist->next;
-                    rdlist->next = rdlist->next->next;
-                    ep->eventpoll_num --;
-                    rt_free(fre_rdl);
+                    fre_fd = fdlist->next;
+                    fdlist->next = fdlist->next->next;
+
+                    if (fre_fd->wqn.wqueue)
+                        rt_wqueue_remove(&fre_fd->wqn);
+
+                    rt_free(fre_fd);
                     break;
                 }
                 else
                 {
-                    rdlist = rdlist->next;
+                    fdlist = fdlist->next;
                 }
             }
+
+            rt_mutex_release(&ep->lock);
         }
 
         ret = 0;
@@ -504,9 +426,13 @@ static int epoll_ctl_mod(struct dfs_file *df, int fd, struct epoll_event *event)
         {
             if (fdlist->next->fd == fd)
             {
+                rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
                 memcpy(&fdlist->next->epev.data, &event->data, sizeof(event->data));
                 fdlist->next->revents = event->events;
-                rt_wqueue_remove(&fdlist->next->wqn);
+                if (fdlist->next->wqn.wqueue)
+                    rt_wqueue_remove(&fdlist->next->wqn);
+
+                rt_mutex_release(&ep->lock);
                 epoll_ctl_install(fdlist->next, ep);
                 break;
             }
@@ -538,10 +464,14 @@ static int epoll_do_ctl(int epfd, int op, int fd, struct epoll_event *event)
         return -1;
     }
 
-    if (!(event->events & EPOLLEXCLUSIVE_BITS))
+    if (!(op & EPOLL_CTL_DEL))
     {
-        rt_set_errno(EINVAL);
-        return -1;
+        if (!(event->events & EPOLLEXCLUSIVE_BITS))
+        {
+            rt_set_errno(EINVAL);
+            return -1;
+        }
+        event->events  |= EPOLLERR | EPOLLHUP;
     }
 
     if (!fd_get(fd))
@@ -555,8 +485,6 @@ static int epoll_do_ctl(int epfd, int op, int fd, struct epoll_event *event)
     if (epdf->vnode->data)
     {
         ep = epdf->vnode->data;
-        event->events  |= EPOLLERR | EPOLLHUP;
-        rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
 
         switch (op)
         {
@@ -583,8 +511,6 @@ static int epoll_do_ctl(int epfd, int op, int fd, struct epoll_event *event)
         {
             ep->polling_thread = rt_thread_self();
         }
-
-        rt_mutex_release(&ep->lock);
     }
 
     return ret;
@@ -601,7 +527,7 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec)
 
     timeout = rt_tick_from_millisecond(msec);
 
-    level = rt_spin_lock_irqsave(&spinlock);
+    level = rt_spin_lock_irqsave(&ep->spinlock);
 
     if (timeout != 0 && !ep->tirggered)
     {
@@ -615,16 +541,16 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec)
                 rt_timer_start(&(thread->thread_timer));
             }
 
-            rt_spin_unlock_irqrestore(&spinlock, level);
+            rt_spin_unlock_irqrestore(&ep->spinlock, level);
 
             rt_schedule();
 
-            level = rt_spin_lock_irqsave(&spinlock);
+            level = rt_spin_lock_irqsave(&ep->spinlock);
         }
     }
 
     ret = !ep->tirggered;
-    rt_spin_unlock_irqrestore(&spinlock, level);
+    rt_spin_unlock_irqrestore(&ep->spinlock, level);
 
     return ret;
 }
@@ -658,7 +584,8 @@ static int epoll_get_event(struct rt_fd_list *fl, rt_pollreq_t *req)
 
 static int epoll_do(struct rt_eventpoll *ep, struct epoll_event *events, int maxevents, int timeout)
 {
-    struct rt_ready_list *rdlist, *pre_rdlist;
+    struct rt_fd_list *rdlist;
+    rt_slist_t *node = RT_NULL;
     int event_num = 0;
     int istimeout = 0;
     int isn_add = 0;
@@ -668,23 +595,29 @@ static int epoll_do(struct rt_eventpoll *ep, struct epoll_event *events, int max
     while (1)
     {
         rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
+        rt_spin_lock(&ep->spinlock);
         if (ep->eventpoll_num > 0)
         {
-            rdlist = ep->rdlist;
-            while (rdlist->next != RT_NULL)
+            rt_slist_for_each(node,&ep->rdl_head)
             {
+                rdlist = rt_slist_entry(node, struct rt_fd_list, rdl_node);
+
+                rt_spin_unlock(&ep->spinlock);
+
                 isfree = 0;
                 isn_add = 0;
-                pre_rdlist = rdlist;
-                rdlist = rdlist->next;
                 if (event_num < maxevents)
                 {
-                    rt_wqueue_remove(&rdlist->rdl_event->wqn);
-                    mask = epoll_get_event(rdlist->rdl_event, &rdlist->rdl_event->req);
+                    if (rdlist->wqn.wqueue)
+                    {
+                        rt_wqueue_remove(&rdlist->wqn);
+                    }
+
+                    mask = epoll_get_event(rdlist, &rdlist->req);
 
-                    if (mask & rdlist->rdl_event->revents)
+                    if (mask & rdlist->revents)
                     {
-                        rdlist->rdl_event->epev.events = mask & rdlist->rdl_event->revents;
+                        rdlist->epev.events = mask & rdlist->revents;
                     }
                     else
                     {
@@ -692,54 +625,64 @@ static int epoll_do(struct rt_eventpoll *ep, struct epoll_event *events, int max
                         isn_add = 1;
                     }
 
-                    if (rdlist->rdl_event->revents & EPOLLONESHOT)
+                    if (rdlist->revents & EPOLLONESHOT)
                     {
-                        rdlist->rdl_event->revents = 0;
+                        rdlist->revents = 0;
                         isfree = 1;
-                        rt_wqueue_remove(&rdlist->rdl_event->wqn);
+                        if (rdlist->wqn.wqueue)
+                            rt_wqueue_remove(&rdlist->wqn);
                     }
                     else
                     {
-                        if (rdlist->rdl_event->revents & EPOLLET)
+                        if (rdlist->revents & EPOLLET)
                         {
                             isfree = 1;
                         }
                         else
                         {
+                            rt_spin_lock(&ep->spinlock);
                             if (rdlist->exclusive != 1)
                             {
                                 rdlist->exclusive = 1;
                             }
+                            rt_spin_unlock(&ep->spinlock);
                         }
                     }
 
                     if (!isn_add)
                     {
-                        memcpy(&events[event_num], &rdlist->rdl_event->epev, sizeof(rdlist->rdl_event->epev));
+                        memcpy(&events[event_num], &rdlist->epev, sizeof(rdlist->epev));
                         event_num ++;
                     }
 
                     if (isfree)
                     {
-                        pre_rdlist->next = rdlist->next;
-                        rt_free(rdlist);
+                        rt_spin_lock(&ep->spinlock);
                         ep->eventpoll_num --;
-                        rdlist = pre_rdlist;
+                        rt_slist_remove(&ep->rdl_head, &rdlist->rdl_node);
+                        rt_spin_unlock(&ep->spinlock);
                     }
                 }
                 else
                 {
+                    rt_spin_lock(&ep->spinlock);
                     break;
                 }
+
+                rt_spin_lock(&ep->spinlock);
             }
         }
 
+        rt_spin_unlock(&ep->spinlock);
         rt_mutex_release(&ep->lock);
 
         if (event_num || istimeout)
         {
+            rt_spin_lock(&ep->spinlock);
             ep->tirggered = 0;
-            break;
+            rt_spin_unlock(&ep->spinlock);
+            if ((timeout >= 0) || (event_num > 0))
+                break;
         }
 
         if (epoll_wait_timeout(ep, timeout))

+ 33 - 14
components/libc/posix/io/poll/poll.h

@@ -15,28 +15,47 @@
 extern "C" {
 #endif
 
+#ifdef RT_USING_MUSLLIBC
 #if !defined(POLLIN) && !defined(POLLOUT)
-#define POLLIN          (0x01)
-#define POLLRDNORM      (0x01)
-#define POLLRDBAND      (0x01)
-#define POLLPRI         (0x01)
-
-#define POLLOUT         (0x02)
-#define POLLWRNORM      (0x02)
-#define POLLWRBAND      (0x02)
-
-#define POLLERR         (0x04)
-#define POLLHUP         (0x08)
-#define POLLNVAL        (0x10)
-
+#define POLLIN     0x001
+#define POLLPRI    0x002
+#define POLLOUT    0x004
+#define POLLERR    0x008
+#define POLLHUP    0x010
+#define POLLNVAL   0x020
+#define POLLRDNORM 0x040
+#define POLLRDBAND 0x080
+#define POLLWRNORM 0x100
+#define POLLWRBAND 0x200
+typedef unsigned int nfds_t;
+struct pollfd
+{
+    int fd;
+    short events;
+    short revents;
+};
+#endif
+#else
+#if !defined(POLLIN) && !defined(POLLOUT)
+#define POLLIN     0x1
+#define POLLOUT    0x2
+#define POLLERR    0x4
+#define POLLNVAL   0x8
+/* Below values are unimplemented */
+#define POLLRDNORM 0x10
+#define POLLRDBAND 0x20
+#define POLLPRI    0x40
+#define POLLWRNORM 0x80
+#define POLLWRBAND 0x100
+#define POLLHUP    0x200
 typedef unsigned int nfds_t;
-
 struct pollfd
 {
     int fd;
     short events;
     short revents;
 };
+#endif
 #endif /* !defined(POLLIN) && !defined(POLLOUT) */
 
 #define POLLMASK_DEFAULT (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)

+ 223 - 2
components/lwp/lwp_syscall.c

@@ -3535,6 +3535,150 @@ static int netflags_muslc_2_lwip(int flags)
     return flgs;
 }
 
+#ifdef ARCH_MM_MMU
+static int copy_msghdr_from_user(struct msghdr *kmsg, struct msghdr *umsg,
+        struct iovec **out_iov, void **out_msg_control)
+{
+    size_t iovs_size;
+    struct iovec *uiov, *kiov;
+    size_t iovs_buffer_size = 0;
+    void *iovs_buffer;
+
+    if (!lwp_user_accessable(umsg, sizeof(*umsg)))
+    {
+        return -EFAULT;
+    }
+
+    lwp_get_from_user(kmsg, umsg, sizeof(*kmsg));
+
+    iovs_size = sizeof(*kmsg->msg_iov) * kmsg->msg_iovlen;
+    if (!lwp_user_accessable(kmsg->msg_iov, iovs_size))
+    {
+        return -EFAULT;
+    }
+
+    /* user and kernel */
+    kiov = kmem_get(iovs_size * 2);
+    if (!kiov)
+    {
+        return -ENOMEM;
+    }
+
+    uiov = (void *)kiov + iovs_size;
+    lwp_get_from_user(uiov, kmsg->msg_iov, iovs_size);
+
+    if (out_iov)
+    {
+        *out_iov = uiov;
+    }
+    kmsg->msg_iov = kiov;
+
+    for (int i = 0; i < kmsg->msg_iovlen; ++i)
+    {
+        /*
+         * We MUST check we can copy data to user after socket done in uiov
+         * otherwise we will be lost the messages from the network!
+         */
+        if (!lwp_user_accessable(uiov->iov_base, uiov->iov_len))
+        {
+            kmem_put(kmsg->msg_iov);
+
+            return -EPERM;
+        }
+
+        iovs_buffer_size += uiov->iov_len;
+        kiov->iov_len = uiov->iov_len;
+
+        ++kiov;
+        ++uiov;
+    }
+
+    /* msg_iov and msg_control */
+    iovs_buffer = kmem_get(iovs_buffer_size + kmsg->msg_controllen);
+
+    if (!iovs_buffer)
+    {
+        kmem_put(kmsg->msg_iov);
+
+        return -ENOMEM;
+    }
+
+    kiov = kmsg->msg_iov;
+
+    for (int i = 0; i < kmsg->msg_iovlen; ++i)
+    {
+        kiov->iov_base = iovs_buffer;
+        iovs_buffer += kiov->iov_len;
+        ++kiov;
+    }
+
+    *out_msg_control = kmsg->msg_control;
+    /* msg_control is the end of the iovs_buffer */
+    kmsg->msg_control = iovs_buffer;
+
+    return 0;
+}
+#endif /* ARCH_MM_MMU */
+
+sysret_t sys_recvmsg(int socket, struct msghdr *msg, int flags)
+{
+    int flgs, ret = -1;
+    struct msghdr kmsg;
+#ifdef ARCH_MM_MMU
+    void *msg_control;
+    struct iovec *uiov, *kiov;
+#endif
+
+    if (!msg)
+    {
+        return -EPERM;
+    }
+
+    flgs = netflags_muslc_2_lwip(flags);
+
+#ifdef ARCH_MM_MMU
+    ret = copy_msghdr_from_user(&kmsg, msg, &uiov, &msg_control);
+
+    if (!ret)
+    {
+        ret = recvmsg(socket, &kmsg, flgs);
+
+        if (ret < 0)
+        {
+            goto _free_res;
+        }
+
+        kiov = kmsg.msg_iov;
+
+        for (int i = 0; i < kmsg.msg_iovlen; ++i)
+        {
+            lwp_put_to_user(uiov->iov_base, kiov->iov_base, kiov->iov_len);
+
+            ++kiov;
+            ++uiov;
+        }
+
+        lwp_put_to_user(msg_control, kmsg.msg_control, kmsg.msg_controllen);
+        lwp_put_to_user(&msg->msg_flags, &kmsg.msg_flags, sizeof(kmsg.msg_flags));
+
+    _free_res:
+        kmem_put(kmsg.msg_iov->iov_base);
+        kmem_put(kmsg.msg_iov);
+    }
+#else
+    rt_memcpy(&kmsg, msg, sizeof(kmsg));
+
+    ret = recvmsg(socket, &kmsg, flgs);
+
+    if (!ret)
+    {
+        msg->msg_flags = kmsg.msg_flags;
+    }
+#endif /* ARCH_MM_MMU */
+
+    return (ret < 0 ? GET_ERRNO() : ret);
+}
+
 sysret_t sys_recvfrom(int socket, void *mem, size_t len, int flags,
       struct musl_sockaddr *from, socklen_t *fromlen)
 {
@@ -3633,6 +3777,57 @@ sysret_t sys_recv(int socket, void *mem, size_t len, int flags)
     return (ret < 0 ? GET_ERRNO() : ret);
 }
 
+sysret_t sys_sendmsg(int socket, const struct msghdr *msg, int flags)
+{
+    int flgs, ret = -1;
+    struct msghdr kmsg;
+#ifdef ARCH_MM_MMU
+    void *msg_control;
+    struct iovec *uiov, *kiov;
+#endif
+    if (!msg)
+    {
+        return -EPERM;
+    }
+
+    flgs = netflags_muslc_2_lwip(flags);
+
+#ifdef ARCH_MM_MMU
+    ret = copy_msghdr_from_user(&kmsg, (struct msghdr *)msg, &uiov, &msg_control);
+
+    if (!ret)
+    {
+        kiov = kmsg.msg_iov;
+
+        for (int i = 0; i < kmsg.msg_iovlen; ++i)
+        {
+            lwp_get_from_user(kiov->iov_base, uiov->iov_base, kiov->iov_len);
+
+            ++kiov;
+            ++uiov;
+        }
+
+        lwp_get_from_user(kmsg.msg_control, msg_control, kmsg.msg_controllen);
+
+        ret = sendmsg(socket, &kmsg, flgs);
+
+        kmem_put(kmsg.msg_iov->iov_base);
+        kmem_put(kmsg.msg_iov);
+    }
+#else
+    rt_memcpy(&kmsg, msg, sizeof(kmsg));
+
+    ret = sendmsg(socket, &kmsg, flgs);
+
+    if (!ret)
+    {
+        msg->msg_flags = kmsg.msg_flags;
+    }
+#endif /* ARCH_MM_MMU */
+
+    return (ret < 0 ? GET_ERRNO() : ret);
+}
+
 sysret_t sys_sendto(int socket, const void *dataptr, size_t size, int flags,
     const struct musl_sockaddr *to, socklen_t tolen)
 {
@@ -3757,6 +3952,30 @@ out:
     return (fd < 0 ? GET_ERRNO() : fd);
 }
 
+sysret_t sys_socketpair(int domain, int type, int protocol, int fd[2])
+{   
+#ifdef RT_USING_SAL
+    int ret = 0;
+    int k_fd[2];
+
+    if (!lwp_user_accessable((void *)fd, sizeof(int [2])))
+    {
+        return -EFAULT;
+    }
+
+    ret = socketpair(domain, type, protocol, k_fd);
+
+    if (ret == 0)
+    {
+        lwp_put_to_user(fd, k_fd, sizeof(int [2]));
+    }
+
+    return ret;
+#else
+    return -ELIBACC;
+#endif
+}
+
 sysret_t sys_closesocket(int socket)
 {
     return closesocket(socket);
@@ -6688,8 +6907,8 @@ const static struct rt_syscall_def func_table[] =
     SYSCALL_NET(SYSCALL_SIGN(sys_getaddrinfo)),
     SYSCALL_NET(SYSCALL_SIGN(sys_gethostbyname2_r)), /* 85 */
 
-    SYSCALL_SIGN(sys_notimpl),    //network,
-    SYSCALL_SIGN(sys_notimpl),    //network,
+    SYSCALL_NET(SYSCALL_SIGN(sys_sendmsg)),
+    SYSCALL_NET(SYSCALL_SIGN(sys_recvmsg)),
     SYSCALL_SIGN(sys_notimpl),    //network,
     SYSCALL_SIGN(sys_notimpl),    //network,
     SYSCALL_SIGN(sys_notimpl),    //network, /* 90 */
@@ -6826,6 +7045,8 @@ const static struct rt_syscall_def func_table[] =
     SYSCALL_SIGN(sys_ftruncate),
     SYSCALL_SIGN(sys_setitimer),
     SYSCALL_SIGN(sys_utimensat),
+    SYSCALL_SIGN(sys_notimpl),
+    SYSCALL_SIGN(sys_socketpair),                        /* 205 */
 };
 
 const void *lwp_get_sys_api(rt_uint32_t number)

+ 2 - 1
components/net/netdev/include/netdev.h

@@ -111,7 +111,8 @@ struct netdev
 extern struct netdev *netdev_list;
 /* The default network interface device */
 extern struct netdev *netdev_default;
-
+/* The local virtual network device */
+extern struct netdev *netdev_lo;
 /* The network interface device ping response object */
 struct netdev_ping_resp
 {

+ 2 - 0
components/net/netdev/src/netdev.c

@@ -31,6 +31,8 @@
 struct netdev *netdev_list = RT_NULL;
 /* The default network interface device */
 struct netdev *netdev_default = RT_NULL;
+/* The local virtual network device */
+struct netdev *netdev_lo = RT_NULL;
 /* The global network register callback */
 static netdev_callback_fn g_netdev_register_callback = RT_NULL;
 static netdev_callback_fn g_netdev_default_change_callback = RT_NULL;

+ 29 - 24
components/net/sal/impl/af_inet_lwip.c

@@ -293,44 +293,49 @@ static int inet_poll(struct dfs_file *file, struct rt_pollreq *req)
 
 static const struct sal_socket_ops lwip_socket_ops =
 {
-    inet_socket,
-    lwip_close,
-    lwip_bind,
-    lwip_listen,
-    lwip_connect,
-    inet_accept,
-    (int (*)(int, const void *, size_t, int, const struct sockaddr *, socklen_t))lwip_sendto,
-    (int (*)(int, void *, size_t, int, struct sockaddr *, socklen_t *))lwip_recvfrom,
-    lwip_getsockopt,
+    .socket      = inet_socket,
+    .closesocket = lwip_close,
+    .bind        = lwip_bind,
+    .listen      = lwip_listen,
+    .connect     = lwip_connect,
+    .accept      = inet_accept,
+    .sendto      = (int (*)(int, const void *, size_t, int, const struct sockaddr *, socklen_t))lwip_sendto,
+#if LWIP_VERSION >= 0x20102ff
+    .sendmsg     = (int (*)(int, const struct msghdr *, int))lwip_sendmsg,
+    .recvmsg     = (int (*)(int, struct msghdr *, int))lwip_recvmsg,
+#endif
+    .recvfrom    = (int (*)(int, void *, size_t, int, struct sockaddr *, socklen_t *))lwip_recvfrom,
+    .getsockopt  = lwip_getsockopt,
     //TODO fix on 1.4.1
-    lwip_setsockopt,
-    lwip_shutdown,
-    lwip_getpeername,
-    inet_getsockname,
-    inet_ioctlsocket,
+    .setsockopt  = lwip_setsockopt,
+    .shutdown    = lwip_shutdown,
+    .getpeername = lwip_getpeername,
+    .getsockname = inet_getsockname,
+    .ioctlsocket = inet_ioctlsocket,
+    .socketpair  = RT_NULL,
 #ifdef SAL_USING_POSIX
-    inet_poll,
+    .poll        = inet_poll,
 #endif
 };
 
 static const struct sal_netdb_ops lwip_netdb_ops =
 {
-    lwip_gethostbyname,
-    lwip_gethostbyname_r,
-    lwip_getaddrinfo,
-    lwip_freeaddrinfo,
+    .gethostbyname   = lwip_gethostbyname,
+    .gethostbyname_r = lwip_gethostbyname_r,
+    .getaddrinfo     = lwip_getaddrinfo,
+    .freeaddrinfo    = lwip_freeaddrinfo,
 };
 
 static const struct sal_proto_family lwip_inet_family =
 {
-    AF_INET,
+    .family     = AF_INET,
 #if LWIP_VERSION > 0x2000000
-    AF_INET6,
+    .sec_family = AF_INET6,
 #else
-    AF_INET,
+    .sec_family = AF_INET,
 #endif
-    &lwip_socket_ops,
-    &lwip_netdb_ops,
+    .skt_ops    = &lwip_socket_ops,
+    .netdb_ops  = &lwip_netdb_ops,
 };
 
 /* Set lwIP network interface device protocol family information */

+ 6 - 0
components/net/sal/include/sal_low_lvl.h

@@ -45,6 +45,9 @@ typedef uint32_t socklen_t;
 #define SAL_SOCKET_OFFSET              0
 #endif
 
+struct sockaddr;
+struct msghdr;
+struct addrinfo;
 struct sal_socket
 {
     uint32_t magic;                    /* SAL socket magic word */
@@ -72,6 +75,8 @@ struct sal_socket_ops
     int (*connect)    (int s, const struct sockaddr *name, socklen_t namelen);
     int (*accept)     (int s, struct sockaddr *addr, socklen_t *addrlen);
     int (*sendto)     (int s, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
+    int (*sendmsg)    (int s, const struct msghdr *message, int flags);
+    int (*recvmsg)    (int s, struct msghdr *message, int flags);
     int (*recvfrom)   (int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
     int (*getsockopt) (int s, int level, int optname, void *optval, socklen_t *optlen);
     int (*setsockopt) (int s, int level, int optname, const void *optval, socklen_t optlen);
@@ -79,6 +84,7 @@ struct sal_socket_ops
     int (*getpeername)(int s, struct sockaddr *name, socklen_t *namelen);
     int (*getsockname)(int s, struct sockaddr *name, socklen_t *namelen);
     int (*ioctlsocket)(int s, long cmd, void *arg);
+    int (*socketpair) (int s, int type, int protocol, int *fds);
 #ifdef SAL_USING_POSIX
     int (*poll)       (struct dfs_file *file, struct rt_pollreq *req);
 #endif

+ 92 - 2
components/net/sal/include/sal_socket.h

@@ -48,6 +48,18 @@ typedef uint16_t in_port_t;
 #define SO_KEEPALIVE    0x0008 /* keep connections alive */
 #define SO_BROADCAST    0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
 
+#define SO_PASSCRED	    16
+#define SO_PEERCRED	    17
+
+#define SO_BINDTODEVICE	    25
+#define SO_ATTACH_FILTER	26
+#define SO_DETACH_FILTER	27
+
+#define SO_SNDBUFFORCE	32
+#define SO_RCVBUFFORCE	33
+#define SO_PROTOCOL		38
+#define SO_DOMAIN		39
+
 /* Additional options, not kept in so_options */
 #define SO_DEBUG        0x0001 /* Unimplemented: turn on debugging info recording */
 #define SO_ACCEPTCONN   0x0002 /* socket has had listen() */
@@ -103,6 +115,9 @@ typedef uint16_t in_port_t;
 #define MSG_OOB         0x04    /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */
 #define MSG_DONTWAIT    0x08    /* Nonblocking i/o for this operation only */
 #define MSG_MORE        0x10    /* Sender will send more */
+/* LWIPPTP_SWREQ_0036 */
+#define MSG_ERRQUEUE    0x2000  /* Fetch message from error queue */
+#define MSG_CONFIRM     0x0800  /* Confirm path validity */
 
 /* Options for level IPPROTO_IP */
 #define IP_TOS             1
@@ -150,6 +165,10 @@ typedef struct ip_mreq
 #define IPTOS_PREC_PRIORITY            0x20
 #define IPTOS_PREC_ROUTINE             0x00
 
+#define	SCM_RIGHTS	0x01		    /* rw: access rights (array of int) */
+#define SCM_CREDENTIALS 0x02		/* rw: struct ucred		*/
+#define SCM_SECURITY	0x03		/* rw: security label		*/
+
 /* Options for shatdown type */
 #ifndef SHUT_RD
   #define SHUT_RD       0
@@ -167,8 +186,7 @@ struct sockaddr
 /* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket.  */
 struct sockaddr_un
 {
-    uint8_t        sa_len;
-    sa_family_t    sa_family;
+    unsigned short sa_family;
     char sun_path[108];         /* Path name.  */
 };
 
@@ -209,6 +227,75 @@ struct sockaddr_storage
 #endif /* NETDEV_IPV6 */
 };
 
+/* LWIPPTP_SWREQ_0036 */
+#ifndef __DEFINED_struct_iovec
+struct iovec
+{
+    void *iov_base;
+    size_t iov_len;
+};
+#endif
+
+/* LWIPPTP_SWREQ_0036 */
+struct msghdr
+{
+    void            *msg_name;
+    socklen_t        msg_namelen;
+    struct iovec    *msg_iov;
+    int              msg_iovlen;
+    void            *msg_control;
+    socklen_t        msg_controllen;
+    int              msg_flags;
+};
+
+/* LWIPPTP_SWREQ_0036 */
+/* RFC 3542, Section 20: Ancillary Data */
+struct cmsghdr
+{
+    size_t  cmsg_len;   /* number of bytes, including header */
+    int     cmsg_level; /* originating protocol */
+    int     cmsg_type;  /* protocol-specific type */
+};
+
+/* LWIPPTP_SWREQ_0036 */
+#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
+
+#define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long)-1))
+
+#define CMSG_DATA(cmsg) ((void *)(cmsg) + sizeof(struct cmsghdr))
+#define CMSG_SPACE(len) (sizeof(struct cmsghdr) + CMSG_ALIGN(len))
+#define CMSG_LEN(len)   (sizeof(struct cmsghdr) + (len))
+
+#define __CMSG_FIRSTHDR(ctl, len) \
+    ((len) >= sizeof(struct cmsghdr) ? (struct cmsghdr *)(ctl) : (struct cmsghdr *)NULL)
+
+#define CMSG_FIRSTHDR(msg)  __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG_OK(mhdr, cmsg) \
+    ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \
+    (cmsg)->cmsg_len <= (unsigned long)((mhdr)->msg_controllen - ((char *)(cmsg) - (char *)(mhdr)->msg_control)))
+
+#define for_each_cmsghdr(cmsg, msg) \
+    for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg))
+
+static inline struct cmsghdr *__cmsg_nxthdr(void *_ctl, size_t _size, struct cmsghdr *_cmsg)
+{
+    struct cmsghdr *_ptr;
+
+    _ptr = (struct cmsghdr *)(((unsigned char *)_cmsg) + CMSG_ALIGN(_cmsg->cmsg_len));
+
+    if ((unsigned long)((char *)(_ptr + 1) - (char *)_ctl) > _size)
+    {
+        return (struct cmsghdr *)NULL;
+    }
+
+    return _ptr;
+}
+
+static inline struct cmsghdr *cmsg_nxthdr(struct msghdr *_msg, struct cmsghdr *_cmsg)
+{
+    return __cmsg_nxthdr(_msg->msg_control, _msg->msg_controllen, _cmsg);
+}
+
 #define IFNAMSIZ	16
 struct sal_ifmap 
 {
@@ -252,11 +339,14 @@ int sal_getsockopt (int socket, int level, int optname, void *optval, socklen_t
 int sal_setsockopt (int socket, int level, int optname, const void *optval, socklen_t optlen);
 int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen);
 int sal_listen(int socket, int backlog);
+int sal_sendmsg(int socket, const struct msghdr *message, int flags);
+int sal_recvmsg(int socket, struct msghdr *message, int flags);
 int sal_recvfrom(int socket, void *mem, size_t len, int flags,
       struct sockaddr *from, socklen_t *fromlen);
 int sal_sendto(int socket, const void *dataptr, size_t size, int flags,
     const struct sockaddr *to, socklen_t tolen);
 int sal_socket(int domain, int type, int protocol);
+int sal_socketpair(int domain, int type, int protocol, int *fds);
 int sal_closesocket(int socket);
 int sal_ioctlsocket(int socket, long cmd, void *arg);
 

+ 6 - 0
components/net/sal/include/socket/sys_socket/sys/socket.h

@@ -35,12 +35,15 @@ int listen(int s, int backlog);
 int recv(int s, void *mem, size_t len, int flags);
 int recvfrom(int s, void *mem, size_t len, int flags,
       struct sockaddr *from, socklen_t *fromlen);
+int recvmsg(int s, struct msghdr *message, int flags);
+int sendmsg(int s, const struct msghdr *message, int flags);
 int send(int s, const void *dataptr, size_t size, int flags);
 int sendto(int s, const void *dataptr, size_t size, int flags,
     const struct sockaddr *to, socklen_t tolen);
 int socket(int domain, int type, int protocol);
 int closesocket(int s);
 int ioctlsocket(int s, long cmd, void *arg);
+int socketpair(int domain, int type, int protocol, int *fds);
 #else
 #define accept(s, addr, addrlen)                           sal_accept(s, addr, addrlen)
 #define bind(s, name, namelen)                             sal_bind(s, name, namelen)
@@ -53,9 +56,12 @@ int ioctlsocket(int s, long cmd, void *arg);
 #define listen(s, backlog)                                 sal_listen(s, backlog)
 #define recv(s, mem, len, flags)                           sal_recvfrom(s, mem, len, flags, NULL, NULL)
 #define recvfrom(s, mem, len, flags, from, fromlen)        sal_recvfrom(s, mem, len, flags, from, fromlen)
+#define recvmsg(s, message, flags)                         sal_recvmsg(s, message, flags)
 #define send(s, dataptr, size, flags)                      sal_sendto(s, dataptr, size, flags, NULL, NULL)
 #define sendto(s, dataptr, size, flags, to, tolen)         sal_sendto(s, dataptr, size, flags, to, tolen)
+#define sendmsg(s, message, flags)                         sal_sendmsg(s, message, flags)
 #define socket(domain, type, protocol)                     sal_socket(domain, type, protocol)
+#define socketpair(domain, type, protocol, fds)            sal_socketpair(domain, type, protocol, fds)
 #define closesocket(s)                                     sal_closesocket(s)
 #define ioctlsocket(s, cmd, arg)                           sal_ioctlsocket(s, cmd, arg)
 #endif /* SAL_USING_POSIX */

+ 55 - 30
components/net/sal/socket/net_sockets.c

@@ -75,17 +75,6 @@ int bind(int s, const struct sockaddr *name, socklen_t namelen)
 {
     int socket = dfs_net_getsocket(s);
 
-#ifdef SAL_USING_AF_UNIX
-    struct sockaddr_in server_addr = {0};
-    if (name->sa_family == AF_UNIX)
-    {
-        server_addr.sin_family = AF_INET;
-        server_addr.sin_port = htons(514);
-        server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-        return sal_bind(socket, (struct sockaddr *)&server_addr, namelen);
-    }
-#endif /* SAL_USING_AF_UNIX */
-
     return sal_bind(socket, name, namelen);
 }
 RTM_EXPORT(bind);
@@ -159,18 +148,6 @@ RTM_EXPORT(setsockopt);
 int connect(int s, const struct sockaddr *name, socklen_t namelen)
 {
     int socket = dfs_net_getsocket(s);
-
-#ifdef SAL_USING_AF_UNIX
-    struct sockaddr_in server_addr = {0};
-    if (name->sa_family == AF_UNIX)
-    {
-        server_addr.sin_family = AF_INET;
-        server_addr.sin_port = htons(514);
-        server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-        return sal_connect(socket, (struct sockaddr *)&server_addr, namelen);
-    }
-#endif /* SAL_USING_AF_UNIX */
-
     return sal_connect(socket, name, namelen);
 }
 RTM_EXPORT(connect);
@@ -191,6 +168,24 @@ int recv(int s, void *mem, size_t len, int flags)
 }
 RTM_EXPORT(recv);
 
+/* LWIPPTP_SWREQ_0036 */
+int sendmsg(int s, const struct msghdr *message, int flags)
+{
+    int socket = dfs_net_getsocket(s);
+
+    return sal_sendmsg(socket, message, flags);
+}
+RTM_EXPORT(sendmsg);
+
+/* LWIPPTP_SWREQ_0036 */
+int recvmsg(int s, struct msghdr *message, int flags)
+{
+    int socket = dfs_net_getsocket(s);
+
+    return sal_recvmsg(socket, message, flags);
+}
+RTM_EXPORT(recvmsg);
+
 int recvfrom(int s, void *mem, size_t len, int flags,
              struct sockaddr *from, socklen_t *fromlen)
 {
@@ -247,13 +242,6 @@ int socket(int domain, int type, int protocol)
         return -1;
     }
 
-#ifdef SAL_USING_AF_UNIX
-    if (domain == AF_UNIX)
-    {
-        domain = AF_INET;
-    }
-#endif /* SAL_USING_AF_UNIX */
-
     /* create socket  and then put it to the dfs_file */
     socket = sal_socket(domain, type, protocol);
     if (socket >= 0)
@@ -319,6 +307,43 @@ int closesocket(int s)
 }
 RTM_EXPORT(closesocket);
 
+
+int socketpair(int domain, int type, int protocol, int *fds)
+{
+    rt_err_t ret = 0;
+    int sock_fds[2];
+
+    fds[0] = socket(domain, type, protocol);
+    if (fds[0] < 0)
+    {
+        fds[0] = 0;
+        return -1;
+    }
+
+    fds[1] = socket(domain, type, protocol);
+    if (fds[1] < 0)
+    {
+        closesocket(fds[0]);
+        fds[0] = 0;
+        fds[1] = 0;
+        return -1;
+    }
+
+    sock_fds[0] = dfs_net_getsocket(fds[0]);
+    sock_fds[1] = dfs_net_getsocket(fds[1]);
+
+    ret = sal_socketpair(domain, type, protocol, sock_fds);
+
+    if (ret < 0)
+    {
+        closesocket(fds[0]);
+        closesocket(fds[1]);
+    }
+
+    return ret;
+}
+RTM_EXPORT(socketpair);
+
 int ioctlsocket(int s, long cmd, void *arg)
 {
     int socket = dfs_net_getsocket(s);

+ 135 - 27
components/net/sal/src/sal_socket.c

@@ -15,6 +15,8 @@
 #include <string.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <sal_socket.h>
 #include <sal_netdb.h>
@@ -442,6 +444,11 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r
     struct netdev *netdev = RT_NULL;
     rt_bool_t flag = RT_FALSE;
 
+    if (family == AF_UNIX)
+    {   
+        netdv_def = netdev_lo;
+    }
+
     if (family < 0 || family > AF_MAX)
     {
         return -1;
@@ -667,6 +674,7 @@ int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
 {
     struct sal_socket *sock;
     struct sal_proto_family *pf;
+    struct sockaddr_un *addr_un = RT_NULL;
     ip_addr_t input_ipaddr;
 
     RT_ASSERT(name);
@@ -674,43 +682,47 @@ int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
     /* get the socket object by socket descriptor */
     SAL_SOCKET_OBJ_GET(sock, socket);
 
-    /* bind network interface by ip address */
-    sal_sockaddr_to_ipaddr(name, &input_ipaddr);
+    addr_un = (struct sockaddr_un *)name;
 
-    /* check input ipaddr is default netdev ipaddr */
-    if (!ip_addr_isany_val(input_ipaddr))
-    {
-        struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL;
-        struct netdev *new_netdev = RT_NULL;
+    if (addr_un->sa_family != AF_UNIX)
+    {      
+        /* bind network interface by ip address */
+        sal_sockaddr_to_ipaddr(name, &input_ipaddr);
 
-        new_netdev = netdev_get_by_ipaddr(&input_ipaddr);
-        if (new_netdev == RT_NULL)
+        /* check input ipaddr is default netdev ipaddr */
+        if (!ip_addr_isany_val(input_ipaddr))
         {
-            return -1;
-        }
-
-        /* get input and local ip address proto_family */
-        SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, local_pf, bind);
-        SAL_NETDEV_SOCKETOPS_VALID(new_netdev, input_pf, bind);
+            struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL;
+            struct netdev *new_netdev = RT_NULL;
 
-        /* check the network interface protocol family type */
-        if (input_pf->family != local_pf->family)
-        {
-            int new_socket = -1;
+            new_netdev = netdev_get_by_ipaddr(&input_ipaddr);
+            if (new_netdev == RT_NULL)
+            {
+                return -1;
+            }
 
-            /* protocol family is different, close old socket and create new socket by input ip address */
-            local_pf->skt_ops->closesocket(socket);
+            /* get input and local ip address proto_family */
+            SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, local_pf, bind);
+            SAL_NETDEV_SOCKETOPS_VALID(new_netdev, input_pf, bind);
 
-            new_socket = input_pf->skt_ops->socket(input_pf->family, sock->type, sock->protocol);
-            if (new_socket < 0)
+            /* check the network interface protocol family type */
+            if (input_pf->family != local_pf->family)
             {
-                return -1;
+                int new_socket = -1;
+
+                /* protocol family is different, close old socket and create new socket by input ip address */
+                local_pf->skt_ops->closesocket(socket);
+
+                new_socket = input_pf->skt_ops->socket(input_pf->family, sock->type, sock->protocol);
+                if (new_socket < 0)
+                {
+                    return -1;
+                }
+                sock->netdev = new_netdev;
+                sock->user_data = (void *)(size_t)new_socket;
             }
-            sock->netdev = new_netdev;
-            sock->user_data = (void *)(size_t)new_socket;
         }
     }
-
     /* check and get protocol families by the network interface device */
     SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind);
     return pf->skt_ops->bind((int)(size_t)sock->user_data, name, namelen);
@@ -884,6 +896,72 @@ int sal_listen(int socket, int backlog)
     return pf->skt_ops->listen((int)(size_t)sock->user_data, backlog);
 }
 
+int sal_sendmsg(int socket, const struct msghdr *message, int flags)
+{
+    struct sal_socket *sock;
+    struct sal_proto_family *pf;
+
+    /* get the socket object by socket descriptor */
+    SAL_SOCKET_OBJ_GET(sock, socket);
+
+    /* check the network interface is up status  */
+    SAL_NETDEV_IS_UP(sock->netdev);
+    /* check the network interface socket opreation */
+    SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, sendmsg);
+
+#ifdef SAL_USING_TLS
+    if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, sendmsg))
+    {
+        int ret;
+
+        if ((ret = proto_tls->ops->sendmsg(sock->user_data_tls, message, flags)) < 0)
+        {
+            return -1;
+        }
+        return ret;
+    }
+    else
+    {
+        return pf->skt_ops->sendmsg((int)(size_t)sock->user_data, message, flags);
+    }
+#else
+    return pf->skt_ops->sendmsg((int)(size_t)sock->user_data, message, flags);
+#endif
+}
+
+int sal_recvmsg(int socket, struct msghdr *message, int flags)
+{
+    struct sal_socket *sock;
+    struct sal_proto_family *pf;
+
+    /* get the socket object by socket descriptor */
+    SAL_SOCKET_OBJ_GET(sock, socket);
+
+    /* check the network interface is up status  */
+    SAL_NETDEV_IS_UP(sock->netdev);
+    /* check the network interface socket opreation */
+    SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, recvmsg);
+
+#ifdef SAL_USING_TLS
+    if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recvmsg))
+    {
+        int ret;
+
+        if ((ret = proto_tls->ops->recvmsg(sock->user_data_tls, message, flags)) < 0)
+        {
+            return -1;
+        }
+        return ret;
+    }
+    else
+    {
+        return pf->skt_ops->recvmsg((int)(size_t)sock->user_data, message, flags);
+    }
+#else
+    return pf->skt_ops->recvmsg((int)(size_t)sock->user_data, message, flags);
+#endif
+}
+
 int sal_recvfrom(int socket, void *mem, size_t len, int flags,
                  struct sockaddr *from, socklen_t *fromlen)
 {
@@ -1007,6 +1085,36 @@ int sal_socket(int domain, int type, int protocol)
     return -1;
 }
 
+int sal_socketpair(int domain, int type, int protocol, int *fds)
+{
+    int unix_fd[2];
+    struct sal_socket *socka;
+    struct sal_socket *sockb;
+    struct sal_proto_family *pf;
+
+    if (domain == AF_UNIX)
+    {
+        /* get the socket object by socket descriptor */
+        SAL_SOCKET_OBJ_GET(socka, fds[0]);
+        SAL_SOCKET_OBJ_GET(sockb, fds[1]);
+
+        /* valid the network interface socket opreation */
+        SAL_NETDEV_SOCKETOPS_VALID(socka->netdev, pf, socket);
+
+        unix_fd[0] = (int)(size_t)socka->user_data;
+        unix_fd[1] = (int)(size_t)sockb->user_data;
+
+        if (pf->skt_ops->socketpair)
+        {
+            return pf->skt_ops->socketpair(domain, type, protocol, unix_fd);
+        }
+    }
+
+    rt_set_errno(EINVAL);
+
+    return -1;
+}
+
 int sal_closesocket(int socket)
 {
     struct sal_socket *sock;