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 #include <sys/ioc_net.h> 15 16 #include <net/netlib.h> 17 #include <netinet/in.h> 18 19 #define DEBUG 0 20 21 static int _tcp_socket(int type, int protocol); 22 static int _udp_socket(int type, int protocol); 23 static int _uds_socket(int type, int protocol); 24 static void _socket_flags(int type, int *result); 25 26 int socket(int domain, int type, int protocol) 27 { 28 int sock_type; 29 30 sock_type = type & ~SOCK_FLAGS_MASK; 31 32 #if DEBUG 33 fprintf(stderr, "socket: domain %d, type %d, protocol %d\n", 34 domain, type, protocol); 35 #endif 36 if (domain != AF_INET && domain != AF_UNIX) 37 { 38 #if DEBUG 39 fprintf(stderr, "socket: bad domain %d\n", domain); 40 #endif 41 errno= EAFNOSUPPORT; 42 return -1; 43 } 44 45 if (domain == AF_UNIX && (sock_type == SOCK_STREAM || 46 sock_type == SOCK_DGRAM || 47 sock_type == SOCK_SEQPACKET)) 48 return _uds_socket(type, protocol); 49 50 if (domain == AF_INET && sock_type == SOCK_STREAM) 51 return _tcp_socket(type, protocol); 52 53 if (domain == AF_INET && sock_type == SOCK_DGRAM) 54 return _udp_socket(type, protocol); 55 56 #if DEBUG 57 fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n", 58 domain, type, protocol); 59 #endif 60 errno= EPROTOTYPE; 61 return -1; 62 } 63 64 static void 65 _socket_flags(int type, int *result) 66 { 67 /* Process socket flags */ 68 if (type & SOCK_CLOEXEC) { 69 *result |= O_CLOEXEC; 70 } 71 if (type & SOCK_NONBLOCK) { 72 *result |= O_NONBLOCK; 73 } 74 if (type & SOCK_NOSIGPIPE) { 75 *result |= O_NOSIGPIPE; 76 } 77 } 78 79 static int _tcp_socket(int type, int protocol) 80 { 81 int flags = O_RDWR; 82 83 if (protocol != 0 && protocol != IPPROTO_TCP) 84 { 85 #if DEBUG 86 fprintf(stderr, "socket(tcp): bad protocol %d\n", protocol); 87 #endif 88 errno= EPROTONOSUPPORT; 89 return -1; 90 } 91 92 _socket_flags(type, &flags); 93 94 return open(TCP_DEVICE, flags); 95 } 96 97 static int _udp_socket(int type, int protocol) 98 { 99 int r, fd, t_errno, flags = O_RDWR; 100 struct sockaddr_in sin; 101 102 if (protocol != 0 && protocol != IPPROTO_UDP) 103 { 104 #if DEBUG 105 fprintf(stderr, "socket(udp): bad protocol %d\n", protocol); 106 #endif 107 errno= EPROTONOSUPPORT; 108 return -1; 109 } 110 _socket_flags(type, &flags); 111 fd= open(UDP_DEVICE, flags); 112 if (fd == -1) 113 return fd; 114 115 /* Bind is implict for UDP sockets? */ 116 sin.sin_family= AF_INET; 117 sin.sin_addr.s_addr= INADDR_ANY; 118 sin.sin_port= 0; 119 r= bind(fd, (struct sockaddr *)&sin, sizeof(sin)); 120 if (r != 0) 121 { 122 t_errno= errno; 123 close(fd); 124 errno= t_errno; 125 return -1; 126 } 127 return fd; 128 } 129 130 static int _uds_socket(int type, int protocol) 131 { 132 int fd, r, flags = O_RDWR, sock_type; 133 if (protocol != 0) 134 { 135 #if DEBUG 136 fprintf(stderr, "socket(uds): bad protocol %d\n", protocol); 137 #endif 138 errno= EPROTONOSUPPORT; 139 return -1; 140 } 141 142 _socket_flags(type, &flags); 143 fd= open(UDS_DEVICE, flags); 144 if (fd == -1) { 145 return fd; 146 } 147 148 /* set the type for the socket via ioctl (SOCK_DGRAM, 149 * SOCK_STREAM, SOCK_SEQPACKET, etc) 150 */ 151 sock_type = type & ~SOCK_FLAGS_MASK; 152 r= ioctl(fd, NWIOSUDSTYPE, &sock_type); 153 if (r == -1) { 154 int ioctl_errno; 155 156 /* if that failed rollback socket creation */ 157 ioctl_errno= errno; 158 close(fd); 159 160 /* return the error thrown by the call to ioctl */ 161 errno= ioctl_errno; 162 return -1; 163 } 164 165 return fd; 166 } 167