etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / connect.c
blob9d542beb47efc8a09658c8b1931f6598b0ea9731
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <minix/config.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/ioctl.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <netinet/in.h>
19 #include <net/gen/in.h>
20 #include <net/gen/tcp.h>
21 #include <net/gen/tcp_io.h>
22 #include <net/gen/udp.h>
23 #include <net/gen/udp_io.h>
25 #include <minix/const.h>
27 #define DEBUG 0
29 static int _tcp_connect(int sock, const struct sockaddr *address,
30 socklen_t address_len, nwio_tcpconf_t *tcpconfp);
31 static int _udp_connect(int sock, const struct sockaddr *address,
32 socklen_t address_len, nwio_udpopt_t *udpoptp);
33 static int _uds_connect(int sock, const struct sockaddr *address,
34 socklen_t address_len);
37 * Connect a socket to a remote address.
39 static int
40 __connect(int fd, const struct sockaddr * address, socklen_t address_len)
42 message m;
44 memset(&m, 0, sizeof(m));
45 m.m_lc_vfs_sockaddr.fd = fd;
46 m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
47 m.m_lc_vfs_sockaddr.addr_len = address_len;
49 return _syscall(VFS_PROC_NR, VFS_CONNECT, &m);
52 int connect(int sock, const struct sockaddr *address,
53 socklen_t address_len)
55 int r;
56 nwio_tcpconf_t tcpconf;
57 nwio_udpopt_t udpopt;
59 r = __connect(sock, address, address_len);
60 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
61 return r;
63 r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
64 if (r != -1 || errno != ENOTTY)
66 if (r == -1)
68 /* Bad file descriptor */
69 return -1;
71 return _tcp_connect(sock, address, address_len, &tcpconf);
74 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
75 if (r != -1 || errno != ENOTTY)
77 if (r == -1)
79 /* Bad file descriptor */
80 return -1;
82 return _udp_connect(sock, address, address_len, &udpopt);
85 r= _uds_connect(sock, address, address_len);
86 if (r != -1 || (errno != ENOTTY && errno != EAFNOSUPPORT))
88 if (r == -1)
90 /* Bad file descriptor */
91 return -1;
94 return r;
97 errno = ENOTSOCK;
98 return -1;
101 static int _tcp_connect(int sock, const struct sockaddr *address,
102 socklen_t address_len, nwio_tcpconf_t *tcpconfp)
104 int r;
105 struct sockaddr_in *sinp;
106 nwio_tcpconf_t tcpconf;
107 nwio_tcpcl_t tcpcl;
109 if (address_len != sizeof(*sinp))
111 errno= EINVAL;
112 return -1;
114 sinp= (struct sockaddr_in *) __UNCONST(address);
115 if (sinp->sin_family != AF_INET)
117 errno= EINVAL;
118 return -1;
120 tcpconf.nwtc_flags= NWTC_SET_RA | NWTC_SET_RP;
121 if ((tcpconfp->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
122 tcpconf.nwtc_flags |= NWTC_LP_SEL;
123 tcpconf.nwtc_remaddr= sinp->sin_addr.s_addr;
124 tcpconf.nwtc_remport= sinp->sin_port;
126 if (ioctl(sock, NWIOSTCPCONF, &tcpconf) == -1)
128 /* Ignore EISCONN error. The NWIOTCPCONN ioctl will get the
129 * right error.
131 if (errno != EISCONN)
132 return -1;
135 tcpcl.nwtcl_flags= TCF_DEFAULT;
137 r= fcntl(sock, F_GETFL);
138 if (r == 1)
139 return -1;
140 if (r & O_NONBLOCK)
141 tcpcl.nwtcl_flags |= TCF_ASYNCH;
143 r= ioctl(sock, NWIOTCPCONN, &tcpcl);
144 return r;
147 static int _udp_connect(int sock, const struct sockaddr *address,
148 socklen_t address_len, nwio_udpopt_t *udpoptp)
150 int r;
151 struct sockaddr_in *sinp;
152 nwio_udpopt_t udpopt;
154 if (address == NULL)
156 /* Unset remote address */
157 udpopt.nwuo_flags= NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL;
159 r= ioctl(sock, NWIOSUDPOPT, &udpopt);
160 return r;
163 if (address_len != sizeof(*sinp))
165 errno= EINVAL;
166 return -1;
168 sinp= (struct sockaddr_in *) __UNCONST(address);
169 if (sinp->sin_family != AF_INET)
171 errno= EINVAL;
172 return -1;
174 udpopt.nwuo_flags= NWUO_RP_SET | NWUO_RA_SET | NWUO_RWDATONLY;
175 if ((udpoptp->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY)
176 udpopt.nwuo_flags |= NWUO_LP_SEL;
177 udpopt.nwuo_remaddr= sinp->sin_addr.s_addr;
178 udpopt.nwuo_remport= sinp->sin_port;
180 r= ioctl(sock, NWIOSUDPOPT, &udpopt);
181 return r;
184 static int _uds_connect(int sock, const struct sockaddr *address,
185 socklen_t address_len)
188 if (address == NULL) {
189 errno = EFAULT;
190 return -1;
193 /* perform the connect */
194 return ioctl(sock, NWIOSUDSCONN, (void *) __UNCONST(address));