Print this page
Re-enable commented-out lxinit code, as a prelude to
enabling zonecfg(1M)-property networking configuration for LX.
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/brand/lx/lx_init/lxinit.c
+++ new/usr/src/lib/brand/lx/lx_init/lxinit.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]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2015 Joyent, Inc.
24 24 */
25 25
26 26 /*
27 27 * lxinit performs zone-specific initialization prior to handing control to the
28 28 * guest Linux init. This primarily consists of:
29 29 *
30 30 * - Starting ipmgmtd
31 31 * - Configuring network interfaces
32 32 * - Adding a default route
33 33 */
34 34
35 35 #include <ctype.h>
36 36 #include <errno.h>
37 37 #include <fcntl.h>
38 38 #include <libgen.h>
39 39 #include <limits.h>
40 40 #include <net/if.h>
41 41 #include <stdarg.h>
42 42 #include <stdio.h>
43 43 #include <stdlib.h>
44 44 #include <string.h>
45 45 #include <strings.h>
46 46 #include <stropts.h>
47 47 #include <sys/ioccom.h>
48 48 #include <sys/stat.h>
49 49 #include <sys/systeminfo.h>
50 50 #include <sys/sockio.h>
51 51 #include <sys/types.h>
52 52 #include <sys/wait.h>
53 53 #include <sys/varargs.h>
54 54 #include <unistd.h>
55 55 #include <libintl.h>
56 56 #include <locale.h>
57 57 #include <libcmdutils.h>
58 58
59 59 #include <netinet/dhcp.h>
60 60 #include <dhcpagent_util.h>
61 61 #include <dhcpagent_ipc.h>
62 62
63 63 #include <arpa/inet.h>
64 64 #include <net/route.h>
65 65 #include <libipadm.h>
66 66 #include <libzonecfg.h>
67 67 #include <libinetutil.h>
68 68 #include <sys/lx_brand.h>
69 69
70 70 #include "run_command.h"
71 71
72 72 static void lxi_err(char *msg, ...) __NORETURN;
73 73 static void lxi_err(char *msg, ...);
74 74
75 75 #define IPMGMTD_PATH "/lib/inet/ipmgmtd"
76 76 #define IN_NDPD_PATH "/usr/lib/inet/in.ndpd"
77 77
78 78 #define PREFIX_LOG_WARN "lx_init warn: "
79 79 #define PREFIX_LOG_ERR "lx_init err: "
80 80
81 81 #define RTMBUFSZ (sizeof (struct rt_msghdr) + \
82 82 (3 * sizeof (struct sockaddr_in)))
83 83
84 84 ipadm_handle_t iph;
85 85
86 86 static void
87 87 lxi_err(char *msg, ...)
88 88 {
89 89 char buf[1024];
90 90 int len;
91 91 va_list ap;
92 92
93 93 va_start(ap, msg);
94 94 /*LINTED*/
95 95 len = vsnprintf(buf, sizeof (buf), msg, ap);
96 96 va_end(ap);
97 97
98 98 (void) write(1, PREFIX_LOG_ERR, strlen(PREFIX_LOG_ERR));
99 99 (void) write(1, buf, len);
100 100 (void) write(1, "\n", 1);
101 101
102 102 /*
103 103 * Since a non-zero exit will cause the zone to reboot, a pause here
104 104 * will prevent a mis-configured zone from spinning in a reboot loop.
105 105 */
106 106 (void) pause();
107 107 exit(1);
108 108 /*NOTREACHED*/
109 109 }
110 110
111 111 static void
112 112 lxi_warn(char *msg, ...)
113 113 {
114 114 char buf[1024];
115 115 int len;
116 116 va_list ap;
117 117
118 118 va_start(ap, msg);
119 119 /*LINTED*/
120 120 len = vsnprintf(buf, sizeof (buf), msg, ap);
121 121 va_end(ap);
122 122
123 123 (void) write(1, PREFIX_LOG_WARN, strlen(PREFIX_LOG_WARN));
124 124 (void) write(1, buf, len);
125 125 (void) write(1, "\n", 1);
126 126 }
127 127
128 128 static void
129 129 lxi_log_open()
130 130 {
131 131 int fd = open("/dev/console", O_WRONLY);
132 132
133 133 if (fd < 0) {
134 134 /* hard to log at this point... */
135 135 exit(1);
136 136 } else if (fd != 1) {
137 137 /*
138 138 * Use stdout as the log fd. Init should start with no files
139 139 * open, so we should be required to perform this relocation
140 140 * every time.
141 141 */
142 142 if (dup2(fd, 1) != 1) {
143 143 exit(1);
144 144 }
145 145 }
146 146 }
147 147
148 148 static void
149 149 lxi_log_close()
150 150 {
151 151 (void) close(0);
152 152 (void) close(1);
153 153 }
154 154
155 155 static zone_dochandle_t
156 156 lxi_config_open()
157 157 {
158 158 zoneid_t zoneid;
159 159 char zonename[ZONENAME_MAX];
160 160 zone_dochandle_t handle;
161 161 zone_iptype_t iptype;
162 162 int res;
163 163
164 164 zoneid = getzoneid();
165 165 if (getzonenamebyid(zoneid, zonename, sizeof (zonename)) < 0) {
166 166 lxi_err("could not determine zone name");
167 167 }
168 168
169 169 if ((handle = zonecfg_init_handle()) == NULL)
170 170 lxi_err("internal libzonecfg.so.1 error", 0);
171 171
172 172 if ((res = zonecfg_get_handle(zonename, handle)) != Z_OK) {
173 173 zonecfg_fini_handle(handle);
174 174 lxi_err("could not locate zone config %d", res);
175 175 }
176 176
177 177 /*
178 178 * Only exclusive stack is supported.
179 179 */
|
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
180 180 if (zonecfg_get_iptype(handle, &iptype) != Z_OK ||
181 181 iptype != ZS_EXCLUSIVE) {
182 182 zonecfg_fini_handle(handle);
183 183 lxi_err("lx zones do not support shared IP stacks");
184 184 }
185 185
186 186 return (handle);
187 187
188 188 }
189 189
190 -#if 0 /* XXX KEBE SAYS NOT YET */
191 190 static int
192 191 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
193 192 const char **result)
194 193 {
195 194 while (attrs != NULL) {
196 195 if (strncmp(attrs->zone_res_attr_name, name,
197 196 MAXNAMELEN) == 0) {
198 197 *result = attrs->zone_res_attr_value;
199 198 return (0);
200 199 }
201 200 attrs = attrs->zone_res_attr_next;
202 201 }
203 202 return (-1);
204 203 }
205 -#endif /* XXX KEBE SAYS NOT YET */
206 204
207 205 static void
208 206 lxi_svc_start(char *name, char *path, char *fmri)
209 207 {
210 208 pid_t pid;
211 209 int status;
212 210 char *argv[] = {
213 211 NULL,
214 212 NULL
215 213 };
216 214 char *envp[] = {
217 215 NULL,
218 216 NULL
219 217 };
220 218 argv[0] = name;
221 219 envp[0] = fmri;
222 220
223 221 pid = fork();
224 222 if (pid == -1) {
225 223 lxi_err("fork() failed: %s", strerror(errno));
226 224 }
227 225
228 226 if (pid == 0) {
229 227 /* child */
230 228 const char *zroot = zone_get_nroot();
231 229 char cmd[MAXPATHLEN];
232 230
233 231 /*
234 232 * Construct the full path to the binary, including the native
235 233 * system root (e.g. "/native") if in use for this zone:
236 234 */
237 235 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot != NULL ?
238 236 zroot : "", path);
239 237
240 238 (void) execve(cmd, argv, envp);
241 239
242 240 lxi_err("execve(%s) failed: %s", cmd, strerror(errno));
243 241 /* NOTREACHED */
244 242 }
245 243
246 244 /* parent */
247 245 while (wait(&status) != pid)
248 246 ;
249 247
250 248 if (WIFEXITED(status)) {
251 249 if (WEXITSTATUS(status) != 0) {
252 250 lxi_err("%s[%d] exited: %d", name,
253 251 (int)pid, WEXITSTATUS(status));
254 252 }
255 253 } else if (WIFSIGNALED(status)) {
256 254 lxi_err("%s[%d] died on signal: %d", name,
257 255 (int)pid, WTERMSIG(status));
258 256 } else {
259 257 lxi_err("%s[%d] failed in unknown way", name,
260 258 (int)pid);
261 259 }
262 260 }
263 261
264 262 void
265 263 lxi_net_ipmgmtd_start()
266 264 {
267 265 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
268 266 "SMF_FMRI=svc:/network/ip-interface-management:default");
269 267 }
270 268
271 269 void
272 270 lxi_net_ndpd_start()
273 271 {
274 272 lxi_svc_start("in.ndpd", IN_NDPD_PATH,
275 273 "SMF_FMRI=svc:/network/routing/ndp:default");
276 274 }
277 275
278 276
279 277 static void
280 278 lxi_net_ipadm_open()
281 279 {
282 280 ipadm_status_t status;
283 281
284 282 if ((status = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS) {
285 283 lxi_err("Error opening ipadm handle: %s",
286 284 ipadm_status2str(status));
287 285 }
288 286 }
289 287
290 288 static void
291 289 lxi_net_ipadm_close()
292 290 {
293 291 ipadm_close(iph);
294 292 }
295 293
296 294 void
297 295 lxi_net_plumb(const char *iface)
298 296 {
299 297 ipadm_status_t status;
300 298 char ifbuf[LIFNAMSIZ];
301 299
302 300 /* ipadm_create_if stomps on ifbuf, so create a copy: */
303 301 (void) strncpy(ifbuf, iface, sizeof (ifbuf));
304 302
305 303 if ((status = ipadm_create_if(iph, ifbuf, AF_INET, IPADM_OPT_ACTIVE))
306 304 != IPADM_SUCCESS) {
307 305 lxi_err("ipadm_create_if error %d: %s/v4: %s",
308 306 status, iface, ipadm_status2str(status));
309 307 }
310 308
311 309 if ((status = ipadm_create_if(iph, ifbuf, AF_INET6, IPADM_OPT_ACTIVE))
312 310 != IPADM_SUCCESS) {
313 311 lxi_err("ipadm_create_if error %d: %s/v6: %s",
314 312 status, iface, ipadm_status2str(status));
315 313 }
316 314 }
317 315
318 316 static int
319 317 lxi_getif(int af, char *iface, int len, boolean_t first_ipv4_configured)
320 318 {
321 319 struct lifreq lifr;
322 320 int s = socket(af, SOCK_DGRAM, 0);
323 321 if (s < 0) {
324 322 lxi_warn("socket error %d: bringing up %s: %s",
325 323 errno, iface, strerror(errno));
326 324 return (-1);
327 325 }
328 326
329 327 /*
330 328 * We need a new logical interface for every IP address we add, except
331 329 * for the very first IPv4 address.
332 330 */
333 331 if (af == AF_INET6 || first_ipv4_configured) {
334 332 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
335 333 (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
336 334 if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
337 335 if (close(s) != 0) {
338 336 lxi_warn("failed to close socket: %s\n",
339 337 strerror(errno));
340 338 }
341 339 return (-1);
342 340 }
343 341 (void) strncpy(iface, lifr.lifr_name, len);
344 342 }
345 343
346 344 if (close(s) != 0) {
347 345 lxi_warn("failed to close socket: %s\n",
348 346 strerror(errno));
349 347 }
350 348 return (0);
351 349 }
352 350
353 351 static int
354 352 lxi_iface_ip(const char *origiface, const char *addr,
355 353 boolean_t *first_ipv4_configured)
356 354 {
357 355 static int addrnum = 0;
358 356 ipadm_status_t status;
359 357 ipadm_addrobj_t ipaddr = NULL;
360 358 char iface[LIFNAMSIZ];
361 359 char aobjname[IPADM_AOBJSIZ];
362 360 int af, err = 0;
363 361
364 362 (void) strncpy(iface, origiface, sizeof (iface));
365 363
366 364 af = strstr(addr, ":") == NULL ? AF_INET : AF_INET6;
367 365 if (lxi_getif(af, iface, sizeof (iface), *first_ipv4_configured) != 0) {
368 366 lxi_warn("failed to create new logical interface "
369 367 "on %s: %s", origiface, strerror(errno));
370 368 return (-1);
371 369 }
372 370
373 371 (void) snprintf(aobjname, IPADM_AOBJSIZ, "%s/addr%d", iface,
374 372 addrnum++);
375 373
376 374 if ((status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname,
377 375 &ipaddr)) != IPADM_SUCCESS) {
378 376 lxi_warn("ipadm_create_addrobj error %d: addr %s, "
379 377 "interface %s: %s\n", status, addr, iface,
380 378 ipadm_status2str(status));
381 379 return (-2);
382 380 }
383 381
384 382 if ((status = ipadm_set_addr(ipaddr, addr, AF_UNSPEC))
385 383 != IPADM_SUCCESS) {
386 384 lxi_warn("ipadm_set_addr error %d: addr %s"
387 385 ", interface %s: %s\n", status, addr,
388 386 iface, ipadm_status2str(status));
389 387 err = -3;
390 388 goto done;
391 389 }
392 390
393 391 if ((status = ipadm_create_addr(iph, ipaddr,
394 392 IPADM_OPT_ACTIVE | IPADM_OPT_UP)) != IPADM_SUCCESS) {
395 393 lxi_warn("ipadm_create_addr error for %s: %s\n", iface,
396 394 ipadm_status2str(status));
397 395 err = -4;
398 396 goto done;
399 397 }
|
↓ open down ↓ |
184 lines elided |
↑ open up ↑ |
400 398
401 399 if (af == AF_INET) {
402 400 *first_ipv4_configured = B_TRUE;
403 401 }
404 402
405 403 done:
406 404 ipadm_destroy_addrobj(ipaddr);
407 405 return (err);
408 406 }
409 407
410 -#if 0 /* XXX KEBE SAYS NOT YET */
411 408 static int
412 409 lxi_iface_dhcp(const char *origiface, boolean_t *first_ipv4_configured)
413 410 {
414 411 dhcp_ipc_request_t *dhcpreq = NULL;
415 412 dhcp_ipc_reply_t *dhcpreply = NULL;
416 413 int err = 0, timeout = 5;
417 414 char iface[LIFNAMSIZ];
418 415
419 416 (void) strncpy(iface, origiface, sizeof (iface));
420 417
421 418 if (lxi_getif(AF_INET, iface, sizeof (iface), *first_ipv4_configured)
422 419 != 0) {
423 420 lxi_warn("failed to create new logical interface "
424 421 "on %s: %s", origiface, strerror(errno));
425 422 return (-1);
426 423 }
427 424
428 425 if (dhcp_start_agent(timeout) != 0) {
429 426 lxi_err("Failed to start dhcpagent\n");
430 427 /* NOTREACHED */
431 428 }
432 429
433 430 dhcpreq = dhcp_ipc_alloc_request(DHCP_START, iface,
434 431 NULL, 0, DHCP_TYPE_NONE);
435 432 if (dhcpreq == NULL) {
436 433 lxi_warn("Unable to allocate memory "
437 434 "to start DHCP on %s\n", iface);
438 435 return (-1);
439 436 }
440 437
441 438 err = dhcp_ipc_make_request(dhcpreq, &dhcpreply, timeout);
442 439 if (err != 0) {
443 440 free(dhcpreq);
444 441 lxi_warn("Failed to start DHCP on %s: %s\n", iface,
445 442 dhcp_ipc_strerror(err));
446 443 return (-1);
447 444 }
448 445 err = dhcpreply->return_code;
449 446 if (err != 0) {
450 447 lxi_warn("Failed to start DHCP on %s: %s\n", iface,
451 448 dhcp_ipc_strerror(err));
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
452 449 goto done;
453 450 }
454 451
455 452 *first_ipv4_configured = B_TRUE;
456 453
457 454 done:
458 455 free(dhcpreq);
459 456 free(dhcpreply);
460 457 return (err);
461 458 }
462 -#endif /* XXX KEBE SAYS NOT YET */
463 459
464 460 /*
465 461 * Initialize an IPv6 link-local address on a given interface
466 462 */
467 463 static int
468 464 lxi_iface_ipv6_link_local(const char *iface)
469 465 {
470 466 struct lifreq lifr;
471 467 int s;
472 468
473 469 s = socket(AF_INET6, SOCK_DGRAM, 0);
474 470 if (s == -1) {
475 471 lxi_warn("socket error %d: bringing up %s: %s",
476 472 errno, iface, strerror(errno));
477 473 }
478 474
479 475 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
480 476 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
481 477 lxi_warn("SIOCGLIFFLAGS error %d: bringing up %s: %s",
482 478 errno, iface, strerror(errno));
483 479 return (-1);
484 480 }
485 481
486 482 lifr.lifr_flags |= IFF_UP;
487 483 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
488 484 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
489 485 errno, iface, strerror(errno));
490 486 return (-1);
491 487 }
492 488
493 489 (void) close(s);
494 490 return (0);
495 491 }
496 492
497 493 static int
498 494 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
499 495 const char *gwaddr)
500 496 {
501 497 int idx, len, sockfd;
502 498 /* For lint-happy alignment, use a uint32_t array... */
503 499 uint32_t rtbuf[RTMBUFSZ / sizeof (uint32_t)];
504 500 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
505 501 struct sockaddr_in *dst_sin = (struct sockaddr_in *)(rtm + 1);
506 502 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
507 503 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
508 504
509 505 (void) bzero(rtm, RTMBUFSZ);
510 506 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
511 507 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
512 508 rtm->rtm_msglen = sizeof (rtbuf);
513 509 rtm->rtm_pid = getpid();
514 510 rtm->rtm_type = RTM_ADD;
515 511 rtm->rtm_version = RTM_VERSION;
516 512
517 513
518 514 /*
519 515 * The destination and netmask components have already been zeroed,
520 516 * which represents the default gateway. If we were passed a more
521 517 * specific destination network, use that instead.
522 518 */
523 519 dst_sin->sin_family = AF_INET;
524 520 netmask_sin->sin_family = AF_INET;
525 521 if (dst != NULL) {
526 522 struct sockaddr *mask = (struct sockaddr *)netmask_sin;
527 523
528 524 if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
529 525 plen2mask(dstpfx, AF_INET, mask) != 0) {
530 526 lxi_warn("bad destination network %s/%d: %s", dst,
531 527 dstpfx, strerror(errno));
532 528 return (-1);
533 529 }
534 530 }
535 531
536 532 if ((inet_pton(AF_INET, gwaddr, &(gw_sin->sin_addr))) != 1) {
537 533 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
538 534 return (-1);
539 535 }
540 536
541 537 if (iface != NULL) {
542 538 if ((idx = if_nametoindex(iface)) == 0) {
543 539 lxi_warn("unable to get interface index for %s: %s\n",
544 540 iface, strerror(errno));
545 541 return (-1);
546 542 }
547 543 rtm->rtm_index = idx;
548 544 }
549 545
550 546 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
551 547 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
552 548 return (-1);
553 549 }
554 550
555 551 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
556 552 lxi_warn("could not write rtmsg: %s", strerror(errno));
557 553 (void) close(sockfd);
558 554 return (-1);
559 555 } else if (len < rtm->rtm_msglen) {
560 556 lxi_warn("write() rtmsg incomplete");
561 557 (void) close(sockfd);
562 558 return (-1);
563 559 }
564 560
565 561 (void) close(sockfd);
566 562 return (0);
567 563 }
568 564
569 565 static void
|
↓ open down ↓ |
97 lines elided |
↑ open up ↑ |
570 566 lxi_net_loopback()
571 567 {
572 568 const char *iface = "lo0";
573 569 boolean_t first_ipv4_configured = B_FALSE;
574 570
575 571 lxi_net_plumb(iface);
576 572 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
577 573 (void) lxi_iface_ipv6_link_local(iface);
578 574 }
579 575
580 -
581 -
582 -#if 0 /* XXX KEBE SAYS NOT YET */
583 -/*
584 - * This function is used when the "ips" property doesn't exist in a zone's
585 - * configuration. It may be an older configuration, so we should search for
586 - * "ip" and "netmask" and convert them into the new format.
587 - */
588 -static int
589 -lxi_get_old_ip(struct zone_res_attrtab *attrs, const char **ipaddrs,
590 - char *cidraddr, int len)
591 -{
592 -
593 - const char *netmask;
594 - int prefixlen;
595 - struct sockaddr_in mask_sin;
596 -
597 - lxi_warn("Could not find \"ips\" property for zone. Looking "
598 - "for older \"ip\" and \"netmask\" properties, instead.");
599 -
600 - if (zone_find_attr(attrs, "ip", ipaddrs) != 0) {
601 - return (-1);
602 - }
603 -
604 - if (strcmp(*ipaddrs, "dhcp") == 0) {
605 - return (0);
606 - }
607 -
608 - if (zone_find_attr(attrs, "netmask", &netmask) != 0) {
609 - lxi_err("could not find netmask for interface");
610 - /* NOTREACHED */
611 - }
612 -
613 - /* Convert the netmask to a number */
614 - mask_sin.sin_family = AF_INET;
615 - if (inet_pton(AF_INET, netmask, &mask_sin.sin_addr) != 1) {
616 - lxi_err("invalid netmask address: %s\n",
617 - strerror(errno));
618 - /* NOTREACHED */
619 - }
620 - prefixlen = mask2plen((struct sockaddr *)&mask_sin);
621 -
622 - /*
623 - * Write out the IP address in the new format and use
624 - * that instead
625 - */
626 - (void) snprintf(cidraddr, len, "%s/%d", *ipaddrs, prefixlen);
627 -
628 - *ipaddrs = cidraddr;
629 - return (0);
630 -}
631 -#endif /* XXX KEBE SAYS NOT YET */
632 -
633 576 static void
634 577 lxi_net_setup(zone_dochandle_t handle)
635 578 {
636 579 struct zone_nwiftab lookup;
637 580 boolean_t do_addrconf = B_FALSE;
638 581
639 582 if (zonecfg_setnwifent(handle) != Z_OK)
640 583 return;
641 584 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
642 585 const char *iface = lookup.zone_nwif_physical;
643 -#if 0 /* XXX KEBE SAYS NOT YET */
644 586 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
645 587 const char *ipaddrs, *primary, *gateway;
646 - char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
588 + char ipaddrs_copy[MAXNAMELEN], /* cidraddr[BUFSIZ], */
647 589 *ipaddr, *tmp, *lasts;
648 590 boolean_t first_ipv4_configured = B_FALSE;
649 591 boolean_t *ficp = &first_ipv4_configured;
650 -#endif /* XXX KEBE */
592 + boolean_t no_zonecfg;
651 593
594 + /*
595 + * Regardless of whether we're configured in zonecfg(1M), or
596 + * configured by other means, make sure we plumb every
597 + * physical=<foo> for IPv4 and IPv6.
598 + */
652 599 lxi_net_plumb(iface);
653 600
654 - /* XXX KEBE SAYS this bit was shuffled around. */
601 + if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 /* &&
602 + lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0*/) {
603 + /*
604 + * Do not panic. This interface has no in-zonecfg(1M)
605 + * configuration. We keep a warning around.
606 + */
607 + lxi_warn("Could not find zonecfg(1M) network "
608 + "configuration for the %s interface", iface);
609 + no_zonecfg = B_TRUE;
610 + } else {
611 + no_zonecfg = B_FALSE;
612 + }
613 +
655 614 if (lxi_iface_ipv6_link_local(iface) != 0) {
656 615 lxi_warn("unable to bring up link-local address on "
657 616 "interface %s", iface);
658 - } else {
659 - /* XXX KEBE SAYS this bit is new. */
660 - do_addrconf = B_TRUE;
661 617 }
662 618
663 -#if 0 /* XXX KEBE SAYS NOT YET */
664 - if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
665 - lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
666 - lxi_warn("Could not find a valid network configuration "
667 - "for the %s interface", iface);
619 + /*
620 + * Every thing else below only happens if we have zonecfg(1M)
621 + * network configuration.
622 + */
623 + if (no_zonecfg)
668 624 continue;
669 - }
670 625
671 626 /*
672 - * If we're going to be doing DHCP, we have to do it first since
673 - * dhcpagent doesn't like to operate on non-zero logical
627 + * If we're going to be doing DHCP, we have to do it first
628 + * since dhcpagent doesn't like to operate on non-zero logical
674 629 * interfaces.
675 630 */
676 631 if (strstr(ipaddrs, "dhcp") != NULL &&
677 632 lxi_iface_dhcp(iface, ficp) != 0) {
678 633 lxi_warn("Failed to start DHCP on %s\n", iface);
679 634 }
680 635
681 636 /*
682 637 * Copy the ipaddrs string, since strtok_r will write NUL
683 638 * characters into it.
684 639 */
685 640 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
686 641 tmp = ipaddrs_copy;
687 642
688 643 /*
689 644 * Iterate over each IP and then set it up on the interface.
690 645 */
691 646 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
692 647 tmp = NULL;
693 648 if (strcmp(ipaddr, "addrconf") == 0) {
694 649 do_addrconf = B_TRUE;
695 650 } else if (strcmp(ipaddr, "dhcp") == 0) {
696 651 continue;
697 652 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
698 653 lxi_warn("Unable to add new IP address (%s) "
699 654 "to interface %s", ipaddr, iface);
700 655 }
701 656 }
702 657
703 658 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
704 659 strncmp(primary, "true", MAXNAMELEN) == 0 &&
705 660 zone_find_attr(attrs, "gateway", &gateway) == 0) {
706 661 lxi_iface_gateway(iface, NULL, 0, gateway);
707 662 }
708 -#endif /* XXX KEBE */
709 663 }
710 664
711 665 if (do_addrconf) {
712 666 lxi_net_ndpd_start();
713 667 }
714 668
715 669 (void) zonecfg_endnwifent(handle);
716 670 }
717 671
718 672 static void
719 673 lxi_net_static_route(const char *line)
720 674 {
721 675 /*
722 676 * Each static route line is a string of the form:
723 677 *
724 678 * "10.77.77.2|10.1.1.0/24|false"
725 679 *
726 680 * i.e. gateway address, destination network, and whether this is
727 681 * a "link local" route or a next hop route.
728 682 */
729 683 custr_t *cu = NULL;
730 684 char *gw = NULL, *dst = NULL;
731 685 int pfx = -1;
732 686 int i;
733 687
734 688 if (custr_alloc(&cu) != 0) {
735 689 lxi_err("custr_alloc failure");
736 690 }
737 691
738 692 for (i = 0; line[i] != '\0'; i++) {
739 693 if (gw == NULL) {
740 694 if (line[i] == '|') {
741 695 if ((gw = strdup(custr_cstr(cu))) == NULL) {
742 696 lxi_err("strdup failure");
743 697 }
744 698 custr_reset(cu);
745 699 } else {
746 700 if (custr_appendc(cu, line[i]) != 0) {
747 701 lxi_err("custr_appendc failure");
748 702 }
749 703 }
750 704 continue;
751 705 }
752 706
753 707 if (dst == NULL) {
754 708 if (line[i] == '/') {
755 709 if ((dst = strdup(custr_cstr(cu))) == NULL) {
756 710 lxi_err("strdup failure");
757 711 }
758 712 custr_reset(cu);
759 713 } else {
760 714 if (custr_appendc(cu, line[i]) != 0) {
761 715 lxi_err("custr_appendc failure");
762 716 }
763 717 }
764 718 continue;
765 719 }
766 720
767 721 if (pfx == -1) {
768 722 if (line[i] == '|') {
769 723 pfx = atoi(custr_cstr(cu));
770 724 custr_reset(cu);
771 725 } else {
772 726 if (custr_appendc(cu, line[i]) != 0) {
773 727 lxi_err("custr_appendc failure");
774 728 }
775 729 }
776 730 continue;
777 731 }
778 732
779 733 if (custr_appendc(cu, line[i]) != 0) {
780 734 lxi_err("custr_appendc failure");
781 735 }
782 736 }
783 737
784 738 /*
785 739 * We currently only support "next hop" routes, so ensure that
786 740 * "linklocal" is false:
787 741 */
788 742 if (strcmp(custr_cstr(cu), "false") != 0) {
789 743 lxi_warn("invalid static route: %s", line);
790 744 }
791 745
792 746 if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
793 747 lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
794 748 }
795 749
796 750 custr_free(cu);
797 751 free(gw);
798 752 free(dst);
799 753 }
800 754
801 755 static void
802 756 lxi_net_static_routes(void)
803 757 {
804 758 const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
805 759 char *const argv[] = { "routeinfo", NULL };
806 760 char *const envp[] = { NULL };
807 761 int code;
808 762 struct stat st;
809 763 char errbuf[512];
810 764
811 765 if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
812 766 /*
813 767 * This binary is (potentially) shipped from another
814 768 * consolidation. If it does not exist, then the platform does
815 769 * not currently support static routes for LX-branded zones.
816 770 */
817 771 return;
818 772 }
819 773
820 774 /*
821 775 * Run the command, firing the callback for each line that it
822 776 * outputs. When this function returns, static route processing
823 777 * is complete.
824 778 */
825 779 if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
826 780 lxi_net_static_route, &code) != 0 || code != 0) {
827 781 lxi_err("failed to run \"%s\": %s", cmd, errbuf);
828 782 }
829 783 }
830 784
831 785 static void
832 786 lxi_config_close(zone_dochandle_t handle)
833 787 {
834 788 zonecfg_fini_handle(handle);
835 789 }
836 790
837 791 static void
838 792 lxi_init_exec(char **argv)
839 793 {
840 794 const char *cmd = "/sbin/init";
841 795 char *const envp[] = { "container=zone", NULL };
842 796 int e;
843 797
844 798 argv[0] = "init";
845 799
846 800 /*
847 801 * systemd uses the 'container' env var to determine it is running
848 802 * inside a container. It only supports a few well-known types and
849 803 * treats anything else as 'other' but this is enough to make it
850 804 * behave better inside a zone. See 'detect_container' in systemd.
851 805 */
852 806 (void) execve(cmd, argv, envp);
853 807 e = errno;
854 808
855 809 /*
856 810 * Because stdout was closed prior to exec, it must be opened again in
857 811 * the face of failure to log the error.
858 812 */
859 813 lxi_log_open();
860 814 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
861 815 }
862 816
863 817 /*ARGSUSED*/
864 818 int
865 819 main(int argc, char *argv[])
866 820 {
867 821 zone_dochandle_t handle;
868 822
869 823 lxi_log_open();
870 824
871 825 lxi_net_ipmgmtd_start();
872 826 lxi_net_ipadm_open();
873 827
874 828 handle = lxi_config_open();
875 829 lxi_net_loopback();
876 830 lxi_net_setup(handle);
877 831 lxi_config_close(handle);
878 832
879 833 lxi_net_static_routes();
880 834
881 835 lxi_net_ipadm_close();
882 836
883 837 lxi_log_close();
884 838
885 839 lxi_init_exec(argv);
886 840
887 841 /* NOTREACHED */
888 842 return (0);
889 843 }
|
↓ open down ↓ |
171 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX