5 #include <minix/config.h>
13 #include <sys/ioctl.h>
14 #include <sys/socket.h>
15 #include <sys/types.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>
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.
40 __connect(int fd
, const struct sockaddr
* address
, socklen_t address_len
)
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
)
56 nwio_tcpconf_t tcpconf
;
59 r
= __connect(sock
, address
, address_len
);
60 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
63 r
= ioctl(sock
, NWIOGTCPCONF
, &tcpconf
);
64 if (r
!= -1 || errno
!= ENOTTY
)
68 /* Bad file descriptor */
71 return _tcp_connect(sock
, address
, address_len
, &tcpconf
);
74 r
= ioctl(sock
, NWIOGUDPOPT
, &udpopt
);
75 if (r
!= -1 || errno
!= ENOTTY
)
79 /* Bad file descriptor */
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
))
90 /* Bad file descriptor */
101 static int _tcp_connect(int sock
, const struct sockaddr
*address
,
102 socklen_t address_len
, nwio_tcpconf_t
*tcpconfp
)
105 struct sockaddr_in
*sinp
;
106 nwio_tcpconf_t tcpconf
;
109 if (address_len
!= sizeof(*sinp
))
114 sinp
= (struct sockaddr_in
*) __UNCONST(address
);
115 if (sinp
->sin_family
!= AF_INET
)
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
131 if (errno
!= EISCONN
)
135 tcpcl
.nwtcl_flags
= TCF_DEFAULT
;
137 r
= fcntl(sock
, F_GETFL
);
141 tcpcl
.nwtcl_flags
|= TCF_ASYNCH
;
143 r
= ioctl(sock
, NWIOTCPCONN
, &tcpcl
);
147 static int _udp_connect(int sock
, const struct sockaddr
*address
,
148 socklen_t address_len
, nwio_udpopt_t
*udpoptp
)
151 struct sockaddr_in
*sinp
;
152 nwio_udpopt_t udpopt
;
156 /* Unset remote address */
157 udpopt
.nwuo_flags
= NWUO_RP_ANY
| NWUO_RA_ANY
| NWUO_RWDATALL
;
159 r
= ioctl(sock
, NWIOSUDPOPT
, &udpopt
);
163 if (address_len
!= sizeof(*sinp
))
168 sinp
= (struct sockaddr_in
*) __UNCONST(address
);
169 if (sinp
->sin_family
!= AF_INET
)
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
);
184 static int _uds_connect(int sock
, const struct sockaddr
*address
,
185 socklen_t address_len
)
188 if (address
== NULL
) {
193 /* perform the connect */
194 return ioctl(sock
, NWIOSUDSCONN
, (void *) __UNCONST(address
));