7 // [PROTOCOL:]IP[%INTERFACE][:PORT]
9 // PROTOCOL = tcp or udp
10 // IP = IPv4 or IPv6 IP or hostname, optionally enclosed in [] (required for IPv6)
11 // INTERFACE = for IPv6 only, the network interface to use
12 // PORT = port number or service name
14 int connect_to(const char *definition, int default_port, struct timeval *timeout) {
15 struct addrinfo hints;
16 struct addrinfo *ai_head = NULL, *ai = NULL;
18 char buffer[strlen(definition) + 1];
19 strcpy(buffer, definition);
21 char default_service[10 + 1];
22 snprintfz(default_service, 10, "%d", default_port);
24 char *host = buffer, *service = default_service, *interface = "";
25 int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
26 uint32_t scope_id = 0;
28 if(strncmp(host, "tcp:", 4) == 0) {
30 protocol = IPPROTO_TCP;
31 socktype = SOCK_STREAM;
33 else if(strncmp(host, "udp:", 4) == 0) {
35 protocol = IPPROTO_UDP;
36 socktype = SOCK_DGRAM;
42 while(*e && *e != ']') e++;
49 while(*e && *e != ':' && *e != '%') e++;
56 while(*e && *e != ':') e++;
65 debug(D_CONNECT_TO, "Attempting connection to host = '%s', service = '%s', interface = '%s', protocol = %d (tcp = %d, udp = %d)", host, service, interface, protocol, IPPROTO_TCP, IPPROTO_UDP);
68 error("Definition '%s' does not specify a host.", definition);
73 scope_id = if_nametoindex(interface);
75 error("Cannot find a network interface named '%s'. Continuing with limiting the network interface", interface);
79 service = default_service;
81 memset(&hints, 0, sizeof(hints));
82 hints.ai_family = PF_UNSPEC; /* Allow IPv4 or IPv6 */
83 hints.ai_socktype = socktype;
84 hints.ai_protocol = protocol;
86 int ai_err = getaddrinfo(host, service, &hints, &ai_head);
88 error("Cannot resolve host '%s', port '%s': %s", host, service, gai_strerror(ai_err));
93 for (ai = ai_head; ai != NULL && fd == -1; ai = ai->ai_next) {
95 if (ai->ai_family == PF_INET6) {
96 struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
97 if(pSadrIn6->sin6_scope_id == 0) {
98 pSadrIn6->sin6_scope_id = scope_id;
102 char hostBfr[NI_MAXHOST + 1];
103 char servBfr[NI_MAXSERV + 1];
105 getnameinfo(ai->ai_addr,
111 NI_NUMERICHOST | NI_NUMERICSERV);
113 debug(D_CONNECT_TO, "Address info: host = '%s', service = '%s', ai_flags = 0x%02X, ai_family = %d (PF_INET = %d, PF_INET6 = %d), ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d), ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d), ai_addrlen = %lu (sockaddr_in = %lu, sockaddr_in6 = %lu)",
116 (unsigned int)ai->ai_flags,
126 (unsigned long)ai->ai_addrlen,
127 (unsigned long)sizeof(struct sockaddr_in),
128 (unsigned long)sizeof(struct sockaddr_in6));
130 switch (ai->ai_addr->sa_family) {
132 struct sockaddr_in *pSadrIn = (struct sockaddr_in *)ai->ai_addr;
133 debug(D_CONNECT_TO, "ai_addr = sin_family: %d (AF_INET = %d, AF_INET6 = %d), sin_addr: '%s', sin_port: '%s'",
143 struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
144 debug(D_CONNECT_TO,"ai_addr = sin6_family: %d (AF_INET = %d, AF_INET6 = %d), sin6_addr: '%s', sin6_port: '%s', sin6_flowinfo: %u, sin6_scope_id: %u",
145 pSadrIn6->sin6_family,
150 pSadrIn6->sin6_flowinfo,
151 pSadrIn6->sin6_scope_id);
156 debug(D_CONNECT_TO, "Unknown protocol family %d.", ai->ai_family);
161 fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
163 if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)timeout, sizeof(struct timeval)) < 0)
164 error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr);
166 if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
167 error("Failed to connect to '%s', port '%s'", hostBfr, servBfr);
172 debug(D_CONNECT_TO, "Connected to '%s' on port '%s'.", hostBfr, servBfr);
176 freeaddrinfo(ai_head);