Could not make getnameinfo working on my UDP code - c++

I have the following UDP client communication code:
clUDPPort::clUDPPort(int prt,string hostname){ //client
nServerPort = prt;
szHostName = hostname;
nSocketId = socket (AF_INET , SOCK_DGRAM, 0 ) ;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(nServerPort) ;
host = gethostbyname(szHostName.c_str()) ;
memcpy( (char*)&serverAddr.sin_addr,(char*) host->h_addr , host->h_length ) ;
//nSize = sizeof(serverAddr);
}
This code is part of a CGI application that is installed on an embedded linux device. When testing on my PC, the host name is passed as local address like 192.168.2.50, when deployed to the device the host name is 127.0.0.1 because there is a service program that my application connects with.
The problem is a linking warning saying:
/home/abdalla/XML_Communication/udpport.cpp:24: warning: gethostbyname is obsolescent, use getnameinfo() instead.
This is generated by KDevelop 4.7 on openSUSE 13.2 64-bit. I tried to use getnameinfo but could not figure out how to make it work because according to the documentation it asks for host name and server name. Apparently in my code the host and the server are the same. Can you help me making getnameinfo working for my code ? Thanks.

What you actually need to translate a name into address is probably getaddrinfo. See the linux man page for details which include sample code.

Here is my code which is using getaddrinfo().
///the common socket address. we will use this structure to describe all Internet address.
struct nw_sockaddr_t
{
struct sockaddr addr; //currently 16 bytes
unsigned int addrlen;
};
bool nw_sock_addr_fill(nw_sockaddr_t& addr, const char* node, const char* service)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = addr.addr.sa_family;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo* ai = NULL, *ai_o = NULL;
bool good = false;
do
{
if(0!=getaddrinfo(node, service, &hints, &ai))
break;
ai_o = ai;
if(NULL!=ai)
{
if(NULL==ai->ai_next)
{
memcpy(&addr.addr, ai->ai_addr, sizeof(addr.addr));
addr.addrlen = ai->ai_addrlen;
good = true;
}
else
{
while(NULL!=ai->ai_next)
{
if(ai->ai_family==AF_INET || ai->ai_family==AF_INET6)
break;
ai = ai->ai_next;
}
if(NULL!=ai)
ai = ai_o;
memcpy(&addr.addr, ai->ai_addr, sizeof(addr.addr));
addr.addrlen = ai->ai_addrlen;
good = true;
}
}
}while(false);
if(NULL!=ai_o)
freeaddrinfo(ai_o);
if(good)
{
if(AF_INET==addr.addr.sa_family)
{
struct sockaddr_in* in = (sockaddr_in*)(&addr.addr);
if(0==in->sin_port)
in->sin_port = htons(ut_n2u32(service, strlen(service)));
}
else if(AF_INET6==addr.addr.sa_family)
{
struct sockaddr_in6* in = (sockaddr_in6*)(&addr.addr);
if(0==in->sin6_port)
in->sin6_port = htons(ut_n2u32(service, strlen(service)));
}
}
return good;
}
Usage:
nw_sockaddr_t addr;
if(nw_sock_addr_fill(addr, "127.0.0.1", "80"))
{
//here you will get the ipv4 address
struct sockaddr_in* addr_in = (struct sockaddr_in*)(&addr.addr);
}

Related

Obtaining a MAC address via IPv6 request

I'm trying to ping over IPv6, I need it to get a MAC address from a remote host. As far as I understand, IPv6 does not use the ARP table, but with the help of the so-called ICMPv6 it is possible to get the MAC address, I used tcpdump and saw MAC addresses. If I'm wrong about something, please correct me.
So, I am using Windows and C++,I'm trying to use the Icmp6SendEcho2() function from IcmpAPI.h
and ran into an error 11050 which says that "IP_GENERAL_FAILURE, A general failure. This error can be returned for some malformed ICMP packets.", and I don't know what to do next.
ULONG icmpReplyCount = 0;
HANDLE icmpHandle = INVALID_HANDLE_VALUE;
CHAR icmpEchoBuffer[2048] = { 0 };
IP_OPTION_INFORMATION pingOptions = { 255, 0, IP_FLAG_DF, 0 };
CHAR icmpReplyBuffer [2048];
ULONG icmpReplyLength = 0;
DWORD timeout = 5;
DWORD lastErr = 0;
icmpHandle = Icmp6CreateFile();
struct sockaddr_storage sockStoreLocal = {};
sockaddr_in6* icmp6LocalAddr = (struct sockaddr_in6*)&sockStoreLocal;
icmp6LocalAddr->sin6_family = AF_INET6;
icmp6LocalAddr->sin6_flowinfo = 0;
icmp6LocalAddr->sin6_port = htons(0);
inet_pton(AF_INET6, "fc00:1:1::48", &icmp6LocalAddr->sin6_addr);
struct sockaddr_storage sockStoreRemoute = {};
sockaddr_in6* icmp6RemoteAddr = (struct sockaddr_in6*)&sockStoreRemoute;
icmp6RemoteAddr->sin6_family = AF_INET6;
icmp6RemoteAddr->sin6_port = htons(58);
inet_pton(AF_INET6, "fc00:1:1::109", &icmp6RemoteAddr->sin6_addr);
icmpReplyCount = Icmp6SendEcho2(icmpHandle, NULL, NULL, NULL, icmp6LocalAddr, icmp6RemoteAddr, icmpEchoBuffer, sizeof(icmpEchoBuffer), &pingOptions, icmpReplyBuffer, sizeof(icmpReplyBuffer), timeout);
lastErr = GetLastError();
Maybe I'm converting the IPv6 address incorrectly or what I'm doing wrong with the buffers.
icmpReplyCount = 0 and lastErr = 11050
I found the answer, the buffers were not large enough, I increased the size and everything worked, no errors returned)))

Invalid argument error for sendmsg() on some FreeBSD systems

I have code to send a UDP packet from a specific source IP (see below).
This worky nicely on all system I tried so far, including FreeBSD.
Unfortunately on a client system sendmsg() fails with "invalid argument" error and I'm unable to figure out why.
The FreeBSD versions are the same, tests on all system use the same kind of IPv4 addresses for source and destination.
I did a ktrace, but only shows part of the paramers used (the sockaddr_in6), but those seem fine. Valgrind also didn't complain (on my system).
How do I find this ? Is there a tool that displays the full msghdr struct for sendmsg() calls ?
Update: Please focus on the tools or techniques I could use. You can look at the code snippet, but it won't compile without the surounding code.
ssize_t UDPSendWithSourceIP(int fd, void * data, size_t len, const sockaddr_in6 & toAddress)
{
struct sockaddr_in6 dest = toAddress;
// set source address
PIPSocket::Address src = RasServer::Instance()->GetLocalAddress(toIP);
struct msghdr msgh = { };
struct cmsghdr *cmsg;
struct iovec iov = { };
char cbuf[256];
memset(&cbuf, 0, sizeof(cbuf));
// Set up iov and msgh structures
memset(&msgh, 0, sizeof(struct msghdr));
iov.iov_base = data;
iov.iov_len = len;
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
msgh.msg_name = (struct sockaddr*)&dest;
// must pass short len when sending to IPv4 address on Solaris 11, OpenBSD and NetBSD
// sizeof(dest) is OK on Linux and FreeBSD
size_t addr_len = sizeof(sockaddr_in);
if (toIP.GetVersion() == 6)
addr_len = sizeof(sockaddr_in6);
msgh.msg_namelen = addr_len;
if ((((struct sockaddr*)&dest)->sa_family == AF_INET6)) {
struct in6_pktinfo *pkt;
msgh.msg_control = cbuf;
msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
cmsg = CMSG_FIRSTHDR(&msgh);
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
memset(pkt, 0, sizeof(*pkt));
pkt->ipi6_addr = src;
msgh.msg_controllen = cmsg->cmsg_len;
} else
{
#ifdef IP_SENDSRCADDR // FreeBSD
struct in_addr *in;
msgh.msg_control = cbuf;
msgh.msg_controllen = CMSG_SPACE(sizeof(*in));
cmsg = CMSG_FIRSTHDR(&msgh);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_SENDSRCADDR;
cmsg->cmsg_len = CMSG_LEN(sizeof(*in));
in = (struct in_addr *) CMSG_DATA(cmsg);
*in = src;
#endif // IP_SENDSRCADDR
}
ssize_t bytesSent = sendmsg(fd, &msgh, 0);
if (bytesSent < 0) {
cerr << "RTP\tSend error " << strerror(errno) << endl;
}
return bytesSent;
}
It turns out FreeBSD is very picky when it allows the use of IP_SENDSRCADDR on a UDP socket. If the socket is bound to INADDR_ANY my code works fine. If the socket is bound to a single IP, then sendmsg() returns EINVAL (invalid argument).

getaddrinfo returns previous fixed IP address

Context: My C++ application needs to know on which computer it is running in order to do specific behavior. So my application gets the IP address of the computer and then check that address in a configuration file with an IP list in order to determine the computer's role. All computers have a fixed IP address. I am using gethostname, getaddrinfo and inet_ntop in order to do that.
Problem: On some target platform's computers, getaddrinfo returns the old IP address (the address before I set the fixed value). But if I am doing "ipconfig" in the cmd, the expected fixed value is shown. It is also pingable by other computers. All computers have only 1 network card, IPv6 is disabled.
Platform: Windows 7 x64.
IDE: Visual Studio 2015.
I would like to have the actual fixed IP address.
Thank you for your help!
Code sample:
// [Some stuff...]
addrinfo hints;
addrinfo *pResults;
int returnedCode;
char hostName[1024];
if (0 != (returnedCode = gethostname(hostName, sizeof hostName)))
{
// Error handling stuff.
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // Only want IPv4.
hints.ai_socktype = SOCK_DGRAM; // UDP stream sockets.
hints.ai_flags = AI_PASSIVE; // Fill in my IP for me.
if (0 != (returnedCode = getaddrinfo(hostName, NULL, &hints, &pResults)))
{
// Error handling.
}
struct addrinfo* res;
char buffer[INET_ADDRSTRLEN];
std::string localIP;
for (res = pResults; res != NULL; res = res->ai_next)
{
if (res->ai_family == AF_INET)
{
const char* ip = inet_ntop(AF_INET,
&((struct sockaddr_in *)res->ai_addr)->sin_addr, buffer, INET_ADDRSTRLEN);
if ((NULL == ip) || (nullptr == ip))
{
// Error handling.
}
else
{
localIP = std::string(ip);
}
}
}
freeaddrinfo(pResults); // free the linked-list
WSACleanup();
// [More stuff...]

iOS sockets IPv6 Support

I am getting an error when I try to connect to my ipv4 server. Currently the ios app users are required to enter their sever's an IP address, port, and account information.
The ios app then calls Connect on the SocketSender class (included in the header search path) which in turns calls the connect function of Socket.h and then checks the results.
Connect - SocketSender.cpp
bool SocketSender::Connect (const char *host, int port, CApiError &err)
{
errno = 0;
struct hostent *hostinfo;
hostinfo = gethostbyname (host);
if (!hostinfo) {
#ifdef PLATFORM_WIN32
m_nLastErrorNo = SOCKET_ERRNO();
err.SetSystemError(m_nLastErrorNo);
#else
/* Linux stores the gethostbyname error in h_errno. */
m_nLastErrorNo = EINVAL; // h_errno value is incompatible with the "normal" error codes
err.SetError(FIX_SN(h_errno, hstrerror(h_errno)), CATEGORY_SYSTEM | ERR_TYPE_ERROR);
#endif
return false;
}
socket_fd = socket (AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1) {
m_nLastErrorNo = SOCKET_ERRNO();
err.SetSystemError(m_nLastErrorNo);
return false;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons (port);
address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
int result;
SetSocketOptions();
result = connect (socket_fd, (struct sockaddr *) &address, sizeof (address));
if (result == -1) {
if (IS_IN_PROGRESS()) {
fd_set f1,f2,f3;
struct timeval tv;
/* configure the sets */
FD_ZERO(&f1);
FD_ZERO(&f2);
FD_ZERO(&f3);
FD_SET(socket_fd, &f2);
FD_SET(socket_fd, &f3);
/* we will have a timeout period */
tv.tv_sec = 5;
tv.tv_usec = 0;
int selrez = select(socket_fd + 1,&f1,&f2,&f3,&tv);
if (selrez == -1) { // socket error
m_nLastErrorNo = SOCKET_ERRNO();
Disconnect(true);
err.SetSystemError(m_nLastErrorNo);
return false;
}
if (FD_ISSET(socket_fd, &f3)) { // failed to connect ..
int sockerr = 0;
#ifdef PLATFORM_WIN32
int sockerr_len = sizeof(sockerr);
#else
socklen_t sockerr_len = sizeof(sockerr);
#endif
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &sockerr_len);
if (sockerr != 0) {
m_nLastErrorNo = sockerr;
} else {
#ifdef PLATFORM_WIN32
m_nLastErrorNo = ERROR_TIMEOUT; // windows actually does not specify the error .. is this ok?
#else
m_nLastErrorNo = ETIMEDOUT;
#endif
}
Disconnect(true);
err.SetSystemError(m_nLastErrorNo);
return false;
}
if (!FD_ISSET(socket_fd, &f2)) { // cannot read, so some (unknown) error occured (probably time-out)
int sockerr = 0;
#ifdef PLATFORM_WIN32
int sockerr_len = sizeof(sockerr);
#else
socklen_t sockerr_len = sizeof(sockerr);
#endif
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &sockerr_len);
if (sockerr != 0) {
m_nLastErrorNo = sockerr;
} else {
#ifdef PLATFORM_WIN32
m_nLastErrorNo = ERROR_TIMEOUT; // windows actually does not specify the error .. is this ok?
#else
m_nLastErrorNo = ETIMEDOUT;
#endif
}
Disconnect(true);
err.SetSystemError(m_nLastErrorNo);
return false;
}
#ifndef PLATFORM_WIN32 // FIXME: is the same needed for windows ?
// unix always marks socket as "success", however error code has to be double-checked
int error = 0;
socklen_t len = sizeof(error);
if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
err.SetSystemError();
return false;
}
if(error != 0) {
m_nLastErrorNo = error;
Disconnect(true);
err.SetSystemError(m_nLastErrorNo);
return false;
}
#endif
} else {
m_nLastErrorNo = SOCKET_ERRNO();
Disconnect(true);
err.SetSystemError(m_nLastErrorNo);
return false;
}
}
m_nIP = ntohl(address.sin_addr.s_addr);
m_bServerSocket = false;
return true;
}
That is the original version that worked without any problems. When i changed the above to use AF_INET6 and in_addr6->sin6_addr, i kept getting errors and the application failed to connect. I tried using getaddrinfo but this still did not connect.
struct addrinfo hints, *res, *res0;
int error;
const char *cause = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
error = getaddrinfo(host, "PORT", &hints, &res0);
if (error) {
errx(1, "%s", gai_strerror(error));
/*NOTREACHED*/
}
socket_fd = -1;
printf("IP addresses for %s:\n\n", host);
int result;
void *addr;
char *ipver;
for (res = res0; res!=NULL; res = res->ai_next) {
socket_fd = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (socket_fd < 0) {
cause = "socket";
continue;
}
if ((result = connect(socket_fd, res->ai_addr, res->ai_addrlen)) < 0) {
cause = "connect";
close(socket_fd);
socket_fd = -1;
continue;
}
// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (res->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
SetSocketOptions();
break; /* okay we got one */
}
I need to make it backwards compatible with ipv6 and ipv4. Any help would be much appreciated as i have been stuck testing this for the past week. Also if anyone knows how to debug the SocketSender.cpp on XCode that would be alot of help.
So after two weeks of testing out different approaches and familiarizing myself with networking (POSIX) I finally got this to work mainly due to #user102008 suggestion.
This is relevant to Client-Server applications.My application is a client application that connects to a IPv4 server/system at a remote location. We have yet to support IPv6 for our products which include clients(iOS,android,windows,unix) and servers (windows & unix), but will support upon future releases. The reason for this support was solely due to Apple changing their apple review process environment.
Approach, Tips and Issues
Apple has provided a way to test IPv6 compatibility with your app. This is sharing your connection from your Ethernet using NAT64/DNS64. This failed many times for me. After researching and resetting my SMC, I came across this article and realized i may have been messing with the configuration too much. So I reset my SMC, restarted and created the internet sharing host. Always remember to turn off WiFi before making any changes to internet sharing.
Users were required to connect to the server with a IPv4 IP address. The Application ran perfectly on an IPv4 networking but failed in an IPv6 network. This was due to the app not resolving the IP address literal. The networking library my application uses was a cpp library that was included as a preprocess macro. One of the biggest annoyance was trying to debug, because you cant debug compile time code. So what I did was move over my cpp files with their headers to the project (luckily it was only 3 files).
IMPORTANT TO AYONE PASSING PORT NUMBERS. This is tied to #2 and resolving the IPv4 literal. I used apples exact implementation on the networking overview (listing 10-1). Every time i tested, the connect function was returning -1, meaning it did not connect. Thanks to #user102008 providing me with this article, I realized apple implementation of getaddrinfo was broken when trying to pass a string literal for the port. Yes, they ask for a constant char, even when trying c_str() it would still return port number of 0. For this reason, an apple developer who Ive noticed answer and addresses countless networking problems provided a work around. This fixed my issue of the port continuously returning 0, code is posted below as well. What i did, was simply add this into my networking class (SocketSender.cpp) and instead of calling getaddrinfo in Connect, i called get getaddrinfo_compat. This allowed me to connect perfectly in IPv4 and IPv6 networks.
static int getaddrinfo_compat(
const char * hostname,
const char * servname,
const struct addrinfo * hints,
struct addrinfo ** res
) {
int err;
int numericPort;
// If we're given a service name and it's a numeric string, set `numericPort` to that,
// otherwise it ends up as 0.
numericPort = servname != NULL ? atoi(servname) : 0;
// Call `getaddrinfo` with our input parameters.
err = getaddrinfo(hostname, servname, hints, res);
// Post-process the results of `getaddrinfo` to work around <rdar://problem/26365575>.
if ( (err == 0) && (numericPort != 0) ) {
for (const struct addrinfo * addr = *res; addr != NULL; addr = addr->ai_next) {
in_port_t * portPtr;
switch (addr->ai_family) {
case AF_INET: {
portPtr = &((struct sockaddr_in *) addr->ai_addr)->sin_port;
} break;
case AF_INET6: {
portPtr = &((struct sockaddr_in6 *) addr->ai_addr)->sin6_port;
} break;
default: {
portPtr = NULL;
} break;
}
if ( (portPtr != NULL) && (*portPtr == 0) ) {
*portPtr = htons(numericPort);
}
}
}
return err;
}
I actually save IP (address.sin_addr.s_addr) in a long data type that is a private variable, m_nIP. problem was i didnt need the IPv6 as our entire product groups use IPv4. Solved this using the code is below.
const uint8_t *bytes = ((const struct sockaddr_in6 *)addrPtr)->sin6_addr.s6_addr;
bytes += 12;
struct in_addr addr = { *(const in_addr_t *)bytes };
m_nIP = ntohl(addr.s_addr);
RELEVANT GUIDES Beej's Guide to Network Programming, UserLevel IPv6 Intro, Porting Applications to IPv6

WinSock bind before connects results in WSAEADDRNOTAVAIL - The requested address is not valid in its context

I needed to open a socket from a specific local network card using WinSock. I asked about this and got an answer here. In short, the answer advises that you first bind to the local interface, then call connect.
However, when I do this, I get a WSAEADDRNOTAVAIL (10049) "The requested address is not valid in its context.". Why is this?
Assuming the sample code below is part of an application running on the local box 192.168.1.3 and is attempting to connect to remote server 192.168.1.4. I've checked and double-checked that the local and remote addresses are correct. I can ping both ways (from local to remote and remote to local).
I've tried ports other than 0 for the local; no difference. If I remove the bind before the connect, it then works, but I'm then not able to specify a network interface.
So, any idea why I keep getting WSAEADDRNOTAVAIL ?
addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;
addrinfo *localaddr = NULL;
getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
freeaddrinfo(localaddr);
addrinfo remotehints = {0};
remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
remotehints.ai_family = AF_INET;
remotehints.ai_socktype = SOCK_STREAM;
remotehints.ai_protocol = IPPROTO_TCP;
addrinfo *remoteaddr = NULL;
getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
freeaddrinfo(remoteaddr);
EDIT: This sample code intentionally has no error checking, so that my intent could be communicated in the most efficient way.
EDIT 2: A bind to 192.168.1.3 causes connect to fail. A bind to 127.0.0.1 works. Yes, I'm 100% sure that 192.168.1.3 is the correct local IP.
EDIT 3: Right! On a whim, I tried the test app on my home PC and it works fine. So, at least the code does work, and the trouble must be related to my work PC.
OK, turns out #claptrap was right.
I had disabled my firewall, but unknown to me, our IT department has some other firewally-thingy tightly integrated into the enterprise virus scanner (which I can't uninstall or disable). Once I managed to get IT to temporarily disabled it, everything worked as expected.
Always check error codes when calling API functions, eg:
addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;
addrinfo *localaddr = NULL;
int ret = getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
if (ret == 0)
{
ret = bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
freeaddrinfo(localaddr);
if (ret == 0)
{
addrinfo remotehints = {0};
remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
remotehints.ai_family = AF_INET;
remotehints.ai_socktype = SOCK_STREAM;
remotehints.ai_protocol = IPPROTO_TCP;
addrinfo *remoteaddr = NULL;
ret = getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
if (ret == 0)
{
ret = connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
freeaddrinfo(remoteaddr);
if (ret == 0)
{
// connect succeeded...
// can use getsockname() here to discover which port was actually bound to, if needed.
// On some OS versions, bind() does not perform the actual binding immediately,
// connect() does the actual binding instead since it can make more informed choices based on the target address being connected to...
}
else
{
// connect failed...
}
}
else
{
// getaddrinfo() failed
}
}
else
{
// bind failed
}
}
else
{
// getaddrinfo() failed...
}
How far does the code actually get?