xref: /minix/minix/lib/libc/sys/socket.c (revision 433d6423)
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