Print this page
first pass
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/psm/stand/boot/sparc/common/wbcli.c
+++ new/usr/src/psm/stand/boot/sparc/common/wbcli.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #pragma ident "%Z%%M% %I% %E% SMI"
27 27
28 -/* EXPORT DELETE START */
29 28 #include <sys/types.h>
30 29 #include <sys/param.h>
31 30 #include <sys/salib.h>
32 31 #include <sys/promif.h>
33 32 #include <sys/wanboot_impl.h>
34 33 #include <netinet/in.h>
35 34 #include <parseURL.h>
36 35 #include <bootlog.h>
37 36 #include <sys/socket.h>
38 37 #include <netinet/inetutil.h>
39 38 #include <netinet/dhcp.h>
40 39 #include <dhcp_impl.h>
41 40 #include <lib/inet/mac.h>
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
42 41 #include <lib/inet/ipv4.h>
43 42 #include <lib/inet/dhcpv4.h>
44 43 #include <lib/sock/sock_test.h>
45 44 #include <sys/sunos_dhcp_class.h>
46 45 #include <aes.h>
47 46 #include <des3.h>
48 47 #include <hmac_sha1.h>
49 48 #include <netdb.h>
50 49 #include <wanboot_conf.h>
51 50 #include <bootinfo.h>
52 -/* EXPORT DELETE END */
53 51
54 52 #include "wbcli.h"
55 53
56 -/* EXPORT DELETE START */
57 -
58 54 #define skipspace(p) while (isspace(*(p))) ++p
59 55
60 56 #define skiptext(p) while (*(p) != '\0' && !isspace(*(p)) && \
61 57 *(p) != '=' && *(p) != ',') ++p
62 58
63 59 #define PROMPT "boot> "
64 60 #define TEST_PROMPT "boot-test> "
65 61
66 62 #define CLI_SET 0
67 63 #define CLI_FAIL (-1)
68 64 #define CLI_EXIT (-2)
69 65 #define CLI_CONT (-3)
70 66
71 67 #define CLF_CMD 0x00000001 /* builtin command */
72 68 #define CLF_ARG 0x00000002 /* boot argument directive */
73 69
74 70 #define CLF_IF 0x00000100 /* interface parameter */
75 71 #define CLF_BM 0x00000200 /* bootmisc parameter */
76 72
77 73 #define CLF_VALSET 0x00010000 /* value set, may be null */
78 74 #define CLF_HIDDEN 0x00020000 /* don't show its value (key) */
79 75 #define CLF_VALMOD 0x00040000 /* value modified by the user */
80 76
81 77 /*
82 78 * Macros for use in managing the flags in the cli_list[].
83 79 * The conventions we follow are:
84 80 *
85 81 * CLF_VALSET is cleared if a value is removed from varptr
86 82 * CLF_VALSET is set if a value has been placed in varptr
87 83 * (that value need not be vetted)
88 84 * CLF_HIDDEN is set if a value must not be exposed to the user
89 85 * CLF_HIDDEN is cleared if a value can be exposed to the user
90 86 * CLF_VALMOD is cleared if a value in varptr has not been modified
91 87 * CLF_VALMOD is set if a value in varptr has been modified by
92 88 * the user
93 89 */
94 90 #ifdef DEBUG
95 91 #define CLF_SETVAL(var) { \
96 92 (((var)->flags) |= CLF_VALSET); \
97 93 printf("set %s\n", var->varname);\
98 94 }
99 95
100 96 #define CLF_ISSET(var) (printf("%s\n", \
101 97 (((var)->flags) & CLF_VALSET) != 0 \
102 98 ? "is set" : "not set"), \
103 99 ((((var)->flags) & CLF_VALSET) != 0))
104 100
105 101 #define CLF_CLRHIDDEN(var) { \
106 102 (((var)->flags) &= ~CLF_HIDDEN); \
107 103 printf("unhide %s\n", var->varname); \
108 104 }
109 105
110 106 #define CLF_ISHIDDEN(var) (printf("%s\n", \
111 107 (((var)->flags) & CLF_HIDDEN) != 0 \
112 108 ? "is hidden" : "not hidden"), \
113 109 ((((var)->flags) & CLF_HIDDEN) != 0))
114 110
115 111 #define CLF_MODVAL(var) { \
116 112 (((var)->flags) |= \
117 113 (CLF_VALMOD | CLF_VALSET)); \
118 114 printf("modified %s\n", var->varname);\
119 115 }
120 116
121 117 #define CLF_ISMOD(var) (printf("%s\n", \
122 118 (((var)->flags) & CLF_VALMOD) != 0 \
123 119 ? "is set" : "not set"), \
124 120 ((((var)->flags) & CLF_VALMOD) != 0))
125 121 #else /* DEBUG */
126 122
127 123 #define CLF_SETVAL(var) (((var)->flags) |= CLF_VALSET)
128 124 #define CLF_ISSET(var) ((((var)->flags) & CLF_VALSET) != 0)
129 125 #define CLF_CLRHIDDEN(var) (((var)->flags) &= ~CLF_HIDDEN)
130 126 #define CLF_ISHIDDEN(var) ((((var)->flags) & CLF_HIDDEN) != 0)
131 127 #define CLF_MODVAL(var) (((var)->flags) |= (CLF_VALMOD | CLF_VALSET))
132 128 #define CLF_ISMOD(var) ((((var)->flags) & CLF_VALMOD) != 0)
133 129
134 130 #endif /* DEBUG */
135 131
136 132 /*
137 133 * The width of the widest varname below - currently "subnet_mask".
138 134 */
139 135 #define VAR_MAXWIDTH strlen(BI_SUBNET_MASK)
140 136
141 137 struct cli_ent;
142 138 typedef int claction_t(struct cli_ent *, char *, boolean_t);
143 139
144 140 typedef struct cli_ent {
145 141 char *varname;
146 142 claction_t *action;
147 143 int flags;
148 144 void *varptr;
149 145 uint_t varlen;
150 146 uint_t varmax;
151 147 } cli_ent_t;
152 148
153 149 static cli_ent_t *find_cli_ent(char *varstr);
154 150
155 151 static char cmdbuf[2048]; /* interpreter buffer */
156 152 static char hostip[INET_ADDRSTRLEN];
157 153 static char subnet[INET_ADDRSTRLEN];
158 154 static char router[INET_ADDRSTRLEN];
159 155 static char hostname[MAXHOSTNAMELEN];
160 156 static char httpproxy[INET_ADDRSTRLEN + 5]; /* a.b.c.d:p */
161 157 static char bootserverURL[URL_MAX_STRLEN + 1];
162 158 static unsigned char clientid[WB_MAX_CID_LEN];
163 159 static unsigned char aeskey[AES_128_KEY_SIZE];
164 160 static unsigned char des3key[DES3_KEY_SIZE];
165 161 static unsigned char sha1key[WANBOOT_HMAC_KEY_SIZE];
166 162 static boolean_t args_specified_prompt = B_FALSE;
167 163
168 164 extern bc_handle_t bc_handle;
169 165 extern int getchar(void);
170 166
171 167 static claction_t clcid, clkey, clip, clstr, clurl, clhp;
172 168 static claction_t clhelp, cllist, clprompt, cldhcp, cltest, clgo, clexit;
173 169
174 170 static cli_ent_t cli_list[] = {
175 171 /*
176 172 * Commands/bootargs:
177 173 */
178 174 { "test", cltest, CLF_ARG,
179 175 NULL, 0, 0 },
180 176 { "dhcp", cldhcp, CLF_ARG,
181 177 NULL, 0, 0 },
182 178 { "prompt", clprompt, CLF_CMD | CLF_ARG,
183 179 NULL, 0, 0 },
184 180 { "list", cllist, CLF_CMD,
185 181 NULL, 0, 0 },
186 182 { "help", clhelp, CLF_CMD,
187 183 NULL, 0, 0 },
188 184 { "go", clgo, CLF_CMD,
189 185 NULL, 0, 0 },
190 186 { "exit", clexit, CLF_CMD,
191 187 NULL, 0, 0 },
192 188
193 189 /*
194 190 * Interface:
195 191 */
196 192 { BI_HOST_IP, clip, CLF_IF,
197 193 hostip, 0, sizeof (hostip) },
198 194 { BI_SUBNET_MASK, clip, CLF_IF,
199 195 subnet, 0, sizeof (subnet) },
200 196 { BI_ROUTER_IP, clip, CLF_IF,
201 197 router, 0, sizeof (router) },
202 198 { BI_HOSTNAME, clstr, CLF_IF,
203 199 hostname, 0, sizeof (hostname) },
204 200 { BI_HTTP_PROXY, clhp, CLF_IF,
205 201 httpproxy, 0, sizeof (httpproxy) },
206 202 { BI_CLIENT_ID, clcid, CLF_IF,
207 203 clientid, 0, sizeof (clientid) },
208 204
209 205 /*
210 206 * Bootmisc:
211 207 */
212 208 { BI_AES_KEY, clkey, CLF_BM | CLF_HIDDEN,
213 209 aeskey, 0, sizeof (aeskey) },
214 210 { BI_3DES_KEY, clkey, CLF_BM | CLF_HIDDEN,
215 211 des3key, 0, sizeof (des3key) },
216 212 { BI_SHA1_KEY, clkey, CLF_BM | CLF_HIDDEN,
217 213 sha1key, 0, sizeof (sha1key) },
218 214 { BI_BOOTSERVER, clurl, CLF_BM,
219 215 bootserverURL, 0, sizeof (bootserverURL) },
220 216 };
221 217
222 218 static int num_cli_ent = (sizeof (cli_list) / sizeof (cli_ent_t));
223 219
224 220 /*
225 221 * Fetch a line from the user, handling backspace appropriately.
226 222 */
227 223 static int
228 224 editline(char *buf, int count)
229 225 {
230 226 int i = 0;
231 227 char c;
232 228
233 229 while (i < count - 1) {
234 230 c = getchar();
235 231 if (c == '\n') {
236 232 break;
237 233 } else if (c == '\b') {
238 234 /* Clear for backspace. */
239 235 if (i > 0)
240 236 i--;
241 237 continue;
242 238 } else {
243 239 buf[i++] = c;
244 240 }
245 241 }
246 242 buf[i] = '\0';
247 243 return (i);
248 244 }
249 245
250 246 /*
251 247 * Assign a client-id to cliptr, or output cliptr's value as a client-id.
252 248 * On assignment the value is specified in valstr, either in hexascii or
253 249 * as a quoted string; on output its value is printed in hexascii.
254 250 */
255 251 static int
256 252 clcid(cli_ent_t *cliptr, char *valstr, boolean_t out)
257 253 {
258 254 uint_t len, vmax;
259 255 boolean_t hexascii = B_TRUE;
260 256 char buffer[2 * WB_MAX_CID_LEN + 1];
261 257
262 258 if (out) {
263 259 len = cliptr->varlen * 2 + 1;
264 260 (void) octet_to_hexascii(cliptr->varptr, cliptr->varlen,
265 261 buffer, &len);
266 262 printf("%s", buffer);
267 263 return (CLI_CONT);
268 264 } else {
269 265 len = strlen(valstr);
270 266 vmax = cliptr->varmax - 1; /* space for the prefix */
271 267
272 268 /*
273 269 * Check whether the value is a quoted string; if so, strip
274 270 * the quotes and note that it's not in hexascii.
275 271 */
276 272 if ((valstr[0] == '"' || valstr[0] == '\'') &&
277 273 valstr[len-1] == valstr[0]) {
278 274 hexascii = B_FALSE;
279 275 ++valstr;
280 276 len -= 2;
281 277 valstr[len] = '\0';
282 278 } else {
283 279 /*
284 280 * If the value contains any non-hex digits assume
285 281 * that it's not in hexascii.
286 282 */
287 283 char *p;
288 284
289 285 for (p = valstr; *p != '\0'; ++p) {
290 286 if (!isxdigit(*p)) {
291 287 hexascii = B_FALSE;
292 288 break;
293 289 }
294 290 }
295 291 }
296 292
297 293 if (hexascii) {
298 294 if (len > vmax * 2 ||
299 295 hexascii_to_octet(valstr, len,
300 296 (char *)(cliptr->varptr), &vmax) != 0) {
301 297 return (CLI_FAIL);
302 298 }
303 299 cliptr->varlen = vmax;
304 300 } else {
305 301 if (len > vmax) {
306 302 return (CLI_FAIL);
307 303 }
308 304 bcopy(valstr, cliptr->varptr, len);
309 305 cliptr->varlen = len;
310 306 }
311 307
312 308 return (CLI_SET);
313 309 }
314 310 }
315 311
316 312 /*
317 313 * Assign a key to cliptr, or output cliptr's value as a key.
318 314 * On assignment the value is specified in valstr in hexascii;
319 315 * on output its value is printed in hexascii, provided the key
320 316 * was entered at the interpreter (not obtained from OBP and
321 317 * thus hidden).
322 318 */
323 319 static int
324 320 clkey(cli_ent_t *cliptr, char *valstr, boolean_t out)
325 321 {
326 322 uint_t len, vmax;
327 323
328 324 if (out) {
329 325 char buffer[2 * WANBOOT_MAXKEYLEN + 1];
330 326
331 327 if (!CLF_ISHIDDEN(cliptr)) {
332 328 len = cliptr->varlen * 2 + 1;
333 329 (void) octet_to_hexascii(cliptr->varptr,
334 330 cliptr->varlen, buffer, &len);
335 331 printf("%s", buffer);
336 332 } else {
337 333 printf("*HIDDEN*");
338 334 }
339 335 return (CLI_CONT);
340 336 } else {
341 337 len = strlen(valstr);
342 338 vmax = cliptr->varmax;
343 339 if (len != vmax * 2 || hexascii_to_octet(valstr, len,
344 340 cliptr->varptr, &vmax) != 0) {
345 341 return (CLI_FAIL);
346 342 }
347 343 cliptr->varlen = vmax;
348 344 CLF_CLRHIDDEN(cliptr);
349 345 return (CLI_SET);
350 346 }
351 347 }
352 348
353 349 /*
354 350 * Assign an IP address to cliptr, or output cliptr's value as an
355 351 * IP address. On assignment the value is specified in valstr in
356 352 * dotted-decimal format; on output its value is printed in dotted-
357 353 * decimal format.
358 354 */
359 355 static int
360 356 clip(cli_ent_t *cliptr, char *valstr, boolean_t out)
361 357 {
362 358 uint_t len;
363 359
364 360 if (out) {
365 361 printf("%s", (char *)cliptr->varptr);
366 362 return (CLI_CONT);
367 363 }
368 364
369 365 if (inet_addr(valstr) == (in_addr_t)-1 ||
370 366 (len = strlen(valstr)) >= cliptr->varmax) {
371 367 return (CLI_FAIL);
372 368 }
373 369
374 370 (void) strcpy(cliptr->varptr, valstr);
375 371 cliptr->varlen = len + 1;
376 372 return (CLI_SET);
377 373 }
378 374
379 375 /*
380 376 * Assign an arbitrary string to cliptr, or output cliptr's value as a string.
381 377 */
382 378 static int
383 379 clstr(cli_ent_t *cliptr, char *valstr, boolean_t out)
384 380 {
385 381 uint_t len;
386 382
387 383 if (out) {
388 384 printf("%s", (char *)cliptr->varptr);
389 385 return (CLI_CONT);
390 386 } else {
391 387 if ((len = strlen(valstr)) >= cliptr->varmax) {
392 388 return (CLI_FAIL);
393 389 } else {
394 390 (void) strcpy(cliptr->varptr, valstr);
395 391 cliptr->varlen = len + 1;
396 392 return (CLI_SET);
397 393 }
398 394 }
399 395 }
400 396
401 397 /*
402 398 * Assign a URL to cliptr (having verified the format), or output cliptr's
403 399 * value as a URL. The host must be specified in dotted-decimal, and the
404 400 * scheme must not be https.
405 401 */
406 402 static int
407 403 clurl(cli_ent_t *cliptr, char *valstr, boolean_t out)
408 404 {
409 405 url_t u;
410 406 uint_t len;
411 407
412 408 if (out) {
413 409 printf("%s", (char *)cliptr->varptr);
414 410 return (CLI_CONT);
415 411 }
416 412
417 413 if (url_parse(valstr, &u) != URL_PARSE_SUCCESS ||
418 414 u.https || inet_addr(u.hport.hostname) == (in_addr_t)-1 ||
419 415 (len = strlen(valstr)) >= cliptr->varmax) {
420 416 return (CLI_FAIL);
421 417 }
422 418
423 419 (void) strcpy(cliptr->varptr, valstr);
424 420 cliptr->varlen = len + 1;
425 421 return (CLI_SET);
426 422 }
427 423
428 424 /*
429 425 * Assign a hostport to cliptr (having verified the format), or output cliptr's
430 426 * value as a hostport. The host must be specified in dotted-decimal.
431 427 */
432 428 static int
433 429 clhp(cli_ent_t *cliptr, char *valstr, boolean_t out)
434 430 {
435 431 url_hport_t u;
436 432 uint_t len;
437 433
438 434 if (out) {
439 435 printf("%s", (char *)cliptr->varptr);
440 436 return (CLI_CONT);
441 437 }
442 438
443 439 if (url_parse_hostport(valstr, &u, URL_DFLT_PROXY_PORT) !=
444 440 URL_PARSE_SUCCESS ||
445 441 inet_addr(u.hostname) == (in_addr_t)-1 ||
446 442 (len = strlen(valstr)) >= cliptr->varmax) {
447 443 return (CLI_FAIL);
448 444 }
449 445
450 446 (void) strcpy(cliptr->varptr, valstr);
451 447 cliptr->varlen = len + 1;
452 448 return (CLI_SET);
453 449 }
454 450
455 451 /*
456 452 * Exit the interpreter and return to the booter.
457 453 */
458 454 /*ARGSUSED*/
459 455 static int
460 456 clgo(cli_ent_t *cliptr, char *valstr, boolean_t out)
461 457 {
462 458 return (CLI_EXIT);
463 459 }
464 460
465 461 /*
466 462 * Exit the interpreter and return to OBP.
467 463 */
468 464 /*ARGSUSED*/
469 465 static int
470 466 clexit(cli_ent_t *cliptr, char *valstr, boolean_t out)
471 467 {
472 468 prom_exit_to_mon();
473 469 /*NOTREACHED*/
474 470 return (CLI_EXIT);
475 471 }
476 472
477 473 /*
478 474 * Provide simple help information.
479 475 */
480 476 /*ARGSUSED*/
481 477 static int
482 478 clhelp(cli_ent_t *cliptr, char *valstr, boolean_t out)
483 479 {
484 480 printf("var=val - set variable\n");
485 481 printf("var= - unset variable\n");
486 482 printf("var - print variable\n");
487 483 printf("list - list variables and their values\n");
488 484 printf("prompt - prompt for unset variables\n");
489 485 printf("go - continue booting\n");
490 486 printf("exit - quit boot interpreter and return to OBP\n");
491 487
492 488 return (CLI_CONT);
493 489 }
494 490
495 491 /*
496 492 * List variables and their current values.
497 493 */
498 494 /*ARGSUSED*/
499 495 static int
500 496 cllist(cli_ent_t *cliptr, char *valstr, boolean_t out)
501 497 {
502 498 int wanted = (int)(uintptr_t)valstr; /* use uintptr_t for gcc */
503 499 int i;
504 500
505 501 wanted &= ~(CLF_CMD | CLF_ARG);
506 502
507 503 for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; cliptr++) {
508 504 if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0 ||
509 505 (cliptr->flags & wanted) == 0) {
510 506 continue;
511 507 }
512 508 printf("%s: ", cliptr->varname);
513 509 /*
514 510 * Line the values up - space to the width of the widest
515 511 * varname + 1 for the ':'.
516 512 */
517 513 for (i = VAR_MAXWIDTH + 1 - strlen(cliptr->varname);
518 514 i > 0; --i) {
519 515 printf(" ");
520 516 }
521 517
522 518 if (CLF_ISSET(cliptr) || CLF_ISHIDDEN(cliptr)) {
523 519 (void) cliptr->action(cliptr, NULL, B_TRUE);
524 520 printf("\n");
525 521 } else {
526 522 printf("UNSET\n");
527 523 }
528 524 }
529 525
530 526 return (CLI_CONT);
531 527 }
532 528
533 529 /*
534 530 * Prompt for wanted values.
535 531 */
536 532 /*ARGSUSED*/
537 533 static int
538 534 clprompt(cli_ent_t *cliptr, char *valstr, boolean_t out)
539 535 {
540 536 char *p;
541 537 int wanted = (int)(uintptr_t)valstr; /* use uintrptr_t for gcc */
542 538
543 539 /*
544 540 * If processing boot arguments, simply note the fact that clprompt()
545 541 * should be invoked later when other parameters may be supplied.
546 542 */
547 543 if ((wanted & CLF_ARG) != 0) {
548 544 args_specified_prompt = B_TRUE;
549 545 return (CLI_CONT);
550 546 }
551 547 wanted &= ~(CLF_CMD | CLF_ARG);
552 548
553 549 for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
554 550 if ((cliptr->flags & wanted) == 0) {
555 551 continue;
556 552 }
557 553
558 554 printf("%s", cliptr->varname);
559 555 if (CLF_ISSET(cliptr)) {
560 556 printf(" [");
561 557 (void) cliptr->action(cliptr, NULL, B_TRUE);
562 558 printf("]");
563 559 }
564 560 printf("? ");
565 561 (void) editline(cmdbuf, sizeof (cmdbuf));
566 562 printf("\n");
567 563
568 564 p = cmdbuf;
569 565 skipspace(p);
570 566 if (*p == '\0') { /* nothing there */
571 567 continue;
572 568 }
573 569
574 570 /* Get valstr and nul terminate */
575 571 valstr = p;
576 572 ++p;
577 573 skiptext(p);
578 574 *p = '\0';
579 575
580 576 /* If empty value, do nothing */
581 577 if (strlen(valstr) == 0) {
582 578 continue;
583 579 }
584 580
585 581 switch (cliptr->action(cliptr, valstr, B_FALSE)) {
586 582 case CLI_SET:
587 583 CLF_MODVAL(cliptr);
588 584 break;
589 585 case CLI_FAIL:
590 586 printf("Incorrect format, parameter unchanged!\n");
591 587 break;
592 588 case CLI_EXIT:
593 589 return (CLI_EXIT);
594 590 case CLI_CONT:
595 591 break;
596 592 }
597 593 }
598 594
599 595 return (CLI_CONT);
600 596 }
601 597
602 598 /*
603 599 * If the PROM has done DHCP, bind the interface; otherwise do the full
604 600 * DHCP packet exchange.
605 601 */
606 602 /*ARGSUSED*/
607 603 static int
608 604 cldhcp(cli_ent_t *cliptr, char *valstr, boolean_t out)
609 605 {
610 606 static boolean_t first_time = B_TRUE;
611 607 static int ret = CLI_CONT;
612 608
613 609 if (first_time) {
614 610 /*
615 611 * Set DHCP's idea of the client_id from our cached value.
616 612 */
617 613 cliptr = find_cli_ent(BI_CLIENT_ID);
618 614 if (CLF_ISMOD(cliptr)) {
619 615 dhcp_set_client_id(cliptr->varptr, cliptr->varlen);
620 616 }
621 617
622 618 bootlog("wanboot", BOOTLOG_INFO, "Starting DHCP configuration");
623 619
624 620 (void) ipv4_setpromiscuous(B_TRUE);
625 621 if (dhcp() == 0) {
626 622 bootlog("wanboot", BOOTLOG_INFO,
627 623 "DHCP configuration succeeded");
628 624 } else {
629 625 bootlog("wanboot", BOOTLOG_CRIT,
630 626 "DHCP configuration failed");
631 627 ret = CLI_FAIL;
632 628 }
633 629 (void) ipv4_setpromiscuous(B_FALSE);
634 630
635 631 first_time = B_FALSE;
636 632 }
637 633
638 634 return (ret);
639 635 }
640 636
641 637 /*
642 638 * Invoke the socket test interpreter (for testing purposes only).
643 639 */
644 640 /*ARGSUSED*/
645 641 static int
646 642 cltest(cli_ent_t *cliptr, char *valstr, boolean_t out)
647 643 {
648 644 (void) ipv4_setpromiscuous(B_FALSE);
649 645 printf("\n");
650 646 for (;;) {
651 647 printf(TEST_PROMPT);
652 648 if (editline(cmdbuf, sizeof (cmdbuf)) > 0) {
653 649 printf("\n");
654 650 (void) st_interpret(cmdbuf);
655 651 } else {
656 652 prom_exit_to_mon();
657 653 /* NOTREACHED */
658 654 }
659 655 }
660 656
661 657 /* NOTREACHED */
662 658 return (CLI_CONT);
663 659 }
664 660
665 661 /*
666 662 * Return the cliptr corresponding to the named variable.
667 663 */
668 664 static cli_ent_t *
669 665 find_cli_ent(char *varstr)
670 666 {
671 667 cli_ent_t *cliptr;
672 668
673 669 for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
674 670 if (strcmp(varstr, cliptr->varname) == 0) {
675 671 return (cliptr);
676 672 }
677 673 }
678 674
679 675 return (NULL);
680 676 }
681 677
682 678 /*
683 679 * Evaluate the commands provided by the user (either as "-o" boot arguments
684 680 * or interactively at the boot interpreter).
685 681 */
686 682 static int
687 683 cli_eval_buf(char *inbuf, int wanted)
688 684 {
689 685 char *p, *varstr, *end_varstr, *valstr, *end_valstr;
690 686 boolean_t assign;
691 687 cli_ent_t *cliptr;
692 688
693 689 for (p = inbuf; *p != '\0'; ) {
694 690 skipspace(p);
695 691
696 692 /* If nothing more on line, go get the next one */
697 693 if (*p == '\0') {
698 694 break;
699 695 } else if (*p == ',') { /* orphan ',' ? */
700 696 ++p;
701 697 continue;
702 698 }
703 699
704 700 /* Get ptrs to start & end of variable */
705 701 varstr = p;
706 702 ++p;
707 703 skiptext(p);
708 704 end_varstr = p;
709 705 skipspace(p);
710 706
711 707 /* See if we're doing an assignment */
712 708 valstr = NULL;
713 709 if (*p != '=') { /* nope, just printing */
714 710 assign = B_FALSE;
715 711 } else {
716 712 assign = B_TRUE;
717 713 ++p; /* past '=' */
718 714 skipspace(p);
719 715
720 716 /* Assigning something? (else clear variable) */
721 717 if (*p != '\0' && *p != ',') {
722 718 /* Get ptrs to start & end of valstr */
723 719 valstr = p;
724 720 ++p;
725 721 skiptext(p);
726 722 end_valstr = p;
727 723 skipspace(p);
728 724 }
729 725 }
730 726
731 727 /* Skip ',' delimiter if present */
732 728 if (*p == ',') {
733 729 ++p;
734 730 }
735 731
736 732 /* Nul-terminate varstr and valstr (if appropriate) */
737 733 *end_varstr = '\0';
738 734 if (valstr != NULL) {
739 735 *end_valstr = '\0';
740 736 }
741 737
742 738 if ((cliptr = find_cli_ent(varstr)) == NULL) {
743 739 printf("Unknown variable '%s'; ignored\n", varstr);
744 740 continue;
745 741 }
746 742
747 743 /*
748 744 * It's an error to specify a parameter which can only be a
749 745 * boot argument (and not a command) when not processing the
750 746 * boot arguments.
751 747 */
752 748 if ((cliptr->flags & (CLF_CMD | CLF_ARG)) == CLF_ARG &&
753 749 (wanted & CLF_ARG) == 0) {
754 750 printf("'%s' may only be specified as a "
755 751 "boot argument; ignored\n", varstr);
756 752 continue;
757 753 }
758 754
759 755 /*
760 756 * When doing an assignment, verify that it's not a command
761 757 * or argument name, and that it is permissible in the current
762 758 * context. An 'empty' assignment (var=) is treated the same
763 759 * as a null assignment (var="").
764 760 *
765 761 * If processing the boot arguments, it is an error to not
766 762 * assign a value to a non-argument parameter.
767 763 */
768 764 if (assign) {
769 765 if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0) {
770 766 printf("'%s' is a command and cannot "
771 767 "be assigned\n", varstr);
772 768 return (CLI_FAIL);
773 769 }
774 770 if ((cliptr->flags & wanted) == 0) {
775 771 printf("'%s' cannot be assigned\n", varstr);
776 772 return (CLI_FAIL);
777 773 }
778 774
779 775 if (valstr == NULL) {
780 776 cliptr->varlen = 0;
781 777 CLF_MODVAL(cliptr);
782 778 continue;
783 779 }
784 780 } else if ((wanted & CLF_ARG) != 0 &&
785 781 (cliptr->flags & (CLF_CMD | CLF_ARG)) == 0) {
786 782 printf("'%s' must be assigned when specified in "
787 783 " the boot arguments\n", varstr);
788 784 return (CLI_FAIL);
789 785 }
790 786
791 787 /*
792 788 * Pass 'wanted' to command-handling functions, in particular
793 789 * clprompt() and cllist().
794 790 */
795 791 if ((cliptr->flags & CLF_CMD) != 0) {
796 792 /* use uintptr_t to suppress the gcc warning */
797 793 valstr = (char *)(uintptr_t)wanted;
798 794 }
799 795
800 796 /*
801 797 * Call the parameter's action function.
802 798 */
803 799 switch (cliptr->action(cliptr, valstr, !assign)) {
804 800 case CLI_SET:
805 801 CLF_MODVAL(cliptr);
806 802 break;
807 803 case CLI_FAIL:
808 804 printf("Incorrect format: variable '%s' not set\n",
809 805 cliptr->varname);
810 806 break;
811 807 case CLI_EXIT:
812 808 return (CLI_EXIT);
813 809 case CLI_CONT:
814 810 if (!assign) {
815 811 printf("\n");
816 812 }
817 813 break;
818 814 }
819 815 }
820 816
821 817 return (CLI_CONT);
822 818 }
823 819
824 820 static void
825 821 cli_interpret(int wanted)
826 822 {
827 823 printf("\n");
828 824 do {
829 825 printf(PROMPT);
830 826 (void) editline(cmdbuf, sizeof (cmdbuf));
831 827 printf("\n");
832 828
833 829 } while (cli_eval_buf(cmdbuf, wanted) != CLI_EXIT);
834 830 }
835 831
836 832 #if defined(__sparcv9)
837 833 /*
838 834 * This routine queries the PROM to see what encryption keys exist.
839 835 */
840 836 static void
841 837 get_prom_encr_keys()
842 838 {
843 839 cli_ent_t *cliptr;
844 840 char encr_key[WANBOOT_MAXKEYLEN];
845 841 int keylen;
846 842 int status;
847 843 int ret;
848 844
849 845 /*
850 846 * At the top of the priority list, we have AES.
851 847 */
852 848 ret = prom_get_security_key(WANBOOT_AES_128_KEY_NAME, encr_key,
853 849 WANBOOT_MAXKEYLEN, &keylen, &status);
854 850 if ((ret == 0) && (status == 0) && (keylen == AES_128_KEY_SIZE)) {
855 851 cliptr = find_cli_ent(BI_AES_KEY);
856 852 bcopy(encr_key, cliptr->varptr, AES_128_KEY_SIZE);
857 853 cliptr->varlen = AES_128_KEY_SIZE;
858 854 CLF_MODVAL(cliptr);
859 855 }
860 856
861 857 /*
862 858 * Next, 3DES.
863 859 */
864 860 ret = prom_get_security_key(WANBOOT_DES3_KEY_NAME, encr_key,
865 861 WANBOOT_MAXKEYLEN, &keylen, &status);
866 862 if ((ret == 0) && (status == 0) && (keylen == DES3_KEY_SIZE)) {
867 863 cliptr = find_cli_ent(BI_3DES_KEY);
868 864 bcopy(encr_key, cliptr->varptr, DES3_KEY_SIZE);
869 865 cliptr->varlen = DES3_KEY_SIZE;
870 866 CLF_MODVAL(cliptr);
871 867 }
872 868 }
873 869
874 870 /*
875 871 * This routine queries the PROM to see what hashing keys exist.
876 872 */
877 873 static void
878 874 get_prom_hash_keys()
879 875 {
880 876 cli_ent_t *cliptr;
881 877 char hash_key[WANBOOT_HMAC_KEY_SIZE];
882 878 int keylen;
883 879 int status;
884 880 int ret;
885 881
886 882 /*
887 883 * The only supported key thus far is SHA1.
888 884 */
889 885 ret = prom_get_security_key(WANBOOT_HMAC_SHA1_KEY_NAME, hash_key,
890 886 WANBOOT_HMAC_KEY_SIZE, &keylen, &status);
891 887 if ((ret == 0) && (status == 0) && (keylen == WANBOOT_HMAC_KEY_SIZE)) {
892 888 cliptr = find_cli_ent(BI_SHA1_KEY);
893 889 bcopy(hash_key, cliptr->varptr, WANBOOT_HMAC_KEY_SIZE);
894 890 cliptr->varlen = WANBOOT_HMAC_KEY_SIZE;
895 891 CLF_MODVAL(cliptr);
896 892 }
897 893 }
898 894 #endif /* defined(__sparcv9) */
899 895
900 896 /*
901 897 * For the given parameter type(s), get values from bootinfo and cache in
902 898 * the local variables used by the "boot>" interpreter.
903 899 */
904 900 static void
905 901 bootinfo_defaults(int which)
906 902 {
907 903 cli_ent_t *cliptr;
908 904
909 905 for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
910 906 if ((cliptr->flags & which) != 0 && !CLF_ISSET(cliptr)) {
911 907 size_t len = cliptr->varmax;
912 908
913 909 if (bootinfo_get(cliptr->varname, cliptr->varptr,
914 910 &len, NULL) == BI_E_SUCCESS) {
915 911 cliptr->varlen = len;
916 912 CLF_SETVAL(cliptr);
917 913 }
918 914 }
919 915 }
920 916 }
921 917
922 918 /*
923 919 * For the given parameter type(s), store values entered at the "boot>"
924 920 * interpreter back into bootinfo.
925 921 */
926 922 static void
927 923 update_bootinfo(int which)
928 924 {
929 925 cli_ent_t *cliptr;
930 926
931 927 for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
932 928 if ((cliptr->flags & which) != 0 && CLF_ISMOD(cliptr)) {
933 929 (void) bootinfo_put(cliptr->varname,
934 930 cliptr->varptr, cliptr->varlen, 0);
935 931 }
936 932 }
937 933 }
938 934
939 935 /*
940 936 * Return the net-config-strategy: "dhcp", "manual" or "rarp"
941 937 */
942 938 static char *
943 939 net_config_strategy(void)
944 940 {
945 941 static char ncs[8]; /* "dhcp" or "manual" */
946 942 size_t len = sizeof (ncs);
947 943
948 944 if (ncs[0] == '\0' &&
949 945 bootinfo_get(BI_NET_CONFIG_STRATEGY, ncs, &len, NULL) !=
950 946 BI_E_SUCCESS) {
951 947 /*
952 948 * Support for old PROMs: create the net-config-strategy
953 949 * property under /chosen with an appropriate value. If we
954 950 * have a bootp-response (not interested in its value, just
955 951 * its presence) then we did DHCP; otherwise configuration
956 952 * is manual.
957 953 */
958 954 if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL,
959 955 NULL) == BI_E_BUF2SMALL) {
960 956 (void) strcpy(ncs, "dhcp");
961 957 } else {
962 958 (void) strcpy(ncs, "manual");
963 959 }
964 960 (void) bootinfo_put(BI_NET_CONFIG_STRATEGY, ncs, strlen(ncs),
965 961 BI_R_CHOSEN);
966 962
967 963 bootlog("wanboot", BOOTLOG_INFO,
968 964 "Default net-config-strategy: %s", ncs);
969 965 }
970 966
971 967 return (ncs);
972 968 }
973 969
974 970 /*
975 971 * If there is no client-id property published in /chosen (by the PROM or the
976 972 * boot interpreter) provide a default client-id based on the MAC address of
977 973 * the client.
978 974 * As specified in RFC2132 (section 9.14), this is prefixed with a byte
979 975 * which specifies the ARP hardware type defined in RFC1700 (for Ethernet,
980 976 * this should be 1).
981 977 */
982 978 static void
983 979 generate_default_clientid(void)
984 980 {
985 981 char clid[WB_MAX_CID_LEN];
986 982 size_t len = sizeof (clid);
987 983
988 984 if (bootinfo_get(BI_CLIENT_ID, clid, &len, NULL) != BI_E_SUCCESS) {
989 985 len = mac_get_addr_len() + 1; /* include hwtype */
990 986
991 987 if (len > sizeof (clid)) {
992 988 return;
993 989 }
994 990
995 991 clid[0] = mac_arp_type(mac_get_type());
996 992 bcopy(mac_get_addr_buf(), &clid[1], len - 1);
997 993
998 994 (void) bootinfo_put(BI_CLIENT_ID, clid, len, 0);
999 995 }
1000 996 }
1001 997
1002 998 /*
1003 999 * Determine the URL of the boot server from the 'file' parameter to OBP,
1004 1000 * the SbootURI or BootFile DHCP options, or the 'bootserver' value entered
1005 1001 * either as a "-o" argument or at the interpreter.
1006 1002 */
1007 1003 static void
1008 1004 determine_bootserver_url(void)
1009 1005 {
1010 1006 char bs[URL_MAX_STRLEN + 1];
1011 1007 size_t len;
1012 1008 url_t url;
1013 1009
1014 1010 if (bootinfo_get(BI_BOOTSERVER, bs, &len, NULL) != BI_E_SUCCESS) {
1015 1011 /*
1016 1012 * If OBP has published a network-boot-file property in
1017 1013 * /chosen (or there is a DHCP BootFile or SbootURI vendor
1018 1014 * option) and it's a URL, construct the bootserver URL
1019 1015 * from it.
1020 1016 */
1021 1017 len = URL_MAX_STRLEN;
1022 1018 if (bootinfo_get(BI_NETWORK_BOOT_FILE, bs, &len, NULL) !=
1023 1019 BI_E_SUCCESS) {
1024 1020 len = URL_MAX_STRLEN;
1025 1021 if (bootinfo_get(BI_BOOTFILE, bs, &len, NULL) !=
1026 1022 BI_E_SUCCESS) {
1027 1023 return;
1028 1024 }
1029 1025 }
1030 1026 if (url_parse(bs, &url) == URL_PARSE_SUCCESS) {
1031 1027 (void) bootinfo_put(BI_BOOTSERVER, bs, len, 0);
1032 1028 }
1033 1029 }
1034 1030 }
1035 1031
1036 1032 /*
1037 1033 * Provide a classful subnet mask based on the client's IP address.
1038 1034 */
1039 1035 static in_addr_t
1040 1036 generate_classful_subnet(in_addr_t client_ipaddr)
1041 1037 {
1042 1038 struct in_addr subnetmask;
1043 1039 char *netstr;
1044 1040
1045 1041 if (IN_CLASSA(client_ipaddr)) {
1046 1042 subnetmask.s_addr = IN_CLASSA_NET;
1047 1043 } else if (IN_CLASSB(client_ipaddr)) {
1048 1044 subnetmask.s_addr = IN_CLASSB_NET;
1049 1045 } else if (IN_CLASSC(client_ipaddr)) {
1050 1046 subnetmask.s_addr = IN_CLASSC_NET;
1051 1047 } else {
1052 1048 subnetmask.s_addr = IN_CLASSE_NET;
1053 1049 }
1054 1050
1055 1051 netstr = inet_ntoa(subnetmask);
1056 1052 (void) bootinfo_put(BI_SUBNET_MASK, netstr, strlen(netstr) + 1, 0);
1057 1053
1058 1054 return (subnetmask.s_addr);
1059 1055 }
1060 1056
1061 1057 /*
1062 1058 * Informational output to the user (if interactive) or the bootlogger.
1063 1059 */
1064 1060 static void
1065 1061 info(const char *msg, boolean_t interactive)
1066 1062 {
1067 1063 if (interactive) {
1068 1064 printf("%s\n", msg);
1069 1065 } else {
1070 1066 bootlog("wanboot", BOOTLOG_INFO, "%s", msg);
1071 1067 }
1072 1068 }
1073 1069
1074 1070 /*
1075 1071 * Determine whether we have sufficient information to proceed with booting,
1076 1072 * either for configuring the interface and downloading the bootconf file,
1077 1073 * or for downloading the miniroot.
1078 1074 */
1079 1075 static int
1080 1076 config_incomplete(int why, boolean_t interactive)
1081 1077 {
1082 1078 boolean_t error = B_FALSE;
1083 1079 char buf[URL_MAX_STRLEN + 1];
1084 1080 size_t len;
1085 1081 char *urlstr;
1086 1082 url_t u;
1087 1083 struct hostent *hp;
1088 1084 in_addr_t client_ipaddr, ipaddr, bsnet, pxnet;
1089 1085 static in_addr_t subnetmask, clnet;
1090 1086 static boolean_t have_router = B_FALSE;
1091 1087 static boolean_t have_proxy = B_FALSE;
1092 1088 boolean_t have_root_server = B_FALSE;
1093 1089 boolean_t have_boot_logger = B_FALSE;
1094 1090 in_addr_t rsnet, blnet;
1095 1091
1096 1092 /*
1097 1093 * Note that 'have_router', 'have_proxy', 'subnetmask', and 'clnet'
1098 1094 * are static, so that their values (gathered when checking the
1099 1095 * interface configuration) may be used again when checking the boot
1100 1096 * configuration.
1101 1097 */
1102 1098 if (why == CLF_IF) {
1103 1099 /*
1104 1100 * A valid host IP address is an absolute requirement.
1105 1101 */
1106 1102 len = sizeof (buf);
1107 1103 if (bootinfo_get(BI_HOST_IP, buf, &len, NULL) == BI_E_SUCCESS) {
1108 1104 if ((client_ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
1109 1105 info("host-ip invalid!", interactive);
1110 1106 error = B_TRUE;
1111 1107 }
1112 1108 } else {
1113 1109 info("host-ip not set!", interactive);
1114 1110 error = B_TRUE;
1115 1111 }
1116 1112
1117 1113 /*
1118 1114 * If a subnet mask was provided, use it; otherwise infer it.
1119 1115 */
1120 1116 len = sizeof (buf);
1121 1117 if (bootinfo_get(BI_SUBNET_MASK, buf, &len, NULL) ==
1122 1118 BI_E_SUCCESS) {
1123 1119 if ((subnetmask = inet_addr(buf)) == (in_addr_t)-1) {
1124 1120 info("subnet-mask invalid!", interactive);
1125 1121 error = B_TRUE;
1126 1122 }
1127 1123 } else {
1128 1124 info("Defaulting to classful subnetting", interactive);
1129 1125
1130 1126 subnetmask = generate_classful_subnet(client_ipaddr);
1131 1127 }
1132 1128 clnet = client_ipaddr & subnetmask;
1133 1129
1134 1130 /*
1135 1131 * A legal bootserver URL is also an absolute requirement.
1136 1132 */
1137 1133 len = sizeof (buf);
1138 1134 if (bootinfo_get(BI_BOOTSERVER, buf, &len, NULL) ==
1139 1135 BI_E_SUCCESS) {
1140 1136 if (url_parse(buf, &u) != URL_PARSE_SUCCESS ||
1141 1137 u.https ||
1142 1138 (ipaddr = inet_addr(u.hport.hostname)) ==
1143 1139 (in_addr_t)-1) {
1144 1140 info("bootserver not legal URL!", interactive);
1145 1141 error = B_TRUE;
1146 1142 } else {
1147 1143 bsnet = ipaddr & subnetmask;
1148 1144 }
1149 1145 } else {
1150 1146 info("bootserver not specified!", interactive);
1151 1147 error = B_TRUE;
1152 1148 }
1153 1149
1154 1150 /*
1155 1151 * Is there a correctly-defined router?
1156 1152 */
1157 1153 len = sizeof (buf);
1158 1154 if (bootinfo_get(BI_ROUTER_IP, buf, &len, NULL) ==
1159 1155 BI_E_SUCCESS) {
1160 1156 if ((ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
1161 1157 info("router-ip invalid!", interactive);
1162 1158 error = B_TRUE;
1163 1159 } else if (clnet != (ipaddr & subnetmask)) {
1164 1160 info("router not on local subnet!",
1165 1161 interactive);
1166 1162 error = B_TRUE;
1167 1163 } else {
1168 1164 have_router = B_TRUE;
1169 1165 }
1170 1166 }
1171 1167
1172 1168 /*
1173 1169 * Is there a correctly-defined proxy?
1174 1170 */
1175 1171 len = sizeof (buf);
1176 1172 if (bootinfo_get(BI_HTTP_PROXY, buf, &len, NULL) ==
1177 1173 BI_E_SUCCESS) {
1178 1174 url_hport_t u;
1179 1175
1180 1176 if (url_parse_hostport(buf, &u, URL_DFLT_PROXY_PORT) !=
1181 1177 URL_PARSE_SUCCESS ||
1182 1178 (ipaddr = inet_addr(u.hostname)) == (in_addr_t)-1) {
1183 1179 info("http-proxy port invalid!", interactive);
1184 1180 error = B_TRUE;
1185 1181 } else {
1186 1182 /*
1187 1183 * The proxy is only of use to us if it's on
1188 1184 * our local subnet, or if a router has been
1189 1185 * specified (which should hopefully allow us
1190 1186 * to access the proxy).
1191 1187 */
1192 1188 pxnet = ipaddr & subnetmask;
1193 1189 have_proxy = (have_router || pxnet == clnet);
1194 1190 }
1195 1191 }
1196 1192
1197 1193 /*
1198 1194 * If there is no router and no proxy (either on the local
1199 1195 * subnet or reachable via a router), then the bootserver
1200 1196 * URL must be on the local net.
1201 1197 */
1202 1198 if (!error && !have_router && !have_proxy && bsnet != clnet) {
1203 1199 info("bootserver URL not on local subnet",
1204 1200 interactive);
1205 1201 error = B_TRUE;
1206 1202 }
1207 1203 } else {
1208 1204 /*
1209 1205 * There must be a correctly-defined root_server URL.
1210 1206 */
1211 1207 if ((urlstr = bootconf_get(&bc_handle,
1212 1208 BC_ROOT_SERVER)) == NULL) {
1213 1209 info("no root_server URL!", interactive);
1214 1210 error = B_TRUE;
1215 1211 } else if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
1216 1212 info("root_server not legal URL!", interactive);
1217 1213 error = B_TRUE;
1218 1214 } else if ((hp = gethostbyname(u.hport.hostname)) == NULL) {
1219 1215 info("cannot resolve root_server hostname!",
1220 1216 interactive);
1221 1217 error = B_TRUE;
1222 1218 } else {
1223 1219 rsnet = *(in_addr_t *)hp->h_addr & subnetmask;
1224 1220 have_root_server = B_TRUE;
1225 1221 }
1226 1222
1227 1223 /*
1228 1224 * Is there a correctly-defined (non-empty) boot_logger URL?
1229 1225 */
1230 1226 if ((urlstr = bootconf_get(&bc_handle,
1231 1227 BC_BOOT_LOGGER)) != NULL) {
1232 1228 if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
1233 1229 info("boot_logger not legal URL!", interactive);
1234 1230 error = B_TRUE;
1235 1231 } else if ((hp = gethostbyname(u.hport.hostname)) ==
1236 1232 NULL) {
1237 1233 info("cannot resolve boot_logger hostname!",
1238 1234 interactive);
1239 1235 error = B_TRUE;
1240 1236 } else {
1241 1237 blnet = *(in_addr_t *)hp->h_addr & subnetmask;
1242 1238 have_boot_logger = B_TRUE;
1243 1239 }
1244 1240 }
1245 1241
1246 1242 /*
1247 1243 * If there is no router and no proxy (either on the local
1248 1244 * subnet or reachable via a router), then the root_server
1249 1245 * URL (and the boot_logger URL if specified) must be on the
1250 1246 * local net.
1251 1247 */
1252 1248 if (!error && !have_router && !have_proxy) {
1253 1249 if (have_root_server && rsnet != clnet) {
1254 1250 info("root_server URL not on local subnet",
1255 1251 interactive);
1256 1252 error = B_TRUE;
1257 1253 }
1258 1254 if (have_boot_logger && blnet != clnet) {
1259 1255 info("boot_logger URL not on local subnet",
1260 1256 interactive);
1261 1257 error = B_TRUE;
1262 1258 }
1263 1259 }
1264 1260 }
1265 1261
1266 1262 return (error);
1267 1263 }
1268 1264
1269 1265 /*
1270 1266 * Actually setup our network interface with the values derived from the
1271 1267 * PROM, DHCP or interactively from the user.
1272 1268 */
1273 1269 static void
1274 1270 setup_interface()
1275 1271 {
1276 1272 char str[MAXHOSTNAMELEN]; /* will accomodate an IP too */
1277 1273 size_t len;
1278 1274 struct in_addr in_addr;
1279 1275
1280 1276 len = sizeof (str);
1281 1277 if (bootinfo_get(BI_HOST_IP, str, &len, NULL) == BI_E_SUCCESS &&
1282 1278 (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
1283 1279 in_addr.s_addr = htonl(in_addr.s_addr);
1284 1280 ipv4_setipaddr(&in_addr);
1285 1281 }
1286 1282
1287 1283 len = sizeof (str);
1288 1284 if (bootinfo_get(BI_SUBNET_MASK, str, &len, NULL) == BI_E_SUCCESS &&
1289 1285 (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
1290 1286 in_addr.s_addr = htonl(in_addr.s_addr);
1291 1287 ipv4_setnetmask(&in_addr);
1292 1288 }
1293 1289
1294 1290 len = sizeof (str);
1295 1291 if (bootinfo_get(BI_ROUTER_IP, str, &len, NULL) == BI_E_SUCCESS &&
1296 1292 (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
1297 1293 in_addr.s_addr = htonl(in_addr.s_addr);
↓ open down ↓ |
1230 lines elided |
↑ open up ↑ |
1298 1294 ipv4_setdefaultrouter(&in_addr);
1299 1295 (void) ipv4_route(IPV4_ADD_ROUTE, RT_DEFAULT, NULL, &in_addr);
1300 1296 }
1301 1297
1302 1298 len = sizeof (str);
1303 1299 if (bootinfo_get(BI_HOSTNAME, str, &len, NULL) == BI_E_SUCCESS) {
1304 1300 (void) sethostname(str, len);
1305 1301 }
1306 1302 }
1307 1303
1308 -/* EXPORT DELETE END */
1309 1304 boolean_t
1310 1305 wanboot_init_interface(char *boot_arguments)
1311 1306 {
1312 -/* EXPORT DELETE START */
1313 1307 boolean_t interactive;
1314 1308 int which;
1315 1309
1316 1310 #if defined(__sparcv9)
1317 1311 /*
1318 1312 * Get the keys from PROM before we allow the user
1319 1313 * to override them from the CLI.
1320 1314 */
1321 1315 get_prom_encr_keys();
1322 1316 get_prom_hash_keys();
1323 1317 #endif /* defined(__sparcv9) */
1324 1318
1325 1319 /*
1326 1320 * If there is already a bootp-response property under
1327 1321 * /chosen then the PROM must have done DHCP for us;
1328 1322 * invoke dhcp() to 'bind' the interface.
1329 1323 */
1330 1324 if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL, NULL) ==
1331 1325 BI_E_BUF2SMALL) {
1332 1326 (void) cldhcp(NULL, NULL, 0);
1333 1327 }
1334 1328
1335 1329 /*
1336 1330 * Obtain default interface values from bootinfo.
1337 1331 */
1338 1332 bootinfo_defaults(CLF_IF);
1339 1333
1340 1334 /*
1341 1335 * Process the boot arguments (following the "-o" option).
1342 1336 */
1343 1337 if (boot_arguments != NULL) {
1344 1338 (void) cli_eval_buf(boot_arguments,
1345 1339 (CLF_ARG | CLF_IF | CLF_BM));
1346 1340 }
1347 1341
1348 1342 /*
1349 1343 * Stash away any interface/bootmisc parameter values we got
1350 1344 * from either the PROM or the boot arguments.
1351 1345 */
1352 1346 update_bootinfo(CLF_IF | CLF_BM);
1353 1347
1354 1348 /*
1355 1349 * If we don't already have a value for bootserver, try to
1356 1350 * deduce one. Refresh wbcli's idea of these values.
1357 1351 */
1358 1352 determine_bootserver_url();
1359 1353 bootinfo_defaults(CLF_BM);
1360 1354
1361 1355 /*
1362 1356 * Check that the information we have collected thus far is sufficient.
1363 1357 */
1364 1358 interactive = args_specified_prompt;
1365 1359
1366 1360 if (interactive) {
1367 1361 /*
1368 1362 * Drop into the boot interpreter to allow the input
1369 1363 * of keys, bootserver and bootmisc, and in the case
1370 1364 * that net-config-strategy == "manual" the interface
1371 1365 * parameters.
1372 1366 */
1373 1367 which = CLF_BM | CLF_CMD;
1374 1368 if (strcmp(net_config_strategy(), "manual") == 0)
1375 1369 which |= CLF_IF;
1376 1370
1377 1371 do {
1378 1372 cli_interpret(which);
1379 1373 update_bootinfo(CLF_IF | CLF_BM);
1380 1374 } while (config_incomplete(CLF_IF, interactive));
1381 1375 } else {
1382 1376 /*
1383 1377 * The user is not to be given the opportunity to
1384 1378 * enter further values; fail.
1385 1379 */
1386 1380 if (config_incomplete(CLF_IF, interactive)) {
1387 1381 bootlog("wanboot", BOOTLOG_CRIT,
1388 1382 "interface incorrectly configured");
1389 1383 return (B_FALSE);
1390 1384 }
1391 1385 }
1392 1386
1393 1387 /*
1394 1388 * If a wanboot-enabled PROM hasn't processed client-id in
1395 1389 * network-boot-arguments, or no value for client-id has been
1396 1390 * specified to the boot interpreter, then provide a default
1397 1391 * client-id based on our MAC address.
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
1398 1392 */
1399 1393 generate_default_clientid();
1400 1394
1401 1395 /*
1402 1396 * If net-config-strategy == "manual" then we must setup
1403 1397 * the interface now; if "dhcp" then it will already have
1404 1398 * been setup.
1405 1399 */
1406 1400 if (strcmp(net_config_strategy(), "manual") == 0)
1407 1401 setup_interface();
1408 -/* EXPORT DELETE END */
1409 1402 return (B_TRUE);
1410 1403 }
1411 1404
1412 1405 boolean_t
1413 1406 wanboot_verify_config(void)
1414 1407 {
1415 -/* EXPORT DELETE START */
1416 1408 /*
1417 1409 * Check that the wanboot.conf file defines a valid root_server
1418 1410 * URL, and check that, if given, the boot_logger URL is valid.
1419 1411 */
1420 1412 if (config_incomplete(0, B_FALSE)) {
1421 1413 bootlog("wanboot", BOOTLOG_CRIT,
1422 1414 "incomplete boot configuration");
1423 1415 return (B_FALSE);
1424 1416 }
1425 -/* EXPORT DELETE END */
1426 1417 return (B_TRUE);
1427 1418 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX