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