1 #include <sys/cdefs.h> 2 #include "namespace.h" 3 #include <lib.h> 4 5 #ifdef __weak_alias 6 __weak_alias(socket, __socket30) 7 #endif 8 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <signal.h> 12 #include <stdio.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <sys/socket.h> 16 17 #include <sys/ioctl.h> 18 #include <sys/ioc_net.h> 19 #include <net/hton.h> 20 #include <net/gen/in.h> 21 #include <net/gen/ether.h> 22 #include <net/gen/eth_hdr.h> 23 #include <net/gen/eth_io.h> 24 #include <net/gen/ip_hdr.h> 25 #include <net/gen/ip_io.h> 26 #include <net/gen/udp.h> 27 #include <net/gen/udp_hdr.h> 28 #include <net/gen/udp_io.h> 29 #include <net/gen/dhcp.h> 30 31 #include <net/netlib.h> 32 #include <netinet/in.h> 33 34 #define DEBUG 0 35 36 static int _tcp_socket(int type, int protocol); 37 static int _udp_socket(int type, int protocol); 38 static int _uds_socket(int type, int protocol); 39 static int _raw_socket(int type, int protocol); 40 static void _socket_flags(int type, int *result); 41 42 /* 43 * Create a socket. 44 */ 45 static int 46 __socket(int domain, int type, int protocol) 47 { 48 message m; 49 50 memset(&m, 0, sizeof(m)); 51 m.m_lc_vfs_socket.domain = domain; 52 m.m_lc_vfs_socket.type = type; 53 m.m_lc_vfs_socket.protocol = protocol; 54 55 return _syscall(VFS_PROC_NR, VFS_SOCKET, &m); 56 } 57 58 int socket(int domain, int type, int protocol) 59 { 60 int r, sock_type; 61 62 r = __socket(domain, type, protocol); 63 if (r != -1 || (errno != EAFNOSUPPORT && errno != ENOSYS)) 64 return r; 65 66 sock_type = type & ~SOCK_FLAGS_MASK; 67 68 #if DEBUG 69 fprintf(stderr, "socket: domain %d, type %d, protocol %d\n", 70 domain, type, protocol); 71 #endif 72 73 if (domain == AF_UNIX) 74 return _uds_socket(type, protocol); 75 76 if (domain == AF_INET) { 77 switch (sock_type) { 78 case SOCK_STREAM: 79 return _tcp_socket(type, protocol); 80 case SOCK_DGRAM: 81 return _udp_socket(type, protocol); 82 case SOCK_RAW: 83 return _raw_socket(type, protocol); 84 default: 85 errno = EPROTOTYPE; 86 return -1; 87 } 88 } 89 90 errno = EAFNOSUPPORT; 91 return -1; 92 } 93 94 static void 95 _socket_flags(int type, int *result) 96 { 97 /* Process socket flags */ 98 if (type & SOCK_CLOEXEC) { 99 *result |= O_CLOEXEC; 100 } 101 if (type & SOCK_NONBLOCK) { 102 *result |= O_NONBLOCK; 103 } 104 if (type & SOCK_NOSIGPIPE) { 105 *result |= O_NOSIGPIPE; 106 } 107 } 108 109 static int _tcp_socket(int type, int protocol) 110 { 111 int flags = O_RDWR; 112 113 if (protocol != 0 && protocol != IPPROTO_TCP) 114 { 115 #if DEBUG 116 fprintf(stderr, "socket(tcp): bad protocol %d\n", protocol); 117 #endif 118 errno= EPROTONOSUPPORT; 119 return -1; 120 } 121 122 _socket_flags(type, &flags); 123 124 return open(TCP_DEVICE, flags); 125 } 126 127 static int _udp_socket(int type, int protocol) 128 { 129 int r, fd, t_errno, flags = O_RDWR; 130 struct sockaddr_in sin; 131 132 if (protocol != 0 && protocol != IPPROTO_UDP) 133 { 134 #if DEBUG 135 fprintf(stderr, "socket(udp): bad protocol %d\n", protocol); 136 #endif 137 errno= EPROTONOSUPPORT; 138 return -1; 139 } 140 _socket_flags(type, &flags); 141 fd= open(UDP_DEVICE, flags); 142 if (fd == -1) 143 return fd; 144 145 /* Bind is implict for UDP sockets? */ 146 sin.sin_family= AF_INET; 147 sin.sin_addr.s_addr= INADDR_ANY; 148 sin.sin_port= 0; 149 r= bind(fd, (struct sockaddr *)&sin, sizeof(sin)); 150 if (r != 0) 151 { 152 t_errno= errno; 153 close(fd); 154 errno= t_errno; 155 return -1; 156 } 157 return fd; 158 } 159 160 static int _raw_socket(int type, int protocol) 161 { 162 int fd, flags = O_RDWR; 163 nwio_ipopt_t ipopt; 164 int result; 165 166 if (protocol != IPPROTO_ICMP && protocol != IPPROTO_UDP && protocol != 0) 167 { 168 #if DEBUG 169 fprintf(stderr, "socket(icmp): bad protocol %d\n", protocol); 170 #endif 171 errno= EPROTONOSUPPORT; 172 return -1; 173 } 174 _socket_flags(type, &flags); 175 fd= open(IP_DEVICE, flags); 176 if (fd == -1) 177 return fd; 178 179 memset(&ipopt, 0, sizeof(ipopt)); 180 181 ipopt.nwio_flags= NWIO_COPY; 182 183 if(protocol) { 184 ipopt.nwio_flags |= NWIO_PROTOSPEC; 185 ipopt.nwio_proto = protocol; 186 } 187 188 result = ioctl (fd, NWIOSIPOPT, &ipopt); 189 if (result<0) { 190 close(fd); 191 return -1; 192 } 193 194 result = ioctl (fd, NWIOGIPOPT, &ipopt); 195 if (result<0) { 196 close(fd); 197 return -1; 198 } 199 200 return fd; 201 } 202 203 static int _uds_socket(int type, int protocol) 204 { 205 int fd, r, flags = O_RDWR, sock_type; 206 207 sock_type = type & ~SOCK_FLAGS_MASK; 208 if (sock_type != SOCK_STREAM && 209 sock_type != SOCK_DGRAM && 210 sock_type != SOCK_SEQPACKET) { 211 errno = EPROTOTYPE; 212 return -1; 213 } 214 215 if (protocol != 0) 216 { 217 #if DEBUG 218 fprintf(stderr, "socket(uds): bad protocol %d\n", protocol); 219 #endif 220 errno= EPROTONOSUPPORT; 221 return -1; 222 } 223 224 _socket_flags(type, &flags); 225 fd= open(UDS_DEVICE, flags); 226 if (fd == -1) { 227 return fd; 228 } 229 230 /* set the type for the socket via ioctl (SOCK_DGRAM, 231 * SOCK_STREAM, SOCK_SEQPACKET, etc) 232 */ 233 r= ioctl(fd, NWIOSUDSTYPE, &sock_type); 234 if (r == -1) { 235 int ioctl_errno; 236 237 /* if that failed rollback socket creation */ 238 ioctl_errno= errno; 239 close(fd); 240 241 /* return the error thrown by the call to ioctl */ 242 errno= ioctl_errno; 243 return -1; 244 } 245 246 return fd; 247 } 248