[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