123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- /*-
- * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn.
- * Timo Teräs cleaned up the code for use in Alpine Linux with musl libc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <ctype.h>
- #include <errno.h>
- #include <limits.h>
- #include <netdb.h>
- #include <pwd.h>
- #include <grp.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <paths.h>
- #include <err.h>
- #include <arpa/inet.h>
- #include <arpa/nameser.h>
- #include <net/if.h>
- #include <net/ethernet.h>
- #include <netinet/ether.h>
- #include <netinet/in.h>
- enum {
- RV_OK = 0,
- RV_USAGE = 1,
- RV_NOTFOUND = 2,
- RV_NOENUM = 3
- };
- static int usage(const char *);
- static int parsenum(const char *word, unsigned long *result)
- {
- unsigned long num;
- char *ep;
- if (!isdigit((unsigned char)word[0]))
- return 0;
- errno = 0;
- num = strtoul(word, &ep, 10);
- if (num == ULONG_MAX && errno == ERANGE)
- return 0;
- if (*ep != '\0')
- return 0;
- *result = num;
- return 1;
- }
- /*
- * printfmtstrings --
- * vprintf(format, ...),
- * then the aliases (beginning with prefix, separated by sep),
- * then a newline
- */
- __attribute__ ((format (printf, 4, 5)))
- static void printfmtstrings(char *strings[], const char *prefix, const char *sep,
- const char *fmt, ...)
- {
- va_list ap;
- const char *curpref;
- size_t i;
- va_start(ap, fmt);
- (void)vprintf(fmt, ap);
- va_end(ap);
- curpref = prefix;
- for (i = 0; strings[i] != NULL; i++) {
- (void)printf("%s%s", curpref, strings[i]);
- curpref = sep;
- }
- (void)printf("\n");
- }
- static int ethers(int argc, char *argv[])
- {
- char hostname[MAXHOSTNAMELEN + 1], *hp;
- struct ether_addr ea, *eap;
- int i, rv;
- if (argc == 2) {
- warnx("Enumeration not supported on ethers");
- return RV_NOENUM;
- }
- rv = RV_OK;
- for (i = 2; i < argc; i++) {
- if ((eap = ether_aton(argv[i])) == NULL) {
- eap = &ea;
- hp = argv[i];
- if (ether_hostton(hp, eap) != 0) {
- rv = RV_NOTFOUND;
- break;
- }
- } else {
- hp = hostname;
- if (ether_ntohost(hp, eap) != 0) {
- rv = RV_NOTFOUND;
- break;
- }
- }
- (void)printf("%-17s %s\n", ether_ntoa(eap), hp);
- }
- return rv;
- }
- static void groupprint(const struct group *gr)
- {
- printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u",
- gr->gr_name, gr->gr_passwd, gr->gr_gid);
- }
- static int group(int argc, char *argv[])
- {
- struct group *gr;
- unsigned long id;
- int i, rv;
- rv = RV_OK;
- if (argc == 2) {
- while ((gr = getgrent()) != NULL)
- groupprint(gr);
- } else {
- for (i = 2; i < argc; i++) {
- if (parsenum(argv[i], &id))
- gr = getgrgid((gid_t)id);
- else
- gr = getgrnam(argv[i]);
- if (gr == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- groupprint(gr);
- }
- }
- endgrent();
- return rv;
- }
- static void hostsprint(const struct hostent *he)
- {
- char buf[INET6_ADDRSTRLEN];
- if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
- (void)strlcpy(buf, "# unknown", sizeof(buf));
- printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
- }
- static int hosts(int argc, char *argv[])
- {
- struct hostent *he;
- char addr[IN6ADDRSZ];
- int i, rv;
- sethostent(1);
- rv = RV_OK;
- if (argc == 2) {
- while ((he = gethostent()) != NULL)
- hostsprint(he);
- } else {
- for (i = 2; i < argc; i++) {
- if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
- he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
- else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
- he = gethostbyaddr(addr, INADDRSZ, AF_INET);
- else if ((he = gethostbyname2(argv[i], AF_INET6)) == NULL)
- he = gethostbyname2(argv[i], AF_INET);
- if (he == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- hostsprint(he);
- }
- }
- endhostent();
- return rv;
- }
- static int ahosts_ex(int family, int flags, int argc, char *argv[])
- {
- static const char *socktypes[] = {
- [SOCK_STREAM] = "STREAM",
- [SOCK_DGRAM] = "DGRAM",
- [SOCK_RAW] = "RAW",
- [SOCK_RDM] = "RDM",
- [SOCK_SEQPACKET] = "SEQPACKET",
- [SOCK_DCCP] = "DCCP",
- [SOCK_PACKET] = "PACKET",
- };
- const char *sockstr;
- char sockbuf[16], buf[INET6_ADDRSTRLEN];
- struct addrinfo *res, *r, hint;
- void *addr;
- int i;
- if (argc == 2)
- return hosts(argc, argv);
- hint = (struct addrinfo) {
- .ai_family = family,
- .ai_flags = AI_ADDRCONFIG | AI_CANONNAME | flags,
- };
- for (i = 2; i < argc; i++) {
- if (getaddrinfo(argv[i], 0, &hint, &res) != 0)
- return RV_NOTFOUND;
- for (r = res; r; r = r->ai_next) {
- sockstr = NULL;
- if (r->ai_socktype >= 0 && r->ai_socktype < sizeof(socktypes)/sizeof(socktypes[0]))
- sockstr = socktypes[r->ai_socktype];
- if (!sockstr) {
- sprintf(buf, "%d", r->ai_socktype);
- sockstr = sockbuf;
- }
- switch (r->ai_family) {
- case AF_INET:
- addr = &((struct sockaddr_in*) r->ai_addr)->sin_addr;
- break;
- case AF_INET6:
- addr = &((struct sockaddr_in6*) r->ai_addr)->sin6_addr;
- break;
- default:
- continue;
- }
- if (inet_ntop(r->ai_family, addr, buf, sizeof(buf)) == NULL)
- (void)strlcpy(buf, "# unknown", sizeof(buf));
- printf("%-15s %-6s %s\n", buf, sockstr, r->ai_canonname ?: "");
- }
- }
- return RV_OK;
- }
- static int ahosts(int argc, char *argv[])
- {
- return ahosts_ex(AF_UNSPEC, 0, argc, argv);
- }
- static int ahostsv4(int argc, char *argv[])
- {
- return ahosts_ex(AF_INET, 0, argc, argv);
- }
- static int ahostsv6(int argc, char *argv[])
- {
- return ahosts_ex(AF_INET6, AI_V4MAPPED, argc, argv);
- }
- static void networksprint(const struct netent *ne)
- {
- char buf[INET6_ADDRSTRLEN];
- struct in_addr ianet;
- ianet = inet_makeaddr(ne->n_net, 0);
- if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
- (void)strlcpy(buf, "# unknown", sizeof(buf));
- printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
- }
- static int networks(int argc, char *argv[])
- {
- struct netent *ne;
- in_addr_t net;
- int i, rv;
- setnetent(1);
- rv = RV_OK;
- if (argc == 2) {
- while ((ne = getnetent()) != NULL)
- networksprint(ne);
- } else {
- for (i = 2; i < argc; i++) {
- net = inet_network(argv[i]);
- if (net != INADDR_NONE)
- ne = getnetbyaddr(net, AF_INET);
- else
- ne = getnetbyname(argv[i]);
- if (ne != NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- networksprint(ne);
- }
- }
- endnetent();
- return rv;
- }
- static void passwdprint(struct passwd *pw)
- {
- (void)printf("%s:%s:%u:%u:%s:%s:%s\n",
- pw->pw_name, pw->pw_passwd, pw->pw_uid,
- pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell);
- }
- static int passwd(int argc, char *argv[])
- {
- struct passwd *pw;
- unsigned long id;
- int i, rv;
- rv = RV_OK;
- if (argc == 2) {
- while ((pw = getpwent()) != NULL)
- passwdprint(pw);
- } else {
- for (i = 2; i < argc; i++) {
- if (parsenum(argv[i], &id))
- pw = getpwuid((uid_t)id);
- else
- pw = getpwnam(argv[i]);
- if (pw == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- passwdprint(pw);
- }
- }
- endpwent();
- return rv;
- }
- static void protocolsprint(struct protoent *pe)
- {
- printfmtstrings(pe->p_aliases, " ", " ",
- "%-16s %5d", pe->p_name, pe->p_proto);
- }
- static int protocols(int argc, char *argv[])
- {
- struct protoent *pe;
- unsigned long id;
- int i, rv;
- setprotoent(1);
- rv = RV_OK;
- if (argc == 2) {
- while ((pe = getprotoent()) != NULL)
- protocolsprint(pe);
- } else {
- for (i = 2; i < argc; i++) {
- if (parsenum(argv[i], &id))
- pe = getprotobynumber((int)id);
- else
- pe = getprotobyname(argv[i]);
- if (pe == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- protocolsprint(pe);
- }
- }
- endprotoent();
- return rv;
- }
- static void servicesprint(struct servent *se)
- {
- printfmtstrings(se->s_aliases, " ", " ",
- "%-16s %5d/%s",
- se->s_name, ntohs(se->s_port), se->s_proto);
- }
- static int services(int argc, char *argv[])
- {
- struct servent *se;
- unsigned long id;
- char *proto;
- int i, rv;
- setservent(1);
- rv = RV_OK;
- if (argc == 2) {
- while ((se = getservent()) != NULL)
- servicesprint(se);
- } else {
- for (i = 2; i < argc; i++) {
- proto = strchr(argv[i], '/');
- if (proto != NULL)
- *proto++ = '\0';
- if (parsenum(argv[i], &id))
- se = getservbyport(htons(id), proto);
- else
- se = getservbyname(argv[i], proto);
- if (se == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- servicesprint(se);
- }
- }
- endservent();
- return rv;
- }
- static int shells(int argc, char *argv[])
- {
- const char *sh;
- int i, rv;
- setusershell();
- rv = RV_OK;
- if (argc == 2) {
- while ((sh = getusershell()) != NULL)
- (void)printf("%s\n", sh);
- } else {
- for (i = 2; i < argc; i++) {
- setusershell();
- while ((sh = getusershell()) != NULL) {
- if (strcmp(sh, argv[i]) == 0) {
- (void)printf("%s\n", sh);
- break;
- }
- }
- if (sh == NULL) {
- rv = RV_NOTFOUND;
- break;
- }
- }
- }
- endusershell();
- return rv;
- }
- static struct getentdb {
- const char *name;
- int (*callback)(int, char *[]);
- } databases[] = {
- { "ethers", ethers, },
- { "group", group, },
- { "hosts", hosts, },
- { "ahosts", ahosts, },
- { "ahostsv4", ahostsv4, },
- { "ahostsv6", ahostsv6, },
- { "networks", networks, },
- { "passwd", passwd, },
- { "protocols", protocols, },
- { "services", services, },
- { "shells", shells, },
- { NULL, NULL, },
- };
- static int usage(const char *arg0)
- {
- struct getentdb *curdb;
- size_t i;
- (void)fprintf(stderr, "Usage: %s database [key ...]\n", arg0);
- (void)fprintf(stderr, "\tdatabase may be one of:");
- for (i = 0, curdb = databases; curdb->name != NULL; curdb++, i++) {
- if (i % 7 == 0)
- (void)fputs("\n\t\t", stderr);
- (void)fprintf(stderr, "%s%s", i % 7 == 0 ? "" : " ",
- curdb->name);
- }
- (void)fprintf(stderr, "\n");
- exit(RV_USAGE);
- /* NOTREACHED */
- }
- int
- main(int argc, char *argv[])
- {
- struct getentdb *curdb;
- if (argc < 2)
- usage(argv[0]);
- for (curdb = databases; curdb->name != NULL; curdb++)
- if (strcmp(curdb->name, argv[1]) == 0)
- return (*curdb->callback)(argc, argv);
- warn("Unknown database `%s'", argv[1]);
- usage(argv[0]);
- /* NOTREACHED */
- }
|