netbsd ping & traceroute
[minix3.git] / minix / lib / libc / sys / socket.c
blobf73828a0187ad41838c860975d2d0d2c3b3b4640
1 #include <sys/cdefs.h>
2 #include "namespace.h"
4 #ifdef __weak_alias
5 __weak_alias(socket, __socket30)
6 #endif
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>
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>
28 #include <net/netlib.h>
29 #include <netinet/in.h>
31 #define DEBUG 0
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);
39 int socket(int domain, int type, int protocol)
41 int sock_type;
43 sock_type = type & ~SOCK_FLAGS_MASK;
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)
51 #if DEBUG
52 fprintf(stderr, "socket: bad domain %d\n", domain);
53 #endif
54 errno= EAFNOSUPPORT;
55 return -1;
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);
63 if (domain == AF_INET && sock_type == SOCK_STREAM)
64 return _tcp_socket(type, protocol);
66 if (domain == AF_INET && sock_type == SOCK_DGRAM)
67 return _udp_socket(type, protocol);
69 if (domain == AF_INET && sock_type == SOCK_RAW && protocol == IPPROTO_ICMP)
70 return _raw_socket(type, protocol);
72 if (domain == AF_INET && sock_type == SOCK_RAW && protocol == IPPROTO_UDP)
73 return _raw_socket(type, protocol);
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;
83 static void
84 _socket_flags(int type, int *result)
86 /* Process socket flags */
87 if (type & SOCK_CLOEXEC) {
88 *result |= O_CLOEXEC;
90 if (type & SOCK_NONBLOCK) {
91 *result |= O_NONBLOCK;
93 if (type & SOCK_NOSIGPIPE) {
94 *result |= O_NOSIGPIPE;
98 static int _tcp_socket(int type, int protocol)
100 int flags = O_RDWR;
102 if (protocol != 0 && protocol != IPPROTO_TCP)
104 #if DEBUG
105 fprintf(stderr, "socket(tcp): bad protocol %d\n", protocol);
106 #endif
107 errno= EPROTONOSUPPORT;
108 return -1;
111 _socket_flags(type, &flags);
113 return open(TCP_DEVICE, flags);
116 static int _udp_socket(int type, int protocol)
118 int r, fd, t_errno, flags = O_RDWR;
119 struct sockaddr_in sin;
121 if (protocol != 0 && protocol != IPPROTO_UDP)
123 #if DEBUG
124 fprintf(stderr, "socket(udp): bad protocol %d\n", protocol);
125 #endif
126 errno= EPROTONOSUPPORT;
127 return -1;
129 _socket_flags(type, &flags);
130 fd= open(UDP_DEVICE, flags);
131 if (fd == -1)
132 return fd;
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)
141 t_errno= errno;
142 close(fd);
143 errno= t_errno;
144 return -1;
146 return fd;
149 static int _raw_socket(int type, int protocol)
151 int r, fd, t_errno, flags = O_RDWR;
152 struct sockaddr_in sin;
153 nwio_ipopt_t ipopt;
154 int result;
156 if (protocol != IPPROTO_ICMP && protocol != IPPROTO_UDP && protocol != 0)
158 #if DEBUG
159 fprintf(stderr, "socket(icmp): bad protocol %d\n", protocol);
160 #endif
161 errno= EPROTONOSUPPORT;
162 return -1;
164 _socket_flags(type, &flags);
165 fd= open(IP_DEVICE, flags);
166 if (fd == -1)
167 return fd;
169 memset(&ipopt, 0, sizeof(ipopt));
171 ipopt.nwio_flags= NWIO_COPY;
173 if(protocol) {
174 ipopt.nwio_flags |= NWIO_PROTOSPEC;
175 ipopt.nwio_proto = protocol;
178 result = ioctl (fd, NWIOSIPOPT, &ipopt);
179 if (result<0) {
180 close(fd);
181 return -1;
184 result = ioctl (fd, NWIOGIPOPT, &ipopt);
185 if (result<0) {
186 close(fd);
187 return -1;
190 return fd;
193 static int _uds_socket(int type, int protocol)
195 int fd, r, flags = O_RDWR, sock_type;
196 if (protocol != 0)
198 #if DEBUG
199 fprintf(stderr, "socket(uds): bad protocol %d\n", protocol);
200 #endif
201 errno= EPROTONOSUPPORT;
202 return -1;
205 _socket_flags(type, &flags);
206 fd= open(UDS_DEVICE, flags);
207 if (fd == -1) {
208 return fd;
211 /* set the type for the socket via ioctl (SOCK_DGRAM,
212 * SOCK_STREAM, SOCK_SEQPACKET, etc)
214 sock_type = type & ~SOCK_FLAGS_MASK;
215 r= ioctl(fd, NWIOSUDSTYPE, &sock_type);
216 if (r == -1) {
217 int ioctl_errno;
219 /* if that failed rollback socket creation */
220 ioctl_errno= errno;
221 close(fd);
223 /* return the error thrown by the call to ioctl */
224 errno= ioctl_errno;
225 return -1;
228 return fd;