📄 net.cc
字号:
/* net.cc: network-related routines. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license. Please consult the file "CYGWIN_LICENSE" fordetails. *//* #define DEBUG_NEST_ON 1 */#define __INSIDE_CYGWIN_NET__#include "winsup.h"#include <errno.h>#include <sys/socket.h>#include <sys/un.h>#include <iphlpapi.h>#include <stdlib.h>#include <unistd.h>#include <netdb.h>#define USE_SYS_TYPES_FD_SET#include <winsock2.h>#include "cygerrno.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "cygheap.h"#include "sigproc.h"#include "pinfo.h"#include "registry.h"#include "wsock_event.h"extern "C"{ 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 */LPWSAOVERLAPPEDwsock_event::prepare (){ LPWSAOVERLAPPED ret = NULL; SetLastError (0); if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT) { memset (&ovr, 0, sizeof ovr); ovr.hEvent = event; ret = &ovr; } else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */ WSASetLastError (0); debug_printf ("%d = wsock_event::prepare ()", ret); return ret;}intwsock_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: if (!CancelIo ((HANDLE) socket)) { debug_printf ("CancelIo() %E, fallback to blocking io"); WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags); } else WSASetLastError (WSAEINTR); break; case WSA_WAIT_FAILED: break; default: /* Should be impossible. *LOL* */ WSASetLastError (WSAEFAULT); break; } WSACloseEvent (event); event = NULL; return ret;}WSADATA wsadata;static fhandler_socket *get (const int fd){ cygheap_fdget cfd (fd); if (cfd < 0) return 0; fhandler_socket *const fh = cfd->is_socket (); if (!fh) set_errno (ENOTSOCK); return fh;}static SOCKET __stdcallset_socket_inheritance (SOCKET sock){ SOCKET osock = sock; if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) system_printf ("DuplicateHandle failed %E"); else debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock); return sock;}/* htonl: standards? */extern "C" unsigned long inthtonl (unsigned long int x){ return ((((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)));}/* ntohl: standards? */extern "C" unsigned long intntohl (unsigned long int x){ return htonl (x);}/* htons: standards? */extern "C" unsigned shorthtons (unsigned short x){ return ((((x & 0x000000ffU) << 8) | ((x & 0x0000ff00U) >> 8)));}/* ntohs: standards? */extern "C" unsigned shortntohs (unsigned short x){ return htons (x);}static voiddump_protoent (struct protoent *p){ if (p) debug_printf ("protoent %s %x %x", p->p_name, p->p_aliases, p->p_proto);}/* exported as inet_ntoa: BSD 4.3 */extern "C" char *cygwin_inet_ntoa (struct in_addr in){#ifdef _MT_SAFE#define ntoa_buf _reent_winsup ()->_ntoa_buf#else static char *ntoa_buf = NULL;#endif char *res = inet_ntoa (in); if (ntoa_buf) { free (ntoa_buf); ntoa_buf = NULL; } if (res) ntoa_buf = strdup (res); return ntoa_buf;}/* exported as inet_addr: BSD 4.3 */extern "C" unsigned longcygwin_inet_addr (const char *cp){ if (check_null_str_errno (cp)) return INADDR_NONE; unsigned long res = inet_addr (cp); return res;}/* 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" intcygwin_inet_aton (const char *cp, struct in_addr *inp){ if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp)) return 0; unsigned long res = inet_addr (cp); if (res == INADDR_NONE && strcmp (cp, "255.255.255.255")) return 0; if (inp) inp->s_addr = res; return 1;}/* undocumented in wsock32.dll */extern "C" unsigned int WINAPI inet_network (const char *);extern "C" unsigned intcygwin_inet_network (const char *cp){ if (check_null_str_errno (cp)) return INADDR_NONE; unsigned int res = inet_network (cp); return res;}/* 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. */extern "C" unsigned longinet_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. */extern "C" struct in_addrinet_makeaddr (int net, int lna){ unsigned long i; struct in_addr in; 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;};static NO_COPY struct tl errmap[] = { {WSAEINTR, "WSAEINTR", EINTR}, {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}, {0, "NOERROR", 0}, {0, NULL, 0}};static intfind_winsock_errno (int why){ for (int i = 0; errmap[i].s != NULL; ++i) if (why == errmap[i].w) return errmap[i].e; return EPERM;}void__set_winsock_errno (const char *fn, int ln){ 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);}/* * Since the member `s' isn't used for debug output we can use it * for the error text returned by herror and hstrerror. */static NO_COPY struct tl host_errmap[] = { {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}, {0, NULL, 0}};static voidset_host_errno (){ int i; int why = WSAGetLastError (); for (i = 0; host_errmap[i].w != 0; ++i) if (why == host_errmap[i].w) break; if (host_errmap[i].w != 0) h_errno = host_errmap[i].e; else h_errno = NETDB_INTERNAL;}static voidfree_char_list (char **clist){ if (clist) { for (char **cl = clist; *cl; ++cl) free (*cl); 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;}#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; 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))) return NULL; memcpy (dst[cnt], src[cnt], size); } return dst;}static voidfree_protoent_ptr (struct protoent *&p){ if (p) { debug_printf ("protoent: %s", p->p_name); if (p->p_name) free (p->p_name); 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;}#ifdef _MT_SAFE#define protoent_buf _reent_winsup ()->_protoent_buf#elsestatic struct protoent *protoent_buf = NULL;#endif/* exported as getprotobyname: standards? */extern "C" struct protoent *cygwin_getprotobyname (const char *p){ if (check_null_str_errno (p)) return NULL; free_protoent_ptr (protoent_buf); protoent_buf = dup_protoent_ptr (getprotobyname (p)); if (!protoent_buf) set_winsock_errno (); dump_protoent (protoent_buf); return protoent_buf;}/* exported as getprotobynumber: standards? */extern "C" struct protoent *cygwin_getprotobynumber (int number){ free_protoent_ptr (protoent_buf); protoent_buf = dup_protoent_ptr (getprotobynumber (number)); if (!protoent_buf) set_winsock_errno (); dump_protoent (protoent_buf); return protoent_buf;}fhandler_socket *fdsock (int &fd, const char *name, SOCKET soc){ if (!winsock2_active) soc = set_socket_inheritance (soc); else if (wincap.has_set_handle_information ()) { /* NT systems apparently set sockets to inheritable by default */ SetHandleInformation ((HANDLE) soc, HANDLE_FLAG_INHERIT, 0); debug_printf ("reset socket inheritance since winsock2_active %d", winsock2_active); } else debug_printf ("not setting socket inheritance since winsock2_active %d", winsock2_active); fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name); fh->set_io_handle ((HANDLE) soc); fh->set_flags (O_RDWR | O_BINARY); fh->set_r_no_interrupt (winsock2_active); debug_printf ("fd %d, name '%s', soc %p", fd, name, soc); return fh;}/* exported as socket: standards? */extern "C" intcygwin_socket (int af, int type, int protocol){ int res = -1; SOCKET soc = 0; fhandler_socket *fh = NULL; cygheap_fdnew fd; if (fd >= 0) { debug_printf ("socket (%d, %d, %d)", af, type, protocol); soc = socket (AF_INET, type, af == AF_LOCAL ? 0 : protocol); if (soc == INVALID_SOCKET) { set_winsock_errno (); goto done; } const char *name; if (af == AF_INET) name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp"); else name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket"); fh = fdsock (fd, name, soc); if (fh) { fh->set_addr_family (af); fh->set_socket_type (type); } res = fd; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -