3909 "zfs send -D" does not work
[illumos-gate.git] / usr / src / common / net / wanboot / bootinfo.c
blob67611d877453ad98ac38af65f59ca7560038713d
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <dhcp_impl.h>
32 #include <sys/time.h>
33 #include <sys/nvpair.h>
34 #include <netinet/inetutil.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <strings.h>
38 #include <net/if.h>
39 #if defined(_BOOT)
40 #include <sys/salib.h>
41 #include <sys/bootcmn.h>
42 #include <ipv4.h>
43 #include <dhcpv4.h>
44 #endif /* defined(_BOOT) */
45 #include <bootinfo.h>
46 #include <bootinfo_aux.h>
49 * Declarations and definitions describing parameters which may be known by
50 * a bootconf name, a property of /chosen, a DHCP option or a 'bootmisc' name.
52 typedef struct {
53 const char *opt_name; /* DHCP option name */
54 dsym_cdtype_t opt_type; /* DHCP option type (dhcp_symbol.h) */
55 uchar_t opt_cat; /* DHCP option category */
56 uint16_t opt_code; /* DHCP option code */
57 uint16_t opt_size; /* DHCP option size (FIELDs only) */
58 } bi_dhcpopt_t;
61 * Possible values for the 'bi_flags' field below.
63 #define BI_F_BYTES 0x01 /* chosen value is bytes, not string */
65 typedef struct {
66 const char *bi_name; /* parameter name */
67 int bi_repository; /* entry's repository(s) */
68 int bi_flags; /* BI_F_BYTES or zero */
69 bi_dhcpopt_t *bi_dhcp; /* &dhcpopt struct */
70 } bi_param_t;
73 * DHCP options which have bootinfo equivalents, and the information
74 * necessary to retrieve their values via dhcp_getinfo(). The 'type'
75 * is necessary so that all values may be converted to ascii strings.
77 static bi_dhcpopt_t Yiaddr = {
78 "Yiaddr", DSYM_IP, DSYM_FIELD, 16, 4
80 static bi_dhcpopt_t Subnet = {
81 "Subnet", DSYM_IP, DSYM_STANDARD, 1, 0
83 static bi_dhcpopt_t Router = {
84 "Router", DSYM_IP, DSYM_STANDARD, 3, 0
86 static bi_dhcpopt_t Hostname = {
87 "Hostname", DSYM_ASCII, DSYM_STANDARD, 12, 0
89 static bi_dhcpopt_t ClientID = {
90 "ClientID", DSYM_OCTET, DSYM_STANDARD, 61, 0
92 static bi_dhcpopt_t SHTTPproxy = {
93 "SHTTPproxy", DSYM_ASCII, DSYM_VENDOR, 17, 0
95 #if defined(_BOOT)
96 static bi_dhcpopt_t BootFile = {
97 "BootFile", DSYM_ASCII, DSYM_FIELD, 108, 128
99 static bi_dhcpopt_t SbootURI = {
100 "SbootURI", DSYM_ASCII, DSYM_VENDOR, 16, 0
102 #else
103 static bi_dhcpopt_t SsysidCF = {
104 "SsysidCF", DSYM_ASCII, DSYM_VENDOR, 13, 0
106 static bi_dhcpopt_t SjumpsCF = {
107 "SjumpsCF", DSYM_ASCII, DSYM_VENDOR, 14, 0
109 #endif /* defined(_BOOT) */
112 * bootinfo's main data structure.
114 static bi_param_t bi_params[] = {
116 * Parameters from /chosen or DHCP:
118 { BI_HOST_IP, BI_R_CHOSEN|BI_R_DHCPOPT,
119 0, &Yiaddr },
120 { BI_SUBNET_MASK, BI_R_CHOSEN|BI_R_DHCPOPT,
121 0, &Subnet },
122 { BI_ROUTER_IP, BI_R_CHOSEN|BI_R_DHCPOPT,
123 0, &Router },
124 { BI_HOSTNAME, BI_R_CHOSEN|BI_R_DHCPOPT,
125 0, &Hostname },
126 { BI_CLIENT_ID, BI_R_CHOSEN|BI_R_DHCPOPT,
127 BI_F_BYTES, &ClientID },
128 { BI_HTTP_PROXY, BI_R_CHOSEN|BI_R_DHCPOPT,
129 0, &SHTTPproxy },
131 #if defined(_BOOT)
133 * Parameters from /chosen or DHCP:
135 { BI_NETWORK_BOOT_FILE, BI_R_CHOSEN|BI_R_DHCPOPT,
136 0, &SbootURI },
139 * Parameters from DHCP only:
141 { BI_BOOTFILE, BI_R_DHCPOPT,
142 0, &BootFile },
145 * Parameters from /chosen only:
147 { BI_BOOTP_RESPONSE, BI_R_CHOSEN,
148 BI_F_BYTES, NULL },
149 { BI_NET_CONFIG_STRATEGY, BI_R_CHOSEN,
150 0, NULL },
153 * Parameters from 'bootmisc' only:
155 { BI_BOOTSERVER, BI_R_BOOTMISC,
156 0, NULL },
157 { BI_AES_KEY, BI_R_BOOTMISC,
158 BI_F_BYTES, NULL },
159 { BI_3DES_KEY, BI_R_BOOTMISC,
160 BI_F_BYTES, NULL },
161 { BI_SHA1_KEY, BI_R_BOOTMISC,
162 BI_F_BYTES, NULL },
163 #else
165 * Parameters from DHCP only:
167 { BI_SYSIDCFG, BI_R_DHCPOPT,
168 0, &SsysidCF },
169 { BI_JUMPSCFG, BI_R_DHCPOPT,
170 0, &SjumpsCF },
173 * Parameters from /chosen or 'bootmisc':
175 { BI_NET_CONFIG_STRATEGY, BI_R_CHOSEN|BI_R_BOOTMISC,
176 0, NULL },
179 * Parameters from 'bootmisc' only:
181 { BI_ROOTFS_TYPE, BI_R_BOOTMISC,
182 0, NULL },
183 { BI_INTERFACE_NAME, BI_R_BOOTMISC,
184 0, NULL },
185 #endif /* defined(_BOOT) */
187 NULL
191 * Bootmisc data is handled internally as a nvpair list.
193 static nvlist_t *bi_nvl = NULL;
197 * Scan our parameter table to see whether 'name' matches any entry.
199 static bi_param_t *
200 bi_find_param(const char *name)
202 bi_param_t *bip;
204 for (bip = bi_params; bip->bi_name != NULL; bip++) {
205 if (strcmp(name, bip->bi_name) == 0 ||
206 ((bip->bi_repository & BI_R_DHCPOPT) &&
207 strcmp(name, bip->bi_dhcp->opt_name) == 0)) {
208 return (bip);
211 return (NULL);
215 * Functions for retrieving /chosen, DHCP and bootmisc data.
217 static int
218 bi_getval_chosen(bi_param_t *bip, void *valbuf, size_t *vallenp)
220 size_t buflen = *vallenp;
222 if (!bi_get_chosen_prop(bip->bi_name, valbuf, vallenp)) {
223 return (BI_E_NOVAL);
224 } else if (*vallenp > buflen) {
225 return (BI_E_BUF2SMALL);
228 return (BI_E_SUCCESS);
231 static int
232 bi_getval_dhcpopt(bi_param_t *bip, void *valbuf, size_t *vallenp)
234 void *val;
235 size_t len, buflen = *vallenp;
236 struct in_addr ipaddr;
238 if (bip->bi_dhcp->opt_type == DSYM_IP) {
239 val = &ipaddr;
240 len = sizeof (ipaddr);
241 } else {
242 val = valbuf;
243 len = *vallenp;
246 if (!bi_get_dhcp_info(bip->bi_dhcp->opt_cat, bip->bi_dhcp->opt_code,
247 bip->bi_dhcp->opt_size, val, &len)) {
248 return (BI_E_NOVAL);
251 switch (bip->bi_dhcp->opt_type) {
252 case DSYM_IP:
253 if (buflen < INET_ADDRSTRLEN + 1) {
254 *vallenp = len;
255 return (BI_E_BUF2SMALL);
257 len = strlen(strcpy(valbuf, inet_ntoa(ipaddr))) + 1;
258 break;
260 case DSYM_ASCII:
261 if (len >= buflen)
262 return (BI_E_BUF2SMALL);
264 ((uchar_t *)valbuf)[len++] = '\0';
265 break;
267 *vallenp = len;
269 return (BI_E_SUCCESS);
272 static int
273 bi_getval_bootmisc(bi_param_t *bip, void *valbuf, size_t *vallenp)
275 uchar_t *val;
276 uint_t len;
278 if (nvlist_lookup_byte_array(bi_nvl, (char *)bip->bi_name,
279 &val, &len) != 0) {
280 return (BI_E_NOVAL);
281 } else if (*vallenp < len) {
282 *vallenp = len;
283 return (BI_E_BUF2SMALL);
285 *vallenp = len;
286 (void) memcpy(valbuf, val, *vallenp);
288 return (BI_E_SUCCESS);
292 * This is also called from the userland bootinfo_aux.c to initialize
293 * its bootmisc data.
295 boolean_t
296 bi_put_bootmisc(const char *name, const void *valbuf, size_t vallen)
298 return (nvlist_add_byte_array(bi_nvl, (char *)name,
299 (uchar_t *)valbuf, (uint_t)vallen) == 0);
302 #if defined(_BOOT)
304 * Functions for storing /chosen and bootmisc data.
306 static int
307 bi_putval_chosen(bi_param_t *bip, const void *valbuf, size_t vallen)
309 return (bi_put_chosen_prop(bip->bi_name, valbuf, vallen,
310 (bip->bi_flags & BI_F_BYTES)) ? BI_E_SUCCESS : BI_E_ERROR);
313 static int
314 bi_putval_bootmisc(bi_param_t *bip, const void *valbuf, size_t vallen)
316 return (bi_put_bootmisc(bip->bi_name, valbuf, vallen)
317 ? BI_E_SUCCESS : BI_E_ERROR);
319 #endif /* defined(_BOOT) */
323 * Deallocate resources, etc. after accessing bootinfo.
325 void
326 bootinfo_end(void)
328 if (bi_nvl != NULL) {
329 nvlist_free(bi_nvl);
330 bi_nvl = NULL;
331 bi_end_bootinfo();
336 * Perform bootinfo initialization.
338 boolean_t
339 bootinfo_init(void)
341 if (bi_nvl == NULL &&
342 nvlist_alloc(&bi_nvl, NV_UNIQUE_NAME, 0) == 0) {
343 if (!bi_init_bootinfo()) {
344 nvlist_free(bi_nvl);
345 bi_nvl = NULL;
349 return (bi_nvl != NULL);
353 * bootinfo_get(const char *name, void *valbuf, size_t *vallenp,
354 * int *repository);
356 * Obtain a value for a named boot parameter from one of a number of possible
357 * repositories:
359 * - stored properties under /chosen in the device tree;
360 * - returned DHCP data;
361 * - miscellaneous boot information, determined from the standalone or
362 * the kernel (depending on whether we're in the standalone or userland).
364 * These repositories are interrogated in the order listed above; the first
365 * one to match is value returned.
367 * Returns:
368 * 0 => successful, value copied to valbuf, length assigned to *vallen.
369 * >0 => error (BI_E_* codes defined in bootinfo.h)
371 bi_errcode_t
372 bootinfo_get(const char *name, void *valbufp, size_t *vallenp,
373 int *repositoryp)
375 bi_param_t *bip;
376 int repositories;
377 int err;
378 size_t zerolen = 0;
381 * Check whether we were successfully initialized.
383 if (bi_nvl == NULL) {
384 return (BI_E_ERROR);
388 * Determine which repositories might be accessed; a NULL pointer
389 * means to (possibly) access them all.
391 if (repositoryp != NULL) {
392 repositories = *repositoryp;
393 *repositoryp = 0;
394 } else {
395 repositories = BI_R_ALL;
399 * Check that we know about this name in one or more of the
400 * requested repositories.
402 if ((bip = bi_find_param(name)) == NULL) {
403 return (BI_E_ILLNAME);
405 repositories &= bip->bi_repository;
406 if (repositories == 0) {
407 return (BI_E_ILLNAME);
411 * The caller may simply be enquiring whether a value is present:
413 * bootinfo_get(name, NULL, NULL, repository) == BI_E_BUF2SMALL
415 * indicates that there is a value, but doesn't fetch it.
417 if (vallenp == NULL) {
418 vallenp = &zerolen;
422 * To retrieve a value, try the various repositories in order.
424 if ((repositories & BI_R_CHOSEN) != 0 &&
425 (err = bi_getval_chosen(bip, valbufp, vallenp)) != BI_E_NOVAL) {
426 if (repositoryp != NULL) {
427 *repositoryp = BI_R_CHOSEN;
429 return (err);
431 if ((repositories & BI_R_DHCPOPT) != 0 &&
432 (err = bi_getval_dhcpopt(bip, valbufp, vallenp)) != BI_E_NOVAL) {
433 if (repositoryp != NULL) {
434 *repositoryp = BI_R_DHCPOPT;
436 return (err);
438 if ((repositories & BI_R_BOOTMISC) != 0 &&
439 (err = bi_getval_bootmisc(bip, valbufp, vallenp)) != BI_E_NOVAL) {
440 if (repositoryp != NULL) {
441 *repositoryp = BI_R_BOOTMISC;
443 return (err);
447 * No-one has a value for 'name'.
449 return (BI_E_NOVAL);
452 #if defined(_BOOT)
454 * bootinfo_put(const char *name, char *valbuf, int vallen,
455 * int repository);
457 * Create/update a value in the bootinfo repository (standalone only).
459 * Returns:
460 * 0 => successful, valbuf[0..vallen-1] bytes stored in repository
461 * >0 => error (BI_E_* codes defined in bootinfo.h)
464 bootinfo_put(const char *name, const void *valbuf, size_t vallen,
465 int repository)
467 bi_param_t *bip;
470 * Check whether we were successfully initialized.
472 if (bi_nvl == NULL) {
473 return (BI_E_ERROR);
477 * Determine which repositories might be accessed; a zero value
478 * means to (possibly) access them all.
480 if (repository == 0) {
481 repository = BI_R_ALL;
485 * Check that we know about this name in the specified repository,
486 * and that it may be written (note that DHCP options cannot be
487 * written).
489 if ((bip = bi_find_param(name)) == NULL ||
490 (repository & bip->bi_repository) == 0) {
491 return (BI_E_ILLNAME);
493 if ((repository & bip->bi_repository) == BI_R_DHCPOPT) {
494 return (BI_E_RDONLY);
498 * To put the value, try the various repositories in order.
500 if ((bip->bi_repository & BI_R_CHOSEN) != 0) {
501 return (bi_putval_chosen(bip, valbuf, vallen));
503 if ((bip->bi_repository & BI_R_BOOTMISC) != 0) {
504 return (bi_putval_bootmisc(bip, valbuf, vallen));
507 return (BI_E_ERROR);
509 #endif /* defined(_BOOT) */