diff --git a/tests/udp/BUILD.gn b/tests/udp/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6f02564811c0b51544dee33107fff9616a08e2d9 --- /dev/null +++ b/tests/udp/BUILD.gn @@ -0,0 +1,20 @@ +executable("UdpTest") { + sources = [ + "udp.c" + ] + include_dirs = [ + "//third_party/bounds_checking_function/include" + ] + deps = [ + "//third_party/bounds_checking_function:libsec_shared" + ] + + cflags = [ + "-fPIC", + "-O2", + "-fstack-protector-all", + ] + + + cflags_cc = cflags +} \ No newline at end of file diff --git a/tests/udp/udp.c b/tests/udp/udp.c new file mode 100644 index 0000000000000000000000000000000000000000..f8038250b36ab9bfb7d8aba4abf73dd191617e6f --- /dev/null +++ b/tests/udp/udp.c @@ -0,0 +1,271 @@ +#ifndef __MUSL__ +#define __MUSL__ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" + +#define MONIOTR_SLEEP_TIME_SEC 10 +#define DEFAULT_NETLINK_RECVBUF (32 * 1024) +#define EOK 0 + + +#undef NLMSG_OK +#define NLMSG_OK(nlh, len) \ + (((len) >= (int32_t)(sizeof(struct nlmsghdr))) && (((nlh)->nlmsg_len) >= sizeof(struct nlmsghdr)) && \ + ((int32_t)((nlh)->nlmsg_len) <= (len))) + +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef struct { + uint16_t saFamily; /* address family */ + char saData[14]; +} SoftbusAddr; + +enum SoftBusAdapterErrNo { + SOFTBUS_ADAPTER_COMMON_ERR_BASE = (-10000), + SOFTBUS_ADAPTER_INVALID_PARAM, + + SOFTBUS_ADAPTER_FILE_ERR_BASE = (-9000), + SOFTBUS_ADAPTER_FILE_EXIST, + + SOFTBUS_ADAPTER_SOCKET_ERR_BASE = (-8000), + SOFTBUS_ADAPTER_SOCKET_EINTR, + SOFTBUS_ADAPTER_SOCKET_EINPROGRESS, + SOFTBUS_ADAPTER_SOCKET_EAGAIN, + SOFTBUS_ADAPTER_SOCKET_EBADF, + SOFTBUS_ADAPTER_SOCKET_EINVAL, + SOFTBUS_ADAPTER_SOCKET_ENETUNREACH, + + SOFTBUS_ERR = (-2), + SOFTBUS_ADAPTER_ERR = (-1), + SOFTBUS_ADAPTER_OK = 0, +}; + + +static int32_t GetErrorCode(void) +{ + int32_t errCode; + switch (errno) { + case EINTR: + errCode = SOFTBUS_ADAPTER_SOCKET_EINTR; + break; + case EINPROGRESS: + errCode = SOFTBUS_ADAPTER_SOCKET_EINPROGRESS; + break; + case EAGAIN: + errCode = SOFTBUS_ADAPTER_SOCKET_EAGAIN; + break; + case EBADF: + errCode = SOFTBUS_ADAPTER_SOCKET_EBADF; + break; + case EINVAL: + errCode = SOFTBUS_ADAPTER_SOCKET_EINVAL; + break; + case ENETUNREACH: + errCode = SOFTBUS_ADAPTER_SOCKET_ENETUNREACH; + break; + default: + errCode = SOFTBUS_ADAPTER_ERR; + break; + } + return errCode; +} + +int32_t SocketCreate(int32_t domain, int32_t type, int32_t protocol, int32_t *socketFd) +{ + if (socketFd == NULL) { + printf("socket is null"); + return SOFTBUS_ADAPTER_INVALID_PARAM; + } + int32_t ret = socket(domain, type, protocol); + if (ret < 0) { + printf("socket errno=%s", strerror(errno)); + return SOFTBUS_ADAPTER_ERR; + } else { + *socketFd = ret; + return SOFTBUS_ADAPTER_OK; + } +} + +int32_t SocketSetOpt(int32_t socketFd, int32_t level, int32_t optName, const void *optVal, int32_t optLen) +{ + int32_t ret = setsockopt(socketFd, level, optName, optVal, (socklen_t)optLen); + if (ret != 0) { + printf("setsockopt errno=%s", strerror(errno)); + return SOFTBUS_ADAPTER_ERR; + } + + return SOFTBUS_ADAPTER_OK; +} + + +static int32_t ConvertAddrToSysAddr(const SoftbusAddr *socketAddr, struct sockaddr *sysAddr, uint32_t len) +{ + if ((socketAddr == NULL) || (sysAddr == NULL)) { + printf("invalid input"); + return SOFTBUS_ADAPTER_ERR; + } + if (len < sizeof(socketAddr->saFamily)) { + printf("invalid len"); + return SOFTBUS_ADAPTER_ERR; + } + if (memset_s(sysAddr, sizeof(struct sockaddr), 0, sizeof(struct sockaddr)) != EOK) { + printf("memset fail"); + return SOFTBUS_ADAPTER_ERR; + } + sysAddr->sa_family = socketAddr->saFamily; + if (memcpy_s(sysAddr->sa_data, sizeof(sysAddr->sa_data), socketAddr->saData, + len - sizeof(socketAddr->saFamily)) != EOK) { + printf("memcpy fail"); + return SOFTBUS_ADAPTER_ERR; + } + return SOFTBUS_ADAPTER_OK; +} + + +int32_t SocketBind(int32_t socketFd, SoftbusAddr *addr, int32_t addrLen) +{ + if (addr == NULL || addrLen < 0) { + printf("socket bind invalid input"); + return SOFTBUS_ADAPTER_ERR; + } + struct sockaddr sysAddr; + uint32_t len = ((uint32_t)addrLen >= sizeof(SoftbusAddr)) ? sizeof(SoftbusAddr) : (uint32_t)addrLen; + printf("saFamily=%d\n", addr->saFamily); + if (ConvertAddrToSysAddr(addr, &sysAddr, len) != SOFTBUS_ADAPTER_OK) { + printf("socket bind sys addr to softbus addr failed"); + return SOFTBUS_ADAPTER_ERR; + } + int32_t ret = bind(socketFd, &sysAddr, (socklen_t)addrLen); + if (ret != 0) { + printf("bind strerror=%s, errno=%d", strerror(errno), errno); + return GetErrorCode(); + } + + return SOFTBUS_ADAPTER_OK; +} + +int32_t CloseSocket(int32_t socketFd) +{ + int32_t ret = close(socketFd); + if (ret != 0) { + printf("close errno=%s", strerror(errno)); + return SOFTBUS_ADAPTER_ERR; + } + + return SOFTBUS_ADAPTER_OK; +} + + +int32_t CreateNetlinkSocket() +{ + int32_t sockFd; + struct sockaddr_nl nladdr; + int32_t sz = DEFAULT_NETLINK_RECVBUF; + + int32_t ret = SocketCreate(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE, &sockFd); + if (ret != SOFTBUS_ADAPTER_OK) { + printf("open netlink socket failed"); + return SOFTBUS_ERR; + } + if (SocketSetOpt(sockFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 && + SocketSetOpt(sockFd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) { + printf("set uevent socket SO_RCVBUF option failed"); + CloseSocket(sockFd); + return SOFTBUS_ERR; + } + if (memset_s(&nladdr, sizeof(nladdr), 0, sizeof(nladdr)) != EOK) { + printf("init sockaddr_nl failed"); + CloseSocket(sockFd); + return SOFTBUS_ERR; + } + nladdr.nl_family = AF_NETLINK; + // Kernel will assign a unique nl_pid if set to zero. + nladdr.nl_pid = 0; + nladdr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR; + if (SocketBind(sockFd, (SoftbusAddr *)&nladdr, sizeof(nladdr)) < 0) { + printf("bind netlink socket failed"); + CloseSocket(sockFd); + return SOFTBUS_ERR; + } + return sockFd; +} + + + +int32_t SocketRecv(int32_t socketFd, void *buf, uint32_t len, int32_t flags) +{ + int32_t ret = recv(socketFd, buf, len, flags); + if (ret < 0) { + printf("recv errno=%s", strerror(errno)); + return GetErrorCode(); + } + + return ret; +} + +int32_t main() +{ + struct nlmsghdr *nlh = NULL; + sleep(MONIOTR_SLEEP_TIME_SEC); + printf("test udp monitor thread start\n"); + int32_t socketFd = CreateNetlinkSocket(); + if (socketFd < 0) { + printf("create netlink socket failed\n"); + return false; + } + uint8_t *buffer = (uint8_t *)malloc(DEFAULT_NETLINK_RECVBUF * sizeof(uint8_t)); + if (buffer == NULL) { + CloseSocket(socketFd); + return false; + } + + while (true) { + (void)memset_s(buffer, DEFAULT_NETLINK_RECVBUF, 0, DEFAULT_NETLINK_RECVBUF); + int32_t len = SocketRecv(socketFd, buffer, DEFAULT_NETLINK_RECVBUF, 0); + if (len < 0 && len == SOFTBUS_ADAPTER_SOCKET_EINTR) { + continue; + } + if (len < 0) { + printf("recv socket error\n"); + break; + } + if (len < (int32_t)sizeof(struct nlmsghdr)) { + printf("recv buffer not enough\n"); + continue; + } + nlh = (struct nlmsghdr *)buffer; + while (NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE) { + printf("nlmsg_type=%d\n", nlh->nlmsg_type); + switch (nlh->nlmsg_type) { + case RTM_NEWADDR: + case RTM_DELADDR: + printf("ADDR event happend!, type:%d\n", nlh->nlmsg_type); + break; + case RTM_NEWLINK: + case RTM_DELLINK: + printf("LINK event happend!, type:%d\n", nlh->nlmsg_type); + break; + default: + break; + } + nlh = NLMSG_NEXT(nlh, len); + } + } + CloseSocket(socketFd); + free(buffer); + printf("test netlink monitor thread exit"); + return 0; +} \ No newline at end of file