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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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