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