1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * 	selfcheck.c
24 *      Copyright (c) 1999 Sun Microsystems Inc.
25 *      All Rights Reserved.
26 */
27
28/*
29 * Portions Copyright 2007-2011 Apple Inc.
30 */
31
32#pragma ident	"@(#)selfcheck.c	1.3	05/06/08 SMI"
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <ifaddrs.h>
37
38#include <stdlib.h>
39#include <string.h>
40#include <errno.h>
41#include <syslog.h>
42
43#include <strings.h>
44#include <stdio.h>
45#include <netdb.h>
46
47#include "autofs.h"
48#include "automount.h"
49
50static int self_check_af(char *, struct ifaddrs *, int);
51
52int
53self_check(hostname)
54	char *hostname;
55{
56	int res;
57	struct ifaddrs *ifaddrs;
58
59	/*
60	 * Check whether the host has a name that begins with ".";
61	 * if so, it's not a valid host name, and we return ENOENT.
62	 * That way, we avoid doing host name lookups for various
63	 * dot-file names, e.g. ".localized" and ".DS_Store".
64	 *
65	 * We want to avoid this so that we don't pass the name on to
66	 * getipnodebyname() and thus on to mDNSResponder, which will
67	 * whine about being handed a name beginning with ".".  (This
68	 * filtering *belongs* in lower-level routines such as
69	 * getipnodebyname(), gethostbyname(), etc. or routines
70	 * they call, so that we return errors for host names beginning
71	 * with "." before sending them to anybody else, so that even
72	 * "ping .localized" won't provoke mDNSResponder to whine, but
73	 * it's not being done there, alas, so we have to do it ourselves.)
74	 */
75	if (hostname[0] == '.') {
76		/*
77		 * This cannot possibly be any host, much less us.
78		 */
79		return (0);
80	}
81
82	if (getifaddrs(&ifaddrs) == -1) {
83		syslog(LOG_ERR, "getifaddrs failed:  %s\n",
84		    strerror(errno));
85		return (0);
86	}
87	res = self_check_af(hostname, ifaddrs, AF_INET6) ||
88	    self_check_af(hostname, ifaddrs, AF_INET);
89	freeifaddrs(ifaddrs);
90	return (res);
91}
92
93static int
94self_check_af(char *hostname, struct ifaddrs *ifaddrs, int family)
95{
96	struct hostent *hostinfo;
97	int error_num;
98	char **hostptr;
99	struct ifaddrs *ifaddr;
100	struct sockaddr *addr;
101	struct sockaddr_in *addr_in;
102	struct sockaddr_in6 *addr_in6;
103
104	if ((hostinfo = getipnodebyname(hostname, family, AI_DEFAULT,
105	    &error_num)) == NULL) {
106		if (error_num == TRY_AGAIN)
107			syslog(LOG_DEBUG,
108			    "self_check: unknown host: %s (try again later)\n",
109			    hostname);
110		else
111			syslog(LOG_DEBUG,
112			    "self_check: unknown host: %s\n", hostname);
113
114		return (0);
115	}
116
117	for (hostptr = hostinfo->h_addr_list; *hostptr; hostptr++) {
118		for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
119			addr = ifaddr->ifa_addr;
120			if (addr->sa_family != hostinfo->h_addrtype)
121				continue;
122			switch (addr->sa_family) {
123
124			case AF_INET:
125				addr_in = (struct sockaddr_in *)addr;
126				if (memcmp(*hostptr, &addr_in->sin_addr,
127				    hostinfo->h_length) == 0) {
128					freehostent(hostinfo);
129					return (1);
130				}
131				break;
132
133			case AF_INET6:
134				addr_in6 = (struct sockaddr_in6 *)addr;
135				if (memcmp(*hostptr, &addr_in6->sin6_addr,
136				    hostinfo->h_length) == 0) {
137					freehostent(hostinfo);
138					return (1);
139				}
140				break;
141
142			default:
143				break;
144			}
145		}
146	}
147
148	freehostent(hostinfo);
149	return (0);
150}
151