static void uv__getnameinfo_work(struct uv__work* w) { uv_getnameinfo_t* req; WCHAR host[NI_MAXHOST]; WCHAR service[NI_MAXSERV]; int ret; req = container_of(w, uv_getnameinfo_t, work_req); if (GetNameInfoW((struct sockaddr*)&req->storage, sizeof(req->storage), host, ARRAY_SIZE(host), service, ARRAY_SIZE(service), req->flags)) { ret = WSAGetLastError(); req->retcode = uv__getaddrinfo_translate_error(ret); return; } ret = WideCharToMultiByte(CP_UTF8, 0, host, -1, req->host, sizeof(req->host), NULL, NULL); if (ret == 0) { req->retcode = uv_translate_sys_error(GetLastError()); return; } ret = WideCharToMultiByte(CP_UTF8, 0, service, -1, req->service, sizeof(req->service), NULL, NULL); if (ret == 0) { req->retcode = uv_translate_sys_error(GetLastError()); } }
/* getnameinfo worker thread implementation */ static DWORD WINAPI getnameinfo_thread_proc(void* parameter) { uv_getnameinfo_t* req = (uv_getnameinfo_t*)parameter; uv_loop_t* loop = req->loop; WCHAR host[NI_MAXHOST]; WCHAR service[NI_MAXSERV]; int ret = 0; assert(req != NULL); ret = GetNameInfoW((struct sockaddr*)&req->storage, sizeof(req->storage), host, sizeof(host), service, sizeof(service), req->flags); req->retcode = uv__getaddrinfo_translate_error(ret); /* convert results to UTF-8 */ WideCharToMultiByte(CP_UTF8, 0, host, -1, req->host, sizeof(req->host), NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, service, -1, req->service, sizeof(req->service), NULL, NULL); /* post getnameinfo completed */ POST_COMPLETION_FOR_REQ(loop, req); return 0; }
static BOOL ResolveTarget(PCWSTR target) { ADDRINFOW hints; int Status; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = Family; hints.ai_flags = AI_NUMERICHOST; Status = GetAddrInfoW(target, NULL, &hints, &Target); if (Status != 0) { hints.ai_flags = AI_CANONNAME; Status = GetAddrInfoW(target, NULL, &hints, &Target); if (Status != 0) { ConResPrintf(StdOut, IDS_UNKNOWN_HOST, target); return FALSE; } wcsncpy(CanonName, Target->ai_canonname, wcslen(Target->ai_canonname)); } else if (ResolveAddress) { Status = GetNameInfoW(Target->ai_addr, Target->ai_addrlen, CanonName, _countof(CanonName), NULL, 0, NI_NAMEREQD); if (Status != 0) { DPRINT("GetNameInfoW failed: %d\n", WSAGetLastError()); } } Family = Target->ai_family; return TRUE; }
static void Ping(void) { PVOID ReplyBuffer = NULL; PVOID SendBuffer = NULL; DWORD ReplySize = 0; DWORD Status; SendBuffer = malloc(RequestSize); if (SendBuffer == NULL) { ConResPrintf(StdErr, IDS_NO_RESOURCES); exit(1); } ZeroMemory(SendBuffer, RequestSize); if (Family == AF_INET6) ReplySize += sizeof(ICMPV6_ECHO_REPLY); else ReplySize += sizeof(ICMP_ECHO_REPLY); ReplySize += RequestSize + SIZEOF_ICMP_ERROR + SIZEOF_IO_STATUS_BLOCK; ReplyBuffer = malloc(ReplySize); if (ReplyBuffer == NULL) { ConResPrintf(StdErr, IDS_NO_RESOURCES); free(SendBuffer); exit(1); } ZeroMemory(ReplyBuffer, ReplySize); EchosSent++; if (Family == AF_INET6) { struct sockaddr_in6 Source; ZeroMemory(&Source, sizeof(Source)); Source.sin6_family = AF_INET6; Status = Icmp6SendEcho2(hIcmpFile, NULL, NULL, NULL, &Source, (struct sockaddr_in6 *)Target->ai_addr, SendBuffer, (USHORT)RequestSize, &IpOptions, ReplyBuffer, ReplySize, Timeout); } else { Status = IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL, ((PSOCKADDR_IN)Target->ai_addr)->sin_addr.s_addr, SendBuffer, (USHORT)RequestSize, &IpOptions, ReplyBuffer, ReplySize, Timeout); } free(SendBuffer); if (Status == 0) { Status = GetLastError(); switch (Status) { case IP_REQ_TIMED_OUT: ConResPrintf(StdOut, IDS_REQUEST_TIMED_OUT); break; default: ConResPrintf(StdOut, IDS_TRANSMIT_FAILED, Status); break; } } else { SOCKADDR_IN6 SockAddrIn6; SOCKADDR_IN SockAddrIn; PSOCKADDR SockAddr; socklen_t Size; EchosReceived++; ZeroMemory(&SockAddrIn, sizeof(SockAddrIn)); ZeroMemory(&SockAddrIn6, sizeof(SockAddrIn6)); if (Family == AF_INET6) { PICMPV6_ECHO_REPLY pEchoReply; PIPV6_ADDRESS_EX Ipv6Addr; pEchoReply = (PICMPV6_ECHO_REPLY)ReplyBuffer; Ipv6Addr = (PIPV6_ADDRESS_EX)&pEchoReply->Address; SockAddrIn6.sin6_family = AF_INET6; CopyMemory(SockAddrIn6.sin6_addr.u.Word, Ipv6Addr->sin6_addr, sizeof(SockAddrIn6.sin6_addr)); //SockAddrIn6.sin6_addr = Ipv6Addr->sin6_addr; SockAddr = (PSOCKADDR)&SockAddrIn6; Size = sizeof(SOCKADDR_IN6); GetNameInfoW(SockAddr, Size, Address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); ConResPrintf(StdOut, IDS_REPLY_FROM, Address); switch (pEchoReply->Status) { case IP_SUCCESS: { EchosSuccessful++; if (pEchoReply->RoundTripTime == 0) ConResPrintf(StdOut, IDS_REPLY_TIME_0MS); else ConResPrintf(StdOut, IDS_REPLY_TIME_MS, pEchoReply->RoundTripTime); if (pEchoReply->RoundTripTime < RTTMin || RTTMin == 0) RTTMin = pEchoReply->RoundTripTime; if (pEchoReply->RoundTripTime > RTTMax || RTTMax == 0) RTTMax = pEchoReply->RoundTripTime; ConPuts(StdOut, L"\n"); RTTTotal += pEchoReply->RoundTripTime; break; } case IP_DEST_NET_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_NET_UNREACHABLE); break; case IP_DEST_HOST_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_HOST_UNREACHABLE); break; case IP_TTL_EXPIRED_TRANSIT: ConResPrintf(StdOut, IDS_TTL_EXPIRED); break; default: ConResPrintf(StdOut, IDS_REPLY_STATUS, pEchoReply->Status); break; } } else { PICMP_ECHO_REPLY pEchoReply; IPAddr *IP4Addr; pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer; IP4Addr = (IPAddr *)&pEchoReply->Address; SockAddrIn.sin_family = AF_INET; SockAddrIn.sin_addr.S_un.S_addr = *IP4Addr; SockAddr = (PSOCKADDR)&SockAddrIn; Size = sizeof(SOCKADDR_IN); GetNameInfoW(SockAddr, Size, Address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); ConResPrintf(StdOut, IDS_REPLY_FROM, Address); switch (pEchoReply->Status) { case IP_SUCCESS: { EchosSuccessful++; ConResPrintf(StdOut, IDS_REPLY_BYTES, pEchoReply->DataSize); if (pEchoReply->RoundTripTime == 0) ConResPrintf(StdOut, IDS_REPLY_TIME_0MS); else ConResPrintf(StdOut, IDS_REPLY_TIME_MS, pEchoReply->RoundTripTime); ConResPrintf(StdOut, IDS_REPLY_TTL, pEchoReply->Options.Ttl); if (pEchoReply->RoundTripTime < RTTMin || RTTMin == 0) RTTMin = pEchoReply->RoundTripTime; if (pEchoReply->RoundTripTime > RTTMax || RTTMax == 0) RTTMax = pEchoReply->RoundTripTime; RTTTotal += pEchoReply->RoundTripTime; break; } case IP_DEST_NET_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_NET_UNREACHABLE); break; case IP_DEST_HOST_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_HOST_UNREACHABLE); break; case IP_TTL_EXPIRED_TRANSIT: ConResPrintf(StdOut, IDS_TTL_EXPIRED); break; default: ConResPrintf(StdOut, IDS_REPLY_STATUS, pEchoReply->Status); break; } } } free(ReplyBuffer); }
/* * @implemented */ INT WSAAPI GetAddrInfoW(IN PCWSTR pszNodeName, IN PCWSTR pszServiceName, IN const ADDRINFOW *ptHints, OUT PADDRINFOW *pptResult) { INT iError = 0; INT iFlags = 0; INT iFamily = PF_UNSPEC; INT iSocketType = 0; INT iProtocol = 0; WORD wPort = 0; DWORD dwAddress = 0; PSERVENT ptService = NULL; PCHAR pc = NULL; BOOL bClone = FALSE; WORD wTcpPort = 0; WORD wUdpPort = 0; WCHAR CanonicalName[0x42]; CHAR AnsiServiceName[256]; CHAR AnsiNodeName[256]; DPRINT("GetAddrInfoW: %S, %S, %p, %p\n", pszNodeName, pszServiceName, ptHints, pptResult); /* Assume error */ *pptResult = NULL; /* We must have at least one name to work with */ if (!(pszNodeName) && !(pszServiceName)) { /* Fail */ SetLastError(EAI_NONAME); return EAI_NONAME; } /* Check if we got hints */ if (ptHints) { /* Make sure these are empty */ if ((ptHints->ai_addrlen) || (ptHints->ai_canonname) || (ptHints->ai_addr) || (ptHints->ai_next)) { /* Fail if they aren't */ SetLastError(EAI_FAIL); return EAI_FAIL; } /* Save the flags and validate them */ iFlags = ptHints->ai_flags; if ((iFlags & AI_CANONNAME) && !pszNodeName) { SetLastError(EAI_BADFLAGS); return EAI_BADFLAGS; } /* Save family and validate it */ iFamily = ptHints->ai_family; if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET)) { SetLastError(EAI_FAMILY); return EAI_FAMILY; } /* Save socket type and validate it */ iSocketType = ptHints->ai_socktype; if ((iSocketType != 0) && (iSocketType != SOCK_STREAM) && (iSocketType != SOCK_DGRAM) && (iSocketType != SOCK_RAW)) { SetLastError(EAI_SOCKTYPE); return EAI_SOCKTYPE; } /* Save the protocol */ iProtocol = ptHints->ai_protocol; } /* Check if we have a service name */ if (pszServiceName) { /* We need to convert it to ANSI */ WideCharToMultiByte(CP_ACP, 0, pszServiceName, -1, AnsiServiceName, sizeof(AnsiServiceName), NULL, 0); /* Get the port */ wPort = (WORD)strtoul(AnsiServiceName, &pc, 10); /* Check if the port string is numeric */ if (*pc == '\0') { /* Get the port directly */ wPort = wTcpPort = wUdpPort = htons(wPort); #if 0 /* Check if this is both TCP and UDP */ if (iSocketType == 0) { /* Set it to TCP for now, but remember to clone */ bClone = TRUE; iSocketType = SOCK_STREAM; } #endif } else { wPort = 0; /* The port name was a string. Check if this is a UDP socket */ if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM)) { /* It's UDP, do a getservbyname */ ptService = getservbyname(AnsiServiceName, "udp"); /* If we got a servent, return the port from it */ if (ptService) wPort = wUdpPort = ptService->s_port; } /* Check if this is a TCP socket */ if ((iSocketType == 0) || (iSocketType == SOCK_STREAM)) { /* It's TCP, do a getserbyname */ ptService = getservbyname(AnsiServiceName, "tcp"); /* Return the port from the servent */ if (ptService) wPort = wTcpPort = ptService->s_port; } /* If we got 0, then fail */ if (wPort == 0) { SetLastError(EAI_SERVICE); return EAI_SERVICE; } /* Check if this was for both */ if (iSocketType == 0) { /* Do the TCP case right now */ if (wTcpPort && !wUdpPort) iSocketType = SOCK_STREAM; if (!wTcpPort && wUdpPort) iSocketType = SOCK_DGRAM; //bClone = (wTcpPort && wUdpPort); } } } /* Check if no node was given or if this is is a valid IPv4 address */ if ((!pszNodeName) || (ParseV4Address(pszNodeName, &dwAddress))) { /* Check if we don't have a node name */ if (!pszNodeName) { /* Make one up based on the flags */ dwAddress = htonl((iFlags & AI_PASSIVE) ? INADDR_ANY : INADDR_LOOPBACK); } /* Create the Addr Info */ *pptResult = NewAddrInfo(iSocketType, iProtocol, wPort, dwAddress); /* If we didn't get one back, assume out of memory */ if (!(*pptResult)) iError = EAI_MEMORY; /* Check if we have success and a nodename */ if (!iError && pszNodeName) { /* Set AI_NUMERICHOST since this is a numeric string */ (*pptResult)->ai_flags |= AI_NUMERICHOST; /* Check if the canonical name was requested */ if (iFlags & AI_CANONNAME) { /* Get the canonical name */ GetNameInfoW((*pptResult)->ai_addr, (socklen_t)(*pptResult)->ai_addrlen, CanonicalName, 0x41, NULL, 0, 2); /* Allocate memory for a copy */ (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 0, wcslen(CanonicalName)); if (!(*pptResult)->ai_canonname) { /* No memory for the copy */ iError = EAI_MEMORY; } else { /* Duplicate the string */ RtlMoveMemory((*pptResult)->ai_canonname, CanonicalName, wcslen(CanonicalName)); } } } } else if (iFlags & AI_NUMERICHOST) { /* No name for this request (we have a non-numeric name) */ iError = EAI_NONAME; } else { /* We need to convert it to ANSI */ WideCharToMultiByte(CP_ACP, 0, pszNodeName, -1, AnsiNodeName, sizeof(AnsiNodeName), NULL, 0); /* Non-numeric name, do DNS lookup */ iError = LookupAddressForName(AnsiNodeName, iSocketType, iProtocol, wPort, (iFlags & AI_CANONNAME), pptResult); } /* If all was good and the caller requested UDP and TCP */ if (!iError && bClone) { /* Process UDP now, we already did TCP */ iError = CloneAddrInfo(wUdpPort, *pptResult); } /* If we've hit an error till here */ if (iError) { /* Free the address info and return nothing */ FreeAddrInfoW(*pptResult); *pptResult = NULL; } /* Return to caller */ SetLastError(iError); return iError; }