This is an automated email from the ASF dual-hosted git repository. gnutt pushed a commit to branch SocketCAN in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 4f7a02696e1b36d8c48e2b2c84aa82882dcebf70 Author: Peter van der Perk <peter.vanderp...@nxp.com> AuthorDate: Fri Mar 13 18:12:29 2020 +0100 Socket: Control message addded initial stubs for sendmsg() --- arch/arm/src/s32k1xx/Kconfig | 1 + arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 9 +- include/netpacket/can.h | 2 + include/nuttx/net/net.h | 13 ++- libs/libc/net/lib_recvmsg.c | 4 +- libs/libc/net/lib_sendmsg.c | 4 +- net/bluetooth/bluetooth_sockif.c | 3 +- net/can/Kconfig | 20 ++++ net/can/can.h | 16 +-- net/can/can_getsockopt.c | 21 ++++ net/can/can_recvfrom.c | 191 +++++++++++++++------------------ net/can/can_send.c | 4 + net/can/can_setsockopt.c | 10 ++ net/can/can_sockif.c | 51 ++++++++- net/icmp/icmp_sockif.c | 3 +- net/icmpv6/icmpv6_sockif.c | 3 +- net/ieee802154/ieee802154_sockif.c | 3 +- net/inet/inet_sockif.c | 3 +- net/local/local_sockif.c | 3 +- net/netlink/netlink_sockif.c | 3 +- net/pkt/pkt_sockif.c | 3 +- net/socket/Kconfig | 14 +-- net/socket/Make.defs | 5 +- net/socket/recvmsg.c | 4 +- net/socket/{recvmsg.c => sendmsg.c} | 68 ++++++------ 25 files changed, 282 insertions(+), 179 deletions(-) diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig index 68f9bb6..41638d0 100644 --- a/arch/arm/src/s32k1xx/Kconfig +++ b/arch/arm/src/s32k1xx/Kconfig @@ -152,6 +152,7 @@ config S32K1XX_ENET config S32K1XX_FLEXCAN bool "FLEXCAN" + select NET_CAN_HAVE_TX_DEADLINE default n menuconfig S32K1XX_LPI2C0 diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c index 15e5b62..5c02aa0 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c +++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c @@ -433,10 +433,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv) mb->id.std = frame->can_id & MASKSTDID; } - #if 0 - /* cs.rtr = frame.isRemoteTransmissionRequest(); */ - #endif - + cs.rtr = frame->can_id & FLAGRTR ? 1 : 0; cs.dlc = frame->can_dlc; mb->data[0].w00 = __builtin_bswap32(*(uint32_t *)&frame->data[0]); @@ -458,9 +455,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv) mb->id.std = frame->can_id & MASKSTDID; } -#if 0 - /* cs.rtr = frame.isRemoteTransmissionRequest(); */ -#endif + cs.rtr = frame->can_id & FLAGRTR ? 1 : 0; if (frame->len < 9) { diff --git a/include/netpacket/can.h b/include/netpacket/can.h index 4ea2104..bd0442d 100644 --- a/include/netpacket/can.h +++ b/include/netpacket/can.h @@ -75,6 +75,8 @@ /* allow CAN FD frames (default:off) */ #define CAN_RAW_JOIN_FILTERS (__SO_PROTOCOL + 5) /* all filters must match to trigger */ +#define CAN_RAW_TX_DEADLINE (__SO_PROTOCOL + 6) + /* Abort frame when deadline has been passed */ /**************************************************************************** * Public Types diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index b7d759c..1c661b1 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -214,7 +214,7 @@ struct sock_intf_s FAR socklen_t *fromlen); #ifdef CONFIG_NET_RECVMSG_CMSG CODE ssize_t (*si_recvmsg)(FAR struct socket *psock, - FAR struct msghdr *msg, int flags); + FAR struct msghdr *msg, int flags); #endif CODE int (*si_close)(FAR struct socket *psock); #ifdef CONFIG_NET_USRSOCK @@ -504,9 +504,9 @@ FAR struct iob_s *net_ioballoc(bool throttled, enum iob_user_e consumerid); * Description: * Check if the socket descriptor is valid for the provided TCB and if it * supports the requested access. This trivial operation is part of the - * fdopen() operation when the fdopen() is performed on a socket - * descriptor. It simply performs some sanity checking before permitting - * the socket descriptor to be wrapped as a C FILE stream. + * fdopen() operation when the fdopen() is performed on a socket descriptor. + * It simply performs some sanity checking before permitting the socket + * descriptor to be wrapped as a C FILE stream. * ****************************************************************************/ @@ -739,8 +739,7 @@ int psock_listen(FAR struct socket *psock, int backlog); * Input Parameters: * psock Reference to the listening socket structure * addr Receives the address of the connecting client - * addrlen Input: allocated size of 'addr', - * Return: returned size of 'addr' + * addrlen Input: allocated size of 'addr', Return: returned size of 'addr' * newsock Location to return the accepted socket information. * * Returned Value: @@ -1564,7 +1563,7 @@ int net_vfcntl(int sockfd, int cmd, va_list ap); * * Input Parameters: * dev - The device driver structure to be registered. - * lltype - Link level protocol used by driver (Ethernet, SLIP, TUN, ... + * lltype - Link level protocol used by the driver (Ethernet, SLIP, TUN, ... * * Returned Value: * 0:Success; negated errno on failure diff --git a/libs/libc/net/lib_recvmsg.c b/libs/libc/net/lib_recvmsg.c index 5200acd..071c189 100644 --- a/libs/libc/net/lib_recvmsg.c +++ b/libs/libc/net/lib_recvmsg.c @@ -39,7 +39,7 @@ #include <nuttx/config.h> -#if defined(CONFIG_NET) && !defined(CONFIG_NET_RECVMSG_CMSG) +#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG) #include <sys/types.h> #include <sys/socket.h> @@ -87,4 +87,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags) } } -#endif /* CONFIG_NET && !CONFIG_NET_RECVMSG_CMSG */ +#endif /* CONFIG_NET && !CONFIG_NET_CMSG */ diff --git a/libs/libc/net/lib_sendmsg.c b/libs/libc/net/lib_sendmsg.c index 0d09faa..9f98e51 100644 --- a/libs/libc/net/lib_sendmsg.c +++ b/libs/libc/net/lib_sendmsg.c @@ -39,7 +39,7 @@ #include <nuttx/config.h> -#ifdef CONFIG_NET +#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG) #include <sys/types.h> #include <sys/socket.h> @@ -86,4 +86,4 @@ ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags) } } -#endif /* CONFIG_NET */ +#endif /* CONFIG_NET && !CONFIG_NET_CMSG */ diff --git a/net/bluetooth/bluetooth_sockif.c b/net/bluetooth/bluetooth_sockif.c index fd6d95f..4057d93 100644 --- a/net/bluetooth/bluetooth_sockif.c +++ b/net/bluetooth/bluetooth_sockif.c @@ -109,8 +109,9 @@ const struct sock_intf_s g_bluetooth_sockif = NULL, /* si_sendfile */ #endif bluetooth_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif bluetooth_close /* si_close */ }; diff --git a/net/can/Kconfig b/net/can/Kconfig index 3b2e450..ac94021 100644 --- a/net/can/Kconfig +++ b/net/can/Kconfig @@ -18,6 +18,10 @@ config NET_CAN if NET_CAN +config NET_CAN_HAVE_TX_DEADLINE + bool + default n + config CAN_CONNS int "Number of CAN connections" default 4 @@ -27,9 +31,25 @@ config CAN_CONNS config NET_CAN_SOCK_OPTS bool "sockopt support" default n + select NET_SOCKOPTS select NET_CANPROTO_OPTIONS ---help--- Enable support for the CAN socket options + +config NET_CAN_RAW_TX_DEADLINE + bool "TX deadline sockopt" + default n + depends on NET_CAN_SOCK_OPTS && NET_CAN_HAVE_TX_DEADLINE + select NET_CMSG + ---help--- + Note: Non-standard SocketCAN sockopt, but this options helps us in + real-time use cases. + + When the CAN_RAW_TX_DEADLINE sockopt is enabled. The user can send + CAN frames using sendmsg() function and add a deadline timespec + value in the CMSG data. When the deadline has been passed and the + CAN frame is still in the HW TX mailbox then the CAN driver will + discard the CAN frame automatically. config NET_CAN_RAW_FILTER_MAX int "CAN_RAW_FILTER max filter count" diff --git a/net/can/can.h b/net/can/can.h index 7c6b614..00c297d 100644 --- a/net/can/can.h +++ b/net/can/can.h @@ -104,20 +104,23 @@ struct can_conn_s */ struct can_poll_s pollinfo[4]; /* FIXME make dynamic */ - + #ifdef CONFIG_NET_CANPROTO_OPTIONS int32_t loopback; int32_t recv_own_msgs; int32_t fd_frames; struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX]; int32_t filter_count; - - /* TODO add filter support */ +# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE + int32_t tx_deadline; +# endif #endif - + #ifdef CONFIG_NET_TIMESTAMP FAR struct socket *psock; /* Needed to get SO_TIMESTAMP value */ #endif + + }; /**************************************************************************** @@ -166,8 +169,8 @@ FAR struct can_conn_s *can_alloc(void); * Name: can_free() * * Description: - * Free a NetLink connection structure that is no longer in use. This - * should be done by the implementation of close(). + * Free a NetLink connection structure that is no longer in use. This should + * be done by the implementation of close(). * ****************************************************************************/ @@ -256,6 +259,7 @@ uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer, * ****************************************************************************/ + ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, int flags, FAR struct sockaddr *from, FAR socklen_t *fromlen); diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c index 238695c..17184e2 100644 --- a/net/can/can_getsockopt.c +++ b/net/can/can_getsockopt.c @@ -188,6 +188,27 @@ int can_getsockopt(FAR struct socket *psock, int option, case CAN_RAW_JOIN_FILTERS: break; +#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE + case CAN_RAW_TX_DEADLINE: + if (*value_len < sizeof(conn->tx_deadline)) + { + /* REVISIT: POSIX says that we should truncate the value if it + * is larger than value_len. That just doesn't make sense + * to me in this case. + */ + + ret = -EINVAL; + } + else + { + FAR int *tx_deadline = (FAR int32_t *)value; + *tx_deadline = conn->tx_deadline; + *value_len = sizeof(conn->tx_deadline); + ret = OK; + } + break; +#endif + default: nerr("ERROR: Unrecognized RAW CAN socket option: %d\n", option); ret = -ENOPROTOOPT; diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c index 2211ed0..d9ed8cb 100644 --- a/net/can/can_recvfrom.c +++ b/net/can/can_recvfrom.c @@ -50,19 +50,20 @@ #include <sys/time.h> #endif + /**************************************************************************** * Private Types ****************************************************************************/ struct can_recvfrom_s { - FAR struct socket *pr_sock; /* The parent socket structure */ + FAR struct socket *pr_sock; /* The parent socket structure */ FAR struct devif_callback_s *pr_cb; /* Reference to callback instance */ sem_t pr_sem; /* Semaphore signals recv completion */ size_t pr_buflen; /* Length of receive buffer */ FAR uint8_t *pr_buffer; /* Pointer to receive buffer */ ssize_t pr_recvlen; /* The received length */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG size_t pr_msglen; /* Length of msg buffer */ FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */ #endif @@ -232,15 +233,14 @@ static inline void can_newdata(FAR struct net_driver_s *dev, static inline int can_readahead(struct can_recvfrom_s *pstate) { - FAR struct can_conn_s *conn = - (FAR struct can_conn_s *) pstate->pr_sock->s_conn; + FAR struct can_conn_s *conn = (FAR struct can_conn_s *)pstate->pr_sock->s_conn; FAR struct iob_s *iob; int recvlen; /* Check there is any CAN data already buffered in a read-ahead * buffer. */ - + pstate->pr_recvlen = -1; if ((iob = iob_peek_queue(&conn->readahead)) != NULL && @@ -287,16 +287,15 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) IOBUSER_NET_CAN_READAHEAD); } - /* do not pass frames with DLC > 8 to a legacy socket */ - - if (!conn->fd_frames) - { - struct canfd_frame *cfd = (struct canfd_frame *)pstate->pr_buffer; - if (cfd->len > CAN_MAX_DLEN) - { - return 0; - } - } + /* do not pass frames with DLC > 8 to a legacy socket */ + if (!conn->fd_frames) + { + struct canfd_frame *cfd = (struct canfd_frame *)pstate->pr_buffer; + if (cfd->len > CAN_MAX_DLEN) + { + return 0; + } + } return recvlen; } @@ -320,14 +319,13 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) * The network is locked. * ****************************************************************************/ - #ifdef CONFIG_NET_TIMESTAMP -static inline int can_readahead_timestamp(struct can_conn_s *conn, - FAR uint8_t *buffer) +static inline int can_readahead_timestamp(struct can_conn_s *conn, FAR uint8_t *buffer) { FAR struct iob_s *iob; int recvlen; + if ((iob = iob_peek_queue(&conn->readahead)) != NULL) { DEBUGASSERT(iob->io_pktlen > 0); @@ -381,27 +379,26 @@ static inline int can_readahead_timestamp(struct can_conn_s *conn, #ifdef CONFIG_NET_CANPROTO_OPTIONS static int can_recv_filter(struct can_conn_s *conn, canid_t id) { - for (int i = 0; i < conn->filter_count; i++) + for(int i = 0; i < conn->filter_count; i++) { - if (conn->filters[i].can_id & CAN_INV_FILTER) - { - if ((id & conn->filters[i].can_mask) != - ((conn->filters[i].can_id & ~CAN_INV_FILTER) & - conn->filters[i].can_mask)) - { - return 1; - } - } - else - { - if ((id & conn->filters[i].can_mask) == - (conn->filters[i].can_id & conn->filters[i].can_mask)) - { - return 1; - } - } + if (conn->filters[i].can_id & CAN_INV_FILTER) + { + if((id & conn->filters[i].can_mask) != + ((conn->filters[i].can_id & ~CAN_INV_FILTER) + & conn->filters[i].can_mask)) + { + return 1; + } + } + else + { + if((id & conn->filters[i].can_mask) == + (conn->filters[i].can_id & conn->filters[i].can_mask)) + { + return 1; + } + } } - return 0; } #endif @@ -419,50 +416,46 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, { if ((flags & CAN_NEWDATA) != 0) { - /* If a new packet is available, check receive filters - * when is valid then complete the read action. - */ + /* If a new packet is available, check receive filters + * when is valid then complete the read action. */ #ifdef CONFIG_NET_CANPROTO_OPTIONS - if (can_recv_filter(conn, (canid_t) *dev->d_appdata) == 0) - { - flags &= ~CAN_NEWDATA; - return flags; - } + if(can_recv_filter(conn,(canid_t)*dev->d_appdata) == 0) + { + flags &= ~CAN_NEWDATA; + return flags; + } #endif - /* do not pass frames with DLC > 8 to a legacy socket */ - - if (!conn->fd_frames) - { - struct canfd_frame *cfd = (struct canfd_frame *)dev->d_appdata; - if (cfd->len > CAN_MAX_DLEN) - { - /* DO WE NEED TO CLEAR FLAGS?? */ - - flags &= ~CAN_NEWDATA; - return flags; - } - } + /* do not pass frames with DLC > 8 to a legacy socket */ + if (!conn->fd_frames) + { + struct canfd_frame *cfd = (struct canfd_frame*)dev->d_appdata; + if (cfd->len > CAN_MAX_DLEN) + { + /* DO WE NEED TO CLEAR FLAGS?? */ + flags &= ~CAN_NEWDATA; + return flags; + } + } /* Copy the packet */ can_newdata(dev, pstate); #ifdef CONFIG_NET_TIMESTAMP - if (pstate->pr_sock->s_timestamp) - { - if (pstate->pr_msglen == sizeof(struct timeval)) - { - can_readahead_timestamp(conn, pstate->pr_msgbuf); - } - else - { - /* We still have to consume the data otherwise IOB gets full */ - - uint8_t dummy_buf[sizeof(struct timeval)]; - can_readahead_timestamp(conn, &dummy_buf); - } - } + if(pstate->pr_sock->s_timestamp) + { + if(pstate->pr_msglen == sizeof(struct timeval)) + { + can_readahead_timestamp(conn, pstate->pr_msgbuf); + } + else + { + /* We still have to consume the data otherwise IOB gets full */ + uint8_t dummy_buf[sizeof(struct timeval)]; + can_readahead_timestamp(conn, &dummy_buf); + } + } #endif /* We are finished. */ @@ -515,7 +508,6 @@ static ssize_t can_recvfrom_result(int result, if (pstate->pr_result < 0) { /* This might return EAGAIN on a timeout */ - return pstate->pr_result; } @@ -600,10 +592,10 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, ret = can_readahead(&state); if (ret > 0) - { + { goto errout_with_state; } - + ret = state.pr_recvlen; /* Handle non-blocking CAN sockets */ @@ -618,7 +610,7 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, { /* Nothing was received */ - ret = -EAGAIN; + ret = -EAGAIN; goto errout_with_state; } } @@ -683,7 +675,6 @@ errout_with_state: * flags Receive flags (ignored) * ****************************************************************************/ - #ifdef CONFIG_NET_RECVMSG_CMSG ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, size_t len, int flags) @@ -716,22 +707,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */ nxsem_setprotocol(&state.pr_sem, SEM_PRIO_NONE); + state.pr_buflen = msg->msg_iov->iov_len; state.pr_buffer = msg->msg_iov->iov_base; - #ifdef CONFIG_NET_TIMESTAMP - if (psock->s_timestamp && msg->msg_controllen == - (sizeof(struct cmsghdr) + sizeof(struct timeval))) + if(psock->s_timestamp && msg->msg_controllen == (sizeof(struct cmsghdr) + sizeof(struct timeval))) { - struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); - state.pr_msglen = sizeof(struct timeval); - state.pr_msgbuf = CMSG_DATA(cmsg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SO_TIMESTAMP; - cmsg->cmsg_len = state.pr_msglen; + struct cmsghdr* cmsg = CMSG_FIRSTHDR(msg); + state.pr_msglen = sizeof(struct timeval); + state.pr_msgbuf = CMSG_DATA(cmsg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMP; + cmsg->cmsg_len = state.pr_msglen; } #endif - state.pr_sock = psock; /* Handle any any CAN data already buffered in a read-ahead buffer. NOTE @@ -743,22 +732,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, if (ret > 0) { #ifdef CONFIG_NET_TIMESTAMP - if (psock->s_timestamp) - { - if (state.pr_msglen == sizeof(struct timeval)) - { - can_readahead_timestamp(conn, state.pr_msgbuf); - } - else - { - /* We still have to consume the data otherwise IOB gets full */ - - uint8_t dummy_buf[sizeof(struct timeval)]; - can_readahead_timestamp(conn, &dummy_buf); - } - } + if(psock->s_timestamp) + { + if(state.pr_msglen == sizeof(struct timeval)) + { + can_readahead_timestamp(conn, state.pr_msgbuf); + } + else + { + /* We still have to consume the data otherwise IOB gets full */ + uint8_t dummy_buf[sizeof(struct timeval)]; + can_readahead_timestamp(conn, &dummy_buf); + } + } #endif - goto errout_with_state; } diff --git a/net/can/can_send.c b/net/can/can_send.c index 644adc3..dfb03d0 100644 --- a/net/can/can_send.c +++ b/net/can/can_send.c @@ -76,6 +76,10 @@ struct send_s sem_t snd_sem; /* Used to wake up the waiting thread */ FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */ size_t snd_buflen; /* Number of bytes in the buffer to send */ +#ifdef CONFIG_NET_CMSG + size_t pr_msglen; /* Length of msg buffer */ + FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */ +#endif ssize_t snd_sent; /* The number of bytes sent */ }; diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c index 6858c1a..ac9f912 100644 --- a/net/can/can_setsockopt.c +++ b/net/can/can_setsockopt.c @@ -147,6 +147,16 @@ int can_setsockopt(FAR struct socket *psock, int option, case CAN_RAW_JOIN_FILTERS: break; +#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE + case CAN_RAW_TX_DEADLINE: + if (value_len != sizeof(conn->tx_deadline)) + return -EINVAL; + + conn->tx_deadline = *(FAR int32_t *)value; + + break; +#endif + default: nerr("ERROR: Unrecognized CAN option: %d\n", option); ret = -ENOPROTOOPT; diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c index 737788e..09a61d0 100644 --- a/net/can/can_sockif.c +++ b/net/can/can_sockif.c @@ -69,6 +69,10 @@ static ssize_t can_send(FAR struct socket *psock, static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen); +#ifdef CONFIG_NET_CMSG +static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, + size_t len, int flags); +#endif static int can_close(FAR struct socket *psock); /**************************************************************************** @@ -93,8 +97,9 @@ const struct sock_intf_s g_can_sockif = NULL, /* si_sendfile */ #endif can_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG can_recvmsg, /* si_recvmsg */ + can_sendmsg, /* si_sendmsg */ #endif can_close /* si_close */ }; @@ -774,6 +779,50 @@ static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf, } /**************************************************************************** + * Name: can_sendmsg + * + * Description: + * The can_sendmsg() send a CAN frame to psock + * + * Input Parameters: + * psock - An instance of the internal socket structure. + * msg - CAN frame and optional CMSG + * flags - Send flags (ignored) + * + * Returned Value: + * On success, returns the number of characters sent. On error, a negated + * errno value is returned (see send() for the list of appropriate error + * values. + * + ****************************************************************************/ +#ifdef CONFIG_NET_CMSG +static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, + size_t len, int flags); +{ + ssize_t ret; + + /* Only SOCK_RAW is supported */ + + if (psock->s_type == SOCK_RAW) + { + /* Raw packet send */ + + ret = psock_can_send(psock, buf, len); + } + else + { + /* EDESTADDRREQ. Signifies that the socket is not connection-mode and + * no peer address is set. + */ + + ret = -EDESTADDRREQ; + } + + return ret; +} +#endif + +/**************************************************************************** * Name: can_close * * Description: diff --git a/net/icmp/icmp_sockif.c b/net/icmp/icmp_sockif.c index c81592e..ebe2bab 100644 --- a/net/icmp/icmp_sockif.c +++ b/net/icmp/icmp_sockif.c @@ -102,8 +102,9 @@ const struct sock_intf_s g_icmp_sockif = NULL, /* si_sendfile */ #endif icmp_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif icmp_close /* si_close */ }; diff --git a/net/icmpv6/icmpv6_sockif.c b/net/icmpv6/icmpv6_sockif.c index 29e5e47..5adae60 100644 --- a/net/icmpv6/icmpv6_sockif.c +++ b/net/icmpv6/icmpv6_sockif.c @@ -102,8 +102,9 @@ const struct sock_intf_s g_icmpv6_sockif = NULL, /* si_sendfile */ #endif icmpv6_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif icmpv6_close /* si_close */ }; diff --git a/net/ieee802154/ieee802154_sockif.c b/net/ieee802154/ieee802154_sockif.c index d1ac29b..6c0f88a 100644 --- a/net/ieee802154/ieee802154_sockif.c +++ b/net/ieee802154/ieee802154_sockif.c @@ -107,8 +107,9 @@ const struct sock_intf_s g_ieee802154_sockif = NULL, /* si_sendfile */ #endif ieee802154_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif ieee802154_close /* si_close */ }; diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index 0980989..abdef2e 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -117,8 +117,9 @@ static const struct sock_intf_s g_inet_sockif = inet_sendfile, /* si_sendfile */ #endif inet_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif inet_close /* si_close */ }; diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c index 62d56b5..cd9bd66 100644 --- a/net/local/local_sockif.c +++ b/net/local/local_sockif.c @@ -110,8 +110,9 @@ const struct sock_intf_s g_local_sockif = NULL, /* si_sendfile */ #endif local_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif local_close /* si_close */ }; diff --git a/net/netlink/netlink_sockif.c b/net/netlink/netlink_sockif.c index 1c0c815..b3ef9ad 100644 --- a/net/netlink/netlink_sockif.c +++ b/net/netlink/netlink_sockif.c @@ -111,8 +111,9 @@ const struct sock_intf_s g_netlink_sockif = NULL, /* si_sendfile */ #endif netlink_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif netlink_close /* si_close */ }; diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c index bbabf42..dbf3e3c 100644 --- a/net/pkt/pkt_sockif.c +++ b/net/pkt/pkt_sockif.c @@ -108,8 +108,9 @@ const struct sock_intf_s g_pkt_sockif = NULL, /* si_sendfile */ #endif pkt_recvfrom, /* si_recvfrom */ -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG NULL, /* si_recvmsg */ + NULL, /* si_sendmsg */ #endif pkt_close /* si_close */ }; diff --git a/net/socket/Kconfig b/net/socket/Kconfig index f4c9408..f13e22d 100644 --- a/net/socket/Kconfig +++ b/net/socket/Kconfig @@ -58,18 +58,20 @@ config NET_SOLINGER config NET_TIMESTAMP bool "SO_TIMESTAMP socket option" default n - depends on NET_CAN && NET_RECVMSG_CMSG + depends on NET_CAN + select NET_CMSG ---help--- Enable or disable support for the SO_TIMESTAMP socket option. Currently only tested & implemented in SocketCAN but should work on all sockets endif # NET_SOCKOPTS -config NET_RECVMSG_CMSG - bool "recvmsg() control messages (CMSG) support" +config NET_CMSG + bool "Control messages (CMSG) support" default n ---help--- - Enable or disable support for control messages in the recvmsg function. - Control messages (also defined in POSIX 1003.1g as ancillary data object information). - Includes additional information on the packet received. + Enable or disable support for control messages in the recvmsg() and + sendmsg() function. Control messages (also defined in POSIX 1003.1g + as ancillary data object information). Includes additional + information on the packet received or to be transmitted. endmenu # Socket Support diff --git a/net/socket/Make.defs b/net/socket/Make.defs index 2be9dbf..6bf79ed 100644 --- a/net/socket/Make.defs +++ b/net/socket/Make.defs @@ -75,7 +75,8 @@ endif DEPPATH += --dep-path socket VPATH += :socket -# Support for recvmsg() with control messages (CMSG) -ifeq ($(CONFIG_NET_RECVMSG_CMSG),y) +# Support for control messages (CMSG) +ifeq ($(CONFIG_NET_CMSG),y) SOCK_CSRCS += recvmsg.c +SOCK_CSRCS += sendmsg.c endif diff --git a/net/socket/recvmsg.c b/net/socket/recvmsg.c index 17d4dfe..800eeb1 100644 --- a/net/socket/recvmsg.c +++ b/net/socket/recvmsg.c @@ -47,7 +47,7 @@ #include "socket/socket.h" -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG /**************************************************************************** * Public Functions @@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags) return ret; } -#endif /* CONFIG_NET_RECVMSG_CMSG */ +#endif /* CONFIG_NET_CMSG */ diff --git a/net/socket/recvmsg.c b/net/socket/sendmsg.c similarity index 78% copy from net/socket/recvmsg.c copy to net/socket/sendmsg.c index 17d4dfe..3bc32e8 100644 --- a/net/socket/recvmsg.c +++ b/net/socket/sendmsg.c @@ -1,5 +1,5 @@ /**************************************************************************** - * net/socket/recvmsg.c + * net/socket/sendmsg.c * * Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gn...@nuttx.org> @@ -47,20 +47,20 @@ #include "socket/socket.h" -#ifdef CONFIG_NET_RECVMSG_CMSG +#ifdef CONFIG_NET_CMSG /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: psock_recvmsg + * Name: psock_sendmsg * * Description: - * psock_recvfrom() receives messages from a socket, and may be used to - * receive data on a socket whether or not it is connection-oriented. + * psock_sendfrom() sends messages to a socket, and may be used to + * send data on a socket whether or not it is connection-oriented. * This is an internal OS interface. It is functionally equivalent to - * recvfrom() except that: + * sendfrom() except that: * * - It is not a cancellation point, * - It does not modify the errno variable, and @@ -69,20 +69,20 @@ * * Input Parameters: * psock - A pointer to a NuttX-specific, internal socket structure - * msg Buffer to receive msg + * msg - Buffer to of the msg * len - Length of buffer * flags - Receive flags * * Returned Value: * On success, returns the number of characters sent. If no data is * available to be received and the peer has performed an orderly shutdown, - * recv() will return 0. Otherwise, on any failure, a negated errno value + * send() will return 0. Otherwise, on any failure, a negated errno value * is returned (see comments with send() for a list of appropriate errno * values). * ****************************************************************************/ -ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, +ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, int flags) { /* Verify that non-NULL pointers were passed */ @@ -103,38 +103,38 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, return -EBADF; } - /* Let logic specific to this address family handle the recvfrom() + /* Let logic specific to this address family handle the sendfrom() * operation. */ DEBUGASSERT(psock->s_sockif != NULL && - (psock->s_sockif->si_recvmsg != NULL || - psock->s_sockif->si_recvfrom != NULL)); + (psock->s_sockif->si_sendmsg != NULL || + psock->s_sockif->si_sendto != NULL)); - if(psock->s_sockif->si_recvmsg != NULL) + if(psock->s_sockif->si_sendmsg != NULL) { - return psock->s_sockif->si_recvmsg(psock, msg, flags); + return psock->s_sockif->si_sendmsg(psock, msg, flags); } else { - /* Socket doesn't implement si_recvmsg fallback to si_recvfrom */ - FAR void *buf = msg->msg_iov->iov_base; - FAR struct sockaddr *from = msg->msg_name; - FAR socklen_t *fromlen = (FAR socklen_t *)&msg->msg_namelen; - size_t len = msg->msg_iov->iov_len; - return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from, fromlen); + /* Socket doesn't implement si_sendmsg fallback to si_sendto */ + FAR void *buf = msg->msg_iov->iov_base; + FAR struct sockaddr *to = msg->msg_name; + socklen_t tolen = msg->msg_namelen; + size_t len = msg->msg_iov->iov_len; + return psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen); } } /**************************************************************************** - * Name: nx_recvfrom + * Name: nx_sendfrom * * Description: - * nx_recvfrom() receives messages from a socket, and may be used to + * nx_sendfrom() receives messages from a socket, and may be used to * receive data on a socket whether or not it is connection-oriented. * This is an internal OS interface. It is functionally equivalent to - * recvfrom() except that: + * sendfrom() except that: * * - It is not a cancellation point, and * - It does not modify the errno variable. @@ -148,13 +148,13 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, * Returned Value: * On success, returns the number of characters sent. If no data is * available to be received and the peer has performed an orderly shutdown, - * recv() will return 0. Otherwise, on any failure, a negated errno value + * send() will return 0. Otherwise, on any failure, a negated errno value * is returned (see comments with send() for a list of appropriate errno * values). * ****************************************************************************/ -ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags) +ssize_t nx_sendmsg(int sockfd, FAR struct msghdr *msg, int flags) { FAR struct socket *psock; @@ -162,16 +162,16 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags) psock = sockfd_socket(sockfd); - /* Then let psock_recvmsg() do all of the work */ + /* Then let psock_sendmsg() do all of the work */ - return psock_recvmsg(psock, msg, flags); + return psock_sendmsg(psock, msg, flags); } /**************************************************************************** - * Function: recvmsg + * Function: sendmsg * * Description: - * The recvmsg() call is identical to recvfrom() with a NULL from parameter. + * The sendmsg() call is identical to sendfrom() with a NULL from parameter. * * Parameters: * sockfd Socket descriptor of socket @@ -209,12 +209,12 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags) * ****************************************************************************/ -ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags) +ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags) { FAR struct socket *psock; ssize_t ret; - /* recvfrom() is a cancellation point */ + /* sendfrom() is a cancellation point */ enter_cancellation_point(); @@ -222,9 +222,9 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags) psock = sockfd_socket(sockfd); - /* Let psock_recvfrom() do all of the work */ + /* Let psock_sendfrom() do all of the work */ - ret = psock_recvmsg(psock, msg, flags); + ret = psock_sendmsg(psock, msg, flags); if (ret < 0) { _SO_SETERRNO(psock, -ret); @@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags) return ret; } -#endif /* CONFIG_NET_RECVMSG_CMSG */ +#endif /* CONFIG_NET_CMSG */