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 2010 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
self_check(char * hostname)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 /*
56 * We cannot specify AI_DEFAULT since it includes AI_ADDRCONFIG.
57 * Localhost name resolution will fail if no IP interfaces other than
58 * loopback are plumbed and AI_ADDRCONFIG is specified, and this
59 * causes localhost mounts to fail.
60 */
61 flags = AI_V4MAPPED;
62
63 if ((s = socket(family, SOCK_DGRAM, 0)) < 0) {
64 syslog(LOG_ERR, "self_check: socket: %m");
65 return (0);
66 }
67
68 if ((hostinfo = getipnodebyname(hostname, family, flags,
69 &error_num)) == NULL) {
70
71 if (error_num == TRY_AGAIN)
72 syslog(LOG_DEBUG,
73 "self_check: unknown host: %s (try again later)\n",
74 hostname);
75 else
76 syslog(LOG_DEBUG,
77 "self_check: unknown host: %s\n", hostname);
78
79 (void) close(s);
80 return (0);
81 }
82
83 for (hostptr = hostinfo->h_addr_list; *hostptr; hostptr++) {
84 bzero(&ipv6addr, sizeof (ipv6addr));
85 ipv6addr.sin6_family = AF_INET6;
86 ipv6addr.sin6_addr = *((struct in6_addr *)(*hostptr));
87 memcpy(&areq.sa_addr, (void *)&ipv6addr, sizeof (ipv6addr));
88 areq.sa_res = -1;
89 (void) ioctl(s, SIOCTMYADDR, (caddr_t)&areq);
90 if (areq.sa_res == 1) {
91 res = 1;
92 break;
93 }
94 }
95
96 freehostent(hostinfo);
97
98 (void) close(s);
99 return (res);
100 }
101
102 #define MAXIFS 32
103
104 /*
105 * create an ifconf structure that represents all the interfaces
106 * configured for this host. Two buffers are allcated here:
107 * lifc - the ifconf structure returned
108 * lifc->lifc_buf - the list of ifreq structures
109 * Both of the buffers must be freed by the calling routine.
110 * A NULL pointer is returned upon failure. In this case any
111 * data that was allocated before the failure has already been
112 * freed.
113 */
114 struct lifconf *
getmyaddrs(void)115 getmyaddrs(void)
116 {
117 int sock;
118 struct lifnum lifn;
119 int numifs;
120 char *buf;
121 struct lifconf *lifc;
122
123 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
124 syslog(LOG_ERR, "statd:getmyaddrs socket: %m");
125 return ((struct lifconf *)NULL);
126 }
127
128 lifn.lifn_family = AF_UNSPEC;
129 lifn.lifn_flags = 0;
130
131 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
132 syslog(LOG_ERR,
133 "statd:getmyaddrs, get number of interfaces, error: %m");
134 numifs = MAXIFS;
135 }
136
137 numifs = lifn.lifn_count;
138
139 lifc = (struct lifconf *)malloc(sizeof (struct lifconf));
140 if (lifc == NULL) {
141 syslog(LOG_ERR,
142 "statd:getmyaddrs, malloc for lifconf failed: %m");
143 (void) close(sock);
144 return ((struct lifconf *)NULL);
145 }
146 buf = (char *)malloc(numifs * sizeof (struct lifreq));
147 if (buf == NULL) {
148 syslog(LOG_ERR,
149 "statd:getmyaddrs, malloc for lifreq failed: %m");
150 (void) close(sock);
151 free(lifc);
152 return ((struct lifconf *)NULL);
153 }
154
155 lifc->lifc_family = AF_UNSPEC;
156 lifc->lifc_flags = 0;
157 lifc->lifc_buf = buf;
158 lifc->lifc_len = numifs * sizeof (struct lifreq);
159
160 if (ioctl(sock, SIOCGLIFCONF, (char *)lifc) < 0) {
161 syslog(LOG_ERR, "statd:getmyaddrs, SIOCGLIFCONF, error: %m");
162 (void) close(sock);
163 free(buf);
164 free(lifc);
165 return ((struct lifconf *)NULL);
166 }
167
168 (void) close(sock);
169
170 return (lifc);
171 }
172
173 int
Is_ipv6present(void)174 Is_ipv6present(void)
175 {
176 int sock;
177 struct lifnum lifn;
178
179 sock = socket(AF_INET6, SOCK_DGRAM, 0);
180 if (sock < 0)
181 return (0);
182
183 lifn.lifn_family = AF_INET6;
184 lifn.lifn_flags = 0;
185 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
186 close(sock);
187 return (0);
188 }
189 close(sock);
190 if (lifn.lifn_count == 0)
191 return (0);
192 return (1);
193 }
194