[Hostname-devel] Bug#562830: hostname: Better support for multi-homed and mobile machines

Gábor Gombás gombasg at sztaki.hu
Mon Dec 28 11:25:37 UTC 2009


Package: hostname
Version: 3.01
Severity: wishlist
Tags: patch

Hi,

The options --fqdn, --domain and --ip-address are problematic because
they all assume that the output of gethostname(3) can be resolved by the
DNS, and that a machine has only one FQDN/domain/address.

The following patch tries to improve the situation by introducing two
new options: --all-fqdns and --all-ip-addresses that do not depend on
the value of gethostname(3) but properly enumerate the configured
network interfaces/addresses instead. At the same time, warnings are
added to the man page not to use the old --fqdn, --domain and
--ip-address options.

I left the French man page untouched as I do not speak the language.

I've tested it on some machines with multiple interfaces and multiple
IPv4 addresses on every interface, and it seems to work fine. I could
not test it with IPv6, but I do not expect any real issues.

Gabor

diff -u -r hostname-3.01/hostname.1 hostname-3.01-new/hostname.1
--- hostname-3.01/hostname.1	2009-09-22 14:21:50.000000000 +0200
+++ hostname-3.01-new/hostname.1	2009-12-28 12:08:15.807846478 +0100
@@ -21,8 +21,12 @@
 .RB [ \-\-domain ]
 .RB [ \-f ]
 .RB [ \-\-fqdn ]
+.RB [ \-A ]
+.RB [ \-\-all-fqdns ]
 .RB [ \-i ]
 .RB [ \-\-ip-address ]
+.RB [ \-I ]
+.RB [ \-\-all-ip-addresses ]
 .RB [ \-\-long ]
 .RB [ \-s ]
 .RB [ \-\-short ]
@@ -89,7 +93,10 @@
 .B dnsdomainname
 will print the domain part of the FQDN (Fully Qualified Domain Name). The
 complete FQDN of the system is returned with
-.BR "hostname \-\-fqdn" .
+.BR "hostname \-\-fqdn"
+(but see the warnings in section
+.B "THE FQDN"
+below).
 
 .SS "SET NAME"
 When called with one argument or with the
@@ -142,6 +149,16 @@
 how you can change it. Usually (if the hosts file is parsed before DNS or
 NIS) you can change it in
 .IR /etc/hosts .
+.LP
+If a machine has multiple network interfaces/addresses or is used in a
+mobile environment, then it may either have multiple FQDNs/domain names
+or none at all. Therefore avoid using
+.BR "hostname \-\-fqdn" ,
+.BR "hostname \-\-domain"
+and
+.BR "dnsdomainname" .
+.BR "hostname \-\-ip-address"
+is subject to the same limitations so it should be avoided as well.
 
 .SH OPTIONS
 .TP
@@ -160,7 +177,9 @@
 to get the DNS domain name because it will show the NIS domain name and
 not the DNS domain name. Use
 .B dnsdomainname
-instead.
+instead. Ssee the warnings in section
+.B "THE FQDN"
+above, and avoid using this option.
 .TP
 .I "\-F, \-\-file filename"
 Read the host name from the specified file. Comments (lines starting with
@@ -170,13 +189,36 @@
 Display the FQDN (Fully Qualified Domain Name). A FQDN consists of a
 short host name and the DNS domain name. Unless you are using bind or NIS
 for host lookups you can change the FQDN and the DNS domain name (which is
-part of the FQDN) in the \fI/etc/hosts\fR file.
+part of the FQDN) in the \fI/etc/hosts\fR file. See the warnings in section
+.B "THE FQDN"
+above, and avoid using this option; use
+.BR "hostname \-\-all-fqdns"
+instead.
+.TP
+.I "\-A, \-\-all-fqdns"
+Displays all FQDNs of the machine. This option enumerates all configured
+network addresses on all configured network interfaces, and translates
+them to DNS domain names. Addresses that cannot be translated (i.e. because
+they do not have an appropriate reverse DNS entry) are skipped. Note that
+different addresses may resolve to the same name, therefore the output may
+contain duplicate entries. Do not make any assumptions about the order of the
+output.
 .TP
 .I "\-h, \-\-help"
 Print a usage message and exit.
 .TP
 .I "\-i, \-\-ip-address"
-Display the network address(es) of the host.
+Display the network address(es) of the host name. Note that this works only
+if the host name can be resolved. Avoid using this option; use
+.BR "hostname \-\-all-ip-addresses"
+instead.
+.TP
+.I "\-I, \-\-all-ip-addresses"
+Display all network addresses of the host. This option enumerates all
+configured addresses on all network interfaces. The loopback interface and IPv6
+link-local addresses are omitted. Contrary to option \fI-i\fR, this option
+does not depend on name resolution. Do not make any assumptions about the
+order of the output.
 .TP
 .I "\-s, \-\-short"
 Display the short host name. This is the host name cut at the first dot.
diff -u -r hostname-3.01/hostname.c hostname-3.01-new/hostname.c
--- hostname-3.01/hostname.c	2009-10-27 13:19:28.000000000 +0100
+++ hostname-3.01-new/hostname.c	2009-12-28 11:54:50.911346554 +0100
@@ -3,7 +3,7 @@
  *		that maintains the host name and the domain name. It
  *		is also used to show the FQDN and the IP-Addresses.
  *
- * Usage:	hostname [-d|-f|-s|-a|-i|-y]
+ * Usage:	hostname [-d|-f|-s|-a|-i|-y|-A|-I]
  *		hostname [-h|-V]
  *		hostname [-b] {name|-F file}
  *		dnsdomainname
@@ -31,6 +31,8 @@
 #include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <net/if.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -45,7 +47,7 @@
 
 #define VERSION "3.00"
 
-enum type_t { DEFAULT, DNS, FQDN, SHORT, ALIAS, IP, NIS, NIS_DEF };
+enum type_t { DEFAULT, DNS, FQDN, SHORT, ALIAS, IP, NIS, NIS_DEF, ALL_FQDNS, ALL_IPS };
 
 char *progname;
 
@@ -151,7 +153,7 @@
 {
 	fprintf(stream,
 		"Usage: hostname [-v] [-b] {hostname|-F file}         set host name (from file)\n"
-		"       hostname [-v] [-d|-f|-s|-a|-i|-y]             display formatted name\n"
+		"       hostname [-v] [-d|-f|-s|-a|-i|-y|-A|-I]       display formatted name(s)\n"
 		"       hostname [-v]                                 display host name\n"
 		"\n"
 		"       {yp,nis,}domainname [-v] {nisdomain|-F file}  set NIS domain name (from file)\n"
@@ -166,14 +168,16 @@
 		"       dnsdomainname=hostname -d\n"
 		"\n"
 		"Program options:\n"
-		"    -s, --short           short host name\n"
-		"    -a, --alias           alias names\n"
-		"    -i, --ip-address      addresses for the host name\n"
-		"    -f, --fqdn, --long    long host name (FQDN)\n"
-		"    -d, --domain          DNS domain name\n"
-		"    -y, --yp, --nis       NIS/YP domain name\n"
-		"    -b, --boot            set default hostname if none available\n"
-		"    -F, --file            read host name or NIS domain name from given file\n"
+		"    -s, --short            short host name\n"
+		"    -a, --alias            alias names\n"
+		"    -i, --ip-address       addresses for the host name\n"
+		"    -I, --all-ip-addresses all addresses for the host\n"
+		"    -f, --fqdn, --long     long host name (FQDN)\n"
+		"    -A, --all-fqdns        all long host names (FQDNs)\n"
+		"    -d, --domain           DNS domain name\n"
+		"    -y, --yp, --nis        NIS/YP domain name\n"
+		"    -b, --boot             set default hostname if none available\n"
+		"    -F, --file             read host name or NIS domain name from given file\n"
 		"\n"
 		"Description:\n"
 		"   This command can get or set the host name or the NIS domain name. You can\n"
@@ -249,6 +253,7 @@
 {
 	struct addrinfo *res;
 	struct addrinfo hints;
+	struct ifaddrs *ifa, *ifap;
 	char *p;
 	int ret;
 
@@ -265,6 +270,57 @@
 		case NIS_DEF:
 			printf("%s\n", localnisdomain());
 			break;
+		case ALL_IPS:
+		case ALL_FQDNS: {
+			char buf[INET6_ADDRSTRLEN];
+			int flags, ret, family, addrlen;
+
+			/* What kind of information do we want from getnameinfo()? */
+			flags = (type == ALL_IPS) ? NI_NUMERICHOST : NI_NAMEREQD;
+
+			if (getifaddrs(&ifa) != 0)
+				errx(1, "%s", strerror(errno));
+			for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
+				/* Skip interfaces that have no configured addresses */
+				if (ifap->ifa_addr == NULL)
+					continue;
+				/* Skip the loopback interface */
+				if (ifap->ifa_flags & IFF_LOOPBACK)
+					continue;
+				/* Skip interfaces that are not UP */
+				if (!(ifap->ifa_flags & IFF_UP))
+					continue;
+
+				/* Only handle IPv4 and IPv6 addresses */
+				family = ifap->ifa_addr->sa_family;
+				if (family != AF_INET && family != AF_INET6)
+					continue;
+
+				addrlen = (family == AF_INET) ? sizeof(struct sockaddr_in) :
+								sizeof(struct sockaddr_in6);
+
+				/* Skip IPv6 link-local addresses */
+				if (family == AF_INET6) {
+					struct sockaddr_in6 *sin6;
+
+					sin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
+					if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+							IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
+						continue;
+				}
+
+				ret = getnameinfo(ifap->ifa_addr, addrlen,
+						  buf, sizeof(buf), NULL, 0, flags);
+
+				/* Just skip addresses that cannot be translated */
+				if (ret != 0 && (type != ALL_FQDNS || ret != EAI_NONAME))
+					errx(1, "%s", gai_strerror(ret));
+
+				printf("%s\n", buf);
+			}
+			freeifaddrs(ifa);
+			break;
+		}
 		default:
 			memset(&hints, 0, sizeof(struct addrinfo));
 			hints.ai_socktype = SOCK_DGRAM;
@@ -376,6 +432,7 @@
 		{"boot", no_argument, 0, 'b'},
 		{"file", required_argument, 0, 'F'},
 		{"fqdn", no_argument, 0, 'f'},
+		{"all-fqdns", no_argument, 0, 'A'},
 		{"help", no_argument, 0, 'h'},
 		{"long", no_argument, 0, 'f'},
 		{"short", no_argument, 0, 's'},
@@ -383,6 +440,7 @@
 		{"verbose", no_argument, 0, 'v'},
 		{"alias", no_argument, 0, 'a'},
 		{"ip-address", no_argument, 0, 'i'},
+		{"all-ip-addresses", no_argument, 0, 'I'},
 		{"nis", no_argument, 0, 'y'},
 		{"yp", no_argument, 0, 'y'},
 		{0, 0, 0, 0}
@@ -399,7 +457,7 @@
 	else if (!strcmp(progname, "nisdomainname"))
 		type = NIS_DEF;
 
-	while((o = getopt_long(argc, argv, "adfbF:h?isVvy", long_options, NULL)) != -1)
+	while((o = getopt_long(argc, argv, "aAdfbF:h?iIsVvy", long_options, NULL)) != -1)
 		switch (o) {
 		case 'd':
 			type = DNS;
@@ -410,9 +468,15 @@
 		case 'f':
 			type = FQDN;
 			break;
+		case 'A':
+			type = ALL_FQDNS;
+			break;
 		case 'i':
 			type = IP;
 			break;
+		case 'I':
+			type = ALL_IPS;
+			break;
 		case 's':
 			type = SHORT;
 			break;

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'stable'), (110, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.31.6 (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages hostname depends on:
ii  libc6                         2.10.2-2   GNU C Library: Shared libraries

hostname recommends no packages.

hostname suggests no packages.

-- no debconf information





More information about the Hostname-devel mailing list