/* IP Address Of * Copyright 2019 Tj * Licensed on the terms of the GNU General Public Licence version 3. * * Build using: gcc -o ipaddrof ipaddrof.c * * Call with name to be resolved. This is a multicall binary; it will change its * behaviour based on the name it is called with. * * Create symlinks to the binary: * ln -s ipaddrof ipaddrof4 * ln -s ipaddrof ipaddrof6 * * ./ipaddrof mail.google.com # returns first IPv4 or IPv6 address found * ./ipaddrof4 mail.google.com # returns first IPv4 address found * ./ipaddrof6 mail.google.com # returns first IPv6 address found * */ #include #include #include #include #include #include #include #include #include #include static const char const *ipv6 = "ipaddrof6"; static const char const *ipv4 = "ipaddrof4"; int main(int argc, char **argv, char **env) { struct addrinfo hints; struct addrinfo *results, *rp; int family = AF_UNSPEC; // any char *multicall = basename(argv[0]); if ( strncmp(multicall, ipv4, strlen(ipv4)) == 0) { family = AF_INET; }else if ( strncmp(multicall, ipv6, strlen(ipv6)) == 0 ) { family = AF_INET6; } memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = family; hints.ai_protocol = 0; if (argc > 1) { if (getaddrinfo(argv[1], NULL, &hints, &results) == 0) { char answer[INET6_ADDRSTRLEN]; void *addr; for (rp = results; rp != NULL; rp = rp->ai_next) { if (rp->ai_family == family || family == AF_UNSPEC) { if (rp->ai_family == AF_INET) { struct sockaddr_in *ipv4 = (struct sockaddr_in *)rp->ai_addr; addr = &(ipv4->sin_addr); } else { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)rp->ai_addr; addr = &(ipv6->sin6_addr); } inet_ntop(rp->ai_family, addr, answer, sizeof(answer)); printf("%s\n", answer); break; } } freeaddrinfo(results); } } return 0; }