17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*2a9459bdSsangeeta * Common Development and Distribution License (the "License").
6*2a9459bdSsangeeta * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*2a9459bdSsangeeta * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/salib.h>
297c478bd9Sstevel@tonic-gate #include <sys/promif.h>
307c478bd9Sstevel@tonic-gate #include <sys/wanboot_impl.h>
317c478bd9Sstevel@tonic-gate #include <netinet/in.h>
327c478bd9Sstevel@tonic-gate #include <parseURL.h>
337c478bd9Sstevel@tonic-gate #include <bootlog.h>
347c478bd9Sstevel@tonic-gate #include <sys/socket.h>
357c478bd9Sstevel@tonic-gate #include <netinet/inetutil.h>
367c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h>
377c478bd9Sstevel@tonic-gate #include <dhcp_impl.h>
387c478bd9Sstevel@tonic-gate #include <lib/inet/mac.h>
397c478bd9Sstevel@tonic-gate #include <lib/inet/ipv4.h>
407c478bd9Sstevel@tonic-gate #include <lib/inet/dhcpv4.h>
417c478bd9Sstevel@tonic-gate #include <lib/sock/sock_test.h>
427c478bd9Sstevel@tonic-gate #include <sys/sunos_dhcp_class.h>
437c478bd9Sstevel@tonic-gate #include <aes.h>
447c478bd9Sstevel@tonic-gate #include <des3.h>
457c478bd9Sstevel@tonic-gate #include <hmac_sha1.h>
467c478bd9Sstevel@tonic-gate #include <netdb.h>
477c478bd9Sstevel@tonic-gate #include <wanboot_conf.h>
487c478bd9Sstevel@tonic-gate #include <bootinfo.h>
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #include "wbcli.h"
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #define skipspace(p) while (isspace(*(p))) ++p
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #define skiptext(p) while (*(p) != '\0' && !isspace(*(p)) && \
557c478bd9Sstevel@tonic-gate *(p) != '=' && *(p) != ',') ++p
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #define PROMPT "boot> "
587c478bd9Sstevel@tonic-gate #define TEST_PROMPT "boot-test> "
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #define CLI_SET 0
617c478bd9Sstevel@tonic-gate #define CLI_FAIL (-1)
627c478bd9Sstevel@tonic-gate #define CLI_EXIT (-2)
637c478bd9Sstevel@tonic-gate #define CLI_CONT (-3)
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #define CLF_CMD 0x00000001 /* builtin command */
667c478bd9Sstevel@tonic-gate #define CLF_ARG 0x00000002 /* boot argument directive */
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #define CLF_IF 0x00000100 /* interface parameter */
697c478bd9Sstevel@tonic-gate #define CLF_BM 0x00000200 /* bootmisc parameter */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate #define CLF_VALSET 0x00010000 /* value set, may be null */
727c478bd9Sstevel@tonic-gate #define CLF_HIDDEN 0x00020000 /* don't show its value (key) */
737c478bd9Sstevel@tonic-gate #define CLF_VALMOD 0x00040000 /* value modified by the user */
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate * Macros for use in managing the flags in the cli_list[].
777c478bd9Sstevel@tonic-gate * The conventions we follow are:
787c478bd9Sstevel@tonic-gate *
797c478bd9Sstevel@tonic-gate * CLF_VALSET is cleared if a value is removed from varptr
807c478bd9Sstevel@tonic-gate * CLF_VALSET is set if a value has been placed in varptr
817c478bd9Sstevel@tonic-gate * (that value need not be vetted)
827c478bd9Sstevel@tonic-gate * CLF_HIDDEN is set if a value must not be exposed to the user
837c478bd9Sstevel@tonic-gate * CLF_HIDDEN is cleared if a value can be exposed to the user
847c478bd9Sstevel@tonic-gate * CLF_VALMOD is cleared if a value in varptr has not been modified
857c478bd9Sstevel@tonic-gate * CLF_VALMOD is set if a value in varptr has been modified by
867c478bd9Sstevel@tonic-gate * the user
877c478bd9Sstevel@tonic-gate */
887c478bd9Sstevel@tonic-gate #ifdef DEBUG
897c478bd9Sstevel@tonic-gate #define CLF_SETVAL(var) { \
907c478bd9Sstevel@tonic-gate (((var)->flags) |= CLF_VALSET); \
917c478bd9Sstevel@tonic-gate printf("set %s\n", var->varname);\
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate #define CLF_ISSET(var) (printf("%s\n", \
957c478bd9Sstevel@tonic-gate (((var)->flags) & CLF_VALSET) != 0 \
967c478bd9Sstevel@tonic-gate ? "is set" : "not set"), \
977c478bd9Sstevel@tonic-gate ((((var)->flags) & CLF_VALSET) != 0))
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate #define CLF_CLRHIDDEN(var) { \
1007c478bd9Sstevel@tonic-gate (((var)->flags) &= ~CLF_HIDDEN); \
1017c478bd9Sstevel@tonic-gate printf("unhide %s\n", var->varname); \
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate #define CLF_ISHIDDEN(var) (printf("%s\n", \
1057c478bd9Sstevel@tonic-gate (((var)->flags) & CLF_HIDDEN) != 0 \
1067c478bd9Sstevel@tonic-gate ? "is hidden" : "not hidden"), \
1077c478bd9Sstevel@tonic-gate ((((var)->flags) & CLF_HIDDEN) != 0))
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate #define CLF_MODVAL(var) { \
1107c478bd9Sstevel@tonic-gate (((var)->flags) |= \
1117c478bd9Sstevel@tonic-gate (CLF_VALMOD | CLF_VALSET)); \
1127c478bd9Sstevel@tonic-gate printf("modified %s\n", var->varname);\
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate #define CLF_ISMOD(var) (printf("%s\n", \
1167c478bd9Sstevel@tonic-gate (((var)->flags) & CLF_VALMOD) != 0 \
1177c478bd9Sstevel@tonic-gate ? "is set" : "not set"), \
1187c478bd9Sstevel@tonic-gate ((((var)->flags) & CLF_VALMOD) != 0))
1197c478bd9Sstevel@tonic-gate #else /* DEBUG */
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate #define CLF_SETVAL(var) (((var)->flags) |= CLF_VALSET)
1227c478bd9Sstevel@tonic-gate #define CLF_ISSET(var) ((((var)->flags) & CLF_VALSET) != 0)
1237c478bd9Sstevel@tonic-gate #define CLF_CLRHIDDEN(var) (((var)->flags) &= ~CLF_HIDDEN)
1247c478bd9Sstevel@tonic-gate #define CLF_ISHIDDEN(var) ((((var)->flags) & CLF_HIDDEN) != 0)
1257c478bd9Sstevel@tonic-gate #define CLF_MODVAL(var) (((var)->flags) |= (CLF_VALMOD | CLF_VALSET))
1267c478bd9Sstevel@tonic-gate #define CLF_ISMOD(var) ((((var)->flags) & CLF_VALMOD) != 0)
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate * The width of the widest varname below - currently "subnet_mask".
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate #define VAR_MAXWIDTH strlen(BI_SUBNET_MASK)
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate struct cli_ent;
1367c478bd9Sstevel@tonic-gate typedef int claction_t(struct cli_ent *, char *, boolean_t);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate typedef struct cli_ent {
1397c478bd9Sstevel@tonic-gate char *varname;
1407c478bd9Sstevel@tonic-gate claction_t *action;
1417c478bd9Sstevel@tonic-gate int flags;
1427c478bd9Sstevel@tonic-gate void *varptr;
1437c478bd9Sstevel@tonic-gate uint_t varlen;
1447c478bd9Sstevel@tonic-gate uint_t varmax;
1457c478bd9Sstevel@tonic-gate } cli_ent_t;
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate static cli_ent_t *find_cli_ent(char *varstr);
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate static char cmdbuf[2048]; /* interpreter buffer */
1507c478bd9Sstevel@tonic-gate static char hostip[INET_ADDRSTRLEN];
1517c478bd9Sstevel@tonic-gate static char subnet[INET_ADDRSTRLEN];
1527c478bd9Sstevel@tonic-gate static char router[INET_ADDRSTRLEN];
1537c478bd9Sstevel@tonic-gate static char hostname[MAXHOSTNAMELEN];
1547c478bd9Sstevel@tonic-gate static char httpproxy[INET_ADDRSTRLEN + 5]; /* a.b.c.d:p */
1557c478bd9Sstevel@tonic-gate static char bootserverURL[URL_MAX_STRLEN + 1];
1567c478bd9Sstevel@tonic-gate static unsigned char clientid[WB_MAX_CID_LEN];
1577c478bd9Sstevel@tonic-gate static unsigned char aeskey[AES_128_KEY_SIZE];
1587c478bd9Sstevel@tonic-gate static unsigned char des3key[DES3_KEY_SIZE];
1597c478bd9Sstevel@tonic-gate static unsigned char sha1key[WANBOOT_HMAC_KEY_SIZE];
1607c478bd9Sstevel@tonic-gate static boolean_t args_specified_prompt = B_FALSE;
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate extern bc_handle_t bc_handle;
1637c478bd9Sstevel@tonic-gate extern int getchar(void);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate static claction_t clcid, clkey, clip, clstr, clurl, clhp;
1667c478bd9Sstevel@tonic-gate static claction_t clhelp, cllist, clprompt, cldhcp, cltest, clgo, clexit;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate static cli_ent_t cli_list[] = {
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * Commands/bootargs:
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate { "test", cltest, CLF_ARG,
1737c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1747c478bd9Sstevel@tonic-gate { "dhcp", cldhcp, CLF_ARG,
1757c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1767c478bd9Sstevel@tonic-gate { "prompt", clprompt, CLF_CMD | CLF_ARG,
1777c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1787c478bd9Sstevel@tonic-gate { "list", cllist, CLF_CMD,
1797c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1807c478bd9Sstevel@tonic-gate { "help", clhelp, CLF_CMD,
1817c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1827c478bd9Sstevel@tonic-gate { "go", clgo, CLF_CMD,
1837c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1847c478bd9Sstevel@tonic-gate { "exit", clexit, CLF_CMD,
1857c478bd9Sstevel@tonic-gate NULL, 0, 0 },
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate * Interface:
1897c478bd9Sstevel@tonic-gate */
1907c478bd9Sstevel@tonic-gate { BI_HOST_IP, clip, CLF_IF,
1917c478bd9Sstevel@tonic-gate hostip, 0, sizeof (hostip) },
1927c478bd9Sstevel@tonic-gate { BI_SUBNET_MASK, clip, CLF_IF,
1937c478bd9Sstevel@tonic-gate subnet, 0, sizeof (subnet) },
1947c478bd9Sstevel@tonic-gate { BI_ROUTER_IP, clip, CLF_IF,
1957c478bd9Sstevel@tonic-gate router, 0, sizeof (router) },
1967c478bd9Sstevel@tonic-gate { BI_HOSTNAME, clstr, CLF_IF,
1977c478bd9Sstevel@tonic-gate hostname, 0, sizeof (hostname) },
1987c478bd9Sstevel@tonic-gate { BI_HTTP_PROXY, clhp, CLF_IF,
1997c478bd9Sstevel@tonic-gate httpproxy, 0, sizeof (httpproxy) },
2007c478bd9Sstevel@tonic-gate { BI_CLIENT_ID, clcid, CLF_IF,
2017c478bd9Sstevel@tonic-gate clientid, 0, sizeof (clientid) },
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate * Bootmisc:
2057c478bd9Sstevel@tonic-gate */
2067c478bd9Sstevel@tonic-gate { BI_AES_KEY, clkey, CLF_BM | CLF_HIDDEN,
2077c478bd9Sstevel@tonic-gate aeskey, 0, sizeof (aeskey) },
2087c478bd9Sstevel@tonic-gate { BI_3DES_KEY, clkey, CLF_BM | CLF_HIDDEN,
2097c478bd9Sstevel@tonic-gate des3key, 0, sizeof (des3key) },
2107c478bd9Sstevel@tonic-gate { BI_SHA1_KEY, clkey, CLF_BM | CLF_HIDDEN,
2117c478bd9Sstevel@tonic-gate sha1key, 0, sizeof (sha1key) },
2127c478bd9Sstevel@tonic-gate { BI_BOOTSERVER, clurl, CLF_BM,
2137c478bd9Sstevel@tonic-gate bootserverURL, 0, sizeof (bootserverURL) },
2147c478bd9Sstevel@tonic-gate };
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate static int num_cli_ent = (sizeof (cli_list) / sizeof (cli_ent_t));
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * Fetch a line from the user, handling backspace appropriately.
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate static int
editline(char * buf,int count)2227c478bd9Sstevel@tonic-gate editline(char *buf, int count)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate int i = 0;
2257c478bd9Sstevel@tonic-gate char c;
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate while (i < count - 1) {
2287c478bd9Sstevel@tonic-gate c = getchar();
2297c478bd9Sstevel@tonic-gate if (c == '\n') {
2307c478bd9Sstevel@tonic-gate break;
2317c478bd9Sstevel@tonic-gate } else if (c == '\b') {
2327c478bd9Sstevel@tonic-gate /* Clear for backspace. */
2337c478bd9Sstevel@tonic-gate if (i > 0)
2347c478bd9Sstevel@tonic-gate i--;
2357c478bd9Sstevel@tonic-gate continue;
2367c478bd9Sstevel@tonic-gate } else {
2377c478bd9Sstevel@tonic-gate buf[i++] = c;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate buf[i] = '\0';
2417c478bd9Sstevel@tonic-gate return (i);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * Assign a client-id to cliptr, or output cliptr's value as a client-id.
2467c478bd9Sstevel@tonic-gate * On assignment the value is specified in valstr, either in hexascii or
2477c478bd9Sstevel@tonic-gate * as a quoted string; on output its value is printed in hexascii.
2487c478bd9Sstevel@tonic-gate */
2497c478bd9Sstevel@tonic-gate static int
clcid(cli_ent_t * cliptr,char * valstr,boolean_t out)2507c478bd9Sstevel@tonic-gate clcid(cli_ent_t *cliptr, char *valstr, boolean_t out)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate uint_t len, vmax;
2537c478bd9Sstevel@tonic-gate boolean_t hexascii = B_TRUE;
2547c478bd9Sstevel@tonic-gate char buffer[2 * WB_MAX_CID_LEN + 1];
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate if (out) {
2577c478bd9Sstevel@tonic-gate len = cliptr->varlen * 2 + 1;
2587c478bd9Sstevel@tonic-gate (void) octet_to_hexascii(cliptr->varptr, cliptr->varlen,
2597c478bd9Sstevel@tonic-gate buffer, &len);
2607c478bd9Sstevel@tonic-gate printf("%s", buffer);
2617c478bd9Sstevel@tonic-gate return (CLI_CONT);
2627c478bd9Sstevel@tonic-gate } else {
2637c478bd9Sstevel@tonic-gate len = strlen(valstr);
2647c478bd9Sstevel@tonic-gate vmax = cliptr->varmax - 1; /* space for the prefix */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Check whether the value is a quoted string; if so, strip
2687c478bd9Sstevel@tonic-gate * the quotes and note that it's not in hexascii.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate if ((valstr[0] == '"' || valstr[0] == '\'') &&
2717c478bd9Sstevel@tonic-gate valstr[len-1] == valstr[0]) {
2727c478bd9Sstevel@tonic-gate hexascii = B_FALSE;
2737c478bd9Sstevel@tonic-gate ++valstr;
2747c478bd9Sstevel@tonic-gate len -= 2;
2757c478bd9Sstevel@tonic-gate valstr[len] = '\0';
2767c478bd9Sstevel@tonic-gate } else {
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate * If the value contains any non-hex digits assume
2797c478bd9Sstevel@tonic-gate * that it's not in hexascii.
2807c478bd9Sstevel@tonic-gate */
2817c478bd9Sstevel@tonic-gate char *p;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate for (p = valstr; *p != '\0'; ++p) {
2847c478bd9Sstevel@tonic-gate if (!isxdigit(*p)) {
2857c478bd9Sstevel@tonic-gate hexascii = B_FALSE;
2867c478bd9Sstevel@tonic-gate break;
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate if (hexascii) {
2927c478bd9Sstevel@tonic-gate if (len > vmax * 2 ||
2937c478bd9Sstevel@tonic-gate hexascii_to_octet(valstr, len,
2947c478bd9Sstevel@tonic-gate (char *)(cliptr->varptr), &vmax) != 0) {
2957c478bd9Sstevel@tonic-gate return (CLI_FAIL);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate cliptr->varlen = vmax;
2987c478bd9Sstevel@tonic-gate } else {
2997c478bd9Sstevel@tonic-gate if (len > vmax) {
3007c478bd9Sstevel@tonic-gate return (CLI_FAIL);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate bcopy(valstr, cliptr->varptr, len);
3037c478bd9Sstevel@tonic-gate cliptr->varlen = len;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate return (CLI_SET);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /*
3117c478bd9Sstevel@tonic-gate * Assign a key to cliptr, or output cliptr's value as a key.
3127c478bd9Sstevel@tonic-gate * On assignment the value is specified in valstr in hexascii;
3137c478bd9Sstevel@tonic-gate * on output its value is printed in hexascii, provided the key
3147c478bd9Sstevel@tonic-gate * was entered at the interpreter (not obtained from OBP and
3157c478bd9Sstevel@tonic-gate * thus hidden).
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate static int
clkey(cli_ent_t * cliptr,char * valstr,boolean_t out)3187c478bd9Sstevel@tonic-gate clkey(cli_ent_t *cliptr, char *valstr, boolean_t out)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate uint_t len, vmax;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (out) {
3237c478bd9Sstevel@tonic-gate char buffer[2 * WANBOOT_MAXKEYLEN + 1];
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate if (!CLF_ISHIDDEN(cliptr)) {
3267c478bd9Sstevel@tonic-gate len = cliptr->varlen * 2 + 1;
3277c478bd9Sstevel@tonic-gate (void) octet_to_hexascii(cliptr->varptr,
3287c478bd9Sstevel@tonic-gate cliptr->varlen, buffer, &len);
3297c478bd9Sstevel@tonic-gate printf("%s", buffer);
3307c478bd9Sstevel@tonic-gate } else {
3317c478bd9Sstevel@tonic-gate printf("*HIDDEN*");
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate return (CLI_CONT);
3347c478bd9Sstevel@tonic-gate } else {
3357c478bd9Sstevel@tonic-gate len = strlen(valstr);
3367c478bd9Sstevel@tonic-gate vmax = cliptr->varmax;
3377c478bd9Sstevel@tonic-gate if (len != vmax * 2 || hexascii_to_octet(valstr, len,
3387c478bd9Sstevel@tonic-gate cliptr->varptr, &vmax) != 0) {
3397c478bd9Sstevel@tonic-gate return (CLI_FAIL);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate cliptr->varlen = vmax;
3427c478bd9Sstevel@tonic-gate CLF_CLRHIDDEN(cliptr);
3437c478bd9Sstevel@tonic-gate return (CLI_SET);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate * Assign an IP address to cliptr, or output cliptr's value as an
3497c478bd9Sstevel@tonic-gate * IP address. On assignment the value is specified in valstr in
3507c478bd9Sstevel@tonic-gate * dotted-decimal format; on output its value is printed in dotted-
3517c478bd9Sstevel@tonic-gate * decimal format.
3527c478bd9Sstevel@tonic-gate */
3537c478bd9Sstevel@tonic-gate static int
clip(cli_ent_t * cliptr,char * valstr,boolean_t out)3547c478bd9Sstevel@tonic-gate clip(cli_ent_t *cliptr, char *valstr, boolean_t out)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate uint_t len;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate if (out) {
3597c478bd9Sstevel@tonic-gate printf("%s", (char *)cliptr->varptr);
3607c478bd9Sstevel@tonic-gate return (CLI_CONT);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate if (inet_addr(valstr) == (in_addr_t)-1 ||
3647c478bd9Sstevel@tonic-gate (len = strlen(valstr)) >= cliptr->varmax) {
3657c478bd9Sstevel@tonic-gate return (CLI_FAIL);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate (void) strcpy(cliptr->varptr, valstr);
3697c478bd9Sstevel@tonic-gate cliptr->varlen = len + 1;
3707c478bd9Sstevel@tonic-gate return (CLI_SET);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate * Assign an arbitrary string to cliptr, or output cliptr's value as a string.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate static int
clstr(cli_ent_t * cliptr,char * valstr,boolean_t out)3777c478bd9Sstevel@tonic-gate clstr(cli_ent_t *cliptr, char *valstr, boolean_t out)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate uint_t len;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate if (out) {
3827c478bd9Sstevel@tonic-gate printf("%s", (char *)cliptr->varptr);
3837c478bd9Sstevel@tonic-gate return (CLI_CONT);
3847c478bd9Sstevel@tonic-gate } else {
3857c478bd9Sstevel@tonic-gate if ((len = strlen(valstr)) >= cliptr->varmax) {
3867c478bd9Sstevel@tonic-gate return (CLI_FAIL);
3877c478bd9Sstevel@tonic-gate } else {
3887c478bd9Sstevel@tonic-gate (void) strcpy(cliptr->varptr, valstr);
3897c478bd9Sstevel@tonic-gate cliptr->varlen = len + 1;
3907c478bd9Sstevel@tonic-gate return (CLI_SET);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate * Assign a URL to cliptr (having verified the format), or output cliptr's
3977c478bd9Sstevel@tonic-gate * value as a URL. The host must be specified in dotted-decimal, and the
3987c478bd9Sstevel@tonic-gate * scheme must not be https.
3997c478bd9Sstevel@tonic-gate */
4007c478bd9Sstevel@tonic-gate static int
clurl(cli_ent_t * cliptr,char * valstr,boolean_t out)4017c478bd9Sstevel@tonic-gate clurl(cli_ent_t *cliptr, char *valstr, boolean_t out)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate url_t u;
4047c478bd9Sstevel@tonic-gate uint_t len;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if (out) {
4077c478bd9Sstevel@tonic-gate printf("%s", (char *)cliptr->varptr);
4087c478bd9Sstevel@tonic-gate return (CLI_CONT);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (url_parse(valstr, &u) != URL_PARSE_SUCCESS ||
4127c478bd9Sstevel@tonic-gate u.https || inet_addr(u.hport.hostname) == (in_addr_t)-1 ||
4137c478bd9Sstevel@tonic-gate (len = strlen(valstr)) >= cliptr->varmax) {
4147c478bd9Sstevel@tonic-gate return (CLI_FAIL);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate (void) strcpy(cliptr->varptr, valstr);
4187c478bd9Sstevel@tonic-gate cliptr->varlen = len + 1;
4197c478bd9Sstevel@tonic-gate return (CLI_SET);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate * Assign a hostport to cliptr (having verified the format), or output cliptr's
4247c478bd9Sstevel@tonic-gate * value as a hostport. The host must be specified in dotted-decimal.
4257c478bd9Sstevel@tonic-gate */
4267c478bd9Sstevel@tonic-gate static int
clhp(cli_ent_t * cliptr,char * valstr,boolean_t out)4277c478bd9Sstevel@tonic-gate clhp(cli_ent_t *cliptr, char *valstr, boolean_t out)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate url_hport_t u;
4307c478bd9Sstevel@tonic-gate uint_t len;
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate if (out) {
4337c478bd9Sstevel@tonic-gate printf("%s", (char *)cliptr->varptr);
4347c478bd9Sstevel@tonic-gate return (CLI_CONT);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate if (url_parse_hostport(valstr, &u, URL_DFLT_PROXY_PORT) !=
4387c478bd9Sstevel@tonic-gate URL_PARSE_SUCCESS ||
4397c478bd9Sstevel@tonic-gate inet_addr(u.hostname) == (in_addr_t)-1 ||
4407c478bd9Sstevel@tonic-gate (len = strlen(valstr)) >= cliptr->varmax) {
4417c478bd9Sstevel@tonic-gate return (CLI_FAIL);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate (void) strcpy(cliptr->varptr, valstr);
4457c478bd9Sstevel@tonic-gate cliptr->varlen = len + 1;
4467c478bd9Sstevel@tonic-gate return (CLI_SET);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate * Exit the interpreter and return to the booter.
4517c478bd9Sstevel@tonic-gate */
4527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4537c478bd9Sstevel@tonic-gate static int
clgo(cli_ent_t * cliptr,char * valstr,boolean_t out)4547c478bd9Sstevel@tonic-gate clgo(cli_ent_t *cliptr, char *valstr, boolean_t out)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate return (CLI_EXIT);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate * Exit the interpreter and return to OBP.
4617c478bd9Sstevel@tonic-gate */
4627c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4637c478bd9Sstevel@tonic-gate static int
clexit(cli_ent_t * cliptr,char * valstr,boolean_t out)4647c478bd9Sstevel@tonic-gate clexit(cli_ent_t *cliptr, char *valstr, boolean_t out)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate prom_exit_to_mon();
4677c478bd9Sstevel@tonic-gate /*NOTREACHED*/
4687c478bd9Sstevel@tonic-gate return (CLI_EXIT);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate * Provide simple help information.
4737c478bd9Sstevel@tonic-gate */
4747c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4757c478bd9Sstevel@tonic-gate static int
clhelp(cli_ent_t * cliptr,char * valstr,boolean_t out)4767c478bd9Sstevel@tonic-gate clhelp(cli_ent_t *cliptr, char *valstr, boolean_t out)
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate printf("var=val - set variable\n");
4797c478bd9Sstevel@tonic-gate printf("var= - unset variable\n");
4807c478bd9Sstevel@tonic-gate printf("var - print variable\n");
4817c478bd9Sstevel@tonic-gate printf("list - list variables and their values\n");
4827c478bd9Sstevel@tonic-gate printf("prompt - prompt for unset variables\n");
4837c478bd9Sstevel@tonic-gate printf("go - continue booting\n");
4847c478bd9Sstevel@tonic-gate printf("exit - quit boot interpreter and return to OBP\n");
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate return (CLI_CONT);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate * List variables and their current values.
4917c478bd9Sstevel@tonic-gate */
4927c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4937c478bd9Sstevel@tonic-gate static int
cllist(cli_ent_t * cliptr,char * valstr,boolean_t out)4947c478bd9Sstevel@tonic-gate cllist(cli_ent_t *cliptr, char *valstr, boolean_t out)
4957c478bd9Sstevel@tonic-gate {
49653391bafSeota int wanted = (int)(uintptr_t)valstr; /* use uintptr_t for gcc */
4977c478bd9Sstevel@tonic-gate int i;
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate wanted &= ~(CLF_CMD | CLF_ARG);
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; cliptr++) {
5027c478bd9Sstevel@tonic-gate if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0 ||
5037c478bd9Sstevel@tonic-gate (cliptr->flags & wanted) == 0) {
5047c478bd9Sstevel@tonic-gate continue;
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate printf("%s: ", cliptr->varname);
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * Line the values up - space to the width of the widest
5097c478bd9Sstevel@tonic-gate * varname + 1 for the ':'.
5107c478bd9Sstevel@tonic-gate */
5117c478bd9Sstevel@tonic-gate for (i = VAR_MAXWIDTH + 1 - strlen(cliptr->varname);
5127c478bd9Sstevel@tonic-gate i > 0; --i) {
5137c478bd9Sstevel@tonic-gate printf(" ");
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate if (CLF_ISSET(cliptr) || CLF_ISHIDDEN(cliptr)) {
5177c478bd9Sstevel@tonic-gate (void) cliptr->action(cliptr, NULL, B_TRUE);
5187c478bd9Sstevel@tonic-gate printf("\n");
5197c478bd9Sstevel@tonic-gate } else {
5207c478bd9Sstevel@tonic-gate printf("UNSET\n");
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate return (CLI_CONT);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate /*
5287c478bd9Sstevel@tonic-gate * Prompt for wanted values.
5297c478bd9Sstevel@tonic-gate */
5307c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5317c478bd9Sstevel@tonic-gate static int
clprompt(cli_ent_t * cliptr,char * valstr,boolean_t out)5327c478bd9Sstevel@tonic-gate clprompt(cli_ent_t *cliptr, char *valstr, boolean_t out)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate char *p;
53553391bafSeota int wanted = (int)(uintptr_t)valstr; /* use uintrptr_t for gcc */
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate /*
5387c478bd9Sstevel@tonic-gate * If processing boot arguments, simply note the fact that clprompt()
5397c478bd9Sstevel@tonic-gate * should be invoked later when other parameters may be supplied.
5407c478bd9Sstevel@tonic-gate */
5417c478bd9Sstevel@tonic-gate if ((wanted & CLF_ARG) != 0) {
5427c478bd9Sstevel@tonic-gate args_specified_prompt = B_TRUE;
5437c478bd9Sstevel@tonic-gate return (CLI_CONT);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate wanted &= ~(CLF_CMD | CLF_ARG);
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
5487c478bd9Sstevel@tonic-gate if ((cliptr->flags & wanted) == 0) {
5497c478bd9Sstevel@tonic-gate continue;
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate printf("%s", cliptr->varname);
5537c478bd9Sstevel@tonic-gate if (CLF_ISSET(cliptr)) {
5547c478bd9Sstevel@tonic-gate printf(" [");
5557c478bd9Sstevel@tonic-gate (void) cliptr->action(cliptr, NULL, B_TRUE);
5567c478bd9Sstevel@tonic-gate printf("]");
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate printf("? ");
5597c478bd9Sstevel@tonic-gate (void) editline(cmdbuf, sizeof (cmdbuf));
5607c478bd9Sstevel@tonic-gate printf("\n");
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate p = cmdbuf;
5637c478bd9Sstevel@tonic-gate skipspace(p);
5647c478bd9Sstevel@tonic-gate if (*p == '\0') { /* nothing there */
5657c478bd9Sstevel@tonic-gate continue;
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate /* Get valstr and nul terminate */
5697c478bd9Sstevel@tonic-gate valstr = p;
5707c478bd9Sstevel@tonic-gate ++p;
5717c478bd9Sstevel@tonic-gate skiptext(p);
5727c478bd9Sstevel@tonic-gate *p = '\0';
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate /* If empty value, do nothing */
5757c478bd9Sstevel@tonic-gate if (strlen(valstr) == 0) {
5767c478bd9Sstevel@tonic-gate continue;
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate switch (cliptr->action(cliptr, valstr, B_FALSE)) {
5807c478bd9Sstevel@tonic-gate case CLI_SET:
5817c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
5827c478bd9Sstevel@tonic-gate break;
5837c478bd9Sstevel@tonic-gate case CLI_FAIL:
5847c478bd9Sstevel@tonic-gate printf("Incorrect format, parameter unchanged!\n");
5857c478bd9Sstevel@tonic-gate break;
5867c478bd9Sstevel@tonic-gate case CLI_EXIT:
5877c478bd9Sstevel@tonic-gate return (CLI_EXIT);
5887c478bd9Sstevel@tonic-gate case CLI_CONT:
5897c478bd9Sstevel@tonic-gate break;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate return (CLI_CONT);
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /*
5977c478bd9Sstevel@tonic-gate * If the PROM has done DHCP, bind the interface; otherwise do the full
5987c478bd9Sstevel@tonic-gate * DHCP packet exchange.
5997c478bd9Sstevel@tonic-gate */
6007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6017c478bd9Sstevel@tonic-gate static int
cldhcp(cli_ent_t * cliptr,char * valstr,boolean_t out)6027c478bd9Sstevel@tonic-gate cldhcp(cli_ent_t *cliptr, char *valstr, boolean_t out)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate static boolean_t first_time = B_TRUE;
6057c478bd9Sstevel@tonic-gate static int ret = CLI_CONT;
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate if (first_time) {
6087c478bd9Sstevel@tonic-gate /*
6097c478bd9Sstevel@tonic-gate * Set DHCP's idea of the client_id from our cached value.
6107c478bd9Sstevel@tonic-gate */
6117c478bd9Sstevel@tonic-gate cliptr = find_cli_ent(BI_CLIENT_ID);
6127c478bd9Sstevel@tonic-gate if (CLF_ISMOD(cliptr)) {
6137c478bd9Sstevel@tonic-gate dhcp_set_client_id(cliptr->varptr, cliptr->varlen);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_INFO, "Starting DHCP configuration");
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate (void) ipv4_setpromiscuous(B_TRUE);
6197c478bd9Sstevel@tonic-gate if (dhcp() == 0) {
6207c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_INFO,
6217c478bd9Sstevel@tonic-gate "DHCP configuration succeeded");
6227c478bd9Sstevel@tonic-gate } else {
6237c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_CRIT,
6247c478bd9Sstevel@tonic-gate "DHCP configuration failed");
6257c478bd9Sstevel@tonic-gate ret = CLI_FAIL;
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate (void) ipv4_setpromiscuous(B_FALSE);
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate first_time = B_FALSE;
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate return (ret);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate /*
6367c478bd9Sstevel@tonic-gate * Invoke the socket test interpreter (for testing purposes only).
6377c478bd9Sstevel@tonic-gate */
6387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6397c478bd9Sstevel@tonic-gate static int
cltest(cli_ent_t * cliptr,char * valstr,boolean_t out)6407c478bd9Sstevel@tonic-gate cltest(cli_ent_t *cliptr, char *valstr, boolean_t out)
6417c478bd9Sstevel@tonic-gate {
6427c478bd9Sstevel@tonic-gate (void) ipv4_setpromiscuous(B_FALSE);
6437c478bd9Sstevel@tonic-gate printf("\n");
6447c478bd9Sstevel@tonic-gate for (;;) {
6457c478bd9Sstevel@tonic-gate printf(TEST_PROMPT);
6467c478bd9Sstevel@tonic-gate if (editline(cmdbuf, sizeof (cmdbuf)) > 0) {
6477c478bd9Sstevel@tonic-gate printf("\n");
6487c478bd9Sstevel@tonic-gate (void) st_interpret(cmdbuf);
6497c478bd9Sstevel@tonic-gate } else {
6507c478bd9Sstevel@tonic-gate prom_exit_to_mon();
6517c478bd9Sstevel@tonic-gate /* NOTREACHED */
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /* NOTREACHED */
6567c478bd9Sstevel@tonic-gate return (CLI_CONT);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate * Return the cliptr corresponding to the named variable.
6617c478bd9Sstevel@tonic-gate */
6627c478bd9Sstevel@tonic-gate static cli_ent_t *
find_cli_ent(char * varstr)6637c478bd9Sstevel@tonic-gate find_cli_ent(char *varstr)
6647c478bd9Sstevel@tonic-gate {
6657c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
6687c478bd9Sstevel@tonic-gate if (strcmp(varstr, cliptr->varname) == 0) {
6697c478bd9Sstevel@tonic-gate return (cliptr);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate return (NULL);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate * Evaluate the commands provided by the user (either as "-o" boot arguments
6787c478bd9Sstevel@tonic-gate * or interactively at the boot interpreter).
6797c478bd9Sstevel@tonic-gate */
6807c478bd9Sstevel@tonic-gate static int
cli_eval_buf(char * inbuf,int wanted)6817c478bd9Sstevel@tonic-gate cli_eval_buf(char *inbuf, int wanted)
6827c478bd9Sstevel@tonic-gate {
6837c478bd9Sstevel@tonic-gate char *p, *varstr, *end_varstr, *valstr, *end_valstr;
6847c478bd9Sstevel@tonic-gate boolean_t assign;
6857c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate for (p = inbuf; *p != '\0'; ) {
6887c478bd9Sstevel@tonic-gate skipspace(p);
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate /* If nothing more on line, go get the next one */
6917c478bd9Sstevel@tonic-gate if (*p == '\0') {
6927c478bd9Sstevel@tonic-gate break;
6937c478bd9Sstevel@tonic-gate } else if (*p == ',') { /* orphan ',' ? */
6947c478bd9Sstevel@tonic-gate ++p;
6957c478bd9Sstevel@tonic-gate continue;
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate /* Get ptrs to start & end of variable */
6997c478bd9Sstevel@tonic-gate varstr = p;
7007c478bd9Sstevel@tonic-gate ++p;
7017c478bd9Sstevel@tonic-gate skiptext(p);
7027c478bd9Sstevel@tonic-gate end_varstr = p;
7037c478bd9Sstevel@tonic-gate skipspace(p);
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate /* See if we're doing an assignment */
7067c478bd9Sstevel@tonic-gate valstr = NULL;
7077c478bd9Sstevel@tonic-gate if (*p != '=') { /* nope, just printing */
7087c478bd9Sstevel@tonic-gate assign = B_FALSE;
7097c478bd9Sstevel@tonic-gate } else {
7107c478bd9Sstevel@tonic-gate assign = B_TRUE;
7117c478bd9Sstevel@tonic-gate ++p; /* past '=' */
7127c478bd9Sstevel@tonic-gate skipspace(p);
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate /* Assigning something? (else clear variable) */
7157c478bd9Sstevel@tonic-gate if (*p != '\0' && *p != ',') {
7167c478bd9Sstevel@tonic-gate /* Get ptrs to start & end of valstr */
7177c478bd9Sstevel@tonic-gate valstr = p;
7187c478bd9Sstevel@tonic-gate ++p;
7197c478bd9Sstevel@tonic-gate skiptext(p);
7207c478bd9Sstevel@tonic-gate end_valstr = p;
7217c478bd9Sstevel@tonic-gate skipspace(p);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate /* Skip ',' delimiter if present */
7267c478bd9Sstevel@tonic-gate if (*p == ',') {
7277c478bd9Sstevel@tonic-gate ++p;
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate /* Nul-terminate varstr and valstr (if appropriate) */
7317c478bd9Sstevel@tonic-gate *end_varstr = '\0';
7327c478bd9Sstevel@tonic-gate if (valstr != NULL) {
7337c478bd9Sstevel@tonic-gate *end_valstr = '\0';
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate if ((cliptr = find_cli_ent(varstr)) == NULL) {
7377c478bd9Sstevel@tonic-gate printf("Unknown variable '%s'; ignored\n", varstr);
7387c478bd9Sstevel@tonic-gate continue;
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate * It's an error to specify a parameter which can only be a
7437c478bd9Sstevel@tonic-gate * boot argument (and not a command) when not processing the
7447c478bd9Sstevel@tonic-gate * boot arguments.
7457c478bd9Sstevel@tonic-gate */
7467c478bd9Sstevel@tonic-gate if ((cliptr->flags & (CLF_CMD | CLF_ARG)) == CLF_ARG &&
7477c478bd9Sstevel@tonic-gate (wanted & CLF_ARG) == 0) {
7487c478bd9Sstevel@tonic-gate printf("'%s' may only be specified as a "
7497c478bd9Sstevel@tonic-gate "boot argument; ignored\n", varstr);
7507c478bd9Sstevel@tonic-gate continue;
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate
7537c478bd9Sstevel@tonic-gate /*
7547c478bd9Sstevel@tonic-gate * When doing an assignment, verify that it's not a command
7557c478bd9Sstevel@tonic-gate * or argument name, and that it is permissible in the current
7567c478bd9Sstevel@tonic-gate * context. An 'empty' assignment (var=) is treated the same
7577c478bd9Sstevel@tonic-gate * as a null assignment (var="").
7587c478bd9Sstevel@tonic-gate *
7597c478bd9Sstevel@tonic-gate * If processing the boot arguments, it is an error to not
7607c478bd9Sstevel@tonic-gate * assign a value to a non-argument parameter.
7617c478bd9Sstevel@tonic-gate */
7627c478bd9Sstevel@tonic-gate if (assign) {
7637c478bd9Sstevel@tonic-gate if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0) {
7647c478bd9Sstevel@tonic-gate printf("'%s' is a command and cannot "
7657c478bd9Sstevel@tonic-gate "be assigned\n", varstr);
7667c478bd9Sstevel@tonic-gate return (CLI_FAIL);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate if ((cliptr->flags & wanted) == 0) {
7697c478bd9Sstevel@tonic-gate printf("'%s' cannot be assigned\n", varstr);
7707c478bd9Sstevel@tonic-gate return (CLI_FAIL);
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate if (valstr == NULL) {
7747c478bd9Sstevel@tonic-gate cliptr->varlen = 0;
7757c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
7767c478bd9Sstevel@tonic-gate continue;
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate } else if ((wanted & CLF_ARG) != 0 &&
7797c478bd9Sstevel@tonic-gate (cliptr->flags & (CLF_CMD | CLF_ARG)) == 0) {
7807c478bd9Sstevel@tonic-gate printf("'%s' must be assigned when specified in "
7817c478bd9Sstevel@tonic-gate " the boot arguments\n", varstr);
7827c478bd9Sstevel@tonic-gate return (CLI_FAIL);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * Pass 'wanted' to command-handling functions, in particular
7877c478bd9Sstevel@tonic-gate * clprompt() and cllist().
7887c478bd9Sstevel@tonic-gate */
7897c478bd9Sstevel@tonic-gate if ((cliptr->flags & CLF_CMD) != 0) {
79053391bafSeota /* use uintptr_t to suppress the gcc warning */
79153391bafSeota valstr = (char *)(uintptr_t)wanted;
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate /*
7957c478bd9Sstevel@tonic-gate * Call the parameter's action function.
7967c478bd9Sstevel@tonic-gate */
7977c478bd9Sstevel@tonic-gate switch (cliptr->action(cliptr, valstr, !assign)) {
7987c478bd9Sstevel@tonic-gate case CLI_SET:
7997c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
8007c478bd9Sstevel@tonic-gate break;
8017c478bd9Sstevel@tonic-gate case CLI_FAIL:
8027c478bd9Sstevel@tonic-gate printf("Incorrect format: variable '%s' not set\n",
8037c478bd9Sstevel@tonic-gate cliptr->varname);
8047c478bd9Sstevel@tonic-gate break;
8057c478bd9Sstevel@tonic-gate case CLI_EXIT:
8067c478bd9Sstevel@tonic-gate return (CLI_EXIT);
8077c478bd9Sstevel@tonic-gate case CLI_CONT:
8087c478bd9Sstevel@tonic-gate if (!assign) {
8097c478bd9Sstevel@tonic-gate printf("\n");
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate break;
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate return (CLI_CONT);
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate static void
cli_interpret(int wanted)8197c478bd9Sstevel@tonic-gate cli_interpret(int wanted)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate printf("\n");
8227c478bd9Sstevel@tonic-gate do {
8237c478bd9Sstevel@tonic-gate printf(PROMPT);
8247c478bd9Sstevel@tonic-gate (void) editline(cmdbuf, sizeof (cmdbuf));
8257c478bd9Sstevel@tonic-gate printf("\n");
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate } while (cli_eval_buf(cmdbuf, wanted) != CLI_EXIT);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * This routine queries the PROM to see what encryption keys exist.
8337c478bd9Sstevel@tonic-gate */
8347c478bd9Sstevel@tonic-gate static void
get_prom_encr_keys()8357c478bd9Sstevel@tonic-gate get_prom_encr_keys()
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
8387c478bd9Sstevel@tonic-gate char encr_key[WANBOOT_MAXKEYLEN];
8397c478bd9Sstevel@tonic-gate int keylen;
8407c478bd9Sstevel@tonic-gate int status;
8417c478bd9Sstevel@tonic-gate int ret;
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate * At the top of the priority list, we have AES.
8457c478bd9Sstevel@tonic-gate */
8467c478bd9Sstevel@tonic-gate ret = prom_get_security_key(WANBOOT_AES_128_KEY_NAME, encr_key,
8477c478bd9Sstevel@tonic-gate WANBOOT_MAXKEYLEN, &keylen, &status);
8487c478bd9Sstevel@tonic-gate if ((ret == 0) && (status == 0) && (keylen == AES_128_KEY_SIZE)) {
8497c478bd9Sstevel@tonic-gate cliptr = find_cli_ent(BI_AES_KEY);
8507c478bd9Sstevel@tonic-gate bcopy(encr_key, cliptr->varptr, AES_128_KEY_SIZE);
8517c478bd9Sstevel@tonic-gate cliptr->varlen = AES_128_KEY_SIZE;
8527c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate
8557c478bd9Sstevel@tonic-gate /*
8567c478bd9Sstevel@tonic-gate * Next, 3DES.
8577c478bd9Sstevel@tonic-gate */
8587c478bd9Sstevel@tonic-gate ret = prom_get_security_key(WANBOOT_DES3_KEY_NAME, encr_key,
8597c478bd9Sstevel@tonic-gate WANBOOT_MAXKEYLEN, &keylen, &status);
8607c478bd9Sstevel@tonic-gate if ((ret == 0) && (status == 0) && (keylen == DES3_KEY_SIZE)) {
8617c478bd9Sstevel@tonic-gate cliptr = find_cli_ent(BI_3DES_KEY);
8627c478bd9Sstevel@tonic-gate bcopy(encr_key, cliptr->varptr, DES3_KEY_SIZE);
8637c478bd9Sstevel@tonic-gate cliptr->varlen = DES3_KEY_SIZE;
8647c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate /*
8697c478bd9Sstevel@tonic-gate * This routine queries the PROM to see what hashing keys exist.
8707c478bd9Sstevel@tonic-gate */
8717c478bd9Sstevel@tonic-gate static void
get_prom_hash_keys()8727c478bd9Sstevel@tonic-gate get_prom_hash_keys()
8737c478bd9Sstevel@tonic-gate {
8747c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
8757c478bd9Sstevel@tonic-gate char hash_key[WANBOOT_HMAC_KEY_SIZE];
8767c478bd9Sstevel@tonic-gate int keylen;
8777c478bd9Sstevel@tonic-gate int status;
8787c478bd9Sstevel@tonic-gate int ret;
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate /*
8817c478bd9Sstevel@tonic-gate * The only supported key thus far is SHA1.
8827c478bd9Sstevel@tonic-gate */
8837c478bd9Sstevel@tonic-gate ret = prom_get_security_key(WANBOOT_HMAC_SHA1_KEY_NAME, hash_key,
8847c478bd9Sstevel@tonic-gate WANBOOT_HMAC_KEY_SIZE, &keylen, &status);
8857c478bd9Sstevel@tonic-gate if ((ret == 0) && (status == 0) && (keylen == WANBOOT_HMAC_KEY_SIZE)) {
8867c478bd9Sstevel@tonic-gate cliptr = find_cli_ent(BI_SHA1_KEY);
8877c478bd9Sstevel@tonic-gate bcopy(hash_key, cliptr->varptr, WANBOOT_HMAC_KEY_SIZE);
8887c478bd9Sstevel@tonic-gate cliptr->varlen = WANBOOT_HMAC_KEY_SIZE;
8897c478bd9Sstevel@tonic-gate CLF_MODVAL(cliptr);
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate #endif /* defined(__sparcv9) */
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate /*
8957c478bd9Sstevel@tonic-gate * For the given parameter type(s), get values from bootinfo and cache in
8967c478bd9Sstevel@tonic-gate * the local variables used by the "boot>" interpreter.
8977c478bd9Sstevel@tonic-gate */
8987c478bd9Sstevel@tonic-gate static void
bootinfo_defaults(int which)8997c478bd9Sstevel@tonic-gate bootinfo_defaults(int which)
9007c478bd9Sstevel@tonic-gate {
9017c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
9047c478bd9Sstevel@tonic-gate if ((cliptr->flags & which) != 0 && !CLF_ISSET(cliptr)) {
9057c478bd9Sstevel@tonic-gate size_t len = cliptr->varmax;
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate if (bootinfo_get(cliptr->varname, cliptr->varptr,
9087c478bd9Sstevel@tonic-gate &len, NULL) == BI_E_SUCCESS) {
9097c478bd9Sstevel@tonic-gate cliptr->varlen = len;
9107c478bd9Sstevel@tonic-gate CLF_SETVAL(cliptr);
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate * For the given parameter type(s), store values entered at the "boot>"
9187c478bd9Sstevel@tonic-gate * interpreter back into bootinfo.
9197c478bd9Sstevel@tonic-gate */
9207c478bd9Sstevel@tonic-gate static void
update_bootinfo(int which)9217c478bd9Sstevel@tonic-gate update_bootinfo(int which)
9227c478bd9Sstevel@tonic-gate {
9237c478bd9Sstevel@tonic-gate cli_ent_t *cliptr;
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
9267c478bd9Sstevel@tonic-gate if ((cliptr->flags & which) != 0 && CLF_ISMOD(cliptr)) {
9277c478bd9Sstevel@tonic-gate (void) bootinfo_put(cliptr->varname,
9287c478bd9Sstevel@tonic-gate cliptr->varptr, cliptr->varlen, 0);
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate * Return the net-config-strategy: "dhcp", "manual" or "rarp"
9357c478bd9Sstevel@tonic-gate */
9367c478bd9Sstevel@tonic-gate static char *
net_config_strategy(void)9377c478bd9Sstevel@tonic-gate net_config_strategy(void)
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate static char ncs[8]; /* "dhcp" or "manual" */
9407c478bd9Sstevel@tonic-gate size_t len = sizeof (ncs);
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate if (ncs[0] == '\0' &&
9437c478bd9Sstevel@tonic-gate bootinfo_get(BI_NET_CONFIG_STRATEGY, ncs, &len, NULL) !=
9447c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
9457c478bd9Sstevel@tonic-gate /*
9467c478bd9Sstevel@tonic-gate * Support for old PROMs: create the net-config-strategy
9477c478bd9Sstevel@tonic-gate * property under /chosen with an appropriate value. If we
9487c478bd9Sstevel@tonic-gate * have a bootp-response (not interested in its value, just
9497c478bd9Sstevel@tonic-gate * its presence) then we did DHCP; otherwise configuration
9507c478bd9Sstevel@tonic-gate * is manual.
9517c478bd9Sstevel@tonic-gate */
9527c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL,
9537c478bd9Sstevel@tonic-gate NULL) == BI_E_BUF2SMALL) {
9547c478bd9Sstevel@tonic-gate (void) strcpy(ncs, "dhcp");
9557c478bd9Sstevel@tonic-gate } else {
9567c478bd9Sstevel@tonic-gate (void) strcpy(ncs, "manual");
9577c478bd9Sstevel@tonic-gate }
9587c478bd9Sstevel@tonic-gate (void) bootinfo_put(BI_NET_CONFIG_STRATEGY, ncs, strlen(ncs),
9597c478bd9Sstevel@tonic-gate BI_R_CHOSEN);
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_INFO,
9627c478bd9Sstevel@tonic-gate "Default net-config-strategy: %s", ncs);
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate
9657c478bd9Sstevel@tonic-gate return (ncs);
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate /*
9697c478bd9Sstevel@tonic-gate * If there is no client-id property published in /chosen (by the PROM or the
9707c478bd9Sstevel@tonic-gate * boot interpreter) provide a default client-id based on the MAC address of
9717c478bd9Sstevel@tonic-gate * the client.
9727c478bd9Sstevel@tonic-gate * As specified in RFC2132 (section 9.14), this is prefixed with a byte
9737c478bd9Sstevel@tonic-gate * which specifies the ARP hardware type defined in RFC1700 (for Ethernet,
9747c478bd9Sstevel@tonic-gate * this should be 1).
9757c478bd9Sstevel@tonic-gate */
9767c478bd9Sstevel@tonic-gate static void
generate_default_clientid(void)9777c478bd9Sstevel@tonic-gate generate_default_clientid(void)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate char clid[WB_MAX_CID_LEN];
9807c478bd9Sstevel@tonic-gate size_t len = sizeof (clid);
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_CLIENT_ID, clid, &len, NULL) != BI_E_SUCCESS) {
9837c478bd9Sstevel@tonic-gate len = mac_get_addr_len() + 1; /* include hwtype */
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate if (len > sizeof (clid)) {
9867c478bd9Sstevel@tonic-gate return;
9877c478bd9Sstevel@tonic-gate }
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate clid[0] = mac_arp_type(mac_get_type());
9907c478bd9Sstevel@tonic-gate bcopy(mac_get_addr_buf(), &clid[1], len - 1);
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate (void) bootinfo_put(BI_CLIENT_ID, clid, len, 0);
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate /*
9977c478bd9Sstevel@tonic-gate * Determine the URL of the boot server from the 'file' parameter to OBP,
9987c478bd9Sstevel@tonic-gate * the SbootURI or BootFile DHCP options, or the 'bootserver' value entered
9997c478bd9Sstevel@tonic-gate * either as a "-o" argument or at the interpreter.
10007c478bd9Sstevel@tonic-gate */
10017c478bd9Sstevel@tonic-gate static void
determine_bootserver_url(void)10027c478bd9Sstevel@tonic-gate determine_bootserver_url(void)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate char bs[URL_MAX_STRLEN + 1];
10057c478bd9Sstevel@tonic-gate size_t len;
10067c478bd9Sstevel@tonic-gate url_t url;
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_BOOTSERVER, bs, &len, NULL) != BI_E_SUCCESS) {
10097c478bd9Sstevel@tonic-gate /*
10107c478bd9Sstevel@tonic-gate * If OBP has published a network-boot-file property in
10117c478bd9Sstevel@tonic-gate * /chosen (or there is a DHCP BootFile or SbootURI vendor
10127c478bd9Sstevel@tonic-gate * option) and it's a URL, construct the bootserver URL
10137c478bd9Sstevel@tonic-gate * from it.
10147c478bd9Sstevel@tonic-gate */
10157c478bd9Sstevel@tonic-gate len = URL_MAX_STRLEN;
10167c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_NETWORK_BOOT_FILE, bs, &len, NULL) !=
10177c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
10187c478bd9Sstevel@tonic-gate len = URL_MAX_STRLEN;
10197c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_BOOTFILE, bs, &len, NULL) !=
10207c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
10217c478bd9Sstevel@tonic-gate return;
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate if (url_parse(bs, &url) == URL_PARSE_SUCCESS) {
10257c478bd9Sstevel@tonic-gate (void) bootinfo_put(BI_BOOTSERVER, bs, len, 0);
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate /*
10317c478bd9Sstevel@tonic-gate * Provide a classful subnet mask based on the client's IP address.
10327c478bd9Sstevel@tonic-gate */
10337c478bd9Sstevel@tonic-gate static in_addr_t
generate_classful_subnet(in_addr_t client_ipaddr)10347c478bd9Sstevel@tonic-gate generate_classful_subnet(in_addr_t client_ipaddr)
10357c478bd9Sstevel@tonic-gate {
10367c478bd9Sstevel@tonic-gate struct in_addr subnetmask;
10377c478bd9Sstevel@tonic-gate char *netstr;
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate if (IN_CLASSA(client_ipaddr)) {
10407c478bd9Sstevel@tonic-gate subnetmask.s_addr = IN_CLASSA_NET;
10417c478bd9Sstevel@tonic-gate } else if (IN_CLASSB(client_ipaddr)) {
10427c478bd9Sstevel@tonic-gate subnetmask.s_addr = IN_CLASSB_NET;
1043*2a9459bdSsangeeta } else if (IN_CLASSC(client_ipaddr)) {
10447c478bd9Sstevel@tonic-gate subnetmask.s_addr = IN_CLASSC_NET;
1045*2a9459bdSsangeeta } else {
1046*2a9459bdSsangeeta subnetmask.s_addr = IN_CLASSE_NET;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate netstr = inet_ntoa(subnetmask);
10507c478bd9Sstevel@tonic-gate (void) bootinfo_put(BI_SUBNET_MASK, netstr, strlen(netstr) + 1, 0);
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate return (subnetmask.s_addr);
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate /*
10567c478bd9Sstevel@tonic-gate * Informational output to the user (if interactive) or the bootlogger.
10577c478bd9Sstevel@tonic-gate */
10587c478bd9Sstevel@tonic-gate static void
info(const char * msg,boolean_t interactive)10597c478bd9Sstevel@tonic-gate info(const char *msg, boolean_t interactive)
10607c478bd9Sstevel@tonic-gate {
10617c478bd9Sstevel@tonic-gate if (interactive) {
10627c478bd9Sstevel@tonic-gate printf("%s\n", msg);
10637c478bd9Sstevel@tonic-gate } else {
10647c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_INFO, "%s", msg);
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate /*
10697c478bd9Sstevel@tonic-gate * Determine whether we have sufficient information to proceed with booting,
10707c478bd9Sstevel@tonic-gate * either for configuring the interface and downloading the bootconf file,
10717c478bd9Sstevel@tonic-gate * or for downloading the miniroot.
10727c478bd9Sstevel@tonic-gate */
10737c478bd9Sstevel@tonic-gate static int
config_incomplete(int why,boolean_t interactive)10747c478bd9Sstevel@tonic-gate config_incomplete(int why, boolean_t interactive)
10757c478bd9Sstevel@tonic-gate {
10767c478bd9Sstevel@tonic-gate boolean_t error = B_FALSE;
10777c478bd9Sstevel@tonic-gate char buf[URL_MAX_STRLEN + 1];
10787c478bd9Sstevel@tonic-gate size_t len;
10797c478bd9Sstevel@tonic-gate char *urlstr;
10807c478bd9Sstevel@tonic-gate url_t u;
10817c478bd9Sstevel@tonic-gate struct hostent *hp;
10827c478bd9Sstevel@tonic-gate in_addr_t client_ipaddr, ipaddr, bsnet, pxnet;
10837c478bd9Sstevel@tonic-gate static in_addr_t subnetmask, clnet;
10847c478bd9Sstevel@tonic-gate static boolean_t have_router = B_FALSE;
10857c478bd9Sstevel@tonic-gate static boolean_t have_proxy = B_FALSE;
10867c478bd9Sstevel@tonic-gate boolean_t have_root_server = B_FALSE;
10877c478bd9Sstevel@tonic-gate boolean_t have_boot_logger = B_FALSE;
10887c478bd9Sstevel@tonic-gate in_addr_t rsnet, blnet;
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate /*
10917c478bd9Sstevel@tonic-gate * Note that 'have_router', 'have_proxy', 'subnetmask', and 'clnet'
10927c478bd9Sstevel@tonic-gate * are static, so that their values (gathered when checking the
10937c478bd9Sstevel@tonic-gate * interface configuration) may be used again when checking the boot
10947c478bd9Sstevel@tonic-gate * configuration.
10957c478bd9Sstevel@tonic-gate */
10967c478bd9Sstevel@tonic-gate if (why == CLF_IF) {
10977c478bd9Sstevel@tonic-gate /*
10987c478bd9Sstevel@tonic-gate * A valid host IP address is an absolute requirement.
10997c478bd9Sstevel@tonic-gate */
11007c478bd9Sstevel@tonic-gate len = sizeof (buf);
11017c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_HOST_IP, buf, &len, NULL) == BI_E_SUCCESS) {
11027c478bd9Sstevel@tonic-gate if ((client_ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
11037c478bd9Sstevel@tonic-gate info("host-ip invalid!", interactive);
11047c478bd9Sstevel@tonic-gate error = B_TRUE;
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate } else {
11077c478bd9Sstevel@tonic-gate info("host-ip not set!", interactive);
11087c478bd9Sstevel@tonic-gate error = B_TRUE;
11097c478bd9Sstevel@tonic-gate }
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate * If a subnet mask was provided, use it; otherwise infer it.
11137c478bd9Sstevel@tonic-gate */
11147c478bd9Sstevel@tonic-gate len = sizeof (buf);
11157c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_SUBNET_MASK, buf, &len, NULL) ==
11167c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
11177c478bd9Sstevel@tonic-gate if ((subnetmask = inet_addr(buf)) == (in_addr_t)-1) {
11187c478bd9Sstevel@tonic-gate info("subnet-mask invalid!", interactive);
11197c478bd9Sstevel@tonic-gate error = B_TRUE;
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate } else {
11227c478bd9Sstevel@tonic-gate info("Defaulting to classful subnetting", interactive);
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate subnetmask = generate_classful_subnet(client_ipaddr);
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate clnet = client_ipaddr & subnetmask;
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate /*
11297c478bd9Sstevel@tonic-gate * A legal bootserver URL is also an absolute requirement.
11307c478bd9Sstevel@tonic-gate */
11317c478bd9Sstevel@tonic-gate len = sizeof (buf);
11327c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_BOOTSERVER, buf, &len, NULL) ==
11337c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
11347c478bd9Sstevel@tonic-gate if (url_parse(buf, &u) != URL_PARSE_SUCCESS ||
11357c478bd9Sstevel@tonic-gate u.https ||
11367c478bd9Sstevel@tonic-gate (ipaddr = inet_addr(u.hport.hostname)) ==
11377c478bd9Sstevel@tonic-gate (in_addr_t)-1) {
11387c478bd9Sstevel@tonic-gate info("bootserver not legal URL!", interactive);
11397c478bd9Sstevel@tonic-gate error = B_TRUE;
11407c478bd9Sstevel@tonic-gate } else {
11417c478bd9Sstevel@tonic-gate bsnet = ipaddr & subnetmask;
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate } else {
11447c478bd9Sstevel@tonic-gate info("bootserver not specified!", interactive);
11457c478bd9Sstevel@tonic-gate error = B_TRUE;
11467c478bd9Sstevel@tonic-gate }
11477c478bd9Sstevel@tonic-gate
11487c478bd9Sstevel@tonic-gate /*
11497c478bd9Sstevel@tonic-gate * Is there a correctly-defined router?
11507c478bd9Sstevel@tonic-gate */
11517c478bd9Sstevel@tonic-gate len = sizeof (buf);
11527c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_ROUTER_IP, buf, &len, NULL) ==
11537c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
11547c478bd9Sstevel@tonic-gate if ((ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
11557c478bd9Sstevel@tonic-gate info("router-ip invalid!", interactive);
11567c478bd9Sstevel@tonic-gate error = B_TRUE;
11577c478bd9Sstevel@tonic-gate } else if (clnet != (ipaddr & subnetmask)) {
11587c478bd9Sstevel@tonic-gate info("router not on local subnet!",
11597c478bd9Sstevel@tonic-gate interactive);
11607c478bd9Sstevel@tonic-gate error = B_TRUE;
11617c478bd9Sstevel@tonic-gate } else {
11627c478bd9Sstevel@tonic-gate have_router = B_TRUE;
11637c478bd9Sstevel@tonic-gate }
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate /*
11677c478bd9Sstevel@tonic-gate * Is there a correctly-defined proxy?
11687c478bd9Sstevel@tonic-gate */
11697c478bd9Sstevel@tonic-gate len = sizeof (buf);
11707c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_HTTP_PROXY, buf, &len, NULL) ==
11717c478bd9Sstevel@tonic-gate BI_E_SUCCESS) {
11727c478bd9Sstevel@tonic-gate url_hport_t u;
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate if (url_parse_hostport(buf, &u, URL_DFLT_PROXY_PORT) !=
11757c478bd9Sstevel@tonic-gate URL_PARSE_SUCCESS ||
11767c478bd9Sstevel@tonic-gate (ipaddr = inet_addr(u.hostname)) == (in_addr_t)-1) {
11777c478bd9Sstevel@tonic-gate info("http-proxy port invalid!", interactive);
11787c478bd9Sstevel@tonic-gate error = B_TRUE;
11797c478bd9Sstevel@tonic-gate } else {
11807c478bd9Sstevel@tonic-gate /*
11817c478bd9Sstevel@tonic-gate * The proxy is only of use to us if it's on
11827c478bd9Sstevel@tonic-gate * our local subnet, or if a router has been
11837c478bd9Sstevel@tonic-gate * specified (which should hopefully allow us
11847c478bd9Sstevel@tonic-gate * to access the proxy).
11857c478bd9Sstevel@tonic-gate */
11867c478bd9Sstevel@tonic-gate pxnet = ipaddr & subnetmask;
11877c478bd9Sstevel@tonic-gate have_proxy = (have_router || pxnet == clnet);
11887c478bd9Sstevel@tonic-gate }
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate /*
11927c478bd9Sstevel@tonic-gate * If there is no router and no proxy (either on the local
11937c478bd9Sstevel@tonic-gate * subnet or reachable via a router), then the bootserver
11947c478bd9Sstevel@tonic-gate * URL must be on the local net.
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate if (!error && !have_router && !have_proxy && bsnet != clnet) {
11977c478bd9Sstevel@tonic-gate info("bootserver URL not on local subnet",
11987c478bd9Sstevel@tonic-gate interactive);
11997c478bd9Sstevel@tonic-gate error = B_TRUE;
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate } else {
12027c478bd9Sstevel@tonic-gate /*
12037c478bd9Sstevel@tonic-gate * There must be a correctly-defined root_server URL.
12047c478bd9Sstevel@tonic-gate */
12057c478bd9Sstevel@tonic-gate if ((urlstr = bootconf_get(&bc_handle,
12067c478bd9Sstevel@tonic-gate BC_ROOT_SERVER)) == NULL) {
12077c478bd9Sstevel@tonic-gate info("no root_server URL!", interactive);
12087c478bd9Sstevel@tonic-gate error = B_TRUE;
12097c478bd9Sstevel@tonic-gate } else if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
12107c478bd9Sstevel@tonic-gate info("root_server not legal URL!", interactive);
12117c478bd9Sstevel@tonic-gate error = B_TRUE;
12127c478bd9Sstevel@tonic-gate } else if ((hp = gethostbyname(u.hport.hostname)) == NULL) {
12137c478bd9Sstevel@tonic-gate info("cannot resolve root_server hostname!",
12147c478bd9Sstevel@tonic-gate interactive);
12157c478bd9Sstevel@tonic-gate error = B_TRUE;
12167c478bd9Sstevel@tonic-gate } else {
12177c478bd9Sstevel@tonic-gate rsnet = *(in_addr_t *)hp->h_addr & subnetmask;
12187c478bd9Sstevel@tonic-gate have_root_server = B_TRUE;
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate * Is there a correctly-defined (non-empty) boot_logger URL?
12237c478bd9Sstevel@tonic-gate */
12247c478bd9Sstevel@tonic-gate if ((urlstr = bootconf_get(&bc_handle,
12257c478bd9Sstevel@tonic-gate BC_BOOT_LOGGER)) != NULL) {
12267c478bd9Sstevel@tonic-gate if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
12277c478bd9Sstevel@tonic-gate info("boot_logger not legal URL!", interactive);
12287c478bd9Sstevel@tonic-gate error = B_TRUE;
12297c478bd9Sstevel@tonic-gate } else if ((hp = gethostbyname(u.hport.hostname)) ==
12307c478bd9Sstevel@tonic-gate NULL) {
12317c478bd9Sstevel@tonic-gate info("cannot resolve boot_logger hostname!",
12327c478bd9Sstevel@tonic-gate interactive);
12337c478bd9Sstevel@tonic-gate error = B_TRUE;
12347c478bd9Sstevel@tonic-gate } else {
12357c478bd9Sstevel@tonic-gate blnet = *(in_addr_t *)hp->h_addr & subnetmask;
12367c478bd9Sstevel@tonic-gate have_boot_logger = B_TRUE;
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate }
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate /*
12417c478bd9Sstevel@tonic-gate * If there is no router and no proxy (either on the local
12427c478bd9Sstevel@tonic-gate * subnet or reachable via a router), then the root_server
12437c478bd9Sstevel@tonic-gate * URL (and the boot_logger URL if specified) must be on the
12447c478bd9Sstevel@tonic-gate * local net.
12457c478bd9Sstevel@tonic-gate */
12467c478bd9Sstevel@tonic-gate if (!error && !have_router && !have_proxy) {
12477c478bd9Sstevel@tonic-gate if (have_root_server && rsnet != clnet) {
12487c478bd9Sstevel@tonic-gate info("root_server URL not on local subnet",
12497c478bd9Sstevel@tonic-gate interactive);
12507c478bd9Sstevel@tonic-gate error = B_TRUE;
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate if (have_boot_logger && blnet != clnet) {
12537c478bd9Sstevel@tonic-gate info("boot_logger URL not on local subnet",
12547c478bd9Sstevel@tonic-gate interactive);
12557c478bd9Sstevel@tonic-gate error = B_TRUE;
12567c478bd9Sstevel@tonic-gate }
12577c478bd9Sstevel@tonic-gate }
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate return (error);
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate /*
12647c478bd9Sstevel@tonic-gate * Actually setup our network interface with the values derived from the
12657c478bd9Sstevel@tonic-gate * PROM, DHCP or interactively from the user.
12667c478bd9Sstevel@tonic-gate */
12677c478bd9Sstevel@tonic-gate static void
setup_interface()12687c478bd9Sstevel@tonic-gate setup_interface()
12697c478bd9Sstevel@tonic-gate {
12707c478bd9Sstevel@tonic-gate char str[MAXHOSTNAMELEN]; /* will accomodate an IP too */
12717c478bd9Sstevel@tonic-gate size_t len;
12727c478bd9Sstevel@tonic-gate struct in_addr in_addr;
12737c478bd9Sstevel@tonic-gate
12747c478bd9Sstevel@tonic-gate len = sizeof (str);
12757c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_HOST_IP, str, &len, NULL) == BI_E_SUCCESS &&
12767c478bd9Sstevel@tonic-gate (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
12777c478bd9Sstevel@tonic-gate in_addr.s_addr = htonl(in_addr.s_addr);
12787c478bd9Sstevel@tonic-gate ipv4_setipaddr(&in_addr);
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate len = sizeof (str);
12827c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_SUBNET_MASK, str, &len, NULL) == BI_E_SUCCESS &&
12837c478bd9Sstevel@tonic-gate (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
12847c478bd9Sstevel@tonic-gate in_addr.s_addr = htonl(in_addr.s_addr);
12857c478bd9Sstevel@tonic-gate ipv4_setnetmask(&in_addr);
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate len = sizeof (str);
12897c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_ROUTER_IP, str, &len, NULL) == BI_E_SUCCESS &&
12907c478bd9Sstevel@tonic-gate (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
12917c478bd9Sstevel@tonic-gate in_addr.s_addr = htonl(in_addr.s_addr);
12927c478bd9Sstevel@tonic-gate ipv4_setdefaultrouter(&in_addr);
12937c478bd9Sstevel@tonic-gate (void) ipv4_route(IPV4_ADD_ROUTE, RT_DEFAULT, NULL, &in_addr);
12947c478bd9Sstevel@tonic-gate }
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate len = sizeof (str);
12977c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_HOSTNAME, str, &len, NULL) == BI_E_SUCCESS) {
12987c478bd9Sstevel@tonic-gate (void) sethostname(str, len);
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate }
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate boolean_t
wanboot_init_interface(char * boot_arguments)13037c478bd9Sstevel@tonic-gate wanboot_init_interface(char *boot_arguments)
13047c478bd9Sstevel@tonic-gate {
13057c478bd9Sstevel@tonic-gate boolean_t interactive;
13067c478bd9Sstevel@tonic-gate int which;
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate * Get the keys from PROM before we allow the user
13117c478bd9Sstevel@tonic-gate * to override them from the CLI.
13127c478bd9Sstevel@tonic-gate */
13137c478bd9Sstevel@tonic-gate get_prom_encr_keys();
13147c478bd9Sstevel@tonic-gate get_prom_hash_keys();
13157c478bd9Sstevel@tonic-gate #endif /* defined(__sparcv9) */
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate /*
13187c478bd9Sstevel@tonic-gate * If there is already a bootp-response property under
13197c478bd9Sstevel@tonic-gate * /chosen then the PROM must have done DHCP for us;
13207c478bd9Sstevel@tonic-gate * invoke dhcp() to 'bind' the interface.
13217c478bd9Sstevel@tonic-gate */
13227c478bd9Sstevel@tonic-gate if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL, NULL) ==
13237c478bd9Sstevel@tonic-gate BI_E_BUF2SMALL) {
13247c478bd9Sstevel@tonic-gate (void) cldhcp(NULL, NULL, 0);
13257c478bd9Sstevel@tonic-gate }
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate /*
13287c478bd9Sstevel@tonic-gate * Obtain default interface values from bootinfo.
13297c478bd9Sstevel@tonic-gate */
13307c478bd9Sstevel@tonic-gate bootinfo_defaults(CLF_IF);
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate /*
13337c478bd9Sstevel@tonic-gate * Process the boot arguments (following the "-o" option).
13347c478bd9Sstevel@tonic-gate */
13357c478bd9Sstevel@tonic-gate if (boot_arguments != NULL) {
13367c478bd9Sstevel@tonic-gate (void) cli_eval_buf(boot_arguments,
13377c478bd9Sstevel@tonic-gate (CLF_ARG | CLF_IF | CLF_BM));
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate /*
13417c478bd9Sstevel@tonic-gate * Stash away any interface/bootmisc parameter values we got
13427c478bd9Sstevel@tonic-gate * from either the PROM or the boot arguments.
13437c478bd9Sstevel@tonic-gate */
13447c478bd9Sstevel@tonic-gate update_bootinfo(CLF_IF | CLF_BM);
13457c478bd9Sstevel@tonic-gate
13467c478bd9Sstevel@tonic-gate /*
13477c478bd9Sstevel@tonic-gate * If we don't already have a value for bootserver, try to
13487c478bd9Sstevel@tonic-gate * deduce one. Refresh wbcli's idea of these values.
13497c478bd9Sstevel@tonic-gate */
13507c478bd9Sstevel@tonic-gate determine_bootserver_url();
13517c478bd9Sstevel@tonic-gate bootinfo_defaults(CLF_BM);
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate /*
13547c478bd9Sstevel@tonic-gate * Check that the information we have collected thus far is sufficient.
13557c478bd9Sstevel@tonic-gate */
13567c478bd9Sstevel@tonic-gate interactive = args_specified_prompt;
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate if (interactive) {
13597c478bd9Sstevel@tonic-gate /*
13607c478bd9Sstevel@tonic-gate * Drop into the boot interpreter to allow the input
13617c478bd9Sstevel@tonic-gate * of keys, bootserver and bootmisc, and in the case
13627c478bd9Sstevel@tonic-gate * that net-config-strategy == "manual" the interface
13637c478bd9Sstevel@tonic-gate * parameters.
13647c478bd9Sstevel@tonic-gate */
13657c478bd9Sstevel@tonic-gate which = CLF_BM | CLF_CMD;
13667c478bd9Sstevel@tonic-gate if (strcmp(net_config_strategy(), "manual") == 0)
13677c478bd9Sstevel@tonic-gate which |= CLF_IF;
13687c478bd9Sstevel@tonic-gate
13697c478bd9Sstevel@tonic-gate do {
13707c478bd9Sstevel@tonic-gate cli_interpret(which);
13717c478bd9Sstevel@tonic-gate update_bootinfo(CLF_IF | CLF_BM);
13727c478bd9Sstevel@tonic-gate } while (config_incomplete(CLF_IF, interactive));
13737c478bd9Sstevel@tonic-gate } else {
13747c478bd9Sstevel@tonic-gate /*
13757c478bd9Sstevel@tonic-gate * The user is not to be given the opportunity to
13767c478bd9Sstevel@tonic-gate * enter further values; fail.
13777c478bd9Sstevel@tonic-gate */
13787c478bd9Sstevel@tonic-gate if (config_incomplete(CLF_IF, interactive)) {
13797c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_CRIT,
13807c478bd9Sstevel@tonic-gate "interface incorrectly configured");
13817c478bd9Sstevel@tonic-gate return (B_FALSE);
13827c478bd9Sstevel@tonic-gate }
13837c478bd9Sstevel@tonic-gate }
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate /*
13867c478bd9Sstevel@tonic-gate * If a wanboot-enabled PROM hasn't processed client-id in
13877c478bd9Sstevel@tonic-gate * network-boot-arguments, or no value for client-id has been
13887c478bd9Sstevel@tonic-gate * specified to the boot interpreter, then provide a default
13897c478bd9Sstevel@tonic-gate * client-id based on our MAC address.
13907c478bd9Sstevel@tonic-gate */
13917c478bd9Sstevel@tonic-gate generate_default_clientid();
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate /*
13947c478bd9Sstevel@tonic-gate * If net-config-strategy == "manual" then we must setup
13957c478bd9Sstevel@tonic-gate * the interface now; if "dhcp" then it will already have
13967c478bd9Sstevel@tonic-gate * been setup.
13977c478bd9Sstevel@tonic-gate */
13987c478bd9Sstevel@tonic-gate if (strcmp(net_config_strategy(), "manual") == 0)
13997c478bd9Sstevel@tonic-gate setup_interface();
14007c478bd9Sstevel@tonic-gate return (B_TRUE);
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate boolean_t
wanboot_verify_config(void)14047c478bd9Sstevel@tonic-gate wanboot_verify_config(void)
14057c478bd9Sstevel@tonic-gate {
14067c478bd9Sstevel@tonic-gate /*
14077c478bd9Sstevel@tonic-gate * Check that the wanboot.conf file defines a valid root_server
14087c478bd9Sstevel@tonic-gate * URL, and check that, if given, the boot_logger URL is valid.
14097c478bd9Sstevel@tonic-gate */
14107c478bd9Sstevel@tonic-gate if (config_incomplete(0, B_FALSE)) {
14117c478bd9Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_CRIT,
14127c478bd9Sstevel@tonic-gate "incomplete boot configuration");
14137c478bd9Sstevel@tonic-gate return (B_FALSE);
14147c478bd9Sstevel@tonic-gate }
14157c478bd9Sstevel@tonic-gate return (B_TRUE);
14167c478bd9Sstevel@tonic-gate }
1417