summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>2000-09-22 01:06:40 +0000
committerwollman <wollman@FreeBSD.org>2000-09-22 01:06:40 +0000
commit9d63cb2085c2e34ecf7fdeced7953897170810f6 (patch)
tree2b559fb29104a282741be8d1a23af090b72a2722 /usr.bin
parent31737e2a38218128fe816a189468f2f77cd1eaff (diff)
downloadFreeBSD-src-9d63cb2085c2e34ecf7fdeced7953897170810f6.zip
FreeBSD-src-9d63cb2085c2e34ecf7fdeced7953897170810f6.tar.gz
Implement IPv6 support. Also restructure the way multi-homed hosts
are treated, regardless of protocol.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/finger/net.c148
1 files changed, 91 insertions, 57 deletions
diff --git a/usr.bin/finger/net.c b/usr.bin/finger/net.c
index 2903c06..00547ec 100644
--- a/usr.bin/finger/net.c
+++ b/usr.bin/finger/net.c
@@ -62,66 +62,72 @@ static const char rcsid[] =
#include <limits.h>
#include "finger.h"
-void
-cleanup(sig)
- int sig;
-{
- exit(0);
-}
+extern int lflag; /* XXX finger.h? */
+extern int Tflag; /* XXX finger.h? */
+
+static void cleanup(int sig);;
+static int do_protocol(const char *name, const struct addrinfo *ai);
+static void trying(const struct addrinfo *ai);
void
netfinger(name)
char *name;
{
- int cnt;
- int line_len;
- extern int lflag;
- extern int Tflag;
- register FILE *fp;
- register int c, lastc;
- struct in_addr defaddr;
- struct hostent *hp, def;
- struct servent *sp;
- struct sockaddr_in sin;
- int s;
- char *alist[1], *host;
- struct iovec iov[3];
- struct msghdr msg;
+ int error, multi;
+ char *host;
+ struct addrinfo *ai, *ai0;
+ static struct addrinfo hint;
- if (!(host = rindex(name, '@')))
+ host = strrchr(name, '@');
+ if (host == 0)
return;
*host++ = '\0';
signal(SIGALRM, cleanup);
- (void) alarm(TIME_LIMIT);
- if (isdigit(*host) && (defaddr.s_addr = inet_addr(host)) != -1) {
- def.h_name = host;
- def.h_addr_list = alist;
- def.h_addr = (char *)&defaddr;
- def.h_length = sizeof(struct in_addr);
- def.h_addrtype = AF_INET;
- def.h_aliases = 0;
- hp = &def;
- } else if (!(hp = gethostbyname(host))) {
- warnx("unknown host: %s", host);
- return;
- }
- if (!(sp = getservbyname("finger", "tcp"))) {
- warnx("tcp/finger: unknown service");
+ alarm(TIME_LIMIT);
+
+ hint.ai_flags = AI_CANONNAME;
+ hint.ai_family = PF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(host, "finger", &hint, &ai0);
+ if (error) {
+ warnx("%s: %s", host, gai_strerror(error));
return;
}
- sin.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr, (char *)&sin.sin_addr, MIN(hp->h_length,sizeof(sin.sin_addr)));
- sin.sin_port = sp->s_port;
- if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
- perror("finger: socket");
- return;
+
+ multi = (ai0->ai_next) != 0;
+ printf("[%s]\n", ai0->ai_canonname);
+
+ for (ai = ai0; ai != 0; ai = ai->ai_next) {
+ if (multi)
+ trying(ai);
+
+ error = do_protocol(name, ai);
+ if (!error)
+ break;
}
+ alarm(0);
+ freeaddrinfo(ai0);
+}
- /* have network connection; identify the host connected with */
- (void)printf("[%s]\n", hp->h_name);
+static int
+do_protocol(const char *name, const struct addrinfo *ai)
+{
+ int cnt, error, line_len, s;
+ register FILE *fp;
+ register int c, lastc;
+ struct iovec iov[3];
+ struct msghdr msg;
- msg.msg_name = (void *)&sin;
- msg.msg_namelen = sizeof sin;
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s < 0) {
+ warn("socket(%d, %d, %d)", ai->ai_family, ai->ai_socktype,
+ ai->ai_protocol);
+ return -1;
+ }
+
+ msg.msg_name = (void *)ai->ai_addr;
+ msg.msg_namelen = ai->ai_addrlen;
msg.msg_iov = iov;
msg.msg_iovlen = 0;
msg.msg_control = 0;
@@ -139,16 +145,22 @@ netfinger(name)
iov[msg.msg_iovlen].iov_base = "\r\n";
iov[msg.msg_iovlen++].iov_len = 2;
- /* -T disables T/TCP: compatibility option to finger broken hosts */
- if (Tflag && connect(s, (struct sockaddr *)&sin, sizeof (sin))) {
- perror("finger: connect");
- return;
+ /*
+ * -T disables data-on-SYN: compatibility option to finger broken
+ * hosts. Also, the implicit-open API is broken on IPv6, so do
+ * the explicit connect there, too.
+ */
+ if ((Tflag || ai->ai_addr->sa_family == AF_INET6)
+ && connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+ warn("connect");
+ close(s);
+ return -1;
}
if (sendmsg(s, &msg, 0) < 0) {
- perror("finger: sendmsg");
+ warn("sendmsg");
close(s);
- return;
+ return -1;
}
/*
@@ -199,15 +211,37 @@ netfinger(name)
if (lastc == '\n' || lastc == '\r')
line_len = 0;
}
- if (lastc != '\n')
- putchar('\n');
-
if (ferror(fp)) {
/*
* Assume that whatever it was set errno...
*/
- perror("finger: read");
+ warn("reading from network");
}
- (void)fclose(fp);
+ if (lastc != '\n')
+ putchar('\n');
+
+ fclose(fp);
}
+ return 0;
+}
+
+static void
+trying(const struct addrinfo *ai)
+{
+ char buf[NI_MAXHOST];
+
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, buf, sizeof buf,
+ (char *)0, 0, NI_NUMERICHOST) != 0)
+ return; /* XXX can't happen */
+
+ printf("Trying %s...\n", buf);
}
+
+void
+cleanup(int sig)
+{
+#define ERRSTR "Timed out.\n"
+ write(STDERR_FILENO, ERRSTR, sizeof ERRSTR);
+ exit(1);
+}
+
OpenPOWER on IntegriCloud