1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <assert.h> 14#include <stdarg.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <stdint.h> 18#include <string.h> 19#include <errno.h> 20#include <sys/socket.h> 21#include <muslcsys/io.h> 22 23#include "sys_io.h" 24 25int sock_socket(int domain, int type, int protocol) __attribute__((weak)); 26long camkes_sys_socket(va_list ap) 27{ 28 int domain = va_arg(ap, int); 29 int type = va_arg(ap, int); 30 int protocol = va_arg(ap, int); 31 int fd; 32 muslcsys_fd_t *fdt; 33 34 if (sock_socket) { 35 fd = allocate_fd(); 36 fdt = get_fd_struct(fd); 37 fdt->data = malloc(sizeof(int)); 38 *(int *)fdt->data = sock_socket(domain, type, protocol); 39 fdt->filetype = FILE_TYPE_SOCKET; 40 return fd; 41 } else { 42 assert(!"sys_socket not implemented"); 43 } 44 45 return 0; 46} 47 48int sock_bind(int sockfd, int addrlen) __attribute__((weak)); 49long camkes_sys_bind(va_list ap) 50{ 51 int fd = va_arg(ap, int); 52 const struct sockaddr *addr = va_arg(ap, const struct sockaddr *); 53 socklen_t addrlen = va_arg(ap, socklen_t); 54 muslcsys_fd_t *fdt; 55 int sockfd; 56 57 if (sock_bind && sock_data) { 58 fdt = get_fd_struct(fd); 59 sockfd = *(int *)fdt->data; 60 memcpy((char *)sock_data, addr, addrlen); 61 return sock_bind(sockfd, addrlen); 62 } else { 63 assert(!"sys_bind not implemented"); 64 } 65 66 return -1; 67} 68 69int sock_connect(int sockfd, int addrlen) __attribute__((weak)); 70long camkes_sys_connect(va_list ap) 71{ 72 int fd = va_arg(ap, int); 73 const struct sockaddr *addr = va_arg(ap, const struct sockaddr *); 74 socklen_t addrlen = va_arg(ap, socklen_t); 75 76 muslcsys_fd_t *fdt; 77 int sockfd; 78 79 if (sock_connect && sock_data) { 80 fdt = get_fd_struct(fd); 81 sockfd = *(int *)fdt->data; 82 memcpy((char *)sock_data, addr, addrlen); 83 return sock_connect(sockfd, addrlen); 84 } else { 85 assert(!"sys_connect not implemented"); 86 } 87 88 return -1; 89} 90 91int sock_listen(int sockfd, int backlog) __attribute__((weak)); 92long camkes_sys_listen(va_list ap) 93{ 94 int fd = va_arg(ap, int); 95 int backlog = va_arg(ap, int); 96 muslcsys_fd_t *fdt; 97 int sockfd; 98 99 if (sock_listen) { 100 fdt = get_fd_struct(fd); 101 sockfd = *(int *)fdt->data; 102 return sock_listen(sockfd, backlog); 103 } else { 104 assert(!"sys_listen not implemented"); 105 } 106 107 return -1; 108} 109 110int sock_accept(int sockfd) __attribute__((weak)); 111long camkes_sys_accept(va_list ap) 112{ 113 int fd = va_arg(ap, int); 114 struct sockaddr *addr = va_arg(ap, struct sockaddr *); 115 socklen_t *addrlen = va_arg(ap, socklen_t *); 116 117 muslcsys_fd_t *fdt; 118 int sockfd; 119 int newsockfd; 120 121 if (sock_accept && sock_data) { 122 fdt = get_fd_struct(fd); 123 sockfd = *(int *)fdt->data; 124 125 /* addr can be NULL, which means ignore the peer address. */ 126 if (addr) { 127 memcpy((char *)sock_data, addr, sizeof(struct sockaddr)); 128 memcpy((char *)sock_data + sizeof(struct sockaddr), addrlen, sizeof(socklen_t)); 129 } 130 131 newsockfd = sock_accept(sockfd); 132 133 /* -1 is returned when the call fails. */ 134 if (newsockfd == -1) { 135 memcpy(&errno, (void *)sock_data, sizeof(errno)); 136 return newsockfd; 137 } 138 139 if (addr) { 140 memcpy(addr, (char *)sock_data, sizeof(struct sockaddr)); 141 memcpy(addrlen, (char *)sock_data + sizeof(struct sockaddr), sizeof(socklen_t)); 142 } 143 144 /* 145 * Accept returns a new socket file descriptor, so we need to 146 * allocate a new file descriptor. 147 */ 148 fd = allocate_fd(); 149 fdt = get_fd_struct(fd); 150 fdt->data = malloc(sizeof(int)); 151 *(int *)fdt->data = newsockfd; 152 fdt->filetype = FILE_TYPE_SOCKET; 153 154 return fd; 155 } else { 156 assert(!"sys_accept not implemented"); 157 } 158 159 return -1; 160} 161 162int sock_setsockopt(int sockfd, int level, int optname, int optlen) __attribute__((weak)); 163long camkes_sys_setsockopt(va_list ap) 164{ 165 int fd = va_arg(ap, int); 166 int level = va_arg(ap, int); 167 int optname = va_arg(ap, int); 168 const void *optval = va_arg(ap, const void *); 169 socklen_t optlen = va_arg(ap, socklen_t); 170 171 muslcsys_fd_t *fdt; 172 int sockfd; 173 174 if (sock_setsockopt && sock_data) { 175 fdt = get_fd_struct(fd); 176 sockfd = *(int *)fdt->data; 177 178 memcpy((char *)sock_data, optval, optlen); 179 return sock_setsockopt(sockfd, level, optname, optlen); 180 } else { 181 assert(!"sys_setsockopt not implemented"); 182 } 183 184 return -1; 185} 186