There were 3 related bugs here:
1. The same report_sock call would sometimes print information about
the peer socket and sometimes about the local socket. This
confusion may have been enabled by its duplicitous API. This is
fixed by dropping the path parameter and renaming it to
report_addr. Additionally, a new report_sock is added which first
obtains the address for the given socket and then calls
report_addr.
2. In the case of "uflag && !kflag" branch of a listening socket there
was a call to report_sock which neglected to adjust the argument
depending on the address family: unix sockets would cause netcat to
die.
3. report_sock printed awkward messages because it always tacked "on"
to the user-provided message, even though sometimes a different
preposition was needed. This is fixed by no longer adding anything
to the user message.
This patch applies to netcat.c CVS 1.206.
diff --git netcat.c netcat.c
index c04298f..27ecc4e 100644
--- netcat.c
+++ netcat.c
@@ -138,7 +138,8 @@ void set_common_sockopts(int, int);
int process_tos_opt(char *, int *);
int process_tls_opt(char *, int *);
void save_peer_cert(struct tls *_tls_ctx, FILE *_fp);
-void report_sock(const char *, const struct sockaddr *, socklen_t, char *);
+void report_addr(const char *, const struct sockaddr *, socklen_t);
+void report_sock(const char *, int sockfd);
void report_tls(struct tls *tls_ctx, char * host);
void usage(int);
ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
@@ -599,8 +600,8 @@ main(int argc, char *argv[])
err(1, "connect");
if (vflag)
- report_sock("Connection received",
- (struct sockaddr *)&z, len, NULL);
+ report_addr("Connection received from",
+ (struct sockaddr *)&z, len);
readwrite(s, NULL);
} else {
@@ -615,9 +616,8 @@ main(int argc, char *argv[])
err(1, "accept");
}
if (vflag)
- report_sock("Connection received",
- (struct sockaddr *)&cliaddr, len,
- family == AF_UNIX ? host : NULL);
+ report_addr("Connection received from",
+ (struct sockaddr *)&cliaddr, len);
if ((usetls) &&
(tls_cctx = tls_setup_server(tls_ctx,
connfd, host)))
readwrite(connfd, tls_cctx);
@@ -760,7 +760,8 @@ unix_bind(char *path, int flags)
return -1;
}
if (vflag)
- report_sock("Bound", NULL, 0, path);
+ report_addr("Bound to", (struct sockaddr *)&s_un,
+ sizeof(s_un));
return s;
}
@@ -905,7 +906,7 @@ unix_listen(char *path)
return -1;
}
if (vflag)
- report_sock("Listening", NULL, 0, path);
+ report_sock("Listening on", s);
return s;
}
@@ -1047,16 +1048,8 @@ local_listen(const char *host, const char *port, struct
addrinfo hints)
if (listen(s, 1) == -1)
err(1, "listen");
}
- if (vflag && s != -1) {
- struct sockaddr_storage ss;
- socklen_t len;
-
- len = sizeof(ss);
- if (getsockname(s, (struct sockaddr *)&ss, &len) == -1)
- err(1, "getsockname");
- report_sock(uflag ? "Bound" : "Listening",
- (struct sockaddr *)&ss, len, NULL);
- }
+ if (vflag && s != -1)
+ report_sock(uflag ? "Bound to" : "Listening on", s);
freeaddrinfo(res0);
@@ -1713,15 +1706,18 @@ report_tls(struct tls * tls_ctx, char * host)
}
void
-report_sock(const char *msg, const struct sockaddr *sa, socklen_t salen,
- char *path)
+report_addr(const char *msg, const struct sockaddr *sa, socklen_t salen)
{
char host[NI_MAXHOST], port[NI_MAXSERV];
int herr;
int flags = NI_NUMERICSERV;
- if (path != NULL) {
- fprintf(stderr, "%s on %s\n", msg, path);
+ if (sa->sa_family == AF_UNIX) {
+ const struct sockaddr_un *sun = (struct sockaddr_un *) sa;
+ const char *path = (salen < sizeof(struct sockaddr_un))
+ ? "[unknown address]"
+ : sun->sun_path;
+ fprintf(stderr, "%s %s\n", msg, path);
return;
}
@@ -1736,7 +1732,19 @@ report_sock(const char *msg, const struct sockaddr *sa,
socklen_t salen,
errx(1, "getnameinfo: %s", gai_strerror(herr));
}
- fprintf(stderr, "%s on %s %s\n", msg, host, port);
+ fprintf(stderr, "%s %s %s\n", msg, host, port);
+}
+
+void
+report_sock(const char *msg, int sockfd)
+{
+ struct sockaddr_storage ss;
+ socklen_t len;
+
+ len = sizeof(ss);
+ if (getsockname(sockfd, (struct sockaddr *)&ss, &len) == -1)
+ err(1, "getsockname");
+ report_addr(msg, (struct sockaddr *)&ss, len);
}
void