diff --git a/gpsd-ipv6.patch b/gpsd-ipv6.patch new file mode 100644 index 0000000..ade8abb --- /dev/null +++ b/gpsd-ipv6.patch @@ -0,0 +1,356 @@ +commit 5c080c35fc3d981172a5e4af34d0d92854a5433a +Author: Miroslav Lichvar +Date: Tue Jul 25 11:01:14 2023 +0200 + + libgps/netlib.c: Rework enabling non-block and make binding configurable. + + Instead of accepting SOCK_NONBLOCK as flags in netlib_connectsock1() + specify if the non-blocking mode should be enabled after or before + connect(). + + Also add a boolean parameter to the function to select between connect() + and bind() instead of hardcoding it for TCP vs UDP, which will allow + connecting to UDP ports in gps2udp. + +diff --git a/gpsd/libgpsd_core.c b/gpsd/libgpsd_core.c +index 47ee5d57e..341e8b80c 100644 +--- a/gpsd/libgpsd_core.c ++++ b/gpsd/libgpsd_core.c +@@ -561,7 +561,6 @@ int gpsd_open(struct gps_device_t *session) + char server[GPS_PATH_MAX], *host, *port, *device; + socket_t dsock; + char addrbuf[50]; // INET6_ADDRSTRLEN +- int sock_opt; + + session->sourcetype = SOURCE_TCP; + (void)strlcpy(server, session->gpsdata.dev.path + 6, sizeof(server)); +@@ -576,15 +575,9 @@ int gpsd_open(struct gps_device_t *session) + GPSD_LOG(LOG_PROG, &session->context->errout, + "CORE: opening TCP feed at %s, port %s.\n", host, + port); +-#if defined(SOCK_NONBLOCK) +- sock_opt = SOCK_NONBLOCK; +-#else +- // macOS has no SOCK_NONBLOCK +- sock_opt = 0; +-#endif + // open non-blocking + dsock = netlib_connectsock1(AF_UNSPEC, host, port, "tcp", +- sock_opt, addrbuf, sizeof(addrbuf)); ++ 1, false, addrbuf, sizeof(addrbuf)); + if (0 > dsock) { + GPSD_LOG(LOG_ERROR, &session->context->errout, + "CORE: TCP %s IP %s, open error %s(%d).\n", +@@ -614,7 +607,8 @@ int gpsd_open(struct gps_device_t *session) + GPSD_LOG(LOG_PROG, &session->context->errout, + "CORE: opening UDP feed at %s, port %s.\n", host, + port); +- if (0 > (dsock = netlib_connectsock(AF_UNSPEC, host, port, "udp"))) { ++ if (0 > (dsock = netlib_connectsock1(AF_UNSPEC, host, port, "udp", ++ 0, true, NULL, 0))) { + GPSD_LOG(LOG_ERROR, &session->context->errout, + "CORE: UDP device open error %s(%d).\n", + netlib_errstr(dsock), dsock); +diff --git a/gpsd/net_ntrip.c b/gpsd/net_ntrip.c +index 8241995ae..d89bdc1f9 100644 +--- a/gpsd/net_ntrip.c ++++ b/gpsd/net_ntrip.c +@@ -856,7 +856,8 @@ static int ntrip_reconnect(struct gps_device_t *device) + device->gpsdata.dev.path); + dsock = netlib_connectsock1(AF_UNSPEC, device->ntrip.stream.host, + device->ntrip.stream.port, +- "tcp", SOCK_NONBLOCK, addrbuf, sizeof(addrbuf)); ++ "tcp", 1, false, ++ addrbuf, sizeof(addrbuf)); + device->gpsdata.gps_fd = dsock; + // nonblocking means we have the fd, but the connection is not + // finished yet. Connection may fail, later. +diff --git a/include/gpsd.h b/include/gpsd.h +index 0f6b731eb..2f3260c1e 100644 +--- a/include/gpsd.h ++++ b/include/gpsd.h +@@ -1002,7 +1002,7 @@ extern void gpsd_clear_data(struct gps_device_t *); + extern socket_t netlib_connectsock(int, const char *, const char *, + const char *); + extern socket_t netlib_connectsock1(int, const char *, const char *, +- const char *, int, ++ const char *, int, bool, + char *, size_t); + // end FIXME + extern socket_t netlib_localsocket(const char *, int); +diff --git a/libgps/netlib.c b/libgps/netlib.c +index e4e763025..5f553fe10 100644 +--- a/libgps/netlib.c ++++ b/libgps/netlib.c +@@ -55,8 +55,10 @@ + * host - host to connect to + * service -- aka port + * protocol +- * flags -- can be SOCK_NONBLOCK for non-blocking connect +- * Note: macOS does not have SOCK_NONBLOCK ++ * nonblock -- 1 sets the socket as non-blocking before connect() if ++ * SOCK_NONBLOCK is supported, ++ * >1 sets the socket as non-blocking after connect() ++ * bind_me -- call bind() on the socket instead of connect() + * addrbuf -- 50 char buf to put string of IP address conencting + * INET6_ADDRSTRLEN + * addrbuf_sz -- sizeof(adddrbuf) +@@ -70,16 +72,15 @@ + * less than zero on error (NL_*) + */ + socket_t netlib_connectsock1(int af, const char *host, const char *service, +- const char *protocol, int flags, ++ const char *protocol, int nonblock, bool bind_me, + char *addrbuf, size_t addrbuf_sz) + { + struct protoent *ppe; + struct addrinfo hints; + struct addrinfo *result = NULL; + struct addrinfo *rp; +- int ret, type, proto, one; ++ int ret, flags, type, proto, one; + socket_t s; +- bool bind_me; + + if (NULL != addrbuf) { + addrbuf[0] = '\0'; +@@ -97,9 +98,6 @@ socket_t netlib_connectsock1(int af, const char *host, const char *service, + return NL_NOPROTO; + } + +- /* we probably ought to pass this in as an explicit flag argument */ +- bind_me = (SOCK_DGRAM == type); +- + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = af; + hints.ai_socktype = type; +@@ -107,6 +105,15 @@ socket_t netlib_connectsock1(int af, const char *host, const char *service, + if (bind_me) { + hints.ai_flags = AI_PASSIVE; + } ++#if defined(SOCK_NONBLOCK) ++ flags = nonblock == 1 ? SOCK_NONBLOCK : 0; ++#else ++ // macOS has no SOCK_NONBLOCK ++ flags = 0; ++ if (nonblock == 1) ++ nonblock = 2; ++#endif ++ + // FIXME: need a way to bypass these DNS calls if host is an IP. + if ((ret = getaddrinfo(host, service, &hints, &result))) { + // result is unchanged on error, so we need to have set it to NULL +@@ -219,13 +226,15 @@ socket_t netlib_connectsock1(int af, const char *host, const char *service, + sizeof(one)); + } + +- // set socket to noblocking ++ if (nonblock > 1) { ++ // set socket to noblocking + #ifdef HAVE_FCNTL +- (void)fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); ++ (void)fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); + #elif defined(HAVE_WINSOCK2_H) +- u_long one1 = 1; +- (void)ioctlsocket(s, FIONBIO, &one1); ++ u_long one1 = 1; ++ (void)ioctlsocket(s, FIONBIO, &one1); + #endif ++ } + return s; + } + +@@ -235,7 +244,7 @@ socket_t netlib_connectsock1(int af, const char *host, const char *service, + socket_t netlib_connectsock(int af, const char *host, const char *service, + const char *protocol) + { +- return netlib_connectsock1(af, host, service, protocol, 0, NULL, 0); ++ return netlib_connectsock1(af, host, service, protocol, 2, false, NULL, 0); + } + + // Convert NL_* error code to a string + +commit fd6682a6ffd0a5d4d640839422274b582ba38e72 +Author: Miroslav Lichvar +Date: Tue Jul 25 11:08:19 2023 +0200 + + clients/gps2udp.c: Switch to netlib_connectsock1(). + + Use netlib_connectsock1() to avoid using obsolete gethostbyname() and + support IPv6. + +diff --git a/clients/gps2udp.c b/clients/gps2udp.c +index 2d9c6033d..541054d8f 100644 +--- a/clients/gps2udp.c ++++ b/clients/gps2udp.c +@@ -21,7 +21,6 @@ + #ifdef HAVE_GETOPT_LONG + #include // for getopt_long() + #endif +-#include /* for gethostbyname() */ + #include + #include + #include +@@ -50,7 +49,6 @@ static struct gps_data_t gpsdata; + + /* UDP socket variables */ + #define MAX_UDP_DEST 5 +-static struct sockaddr_in remote[MAX_UDP_DEST]; + static int sock[MAX_UDP_DEST]; + static int udpchannel; + +@@ -128,12 +126,10 @@ static int send_udp(char *nmeastring, size_t ind) + + // send message on udp channel + for (channel=0; channel < udpchannel; channel ++) { +- ssize_t status = sendto(sock[channel], +- buffer, +- ind, +- 0, +- (struct sockaddr *)&remote[channel], +- (int)sizeof(remote)); ++ ssize_t status = send(sock[channel], ++ buffer, ++ ind, ++ 0); + if (status < (ssize_t)ind) { + (void)fprintf(stderr, "gps2udp: failed to send [%s] \n", + buffer); +@@ -152,9 +148,6 @@ static int open_udp(char **hostport) + for (channel = 0; channel < udpchannel; channel++) { + char *hostname = NULL; + char *portname = NULL; +- char *endptr = NULL; +- int portnum; +- struct hostent *hp; + + if (NULL == hostport[channel]) { + // pacify coverity +@@ -171,32 +164,13 @@ static int open_udp(char **hostport) + return -1; + } + +- errno = 0; +- portnum = (int)strtol(portname, &endptr, 10); +- if (1 > portnum || 65535 < portnum || '\0' != *endptr || 0 != errno) { +- (void)fprintf(stderr, "gps2udp: syntax is [-u hostname:port] " +- "[%s] is not a valid port number\n", portname); +- return -1; +- } +- +- sock[channel]= socket(AF_INET, SOCK_DGRAM, 0); ++ sock[channel] = netlib_connectsock1(AF_UNSPEC, hostname, portname, "udp", ++ 0, false, NULL, 0); + if (0 > sock[channel]) { +- (void)fprintf(stderr, "gps2udp: error creating UDP socket\n"); ++ (void)fprintf(stderr, "gps2udp: error creating UDP socket: %s\n", ++ netlib_errstr(sock[channel])); + return -1; + } +- +- remote[channel].sin_family = (sa_family_t)AF_INET; +- hp = gethostbyname(hostname); +- if (NULL == hp) { +- (void)fprintf(stderr, +- "gps2udp: syntax is [-u hostname:port] [%s]" +- " is not a valid hostname\n", +- hostname); +- return -1; +- } +- +- memcpy( &remote[channel].sin_addr, hp->h_addr_list[0], hp->h_length); +- remote[channel].sin_port = htons((in_port_t)portnum); + } + return 0; + } + +commit 749be8acce27f16d74ba727f4819f3e49602882a +Author: Miroslav Lichvar +Date: Tue Jul 25 11:10:39 2023 +0200 + + clients/lcdgps.c: Switch to netlib_connectsock1(). + + Use netlib_connectsock1() to avoid using obsolete gethostbyname() and + support IPv6. + +diff --git a/clients/lcdgps.c b/clients/lcdgps.c +index 7d0ee6bc8..b311882b0 100644 +--- a/clients/lcdgps.c ++++ b/clients/lcdgps.c +@@ -21,11 +21,12 @@ + */ + + #define LCDDHOST "localhost" +-#define LCDDPORT 13666 ++#define LCDDPORT "13666" + + #define CLIMB 3 + + #include "../include/gpsd_config.h" /* must be before all includes */ ++#include "../include/gpsd.h" + + #include + #include +@@ -33,7 +34,6 @@ + #include // for getopt_long() + #endif + #include +-#include /* for gethostbyname() */ + #include + #include + #include +@@ -259,9 +259,6 @@ static void usage( char *prog) + + int main(int argc, char *argv[]) + { +- int rc; +- struct sockaddr_in localAddr, servAddr; +- struct hostent *h; + const char *optstring = "?hl:su:V"; + int n; + #ifdef HAVE_GETOPT_LONG +@@ -390,41 +387,10 @@ int main(int argc, char *argv[]) + } + + /* Connect to LCDd */ +- h = gethostbyname(LCDDHOST); +- if (h==NULL) { +- printf("%s: unknown host '%s'\n",argv[0],LCDDHOST); +- exit(EXIT_FAILURE); +- } +- +- servAddr.sin_family = h->h_addrtype; +- memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); +- servAddr.sin_port = htons(LCDDPORT); +- +- /* create socket */ +- sd = socket(AF_INET, SOCK_STREAM, 0); +- if (BAD_SOCKET(sd)) { +- perror("cannot open socket "); +- exit(EXIT_FAILURE); +- } +- +- /* bind any port number */ +- localAddr.sin_family = AF_INET; +- localAddr.sin_addr.s_addr = htonl(INADDR_ANY); +- localAddr.sin_port = htons(0); +- +- /* coverity[uninit_use_in_call] */ +- rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr)); +- if (rc == -1) { +- printf("%s: cannot bind port TCP %d\n",argv[0],LCDDPORT); +- perror("error "); +- exit(EXIT_FAILURE); +- } ++ sd = netlib_connectsock1(AF_UNSPEC, LCDDHOST, LCDDPORT, "tcp", 0, false, NULL, 0); ++ if (0 > sd) { + +- /* connect to server */ +- /* coverity[uninit_use_in_call] */ +- rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); +- if (rc == -1) { +- perror("cannot connect "); ++ (void)fprintf(stderr, "lcdgps: cannot connect: %s\n", netlib_errstr(sd)); + exit(EXIT_FAILURE); + } + diff --git a/gpsd.spec b/gpsd.spec index 8bd4f05..c14876e 100644 --- a/gpsd.spec +++ b/gpsd.spec @@ -18,6 +18,8 @@ URL: https://gpsd.gitlab.io/gpsd/index.html Source0: https://download-mirror.savannah.gnu.org/releases/gpsd/%{name}-%{version}.tar.gz Source11: gpsd.sysconfig +# add missing IPv6 support +Patch1: gpsd-ipv6.patch BuildRequires: gcc BuildRequires: dbus-devel BuildRequires: ncurses-devel @@ -135,6 +137,7 @@ do not reference it or depend on it in any way. %prep %setup -q +%patch -P 1 -p1 -b .ipv6 # don't try reloading systemd when installing in the build root sed -i 's|systemctl daemon-reload|true|' SConscript