From c06f4e98fce6c86ef412aa70c1f31c971a9d61a9 Mon Sep 17 00:00:00 2001 From: rcitachi <68690849+rcitachi@users.noreply.github.com> Date: Tue, 28 Nov 2023 13:56:06 +0800 Subject: [PATCH] =?UTF-8?q?[SAL]=20Update=20SAL=EF=BC=8CAdd=20socketpair?= =?UTF-8?q?=20sendmsg=20recvmsg=20function=20(#8293)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/dfs/dfs_v2/include/dfs_file.h | 2 +- components/dfs/dfs_v2/src/dfs_file.c | 2 +- components/libc/posix/io/epoll/epoll.c | 305 +++++++----------- components/libc/posix/io/poll/poll.h | 47 ++- components/lwp/lwp_syscall.c | 225 ++++++++++++- components/net/netdev/include/netdev.h | 3 +- components/net/netdev/src/netdev.c | 2 + components/net/sal/impl/af_inet_lwip.c | 53 +-- components/net/sal/include/sal_low_lvl.h | 6 + components/net/sal/include/sal_socket.h | 94 +++++- .../include/socket/sys_socket/sys/socket.h | 6 + components/net/sal/socket/net_sockets.c | 85 +++-- components/net/sal/src/sal_socket.c | 164 ++++++++-- 13 files changed, 710 insertions(+), 284 deletions(-) diff --git a/components/dfs/dfs_v2/include/dfs_file.h b/components/dfs/dfs_v2/include/dfs_file.h index 4486401333..17027d93b2 100644 --- a/components/dfs/dfs_v2/include/dfs_file.h +++ b/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); diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c index d2d27010cf..7e7df1738d 100644 --- a/components/dfs/dfs_v2/src/dfs_file.c +++ b/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; diff --git a/components/libc/posix/io/epoll/epoll.c b/components/libc/posix/io/epoll/epoll.c index 7c33d775a2..881b9ac027 100644 --- a/components/libc/posix/io/epoll/epoll.c +++ b/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,7 +74,9 @@ 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); + if (fre_node->wqn.wqueue) + rt_wqueue_remove(&fre_node->wqn); + list->next = fre_node->next; rt_free(fre_node); } @@ -91,26 +87,6 @@ static int epoll_close_fdlist(struct rt_fd_list *fdlist) return 0; } -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); - } - - return 0; -} - static int epoll_close(struct dfs_file *file) { struct rt_eventpoll *ep; @@ -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); + rt_spin_lock(&ep->spinlock); - if (mask & fdlist->revents) - { - events |= mask | POLLIN | EPOLLRDNORM; - break; - } - } - } + if (!rt_slist_isempty(&ep->rdl_head)) + events |= POLLIN | EPOLLRDNORM | POLLOUT; + + rt_spin_unlock(&ep->spinlock); + rt_mutex_release(&ep->lock); } 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_mutex_take(&ep->lock, RT_WAITING_FOREVER); - - 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; - } - } - - ep->tirggered = 1; - - rt_mutex_release(&ep->lock); - - return res; -} - 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 (mask & rdlist->rdl_event->revents) + if (rdlist->wqn.wqueue) { - rdlist->rdl_event->epev.events = mask & rdlist->rdl_event->revents; + rt_wqueue_remove(&rdlist->wqn); + } + + mask = epoll_get_event(rdlist, &rdlist->req); + + if (mask & rdlist->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)) diff --git a/components/libc/posix/io/poll/poll.h b/components/libc/posix/io/poll/poll.h index 0fccd48b0d..7b710cd14e 100644 --- a/components/libc/posix/io/poll/poll.h +++ b/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) diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 94ba29ddcd..90d116db5c 100644 --- a/components/lwp/lwp_syscall.c +++ b/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) diff --git a/components/net/netdev/include/netdev.h b/components/net/netdev/include/netdev.h index ae0e89b65b..5ee7635cd8 100644 --- a/components/net/netdev/include/netdev.h +++ b/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 { diff --git a/components/net/netdev/src/netdev.c b/components/net/netdev/src/netdev.c index 569ba27040..50f2d4bc8d 100644 --- a/components/net/netdev/src/netdev.c +++ b/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; diff --git a/components/net/sal/impl/af_inet_lwip.c b/components/net/sal/impl/af_inet_lwip.c index fa015fd14e..9183e1a63f 100644 --- a/components/net/sal/impl/af_inet_lwip.c +++ b/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 */ diff --git a/components/net/sal/include/sal_low_lvl.h b/components/net/sal/include/sal_low_lvl.h index 1b1959a3e9..c19c10ffc1 100644 --- a/components/net/sal/include/sal_low_lvl.h +++ b/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 diff --git a/components/net/sal/include/sal_socket.h b/components/net/sal/include/sal_socket.h index b77487516f..52767ece67 100644 --- a/components/net/sal/include/sal_socket.h +++ b/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); diff --git a/components/net/sal/include/socket/sys_socket/sys/socket.h b/components/net/sal/include/socket/sys_socket/sys/socket.h index a86240e2ff..adfe51de5d 100644 --- a/components/net/sal/include/socket/sys_socket/sys/socket.h +++ b/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 */ diff --git a/components/net/sal/socket/net_sockets.c b/components/net/sal/socket/net_sockets.c index 211876c6c4..28e96b1795 100644 --- a/components/net/sal/socket/net_sockets.c +++ b/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); diff --git a/components/net/sal/src/sal_socket.c b/components/net/sal/src/sal_socket.c index 225e50ad3b..782710edcf 100644 --- a/components/net/sal/src/sal_socket.c +++ b/components/net/sal/src/sal_socket.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -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; - } + struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL; + struct netdev *new_netdev = RT_NULL; - /* 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); - - /* check the network interface protocol family type */ - if (input_pf->family != local_pf->family) - { - 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) + new_netdev = netdev_get_by_ipaddr(&input_ipaddr); + if (new_netdev == RT_NULL) { return -1; } - sock->netdev = new_netdev; - sock->user_data = (void *)(size_t)new_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); + + /* check the network interface protocol family type */ + if (input_pf->family != local_pf->family) + { + 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; + } } } - /* 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;