xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/selfcheck.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * selfcheck.c
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <errno.h>
28 #include <syslog.h>
29 
30 #include <strings.h>
31 #include <malloc.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <sys/sockio.h>
35 #include <netinet/in.h>
36 #include <sys/socket.h>
37 #include <netdb.h>
38 #include <net/if.h>
39 
40 int
41 self_check(char *hostname)
42 {
43 	int s, res = 0;
44 	struct sioc_addrreq areq;
45 
46 	struct hostent *hostinfo;
47 	int family;
48 	int flags;
49 	int error_num;
50 	char **hostptr;
51 
52 	struct sockaddr_in6 ipv6addr;
53 
54 	family = AF_INET6;
55 	flags = AI_DEFAULT;
56 
57 	if ((s = socket(family, SOCK_DGRAM, 0)) < 0) {
58 		syslog(LOG_ERR, "self_check: socket: %m");
59 		return (0);
60 	}
61 
62 	if ((hostinfo = getipnodebyname(hostname, family, flags,
63 	    &error_num)) == NULL) {
64 
65 		if (error_num == TRY_AGAIN)
66 			syslog(LOG_DEBUG,
67 			    "self_check: unknown host: %s (try again later)\n",
68 			    hostname);
69 		else
70 			syslog(LOG_DEBUG,
71 			    "self_check: unknown host: %s\n", hostname);
72 
73 		(void) close(s);
74 		return (0);
75 	}
76 
77 	for (hostptr = hostinfo->h_addr_list; *hostptr; hostptr++) {
78 		bzero(&ipv6addr, sizeof (ipv6addr));
79 		ipv6addr.sin6_family = AF_INET6;
80 		ipv6addr.sin6_addr = *((struct in6_addr *)(*hostptr));
81 		memcpy(&areq.sa_addr, (void *)&ipv6addr, sizeof (ipv6addr));
82 		areq.sa_res = -1;
83 		(void) ioctl(s, SIOCTMYADDR, (caddr_t)&areq);
84 		if (areq.sa_res == 1) {
85 			res = 1;
86 			break;
87 		}
88 	}
89 
90 	freehostent(hostinfo);
91 
92 	(void) close(s);
93 	return (res);
94 }
95 
96 #define	MAXIFS	32
97 
98 /*
99  * create an ifconf structure that represents all the interfaces
100  * configured for this host.  Two buffers are allcated here:
101  *	lifc - the ifconf structure returned
102  *	lifc->lifc_buf - the list of ifreq structures
103  * Both of the buffers must be freed by the calling routine.
104  * A NULL pointer is returned upon failure.  In this case any
105  * data that was allocated before the failure has already been
106  * freed.
107  */
108 struct lifconf *
109 getmyaddrs(void)
110 {
111 	int sock;
112 	struct lifnum lifn;
113 	int numifs;
114 	char *buf;
115 	struct lifconf *lifc;
116 
117 	if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
118 		syslog(LOG_ERR, "statd:getmyaddrs socket: %m");
119 		return ((struct lifconf *)NULL);
120 	}
121 
122 	lifn.lifn_family = AF_UNSPEC;
123 	lifn.lifn_flags = 0;
124 
125 	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
126 		syslog(LOG_ERR,
127 		"statd:getmyaddrs, get number of interfaces, error: %m");
128 		numifs = MAXIFS;
129 	}
130 
131 	numifs = lifn.lifn_count;
132 
133 	lifc = (struct lifconf *)malloc(sizeof (struct lifconf));
134 	if (lifc == NULL) {
135 		syslog(LOG_ERR,
136 		    "statd:getmyaddrs, malloc for lifconf failed: %m");
137 		(void) close(sock);
138 		return ((struct lifconf *)NULL);
139 	}
140 	buf = (char *)malloc(numifs * sizeof (struct lifreq));
141 	if (buf == NULL) {
142 		syslog(LOG_ERR,
143 		    "statd:getmyaddrs, malloc for lifreq failed: %m");
144 		(void) close(sock);
145 		free(lifc);
146 		return ((struct lifconf *)NULL);
147 	}
148 
149 	lifc->lifc_family = AF_UNSPEC;
150 	lifc->lifc_flags = 0;
151 	lifc->lifc_buf = buf;
152 	lifc->lifc_len = numifs * sizeof (struct lifreq);
153 
154 	if (ioctl(sock, SIOCGLIFCONF, (char *)lifc) < 0) {
155 		syslog(LOG_ERR, "statd:getmyaddrs, SIOCGLIFCONF, error: %m");
156 		(void) close(sock);
157 		free(buf);
158 		free(lifc);
159 		return ((struct lifconf *)NULL);
160 	}
161 
162 	(void) close(sock);
163 
164 	return (lifc);
165 }
166 
167 int
168 Is_ipv6present(void)
169 {
170 	int sock;
171 	struct lifnum lifn;
172 
173 	sock = socket(AF_INET6, SOCK_DGRAM, 0);
174 	if (sock < 0)
175 		return (0);
176 
177 	lifn.lifn_family = AF_INET6;
178 	lifn.lifn_flags = 0;
179 	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
180 		close(sock);
181 		return (0);
182 	}
183 	close(sock);
184 	if (lifn.lifn_count == 0)
185 		return (0);
186 	return (1);
187 }
188