Print this page
6198 Let's EOL cachefs
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-inet/sbin/netstrategy/netstrategy.c
+++ new/usr/src/cmd/cmd-inet/sbin/netstrategy/netstrategy.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 26 */
26 27
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 28
29 29 /*
30 30 * This program does the following:
31 31 *
32 32 * a) Returns:
33 33 * 0 - if the program successfully determined the net strategy.
34 34 * !0 - if an error occurred.
35 35 *
36 36 * b) If the program is successful, it prints three tokens to
37 37 * stdout: <root fs type> <interface name> <net config strategy>.
38 38 * where:
39 - * <root fs type> - "nfs" or "ufs"
39 + * <root fs type> - "nfs", "ufs" or "zfs"
40 40 * <interface name> - "hme0" or "none"
41 41 * <net config strategy> - "dhcp", "rarp", "bootprops"
42 42 * or "none"
43 43 *
44 44 * Eg:
45 45 * # /sbin/netstrategy
46 46 * ufs hme0 dhcp
47 47 *
48 48 * <root fs type> identifies the system's root file system type.
49 49 *
50 50 * <interface name> is the 16 char name of the root interface, and is only
51 51 * set if rarp/dhcp was used to configure the interface.
52 52 *
53 53 * <net config strategy> can be either "rarp", "dhcp", "bootprops", or
54 54 * "none" depending on which strategy was used to configure the
55 55 * interface. Is "none" if no interface was configured using a
56 56 * net-based strategy.
57 57 *
58 58 * CAVEATS: what about autoclient systems? XXX
59 59 *
60 60 * The logic here must match that in usr/src/uts/common/fs/nfs/nfs_dlinet.c,
61 61 * in particular that code (which implements diskless boot) imposes an
62 62 * ordering on possible ways of configuring network interfaces.
63 63 */
64 64
65 65 #include <stdio.h>
66 66 #include <stdlib.h>
67 67 #include <unistd.h>
68 68 #include <string.h>
69 69 #include <sys/types.h>
70 70 #include <errno.h>
71 71 #include <alloca.h>
72 72 #include <sys/systeminfo.h>
73 73 #include <sys/socket.h>
74 74 #include <sys/sockio.h>
75 75 #include <net/if.h>
76 76 #include <sys/statvfs.h>
77 77 #include <libdevinfo.h>
78 78
79 79 static char *program;
80 80
81 81 static int s4, s6; /* inet and inet6 sockets */
82 82
83 83 static boolean_t
84 84 open_sockets(void)
85 85 {
86 86 if ((s4 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
87 87 (void) fprintf(stderr, "%s: inet socket: %s\n", program,
88 88 strerror(errno));
89 89 return (B_FALSE);
90 90 }
91 91 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
92 92 (void) fprintf(stderr, "%s: inet6 socket: %s\n", program,
93 93 strerror(errno));
94 94 return (B_FALSE);
95 95 }
96 96 return (B_TRUE);
97 97 }
98 98
99 99 static void
100 100 close_sockets(void)
101 101 {
102 102 (void) close(s4);
103 103 (void) close(s6);
104 104 }
105 105
106 106 static char *
107 107 get_root_fstype()
108 108 {
109 109 static struct statvfs vfs;
110 110
111 111 /* root location */
112 112 if (statvfs("/", &vfs) < 0) {
113 113 return ("none");
114 114 } else {
115 115 if (strncmp(vfs.f_basetype, "nfs", sizeof ("nfs") - 1) == 0)
116 116 vfs.f_basetype[sizeof ("nfs") - 1] = '\0';
117 117 return (vfs.f_basetype);
118 118 }
119 119 }
120 120
121 121 /*
122 122 * The following boot properties can be used to configure a network
123 123 * interface in the case of a diskless boot.
124 124 * host-ip, subnet-mask, server-path, server-name, server-ip.
125 125 *
126 126 * XXX non-diskless case requires "network-interface"?
127 127 */
128 128 static boolean_t
129 129 boot_properties_present()
130 130 {
131 131 /* XXX should use sys/bootprops.h, but it's not delivered */
132 132 const char *required_properties[] = {
133 133 "host-ip",
134 134 "subnet-mask",
135 135 "server-path",
136 136 "server-name",
137 137 "server-ip",
138 138 NULL,
139 139 };
140 140 const char **prop = required_properties;
141 141 char *prop_value;
142 142 di_node_t dn;
143 143
144 144 if ((dn = di_init("/", DINFOPROP)) == DI_NODE_NIL) {
145 145 (void) fprintf(stderr, "%s: di_init: %s\n", program,
146 146 strerror(errno));
147 147 di_fini(dn);
148 148 return (B_FALSE);
149 149 }
150 150
151 151 while (*prop != NULL) {
152 152 if (di_prop_lookup_strings(DDI_DEV_T_ANY,
153 153 dn, *prop, &prop_value) != 1) {
154 154 di_fini(dn);
155 155 return (B_FALSE);
156 156 }
157 157 prop++;
158 158 }
159 159 di_fini(dn);
160 160
161 161 return (B_TRUE);
162 162 }
163 163
164 164 static char *
165 165 get_first_interface(boolean_t *dhcpflag)
166 166 {
167 167 struct lifnum ifnum;
168 168 struct lifconf ifconf;
169 169 struct lifreq *ifr;
170 170 static char interface[LIFNAMSIZ];
171 171 boolean_t isv4, found_one = B_FALSE;
172 172
173 173 ifnum.lifn_family = AF_UNSPEC;
174 174 ifnum.lifn_flags = 0;
175 175 ifnum.lifn_count = 0;
176 176
177 177 if (ioctl(s4, SIOCGLIFNUM, &ifnum) < 0) {
178 178 (void) fprintf(stderr, "%s: SIOCGLIFNUM: %s\n", program,
179 179 strerror(errno));
180 180 return (NULL);
181 181 }
182 182
183 183 ifconf.lifc_family = AF_UNSPEC;
184 184 ifconf.lifc_flags = 0;
185 185 ifconf.lifc_len = ifnum.lifn_count * sizeof (struct lifreq);
186 186 ifconf.lifc_buf = alloca(ifconf.lifc_len);
187 187
188 188 if (ioctl(s4, SIOCGLIFCONF, &ifconf) < 0) {
189 189 (void) fprintf(stderr, "%s: SIOCGLIFCONF: %s\n", program,
190 190 strerror(errno));
191 191 return (NULL);
192 192 }
193 193
194 194 for (ifr = ifconf.lifc_req; ifr < &ifconf.lifc_req[ifconf.lifc_len /
195 195 sizeof (ifconf.lifc_req[0])]; ifr++) {
196 196 struct lifreq flifr;
197 197 struct sockaddr_in *sin;
198 198
199 199 if (strchr(ifr->lifr_name, ':') != NULL)
200 200 continue; /* skip logical interfaces */
201 201
202 202 isv4 = ifr->lifr_addr.ss_family == AF_INET;
203 203
204 204 (void) strncpy(flifr.lifr_name, ifr->lifr_name, LIFNAMSIZ);
205 205
206 206 if (ioctl(isv4 ? s4 : s6, SIOCGLIFFLAGS, &flifr) < 0) {
207 207 (void) fprintf(stderr, "%s: SIOCGLIFFLAGS: %s\n",
208 208 program, strerror(errno));
209 209 continue;
210 210 }
211 211
212 212 if (!(flifr.lifr_flags & IFF_UP) ||
213 213 (flifr.lifr_flags & (IFF_VIRTUAL|IFF_POINTOPOINT)))
214 214 continue;
215 215
216 216 /*
217 217 * For the "nfs rarp" and "nfs bootprops"
218 218 * cases, we assume that the first non-virtual
219 219 * IFF_UP interface with a non-zero address is
220 220 * the one used.
221 221 *
222 222 * For the non-zero address check, we only check
223 223 * v4 interfaces, as it's not possible to set the
224 224 * the first logical interface (the only ones we
225 225 * look at here) to ::0; that interface must have
226 226 * a link-local address.
227 227 *
228 228 * If we don't find an IFF_UP interface with a
229 229 * non-zero address, we'll return the last IFF_UP
230 230 * interface seen.
231 231 *
232 232 * Since the order of the interfaces retrieved
233 233 * via SIOCGLIFCONF is not deterministic, this
234 234 * is largely silliness, but (a) "it's always
235 235 * been this way", and (b) no one consumes the
236 236 * interface name in the RARP case anyway.
237 237 */
238 238
239 239 found_one = B_TRUE;
240 240 (void) strncpy(interface, ifr->lifr_name, LIFNAMSIZ);
241 241 *dhcpflag = (flifr.lifr_flags & IFF_DHCPRUNNING) != 0;
242 242 sin = (struct sockaddr_in *)&ifr->lifr_addr;
243 243 if (isv4 && (sin->sin_addr.s_addr == INADDR_ANY)) {
244 244 /* keep looking for a non-zero address */
245 245 continue;
246 246 }
247 247 return (interface);
248 248 }
249 249
250 250 return (found_one ? interface : NULL);
251 251 }
252 252
253 253 /* ARGSUSED */
254 254 int
255 255 main(int argc, char *argv[])
256 256 {
257 257 char *root, *interface, *strategy, dummy;
258 258 long len;
259 259 boolean_t dhcp_running = B_FALSE;
260 260
261 261 root = interface = strategy = NULL;
262 262 program = argv[0];
263 263
264 264 root = get_root_fstype();
265 265
266 266 if (!open_sockets()) {
267 267 (void) fprintf(stderr,
268 268 "%s: cannot get interface information\n", program);
269 269 return (2);
270 270 }
271 271
272 272 /*
273 273 * If diskless, perhaps boot properties were used to configure
274 274 * the interface.
275 275 */
276 276 if ((strcmp(root, "nfs") == 0) && boot_properties_present()) {
277 277 strategy = "bootprops";
278 278
279 279 interface = get_first_interface(&dhcp_running);
280 280 if (interface == NULL) {
281 281 (void) fprintf(stderr,
282 282 "%s: cannot identify root interface.\n", program);
283 283 close_sockets();
284 284 return (2);
285 285 }
286 286
287 287 (void) printf("%s %s %s\n", root, interface, strategy);
288 288 close_sockets();
289 289 return (0);
290 290 }
291 291
292 292 /*
293 293 * Handle the simple case where diskless dhcp tells us everything
294 294 * we need to know.
295 295 */
296 296 if ((len = sysinfo(SI_DHCP_CACHE, &dummy, sizeof (dummy))) > 1) {
297 297 /* interface is first thing in cache. */
298 298 strategy = "dhcp";
299 299 interface = alloca(len);
300 300 (void) sysinfo(SI_DHCP_CACHE, interface, len);
↓ open down ↓ |
251 lines elided |
↑ open up ↑ |
301 301 (void) printf("%s %s %s\n", root, interface, strategy);
302 302 close_sockets();
303 303 return (0);
304 304 }
305 305
306 306 /*
307 307 * We're not "nfs dhcp", "nfs none" is impossible, and we don't handle
308 308 * "ufs rarp" (consumers are coded to deal with this reality), so
309 309 * there are three possible situations:
310 310 *
311 - * 1. We're "ufs dhcp" if there are any interfaces which have
312 - * obtained their addresses through DHCP. That is, if there
313 - * are any IFF_UP and non-IFF_VIRTUAL interfaces also have
314 - * IFF_DHCPRUNNING set.
311 + * 1. We're either "ufs dhcp" or "zfs dhcp" if there are any
312 + * interfaces which have obtained their addresses through DHCP.
313 + * That is, if there are any IFF_UP and non-IFF_VIRTUAL
314 + * interfaces also have IFF_DHCPRUNNING set.
315 315 *
316 - * 2. We're "ufs none" if our filesystem is local and there
317 - * are no interfaces which have obtained their addresses
318 - * through DHCP.
316 + * 2. We're either "ufs none" or "zfs none" if our filesystem
317 + * is local and there are no interfaces which have obtained
318 + * their addresses through DHCP.
319 319 *
320 320 * 3. We're "nfs rarp" if our filesystem is remote and there's
321 321 * at least IFF_UP non-IFF_VIRTUAL interface (which there
322 322 * *must* be, since we're running over NFS somehow), then
323 323 * it must be RARP since SI_DHCP_CACHE call above failed.
324 324 * It's too bad there isn't an IFF_RARPRUNNING flag.
325 325 */
326 326
327 327 interface = get_first_interface(&dhcp_running);
328 328
329 329 if (dhcp_running)
330 330 strategy = "dhcp";
331 331
332 - if (strcmp(root, "nfs") == 0 || strcmp(root, "cachefs") == 0) {
332 + if (strcmp(root, "nfs") == 0) {
333 333 if (interface == NULL) {
334 334 (void) fprintf(stderr,
335 335 "%s: cannot identify root interface.\n", program);
336 336 close_sockets();
337 337 return (2);
338 338 }
339 339 if (strategy == NULL)
340 340 strategy = "rarp"; /* must be rarp/bootparams */
341 341 } else {
342 342 if (interface == NULL || strategy == NULL)
343 343 interface = strategy = "none";
344 344 }
345 345
346 346 (void) printf("%s %s %s\n", root, interface, strategy);
347 347 close_sockets();
348 348 return (0);
349 349 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX