From 639b96abc61265c3f0cff5203e527e07923823fb Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 6 Jan 2004 08:29:34 +0000 Subject: [PATCH] Add the -r option to set the hostname based on a reverse lookup of an IP address, the -i option to set the hostname based on a reverse lookup of an interface's primary IP address, and -6 and -4 to select an interface's IPV4 or IPV6 address to run the reverse on. Submitted-by: Kent Ibbetson --- bin/hostname/hostname.1 | 15 ++- bin/hostname/hostname.c | 272 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 274 insertions(+), 13 deletions(-) diff --git a/bin/hostname/hostname.1 b/bin/hostname/hostname.1 index e93358b47c..443ffbafa9 100644 --- a/bin/hostname/hostname.1 +++ b/bin/hostname/hostname.1 @@ -31,7 +31,7 @@ .\" .\" @(#)hostname.1 8.2 (Berkeley) 4/28/95 .\" $FreeBSD: src/bin/hostname/hostname.1,v 1.10.2.4 2002/04/22 22:20:29 keramida Exp $ -.\" $DragonFly: src/bin/hostname/hostname.1,v 1.2 2003/06/17 04:22:50 dillon Exp $ +.\" $DragonFly: src/bin/hostname/hostname.1,v 1.3 2004/01/06 08:29:34 dillon Exp $ .\" .Dd April 28, 1995 .Dt HOSTNAME 1 @@ -42,7 +42,7 @@ .Sh SYNOPSIS .Nm .Op Fl s -.Op Ar name-of-host +.Op Ar name-of-host | -r ip-address | -i interface [-6 | -4] .Sh DESCRIPTION The .Nm @@ -62,6 +62,17 @@ Options: .It Fl s Trim off any domain information from the printed name. +.It Fl r +Retrieve hostname via ip lookup. The hostname is set to the first (official) +name returned for the supplied ip address. Can be an IPv6 or IPv4 address. +.It Fl i +Retrieve hostname via supplied interface name. +.It Fl 6 +Used in conjunction with -i to select the 1st IPv6 address on the interface. +.It Fl 4 +Used in conjunction with -i to select the 1st IPv4 address on the interface. +This is the default and assumed if -6 or -4 is not supplied. + .El .Sh SEE ALSO .Xr gethostname 3 , diff --git a/bin/hostname/hostname.c b/bin/hostname/hostname.c index 14c6b9516d..cdfdb14ef3 100644 --- a/bin/hostname/hostname.c +++ b/bin/hostname/hostname.c @@ -33,10 +33,26 @@ * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. * @(#)hostname.c 8.1 (Berkeley) 5/31/93 * $FreeBSD: src/bin/hostname/hostname.c,v 1.10.2.1 2001/08/01 02:40:23 obrien Exp $ - * $DragonFly: src/bin/hostname/hostname.c,v 1.4 2003/09/28 14:39:14 hmp Exp $ + * $DragonFly: src/bin/hostname/hostname.c,v 1.5 2004/01/06 08:29:34 dillon Exp $ */ #include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -44,18 +60,101 @@ #include #include -int main (int, char *[]); -void usage (void); +#include +#include +#include +#include + +#include + +#define HST_IF (1 << 0) +#define HST_IF_V6 (1 << 1) +#define HST_IF_V4 (1 << 2) + + + +/* + * Expand the compacted form of addresses as returned via the + * configuration read via sysctl(). + * Lifted from getifaddrs(3) + */ + +static void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); +static void usage (void); + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +static +void +rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) +{ + struct sockaddr *sa; + int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} int main(int argc, char **argv) { - int ch, sflag; - char *p, hostname[MAXHOSTNAMELEN]; + int ch,sflag,rflag,ret,flag6,iflag; + char hostname[MAXHOSTNAMELEN]; + char *srflag,*siflag; + struct hostent *hst; + struct in_addr ia; + struct in6_addr ia6; + + int mib[6]; + int needed; + char *buf,*lim,*next,*p; + int idx; + struct sockaddr_dl *sdl; + struct rt_msghdr *rtm; + struct if_msghdr *ifm; + struct ifa_msghdr *ifam; + struct rt_addrinfo info; + struct sockaddr_in *sai; + struct sockaddr_in6 *sai6; + + srflag = NULL; + iflag = sflag = rflag = 0; + flag6 = 0; + hst = NULL; - sflag = 0; - while ((ch = getopt(argc, argv, "s")) != -1) + while ((ch = getopt(argc, argv, "46i:r:s")) != -1) { switch (ch) { + case '4': + iflag |= HST_IF_V4; + break; + case '6': + iflag |= HST_IF_V6; + break; + case 'i': + siflag = (char*)calloc(1,sizeof(char) * (strlen((char*)optarg)+1)); + if (siflag) { + iflag |= HST_IF; + strlcpy(siflag, (char*)optarg, strlen((char*)optarg)+1); + } else { + errx(1, "malloc"); + } + break; + case 'r': + srflag = (char*)calloc(1,sizeof(char) * (strlen((char*)optarg)+1)); + if (srflag) { + rflag = 1; + strlcpy(srflag, (char*)optarg, strlen((char*)optarg)+1); + } else { + errx(1, "malloc"); + } + break; case 's': sflag = 1; break; @@ -63,13 +162,163 @@ main(int argc, char **argv) default: usage(); } + } argc -= optind; argv += optind; if (argc > 1) usage(); - if (*argv) { + if (iflag && *argv) { + free(siflag); + usage(); + } + + if (rflag && *argv) { + free(srflag); + usage(); + } + + if (rflag && (iflag & HST_IF)) { + usage(); + free(srflag); + free(siflag); + } + + if ((iflag & HST_IF_V6) && (iflag & HST_IF_V4)) { + free(siflag); + usage(); + } + + if (!(iflag & HST_IF) && ((iflag & HST_IF_V6)||iflag & HST_IF_V4)) { + free(siflag); + usage(); + } + + if (iflag & HST_IF) { + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + idx = 0; + needed = 1; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + free(siflag); + errx(1, "iflist-sysctl-estimate:%i",errno); + } + if ((buf = malloc(needed)) == NULL) { + free(siflag); + errx(1, "malloc"); + } + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(siflag); + errx(1, "actual retrieval of interface table"); + } + + lim = buf + needed; + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + switch (rtm->rtm_type) { + case RTM_IFINFO: + ifm = (struct if_msghdr *)(void *)rtm; + + if (ifm->ifm_addrs & RTA_IFP) { + sdl = (struct sockaddr_dl *)(ifm+1); + if (strcmp(siflag,sdl->sdl_data) == 0) { + idx = ifm->ifm_index; + } + } + break; + case RTM_NEWADDR: + ifam = (struct ifa_msghdr *)(void *)rtm; + + if (ifam->ifam_index == idx) { + info.rti_addrs = ifam->ifam_addrs; + rt_xaddrs((char *)(ifam + 1), + ifam->ifam_msglen + (char *)ifam, &info); + sai = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; + + if (iflag & HST_IF_V6) { + if (sai->sin_family == AF_INET6) { + sai6 = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA]; + hst = gethostbyaddr((const char*)&sai6->sin6_addr, + sizeof(sai6->sin6_addr),AF_INET6); + + if (h_errno == NETDB_SUCCESS) { + next = buf + needed; + continue; + } + } + } else { + if ((sai->sin_family == AF_INET)) { + + hst = gethostbyaddr((const char*)&sai->sin_addr, + sizeof(sai->sin_addr),AF_INET); + + if (h_errno == NETDB_SUCCESS) { + next = buf + needed; + continue; + } + } + } + } + break; + } /* switch */ + } /* loop */ + + free(buf); + free(siflag); + + if (idx == 0) { + errx(1,"interface not found"); + } + + if (h_errno == NETDB_SUCCESS) { + if (sethostname(hst->h_name, (int)strlen(hst->h_name))) + errx(1, "sethostname"); + } else if (h_errno == HOST_NOT_FOUND) { + errx(1,"hostname not found"); + } else { + errx(1,"gethostbyaddr"); + } + + if (idx == 0) { + errx(1,"interface not found"); + } + } else if (rflag) { + ret = inet_pton(AF_INET, srflag, &ia); + if (ret != 1) { + // check IPV6 + ret = inet_pton(AF_INET6, srflag, &ia6); + + if (ret != 1) { + free(srflag); + errx(1, "invalid ip address"); + } + + flag6 = 1; + } + + if (flag6 == 1) + hst = gethostbyaddr((const char*)&ia6, sizeof(ia6), AF_INET6); + else + hst = gethostbyaddr((const char*)&ia, sizeof(ia), AF_INET); + if (!hst) { + free(srflag); + if(h_errno == HOST_NOT_FOUND) + errx(1,"host not found\n"); + } + + if (sethostname(hst->h_name, (int)strlen(hst->h_name))) + err(1, "sethostname"); + } else if (*argv) { if (sethostname(*argv, (int)strlen(*argv))) err(1, "sethostname"); } else { @@ -82,10 +331,11 @@ main(int argc, char **argv) exit(0); } -void +static void usage(void) { - - (void)fprintf(stderr, "usage: hostname [-s] [name-of-host]\n"); + fprintf(stderr, "usage: hostname [-s] [name-of-host |" + " -r ip-address | -i interface [-4 | -6]]\n"); exit(1); } + -- 2.35.2