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 -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org