aseqnet: use getaddrinfo() instead obsolete gethostbyname()

- modernize code (preparation for IPv6)

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2021-08-09 18:10:56 +02:00
parent f076518254
commit c8e5762750

View file

@ -21,6 +21,7 @@
#include <string.h> #include <string.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <locale.h> #include <locale.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
@ -38,10 +39,9 @@ static void init_buf(void);
static void init_pollfds(void); static void init_pollfds(void);
static void close_files(void); static void close_files(void);
static void init_seq(char *source, char *dest, char *name); static void init_seq(char *source, char *dest, char *name);
static int get_port(char *service);
static void sigterm_exit(int sig); static void sigterm_exit(int sig);
static void init_server(int port); static void init_server(const char *port);
static void init_client(char *server, int port); static void init_client(const char *server, const char *port);
static void do_loop(void); static void do_loop(void);
static int copy_local_to_remote(void); static int copy_local_to_remote(void);
static int copy_remote_to_local(int fd); static int copy_remote_to_local(int fd);
@ -49,7 +49,7 @@ static int copy_remote_to_local(int fd);
/* /*
* default TCP port number * default TCP port number
*/ */
#define DEFAULT_PORT 40002 #define DEFAULT_PORT "40002"
/* /*
* local input buffer * local input buffer
@ -97,7 +97,7 @@ static const struct option long_option[] = {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int c; int c;
int port = DEFAULT_PORT; char *port = DEFAULT_PORT;
char *source = NULL, *dest = NULL; char *source = NULL, *dest = NULL;
char *name = NULL; char *name = NULL;
@ -109,10 +109,7 @@ int main(int argc, char **argv)
while ((c = getopt_long(argc, argv, "p:s:d:n:,vi", long_option, NULL)) != -1) { while ((c = getopt_long(argc, argv, "p:s:d:n:,vi", long_option, NULL)) != -1) {
switch (c) { switch (c) {
case 'p': case 'p':
if (isdigit(*optarg)) port = optarg;
port = atoi(optarg);
else
port = get_port(optarg);
break; break;
case 's': case 's':
source = optarg; source = optarg;
@ -307,19 +304,25 @@ static void init_seq(char *source, char *dest, char* name)
} }
} }
/* /*
* convert from string to TCP port number * translate the binary network address to ASCII
*/ */
static int get_port(char *service) static void get_net_addr(struct addrinfo *rp, char *buf, size_t buflen)
{ {
struct servent *sp; void *ptr;
if ((sp = getservbyname(service, "tcp")) == NULL){ switch (rp->ai_family) {
fprintf(stderr, _("service '%s' is not found in /etc/services\n"), service); case AF_INET:
return -1; ptr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
break;
default:
ptr = NULL;
} }
return sp->s_port; buf[buflen-1] = '\0';
inet_ntop(rp->ai_family, ptr, buf, buflen-1);
} }
/* /*
@ -335,30 +338,48 @@ static void sigterm_exit(int sig)
/* /*
* initialize network server * initialize network server
*/ */
static void init_server(int port) static void init_server(const char *port)
{ {
struct addrinfo hints;
struct addrinfo *result, *rp;
char buf[100];
int i; int i;
int curstate = 1; int curstate = 1;
struct sockaddr_in addr; int save_errno = 0;
memset(&addr, 0, sizeof(addr)); memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
addr.sin_family = AF_INET; if (getaddrinfo(NULL, port, &hints, &result) < 0) {
addr.sin_addr.s_addr = INADDR_ANY; fprintf(stderr, _("can't get address\n"));
addr.sin_port = htons(port);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("create socket");
exit(1); exit(1);
} }
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)); for (rp = result; rp != NULL; rp = rp->ai_next) {
/* the return value is ignored.. */ if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
perror("create socket");
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { exit(1);
perror("can't bind"); }
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) {
perror("setsockopt");
exit(1);
}
if (verbose) {
get_net_addr(rp, buf, sizeof(buf));
fprintf(stderr, _("connecting to: %s\n"), buf);
}
if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
break;
save_errno = errno;
close(sockfd);
}
if (rp == NULL) {
errno = save_errno;
perror("bind");
exit(1); exit(1);
} }
freeaddrinfo(result);
if (listen(sockfd, 5) < 0) { if (listen(sockfd, 5) < 0) {
perror("can't listen"); perror("can't listen");
@ -402,32 +423,48 @@ static void start_connection(void)
/* /*
* initialize network client * initialize network client
*/ */
static void init_client(char *server, int port) static void init_client(const char *server, const char *port)
{ {
struct sockaddr_in addr; struct addrinfo hints;
struct hostent *host; struct addrinfo *result, *rp;
char buf[100];
int curstate = 1; int curstate = 1;
int fd; int fd;
int save_errno = 0;
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ memset(&hints, 0, sizeof(hints));
perror("create socket"); hints.ai_family = AF_INET;
exit(1); hints.ai_socktype = SOCK_STREAM;
} hints.ai_flags = AI_PASSIVE;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) {
perror("setsockopt"); if (getaddrinfo(server, port, &hints, &result) < 0) {
exit(1);
}
if ((host = gethostbyname(server)) == NULL){
fprintf(stderr, _("can't get address %s\n"), server); fprintf(stderr, _("can't get address %s\n"), server);
exit(1); exit(1);
} }
addr.sin_port = htons(port); for (rp = result; rp != NULL; rp = rp->ai_next) {
addr.sin_family = AF_INET; if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
memcpy(&addr.sin_addr, host->h_addr, host->h_length); perror("create socket");
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { exit(1);
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) {
perror("setsockopt");
exit(1);
}
if (verbose) {
get_net_addr(rp, buf, sizeof(buf));
fprintf(stderr, _("connecting to: %s\n"), buf);
}
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0)
break;
save_errno = errno;
close(fd);
}
if (rp == NULL) {
errno = save_errno;
perror("connect"); perror("connect");
exit(1); exit(1);
} }
freeaddrinfo(result);
if (verbose) if (verbose)
fprintf(stderr, _("ok.. connected\n")); fprintf(stderr, _("ok.. connected\n"));
netfd[0] = fd; netfd[0] = fd;