xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/selfcheck.c (revision 03100a6332bd4edc7a53091fcf7c9a7131bcdaa7)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <errno.h>
31 #include <syslog.h>
32 
33 #include <strings.h>
34 #include <malloc.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <sys/sockio.h>
38 #include <netinet/in.h>
39 #include <sys/socket.h>
40 #include <netdb.h>
41 #include <net/if.h>
42 
43 int
44 self_check(hostname)
45 	char *hostname;
46 {
47 	int s, res = 0;
48 	struct sioc_addrreq areq;
49 
50 	struct hostent *hostinfo;
51 	int family;
52 	int flags;
53 	int error_num;
54 	char **hostptr;
55 
56 	struct sockaddr_in6 ipv6addr;
57 
58 	family = AF_INET6;
59 	flags = AI_DEFAULT;
60 
61 	if ((s = socket(family, SOCK_DGRAM, 0)) < 0) {
62 		syslog(LOG_ERR, "self_check: socket: %m");
63 		return (0);
64 	}
65 
66 	if ((hostinfo = getipnodebyname(hostname, family, flags,
67 	    &error_num)) == NULL) {
68 
69 		if (error_num == TRY_AGAIN)
70 			syslog(LOG_DEBUG,
71 			    "self_check: unknown host: %s (try again later)\n",
72 			    hostname);
73 		else
74 			syslog(LOG_DEBUG,
75 			    "self_check: unknown host: %s\n", hostname);
76 
77 		(void) close(s);
78 		return (0);
79 	}
80 
81 	for (hostptr = hostinfo->h_addr_list; *hostptr; hostptr++) {
82 		bzero(&ipv6addr, sizeof (ipv6addr));
83 		ipv6addr.sin6_family = AF_INET6;
84 		ipv6addr.sin6_addr = *((struct in6_addr *)(*hostptr));
85 		memcpy(&areq.sa_addr, (void *)&ipv6addr, sizeof (ipv6addr));
86 		areq.sa_res = -1;
87 		(void) ioctl(s, SIOCTMYADDR, (caddr_t)&areq);
88 		if (areq.sa_res == 1) {
89 			res = 1;
90 			break;
91 		}
92 	}
93 
94 	freehostent(hostinfo);
95 
96 	(void) close(s);
97 	return (res);
98 }
99 
100 #define	MAXIFS	32
101 
102 /*
103  * create an ifconf structure that represents all the interfaces
104  * configured for this host.  Two buffers are allcated here:
105  *	lifc - the ifconf structure returned
106  *	lifc->lifc_buf - the list of ifreq structures
107  * Both of the buffers must be freed by the calling routine.
108  * A NULL pointer is returned upon failure.  In this case any
109  * data that was allocated before the failure has already been
110  * freed.
111  */
112 struct lifconf *
113 getmyaddrs()
114 {
115 	int sock;
116 	struct lifnum lifn;
117 	int numifs;
118 	char *buf;
119 	struct lifconf *lifc;
120 
121 	if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
122 		syslog(LOG_ERR, "statd:getmyaddrs socket: %m");
123 		return ((struct lifconf *)NULL);
124 	}
125 
126 	lifn.lifn_family = AF_UNSPEC;
127 	lifn.lifn_flags = 0;
128 
129 	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
130 		syslog(LOG_ERR,
131 		"statd:getmyaddrs, get number of interfaces, error: %m");
132 		numifs = MAXIFS;
133 	}
134 
135 	numifs = lifn.lifn_count;
136 
137 	lifc = (struct lifconf *)malloc(sizeof (struct lifconf));
138 	lifc = malloc(sizeof (struct lifconf));
139 	if (lifc == NULL) {
140 		syslog(LOG_ERR,
141 			"statd:getmyaddrs, malloc for lifconf failed: %m");
142 		(void) close(sock);
143 		return ((struct lifconf *)NULL);
144 	}
145 	buf = (char *)malloc(numifs * sizeof (struct lifreq));
146 	if (buf == NULL) {
147 		syslog(LOG_ERR,
148 			"statd:getmyaddrs, malloc for lifreq failed: %m");
149 		(void) close(sock);
150 		free(lifc);
151 		return ((struct lifconf *)NULL);
152 	}
153 
154 	lifc->lifc_family = AF_UNSPEC;
155 	lifc->lifc_flags = 0;
156 	lifc->lifc_buf = buf;
157 	lifc->lifc_len = numifs * sizeof (struct lifreq);
158 
159 	if (ioctl(sock, SIOCGLIFCONF, (char *)lifc) < 0) {
160 		syslog(LOG_ERR, "statd:getmyaddrs, SIOCGLIFCONF, error: %m");
161 		(void) close(sock);
162 		free(buf);
163 		free(lifc);
164 		return ((struct lifconf *)NULL);
165 	}
166 
167 	(void) close(sock);
168 
169 	return (lifc);
170 }
171 
172 int
173 Is_ipv6present(void)
174 {
175 	int sock;
176 	struct lifnum lifn;
177 
178 	sock = socket(AF_INET6, SOCK_DGRAM, 0);
179 	if (sock < 0)
180 		return (0);
181 
182 	lifn.lifn_family = AF_INET6;
183 	lifn.lifn_flags = 0;
184 	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
185 		close(sock);
186 		return (0);
187 	}
188 	close(sock);
189 	if (lifn.lifn_count == 0)
190 		return (0);
191 	return (1);
192 }
193