trouble accepting ipv6 requests on c web server - c

The following c function I wrote returns a file descriptor that accepts IPv4 connections but not IPv6.
Could someone help me figure out what went wrong?
I suspect I did not use getaddrinfo() correctly.
Open file descriptor that listens to connections.
/*
* open_listenfd - open and return a listening socket on port
* Returns -1 and sets errno on Unix error.
*/
int open_listenfd(int port)
{
const char* hostname=0;
// Converts port to string
char* pName = malloc(numPlaces(port) + 1);
sprintf(pName, "%d", port);
const char* portname= pName;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol= 0;
hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG;
struct addrinfo* res=0;
int err=getaddrinfo(hostname,portname,&hints,&res);
free(pName);
if (err!=0) {
return -1;
}
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(res->ai_family,res->ai_socktype, res->ai_protocol)) < 0)
return -1;
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = /*AF_INET;*/ AF_UNSPEC;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, res->ai_addr, res->ai_addrlen/*(SA *)&serveraddr, sizeof(serveraddr)*/) < 0)
return -1;
freeaddrinfo(res);
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, 1024) < 0)
return -1;
return listenfd;
}

If you want your server to listen on IPV4 and IPV6 addresses you need to could set up two socket to listen on.
getaddrinfo() might return information for more then one internet address for given host and/or service.
The member ai_family of the hints structure passed specifies which address family the caller is interest in. If AF_UNSPEC is specified IPV4 and IPV6 addresses might be returned.
To find out if there are such addresses available you might like to mod you code like so:
int open_listenfd(int port, int * pfdSocketIpV4, int * pfdSocketIpV6)
{
...
struct addrinfo hints = {0};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE|AI_ADDRCONFIG;
hints.ai_next = NULL;
struct addrinfo * res = NULL;
int err=getaddrinfo(hostname, portname, &hints, &res);
free(pName);
if (err)
{
return -1;
}
struct addrinfo * pAddrInfoIpV4 = NULL;
struct addrinfo * pAddrInfoIpV6 = NULL;
{
struct addrinfo * pAddrInfo = res;
/* Loop over all address infos found until a IPV4 and a IPV6 address is found. */
while (pAddrInfo)
{
if (!pAddrInfoIpV4 && AF_INET == pAddrInfo->ai_family)
{
pAddrInfoIpV4 = pAddrInfo; /* Take first IPV4 address available */
}
else if (!pAddrInfoIpV6 && AF_INET6 == pAddrInfo->ai_family)
{
pAddrInfoIpV6 = pAddrInfo; /* Take first IPV6 address available */
}
else
{
break; /* Already got an IPV4 and IPV6 address, so skip the rest */
}
pAddrInfo= pAddrInfo->ai_next; /* Get next address info, if any */
}
}
if (pAddrInfoIpV4)
{
... /* create, bind and make IPV4 socket listen */
int fdSocketIpV4 = socket(pAddrInfoIpV4->ai_family,...
*pfdSocketIpV4 = fdSocketIpV4;
}
if (pAddrInfoIpV6)
{
/* create, bind and make IPV6 socket listen */
int fdSocketIpV6 = socket(pAddrInfoIpV6->ai_family,...
*pfdSocketIpV6 = fdSocketIpV6;
}
freeaddrinfo(res);
...
Then call it like so:
...
int fdSocketIpV4 = -1;
int fdSocketIpV6 = -1;
if (0 > open_listenfd(port, &fdSocketIpV4, &fdSocketIpV6))
{
printf("Error executing 'open_listenfd()'\n");
}
else
{
... /* go for accepting connectings on 'fdSocketIpV4' and 'fdSocketIpV6' */
Update:
As commented by Per Johansson an alternative approach would be to set up a dual stack socket, supporting both, Ipv4 and Ipv6, as mentioned by this answer: How to support both IPv4 and IPv6 connections

Related

Can I use inet_pton to set a textual address for my TCP socket server like "device1.local"?

I've written a TCP socket in C and it needs to work with a mobile app that connects to this address over a local network: "device1.local:6666".
Every example I find for using inet_pton() to set the server address has either an IPV4 address that looks like this: 192.168.1.34, or an IPV6 address that looks like this: 2001:db8:8714:3a90::12. Which format do I specify if I want my client to telnet to "device1.local" instead of a numeric or hex address? How do I set up my TCP socket server to answer that address?
This doesn't work:
local_socket = socket(AF_INET6, SOCK_STREAM, 0);
if(local_socket < 0) {
printf("unable to create socket\n");
return false;
}
printf("socket created\n");
bzero((void *)&server_address, sizeof(server_address));
server_address.sin6_family = AF_INET6;
int s_code = inet_pton(AF_INET6, "device1.local", &server_address.sin6_addr);
server_address.sin6_port = htons(port_number);
printf("inet_pton returned: %d\n", s_code);
char str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &server_address.sin6_addr, str, INET6_ADDRSTRLEN);
printf("address from inet_ntop(): %s\n", str);
Here's the output:
socket created
inet_pton returned: 0
address from inet_ntop(): ::
I realize I'm probably demonstrating a fundamental lack of understanding about how the internet (or local networks) work. Any relevant links that you can give me so I can learn more about how custom textual addresses work would be appreciated.
Which format do I specify if I want my client to telnet to "device1.local" instead of a numeric or hex address?
inet_pton() converts a textual representation of an IP address into its binary format (in_addr for IPv4, in6_addr for IPv6, etc). You cannot use it to resolve a hostname into an IP address. For that, you need to use either gethostbyname() (deprecated) or getaddrinfo() (preferred).
Here is a gethostbyname() example:
int connect_to_addr(const sockaddr *addr, int addrlen)
{
local_socket = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (local_socket == -1)
{
printf("unable to create socket\n");
return -1;
}
char str[INET6_ADDRSTRLEN];
unsigned short port;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin_port);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin6_port);
break;
}
}
printf("connecting to address: %s on port: %hu\n", str, port);
if (connect(local_socket, addr, addrlen) != 0)
{
printf("unable to connect\n");
close(local_socket);
local_socket = -1;
return 0;
}
printf("connected\n");
return 1;
}
bool connect_to_host(const char *hostname, unsigned short port_number)
{
local_socket = -1;
sockaddr_storage server_address;
bzero(&server_address, sizeof(server_address));
if (inet_pton(AF_INET6, hostname, &(((struct sockaddr_in6*)&server_address)->sin6_addr)) == 1)
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)&server_address;
saddr->sin6_family = AF_INET6;
saddr->sin6_port = htons(port_number);
if (connect_to_addr((struct sockaddr*)saddr, sizeof(*saddr)) != 1)
return false;
}
else if (inet_pton(AF_INET, hostname, &(((struct sockaddr_in*)&server_address)->sin_addr)) == 1)
{
struct sockaddr_in *saddr = (struct sockaddr_in*)&server_address;
saddr->sin_family = AF_INET;
saddr->sin_port = htons(port_number);
if (connect_to_addr((struct sockaddr*)saddr, sizeof(*saddr)) != 1)
return false;
}
else
{
printf("resolving %s\n", hostname);
struct hostent *host = gethostbyname(hostname);
if (!host)
{
printf("unable to resolve\n");
return false;
}
switch (host->h_addrtype)
{
case AF_INET:
case AF_INET6:
break;
default:
printf("resolved host type is not supported\n");
return false;
}
for(char **addr = host->h_addr_list; *addr != 0; ++addr)
{
bzero(&server_address, sizeof(server_address));
int addrlen;
switch (host->h_addrtype)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)&server_address;
saddr->sin_family = AF_INET;
bcopy(*addr, &(saddr->sin_addr), host->h_length);
saddr->sin_port = htons(port_number);
addrlen = sizeof(*saddr);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)&server_address;
saddr->sin6_family = AF_INET6;
bcopy(*addr, &(saddr->sin6_addr), host->h_length);
saddr->sin6_port = htons(port_number);
addrlen = sizeof(*saddr);
break;
}
}
if (connect_to_addr((struct sockaddr*)&server_address, addrlen) != 0)
break;
}
}
return (local_socket != -1);
}
if (connect_to_host("device.local", 6666))
{
// use local_socket as needed...
close(local_socket);
}
Here is a getaddrinfo() example:
int connect_to_addr(const sockaddr *addr, int addrlen)
{
local_socket = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (local_socket == -1)
{
printf("unable to create socket\n");
return -1;
}
char str[INET6_ADDRSTRLEN];
unsigned short port;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin_port);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin6_port);
break;
}
}
printf("connecting to address: %s on port: %hu\n", str, port);
if (connect(local_socket, addr, addrlen) != 0)
{
printf("unable to connect\n");
close(local_socket);
local_socket = -1;
return 0;
}
printf("connected\n");
return 1;
}
bool connect_to_host(const char* hostname, unsigned short port)
{
local_socket = -1;
printf("resolving %s:%hu\n", hostname, port);
struct addrinfo hints;
bzero((void *)&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char service[6];
bzero(service, sizeof(service));
sprintf(service, "%hu", port_number);
struct addrinfo *addrs = 0;
if (getaddrinfo(hostname, service, &hints, &addrs) != 0)
{
printf("unable to resolve\n");
return false;
}
for(struct addrinfo *addr = addrs; addr != 0; addr = addr->ai_next)
{
if (connect_to_addr((struct sockaddr*)(addr->ai_sockaddr), addr->ai_addrlen) != 0)
break;
}
freeaddrinfo(addrs);
return (local_socket != -1);
}
if (connect_to_host("device.local", 6666))
{
// use local_socket as needed...
close(local_socket);
}
How do I set up my TCP socket server to answer that address?
You simply bind() your listening socket to a specific IP address that is local to your server machine (use getifaddrs() or equivalent API to get a list of local IPs). Or use a wildcard address (INADDR_ANY for IPv4, in6addr_any for IPv6) to bind to all available local IPs.
DNS lookups on the client side will take care of resolving device.local to an IP address that routes to your server machine, and if your server socket is listening on that IP then it can accept() incoming connections.
The .local TLD is reserved for mDNS, as described in RFC 6762.
Therefore for device.local to work your local system should be set with device as its hostname and should be running a Bonjour service (built-in to Windows and OSX, available as Avahi on Linux).
Once that's done, your server-side application doesn't need to do anything special at all - it should just bind to INADDR_ANY and accept incoming (IPv4) connections on any interface.
To slightly complicate matters, if you want to serve over IPv6 too then you typically need two listening sockets, with the second one bound to in6addr_any.
On the client side, the getaddrinfo() function should be able to hook into mDNS and resolve the name to the correct IP address accordingly.

How to troubleshoot socket connection from Asterisk

I wrote a module for asterisk that needs to communicate to a service request information an return it, but for some reason my socket does not connect at all. When I telnet to the service it works fine, but I can not figure out why the it returns a -1 in the module
This is the code in my module
int SocketQuery(char buffer[BUFFSIZE],char *qrystr){
int sock;
struct sockaddr_in eserver;
int sockres = 0;
unsigned char receiving = 1;
memset(sendbuff,0,sizeof(sendbuff));
/* Create the TCP socket */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
ast_log(LOG_ERROR,"Failed to create socket for LCRROUTER");
return -1;
}
/* Construct the server sockaddr_in structure */
memset(&eserver, 0, sizeof(eserver)); /* Clear struct */
eserver.sin_family = AF_INET; /* Internet/IP */
eserver.sin_addr.s_addr = inet_addr(IP); /* IP address */
eserver.sin_port = htons(port); /* server port */
/* Establish connection */
ast_log(LOG_NOTICE,"LCRROUTER - Connection to %s on port %s\n", IP, port);
sockres = connect(sock,
(struct sockaddr *) &eserver,
sizeof(eserver));
if (sockres < 0) {
ast_log(LOG_ERROR,"LCRROUTER - Failed to connect with server on %s:%s. Error Code %d", IP,port,sockres);
return -1;
}
sockres returns -1. Do I miss something?
You can use
tcpdump port YOUR_PORT_HERE -v -s0
In that form it will show you all packets sent via socket.

sendto function setting "network is unreachable" errno

I'll apologise for any lack of clarity, and I'll do my best to update with any missed info, but I'm struggling to understand what I need to do to figure out why the network is unreachable.
I'm getting the output "sendto failed Network is unreachable" from the function
int send_dhcp_packet(void * buffer, int buffer_size, int sock, struct sockaddr_in* dest)
{
int result;
result = sendto(sock, (char*) buffer, buffer_size, 0, (struct sockaddr*)dest, sizeof(*dest));
if(result < 0)
{
printf("sendto failed %s\n", strerror(errno));
return -1;
}
return 0;
}
Where buffer is a struct of type dhcp_packet
typedef struct dhcp_packet_struct
{
uint8_t op; //Packet type
uint8_t htype; //Type of hardware address for this machine
uint8_t hlen; //Length of hardware address for this machine
uint8_t hops; //Number of hops to the gateway
uint32_t xid; //Random transaction ID to match this boot request with responses
uint16_t secs; //Seconds since booted
uint16_t flags; //Flags for the packet
struct in_addr ciaddr; //IP of this machine if it has one
struct in_addr yiaddr; //IP of this machine offered by the DHCP server
struct in_addr siaddr; //IP of the DHCP server
struct in_addr giaddr; //IP of the DHCP relay
unsigned char chaddr[MAX_DHCP_CHADDR_LENGTH]; //Hardware address of this machine
char sname[MAX_DHCP_SNAME_LENGTH]; //Name of DHCP server
char file[MAX_DHCP_FILE_LENGTH]; //Boot file name (full path qualified, null terminated string. Used by later sessions)
char options[MAX_DHCP_OPTIONS_LENGTH]; //DHCP options. Variable length octet strings
}dhcp_packet;
And I'm setting it up in the following function
int send_dhcp_discover(int sock)
{
dhcp_packet discover_packet;
struct sockaddr_in sockaddr_bcast;
//We're setting up the discover packet
bzero(&discover_packet, sizeof(discover_packet));
discover_packet.op = BOOTREQUEST;
discover_packet.htype = ETHERNET_HARDWARE_ADDRESS;
discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH;
discover_packet.hops = 0;
srand(time(NULL));
packet_xid = random();
discover_packet.xid = htonl(packet_xid);
ntohl(packet_xid);
discover_packet.secs = DHCP_PACKET_SECS;
//Tell the server to broadcast it's response
discover_packet.flags = htons(DHCP_BROADCAST_FLAG);
memcpy(discover_packet.chaddr, client_hardware_address, ETHERNET_HARDWARE_ADDRESS_LENGTH); //Our hw address
//First 4 bytes is a magic cookie
discover_packet.options[0] = '\x63';
discover_packet.options[1] = '\x82';
discover_packet.options[2] = '\x53';
discover_packet.options[3] = '\x63';
discover_packet.options[4] = DHCP_OPTION_MESSAGE_TYPE;
discover_packet.options[5] = '\x01'; //Message option length (bytes)
discover_packet.options[6] = DHCPDISCOVER;
if(request_specific_address)
{
discover_packet.options[7] = DHCP_OPTION_REQUESTED_ADDRESS;
discover_packet.options[8] = '\x04'; //Length (bytes)
memcpy(&discover_packet.options[9], &requested_address, sizeof(requested_address));
}
//Send the discover packet to the broadcast address
//Set up the struct
sockaddr_bcast.sin_family = AF_INET;
sockaddr_bcast.sin_port = htons(DHCP_SERVER_PORT);
sockaddr_bcast.sin_addr.s_addr = INADDR_BROADCAST;
bzero(&sockaddr_bcast.sin_zero, sizeof(sockaddr_bcast.sin_zero));
//Send the damn packet already
send_dhcp_packet(&discover_packet, sizeof(discover_packet), sock, &sockaddr_bcast);
return 0;
}
How the socket is set up
int create_dhcp_socket()
{
struct sockaddr_in name;
struct ifreq interface;
int sock;
int flag = 1;
//Set up the address that we're going to use
bzero(&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_port = htons(DHCP_CLIENT_PORT); //Converts from host byte order to network byte order
name.sin_addr.s_addr = INADDR_ANY; //Listen on any address
//Create a socket
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //Creates endpoint using ipv4, supporting datagrams over UDP
if(sock < 0)
{
printf("Error: couldn't create socket\n");
return -1;
}
flag = 1;
//Set the reuse option so there aren't errors on restarting
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)) < 0)
{
printf("Error: couldn't set reuse option on DHCP socket\n");
return -1;
}
//Set the broadcast option
if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&flag, sizeof(flag)) < 0)
{
printf("Error: couldn't set broadcast option on DHCP socket\n");
return -1;
}
strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ);
if(bind(sock, (struct sockaddr*)&name, sizeof(name)) < 0)
{
printf("Error: couldn't bind DHCP socket (port %d). Check yo privilage\n", DHCP_CLIENT_PORT);
return -1;
}
return sock;
}
I guess the question is; why is the network unreachable and how do I fix it so that it's reachable?

bind failed: Cannot assign requested address

I'm trying to write a C program that listens on a port on my machine.
I'm running into a strange error.
Whenever I try to bind the socket to a fixed ip (either 127.0.0.1 or my actual IP) I get a "bind failed: Cannot assign requested address" error.
However when I pass INADDR_ANY to the bind as the address to bind to, it works.
These are the only two IPs I have so it can't be that the 0.0.0.0 works because of some other IP address I have available.
Here is the code:
#include<sys/types.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int port = 1234; /* port number */
int rqst; /* socket accepting the request */
socklen_t alen; /* length of address structure */
struct sockaddr_in my_addr; /* address of this service */
struct sockaddr_in client_addr; /* client's address */
int sockoptval = 1;
int svc;
/* create a TCP/IP socket */
if ((svc = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
exit(1);
}
/* allow immediate reuse of the port */
setsockopt(svc, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int));
/* bind the socket to our source address */
memset((char*)&my_addr, 0, sizeof(my_addr)); /* 0 out the structure */
my_addr.sin_family = AF_INET; /* address family */
my_addr.sin_port = htons(port);
//my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Works! */
my_addr.sin_addr.s_addr = htonl(inet_addr("127.0.0.1")); /* Fails! */
if (bind(svc, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
perror("bind failed");
exit(1);
}
printf("Listening on %d\n", my_addr.sin_addr.s_addr);
/* set the socket for listening (queue backlog of 5) */
if (listen(svc, 5) < 0) {
perror("listen failed");
exit(1);
}
/* loop, accepting connection requests */
for (;;) {
while ((rqst = accept(svc, (struct sockaddr *)&client_addr, &alen)) < 0) {
/* we may break out of accept if the system call */
/* was interrupted. In this case, loop back and */
/* try again */
if ((errno != ECHILD) && (errno != ERESTART) && (errno != EINTR)) {
perror("accept failed");
exit(1);
}
}
/* the socket for this accepted connection is rqst */
}
}
The function inet_addr returns the address already in network order:
The inet_addr() function converts the Internet host address cp from
IPv4 numbers-and-dots notation into binary data in network byte order
So drop the htonl.

Getting an address IP and using a socket to connect to it

I'm writing an HTTP client using UNIX sockets (as part of a homework assignment). I currently have this working code to connect to a given IP Address:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
char *server_address = "127.0.0.1";
struct sockaddr_in address;
if (sockfd < 0) {
printf("Unable to open socket\n");
exit(1);
}
// Try to connect to server_address on port PORT
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(server_address);
address.sin_port = htons(PORT);
if (connect(sockfd, (struct sockaddr*) &address, sizeof(address)) < 0) {
printf("Unable to connect to host\n");
exit(1);
}
However, I now want to modify it so that server_address could also be something that is not an IP, such as "google.com". I've been trying to figure out how to do this using gethostbyname, but I am having trouble.
Will gethostbyname accept both an IP Address OR an address like "google.com" and have it work correctly? (or should I try and run a regex on the address first and do something else if it is an IP Address)?
I have tried the following code to try to get it working with something like "google.com", but I am getting a warning warning: assignment makes integer from pointer without a cast
struct hostent *host_entity = gethostbyname(server_address);
address.sin_addr.s_addr = host_entity->h_addr_list[0];
I know I am doing-it-wrong, but the gethostbyname documentation is atrocious.
What you want is maybe getaddrinfo(3):
#include <sys/socket.h>
#include <netdb.h>
static int
resolve(const char *host, const char *port)
{
struct addrinfo *aires;
struct addrinfo hints = {0};
int s = -1;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
#if defined AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif /* AI_ADDRCONFIG */
#if defined AI_V4MAPPED
hints.ai_flags |= AI_V4MAPPED;
#endif /* AI_V4MAPPED */
hints.ai_protocol = 0;
if (getaddrinfo(host, port, &hints, &aires) < 0) {
goto out;
}
/* now try them all */
for (const struct addrinfo *ai = aires;
ai != NULL &&
((s = socket(ai->ai_family, ai->ai_socktype, 0)) < 0 ||
connect(s, ai->ai_addr, ai->ai_addrlen) < 0);
close(s), s = -1, ai = ai->ai_next);
out:
freeaddrinfo(aires);
return s;
}
This version gets you a socket from a host/port pair. It also takes IP addresses for host and service strings for port. It will, however, connect to the host in question already.

Resources