diff options
Diffstat (limited to 'usr/src/lib/print/libpapi-common/common/misc.c')
-rw-r--r-- | usr/src/lib/print/libpapi-common/common/misc.c | 141 |
1 files changed, 139 insertions, 2 deletions
diff --git a/usr/src/lib/print/libpapi-common/common/misc.c b/usr/src/lib/print/libpapi-common/common/misc.c index 646a26e18a..2688fd0ec0 100644 --- a/usr/src/lib/print/libpapi-common/common/misc.c +++ b/usr/src/lib/print/libpapi-common/common/misc.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ @@ -31,9 +31,14 @@ /*LINTLIBRARY*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> #include <string.h> +#include <ctype.h> +#include <sys/types.h> #include <papi.h> - +#include <uri.h> #include <config-site.h> /* @@ -85,3 +90,135 @@ strlcat(char *dst, const char *src, size_t dstsize) return (l1 + l2); } #endif + +#if defined(__sun) && defined(__SVR4) +#include <sys/systeminfo.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/sockio.h> +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +static struct in6_addr ** +local_interfaces() +{ + struct in6_addr **result = NULL; + int s; + struct lifnum n; + struct lifconf c; + struct lifreq *r; + int count; + + /* we need a socket to get the interfaces */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return (0); + + /* get the number of interfaces */ + memset(&n, 0, sizeof (n)); + n.lifn_family = AF_UNSPEC; + if (ioctl(s, SIOCGLIFNUM, (char *)&n) < 0) { + close(s); + return (0); /* no interfaces */ + } + + /* get the interface(s) configuration */ + memset(&c, 0, sizeof (c)); + c.lifc_family = AF_UNSPEC; + c.lifc_buf = calloc(n.lifn_count, sizeof (struct lifreq)); + c.lifc_len = (n.lifn_count * sizeof (struct lifreq)); + if (ioctl(s, SIOCGLIFCONF, (char *)&c) < 0) { + free(c.lifc_buf); + close(s); + return (0); /* can't get interface(s) configuration */ + } + close(s); + + r = c.lifc_req; + for (count = c.lifc_len / sizeof (struct lifreq); + count > 0; count--, r++) { + struct in6_addr v6[1], *addr = NULL; + + switch (r->lifr_addr.ss_family) { + case AF_INET: { + struct sockaddr_in *s = + (struct sockaddr_in *)&r->lifr_addr; + IN6_INADDR_TO_V4MAPPED(&s->sin_addr, v6); + addr = v6; + } + break; + case AF_INET6: { + struct sockaddr_in6 *s = + (struct sockaddr_in6 *)&r->lifr_addr; + addr = &s->sin6_addr; + } + break; + } + + if (addr != NULL) { + struct in6_addr *a = malloc(sizeof (*a)); + + memcpy(a, addr, sizeof (*a)); + list_append(&result, a); + } + } + free(c.lifc_buf); + + return (result); +} + +static int +match_interfaces(char *host) +{ + struct in6_addr **lif = local_interfaces(); + struct hostent *hp; + int rc = 0; + int errnum; + + /* are there any local interfaces */ + if (lif == NULL) + return (0); + + /* cycle through the host db addresses */ + hp = getipnodebyname(host, AF_INET6, AI_ALL|AI_V4MAPPED, &errnum); + if (hp != NULL) { + struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list; + int i; + + for (i = 0; ((rc == 0) && (tmp[i] != NULL)); i++) { + int j; + + for (j = 0; ((rc == 0) && (lif[j] != NULL)); j++) + if (memcmp(tmp[i], lif[j], + sizeof (struct in6_addr)) == 0) + rc = 1; + } + } + free(lif); + + return (rc); +} +#endif + +int +is_localhost(char *host) +{ + char hostname[BUFSIZ]; + + /* is it "localhost" */ + if (strncasecmp(host, "localhost", 10) == 0) + return (1); + + /* is it the {nodename} */ + sysinfo(SI_HOSTNAME, hostname, sizeof (hostname)); + if (strncasecmp(host, hostname, strlen(hostname)) == 0) + return (1); + +#if defined(__sun) && defined(__SVR4) + /* does it match one of the host's configured interfaces */ + if (match_interfaces(host) != 0) + return (1); +#endif + return (0); +} |