
Commit git-c38dbb9 inadvertently broke local MINIX3-on-MINIX3 builds, since its libc changes relied on VFS being upgraded already as well. As a result, after installing the new libc, networking ceased to work, leading to curl(1) failing later on in the build process. This patch introduces transitional code that is necessary for the build process to complete, after which it is obsolete again. Change-Id: I93bf29c01d228e3d7efc7b01befeff682954f54d
196 lines
4.1 KiB
C
196 lines
4.1 KiB
C
#include <sys/cdefs.h>
|
|
#include "namespace.h"
|
|
#include <lib.h>
|
|
|
|
#include <minix/config.h>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <net/gen/in.h>
|
|
#include <net/gen/tcp.h>
|
|
#include <net/gen/tcp_io.h>
|
|
#include <net/gen/udp.h>
|
|
#include <net/gen/udp_io.h>
|
|
|
|
#include <minix/const.h>
|
|
|
|
#define DEBUG 0
|
|
|
|
static int _tcp_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len, nwio_tcpconf_t *tcpconfp);
|
|
static int _udp_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len, nwio_udpopt_t *udpoptp);
|
|
static int _uds_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len);
|
|
|
|
/*
|
|
* Connect a socket to a remote address.
|
|
*/
|
|
static int
|
|
__connect(int fd, const struct sockaddr * address, socklen_t address_len)
|
|
{
|
|
message m;
|
|
|
|
memset(&m, 0, sizeof(m));
|
|
m.m_lc_vfs_sockaddr.fd = fd;
|
|
m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
|
|
m.m_lc_vfs_sockaddr.addr_len = address_len;
|
|
|
|
return _syscall(VFS_PROC_NR, VFS_CONNECT, &m);
|
|
}
|
|
|
|
int connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len)
|
|
{
|
|
int r;
|
|
nwio_tcpconf_t tcpconf;
|
|
nwio_udpopt_t udpopt;
|
|
|
|
r = __connect(sock, address, address_len);
|
|
if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
|
|
return r;
|
|
|
|
r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
|
|
if (r != -1 || errno != ENOTTY)
|
|
{
|
|
if (r == -1)
|
|
{
|
|
/* Bad file descriptor */
|
|
return -1;
|
|
}
|
|
return _tcp_connect(sock, address, address_len, &tcpconf);
|
|
}
|
|
|
|
r= ioctl(sock, NWIOGUDPOPT, &udpopt);
|
|
if (r != -1 || errno != ENOTTY)
|
|
{
|
|
if (r == -1)
|
|
{
|
|
/* Bad file descriptor */
|
|
return -1;
|
|
}
|
|
return _udp_connect(sock, address, address_len, &udpopt);
|
|
}
|
|
|
|
r= _uds_connect(sock, address, address_len);
|
|
if (r != -1 || (errno != ENOTTY && errno != EAFNOSUPPORT))
|
|
{
|
|
if (r == -1)
|
|
{
|
|
/* Bad file descriptor */
|
|
return -1;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
errno = ENOTSOCK;
|
|
return -1;
|
|
}
|
|
|
|
static int _tcp_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len, nwio_tcpconf_t *tcpconfp)
|
|
{
|
|
int r;
|
|
struct sockaddr_in *sinp;
|
|
nwio_tcpconf_t tcpconf;
|
|
nwio_tcpcl_t tcpcl;
|
|
|
|
if (address_len != sizeof(*sinp))
|
|
{
|
|
errno= EINVAL;
|
|
return -1;
|
|
}
|
|
sinp= (struct sockaddr_in *) __UNCONST(address);
|
|
if (sinp->sin_family != AF_INET)
|
|
{
|
|
errno= EINVAL;
|
|
return -1;
|
|
}
|
|
tcpconf.nwtc_flags= NWTC_SET_RA | NWTC_SET_RP;
|
|
if ((tcpconfp->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
|
|
tcpconf.nwtc_flags |= NWTC_LP_SEL;
|
|
tcpconf.nwtc_remaddr= sinp->sin_addr.s_addr;
|
|
tcpconf.nwtc_remport= sinp->sin_port;
|
|
|
|
if (ioctl(sock, NWIOSTCPCONF, &tcpconf) == -1)
|
|
{
|
|
/* Ignore EISCONN error. The NWIOTCPCONN ioctl will get the
|
|
* right error.
|
|
*/
|
|
if (errno != EISCONN)
|
|
return -1;
|
|
}
|
|
|
|
tcpcl.nwtcl_flags= TCF_DEFAULT;
|
|
|
|
r= fcntl(sock, F_GETFL);
|
|
if (r == 1)
|
|
return -1;
|
|
if (r & O_NONBLOCK)
|
|
tcpcl.nwtcl_flags |= TCF_ASYNCH;
|
|
|
|
r= ioctl(sock, NWIOTCPCONN, &tcpcl);
|
|
return r;
|
|
}
|
|
|
|
static int _udp_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len, nwio_udpopt_t *udpoptp)
|
|
{
|
|
int r;
|
|
struct sockaddr_in *sinp;
|
|
nwio_udpopt_t udpopt;
|
|
|
|
if (address == NULL)
|
|
{
|
|
/* Unset remote address */
|
|
udpopt.nwuo_flags= NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL;
|
|
|
|
r= ioctl(sock, NWIOSUDPOPT, &udpopt);
|
|
return r;
|
|
}
|
|
|
|
if (address_len != sizeof(*sinp))
|
|
{
|
|
errno= EINVAL;
|
|
return -1;
|
|
}
|
|
sinp= (struct sockaddr_in *) __UNCONST(address);
|
|
if (sinp->sin_family != AF_INET)
|
|
{
|
|
errno= EINVAL;
|
|
return -1;
|
|
}
|
|
udpopt.nwuo_flags= NWUO_RP_SET | NWUO_RA_SET | NWUO_RWDATONLY;
|
|
if ((udpoptp->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY)
|
|
udpopt.nwuo_flags |= NWUO_LP_SEL;
|
|
udpopt.nwuo_remaddr= sinp->sin_addr.s_addr;
|
|
udpopt.nwuo_remport= sinp->sin_port;
|
|
|
|
r= ioctl(sock, NWIOSUDPOPT, &udpopt);
|
|
return r;
|
|
}
|
|
|
|
static int _uds_connect(int sock, const struct sockaddr *address,
|
|
socklen_t address_len)
|
|
{
|
|
|
|
if (address == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
/* perform the connect */
|
|
return ioctl(sock, NWIOSUDSCONN, (void *) __UNCONST(address));
|
|
}
|