xref: /minix3/minix/lib/libc/sys/connect.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include <sys/cdefs.h>
2*433d6423SLionel Sambuc #include "namespace.h"
3*433d6423SLionel Sambuc #include <minix/config.h>
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc #include <errno.h>
6*433d6423SLionel Sambuc #include <fcntl.h>
7*433d6423SLionel Sambuc #include <stdio.h>
8*433d6423SLionel Sambuc #include <stdlib.h>
9*433d6423SLionel Sambuc #include <unistd.h>
10*433d6423SLionel Sambuc #include <string.h>
11*433d6423SLionel Sambuc #include <sys/ioctl.h>
12*433d6423SLionel Sambuc #include <sys/socket.h>
13*433d6423SLionel Sambuc #include <sys/types.h>
14*433d6423SLionel Sambuc #include <sys/stat.h>
15*433d6423SLionel Sambuc #include <netinet/in.h>
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc #include <net/gen/in.h>
18*433d6423SLionel Sambuc #include <net/gen/tcp.h>
19*433d6423SLionel Sambuc #include <net/gen/tcp_io.h>
20*433d6423SLionel Sambuc #include <net/gen/udp.h>
21*433d6423SLionel Sambuc #include <net/gen/udp_io.h>
22*433d6423SLionel Sambuc 
23*433d6423SLionel Sambuc #include <minix/const.h>
24*433d6423SLionel Sambuc 
25*433d6423SLionel Sambuc #define DEBUG 0
26*433d6423SLionel Sambuc 
27*433d6423SLionel Sambuc static int _tcp_connect(int sock, const struct sockaddr *address,
28*433d6423SLionel Sambuc 	socklen_t address_len, nwio_tcpconf_t *tcpconfp);
29*433d6423SLionel Sambuc static int _udp_connect(int sock, const struct sockaddr *address,
30*433d6423SLionel Sambuc 	socklen_t address_len, nwio_udpopt_t *udpoptp);
31*433d6423SLionel Sambuc static int _uds_connect(int sock, const struct sockaddr *address,
32*433d6423SLionel Sambuc 	socklen_t address_len);
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc int connect(int sock, const struct sockaddr *address,
35*433d6423SLionel Sambuc 	socklen_t address_len)
36*433d6423SLionel Sambuc {
37*433d6423SLionel Sambuc 	int r;
38*433d6423SLionel Sambuc 	nwio_tcpconf_t tcpconf;
39*433d6423SLionel Sambuc 	nwio_udpopt_t udpopt;
40*433d6423SLionel Sambuc 
41*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
42*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
43*433d6423SLionel Sambuc 	{
44*433d6423SLionel Sambuc 		if (r == -1)
45*433d6423SLionel Sambuc 		{
46*433d6423SLionel Sambuc 			/* Bad file descriptor */
47*433d6423SLionel Sambuc 			return -1;
48*433d6423SLionel Sambuc 		}
49*433d6423SLionel Sambuc 		return _tcp_connect(sock, address, address_len, &tcpconf);
50*433d6423SLionel Sambuc 	}
51*433d6423SLionel Sambuc 
52*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGUDPOPT, &udpopt);
53*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
54*433d6423SLionel Sambuc 	{
55*433d6423SLionel Sambuc 		if (r == -1)
56*433d6423SLionel Sambuc 		{
57*433d6423SLionel Sambuc 			/* Bad file descriptor */
58*433d6423SLionel Sambuc 			return -1;
59*433d6423SLionel Sambuc 		}
60*433d6423SLionel Sambuc 		return _udp_connect(sock, address, address_len, &udpopt);
61*433d6423SLionel Sambuc 	}
62*433d6423SLionel Sambuc 
63*433d6423SLionel Sambuc 	r= _uds_connect(sock, address, address_len);
64*433d6423SLionel Sambuc 	if (r != -1 || (errno != ENOTTY && errno != EAFNOSUPPORT))
65*433d6423SLionel Sambuc 	{
66*433d6423SLionel Sambuc 		if (r == -1)
67*433d6423SLionel Sambuc 		{
68*433d6423SLionel Sambuc 			/* Bad file descriptor */
69*433d6423SLionel Sambuc 			return -1;
70*433d6423SLionel Sambuc 		}
71*433d6423SLionel Sambuc 
72*433d6423SLionel Sambuc 		return r;
73*433d6423SLionel Sambuc 	}
74*433d6423SLionel Sambuc 
75*433d6423SLionel Sambuc #if DEBUG
76*433d6423SLionel Sambuc 	fprintf(stderr, "connect: not implemented for fd %d\n", sock);
77*433d6423SLionel Sambuc #endif
78*433d6423SLionel Sambuc 	errno= ENOSYS;
79*433d6423SLionel Sambuc 	return -1;
80*433d6423SLionel Sambuc }
81*433d6423SLionel Sambuc 
82*433d6423SLionel Sambuc static int _tcp_connect(int sock, const struct sockaddr *address,
83*433d6423SLionel Sambuc 	socklen_t address_len, nwio_tcpconf_t *tcpconfp)
84*433d6423SLionel Sambuc {
85*433d6423SLionel Sambuc 	int r;
86*433d6423SLionel Sambuc 	struct sockaddr_in *sinp;
87*433d6423SLionel Sambuc 	nwio_tcpconf_t tcpconf;
88*433d6423SLionel Sambuc 	nwio_tcpcl_t tcpcl;
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc 	if (address_len != sizeof(*sinp))
91*433d6423SLionel Sambuc 	{
92*433d6423SLionel Sambuc 		errno= EINVAL;
93*433d6423SLionel Sambuc 		return -1;
94*433d6423SLionel Sambuc 	}
95*433d6423SLionel Sambuc 	sinp= (struct sockaddr_in *) __UNCONST(address);
96*433d6423SLionel Sambuc 	if (sinp->sin_family != AF_INET)
97*433d6423SLionel Sambuc 	{
98*433d6423SLionel Sambuc 		errno= EINVAL;
99*433d6423SLionel Sambuc 		return -1;
100*433d6423SLionel Sambuc 	}
101*433d6423SLionel Sambuc 	tcpconf.nwtc_flags= NWTC_SET_RA | NWTC_SET_RP;
102*433d6423SLionel Sambuc 	if ((tcpconfp->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
103*433d6423SLionel Sambuc 		tcpconf.nwtc_flags |= NWTC_LP_SEL;
104*433d6423SLionel Sambuc 	tcpconf.nwtc_remaddr= sinp->sin_addr.s_addr;
105*433d6423SLionel Sambuc 	tcpconf.nwtc_remport= sinp->sin_port;
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc 	if (ioctl(sock, NWIOSTCPCONF, &tcpconf) == -1)
108*433d6423SLionel Sambuc         {
109*433d6423SLionel Sambuc 		/* Ignore EISCONN error. The NWIOTCPCONN ioctl will get the
110*433d6423SLionel Sambuc 		 * right error.
111*433d6423SLionel Sambuc 		 */
112*433d6423SLionel Sambuc 		if (errno != EISCONN)
113*433d6423SLionel Sambuc 			return -1;
114*433d6423SLionel Sambuc 	}
115*433d6423SLionel Sambuc 
116*433d6423SLionel Sambuc 	tcpcl.nwtcl_flags= TCF_DEFAULT;
117*433d6423SLionel Sambuc 
118*433d6423SLionel Sambuc 	r= fcntl(sock, F_GETFL);
119*433d6423SLionel Sambuc 	if (r == 1)
120*433d6423SLionel Sambuc 		return -1;
121*433d6423SLionel Sambuc 	if (r & O_NONBLOCK)
122*433d6423SLionel Sambuc 		tcpcl.nwtcl_flags |= TCF_ASYNCH;
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOTCPCONN, &tcpcl);
125*433d6423SLionel Sambuc 	return r;
126*433d6423SLionel Sambuc }
127*433d6423SLionel Sambuc 
128*433d6423SLionel Sambuc static int _udp_connect(int sock, const struct sockaddr *address,
129*433d6423SLionel Sambuc 	socklen_t address_len, nwio_udpopt_t *udpoptp)
130*433d6423SLionel Sambuc {
131*433d6423SLionel Sambuc 	int r;
132*433d6423SLionel Sambuc 	struct sockaddr_in *sinp;
133*433d6423SLionel Sambuc 	nwio_udpopt_t udpopt;
134*433d6423SLionel Sambuc 
135*433d6423SLionel Sambuc 	if (address == NULL)
136*433d6423SLionel Sambuc 	{
137*433d6423SLionel Sambuc 		/* Unset remote address */
138*433d6423SLionel Sambuc 		udpopt.nwuo_flags= NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL;
139*433d6423SLionel Sambuc 
140*433d6423SLionel Sambuc 		r= ioctl(sock, NWIOSUDPOPT, &udpopt);
141*433d6423SLionel Sambuc 		return r;
142*433d6423SLionel Sambuc 	}
143*433d6423SLionel Sambuc 
144*433d6423SLionel Sambuc 	if (address_len != sizeof(*sinp))
145*433d6423SLionel Sambuc 	{
146*433d6423SLionel Sambuc 		errno= EINVAL;
147*433d6423SLionel Sambuc 		return -1;
148*433d6423SLionel Sambuc 	}
149*433d6423SLionel Sambuc 	sinp= (struct sockaddr_in *) __UNCONST(address);
150*433d6423SLionel Sambuc 	if (sinp->sin_family != AF_INET)
151*433d6423SLionel Sambuc 	{
152*433d6423SLionel Sambuc 		errno= EINVAL;
153*433d6423SLionel Sambuc 		return -1;
154*433d6423SLionel Sambuc 	}
155*433d6423SLionel Sambuc 	udpopt.nwuo_flags= NWUO_RP_SET | NWUO_RA_SET | NWUO_RWDATONLY;
156*433d6423SLionel Sambuc 	if ((udpoptp->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY)
157*433d6423SLionel Sambuc 		udpopt.nwuo_flags |= NWUO_LP_SEL;
158*433d6423SLionel Sambuc 	udpopt.nwuo_remaddr= sinp->sin_addr.s_addr;
159*433d6423SLionel Sambuc 	udpopt.nwuo_remport= sinp->sin_port;
160*433d6423SLionel Sambuc 
161*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOSUDPOPT, &udpopt);
162*433d6423SLionel Sambuc 	return r;
163*433d6423SLionel Sambuc }
164*433d6423SLionel Sambuc 
165*433d6423SLionel Sambuc static int _uds_connect(int sock, const struct sockaddr *address,
166*433d6423SLionel Sambuc 	socklen_t address_len)
167*433d6423SLionel Sambuc {
168*433d6423SLionel Sambuc 
169*433d6423SLionel Sambuc 	if (address == NULL) {
170*433d6423SLionel Sambuc 		errno = EFAULT;
171*433d6423SLionel Sambuc 		return -1;
172*433d6423SLionel Sambuc 	}
173*433d6423SLionel Sambuc 
174*433d6423SLionel Sambuc 	/* perform the connect */
175*433d6423SLionel Sambuc 	return ioctl(sock, NWIOSUDSCONN, (void *) __UNCONST(address));
176*433d6423SLionel Sambuc }
177