From 8985b45e1fe1a5d50c5e1dc4c7c306705e602445 Mon Sep 17 00:00:00 2001 From: "A. Maitland Bottoms" Date: Sun, 3 Sep 2017 16:22:55 -0400 Subject: rtl_tcp: Add IPv6 support I've prepared this patch in response to Debian bug #870804 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870804 It passes the text from the -a and -p options through getaddrinfo() and uses the first result that has a valid socket with a successful bind. While not a complete bind to all possible valid names, it does appear to address the use case of the bug submitter without completely changing the program flow. --- src/rtl_tcp.c | 72 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index da6057b..42b90cb 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #else @@ -371,10 +372,18 @@ static void *command_worker(void *arg) int main(int argc, char **argv) { int r, opt, i; - char* addr = "127.0.0.1"; - int port = 1234; + char *addr = "127.0.0.1"; + char *port = "1234"; uint32_t frequency = 100000000, samp_rate = 2048000; - struct sockaddr_in local, remote; + struct sockaddr_storage local, remote; + struct addrinfo *ai; + struct addrinfo *aiHead; + struct addrinfo hints; + char hostinfo[NI_MAXHOST]; + char portinfo[NI_MAXSERV]; + char remhostinfo[NI_MAXHOST]; + char remportinfo[NI_MAXSERV]; + int aiErr; uint32_t buf_num = 0; int dev_index = 0; int dev_given = 0; @@ -413,10 +422,10 @@ int main(int argc, char **argv) samp_rate = (uint32_t)atofs(optarg); break; case 'a': - addr = optarg; + addr = strdup(optarg); break; case 'p': - port = atoi(optarg); + port = strdup(optarg); break; case 'b': buf_num = atoi(optarg); @@ -515,16 +524,42 @@ int main(int argc, char **argv) pthread_cond_init(&cond, NULL); pthread_cond_init(&exit_cond, NULL); - memset(&local,0,sizeof(local)); - local.sin_family = AF_INET; - local.sin_port = htons(port); - local.sin_addr.s_addr = inet_addr(addr); + hints.ai_flags = AI_PASSIVE; /* Server mode. */ + hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6. */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if ((aiErr = getaddrinfo(addr, + port, + &hints, + &aiHead )) != 0) + { + fprintf(stderr, "local address %s ERROR - %s.\n", + addr, gai_strerror(aiErr)); + return(-1); + } + memcpy(&local, aiHead->ai_addr, aiHead->ai_addrlen); + + for (ai = aiHead; ai != NULL; ai = ai->ai_next) { + aiErr = getnameinfo((struct sockaddr *)ai->ai_addr, ai->ai_addrlen, + hostinfo, NI_MAXHOST, + portinfo, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + if (aiErr) + fprintf( stderr, "getnameinfo ERROR - %s.\n",hostinfo); + + listensocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (listensocket < 0) + continue; + + r = 1; + setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); + setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - r = 1; - setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); - setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - bind(listensocket,(struct sockaddr *)&local,sizeof(local)); + if (bind(listensocket, (struct sockaddr *)&local, sizeof(local))) + fprintf(stderr, "rtl_tcp bind error: %s", strerror(errno)); + else + break; + } #ifdef _WIN32 ioctlsocket(listensocket, FIONBIO, &blockmode); @@ -535,11 +570,11 @@ int main(int argc, char **argv) while(1) { printf("listening...\n"); - printf("Use the device argument 'rtl_tcp=%s:%d' in OsmoSDR " + printf("Use the device argument 'rtl_tcp=%s:%s' in OsmoSDR " "(gr-osmosdr) source\n" "to receive samples in GRC and control " "rtl_tcp parameters (frequency, gain, ...).\n", - addr, port); + hostinfo, portinfo); listen(listensocket,1); while(1) { @@ -559,7 +594,10 @@ int main(int argc, char **argv) setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - printf("client accepted!\n"); + getnameinfo((struct sockaddr *)&remote, rlen, + remhostinfo, NI_MAXHOST, + remportinfo, NI_MAXSERV, NI_NUMERICSERV); + printf("client accepted! %s %s\n", remhostinfo, remportinfo); memset(&dongle_info, 0, sizeof(dongle_info)); memcpy(&dongle_info.magic, "RTL0", 4); -- cgit v1.2.3