| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
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. | |
| 1de703da MD |
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 $ | |
| 27feb923 | 36 | * $DragonFly: src/bin/hostname/hostname.c,v 1.14 2008/09/02 22:20:55 swildner Exp $ |
| 984263bc MD |
37 | */ |
| 38 | ||
| 984263bc | 39 | #include <sys/param.h> |
| 639b96ab MD |
40 | #include <sys/ioctl.h> |
| 41 | #include <sys/socket.h> | |
| 42 | #include <sys/sysctl.h> | |
| 639b96ab MD |
43 | #include <sys/module.h> |
| 44 | #include <sys/linker.h> | |
| 45 | ||
| 639b96ab MD |
46 | #include <net/ethernet.h> |
| 47 | #include <net/if.h> | |
| 48 | #include <net/if_var.h> | |
| 49 | #include <net/if_dl.h> | |
| 50 | #include <net/if_types.h> | |
| 51 | #include <net/route.h> | |
| 52 | #include <netinet/in.h> | |
| 53 | ||
| 984263bc MD |
54 | #include <err.h> |
| 55 | #include <stdio.h> | |
| 56 | #include <stdlib.h> | |
| 57 | #include <string.h> | |
| 58 | #include <unistd.h> | |
| 59 | ||
| 639b96ab MD |
60 | #include <netdb.h> |
| 61 | #include <sys/types.h> | |
| 62 | #include <netinet/in.h> | |
| 63 | #include <arpa/inet.h> | |
| 64 | ||
| 65 | #include <errno.h> | |
| 66 | ||
| 67 | #define HST_IF (1 << 0) | |
| 68 | #define HST_IF_V6 (1 << 1) | |
| 69 | #define HST_IF_V4 (1 << 2) | |
| 70 | ||
| 71 | ||
| 72 | ||
| 73 | /* | |
| 74 | * Expand the compacted form of addresses as returned via the | |
| 75 | * configuration read via sysctl(). | |
| 76 | * Lifted from getifaddrs(3) | |
| 77 | */ | |
| 78 | ||
| 79 | static void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); | |
| 80 | static void usage (void); | |
| 81 | ||
| 82 | #define ROUNDUP(a) \ | |
| 83 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
| 84 | #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) | |
| 85 | ||
| 86 | static | |
| 87 | void | |
| 88 | rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) | |
| 89 | { | |
| 90 | struct sockaddr *sa; | |
| 91 | int i; | |
| 92 | ||
| 93 | memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); | |
| 94 | for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { | |
| 95 | if ((rtinfo->rti_addrs & (1 << i)) == 0) | |
| 96 | continue; | |
| 97 | rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; | |
| 98 | ADVANCE(cp, sa); | |
| 99 | } | |
| 100 | } | |
| 984263bc MD |
101 | |
| 102 | int | |
| b5744197 | 103 | main(int argc, char **argv) |
| 984263bc | 104 | { |
| baa0803f | 105 | int ch, sflag, rflag, ret, flag6, iflag; |
| b4035d96 | 106 | int silen = 0; |
| 639b96ab | 107 | char hostname[MAXHOSTNAMELEN]; |
| baa0803f | 108 | char *srflag, *siflag; |
| 639b96ab MD |
109 | struct hostent *hst; |
| 110 | struct in_addr ia; | |
| 111 | struct in6_addr ia6; | |
| 112 | ||
| 113 | int mib[6]; | |
| a78cd756 | 114 | size_t needed; |
| 27feb923 | 115 | char *buf, *next, *p; |
| 639b96ab MD |
116 | int idx; |
| 117 | struct sockaddr_dl *sdl; | |
| 118 | struct rt_msghdr *rtm; | |
| 119 | struct if_msghdr *ifm; | |
| 120 | struct ifa_msghdr *ifam; | |
| 121 | struct rt_addrinfo info; | |
| 122 | struct sockaddr_in *sai; | |
| 123 | struct sockaddr_in6 *sai6; | |
| 124 | ||
| 125 | srflag = NULL; | |
| baa0803f | 126 | siflag = NULL; |
| 639b96ab MD |
127 | iflag = sflag = rflag = 0; |
| 128 | flag6 = 0; | |
| 129 | hst = NULL; | |
| 984263bc | 130 | |
| 639b96ab | 131 | while ((ch = getopt(argc, argv, "46i:r:s")) != -1) { |
| 984263bc | 132 | switch (ch) { |
| 639b96ab MD |
133 | case '4': |
| 134 | iflag |= HST_IF_V4; | |
| 135 | break; | |
| 136 | case '6': | |
| 137 | iflag |= HST_IF_V6; | |
| 138 | break; | |
| 139 | case 'i': | |
| 2c67e6a5 | 140 | siflag = optarg; |
| 2a50c533 | 141 | silen = strlen(siflag); |
| f9b04e01 | 142 | iflag |= HST_IF; |
| 639b96ab MD |
143 | break; |
| 144 | case 'r': | |
| 2c67e6a5 | 145 | srflag = optarg; |
| baa0803f | 146 | rflag = 1; |
| 639b96ab | 147 | break; |
| 984263bc MD |
148 | case 's': |
| 149 | sflag = 1; | |
| 150 | break; | |
| 984263bc MD |
151 | default: |
| 152 | usage(); | |
| 153 | } | |
| 639b96ab | 154 | } |
| 984263bc MD |
155 | argc -= optind; |
| 156 | argv += optind; | |
| 157 | ||
| 158 | if (argc > 1) | |
| 159 | usage(); | |
| 160 | ||
| f9b04e01 | 161 | if (iflag && *argv) |
| 639b96ab | 162 | usage(); |
| 639b96ab | 163 | |
| f9b04e01 | 164 | if (rflag && *argv) |
| 639b96ab | 165 | usage(); |
| 639b96ab | 166 | |
| f9b04e01 | 167 | if (rflag && (iflag & HST_IF)) |
| 639b96ab | 168 | usage(); |
| 639b96ab | 169 | |
| f9b04e01 | 170 | if ((iflag & HST_IF_V6) && (iflag & HST_IF_V4)) |
| 639b96ab | 171 | usage(); |
| 639b96ab | 172 | |
| f9b04e01 | 173 | if (!(iflag & HST_IF) && ((iflag & HST_IF_V6)||iflag & HST_IF_V4)) |
| 639b96ab | 174 | usage(); |
| 639b96ab MD |
175 | |
| 176 | if (iflag & HST_IF) { | |
| 177 | mib[0] = CTL_NET; | |
| 178 | mib[1] = PF_ROUTE; | |
| 179 | mib[2] = 0; | |
| 180 | mib[3] = 0; | |
| 181 | mib[4] = NET_RT_IFLIST; | |
| 182 | mib[5] = 0; | |
| 183 | ||
| 184 | idx = 0; | |
| 185 | needed = 1; | |
| 186 | ||
| f9b04e01 | 187 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) |
| 2c67e6a5 | 188 | err(1, "sysctl: iflist-sysctl-estimate"); |
| f9b04e01 | 189 | if ((buf = malloc(needed)) == NULL) |
| 2c67e6a5 | 190 | err(1, "malloc failed"); |
| f9b04e01 | 191 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) |
| 2c67e6a5 | 192 | err(1, "sysctl: retrieval of interface table"); |
| 639b96ab | 193 | |
| 639b96ab MD |
194 | for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { |
| 195 | rtm = (struct rt_msghdr *)(void *)next; | |
| 196 | if (rtm->rtm_version != RTM_VERSION) | |
| 197 | continue; | |
| 198 | switch (rtm->rtm_type) { | |
| 199 | case RTM_IFINFO: | |
| 200 | ifm = (struct if_msghdr *)(void *)rtm; | |
| 201 | ||
| 2a50c533 MD |
202 | if ((ifm->ifm_addrs & RTA_IFP) == 0) |
| 203 | break; | |
| 204 | sdl = (struct sockaddr_dl *)(ifm + 1); | |
| 205 | if (silen != sdl->sdl_nlen) | |
| 206 | break; | |
| 207 | if (!strncmp(siflag, sdl->sdl_data, silen)) { | |
| 208 | idx = ifm->ifm_index; | |
| 639b96ab MD |
209 | } |
| 210 | break; | |
| 211 | case RTM_NEWADDR: | |
| 212 | ifam = (struct ifa_msghdr *)(void *)rtm; | |
| 213 | ||
| 214 | if (ifam->ifam_index == idx) { | |
| 215 | info.rti_addrs = ifam->ifam_addrs; | |
| 216 | rt_xaddrs((char *)(ifam + 1), | |
| 217 | ifam->ifam_msglen + (char *)ifam, &info); | |
| 218 | sai = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; | |
| 219 | ||
| 220 | if (iflag & HST_IF_V6) { | |
| 221 | if (sai->sin_family == AF_INET6) { | |
| 222 | sai6 = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA]; | |
| 15b85273 | 223 | hst = gethostbyaddr(&sai6->sin6_addr, |
| 639b96ab MD |
224 | sizeof(sai6->sin6_addr),AF_INET6); |
| 225 | ||
| 226 | if (h_errno == NETDB_SUCCESS) { | |
| 227 | next = buf + needed; | |
| 228 | continue; | |
| 229 | } | |
| 230 | } | |
| 231 | } else { | |
| 232 | if ((sai->sin_family == AF_INET)) { | |
| 233 | ||
| 15b85273 | 234 | hst = gethostbyaddr(&sai->sin_addr, |
| 639b96ab MD |
235 | sizeof(sai->sin_addr),AF_INET); |
| 236 | ||
| 237 | if (h_errno == NETDB_SUCCESS) { | |
| 238 | next = buf + needed; | |
| 239 | continue; | |
| 240 | } | |
| 241 | } | |
| 242 | } | |
| 243 | } | |
| 244 | break; | |
| 245 | } /* switch */ | |
| 246 | } /* loop */ | |
| 247 | ||
| 248 | free(buf); | |
| 639b96ab | 249 | |
| f9b04e01 | 250 | if (idx == 0) |
| 639b96ab | 251 | errx(1,"interface not found"); |
| f9b04e01 | 252 | if (hst == NULL) |
| 5213f566 | 253 | errx(1, "ip not found on interface"); |
| 639b96ab MD |
254 | |
| 255 | if (h_errno == NETDB_SUCCESS) { | |
| 256 | if (sethostname(hst->h_name, (int)strlen(hst->h_name))) | |
| 2c67e6a5 | 257 | err(1, "sethostname"); |
| 639b96ab MD |
258 | } else if (h_errno == HOST_NOT_FOUND) { |
| 259 | errx(1,"hostname not found"); | |
| 260 | } else { | |
| 2c67e6a5 LF |
261 | herror("gethostbyaddr"); |
| 262 | exit(1); | |
| 639b96ab MD |
263 | } |
| 264 | } else if (rflag) { | |
| 265 | ret = inet_pton(AF_INET, srflag, &ia); | |
| 266 | if (ret != 1) { | |
| a78cd756 | 267 | /* check IPV6 */ |
| 639b96ab MD |
268 | ret = inet_pton(AF_INET6, srflag, &ia6); |
| 269 | ||
| 270 | if (ret != 1) { | |
| 639b96ab MD |
271 | errx(1, "invalid ip address"); |
| 272 | } | |
| 273 | ||
| 274 | flag6 = 1; | |
| 275 | } | |
| 276 | ||
| 277 | if (flag6 == 1) | |
| 15b85273 | 278 | hst = gethostbyaddr(&ia6, sizeof(ia6), AF_INET6); |
| 639b96ab | 279 | else |
| 15b85273 | 280 | hst = gethostbyaddr(&ia, sizeof(ia), AF_INET); |
| 639b96ab | 281 | if (!hst) { |
| f9b04e01 | 282 | if (h_errno == HOST_NOT_FOUND) |
| 639b96ab MD |
283 | errx(1,"host not found\n"); |
| 284 | } | |
| 285 | ||
| 286 | if (sethostname(hst->h_name, (int)strlen(hst->h_name))) | |
| 287 | err(1, "sethostname"); | |
| 288 | } else if (*argv) { | |
| 984263bc MD |
289 | if (sethostname(*argv, (int)strlen(*argv))) |
| 290 | err(1, "sethostname"); | |
| 291 | } else { | |
| 292 | if (gethostname(hostname, (int)sizeof(hostname))) | |
| 293 | err(1, "gethostname"); | |
| 294 | if (sflag && (p = strchr(hostname, '.'))) | |
| 295 | *p = '\0'; | |
| 57fed2af | 296 | printf("%s\n", hostname); |
| 984263bc MD |
297 | } |
| 298 | exit(0); | |
| 299 | } | |
| 300 | ||
| 639b96ab | 301 | static void |
| b5744197 | 302 | usage(void) |
| 984263bc | 303 | { |
| 639b96ab MD |
304 | fprintf(stderr, "usage: hostname [-s] [name-of-host |" |
| 305 | " -r ip-address | -i interface [-4 | -6]]\n"); | |
| 984263bc MD |
306 | exit(1); |
| 307 | } | |
| 639b96ab | 308 |