2000-02-18 03:38:33 +08:00
|
|
|
|
/* net.cc: network-related routines.
|
|
|
|
|
|
2002-01-02 00:25:31 +08:00
|
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
|
details. */
|
|
|
|
|
|
|
|
|
|
/* #define DEBUG_NEST_ON 1 */
|
|
|
|
|
|
|
|
|
|
#define __INSIDE_CYGWIN_NET__
|
|
|
|
|
|
2000-08-03 00:28:18 +08:00
|
|
|
|
#include "winsup.h"
|
2000-02-18 03:38:33 +08:00
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <sys/un.h>
|
2001-02-08 06:50:50 +08:00
|
|
|
|
#include <iphlpapi.h>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-04-09 15:21:32 +08:00
|
|
|
|
#include <stdlib.h>
|
2000-07-30 00:24:59 +08:00
|
|
|
|
#include <unistd.h>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
#include <netdb.h>
|
|
|
|
|
#include <fcntl.h>
|
2001-03-21 03:50:28 +08:00
|
|
|
|
#define USE_SYS_TYPES_FD_SET
|
2000-10-26 18:13:41 +08:00
|
|
|
|
#include <winsock2.h>
|
2000-08-22 13:10:20 +08:00
|
|
|
|
#include "cygerrno.h"
|
2001-07-27 03:22:24 +08:00
|
|
|
|
#include "security.h"
|
2000-08-22 13:10:20 +08:00
|
|
|
|
#include "fhandler.h"
|
|
|
|
|
#include "path.h"
|
2000-08-12 13:35:42 +08:00
|
|
|
|
#include "dtable.h"
|
2001-04-19 05:10:15 +08:00
|
|
|
|
#include "cygheap.h"
|
2000-08-22 13:10:20 +08:00
|
|
|
|
#include "sync.h"
|
|
|
|
|
#include "sigproc.h"
|
2000-08-12 13:35:42 +08:00
|
|
|
|
#include "pinfo.h"
|
2000-09-08 10:56:55 +08:00
|
|
|
|
#include "registry.h"
|
2002-01-20 00:11:00 +08:00
|
|
|
|
#include <sys/uio.h>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" {
|
2000-02-18 03:38:33 +08:00
|
|
|
|
int h_errno;
|
|
|
|
|
|
|
|
|
|
int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
|
|
|
|
|
char *remuser, char *cmd, SOCKET *fd2p);
|
|
|
|
|
int __stdcall rexec (char **ahost, unsigned short inport, char *locuser,
|
|
|
|
|
char *password, char *cmd, SOCKET *fd2p);
|
|
|
|
|
int __stdcall rresvport (int *);
|
|
|
|
|
int sscanf (const char *, const char *, ...);
|
|
|
|
|
} /* End of "C" section */
|
|
|
|
|
|
2001-05-15 16:15:54 +08:00
|
|
|
|
class wsock_event
|
|
|
|
|
{
|
|
|
|
|
WSAEVENT event;
|
|
|
|
|
WSAOVERLAPPED ovr;
|
|
|
|
|
public:
|
|
|
|
|
wsock_event () : event (NULL) {};
|
2001-06-04 06:18:19 +08:00
|
|
|
|
~wsock_event ()
|
|
|
|
|
{
|
|
|
|
|
if (event)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
WSACloseEvent (event);
|
2001-06-04 06:18:19 +08:00
|
|
|
|
event = NULL;
|
|
|
|
|
};
|
2001-05-15 16:15:54 +08:00
|
|
|
|
|
|
|
|
|
LPWSAOVERLAPPED prepare ();
|
|
|
|
|
int wait (int socket, LPDWORD flags);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LPWSAOVERLAPPED
|
|
|
|
|
wsock_event::prepare ()
|
|
|
|
|
{
|
|
|
|
|
LPWSAOVERLAPPED ret = NULL;
|
|
|
|
|
|
|
|
|
|
SetLastError (0);
|
2001-08-14 15:41:45 +08:00
|
|
|
|
if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
|
|
|
|
memset (&ovr, 0, sizeof ovr);
|
|
|
|
|
ovr.hEvent = event;
|
|
|
|
|
ret = &ovr;
|
|
|
|
|
}
|
|
|
|
|
else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
|
|
|
|
|
WSASetLastError (0);
|
2001-06-26 22:47:48 +08:00
|
|
|
|
|
2001-05-15 16:15:54 +08:00
|
|
|
|
debug_printf ("%d = wsock_event::prepare ()", ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
wsock_event::wait (int socket, LPDWORD flags)
|
|
|
|
|
{
|
|
|
|
|
int ret = -1;
|
|
|
|
|
WSAEVENT ev[2] = { event, signal_arrived };
|
|
|
|
|
|
|
|
|
|
switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE))
|
|
|
|
|
{
|
|
|
|
|
case WSA_WAIT_EVENT_0:
|
|
|
|
|
DWORD len;
|
|
|
|
|
if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags))
|
|
|
|
|
ret = (int) len;
|
|
|
|
|
break;
|
|
|
|
|
case WSA_WAIT_EVENT_0 + 1:
|
2001-05-18 16:33:33 +08:00
|
|
|
|
if (!CancelIo ((HANDLE)socket))
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("CancelIo() %E, fallback to blocking io");
|
|
|
|
|
WSAGetOverlappedResult(socket, &ovr, &len, TRUE, flags);
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2001-05-18 16:33:33 +08:00
|
|
|
|
else
|
2001-06-26 22:47:48 +08:00
|
|
|
|
WSASetLastError (WSAEINTR);
|
2001-05-15 16:15:54 +08:00
|
|
|
|
break;
|
|
|
|
|
case WSA_WAIT_FAILED:
|
|
|
|
|
break;
|
|
|
|
|
default: /* Should be impossible. *LOL* */
|
|
|
|
|
WSASetLastError (WSAEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WSACloseEvent (event);
|
|
|
|
|
event = NULL;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-16 13:07:51 +08:00
|
|
|
|
WSADATA wsadata;
|
2000-10-26 18:13:41 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
/* Cygwin internal */
|
|
|
|
|
static fhandler_socket *
|
|
|
|
|
get (int fd)
|
|
|
|
|
{
|
|
|
|
|
cygheap_fdget cfd (fd);
|
|
|
|
|
if (cfd < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return cfd->is_socket ();
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* Cygwin internal */
|
2000-10-07 03:11:14 +08:00
|
|
|
|
static SOCKET __stdcall
|
|
|
|
|
set_socket_inheritance (SOCKET sock)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-10-14 12:14:24 +08:00
|
|
|
|
SOCKET osock = sock;
|
|
|
|
|
if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock,
|
|
|
|
|
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
|
|
|
|
system_printf ("DuplicateHandle failed %E");
|
2000-10-07 03:11:14 +08:00
|
|
|
|
else
|
2001-10-14 12:14:24 +08:00
|
|
|
|
debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* htonl: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned long int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
htonl (unsigned long int x)
|
|
|
|
|
{
|
|
|
|
|
return ((((x & 0x000000ffU) << 24) |
|
|
|
|
|
((x & 0x0000ff00U) << 8) |
|
|
|
|
|
((x & 0x00ff0000U) >> 8) |
|
|
|
|
|
((x & 0xff000000U) >> 24)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ntohl: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned long int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
ntohl (unsigned long int x)
|
|
|
|
|
{
|
|
|
|
|
return htonl (x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* htons: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned short
|
2000-02-18 03:38:33 +08:00
|
|
|
|
htons (unsigned short x)
|
|
|
|
|
{
|
|
|
|
|
return ((((x & 0x000000ffU) << 8) |
|
|
|
|
|
((x & 0x0000ff00U) >> 8)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ntohs: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned short
|
2000-02-18 03:38:33 +08:00
|
|
|
|
ntohs (unsigned short x)
|
|
|
|
|
{
|
|
|
|
|
return htons (x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cygwin internal */
|
|
|
|
|
static void
|
|
|
|
|
dump_protoent (struct protoent *p)
|
|
|
|
|
{
|
|
|
|
|
if (p)
|
|
|
|
|
debug_printf ("protoent %s %x %x", p->p_name, p->p_aliases, p->p_proto);
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-25 18:23:55 +08:00
|
|
|
|
/* exported as inet_ntoa: BSD 4.3 */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" char *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_inet_ntoa (struct in_addr in)
|
|
|
|
|
{
|
2001-08-23 05:51:48 +08:00
|
|
|
|
#ifdef _MT_SAFE
|
|
|
|
|
#define ntoa_buf _reent_winsup ()->_ntoa_buf
|
|
|
|
|
#else
|
|
|
|
|
static char *ntoa_buf = NULL;
|
|
|
|
|
#endif
|
2001-08-22 23:31:59 +08:00
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
char *res = inet_ntoa (in);
|
2001-08-23 05:51:48 +08:00
|
|
|
|
if (ntoa_buf)
|
2001-08-22 23:31:59 +08:00
|
|
|
|
{
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free (ntoa_buf);
|
|
|
|
|
ntoa_buf = NULL;
|
2001-08-22 23:31:59 +08:00
|
|
|
|
}
|
|
|
|
|
if (res)
|
2001-08-23 05:51:48 +08:00
|
|
|
|
ntoa_buf = strdup (res);
|
|
|
|
|
return ntoa_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2000-11-25 18:23:55 +08:00
|
|
|
|
/* exported as inet_addr: BSD 4.3 */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned long
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_inet_addr (const char *cp)
|
|
|
|
|
{
|
2001-11-25 05:10:00 +08:00
|
|
|
|
if (check_null_str_errno (cp))
|
|
|
|
|
return INADDR_NONE;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
unsigned long res = inet_addr (cp);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-25 18:23:55 +08:00
|
|
|
|
/* exported as inet_aton: BSD 4.3
|
|
|
|
|
inet_aton is not exported by wsock32 and ws2_32,
|
|
|
|
|
so it has to be implemented here. */
|
|
|
|
|
extern "C" int
|
|
|
|
|
cygwin_inet_aton (const char *cp, struct in_addr *inp)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2000-11-25 18:23:55 +08:00
|
|
|
|
unsigned long res = inet_addr (cp);
|
|
|
|
|
if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
|
2000-11-30 01:15:00 +08:00
|
|
|
|
return 0;
|
2000-11-25 18:23:55 +08:00
|
|
|
|
if (inp)
|
|
|
|
|
inp->s_addr = res;
|
2000-11-30 01:15:00 +08:00
|
|
|
|
return 1;
|
2000-11-25 18:23:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-24 23:44:11 +08:00
|
|
|
|
/* undocumented in wsock32.dll */
|
2000-04-25 16:50:22 +08:00
|
|
|
|
extern "C" unsigned int WINAPI inet_network (const char *);
|
2000-04-24 23:44:11 +08:00
|
|
|
|
|
2000-10-28 13:41:44 +08:00
|
|
|
|
extern "C" unsigned int
|
2000-04-24 23:44:11 +08:00
|
|
|
|
cygwin_inet_network (const char *cp)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_str_errno (cp))
|
2001-11-25 05:10:00 +08:00
|
|
|
|
return INADDR_NONE;
|
2000-04-24 23:44:11 +08:00
|
|
|
|
unsigned int res = inet_network (cp);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* inet_netof is in the standard BSD sockets library. It is useless
|
|
|
|
|
for modern networks, since it assumes network values which are no
|
|
|
|
|
longer meaningful, but some existing code calls it. */
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" unsigned long
|
2000-02-18 03:38:33 +08:00
|
|
|
|
inet_netof (struct in_addr in)
|
|
|
|
|
{
|
|
|
|
|
unsigned long i, res;
|
|
|
|
|
|
|
|
|
|
i = ntohl (in.s_addr);
|
|
|
|
|
if (IN_CLASSA (i))
|
|
|
|
|
res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
|
|
|
|
|
else if (IN_CLASSB (i))
|
|
|
|
|
res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
|
|
|
|
|
else
|
|
|
|
|
res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* inet_makeaddr is in the standard BSD sockets library. It is
|
|
|
|
|
useless for modern networks, since it assumes network values which
|
|
|
|
|
are no longer meaningful, but some existing code calls it. */
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct in_addr
|
2000-02-18 03:38:33 +08:00
|
|
|
|
inet_makeaddr (int net, int lna)
|
|
|
|
|
{
|
|
|
|
|
unsigned long i;
|
2001-11-25 01:31:15 +08:00
|
|
|
|
struct in_addr in;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
if (net < IN_CLASSA_MAX)
|
|
|
|
|
i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
|
|
|
|
|
else if (net < IN_CLASSB_MAX)
|
|
|
|
|
i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
|
|
|
|
|
else if (net < 0x1000000)
|
|
|
|
|
i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
|
|
|
|
|
else
|
|
|
|
|
i = net | lna;
|
|
|
|
|
|
|
|
|
|
in.s_addr = htonl (i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return in;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct tl
|
|
|
|
|
{
|
|
|
|
|
int w;
|
|
|
|
|
const char *s;
|
|
|
|
|
int e;
|
|
|
|
|
};
|
|
|
|
|
|
2001-09-06 13:17:22 +08:00
|
|
|
|
static NO_COPY struct tl errmap[] =
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-05-17 03:40:45 +08:00
|
|
|
|
{WSAEINTR, "WSAEINTR", EINTR},
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
|
|
|
|
|
{WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
|
|
|
|
|
{WSAEALREADY, "WSAEALREADY", EALREADY},
|
|
|
|
|
{WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
|
|
|
|
|
{WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
|
|
|
|
|
{WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
|
|
|
|
|
{WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
|
|
|
|
|
{WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
|
|
|
|
|
{WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
|
|
|
|
|
{WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
|
|
|
|
|
{WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
|
|
|
|
|
{WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
|
|
|
|
|
{WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
|
|
|
|
|
{WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
|
|
|
|
|
{WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
|
|
|
|
|
{WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
|
|
|
|
|
{WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
|
|
|
|
|
{WSAENETRESET, "WSAENETRESET", ENETRESET},
|
|
|
|
|
{WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
|
|
|
|
|
{WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
|
|
|
|
|
{WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
|
|
|
|
|
{WSAEISCONN, "WSAEISCONN", EISCONN},
|
|
|
|
|
{WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
|
|
|
|
|
{WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
|
|
|
|
|
{WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
|
|
|
|
|
{WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
|
|
|
|
|
{WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
|
|
|
|
|
{WSAELOOP, "WSAELOOP", ELOOP},
|
|
|
|
|
{WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
|
|
|
|
|
{WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
|
|
|
|
|
{WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
|
|
|
|
|
{WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
|
|
|
|
|
{WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
|
|
|
|
|
{WSAEUSERS, "WSAEUSERS", EUSERS},
|
|
|
|
|
{WSAEDQUOT, "WSAEDQUOT", EDQUOT},
|
|
|
|
|
{WSAESTALE, "WSAESTALE", ESTALE},
|
|
|
|
|
{WSAEREMOTE, "WSAEREMOTE", EREMOTE},
|
|
|
|
|
{WSAEINVAL, "WSAEINVAL", EINVAL},
|
|
|
|
|
{WSAEFAULT, "WSAEFAULT", EFAULT},
|
2001-04-24 00:46:30 +08:00
|
|
|
|
{0, "NOERROR", 0},
|
2000-02-23 12:07:13 +08:00
|
|
|
|
{0, NULL, 0}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
};
|
|
|
|
|
|
2001-04-03 10:53:25 +08:00
|
|
|
|
static int
|
|
|
|
|
find_winsock_errno (int why)
|
|
|
|
|
{
|
2001-04-24 00:46:30 +08:00
|
|
|
|
for (int i = 0; errmap[i].s != NULL; ++i)
|
2001-04-03 10:53:25 +08:00
|
|
|
|
if (why == errmap[i].w)
|
|
|
|
|
return errmap[i].e;
|
|
|
|
|
|
|
|
|
|
return EPERM;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* Cygwin internal */
|
|
|
|
|
void
|
2000-10-07 03:11:14 +08:00
|
|
|
|
__set_winsock_errno (const char *fn, int ln)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-04-03 10:53:25 +08:00
|
|
|
|
DWORD werr = WSAGetLastError ();
|
|
|
|
|
int err = find_winsock_errno (werr);
|
|
|
|
|
set_errno (err);
|
|
|
|
|
syscall_printf ("%s:%d - winsock error %d -> errno %d", fn, ln, werr, err);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2000-10-14 16:55:44 +08:00
|
|
|
|
/*
|
|
|
|
|
* Since the member `s' isn't used for debug output we can use it
|
|
|
|
|
* for the error text returned by herror and hstrerror.
|
|
|
|
|
*/
|
2001-10-13 09:35:15 +08:00
|
|
|
|
static NO_COPY struct tl host_errmap[] =
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2000-10-14 16:55:44 +08:00
|
|
|
|
{WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
|
|
|
|
|
{WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
|
|
|
|
|
{WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
|
|
|
|
|
{WSANO_DATA, "No address associated with name", NO_DATA},
|
2000-02-23 12:07:13 +08:00
|
|
|
|
{0, NULL, 0}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Cygwin internal */
|
|
|
|
|
static void
|
|
|
|
|
set_host_errno ()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
int why = WSAGetLastError ();
|
2000-10-14 16:55:44 +08:00
|
|
|
|
for (i = 0; host_errmap[i].w != 0; ++i)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (why == host_errmap[i].w)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (host_errmap[i].w != 0)
|
|
|
|
|
h_errno = host_errmap[i].e;
|
|
|
|
|
else
|
|
|
|
|
h_errno = NETDB_INTERNAL;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-22 23:31:59 +08:00
|
|
|
|
static void
|
|
|
|
|
free_char_list (char **clist)
|
|
|
|
|
{
|
|
|
|
|
if (clist)
|
|
|
|
|
{
|
|
|
|
|
for (char **cl = clist; *cl; ++cl)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
free (*cl);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
free (clist);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char **
|
|
|
|
|
dup_char_list (char **src)
|
|
|
|
|
{
|
|
|
|
|
char **dst;
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
|
|
for (char **cl = src; *cl; ++cl)
|
|
|
|
|
++cnt;
|
|
|
|
|
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
|
|
|
|
|
return NULL;
|
|
|
|
|
while (cnt-- > 0)
|
|
|
|
|
if (!(dst[cnt] = strdup (src[cnt])))
|
|
|
|
|
return NULL;
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-24 14:57:53 +08:00
|
|
|
|
#define free_addr_list(addr_list) free_char_list (addr_list)
|
|
|
|
|
|
|
|
|
|
static char **
|
|
|
|
|
dup_addr_list (char **src, unsigned int size)
|
|
|
|
|
{
|
|
|
|
|
char **dst;
|
|
|
|
|
int cnt = 0;
|
2001-09-08 05:32:07 +08:00
|
|
|
|
|
2001-08-24 14:57:53 +08:00
|
|
|
|
for (char **cl = src; *cl; ++cl)
|
|
|
|
|
++cnt;
|
|
|
|
|
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
|
|
|
|
|
return NULL;
|
|
|
|
|
while (cnt-- > 0)
|
|
|
|
|
{
|
|
|
|
|
if (!(dst[cnt] = (char *) malloc(size)))
|
2001-09-08 05:32:07 +08:00
|
|
|
|
return NULL;
|
2001-08-24 14:57:53 +08:00
|
|
|
|
memcpy(dst[cnt], src[cnt], size);
|
|
|
|
|
}
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-22 23:31:59 +08:00
|
|
|
|
static void
|
|
|
|
|
free_protoent_ptr (struct protoent *&p)
|
|
|
|
|
{
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("protoent: %s", p->p_name);
|
|
|
|
|
|
|
|
|
|
if (p->p_name)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
free (p->p_name);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
free_char_list (p->p_aliases);
|
|
|
|
|
p = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct protoent *
|
|
|
|
|
dup_protoent_ptr (struct protoent *src)
|
|
|
|
|
{
|
|
|
|
|
if (!src)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct protoent *dst = (struct protoent *) calloc (1, sizeof *dst);
|
|
|
|
|
if (!dst)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
debug_printf ("protoent: %s", src->p_name);
|
|
|
|
|
|
|
|
|
|
dst->p_proto = src->p_proto;
|
|
|
|
|
if (src->p_name && !(dst->p_name = strdup (src->p_name)))
|
|
|
|
|
goto out;
|
|
|
|
|
if (src->p_aliases && !(dst->p_aliases = dup_char_list (src->p_aliases)))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
debug_printf ("protoent: copied %s", dst->p_name);
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
free_protoent_ptr (dst);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
#ifdef _MT_SAFE
|
|
|
|
|
#define protoent_buf _reent_winsup ()->_protoent_buf
|
|
|
|
|
#else
|
|
|
|
|
static struct protoent *protoent_buf = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* exported as getprotobyname: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct protoent *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getprotobyname (const char *p)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_str_errno (p))
|
|
|
|
|
return NULL;
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_protoent_ptr (protoent_buf);
|
|
|
|
|
protoent_buf = dup_protoent_ptr (getprotobyname (p));
|
|
|
|
|
if (!protoent_buf)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
dump_protoent (protoent_buf);
|
|
|
|
|
return protoent_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as getprotobynumber: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct protoent *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getprotobynumber (int number)
|
|
|
|
|
{
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_protoent_ptr (protoent_buf);
|
|
|
|
|
protoent_buf = dup_protoent_ptr (getprotobynumber (number));
|
|
|
|
|
if (!protoent_buf)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
dump_protoent (protoent_buf);
|
|
|
|
|
return protoent_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
fhandler_socket *
|
2001-10-16 07:39:33 +08:00
|
|
|
|
fdsock (int& fd, const char *name, SOCKET soc)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-10-14 12:14:24 +08:00
|
|
|
|
if (!winsock2_active)
|
2000-10-26 18:13:41 +08:00
|
|
|
|
soc = set_socket_inheritance (soc);
|
2001-10-14 12:14:24 +08:00
|
|
|
|
else
|
|
|
|
|
debug_printf ("not setting socket inheritance since winsock2_active %d", winsock2_active);
|
2001-04-19 05:10:15 +08:00
|
|
|
|
fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
fh->set_io_handle ((HANDLE) soc);
|
|
|
|
|
fh->set_flags (O_RDWR);
|
2001-10-14 01:23:35 +08:00
|
|
|
|
fh->set_name (name, name);
|
2001-10-14 12:14:24 +08:00
|
|
|
|
debug_printf ("fd %d, name '%s', soc %p", fd, name, soc);
|
2000-10-05 13:57:00 +08:00
|
|
|
|
return fh;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as socket: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_socket (int af, int type, int protocol)
|
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
2001-10-14 12:14:24 +08:00
|
|
|
|
SOCKET soc = 0;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew fd;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
if (fd >= 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
debug_printf ("socket (%d, %d, %d)", af, type, protocol);
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
soc = socket (AF_INET, type, af == AF_LOCAL ? 0 : protocol);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
if (soc == INVALID_SOCKET)
|
2000-09-03 12:16:35 +08:00
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
const char *name;
|
|
|
|
|
if (af == AF_INET)
|
2000-09-03 12:16:35 +08:00
|
|
|
|
name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
|
2000-02-18 03:38:33 +08:00
|
|
|
|
else
|
2001-04-19 05:10:15 +08:00
|
|
|
|
name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
fdsock (fd, name, soc)->set_addr_family (af);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
res = fd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* cygwin internal: map sockaddr into internet domain address */
|
|
|
|
|
|
|
|
|
|
static int get_inet_addr (const struct sockaddr *in, int inlen,
|
2001-04-09 15:21:32 +08:00
|
|
|
|
struct sockaddr_in *out, int *outlen, int* secret = 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
int secret_buf [4];
|
|
|
|
|
int* secret_ptr = (secret ? : secret_buf);
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (in->sa_family == AF_INET)
|
|
|
|
|
{
|
|
|
|
|
*out = * (sockaddr_in *)in;
|
|
|
|
|
*outlen = inlen;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2002-01-05 00:56:53 +08:00
|
|
|
|
else if (in->sa_family == AF_LOCAL)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2000-12-03 05:29:00 +08:00
|
|
|
|
int fd = _open (in->sa_data, O_RDONLY);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (fd == -1)
|
|
|
|
|
return 0;
|
2000-12-03 05:29:00 +08:00
|
|
|
|
|
|
|
|
|
int ret = 0;
|
2001-04-09 15:21:32 +08:00
|
|
|
|
char buf[128];
|
2000-12-03 05:29:00 +08:00
|
|
|
|
memset (buf, 0, sizeof buf);
|
|
|
|
|
if (read (fd, buf, sizeof buf) != -1)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2000-12-03 05:29:00 +08:00
|
|
|
|
sockaddr_in sin;
|
|
|
|
|
sin.sin_family = AF_INET;
|
2001-04-09 15:21:32 +08:00
|
|
|
|
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
|
|
|
|
|
&sin.sin_port,
|
|
|
|
|
secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
|
2000-12-03 05:29:00 +08:00
|
|
|
|
sin.sin_port = htons (sin.sin_port);
|
|
|
|
|
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
|
|
|
*out = sin;
|
|
|
|
|
*outlen = sizeof sin;
|
|
|
|
|
ret = 1;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2000-12-03 05:29:00 +08:00
|
|
|
|
_close (fd);
|
|
|
|
|
return ret;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
set_errno (EAFNOSUPPORT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as sendto: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_sendto (int fd,
|
2001-12-04 04:09:33 +08:00
|
|
|
|
const void *buf,
|
|
|
|
|
int len,
|
|
|
|
|
unsigned int flags,
|
|
|
|
|
const struct sockaddr *to,
|
|
|
|
|
int tolen)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-05-15 16:15:54 +08:00
|
|
|
|
int res;
|
|
|
|
|
wsock_event wsock_evt;
|
|
|
|
|
LPWSAOVERLAPPED ovr;
|
2001-11-24 11:11:39 +08:00
|
|
|
|
fhandler_socket *h = get (fd);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len))
|
|
|
|
|
|| __check_null_invalid_struct_errno (to, tolen)
|
|
|
|
|
|| !h)
|
|
|
|
|
res = -1;
|
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
sockaddr_in sin;
|
|
|
|
|
sigframe thisframe (mainthread);
|
|
|
|
|
|
|
|
|
|
if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
debug_printf ("Fallback to winsock 1 sendto call");
|
|
|
|
|
if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
|
|
|
|
|
(sockaddr *) &sin, tolen)) == SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
2001-05-15 16:15:54 +08:00
|
|
|
|
}
|
2001-11-24 11:11:39 +08:00
|
|
|
|
else
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
WSABUF wsabuf = { len, (char *) buf };
|
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
|
|
|
|
(sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR)
|
|
|
|
|
res = ret;
|
|
|
|
|
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
|
|
|
|
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
|
|
|
|
set_winsock_errno ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
2001-05-15 16:15:54 +08:00
|
|
|
|
|
|
|
|
|
syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as recvfrom: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_recvfrom (int fd,
|
|
|
|
|
char *buf,
|
|
|
|
|
int len,
|
|
|
|
|
int flags,
|
|
|
|
|
struct sockaddr *from,
|
|
|
|
|
int *fromlen)
|
|
|
|
|
{
|
2001-05-15 16:15:54 +08:00
|
|
|
|
int res;
|
|
|
|
|
wsock_event wsock_evt;
|
|
|
|
|
LPWSAOVERLAPPED ovr;
|
2001-11-24 11:11:39 +08:00
|
|
|
|
fhandler_socket *h = get (fd);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (buf, (unsigned) len)
|
|
|
|
|
|| check_null_invalid_struct_errno (fromlen)
|
2001-12-04 04:09:33 +08:00
|
|
|
|
|| (from && __check_null_invalid_struct_errno (from, (unsigned) *fromlen))
|
2001-11-24 11:11:39 +08:00
|
|
|
|
|| !h)
|
|
|
|
|
res = -1;
|
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
|
|
|
|
|
|
|
|
|
if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
debug_printf ("Fallback to winsock 1 recvfrom call");
|
|
|
|
|
if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
|
|
|
|
|
== SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
2001-05-15 16:15:54 +08:00
|
|
|
|
}
|
2001-11-24 11:11:39 +08:00
|
|
|
|
else
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
WSABUF wsabuf = { len, (char *) buf };
|
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
|
|
|
|
from, fromlen, ovr, NULL) != SOCKET_ERROR)
|
|
|
|
|
res = ret;
|
|
|
|
|
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
|
|
|
|
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
|
|
|
|
set_winsock_errno ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2001-05-15 16:15:54 +08:00
|
|
|
|
syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as setsockopt: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_setsockopt (int fd,
|
|
|
|
|
int level,
|
|
|
|
|
int optname,
|
|
|
|
|
const void *optval,
|
|
|
|
|
int optlen)
|
|
|
|
|
{
|
|
|
|
|
fhandler_socket *h = get (fd);
|
|
|
|
|
int res = -1;
|
|
|
|
|
const char *name = "error";
|
|
|
|
|
|
2001-12-04 04:09:33 +08:00
|
|
|
|
if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && h)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
/* For the following debug_printf */
|
|
|
|
|
switch (optname)
|
|
|
|
|
{
|
|
|
|
|
case SO_DEBUG:
|
|
|
|
|
name="SO_DEBUG";
|
|
|
|
|
break;
|
|
|
|
|
case SO_ACCEPTCONN:
|
|
|
|
|
name="SO_ACCEPTCONN";
|
|
|
|
|
break;
|
|
|
|
|
case SO_REUSEADDR:
|
|
|
|
|
name="SO_REUSEADDR";
|
|
|
|
|
break;
|
|
|
|
|
case SO_KEEPALIVE:
|
|
|
|
|
name="SO_KEEPALIVE";
|
|
|
|
|
break;
|
|
|
|
|
case SO_DONTROUTE:
|
|
|
|
|
name="SO_DONTROUTE";
|
|
|
|
|
break;
|
|
|
|
|
case SO_BROADCAST:
|
|
|
|
|
name="SO_BROADCAST";
|
|
|
|
|
break;
|
|
|
|
|
case SO_USELOOPBACK:
|
|
|
|
|
name="SO_USELOOPBACK";
|
|
|
|
|
break;
|
|
|
|
|
case SO_LINGER:
|
|
|
|
|
name="SO_LINGER";
|
|
|
|
|
break;
|
|
|
|
|
case SO_OOBINLINE:
|
|
|
|
|
name="SO_OOBINLINE";
|
|
|
|
|
break;
|
2001-04-03 10:53:25 +08:00
|
|
|
|
case SO_ERROR:
|
|
|
|
|
name="SO_ERROR";
|
|
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = setsockopt (h->get_socket (), level, optname,
|
|
|
|
|
(const char *) optval, optlen);
|
|
|
|
|
|
|
|
|
|
if (optlen == 4)
|
|
|
|
|
syscall_printf ("setsockopt optval=%x", *(long *) optval);
|
|
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %x, %d)",
|
|
|
|
|
res, fd, level, optname, name, optval, optlen);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as getsockopt: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getsockopt (int fd,
|
|
|
|
|
int level,
|
|
|
|
|
int optname,
|
|
|
|
|
void *optval,
|
|
|
|
|
int *optlen)
|
|
|
|
|
{
|
|
|
|
|
fhandler_socket *h = get (fd);
|
|
|
|
|
int res = -1;
|
|
|
|
|
const char *name = "error";
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (!check_null_invalid_struct_errno (optlen)
|
2001-12-05 06:01:03 +08:00
|
|
|
|
&& (!optval || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen))
|
2001-11-24 11:11:39 +08:00
|
|
|
|
&& h)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
/* For the following debug_printf */
|
|
|
|
|
switch (optname)
|
|
|
|
|
{
|
|
|
|
|
case SO_DEBUG:
|
|
|
|
|
name="SO_DEBUG";
|
|
|
|
|
break;
|
|
|
|
|
case SO_ACCEPTCONN:
|
|
|
|
|
name="SO_ACCEPTCONN";
|
|
|
|
|
break;
|
|
|
|
|
case SO_REUSEADDR:
|
|
|
|
|
name="SO_REUSEADDR";
|
|
|
|
|
break;
|
|
|
|
|
case SO_KEEPALIVE:
|
|
|
|
|
name="SO_KEEPALIVE";
|
|
|
|
|
break;
|
|
|
|
|
case SO_DONTROUTE:
|
|
|
|
|
name="SO_DONTROUTE";
|
|
|
|
|
break;
|
|
|
|
|
case SO_BROADCAST:
|
|
|
|
|
name="SO_BROADCAST";
|
|
|
|
|
break;
|
|
|
|
|
case SO_USELOOPBACK:
|
|
|
|
|
name="SO_USELOOPBACK";
|
|
|
|
|
break;
|
|
|
|
|
case SO_LINGER:
|
|
|
|
|
name="SO_LINGER";
|
|
|
|
|
break;
|
|
|
|
|
case SO_OOBINLINE:
|
|
|
|
|
name="SO_OOBINLINE";
|
|
|
|
|
break;
|
2001-04-03 10:53:25 +08:00
|
|
|
|
case SO_ERROR:
|
|
|
|
|
name="SO_ERROR";
|
|
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = getsockopt (h->get_socket (), level, optname,
|
|
|
|
|
(char *) optval, (int *) optlen);
|
|
|
|
|
|
2001-04-03 10:53:25 +08:00
|
|
|
|
if (optname == SO_ERROR)
|
|
|
|
|
{
|
|
|
|
|
int *e = (int *) optval;
|
|
|
|
|
*e = find_winsock_errno (*e);
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %x, %d)",
|
|
|
|
|
res, fd, level, optname, name, optval, optlen);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as connect: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_connect (int fd,
|
|
|
|
|
const struct sockaddr *name,
|
|
|
|
|
int namelen)
|
|
|
|
|
{
|
|
|
|
|
int res;
|
2001-04-09 15:21:32 +08:00
|
|
|
|
BOOL secret_check_failed = FALSE;
|
2001-06-20 14:50:13 +08:00
|
|
|
|
BOOL in_progress = FALSE;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
sockaddr_in sin;
|
2001-04-09 15:21:32 +08:00
|
|
|
|
int secret [4];
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_invalid_read_ptr_errno (name, namelen))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2001-04-09 15:21:32 +08:00
|
|
|
|
if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (!sock)
|
2001-11-24 11:11:39 +08:00
|
|
|
|
res = -1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
|
|
|
|
|
if (res)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2000-11-08 04:01:09 +08:00
|
|
|
|
/* Special handling for connect to return the correct error code
|
2001-09-05 16:16:51 +08:00
|
|
|
|
when called on a non-blocking socket. */
|
|
|
|
|
if (sock->is_nonblocking ())
|
2001-06-20 14:50:13 +08:00
|
|
|
|
{
|
2001-09-05 16:16:51 +08:00
|
|
|
|
DWORD err = WSAGetLastError ();
|
|
|
|
|
if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
|
|
|
|
|
{
|
|
|
|
|
WSASetLastError (WSAEINPROGRESS);
|
|
|
|
|
in_progress = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (err == WSAEINVAL)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
WSASetLastError (WSAEISCONN);
|
2001-06-20 14:50:13 +08:00
|
|
|
|
}
|
2000-11-08 04:01:09 +08:00
|
|
|
|
set_winsock_errno ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (sock->get_addr_family () == AF_LOCAL)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
|
|
|
|
if (!res || in_progress)
|
|
|
|
|
{
|
|
|
|
|
if (!sock->create_secret_event (secret))
|
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
secret_check_failed = TRUE;
|
|
|
|
|
}
|
2001-06-20 14:50:13 +08:00
|
|
|
|
else if (in_progress)
|
|
|
|
|
sock->signal_secret_event ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2001-04-09 15:21:32 +08:00
|
|
|
|
|
2001-06-26 22:47:48 +08:00
|
|
|
|
if (!secret_check_failed && !res)
|
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
if (!sock->check_peer_secret_event (&sin, secret))
|
|
|
|
|
{
|
|
|
|
|
debug_printf ( "accept from unauthorized server" );
|
|
|
|
|
secret_check_failed = TRUE;
|
|
|
|
|
}
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2001-04-09 15:21:32 +08:00
|
|
|
|
|
2001-06-26 22:47:48 +08:00
|
|
|
|
if (secret_check_failed)
|
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
sock->close_secret_event ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
if (res)
|
|
|
|
|
closesocket (res);
|
2001-04-09 15:21:32 +08:00
|
|
|
|
set_errno (ECONNREFUSED);
|
|
|
|
|
res = -1;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-22 23:31:59 +08:00
|
|
|
|
static void
|
|
|
|
|
free_servent_ptr (struct servent *&p)
|
|
|
|
|
{
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("servent: %s", p->s_name);
|
|
|
|
|
|
|
|
|
|
if (p->s_name)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
free (p->s_name);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
if (p->s_proto)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
free (p->s_proto);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
free_char_list (p->s_aliases);
|
|
|
|
|
p = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-09-16 10:56:58 +08:00
|
|
|
|
#pragma pack(push,2)
|
|
|
|
|
struct pservent
|
|
|
|
|
{
|
|
|
|
|
char *s_name;
|
|
|
|
|
char **s_aliases;
|
|
|
|
|
short s_port;
|
|
|
|
|
char *s_proto;
|
|
|
|
|
};
|
|
|
|
|
#pragma pack(pop)
|
2001-08-22 23:31:59 +08:00
|
|
|
|
static struct servent *
|
|
|
|
|
dup_servent_ptr (struct servent *src)
|
|
|
|
|
{
|
|
|
|
|
if (!src)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct servent *dst = (struct servent *) calloc (1, sizeof *dst);
|
|
|
|
|
if (!dst)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
debug_printf ("servent: %s", src->s_name);
|
|
|
|
|
|
|
|
|
|
dst->s_port = src->s_port;
|
|
|
|
|
if (src->s_name && !(dst->s_name = strdup (src->s_name)))
|
|
|
|
|
goto out;
|
|
|
|
|
if (src->s_aliases && !(dst->s_aliases = dup_char_list (src->s_aliases)))
|
|
|
|
|
goto out;
|
2001-09-16 10:56:58 +08:00
|
|
|
|
char *s_proto;
|
|
|
|
|
if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto))
|
|
|
|
|
&& !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto)))
|
|
|
|
|
s_proto = ((pservent *)src)->s_proto;
|
|
|
|
|
else
|
|
|
|
|
s_proto = src->s_proto;
|
|
|
|
|
|
|
|
|
|
if (s_proto && !(dst->s_proto = strdup (s_proto)))
|
|
|
|
|
goto out;
|
2001-08-22 23:31:59 +08:00
|
|
|
|
|
|
|
|
|
debug_printf ("servent: copied %s", dst->s_name);
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
free_servent_ptr (dst);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
#ifdef _MT_SAFE
|
|
|
|
|
#define servent_buf _reent_winsup ()->_servent_buf
|
|
|
|
|
#else
|
|
|
|
|
static struct servent *servent_buf = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* exported as getservbyname: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct servent *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getservbyname (const char *name, const char *proto)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_str_errno (name)
|
|
|
|
|
|| (proto != NULL && check_null_str_errno (proto)))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_servent_ptr (servent_buf);
|
|
|
|
|
servent_buf = dup_servent_ptr (getservbyname (name, proto));
|
|
|
|
|
if (!servent_buf)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
syscall_printf ("%x = getservbyname (%s, %s)", servent_buf, name, proto);
|
|
|
|
|
return servent_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as getservbyport: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct servent *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getservbyport (int port, const char *proto)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (proto != NULL && check_null_str_errno (proto))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_servent_ptr (servent_buf);
|
|
|
|
|
servent_buf = dup_servent_ptr (getservbyport (port, proto));
|
|
|
|
|
if (!servent_buf)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
syscall_printf ("%x = getservbyport (%d, %s)", servent_buf, port, proto);
|
|
|
|
|
return servent_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_gethostname (char *name, size_t len)
|
|
|
|
|
{
|
2000-10-05 13:57:00 +08:00
|
|
|
|
int PASCAL win32_gethostname (char*, int);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (name, len))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (wsock32_handle == NULL ||
|
|
|
|
|
win32_gethostname (name, len) == SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
DWORD local_len = len;
|
|
|
|
|
|
|
|
|
|
if (!GetComputerNameA (name, &local_len))
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
debug_printf ("name %s\n", name);
|
|
|
|
|
h_errno = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-22 23:31:59 +08:00
|
|
|
|
static void
|
|
|
|
|
free_hostent_ptr (struct hostent *&p)
|
|
|
|
|
{
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("hostent: %s", p->h_name);
|
|
|
|
|
|
|
|
|
|
if (p->h_name)
|
2001-09-08 05:32:07 +08:00
|
|
|
|
free ((void *)p->h_name);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
free_char_list (p->h_aliases);
|
2001-08-24 14:57:53 +08:00
|
|
|
|
free_addr_list (p->h_addr_list);
|
2001-08-22 23:31:59 +08:00
|
|
|
|
p = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct hostent *
|
|
|
|
|
dup_hostent_ptr (struct hostent *src)
|
|
|
|
|
{
|
|
|
|
|
if (!src)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct hostent *dst = (struct hostent *) calloc (1, sizeof *dst);
|
|
|
|
|
if (!dst)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
debug_printf ("hostent: %s", src->h_name);
|
|
|
|
|
|
|
|
|
|
dst->h_addrtype = src->h_addrtype;
|
|
|
|
|
dst->h_length = src->h_length;
|
|
|
|
|
if (src->h_name && !(dst->h_name = strdup (src->h_name)))
|
|
|
|
|
goto out;
|
|
|
|
|
if (src->h_aliases && !(dst->h_aliases = dup_char_list (src->h_aliases)))
|
|
|
|
|
goto out;
|
2001-08-24 14:57:53 +08:00
|
|
|
|
if (src->h_addr_list
|
|
|
|
|
&& !(dst->h_addr_list = dup_addr_list(src->h_addr_list, src->h_length)))
|
2001-08-22 23:31:59 +08:00
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
debug_printf ("hostent: copied %s", dst->h_name);
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
free_hostent_ptr (dst);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
#ifdef _MT_SAFE
|
|
|
|
|
#define hostent_buf _reent_winsup ()->_hostent_buf
|
|
|
|
|
#else
|
|
|
|
|
static struct hostent *hostent_buf = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* exported as gethostbyname: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" struct hostent *
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_gethostbyname (const char *name)
|
|
|
|
|
{
|
|
|
|
|
static unsigned char tmp_addr[4];
|
|
|
|
|
static struct hostent tmp;
|
2001-09-06 12:41:59 +08:00
|
|
|
|
static char *tmp_aliases[1];
|
|
|
|
|
static char *tmp_addr_list[2];
|
2000-02-18 03:38:33 +08:00
|
|
|
|
static int a, b, c, d;
|
2000-10-05 13:57:00 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_str_errno (name))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
/* In case you don't have DNS, at least x.x.x.x still works */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
memset (&tmp, 0, sizeof (tmp));
|
2000-02-18 03:38:33 +08:00
|
|
|
|
tmp_addr[0] = a;
|
|
|
|
|
tmp_addr[1] = b;
|
|
|
|
|
tmp_addr[2] = c;
|
|
|
|
|
tmp_addr[3] = d;
|
|
|
|
|
tmp_addr_list[0] = (char *)tmp_addr;
|
|
|
|
|
tmp.h_name = name;
|
|
|
|
|
tmp.h_aliases = tmp_aliases;
|
|
|
|
|
tmp.h_addrtype = 2;
|
|
|
|
|
tmp.h_length = 4;
|
|
|
|
|
tmp.h_addr_list = tmp_addr_list;
|
|
|
|
|
return &tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_hostent_ptr (hostent_buf);
|
|
|
|
|
hostent_buf = dup_hostent_ptr (gethostbyname (name));
|
|
|
|
|
if (!hostent_buf)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
set_host_errno ();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2001-08-23 05:51:48 +08:00
|
|
|
|
debug_printf ("h_name %s", hostent_buf->h_name);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
h_errno = 0;
|
|
|
|
|
}
|
2001-08-23 05:51:48 +08:00
|
|
|
|
return hostent_buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as gethostbyaddr: standards? */
|
|
|
|
|
extern "C" struct hostent *
|
|
|
|
|
cygwin_gethostbyaddr (const char *addr, int len, int type)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (addr, len))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2001-08-23 05:51:48 +08:00
|
|
|
|
free_hostent_ptr (hostent_buf);
|
|
|
|
|
hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
|
|
|
|
|
if (!hostent_buf)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
set_host_errno ();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("h_name %s", hostent_buf->h_name);
|
|
|
|
|
h_errno = 0;
|
|
|
|
|
}
|
|
|
|
|
return hostent_buf;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as accept: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_accept (int fd, struct sockaddr *peer, int *len)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (peer != NULL
|
|
|
|
|
&& (check_null_invalid_struct_errno (len)
|
|
|
|
|
|| __check_null_invalid_struct_errno (peer, (unsigned) *len)))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
int res = -1;
|
2001-04-09 15:21:32 +08:00
|
|
|
|
BOOL secret_check_failed = FALSE;
|
2001-06-20 14:50:13 +08:00
|
|
|
|
BOOL in_progress = FALSE;
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
if (sock)
|
|
|
|
|
{
|
2001-08-03 20:06:29 +08:00
|
|
|
|
/* Allows NULL peer and len parameters. */
|
|
|
|
|
struct sockaddr_in peer_dummy;
|
|
|
|
|
int len_dummy;
|
|
|
|
|
if (!peer)
|
2001-08-07 08:01:42 +08:00
|
|
|
|
peer = (struct sockaddr *) &peer_dummy;
|
2001-08-03 20:06:29 +08:00
|
|
|
|
if (!len)
|
2001-08-07 08:01:42 +08:00
|
|
|
|
{
|
2001-08-03 20:06:29 +08:00
|
|
|
|
len_dummy = sizeof (struct sockaddr_in);
|
|
|
|
|
len = &len_dummy;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
/* accept on NT fails if len < sizeof (sockaddr_in)
|
|
|
|
|
* some programs set len to
|
2000-10-05 13:57:00 +08:00
|
|
|
|
* sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
|
2000-02-18 03:38:33 +08:00
|
|
|
|
*/
|
|
|
|
|
if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
|
|
|
|
|
*len = sizeof (struct sockaddr_in);
|
|
|
|
|
|
|
|
|
|
res = accept (sock->get_socket (), peer, len); // can't use a blocking call inside a lock
|
|
|
|
|
|
2001-06-20 14:50:13 +08:00
|
|
|
|
if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
|
|
|
|
|
WSAGetLastError () == WSAEWOULDBLOCK)
|
|
|
|
|
in_progress = TRUE;
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (sock->get_addr_family () == AF_LOCAL)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2001-06-20 14:50:13 +08:00
|
|
|
|
if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
|
|
|
|
|
{
|
|
|
|
|
if (!sock->create_secret_event ())
|
|
|
|
|
secret_check_failed = TRUE;
|
|
|
|
|
else if (in_progress)
|
|
|
|
|
sock->signal_secret_event ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!secret_check_failed &&
|
2001-06-26 22:47:48 +08:00
|
|
|
|
(SOCKET) res != (SOCKET) INVALID_SOCKET)
|
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer))
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("connect from unauthorized client");
|
|
|
|
|
secret_check_failed = TRUE;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (secret_check_failed)
|
|
|
|
|
{
|
|
|
|
|
sock->close_secret_event ();
|
|
|
|
|
if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
|
|
|
|
|
closesocket (res);
|
2001-04-09 15:21:32 +08:00
|
|
|
|
set_errno (ECONNABORTED);
|
2001-06-26 22:47:48 +08:00
|
|
|
|
res = -1;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-04-09 15:21:32 +08:00
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew res_fd;
|
|
|
|
|
if (res_fd < 0)
|
|
|
|
|
/* FIXME: what is correct errno? */;
|
2001-10-14 12:14:24 +08:00
|
|
|
|
else if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
else
|
|
|
|
|
{
|
2001-04-09 15:21:32 +08:00
|
|
|
|
fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res);
|
2002-01-10 04:57:55 +08:00
|
|
|
|
if (sock->get_addr_family () == AF_LOCAL)
|
|
|
|
|
res_fh->set_sun_path (sock->get_sun_path ());
|
2001-04-09 15:21:32 +08:00
|
|
|
|
res_fh->set_addr_family (sock->get_addr_family ());
|
2000-02-18 03:38:33 +08:00
|
|
|
|
res = res_fd;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-10-14 12:14:24 +08:00
|
|
|
|
done:
|
2000-02-18 03:38:33 +08:00
|
|
|
|
syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as bind: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2001-01-10 00:00:58 +08:00
|
|
|
|
cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (my_addr, addrlen))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
int res = -1;
|
|
|
|
|
|
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
if (sock)
|
|
|
|
|
{
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (my_addr->sa_family == AF_LOCAL)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
#define un_addr ((struct sockaddr_un *) my_addr)
|
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
|
int len = sizeof sin;
|
|
|
|
|
int fd;
|
|
|
|
|
|
2000-09-03 12:16:35 +08:00
|
|
|
|
if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
|
|
|
|
|
{
|
|
|
|
|
set_errno (ENAMETOOLONG);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
|
sin.sin_port = 0;
|
|
|
|
|
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
|
|
|
if (bind (sock->get_socket (), (sockaddr *) &sin, len))
|
|
|
|
|
{
|
2002-01-05 00:56:53 +08:00
|
|
|
|
syscall_printf ("AF_LOCAL: bind failed %d", get_errno ());
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len))
|
|
|
|
|
{
|
2002-01-05 00:56:53 +08:00
|
|
|
|
syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ());
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sin.sin_port = ntohs (sin.sin_port);
|
2002-01-05 00:56:53 +08:00
|
|
|
|
debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-03 12:16:35 +08:00
|
|
|
|
/* bind must fail if file system socket object already exists
|
2000-10-05 13:57:00 +08:00
|
|
|
|
so _open () is called with O_EXCL flag. */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
fd = _open (un_addr->sun_path,
|
2000-09-03 12:16:35 +08:00
|
|
|
|
O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
|
|
|
|
|
0);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (fd < 0)
|
2000-09-03 12:16:35 +08:00
|
|
|
|
{
|
|
|
|
|
if (get_errno () == EEXIST)
|
|
|
|
|
set_errno (EADDRINUSE);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
goto out;
|
2000-09-03 12:16:35 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-06-26 22:47:48 +08:00
|
|
|
|
sock->set_connect_secret ();
|
2001-04-09 15:21:32 +08:00
|
|
|
|
|
|
|
|
|
char buf[sizeof (SOCKET_COOKIE) + 80];
|
|
|
|
|
__small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
|
2001-06-26 22:47:48 +08:00
|
|
|
|
sock->get_connect_secret (strchr (buf, '\0'));
|
2000-09-03 12:16:35 +08:00
|
|
|
|
len = strlen (buf) + 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-03 12:16:35 +08:00
|
|
|
|
/* Note that the terminating nul is written. */
|
|
|
|
|
if (_write (fd, buf, len) != len)
|
|
|
|
|
{
|
2000-02-18 03:38:33 +08:00
|
|
|
|
save_errno here;
|
2000-09-03 12:16:35 +08:00
|
|
|
|
_close (fd);
|
|
|
|
|
_unlink (un_addr->sun_path);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_close (fd);
|
|
|
|
|
chmod (un_addr->sun_path,
|
2000-11-14 13:53:32 +08:00
|
|
|
|
(S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask);
|
2002-01-02 00:25:31 +08:00
|
|
|
|
sock->set_sun_path (un_addr->sun_path);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
res = 0;
|
2000-09-03 12:16:35 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
#undef un_addr
|
|
|
|
|
}
|
|
|
|
|
else if (bind (sock->get_socket (), my_addr, addrlen))
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
else
|
|
|
|
|
res = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as getsockname: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_invalid_struct_errno (namelen)
|
|
|
|
|
|| __check_null_invalid_struct_errno (addr, (unsigned) *namelen))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
int res = -1;
|
|
|
|
|
|
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
if (sock)
|
|
|
|
|
{
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (sock->get_addr_family () == AF_LOCAL)
|
2002-01-02 00:25:31 +08:00
|
|
|
|
{
|
|
|
|
|
struct sockaddr_un *sun = (struct sockaddr_un *) addr;
|
|
|
|
|
memset (sun, 0, *namelen);
|
2002-01-05 00:56:53 +08:00
|
|
|
|
sun->sun_family = AF_LOCAL;
|
2002-01-02 00:25:31 +08:00
|
|
|
|
/* According to SUSv2 "If the actual length of the address is greater
|
|
|
|
|
than the length of the supplied sockaddr structure, the stored
|
|
|
|
|
address will be truncated." We play it save here so that the
|
|
|
|
|
path always has a trailing 0 even if it's truncated. */
|
|
|
|
|
strncpy (sun->sun_path, sock->get_sun_path (),
|
|
|
|
|
*namelen - sizeof *sun + sizeof sun->sun_path - 1);
|
|
|
|
|
*namelen = sizeof *sun - sizeof sun->sun_path
|
|
|
|
|
+ strlen (sun->sun_path) + 1;
|
|
|
|
|
res = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = getsockname (sock->get_socket (), addr, namelen);
|
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as listen: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_listen (int fd, int backlog)
|
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
if (sock)
|
|
|
|
|
{
|
|
|
|
|
res = listen (sock->get_socket (), backlog);
|
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
}
|
|
|
|
|
syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as shutdown: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_shutdown (int fd, int how)
|
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
fhandler_socket *sock = get (fd);
|
|
|
|
|
if (sock)
|
|
|
|
|
{
|
|
|
|
|
res = shutdown (sock->get_socket (), how);
|
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
2001-08-31 13:06:14 +08:00
|
|
|
|
else
|
|
|
|
|
switch (how)
|
|
|
|
|
{
|
|
|
|
|
case SHUT_RD:
|
|
|
|
|
sock->set_shutdown_read ();
|
|
|
|
|
break;
|
|
|
|
|
case SHUT_WR:
|
|
|
|
|
sock->set_shutdown_write ();
|
|
|
|
|
break;
|
|
|
|
|
case SHUT_RDWR:
|
|
|
|
|
sock->set_shutdown_read ();
|
|
|
|
|
sock->set_shutdown_write ();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-14 16:55:44 +08:00
|
|
|
|
/* exported as hstrerror: BSD 4.3 */
|
|
|
|
|
extern "C" const char *
|
|
|
|
|
cygwin_hstrerror (int err)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; host_errmap[i].e != 0; ++i)
|
|
|
|
|
if (err == host_errmap[i].e)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
return host_errmap[i].s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as herror: BSD 4.3 */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" void
|
2000-10-14 16:55:44 +08:00
|
|
|
|
cygwin_herror (const char *s)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-25 05:52:28 +08:00
|
|
|
|
if (s && check_null_str (s))
|
2001-11-25 05:10:00 +08:00
|
|
|
|
return;
|
2001-04-19 05:10:15 +08:00
|
|
|
|
if (cygheap->fdtab.not_open (2))
|
2000-10-14 16:55:44 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
write (2, s, strlen (s));
|
|
|
|
|
write (2, ": ", 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *h_errstr = cygwin_hstrerror (h_errno);
|
|
|
|
|
|
|
|
|
|
if (!h_errstr)
|
|
|
|
|
switch (h_errno)
|
|
|
|
|
{
|
|
|
|
|
case NETDB_INTERNAL:
|
2001-06-26 22:47:48 +08:00
|
|
|
|
h_errstr = "Resolver internal error";
|
|
|
|
|
break;
|
2000-10-14 16:55:44 +08:00
|
|
|
|
case NETDB_SUCCESS:
|
2001-06-26 22:47:48 +08:00
|
|
|
|
h_errstr = "Resolver error 0 (no error)";
|
|
|
|
|
break;
|
2000-10-14 16:55:44 +08:00
|
|
|
|
default:
|
2001-06-26 22:47:48 +08:00
|
|
|
|
h_errstr = "Unknown resolver error";
|
|
|
|
|
break;
|
2000-10-14 16:55:44 +08:00
|
|
|
|
}
|
|
|
|
|
write (2, h_errstr, strlen (h_errstr));
|
|
|
|
|
write (2, "\n", 1);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as getpeername: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_getpeername (int fd, struct sockaddr *name, int *len)
|
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
int res;
|
|
|
|
|
if (check_null_invalid_struct_errno (len)
|
|
|
|
|
|| __check_null_invalid_struct_errno (name, (unsigned) *len))
|
|
|
|
|
return -1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
fhandler_socket *h = get (fd);
|
|
|
|
|
|
|
|
|
|
if (!h)
|
|
|
|
|
res = -1;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = getpeername (h->get_socket (), name, len);
|
|
|
|
|
if (res)
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
debug_printf ("%d = getpeername %d", res, h->get_socket ());
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as recv: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_recv (int fd, void *buf, int len, unsigned int flags)
|
|
|
|
|
{
|
2001-05-15 16:15:54 +08:00
|
|
|
|
int res;
|
|
|
|
|
wsock_event wsock_evt;
|
|
|
|
|
LPWSAOVERLAPPED ovr;
|
2001-11-24 11:11:39 +08:00
|
|
|
|
fhandler_socket *h = get (fd);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (buf, len) || !h)
|
|
|
|
|
res = -1;
|
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
|
|
|
|
|
|
|
|
|
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
debug_printf ("Fallback to winsock 1 recv call");
|
|
|
|
|
if ((res = recv (h->get_socket (), (char *) buf, len, flags))
|
|
|
|
|
== SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
2001-05-15 16:15:54 +08:00
|
|
|
|
}
|
2001-11-24 11:11:39 +08:00
|
|
|
|
else
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
WSABUF wsabuf = { len, (char *) buf };
|
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
|
|
|
|
ovr, NULL) != SOCKET_ERROR)
|
|
|
|
|
res = ret;
|
|
|
|
|
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
|
|
|
|
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
|
|
|
|
set_winsock_errno ();
|
2001-05-15 16:15:54 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as send: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_send (int fd, const void *buf, int len, unsigned int flags)
|
|
|
|
|
{
|
2001-05-15 16:15:54 +08:00
|
|
|
|
int res;
|
|
|
|
|
wsock_event wsock_evt;
|
|
|
|
|
LPWSAOVERLAPPED ovr;
|
2001-11-24 11:11:39 +08:00
|
|
|
|
fhandler_socket *h = get (fd);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_invalid_read_ptr_errno (buf, len) || !h)
|
|
|
|
|
res = -1;
|
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
|
|
|
|
|
|
|
|
|
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
2001-05-15 16:15:54 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
debug_printf ("Fallback to winsock 1 send call");
|
|
|
|
|
if ((res = send (h->get_socket (), (const char *) buf, len, flags))
|
|
|
|
|
== SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
2001-05-15 16:15:54 +08:00
|
|
|
|
}
|
2001-11-24 11:11:39 +08:00
|
|
|
|
else
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
2001-11-24 11:11:39 +08:00
|
|
|
|
WSABUF wsabuf = { len, (char *) buf };
|
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
|
|
|
|
ovr, NULL) != SOCKET_ERROR)
|
|
|
|
|
res = ret;
|
|
|
|
|
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
|
|
|
|
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
|
|
|
|
set_winsock_errno ();
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* getdomainname: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
getdomainname (char *domain, int len)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This works for Win95 only if the machine is configured to use MS-TCP.
|
|
|
|
|
* If a third-party TCP is being used this will fail.
|
|
|
|
|
* FIXME: On Win95, is there a way to portably check the TCP stack
|
|
|
|
|
* in use and include paths for the Domain name in each ?
|
|
|
|
|
* Punt for now and assume MS-TCP on Win95.
|
|
|
|
|
*/
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (domain, len))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-13 01:46:37 +08:00
|
|
|
|
(!wincap.is_winnt ()) ? "System" : "SYSTEM",
|
2000-02-18 03:38:33 +08:00
|
|
|
|
"CurrentControlSet", "Services",
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-13 01:46:37 +08:00
|
|
|
|
(!wincap.is_winnt ()) ? "MSTCP" : "Tcpip",
|
2000-02-18 03:38:33 +08:00
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Are registry keys case sensitive? */
|
|
|
|
|
if (r.error () || r.get_string ("Domain", domain, len, "") != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
__seterrno ();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cygwin internal */
|
2000-10-03 04:21:47 +08:00
|
|
|
|
/* Fill out an ifconf struct. */
|
|
|
|
|
|
|
|
|
|
/*
|
2001-02-08 06:50:50 +08:00
|
|
|
|
* IFCONF 98/ME, NTSP4, W2K:
|
|
|
|
|
* Use IP Helper Library
|
2000-02-18 03:38:33 +08:00
|
|
|
|
*/
|
2000-09-28 14:34:38 +08:00
|
|
|
|
static void
|
2000-10-03 04:21:47 +08:00
|
|
|
|
get_2k_ifconf (struct ifconf *ifc, int what)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-02-08 06:50:50 +08:00
|
|
|
|
int cnt = 0;
|
2001-10-22 20:23:33 +08:00
|
|
|
|
char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0";
|
2000-09-28 14:34:38 +08:00
|
|
|
|
|
|
|
|
|
/* Union maps buffer to correct struct */
|
|
|
|
|
struct ifreq *ifr = ifc->ifc_req;
|
|
|
|
|
|
2001-02-08 06:50:50 +08:00
|
|
|
|
DWORD if_cnt, ip_cnt, lip, lnp;
|
|
|
|
|
DWORD siz_if_table = 0;
|
|
|
|
|
DWORD siz_ip_table = 0;
|
|
|
|
|
PMIB_IFTABLE ift;
|
|
|
|
|
PMIB_IPADDRTABLE ipt;
|
|
|
|
|
struct sockaddr_in *sa = NULL;
|
|
|
|
|
struct sockaddr *so = NULL;
|
|
|
|
|
|
|
|
|
|
if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
|
|
|
|
|
GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
|
|
|
|
|
(ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
|
|
|
|
|
(ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
|
|
|
|
|
!GetIfTable(ift, &siz_if_table, TRUE) &&
|
|
|
|
|
!GetIpAddrTable(ipt, &siz_ip_table, TRUE))
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-10-22 20:23:33 +08:00
|
|
|
|
/* Iterate over all known interfaces */
|
2001-02-08 06:50:50 +08:00
|
|
|
|
for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
|
2001-11-05 14:09:15 +08:00
|
|
|
|
{
|
2001-10-22 20:23:33 +08:00
|
|
|
|
*sub = '0';
|
|
|
|
|
/* Iterate over all configured IP-addresses */
|
2001-11-05 14:09:15 +08:00
|
|
|
|
for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
|
2001-02-08 06:50:50 +08:00
|
|
|
|
{
|
2001-10-22 20:23:33 +08:00
|
|
|
|
/* Does the IP address belong to the interface? */
|
|
|
|
|
if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
|
|
|
|
|
{
|
|
|
|
|
/* Setup the interface name */
|
|
|
|
|
switch (ift->table[if_cnt].dwType)
|
|
|
|
|
{
|
|
|
|
|
case MIB_IF_TYPE_ETHERNET:
|
|
|
|
|
if (*sub == '0')
|
|
|
|
|
++*eth;
|
|
|
|
|
strcpy (ifr->ifr_name, "eth");
|
|
|
|
|
strcat (ifr->ifr_name, eth);
|
|
|
|
|
break;
|
|
|
|
|
case MIB_IF_TYPE_PPP:
|
|
|
|
|
++*ppp;
|
|
|
|
|
strcpy (ifr->ifr_name, "ppp");
|
|
|
|
|
strcat (ifr->ifr_name, ppp);
|
|
|
|
|
break;
|
|
|
|
|
case MIB_IF_TYPE_SLIP:
|
|
|
|
|
++*slp;
|
|
|
|
|
strcpy (ifr->ifr_name, "slp");
|
|
|
|
|
strcat (ifr->ifr_name, slp);
|
|
|
|
|
break;
|
|
|
|
|
case MIB_IF_TYPE_LOOPBACK:
|
|
|
|
|
strcpy (ifr->ifr_name, "lo");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (*sub > '0')
|
|
|
|
|
{
|
|
|
|
|
strcat (ifr->ifr_name, ":");
|
|
|
|
|
strcat (ifr->ifr_name, sub);
|
|
|
|
|
}
|
|
|
|
|
++*sub;
|
|
|
|
|
/* setup sockaddr struct */
|
|
|
|
|
switch (what)
|
|
|
|
|
{
|
|
|
|
|
case SIOCGIFCONF:
|
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_addr;
|
|
|
|
|
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
|
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
#if 0
|
2001-10-22 20:23:33 +08:00
|
|
|
|
/* Unfortunately, the field returns only crap. */
|
|
|
|
|
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
#else
|
2001-10-22 20:23:33 +08:00
|
|
|
|
lip = ipt->table[ip_cnt].dwAddr;
|
|
|
|
|
lnp = ipt->table[ip_cnt].dwMask;
|
|
|
|
|
sa->sin_addr.s_addr = lip & lnp | ~lnp;
|
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
#endif
|
2001-10-22 20:23:33 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
|
|
|
|
|
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
|
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFHWADDR:
|
|
|
|
|
so = &ifr->ifr_hwaddr;
|
|
|
|
|
for (UINT i = 0; i < IFHWADDRLEN; ++i)
|
|
|
|
|
if (i >= ift->table[if_cnt].dwPhysAddrLen)
|
|
|
|
|
so->sa_data[i] = '\0';
|
|
|
|
|
else
|
|
|
|
|
so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
|
|
|
|
|
so->sa_family = AF_INET;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMETRIC:
|
|
|
|
|
ifr->ifr_metric = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMTU:
|
|
|
|
|
ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++cnt;
|
|
|
|
|
if ((caddr_t) ++ifr >
|
|
|
|
|
ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-02-08 06:50:50 +08:00
|
|
|
|
}
|
2000-09-28 14:34:38 +08:00
|
|
|
|
}
|
2001-02-08 06:50:50 +08:00
|
|
|
|
done:
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Set the correct length */
|
|
|
|
|
ifc->ifc_len = cnt * sizeof (struct ifreq);
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-03 04:21:47 +08:00
|
|
|
|
/*
|
2001-02-08 06:50:50 +08:00
|
|
|
|
* IFCONF Windows NT < SP4:
|
2000-10-03 04:21:47 +08:00
|
|
|
|
* Look at the Bind value in
|
|
|
|
|
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\
|
|
|
|
|
* This is a REG_MULTI_SZ with strings of the form:
|
|
|
|
|
* \Device\<Netcard>, where netcard is the name of the net device.
|
|
|
|
|
* Then look under:
|
|
|
|
|
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
|
|
|
|
|
* Parameters\Tcpip
|
|
|
|
|
* at the IPAddress, Subnetmask and DefaultGateway values for the
|
|
|
|
|
* required values.
|
|
|
|
|
*/
|
2000-09-28 14:34:38 +08:00
|
|
|
|
static void
|
2000-10-03 04:21:47 +08:00
|
|
|
|
get_nt_ifconf (struct ifconf *ifc, int what)
|
2000-09-28 14:34:38 +08:00
|
|
|
|
{
|
|
|
|
|
HKEY key;
|
|
|
|
|
unsigned long lip, lnp;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
struct sockaddr_in *sa = NULL;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
struct sockaddr *so = NULL;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
DWORD size;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
int cnt = 1;
|
|
|
|
|
char *binding = (char *) 0;
|
|
|
|
|
|
|
|
|
|
/* Union maps buffer to correct struct */
|
|
|
|
|
struct ifreq *ifr = ifc->ifc_req;
|
|
|
|
|
|
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
2001-06-26 22:47:48 +08:00
|
|
|
|
"SYSTEM\\"
|
|
|
|
|
"CurrentControlSet\\"
|
|
|
|
|
"Services\\"
|
|
|
|
|
"Tcpip\\"
|
|
|
|
|
"Linkage",
|
|
|
|
|
0, KEY_READ, &key) == ERROR_SUCCESS)
|
2000-09-28 14:34:38 +08:00
|
|
|
|
{
|
|
|
|
|
if (RegQueryValueEx (key, "Bind",
|
2001-06-26 22:47:48 +08:00
|
|
|
|
NULL, NULL,
|
|
|
|
|
NULL, &size) == ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
binding = (char *) alloca (size);
|
|
|
|
|
if (RegQueryValueEx (key, "Bind",
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
(unsigned char *) binding,
|
|
|
|
|
&size) != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
binding = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-09-28 14:34:38 +08:00
|
|
|
|
RegCloseKey (key);
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
if (binding)
|
|
|
|
|
{
|
|
|
|
|
char *bp, eth[2] = "/";
|
|
|
|
|
char cardkey[256], ipaddress[256], netmask[256];
|
|
|
|
|
|
2000-10-05 13:57:00 +08:00
|
|
|
|
for (bp = binding; *bp; bp += strlen (bp) + 1)
|
2001-06-26 22:47:48 +08:00
|
|
|
|
{
|
|
|
|
|
bp += strlen ("\\Device\\");
|
|
|
|
|
strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
|
|
|
|
|
strcat (cardkey, bp);
|
|
|
|
|
strcat (cardkey, "\\Parameters\\Tcpip");
|
|
|
|
|
|
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
|
|
|
|
|
0, KEY_READ, &key) != ERROR_SUCCESS)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (RegQueryValueEx (key, "IPAddress",
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
(unsigned char *) ipaddress,
|
|
|
|
|
(size = 256, &size)) == ERROR_SUCCESS
|
|
|
|
|
&& RegQueryValueEx (key, "SubnetMask",
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
(unsigned char *) netmask,
|
|
|
|
|
(size = 256, &size)) == ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
char *ip, *np;
|
|
|
|
|
char dhcpaddress[256], dhcpnetmask[256];
|
|
|
|
|
|
|
|
|
|
for (ip = ipaddress, np = netmask;
|
|
|
|
|
*ip && *np;
|
|
|
|
|
ip += strlen (ip) + 1, np += strlen (np) + 1)
|
|
|
|
|
{
|
|
|
|
|
if ((caddr_t) ++ifr > ifc->ifc_buf
|
|
|
|
|
+ ifc->ifc_len
|
|
|
|
|
- sizeof (struct ifreq))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (! strncmp (bp, "NdisWan", 7))
|
|
|
|
|
{
|
|
|
|
|
strcpy (ifr->ifr_name, "ppp");
|
|
|
|
|
strcat (ifr->ifr_name, bp + 7);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++*eth;
|
|
|
|
|
strcpy (ifr->ifr_name, "eth");
|
|
|
|
|
strcat (ifr->ifr_name, eth);
|
|
|
|
|
}
|
|
|
|
|
memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
|
|
|
|
|
if (cygwin_inet_addr (ip) == 0L
|
|
|
|
|
&& RegQueryValueEx (key, "DhcpIPAddress",
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
(unsigned char *) dhcpaddress,
|
|
|
|
|
(size = 256, &size))
|
|
|
|
|
== ERROR_SUCCESS
|
|
|
|
|
&& RegQueryValueEx (key, "DhcpSubnetMask",
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
(unsigned char *) dhcpnetmask,
|
|
|
|
|
(size = 256, &size))
|
|
|
|
|
== ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
switch (what)
|
|
|
|
|
{
|
|
|
|
|
case SIOCGIFCONF:
|
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_addr;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
|
lip = cygwin_inet_addr (dhcpaddress);
|
|
|
|
|
lnp = cygwin_inet_addr (dhcpnetmask);
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
|
|
|
|
|
sa->sin_addr.s_addr = lip & lnp | ~lnp;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
|
|
|
|
|
sa->sin_addr.s_addr =
|
|
|
|
|
cygwin_inet_addr (dhcpnetmask);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFHWADDR:
|
2001-02-08 06:50:50 +08:00
|
|
|
|
so = &ifr->ifr_hwaddr;
|
|
|
|
|
memset (so->sa_data, 0, IFHWADDRLEN);
|
|
|
|
|
so->sa_family = AF_INET;
|
|
|
|
|
break;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
case SIOCGIFMETRIC:
|
2001-02-08 06:50:50 +08:00
|
|
|
|
ifr->ifr_metric = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMTU:
|
|
|
|
|
ifr->ifr_mtu = 1500;
|
|
|
|
|
break;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (what)
|
|
|
|
|
{
|
|
|
|
|
case SIOCGIFCONF:
|
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_addr;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr (ip);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
|
lip = cygwin_inet_addr (ip);
|
|
|
|
|
lnp = cygwin_inet_addr (np);
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
|
|
|
|
|
sa->sin_addr.s_addr = lip & lnp | ~lnp;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr (np);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFHWADDR:
|
2001-02-08 06:50:50 +08:00
|
|
|
|
so = &ifr->ifr_hwaddr;
|
|
|
|
|
memset (so->sa_data, 0, IFHWADDRLEN);
|
|
|
|
|
so->sa_family = AF_INET;
|
|
|
|
|
break;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
case SIOCGIFMETRIC:
|
2001-02-08 06:50:50 +08:00
|
|
|
|
ifr->ifr_metric = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMTU:
|
|
|
|
|
ifr->ifr_mtu = 1500;
|
|
|
|
|
break;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++cnt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey (key);
|
|
|
|
|
}
|
2000-09-28 14:34:38 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Set the correct length */
|
|
|
|
|
ifc->ifc_len = cnt * sizeof (struct ifreq);
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-03 04:21:47 +08:00
|
|
|
|
/*
|
2001-02-08 06:50:50 +08:00
|
|
|
|
* IFCONF Windows 95:
|
2000-10-03 04:21:47 +08:00
|
|
|
|
* HKLM/Enum/Network/MSTCP/"*"
|
2001-09-08 05:32:07 +08:00
|
|
|
|
* -> Value "Driver" enth<EFBFBD>lt Subkey relativ zu
|
|
|
|
|
* HKLM/System/CurrentControlSet/Class/
|
|
|
|
|
* -> In Subkey "Bindings" die Values aufz<EFBFBD>hlen
|
|
|
|
|
* -> Enth<EFBFBD>lt Subkeys der Form "VREDIR\*"
|
|
|
|
|
* Das * ist ein Subkey relativ zu
|
|
|
|
|
* HKLM/System/CurrentControlSet/Class/Net/
|
2000-10-03 04:21:47 +08:00
|
|
|
|
* HKLM/System/CurrentControlSet/Class/"Driver"
|
2001-09-08 05:32:07 +08:00
|
|
|
|
* -> Value "IPAddress"
|
|
|
|
|
* -> Value "IPMask"
|
2000-10-03 04:21:47 +08:00
|
|
|
|
* HKLM/System/CurrentControlSet/Class/Net/"*"(aus "VREDIR\*")
|
2001-09-08 05:32:07 +08:00
|
|
|
|
* -> Wenn Value "AdapterName" == "MS$PPP" -> ppp interface
|
|
|
|
|
* -> Value "DriverDesc" enth<EFBFBD>lt den Namen
|
2000-10-03 04:21:47 +08:00
|
|
|
|
*
|
|
|
|
|
*/
|
2000-09-28 14:34:38 +08:00
|
|
|
|
static void
|
2001-02-08 06:50:50 +08:00
|
|
|
|
get_95_ifconf (struct ifconf *ifc, int what)
|
2000-09-28 14:34:38 +08:00
|
|
|
|
{
|
2000-10-03 04:21:47 +08:00
|
|
|
|
HKEY key;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
unsigned long lip, lnp;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
struct sockaddr_in *sa = NULL;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
struct sockaddr *so = NULL;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
FILETIME update;
|
|
|
|
|
LONG res;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
DWORD size;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
int cnt = 1;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
char ifname[256];
|
|
|
|
|
char eth[2] = "/";
|
|
|
|
|
char ppp[2] = "/";
|
2000-09-28 14:34:38 +08:00
|
|
|
|
|
|
|
|
|
/* Union maps buffer to correct struct */
|
|
|
|
|
struct ifreq *ifr = ifc->ifc_req;
|
|
|
|
|
|
2000-10-03 04:21:47 +08:00
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Enum\\Network\\MSTCP",
|
2001-06-26 22:47:48 +08:00
|
|
|
|
0, KEY_READ, &key) != ERROR_SUCCESS)
|
2000-10-03 04:21:47 +08:00
|
|
|
|
{
|
|
|
|
|
/* Set the correct length */
|
|
|
|
|
ifc->ifc_len = cnt * sizeof (struct ifreq);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0;
|
|
|
|
|
(res = RegEnumKeyEx (key, i, ifname,
|
2001-06-26 22:47:48 +08:00
|
|
|
|
(size = sizeof ifname, &size),
|
|
|
|
|
0, 0, 0, &update)) != ERROR_NO_MORE_ITEMS;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
++i)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2000-10-03 04:21:47 +08:00
|
|
|
|
HKEY ifkey, subkey;
|
2001-10-11 03:28:19 +08:00
|
|
|
|
char driver[256], classname[256], netname[256];
|
2000-10-03 04:21:47 +08:00
|
|
|
|
char adapter[256], ip[256], np[256];
|
|
|
|
|
|
|
|
|
|
if (res != ERROR_SUCCESS
|
2001-06-26 22:47:48 +08:00
|
|
|
|
|| RegOpenKeyEx (key, ifname, 0,
|
|
|
|
|
KEY_READ, &ifkey) != ERROR_SUCCESS)
|
|
|
|
|
continue;
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
|
|
|
|
if (RegQueryValueEx (ifkey, "Driver", 0,
|
2001-06-26 22:47:48 +08:00
|
|
|
|
NULL, (unsigned char *) driver,
|
|
|
|
|
(size = sizeof driver, &size)) != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
RegCloseKey (ifkey);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
|
|
|
|
strcpy (classname, "System\\CurrentControlSet\\Services\\Class\\");
|
|
|
|
|
strcat (classname, driver);
|
|
|
|
|
if ((res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, classname,
|
2001-06-26 22:47:48 +08:00
|
|
|
|
0, KEY_READ, &subkey)) != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
RegCloseKey (ifkey);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
|
|
|
|
if (RegQueryValueEx (subkey, "IPAddress", 0,
|
2001-06-26 22:47:48 +08:00
|
|
|
|
NULL, (unsigned char *) ip,
|
|
|
|
|
(size = sizeof ip, &size)) == ERROR_SUCCESS
|
|
|
|
|
&& RegQueryValueEx (subkey, "IPMask", 0,
|
|
|
|
|
NULL, (unsigned char *) np,
|
|
|
|
|
(size = sizeof np, &size)) == ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
if ((caddr_t)++ifr > ifc->ifc_buf
|
|
|
|
|
+ ifc->ifc_len
|
|
|
|
|
- sizeof (struct ifreq))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
switch (what)
|
|
|
|
|
{
|
|
|
|
|
case SIOCGIFCONF:
|
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_addr;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr (ip);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
|
lip = cygwin_inet_addr (ip);
|
|
|
|
|
lnp = cygwin_inet_addr (np);
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
|
|
|
|
|
sa->sin_addr.s_addr = lip & lnp | ~lnp;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr (np);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
break;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
case SIOCGIFHWADDR:
|
|
|
|
|
so = &ifr->ifr_hwaddr;
|
|
|
|
|
memset (so->sa_data, 0, IFHWADDRLEN);
|
|
|
|
|
so->sa_family = AF_INET;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMETRIC:
|
|
|
|
|
ifr->ifr_metric = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMTU:
|
|
|
|
|
ifr->ifr_mtu = 1500;
|
|
|
|
|
break;
|
2001-06-26 22:47:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
|
|
|
|
RegCloseKey (subkey);
|
|
|
|
|
|
2001-10-11 03:28:19 +08:00
|
|
|
|
strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
|
|
|
|
|
strcat (netname, ifname);
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
2001-10-11 03:28:19 +08:00
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
|
2001-11-05 14:09:15 +08:00
|
|
|
|
0, KEY_READ, &subkey) != ERROR_SUCCESS)
|
2001-10-11 03:28:19 +08:00
|
|
|
|
{
|
2001-11-05 14:09:15 +08:00
|
|
|
|
RegCloseKey (ifkey);
|
|
|
|
|
--ifr;
|
|
|
|
|
continue;
|
2001-10-11 03:28:19 +08:00
|
|
|
|
}
|
2000-10-03 04:21:47 +08:00
|
|
|
|
|
2001-10-11 03:28:19 +08:00
|
|
|
|
if (RegQueryValueEx (subkey, "AdapterName", 0,
|
2001-11-05 14:09:15 +08:00
|
|
|
|
NULL, (unsigned char *) adapter,
|
|
|
|
|
(size = sizeof adapter, &size)) == ERROR_SUCCESS
|
|
|
|
|
&& strcasematch (adapter, "MS$PPP"))
|
2001-10-11 03:28:19 +08:00
|
|
|
|
{
|
2001-11-05 14:09:15 +08:00
|
|
|
|
++*ppp;
|
|
|
|
|
strcpy (ifr->ifr_name, "ppp");
|
|
|
|
|
strcat (ifr->ifr_name, ppp);
|
2001-10-11 03:28:19 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2001-11-05 14:09:15 +08:00
|
|
|
|
++*eth;
|
|
|
|
|
strcpy (ifr->ifr_name, "eth");
|
|
|
|
|
strcat (ifr->ifr_name, eth);
|
2001-10-11 03:28:19 +08:00
|
|
|
|
}
|
2001-11-05 14:09:15 +08:00
|
|
|
|
|
2000-10-03 04:21:47 +08:00
|
|
|
|
RegCloseKey (subkey);
|
|
|
|
|
RegCloseKey (ifkey);
|
|
|
|
|
|
|
|
|
|
++cnt;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-03 04:21:47 +08:00
|
|
|
|
out:
|
|
|
|
|
|
|
|
|
|
RegCloseKey (key);
|
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Set the correct length */
|
|
|
|
|
ifc->ifc_len = cnt * sizeof (struct ifreq);
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-10-27 17:50:33 +08:00
|
|
|
|
int
|
2000-09-28 14:34:38 +08:00
|
|
|
|
get_ifconf (struct ifconf *ifc, int what)
|
|
|
|
|
{
|
|
|
|
|
unsigned long lip, lnp;
|
|
|
|
|
struct sockaddr_in *sa;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-24 11:11:39 +08:00
|
|
|
|
if (check_null_invalid_struct_errno (ifc))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Union maps buffer to correct struct */
|
|
|
|
|
struct ifreq *ifr = ifc->ifc_req;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Ensure we have space for two struct ifreqs, fail if not. */
|
|
|
|
|
if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
|
|
|
|
|
{
|
|
|
|
|
set_errno (EFAULT);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2000-09-28 14:34:38 +08:00
|
|
|
|
/* Set up interface lo0 first */
|
2001-02-08 06:50:50 +08:00
|
|
|
|
strcpy (ifr->ifr_name, "lo");
|
2000-09-28 14:34:38 +08:00
|
|
|
|
memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
|
|
|
|
|
switch (what)
|
|
|
|
|
{
|
|
|
|
|
case SIOCGIFCONF:
|
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_addr;
|
|
|
|
|
sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
|
lip = htonl (INADDR_LOOPBACK);
|
|
|
|
|
lnp = cygwin_inet_addr ("255.0.0.0");
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
|
|
|
|
|
sa->sin_addr.s_addr = lip & lnp | ~lnp;
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
|
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
|
|
|
|
|
sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
|
2001-02-08 06:50:50 +08:00
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
|
sa->sin_port = 0;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFHWADDR:
|
|
|
|
|
ifr->ifr_hwaddr.sa_family = AF_INET;
|
|
|
|
|
memset (ifr->ifr_hwaddr.sa_data, 0, IFHWADDRLEN);
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMETRIC:
|
|
|
|
|
ifr->ifr_metric = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SIOCGIFMTU:
|
|
|
|
|
/* This funny value is returned by `ifconfig lo' on Linux 2.2 kernel. */
|
|
|
|
|
ifr->ifr_mtu = 3924;
|
2000-09-28 14:34:38 +08:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
set_errno (EINVAL);
|
|
|
|
|
return -1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
2000-09-28 14:34:38 +08:00
|
|
|
|
|
|
|
|
|
OSVERSIONINFO os_version_info;
|
|
|
|
|
memset (&os_version_info, 0, sizeof os_version_info);
|
|
|
|
|
os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
|
|
|
GetVersionEx (&os_version_info);
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-13 01:46:37 +08:00
|
|
|
|
if (wincap.has_ip_helper_lib ())
|
|
|
|
|
get_2k_ifconf (ifc, what);
|
|
|
|
|
else if (wincap.is_winnt ())
|
2000-10-03 04:21:47 +08:00
|
|
|
|
get_nt_ifconf (ifc, what);
|
2000-09-28 14:34:38 +08:00
|
|
|
|
else
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-13 01:46:37 +08:00
|
|
|
|
get_95_ifconf (ifc, what);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as rcmd: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
|
|
|
|
|
char *remuser, char *cmd, int *fd2p)
|
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
|
|
|
|
SOCKET fd2s;
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-25 05:52:28 +08:00
|
|
|
|
if (check_null_invalid_struct_errno (ahost) ||
|
|
|
|
|
check_null_empty_str_errno (*ahost) ||
|
|
|
|
|
(locuser && check_null_empty_str_errno (locuser)) ||
|
|
|
|
|
(remuser && check_null_str_errno (remuser)))
|
|
|
|
|
return (int) INVALID_SOCKET;
|
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew res_fd;
|
|
|
|
|
if (res_fd < 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
if (fd2p)
|
|
|
|
|
{
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew newfd (res_fd, false);
|
|
|
|
|
if (*fd2p < 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
goto done;
|
2001-10-16 07:39:33 +08:00
|
|
|
|
*fd2p = newfd;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p ? &fd2s : NULL);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (res == (int) INVALID_SOCKET)
|
|
|
|
|
goto done;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fdsock (res_fd, "/dev/tcp", res);
|
|
|
|
|
res = res_fd;
|
|
|
|
|
}
|
2001-10-16 07:39:33 +08:00
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (fd2p)
|
2001-10-14 12:14:24 +08:00
|
|
|
|
fdsock (*fd2p, "/dev/tcp", fd2s);
|
2001-10-16 07:39:33 +08:00
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
done:
|
|
|
|
|
syscall_printf ("%d = rcmd (...)", res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as rresvport: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_rresvport (int *port)
|
|
|
|
|
{
|
2001-10-16 07:39:33 +08:00
|
|
|
|
int res;
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-25 05:10:00 +08:00
|
|
|
|
if (check_null_invalid_struct_errno (port))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew res_fd;
|
|
|
|
|
if (res_fd < 0)
|
|
|
|
|
res = -1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
2001-10-16 07:39:33 +08:00
|
|
|
|
res = rresvport (port);
|
|
|
|
|
|
|
|
|
|
if (res != (int) INVALID_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
fdsock (res_fd, "/dev/tcp", res);
|
|
|
|
|
res = res_fd;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
2001-10-16 07:39:33 +08:00
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
syscall_printf ("%d = rresvport (%d)", res, port ? *port : 0);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as rexec: standards? */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2000-02-18 03:38:33 +08:00
|
|
|
|
cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
|
|
|
|
|
char *password, char *cmd, int *fd2p)
|
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
|
|
|
|
SOCKET fd2s;
|
2000-09-08 11:12:13 +08:00
|
|
|
|
sigframe thisframe (mainthread);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-25 05:52:28 +08:00
|
|
|
|
if (check_null_invalid_struct_errno (ahost) ||
|
|
|
|
|
check_null_empty_str_errno (*ahost) ||
|
|
|
|
|
(locuser && check_null_empty_str_errno (locuser)) ||
|
|
|
|
|
(password && check_null_str_errno (password)))
|
|
|
|
|
return (int) INVALID_SOCKET;
|
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew res_fd;
|
|
|
|
|
if (res_fd < 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
goto done;
|
|
|
|
|
if (fd2p)
|
|
|
|
|
{
|
2001-10-16 07:39:33 +08:00
|
|
|
|
cygheap_fdnew newfd (res_fd);
|
|
|
|
|
if (newfd < 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
goto done;
|
2001-10-16 07:39:33 +08:00
|
|
|
|
*fd2p = newfd;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
res = rexec (ahost, inport, locuser, password, cmd, fd2p ? &fd2s : NULL);
|
|
|
|
|
if (res == (int) INVALID_SOCKET)
|
|
|
|
|
goto done;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fdsock (res_fd, "/dev/tcp", res);
|
|
|
|
|
res = res_fd;
|
|
|
|
|
}
|
|
|
|
|
if (fd2p)
|
2000-12-12 03:45:54 +08:00
|
|
|
|
fdsock (*fd2p, "/dev/tcp", fd2s);
|
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
|
done:
|
|
|
|
|
syscall_printf ("%d = rexec (...)", res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* socketpair: standards? */
|
|
|
|
|
/* Win32 supports AF_INET only, so ignore domain and protocol arguments */
|
2000-10-05 13:57:00 +08:00
|
|
|
|
extern "C" int
|
2002-01-05 00:56:53 +08:00
|
|
|
|
socketpair (int family, int type, int protocol, int *sb)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
|
|
|
|
int res = -1;
|
|
|
|
|
SOCKET insock, outsock, newsock;
|
2002-01-05 00:56:53 +08:00
|
|
|
|
struct sockaddr_in sock_in, sock_out;
|
|
|
|
|
int len;
|
|
|
|
|
cygheap_fdnew sb0;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-11-25 05:10:00 +08:00
|
|
|
|
if (__check_null_invalid_struct_errno (sb, 2 * sizeof(int)))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (family != AF_LOCAL && family != AF_INET)
|
|
|
|
|
{
|
|
|
|
|
set_errno (EAFNOSUPPORT);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
if (type != SOCK_STREAM && type != SOCK_DGRAM)
|
|
|
|
|
{
|
|
|
|
|
set_errno (EPROTOTYPE);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
|
|
|
|
|
|| (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
|
|
|
|
|
{
|
|
|
|
|
set_errno (EPROTONOSUPPORT);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
if (sb0 < 0)
|
|
|
|
|
goto done;
|
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2001-10-16 07:39:33 +08:00
|
|
|
|
sb[0] = sb0;
|
|
|
|
|
cygheap_fdnew sb1 (sb0, false);
|
|
|
|
|
if (sb1 < 0)
|
|
|
|
|
goto done;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2001-10-16 07:39:33 +08:00
|
|
|
|
sb[1] = sb1;
|
|
|
|
|
}
|
2002-01-05 00:56:53 +08:00
|
|
|
|
|
|
|
|
|
/* create the first socket */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
newsock = socket (AF_INET, type, 0);
|
|
|
|
|
if (newsock == INVALID_SOCKET)
|
|
|
|
|
{
|
2000-10-05 13:57:00 +08:00
|
|
|
|
debug_printf ("first socket call failed");
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* bind the socket to any unused port */
|
|
|
|
|
sock_in.sin_family = AF_INET;
|
|
|
|
|
sock_in.sin_port = 0;
|
|
|
|
|
sock_in.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
|
|
|
|
|
{
|
2000-10-05 13:57:00 +08:00
|
|
|
|
debug_printf ("bind failed");
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
2002-01-05 00:56:53 +08:00
|
|
|
|
len = sizeof (sock_in);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("getsockname error");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
/* For stream sockets, create a listener */
|
|
|
|
|
if (type == SOCK_STREAM)
|
|
|
|
|
listen (newsock, 2);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
/* create a connecting socket */
|
|
|
|
|
outsock = socket (AF_INET, type, 0);
|
|
|
|
|
if (outsock == INVALID_SOCKET)
|
|
|
|
|
{
|
2000-10-05 13:57:00 +08:00
|
|
|
|
debug_printf ("second socket call failed");
|
2000-02-18 03:38:33 +08:00
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
/* For datagram sockets, bind the 2nd socket to an unused address, too */
|
|
|
|
|
if (type == SOCK_DGRAM)
|
|
|
|
|
{
|
|
|
|
|
sock_out.sin_family = AF_INET;
|
|
|
|
|
sock_out.sin_port = 0;
|
|
|
|
|
sock_out.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("bind failed");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
closesocket (outsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
len = sizeof (sock_out);
|
|
|
|
|
if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("getsockname error");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
closesocket (outsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Force IP address to loopback */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (type == SOCK_DGRAM)
|
|
|
|
|
sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
/* Do a connect */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
if (connect (outsock, (struct sockaddr *) &sock_in,
|
|
|
|
|
sizeof (sock_in)) < 0)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("connect error");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
closesocket (outsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (type == SOCK_STREAM)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
{
|
2002-01-05 00:56:53 +08:00
|
|
|
|
/* For stream sockets, accept the connection and close the listener */
|
|
|
|
|
len = sizeof (sock_in);
|
|
|
|
|
insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
|
|
|
|
|
if (insock == INVALID_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("accept error");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
closesocket (outsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
closesocket (newsock);
|
2002-01-05 00:56:53 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* For datagram sockets, connect the 2nd socket */
|
|
|
|
|
if (connect (newsock, (struct sockaddr *) &sock_out,
|
|
|
|
|
sizeof (sock_out)) < 0)
|
|
|
|
|
{
|
|
|
|
|
debug_printf ("connect error");
|
|
|
|
|
set_winsock_errno ();
|
|
|
|
|
closesocket (newsock);
|
|
|
|
|
closesocket (outsock);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
insock = newsock;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = 0;
|
|
|
|
|
|
2002-01-05 00:56:53 +08:00
|
|
|
|
if (family == AF_LOCAL)
|
|
|
|
|
{
|
|
|
|
|
fhandler_socket *fh;
|
|
|
|
|
|
|
|
|
|
fh = fdsock (sb[0],
|
|
|
|
|
type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
|
|
|
|
|
insock);
|
|
|
|
|
fh->set_sun_path ("");
|
|
|
|
|
fh->set_addr_family (AF_LOCAL);
|
|
|
|
|
fh = fdsock (sb[1],
|
|
|
|
|
type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
|
|
|
|
|
outsock);
|
|
|
|
|
fh->set_sun_path ("");
|
|
|
|
|
fh->set_addr_family (AF_LOCAL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fdsock (sb[0], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
|
|
|
|
|
insock)->set_addr_family (AF_INET);
|
|
|
|
|
fdsock (sb[1], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
|
|
|
|
|
outsock)->set_addr_family (AF_INET);
|
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
syscall_printf ("%d = socketpair (...)", res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-26 18:13:41 +08:00
|
|
|
|
/* sethostent: standards? */
|
|
|
|
|
extern "C" void
|
|
|
|
|
sethostent (int)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* endhostent: standards? */
|
|
|
|
|
extern "C" void
|
|
|
|
|
endhostent (void)
|
|
|
|
|
{
|
|
|
|
|
}
|
2002-01-20 00:11:00 +08:00
|
|
|
|
|
|
|
|
|
/* exported as recvmsg: standards? */
|
|
|
|
|
extern "C" int
|
|
|
|
|
cygwin_recvmsg(int s, struct msghdr *msg, int flags)
|
|
|
|
|
{
|
|
|
|
|
int ret, nb;
|
|
|
|
|
size_t tot = 0;
|
|
|
|
|
int i;
|
|
|
|
|
char *buf, *p;
|
|
|
|
|
struct iovec *iov = msg->msg_iov;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < msg->msg_iovlen; ++i)
|
|
|
|
|
tot += iov[i].iov_len;
|
|
|
|
|
buf = (char *) malloc(tot);
|
|
|
|
|
if (tot != 0 && buf == NULL) {
|
|
|
|
|
errno = ENOMEM;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
nb = ret = cygwin_recvfrom (s, buf, tot, flags,
|
|
|
|
|
(struct sockaddr *) msg->msg_name, (int *) &msg->msg_namelen);
|
|
|
|
|
p = buf;
|
|
|
|
|
while (nb > 0) {
|
|
|
|
|
ssize_t cnt = min(nb, iov->iov_len);
|
|
|
|
|
|
|
|
|
|
memcpy (iov->iov_base, p, cnt);
|
|
|
|
|
p += cnt;
|
|
|
|
|
nb -= cnt;
|
|
|
|
|
++iov;
|
|
|
|
|
}
|
|
|
|
|
free(buf);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* exported as sendmsg: standards? */
|
|
|
|
|
extern "C" int
|
|
|
|
|
cygwin_sendmsg(int s, const struct msghdr *msg, int flags)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
size_t tot = 0;
|
|
|
|
|
int i;
|
|
|
|
|
char *buf, *p;
|
|
|
|
|
struct iovec *iov = msg->msg_iov;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < msg->msg_iovlen; ++i)
|
|
|
|
|
tot += iov[i].iov_len;
|
|
|
|
|
buf = (char *) malloc(tot);
|
|
|
|
|
if (tot != 0 && buf == NULL) {
|
|
|
|
|
errno = ENOMEM;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
p = buf;
|
|
|
|
|
for (i = 0; i < msg->msg_iovlen; ++i) {
|
|
|
|
|
memcpy (p, iov[i].iov_base, iov[i].iov_len);
|
|
|
|
|
p += iov[i].iov_len;
|
|
|
|
|
}
|
|
|
|
|
ret = cygwin_sendto (s, buf, tot, flags,
|
|
|
|
|
(struct sockaddr *) msg->msg_name, msg->msg_namelen);
|
|
|
|
|
free (buf);
|
|
|
|
|
return ret;
|
2002-01-22 01:47:53 +08:00
|
|
|
|
}
|