2 * This file is Copyright (c) 2010 by the GPSD project
3 * BSD terms apply: see the file COPYING in the distribution root for details.
7 #include "gpsd_config.h"
10 #ifdef HAVE_SYS_SOCKET_H
11 #include <sys/socket.h>
13 #ifdef HAVE_NETINET_IN_H
14 #include <netinet/in.h>
16 #ifdef HAVE_NETINET_IN_SYSTM_H
17 #include <netinet/in_systm.h>
19 #ifdef HAVE_NETINET_IN_H
20 #include <netinet/ip.h>
22 #endif /* S_SPLINT_S */
26 #endif /* HAVE_NETDB_H */
27 #ifdef HAVE_ARPA_INET_H
28 #include <arpa/inet.h>
29 #endif /* HAVE_ARPA_INET_H */
30 #endif /* S_SPLINT_S */
35 #endif /* S_SPLINT_S */
41 #if !defined (INADDR_NONE)
42 #define INADDR_NONE ((in_addr_t)-1)
45 /*@-mustfreefresh -usedef@*/
46 socket_t netlib_connectsock(int af, const char *host, const char *service,
50 struct addrinfo hints;
51 struct addrinfo *result, *rp;
52 int ret, type, proto, one = 1;
57 ppe = getprotobyname(protocol);
58 if (strcmp(protocol, "udp") == 0) {
60 proto = (ppe) ? ppe->p_proto : IPPROTO_UDP;
63 proto = (ppe) ? ppe->p_proto : IPPROTO_TCP;
67 /* we probably ought to pass this in as an explicit flag argument */
68 bind_me = (type == SOCK_DGRAM);
70 memset(&hints, 0, sizeof(struct addrinfo));
72 hints.ai_socktype = type;
73 hints.ai_protocol = proto;
76 hints.ai_flags = AI_PASSIVE;
77 if ((ret = getaddrinfo(host, service, &hints, &result))) {
80 #endif /* S_SPLINT_S */
83 * From getaddrinfo(3):
84 * Normally, the application should try using the addresses in the
85 * order in which they are returned. The sorting function used within
86 * getaddrinfo() is defined in RFC 3484).
87 * From RFC 3484 (Section 10.3):
88 * The default policy table gives IPv6 addresses higher precedence than
90 * Thus, with the default parameters, we get IPv6 addresses first.
93 for (rp = result; rp != NULL; rp = rp->ai_next) {
95 if ((s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
98 (s, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
104 if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) {
109 if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) {
117 gpsd_report(LOG_SPIN, "close(%d) in netlib_connectsock()\n", s);
123 freeaddrinfo(result);
124 #endif /* S_SPLINT_S */
128 #ifdef IPTOS_LOWDELAY
130 int opt = IPTOS_LOWDELAY;
132 (void)setsockopt(s, IPPROTO_IP, IP_TOS, &opt, sizeof opt);
137 if (type == SOCK_STREAM)
138 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof one);
141 gpsd_report(LOG_SPIN, "netlib_connectsock() returns socket on fd %d\n",
144 /*@ +type +mustfreefresh @*/
147 /*@+mustfreefresh +usedef@*/
149 char /*@observer@*/ *netlib_errstr(const int err)
153 return "can't get service entry";
155 return "can't get host entry";
157 return "can't get protocol entry";
159 return "can't create socket";
161 return "error SETSOCKOPT SO_REUSEADDR";
163 return "can't connect to host/port pair";
165 return "unknown error";
169 char *netlib_sock2ip(int fd)
172 socklen_t alen = (socklen_t) sizeof(fsin);
173 /*@i1@*/ static char ip[INET6_ADDRSTRLEN];
176 r = getpeername(fd, &(fsin.sa), &alen);
177 /*@ -branchstate -unrecog @*/
179 switch (fsin.sa.sa_family) {
181 r = !inet_ntop(fsin.sa_in.sin_family, &(fsin.sa_in.sin_addr),
186 r = !inet_ntop(fsin.sa_in6.sin6_family, &(fsin.sa_in6.sin6_addr),
191 gpsd_report(LOG_ERROR, "Unhandled address family %d in %s\n",
192 fsin.sa.sa_family, __FUNCTION__);
193 (void)strlcpy(ip, "<unknown AF>", sizeof(ip));
198 gpsd_report(LOG_INF, "getpeername() = %d, error = %s (%d)\n", r,
199 strerror(errno), errno);
200 (void)strlcpy(ip, "<unknown>", sizeof(ip));
202 /*@ +branchstate +unrecog @*/