Home | History | Annotate | Line # | Download | only in hostname
hostname.c revision 1.20
      1 /* $NetBSD: hostname.c,v 1.20 2013/07/19 15:53:00 christos Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
     35  The Regents of the University of California.  All rights reserved.");
     36 #endif /* not lint */
     37 
     38 #ifndef lint
     39 #if 0
     40 static char sccsid[] = "@(#)hostname.c	8.2 (Berkeley) 4/28/95";
     41 #else
     42 __RCSID("$NetBSD: hostname.c,v 1.20 2013/07/19 15:53:00 christos Exp $");
     43 #endif
     44 #endif /* not lint */
     45 
     46 #include <sys/param.h>
     47 #include <sys/socket.h>
     48 
     49 #include <net/if.h>
     50 #include <netinet/in.h>
     51 
     52 #include <err.h>
     53 #include <ifaddrs.h>
     54 #include <netdb.h>
     55 #include <stdio.h>
     56 #include <stdlib.h>
     57 #include <string.h>
     58 #include <unistd.h>
     59 
     60 __dead static void usage(void);
     61 
     62 int
     63 main(int argc, char *argv[])
     64 {
     65 	int ch, Aflag, aflag, dflag, Iflag, iflag, fflag, sflag, i;
     66 	char *p, hostname[MAXHOSTNAMELEN + 1];
     67 	struct addrinfo hints, *ainfos, *ai;
     68 	struct hostent *hent;
     69 	struct ifaddrs *ifa, *ifp;
     70 	struct sockaddr_in6 *sin6;
     71 	char buf[MAX(MAXHOSTNAMELEN + 1, INET6_ADDRSTRLEN)];
     72 
     73 	setprogname(argv[0]);
     74 	Aflag = aflag = dflag = Iflag = iflag = fflag = sflag = 0;
     75 	while ((ch = getopt(argc, argv, "AadIifs")) != -1)
     76 		switch (ch) {
     77 		case 'A':
     78 			Aflag = 1;
     79 			break;
     80 		case 'a':
     81 			aflag = 1;
     82 			break;
     83 		case 'd':
     84 			dflag = 1;
     85 			break;
     86 		case 'I':
     87 			Iflag = 1;
     88 			break;
     89 		case 'i':
     90 			iflag = 1;
     91 			break;
     92 		case 'f':
     93 			fflag = 1;
     94 			break;
     95 		case 's':
     96 			sflag = 1;
     97 			break;
     98 		case '?':
     99 		default:
    100 			usage();
    101 		}
    102 	argc -= optind;
    103 	argv += optind;
    104 
    105 	if (argc > 1)
    106 		usage();
    107 
    108 	if (*argv) {
    109 		if (sethostname(*argv, strlen(*argv)))
    110 			err(1, "sethostname");
    111 	} else if (Aflag || Iflag) {
    112 		if (getifaddrs(&ifa) == -1)
    113 			err(1, "getifaddrs");
    114 		for (ifp = ifa; ifp; ifp = ifp->ifa_next) {
    115 			if (ifp->ifa_addr == NULL ||
    116 			    ifp->ifa_flags & IFF_LOOPBACK ||
    117 			    !(ifp->ifa_flags & IFF_UP))
    118 				continue;
    119 
    120 			switch(ifp->ifa_addr->sa_family) {
    121 			case AF_INET:
    122 				break;
    123 			case AF_INET6:
    124 				/* Skip link local addresses */
    125 				sin6 = (struct sockaddr_in6 *)ifp->ifa_addr;
    126 				if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
    127 				    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
    128 					continue;
    129 				break;
    130 			default:
    131 				/* We only translate IPv4 or IPv6 addresses */
    132 				continue;
    133 			}
    134 			i = getnameinfo(ifp->ifa_addr, ifp->ifa_addr->sa_len,
    135 			    buf, sizeof(buf), NULL, 0,
    136 			    Iflag ? NI_NUMERICHOST: NI_NAMEREQD);
    137 			if (i) {
    138 				if (Iflag && i != EAI_NONAME)
    139 					errx(1, "getnameinfo: %s",
    140 					    gai_strerror(i));
    141 			} else
    142 				printf("%s\n", buf);
    143 		}
    144 		freeifaddrs(ifa);
    145 	} else {
    146 		if (gethostname(hostname, sizeof(hostname)))
    147 			err(1, "gethostname");
    148 		hostname[sizeof(hostname) - 1] = '\0';
    149 		if (aflag) {
    150 			if ((hent = gethostbyname(hostname)) == NULL)
    151 				errx(1, "gethostbyname: %s",
    152 				    hstrerror(h_errno));
    153 			for (i = 0; hent->h_aliases[i]; i++)
    154 				printf("%s\n", hent->h_aliases[i]);
    155 		} else if (dflag || iflag || fflag) {
    156 			memset(&hints, 0, sizeof(hints));
    157 			hints.ai_family = AF_UNSPEC;
    158 			hints.ai_socktype = SOCK_DGRAM;
    159 			hints.ai_flags = AI_CANONNAME;
    160 			i = getaddrinfo(hostname, NULL, &hints, &ainfos);
    161 			if (i)
    162 				errx(1, "getaddrinfo: %s", gai_strerror(i));
    163 			if (ainfos) {
    164 				if (dflag) {
    165 					if ((p = strchr(ainfos->ai_canonname,
    166 					    '.')))
    167 						printf("%s\n", p + 1);
    168 				} else if (iflag) {
    169 					for (ai = ainfos; ai; ai = ai->ai_next)
    170 					{
    171 						i = getnameinfo(ai->ai_addr,
    172 						    ai->ai_addrlen,
    173 						    buf, sizeof(buf), NULL, 0,
    174 						    NI_NUMERICHOST);
    175 						if (i)
    176 							errx(1,
    177 							    "getnameinfo: %s",
    178 							    gai_strerror(i));
    179 						printf("%s\n", buf);
    180 					}
    181 				} else {
    182 					if (sflag &&
    183 					    (p = strchr(ainfos->ai_canonname,
    184 					    '.')))
    185 						*p = '\0';
    186 					printf("%s\n", ainfos->ai_canonname);
    187 				}
    188 				freeaddrinfo(ainfos);
    189 			}
    190 		} else {
    191 			if (sflag && (p = strchr(hostname, '.')))
    192 				*p = '\0';
    193 			printf("%s\n", hostname);
    194 		}
    195 	}
    196 	exit(0);
    197 	/* NOTREACHED */
    198 }
    199 
    200 static void
    201 usage(void)
    202 {
    203 	(void)fprintf(stderr, "usage: %s [-AadfIis] [name-of-host]\n",
    204 	    getprogname());
    205 	exit(1);
    206 	/* NOTREACHED */
    207 }
    208