Module Name: src
Committed By: christos
Date: Mon Jan 27 18:30:19 UTC 2025
Modified Files:
src/usr.bin: Makefile
Added Files:
src/usr.bin/getnameinfo: Makefile getnameinfo.1 getnameinfo.c
Log Message:
PR/57953: Attaullah Ansari: Add getnameinfo program
To generate a diff of this commit:
cvs rdiff -u -r1.241 -r1.242 src/usr.bin/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/getnameinfo/Makefile \
src/usr.bin/getnameinfo/getnameinfo.1 \
src/usr.bin/getnameinfo/getnameinfo.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/Makefile
diff -u src/usr.bin/Makefile:1.241 src/usr.bin/Makefile:1.242
--- src/usr.bin/Makefile:1.241 Mon Oct 28 13:55:12 2024
+++ src/usr.bin/Makefile Mon Jan 27 13:30:19 2025
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.241 2024/10/28 17:55:12 nia Exp $
+# $NetBSD: Makefile,v 1.242 2025/01/27 18:30:19 christos Exp $
# from: @(#)Makefile 8.3 (Berkeley) 1/7/94
.include <bsd.own.mk>
@@ -12,7 +12,7 @@ SUBDIR= aiomixer apply asa at audio audi
eject elf2aout elf2ecoff env error expand extattr \
false fdformat fgen fincore find finger flock fmt fold fpr from \
fsplit fstat ftp gcore genassym gencat getaddrinfo getconf getent \
- getopt gettext gprof \
+ getnameinfo getopt gettext gprof \
head hexdump iconv id indent infocmp innetgr ipcrm ipcs join jot \
kdump ktrace ktruss lam last lastcomm ldd leave \
locale locate lock logger login logname look lorder m4 \
Added files:
Index: src/usr.bin/getnameinfo/Makefile
diff -u /dev/null src/usr.bin/getnameinfo/Makefile:1.1
--- /dev/null Mon Jan 27 13:30:19 2025
+++ src/usr.bin/getnameinfo/Makefile Mon Jan 27 13:30:19 2025
@@ -0,0 +1,9 @@
+# $NetBSD: Makefile,v 1.1 2025/01/27 18:30:19 christos Exp $
+
+.include <bsd.own.mk>
+
+PROG = getnameinfo
+
+WARNS = 5
+
+.include <bsd.prog.mk>
Index: src/usr.bin/getnameinfo/getnameinfo.1
diff -u /dev/null src/usr.bin/getnameinfo/getnameinfo.1:1.1
--- /dev/null Mon Jan 27 13:30:19 2025
+++ src/usr.bin/getnameinfo/getnameinfo.1 Mon Jan 27 13:30:19 2025
@@ -0,0 +1,142 @@
+.\" $NetBSD: getnameinfo.1,v 1.1 2025/01/27 18:30:19 christos Exp $
+.\"
+.\" Copyright (c) 2025 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This documentation is derived from text contributed to The NetBSD
+.\" Foundation by Attaullah Ansari.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd January 16, 2025
+.Dt GETNAMEINFO 1
+.Os
+.Sh NAME
+.Nm getnameinfo
+.Nd resolve IP addresses and ports to host and service names
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46rufnNHS
+.Op Fl p Ar port
+.Ar IP-address
+.Sh DESCRIPTION
+The
+.Nm
+utility resolves IP addresses and port numbers to hostnames and service names
+as if with the
+.Xr getnameinfo 3
+library routine and formats them to standard output.
+.Pp
+The output is a single line of space-separated fields:
+.Pp
+.Dl hostname service
+.Pp
+Depending on the flags specified, the output may consist only of the hostname
+or service name, or their numeric representations.
+By default, both are shown.
+.Pp
+Although
+.Nm
+may query the DNS or other sources for name resolution depending on the
+system's
+.Xr nsswitch.conf 5
+configuration, it is not intended to replace DNS-specific tools like
+.Xr dig 1 .
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl 4
+Restrict the lookup to IPv4 addresses only.
+.It Fl 6
+Restrict the lookup to IPv6 addresses only.
+.It Fl r
+Ensure that a name is returned.
+If no name can be resolved, an error is reported.
+This is equivalent to the
+.Dv NI_NAMEREQD
+flag in
+.Xr getnameinfo 3 .
+.It Fl u
+Use UDP instead of the default TCP.
+This is equivalent to the
+.Dv NI_DGRAM
+flag in
+.Xr getnameinfo 3 .
+.It Fl f
+Suppress the fully-qualified domain name (FQDN).
+This is equivalent to the
+.Dv NI_NOFQDN
+flag in
+.Xr getnameinfo 3 .
+.It Fl n
+Display the numeric host address instead of resolving to a hostname.
+This is equivalent to the
+.Dv NI_NUMERICHOST
+flag in
+.Xr getnameinfo 3 .
+.It Fl N
+Display the numeric service name instead of resolving to a service name.
+This is equivalent to the
+.Dv NI_NUMERICSERV
+flag in
+.Xr getnameinfo 3 .
+.It Fl H
+Display only the hostname, omitting the service name.
+.It Fl S
+Display only the service name, omitting the hostname.
+.It Fl p Ar port
+Specify the port number to be used in the lookup.
+.El
+.Sh EXIT STATUS
+.Ex -std getnameinfo
+.Sh EXAMPLES
+Look up the hostname and service name for an IPv4 address:
+.Bd -literal -offset indent
+$ getnameinfo -4 -p 80 93.184.216.34
+example.com http
+.Ed
+.Pp
+Look up the numeric host and service for an IPv6 address:
+.Bd -literal -offset indent
+$ getnameinfo -nN -p 443 2606:2800:220:1:248:1893:25c8:1946
+2606:2800:220:1:248:1893:25c8:1946 443
+.Ed
+.Pp
+Resolve an address to its hostname but suppress the service name:
+.Bd -literal -offset indent
+$ getnameinfo -H -p 22 192.0.2.1
+example-host
+.Ed
+.Pp
+Resolve a hostname and service for a UDP connection:
+.Bd -literal -offset indent
+$ getnameinfo -u -p 53 198.51.100.2
+example-dns-server domain
+.Ed
+.Sh SEE ALSO
+.Xr dig 1 ,
+.Xr getaddrinfo 1 ,
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3 ,
+.Xr inet 3 ,
+.Xr hosts 5 ,
+.Xr nsswitch.conf 5
Index: src/usr.bin/getnameinfo/getnameinfo.c
diff -u /dev/null src/usr.bin/getnameinfo/getnameinfo.c:1.1
--- /dev/null Mon Jan 27 13:30:19 2025
+++ src/usr.bin/getnameinfo/getnameinfo.c Mon Jan 27 13:30:19 2025
@@ -0,0 +1,262 @@
+/* $NetBSD: getnameinfo.c,v 1.1 2025/01/27 18:30:19 christos Exp $ */
+
+/*
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Attaullah Ansari.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: getnameinfo.c,v 1.1 2025/01/27 18:30:19 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * getnameinfo: Resolve IP addresses and ports to hostnames and service names,
+ * similar to the getnameinfo function in the standard library.
+ *
+ * usage:
+ * getnameinfo [-46rufnNHS] [-p port] <IP-address>
+ *
+ * -4: Restrict lookup to IPv4 addresses only
+ * -6: Restrict lookup to IPv6 addresses only
+ * -r: Ensure that the name is returned (error if no name is found)
+ * -u: Use UDP instead of the default TCP
+ * -f: Suppress the fully-qualified domain name (FQDN)
+ * -n: Display the numeric host address instead of the hostname
+ * -N: Display the numeric service name instead of the service name
+ * -H: Display only the hostname, omitting the service name
+ * -S: Display only the service name, omitting the hostname
+ * -p: Specify the port number to be used in the lookup
+ */
+
+
+static void usage(void) __dead;
+static void print_result(int, int, char *, char *);
+static in_port_t get_port(const char *);
+static uint8_t get_family(const char *);
+
+int
+main(int argc, char **argv)
+{
+ int hostlen = NI_MAXHOST, servlen = NI_MAXSERV;
+ char hostname[hostlen], service[servlen];
+ bool hostname_only = false, service_only = false;
+ int family = AF_UNSPEC;
+ int flags = 0;
+ char *address = NULL;
+ in_port_t port = 0;
+ struct sockaddr_storage addr_st;
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in6 *addr_in6;
+ int addr_stlen;
+ int ch;
+ int error;
+
+ setprogname(argv[0]);
+
+ while ((ch = getopt(argc, argv, "46rufnNHSp:")) != -1) {
+ switch (ch) {
+ case '4':
+ if (family != AF_UNSPEC)
+ goto opt46;
+ family = AF_INET;
+ break;
+ case '6':
+ if (family != AF_UNSPEC)
+ goto opt46;
+ family = AF_INET6;
+ break;
+ case 'r':
+ flags |= NI_NAMEREQD;
+ break;
+ case 'u':
+ flags |= NI_DGRAM;
+ break;
+ case 'f':
+ flags |= NI_NOFQDN;
+ break;
+ case 'n':
+ flags |= NI_NUMERICHOST;
+ break;
+ case 'N':
+ flags |= NI_NUMERICSERV;
+ break;
+ case 'H':
+ if (service_only)
+ goto optHS;
+ hostname_only = true;
+ break;
+ case 'S':
+ if (hostname_only)
+ goto optHS;
+ service_only = true;
+ break;
+ case 'p':
+ port = get_port(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1) {
+ warnx("Too many addresses");
+ usage();
+ }
+
+ if (argc == 0 && (hostname_only ||
+ (hostname_only == 0 && service_only == 0))) {
+ warnx("No IP address provided");
+ usage();
+ }
+
+ if (port == 0 && (service_only ||
+ (hostname_only == 0 && service_only == 0))) {
+ warnx("No port number provided");
+ usage();
+ }
+
+ if (argc == 1) {
+ address = argv[0];
+ if (family == AF_UNSPEC)
+ family = get_family(address);
+ }
+
+ switch (family) {
+ case AF_INET:
+ addr_in = (struct sockaddr_in *)&addr_st;
+ addr_in->sin_family = family;
+ addr_in->sin_port = htons(port);
+ if (inet_pton(family, address, &addr_in->sin_addr) == 0) {
+ warnx("Invalid IPv4 address: %s", address);
+ return EXIT_FAILURE;
+ }
+ addr_stlen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addr_in6 = (struct sockaddr_in6 *)&addr_st;
+ addr_in6->sin6_family = family;
+ addr_in6->sin6_port = htons(port);
+ if (inet_pton(family, address, &addr_in6->sin6_addr) == 0) {
+ warnx("Invalid IPv6 address: %s", address);
+ return EXIT_FAILURE;
+ }
+ addr_stlen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ warnx("Unsupported family %d", family);
+ return EXIT_FAILURE;
+ }
+
+ if (hostname_only)
+ servlen = 0;
+ else if (service_only)
+ hostlen = 0;
+
+ error = getnameinfo((struct sockaddr *)&addr_st, addr_stlen,
+ hostname, hostlen, service, servlen, flags);
+ if (error)
+ errx(EXIT_FAILURE, "%s", gai_strerror(error));
+
+ print_result(hostname_only, service_only, hostname, service);
+
+ return EXIT_SUCCESS;
+opt46:
+ warnx("Options -4 and -6 cannot be used together");
+ usage();
+optHS:
+ warnx("Options -H and -S cannot be used together");
+ usage();
+}
+
+static uint8_t
+get_family(const char* address)
+{
+ struct in_addr ipv4_addr;
+ struct in6_addr ipv6_addr;
+
+ if (inet_pton(AF_INET, address, &ipv4_addr) == 1)
+ return AF_INET;
+
+ if (inet_pton(AF_INET6, address, &ipv6_addr) == 1)
+ return AF_INET6;
+
+ errx(EXIT_FAILURE, "Invalid addrsss %s", address);
+}
+
+static in_port_t
+get_port(const char *port_str)
+{
+ int r;
+ intmax_t port = strtoi(port_str, NULL, 0, 0, 65535, &r);
+ if (r)
+ errc(EXIT_FAILURE, r, "Invalid port number %s", port_str);
+
+ return (in_port_t)port;
+}
+
+static void
+print_result(int hostname_only, int service_only, char *hostname, char *service)
+{
+ int n;
+ if (hostname_only)
+ n = printf("%s\n", hostname);
+ else if (service_only)
+ n = printf("%s\n", service);
+ else
+ n = printf("%s %s\n", hostname, service);
+ if (n < 0)
+ err(EXIT_FAILURE, "printf");
+}
+
+
+static void __dead
+usage(void)
+{
+ (void)fprintf(stderr, "Usage: %s", getprogname());
+ (void)fprintf(stderr, " [-46rufnNHS] [-p port] <IP-address>\n");
+ exit(EXIT_FAILURE);
+}