1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. 34 * @(#)hostname.c 8.1 (Berkeley) 5/31/93 35 * $FreeBSD: src/bin/hostname/hostname.c,v 1.10.2.1 2001/08/01 02:40:23 obrien Exp $ 36 * $DragonFly: src/bin/hostname/hostname.c,v 1.7 2004/03/19 17:17:46 cpressey Exp $ 37 */ 38 39 #include <sys/param.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/sysctl.h> 43 #include <sys/time.h> 44 #include <sys/module.h> 45 #include <sys/linker.h> 46 47 48 #include <net/ethernet.h> 49 #include <net/if.h> 50 #include <net/if_var.h> 51 #include <net/if_dl.h> 52 #include <net/if_types.h> 53 #include <net/route.h> 54 #include <netinet/in.h> 55 56 57 #include <err.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include <unistd.h> 62 63 #include <netdb.h> 64 #include <sys/types.h> 65 #include <netinet/in.h> 66 #include <arpa/inet.h> 67 68 #include <errno.h> 69 70 #define HST_IF (1 << 0) 71 #define HST_IF_V6 (1 << 1) 72 #define HST_IF_V4 (1 << 2) 73 74 75 76 /* 77 * Expand the compacted form of addresses as returned via the 78 * configuration read via sysctl(). 79 * Lifted from getifaddrs(3) 80 */ 81 82 static void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 83 static void usage (void); 84 85 #define ROUNDUP(a) \ 86 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 87 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 88 89 static 90 void 91 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 92 { 93 struct sockaddr *sa; 94 int i; 95 96 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 97 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 98 if ((rtinfo->rti_addrs & (1 << i)) == 0) 99 continue; 100 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 101 ADVANCE(cp, sa); 102 } 103 } 104 105 int 106 main(int argc, char **argv) 107 { 108 int ch,sflag,rflag,ret,flag6,iflag; 109 char hostname[MAXHOSTNAMELEN]; 110 char *srflag, *siflag = NULL; 111 struct hostent *hst; 112 struct in_addr ia; 113 struct in6_addr ia6; 114 115 int mib[6]; 116 size_t needed; 117 char *buf,*lim,*next,*p; 118 int idx; 119 struct sockaddr_dl *sdl; 120 struct rt_msghdr *rtm; 121 struct if_msghdr *ifm; 122 struct ifa_msghdr *ifam; 123 struct rt_addrinfo info; 124 struct sockaddr_in *sai; 125 struct sockaddr_in6 *sai6; 126 127 srflag = NULL; 128 iflag = sflag = rflag = 0; 129 flag6 = 0; 130 hst = NULL; 131 132 while ((ch = getopt(argc, argv, "46i:r:s")) != -1) { 133 switch (ch) { 134 case '4': 135 iflag |= HST_IF_V4; 136 break; 137 case '6': 138 iflag |= HST_IF_V6; 139 break; 140 case 'i': 141 siflag = (char*)calloc(1,sizeof(char) * (strlen((char*)optarg)+1)); 142 if (siflag) { 143 iflag |= HST_IF; 144 strlcpy(siflag, (char*)optarg, strlen((char*)optarg)+1); 145 } else { 146 errx(1, "malloc"); 147 } 148 break; 149 case 'r': 150 srflag = (char*)calloc(1,sizeof(char) * (strlen((char*)optarg)+1)); 151 if (srflag) { 152 rflag = 1; 153 strlcpy(srflag, (char*)optarg, strlen((char*)optarg)+1); 154 } else { 155 errx(1, "malloc"); 156 } 157 break; 158 case 's': 159 sflag = 1; 160 break; 161 case '?': 162 default: 163 usage(); 164 } 165 } 166 argc -= optind; 167 argv += optind; 168 169 if (argc > 1) 170 usage(); 171 172 if (iflag && *argv) { 173 free(siflag); 174 usage(); 175 } 176 177 if (rflag && *argv) { 178 free(srflag); 179 usage(); 180 } 181 182 if (rflag && (iflag & HST_IF)) { 183 usage(); 184 free(srflag); 185 free(siflag); 186 } 187 188 if ((iflag & HST_IF_V6) && (iflag & HST_IF_V4)) { 189 free(siflag); 190 usage(); 191 } 192 193 if (!(iflag & HST_IF) && ((iflag & HST_IF_V6)||iflag & HST_IF_V4)) { 194 free(siflag); 195 usage(); 196 } 197 198 if (iflag & HST_IF) { 199 mib[0] = CTL_NET; 200 mib[1] = PF_ROUTE; 201 mib[2] = 0; 202 mib[3] = 0; 203 mib[4] = NET_RT_IFLIST; 204 mib[5] = 0; 205 206 idx = 0; 207 needed = 1; 208 209 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 210 free(siflag); 211 errx(1, "iflist-sysctl-estimate:%i",errno); 212 } 213 if ((buf = malloc(needed)) == NULL) { 214 free(siflag); 215 errx(1, "malloc"); 216 } 217 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 218 free(siflag); 219 errx(1, "actual retrieval of interface table"); 220 } 221 222 lim = buf + needed; 223 224 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 225 rtm = (struct rt_msghdr *)(void *)next; 226 if (rtm->rtm_version != RTM_VERSION) 227 continue; 228 switch (rtm->rtm_type) { 229 case RTM_IFINFO: 230 ifm = (struct if_msghdr *)(void *)rtm; 231 232 if (ifm->ifm_addrs & RTA_IFP) { 233 sdl = (struct sockaddr_dl *)(ifm+1); 234 if (strcmp(siflag,sdl->sdl_data) == 0) { 235 idx = ifm->ifm_index; 236 } 237 } 238 break; 239 case RTM_NEWADDR: 240 ifam = (struct ifa_msghdr *)(void *)rtm; 241 242 if (ifam->ifam_index == idx) { 243 info.rti_addrs = ifam->ifam_addrs; 244 rt_xaddrs((char *)(ifam + 1), 245 ifam->ifam_msglen + (char *)ifam, &info); 246 sai = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; 247 248 if (iflag & HST_IF_V6) { 249 if (sai->sin_family == AF_INET6) { 250 sai6 = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA]; 251 hst = gethostbyaddr((const char*)&sai6->sin6_addr, 252 sizeof(sai6->sin6_addr),AF_INET6); 253 254 if (h_errno == NETDB_SUCCESS) { 255 next = buf + needed; 256 continue; 257 } 258 } 259 } else { 260 if ((sai->sin_family == AF_INET)) { 261 262 hst = gethostbyaddr((const char*)&sai->sin_addr, 263 sizeof(sai->sin_addr),AF_INET); 264 265 if (h_errno == NETDB_SUCCESS) { 266 next = buf + needed; 267 continue; 268 } 269 } 270 } 271 } 272 break; 273 } /* switch */ 274 } /* loop */ 275 276 free(buf); 277 free(siflag); 278 279 if (idx == 0) { 280 errx(1,"interface not found"); 281 } 282 if (hst == NULL) { 283 errx(1, "ip not found on interface"); 284 } 285 286 if (h_errno == NETDB_SUCCESS) { 287 if (sethostname(hst->h_name, (int)strlen(hst->h_name))) 288 errx(1, "sethostname"); 289 } else if (h_errno == HOST_NOT_FOUND) { 290 errx(1,"hostname not found"); 291 } else { 292 errx(1,"gethostbyaddr"); 293 } 294 } else if (rflag) { 295 ret = inet_pton(AF_INET, srflag, &ia); 296 if (ret != 1) { 297 /* check IPV6 */ 298 ret = inet_pton(AF_INET6, srflag, &ia6); 299 300 if (ret != 1) { 301 free(srflag); 302 errx(1, "invalid ip address"); 303 } 304 305 flag6 = 1; 306 } 307 308 if (flag6 == 1) 309 hst = gethostbyaddr((const char*)&ia6, sizeof(ia6), AF_INET6); 310 else 311 hst = gethostbyaddr((const char*)&ia, sizeof(ia), AF_INET); 312 if (!hst) { 313 free(srflag); 314 if(h_errno == HOST_NOT_FOUND) 315 errx(1,"host not found\n"); 316 } 317 318 if (sethostname(hst->h_name, (int)strlen(hst->h_name))) 319 err(1, "sethostname"); 320 } else if (*argv) { 321 if (sethostname(*argv, (int)strlen(*argv))) 322 err(1, "sethostname"); 323 } else { 324 if (gethostname(hostname, (int)sizeof(hostname))) 325 err(1, "gethostname"); 326 if (sflag && (p = strchr(hostname, '.'))) 327 *p = '\0'; 328 (void)printf("%s\n", hostname); 329 } 330 exit(0); 331 } 332 333 static void 334 usage(void) 335 { 336 fprintf(stderr, "usage: hostname [-s] [name-of-host |" 337 " -r ip-address | -i interface [-4 | -6]]\n"); 338 exit(1); 339 } 340 341