Print this page
Reduce lint
| 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);
|
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
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 - pause();
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 */
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 190 #if 0 /* XXX KEBE SAYS NOT YET */
191 191 static int
192 192 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
193 193 const char **result)
194 194 {
195 195 while (attrs != NULL) {
196 196 if (strncmp(attrs->zone_res_attr_name, name,
|
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
197 197 MAXNAMELEN) == 0) {
198 198 *result = attrs->zone_res_attr_value;
199 199 return (0);
200 200 }
201 201 attrs = attrs->zone_res_attr_next;
202 202 }
203 203 return (-1);
204 204 }
205 205 #endif /* XXX KEBE SAYS NOT YET */
206 206
207 -void
207 +static void
208 208 lxi_svc_start(char *name, char *path, char *fmri)
209 209 {
210 210 pid_t pid;
211 211 int status;
212 - char *const argv[] = {
213 - name,
212 + char *argv[] = {
213 + NULL,
214 214 NULL
215 215 };
216 - char *const envp[] = {
217 - fmri,
216 + char *envp[] = {
217 + NULL,
218 218 NULL
219 219 };
220 + argv[0] = name;
221 + envp[0] = fmri;
220 222
221 223 pid = fork();
222 224 if (pid == -1) {
223 225 lxi_err("fork() failed: %s", strerror(errno));
224 226 }
225 227
226 228 if (pid == 0) {
227 229 /* child */
228 230 const char *zroot = zone_get_nroot();
229 231 char cmd[MAXPATHLEN];
230 232
231 233 /*
232 234 * Construct the full path to the binary, including the native
233 235 * system root (e.g. "/native") if in use for this zone:
234 236 */
235 237 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot != NULL ?
236 238 zroot : "", path);
237 239
238 - execve(cmd, argv, envp);
240 + (void) execve(cmd, argv, envp);
239 241
240 242 lxi_err("execve(%s) failed: %s", cmd, strerror(errno));
241 243 /* NOTREACHED */
242 244 }
243 245
244 246 /* parent */
245 - while (wait(&status) != pid) {
246 - /* EMPTY */;
247 - }
247 + while (wait(&status) != pid)
248 + ;
248 249
249 250 if (WIFEXITED(status)) {
250 251 if (WEXITSTATUS(status) != 0) {
251 252 lxi_err("%s[%d] exited: %d", name,
252 253 (int)pid, WEXITSTATUS(status));
253 254 }
254 255 } else if (WIFSIGNALED(status)) {
255 256 lxi_err("%s[%d] died on signal: %d", name,
256 257 (int)pid, WTERMSIG(status));
257 258 } else {
258 259 lxi_err("%s[%d] failed in unknown way", name,
259 260 (int)pid);
260 261 }
261 262 }
262 263
263 264 void
264 265 lxi_net_ipmgmtd_start()
265 266 {
266 267 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
267 268 "SMF_FMRI=svc:/network/ip-interface-management:default");
268 269 }
269 270
270 271 void
271 272 lxi_net_ndpd_start()
272 273 {
273 274 lxi_svc_start("in.ndpd", IN_NDPD_PATH,
274 275 "SMF_FMRI=svc:/network/routing/ndp:default");
275 276 }
276 277
277 278
278 279 static void
279 280 lxi_net_ipadm_open()
280 281 {
281 282 ipadm_status_t status;
282 283
283 284 if ((status = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS) {
284 285 lxi_err("Error opening ipadm handle: %s",
285 286 ipadm_status2str(status));
286 287 }
287 288 }
288 289
289 290 static void
290 291 lxi_net_ipadm_close()
291 292 {
292 293 ipadm_close(iph);
293 294 }
294 295
295 296 void
296 297 lxi_net_plumb(const char *iface)
297 298 {
298 299 ipadm_status_t status;
299 300 char ifbuf[LIFNAMSIZ];
300 301
301 302 /* ipadm_create_if stomps on ifbuf, so create a copy: */
302 303 (void) strncpy(ifbuf, iface, sizeof (ifbuf));
303 304
304 305 if ((status = ipadm_create_if(iph, ifbuf, AF_INET, IPADM_OPT_ACTIVE))
305 306 != IPADM_SUCCESS) {
306 307 lxi_err("ipadm_create_if error %d: %s/v4: %s",
307 308 status, iface, ipadm_status2str(status));
308 309 }
309 310
310 311 if ((status = ipadm_create_if(iph, ifbuf, AF_INET6, IPADM_OPT_ACTIVE))
311 312 != IPADM_SUCCESS) {
312 313 lxi_err("ipadm_create_if error %d: %s/v6: %s",
313 314 status, iface, ipadm_status2str(status));
314 315 }
315 316 }
316 317
317 318 static int
318 319 lxi_getif(int af, char *iface, int len, boolean_t first_ipv4_configured)
319 320 {
320 321 struct lifreq lifr;
321 322 int s = socket(af, SOCK_DGRAM, 0);
322 323 if (s < 0) {
323 324 lxi_warn("socket error %d: bringing up %s: %s",
324 325 errno, iface, strerror(errno));
325 326 return (-1);
326 327 }
327 328
328 329 /*
329 330 * We need a new logical interface for every IP address we add, except
330 331 * for the very first IPv4 address.
331 332 */
332 333 if (af == AF_INET6 || first_ipv4_configured) {
333 334 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
334 335 (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
335 336 if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
336 337 if (close(s) != 0) {
337 338 lxi_warn("failed to close socket: %s\n",
338 339 strerror(errno));
339 340 }
340 341 return (-1);
341 342 }
342 343 (void) strncpy(iface, lifr.lifr_name, len);
343 344 }
344 345
345 346 if (close(s) != 0) {
346 347 lxi_warn("failed to close socket: %s\n",
347 348 strerror(errno));
348 349 }
349 350 return (0);
350 351 }
351 352
352 353 static int
353 354 lxi_iface_ip(const char *origiface, const char *addr,
354 355 boolean_t *first_ipv4_configured)
355 356 {
356 357 static int addrnum = 0;
357 358 ipadm_status_t status;
358 359 ipadm_addrobj_t ipaddr = NULL;
359 360 char iface[LIFNAMSIZ];
360 361 char aobjname[IPADM_AOBJSIZ];
361 362 int af, err = 0;
362 363
363 364 (void) strncpy(iface, origiface, sizeof (iface));
364 365
365 366 af = strstr(addr, ":") == NULL ? AF_INET : AF_INET6;
366 367 if (lxi_getif(af, iface, sizeof (iface), *first_ipv4_configured) != 0) {
367 368 lxi_warn("failed to create new logical interface "
368 369 "on %s: %s", origiface, strerror(errno));
369 370 return (-1);
370 371 }
371 372
372 373 (void) snprintf(aobjname, IPADM_AOBJSIZ, "%s/addr%d", iface,
373 374 addrnum++);
374 375
375 376 if ((status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname,
376 377 &ipaddr)) != IPADM_SUCCESS) {
377 378 lxi_warn("ipadm_create_addrobj error %d: addr %s, "
378 379 "interface %s: %s\n", status, addr, iface,
379 380 ipadm_status2str(status));
380 381 return (-2);
381 382 }
382 383
383 384 if ((status = ipadm_set_addr(ipaddr, addr, AF_UNSPEC))
384 385 != IPADM_SUCCESS) {
385 386 lxi_warn("ipadm_set_addr error %d: addr %s"
386 387 ", interface %s: %s\n", status, addr,
387 388 iface, ipadm_status2str(status));
388 389 err = -3;
389 390 goto done;
390 391 }
391 392
392 393 if ((status = ipadm_create_addr(iph, ipaddr,
393 394 IPADM_OPT_ACTIVE | IPADM_OPT_UP)) != IPADM_SUCCESS) {
394 395 lxi_warn("ipadm_create_addr error for %s: %s\n", iface,
395 396 ipadm_status2str(status));
396 397 err = -4;
397 398 goto done;
398 399 }
399 400
400 401 if (af == AF_INET) {
401 402 *first_ipv4_configured = B_TRUE;
402 403 }
403 404
404 405 done:
405 406 ipadm_destroy_addrobj(ipaddr);
406 407 return (err);
407 408 }
408 409
409 410 #if 0 /* XXX KEBE SAYS NOT YET */
410 411 static int
411 412 lxi_iface_dhcp(const char *origiface, boolean_t *first_ipv4_configured)
412 413 {
413 414 dhcp_ipc_request_t *dhcpreq = NULL;
414 415 dhcp_ipc_reply_t *dhcpreply = NULL;
415 416 int err = 0, timeout = 5;
416 417 char iface[LIFNAMSIZ];
417 418
418 419 (void) strncpy(iface, origiface, sizeof (iface));
419 420
420 421 if (lxi_getif(AF_INET, iface, sizeof (iface), *first_ipv4_configured)
421 422 != 0) {
422 423 lxi_warn("failed to create new logical interface "
423 424 "on %s: %s", origiface, strerror(errno));
424 425 return (-1);
425 426 }
426 427
427 428 if (dhcp_start_agent(timeout) != 0) {
428 429 lxi_err("Failed to start dhcpagent\n");
429 430 /* NOTREACHED */
430 431 }
431 432
432 433 dhcpreq = dhcp_ipc_alloc_request(DHCP_START, iface,
433 434 NULL, 0, DHCP_TYPE_NONE);
434 435 if (dhcpreq == NULL) {
435 436 lxi_warn("Unable to allocate memory "
436 437 "to start DHCP on %s\n", iface);
437 438 return (-1);
438 439 }
439 440
440 441 err = dhcp_ipc_make_request(dhcpreq, &dhcpreply, timeout);
441 442 if (err != 0) {
442 443 free(dhcpreq);
443 444 lxi_warn("Failed to start DHCP on %s: %s\n", iface,
444 445 dhcp_ipc_strerror(err));
445 446 return (-1);
446 447 }
447 448 err = dhcpreply->return_code;
448 449 if (err != 0) {
449 450 lxi_warn("Failed to start DHCP on %s: %s\n", iface,
450 451 dhcp_ipc_strerror(err));
451 452 goto done;
452 453 }
453 454
454 455 *first_ipv4_configured = B_TRUE;
455 456
456 457 done:
457 458 free(dhcpreq);
458 459 free(dhcpreply);
459 460 return (err);
460 461 }
461 462 #endif /* XXX KEBE SAYS NOT YET */
462 463
463 464 /*
464 465 * Initialize an IPv6 link-local address on a given interface
465 466 */
466 467 static int
467 468 lxi_iface_ipv6_link_local(const char *iface)
468 469 {
469 470 struct lifreq lifr;
470 471 int s;
471 472
472 473 s = socket(AF_INET6, SOCK_DGRAM, 0);
473 474 if (s == -1) {
474 475 lxi_warn("socket error %d: bringing up %s: %s",
475 476 errno, iface, strerror(errno));
476 477 }
477 478
478 479 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
479 480 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
480 481 lxi_warn("SIOCGLIFFLAGS error %d: bringing up %s: %s",
481 482 errno, iface, strerror(errno));
482 483 return (-1);
483 484 }
484 485
485 486 lifr.lifr_flags |= IFF_UP;
486 487 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
487 488 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
488 489 errno, iface, strerror(errno));
489 490 return (-1);
490 491 }
|
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
491 492
492 493 (void) close(s);
493 494 return (0);
494 495 }
495 496
496 497 static int
497 498 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
498 499 const char *gwaddr)
499 500 {
500 501 int idx, len, sockfd;
501 - char rtbuf[RTMBUFSZ];
502 + /* For lint-happy alignment, use a uint32_t array... */
503 + uint32_t rtbuf[RTMBUFSZ / sizeof (uint32_t)];
502 504 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
503 - struct sockaddr_in *dst_sin = (struct sockaddr_in *)
504 - (rtbuf + sizeof (struct rt_msghdr));
505 + struct sockaddr_in *dst_sin = (struct sockaddr_in *)(rtm + 1);
505 506 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
506 507 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
507 508
508 509 (void) bzero(rtm, RTMBUFSZ);
509 510 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
510 511 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
511 512 rtm->rtm_msglen = sizeof (rtbuf);
512 513 rtm->rtm_pid = getpid();
513 514 rtm->rtm_type = RTM_ADD;
514 515 rtm->rtm_version = RTM_VERSION;
515 516
516 517
517 518 /*
518 519 * The destination and netmask components have already been zeroed,
519 520 * which represents the default gateway. If we were passed a more
520 521 * specific destination network, use that instead.
521 522 */
522 523 dst_sin->sin_family = AF_INET;
523 524 netmask_sin->sin_family = AF_INET;
524 525 if (dst != NULL) {
525 526 struct sockaddr *mask = (struct sockaddr *)netmask_sin;
526 527
527 528 if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
528 529 plen2mask(dstpfx, AF_INET, mask) != 0) {
529 530 lxi_warn("bad destination network %s/%d: %s", dst,
530 531 dstpfx, strerror(errno));
531 532 return (-1);
532 533 }
533 534 }
534 535
535 536 if ((inet_pton(AF_INET, gwaddr, &(gw_sin->sin_addr))) != 1) {
536 537 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
537 538 return (-1);
538 539 }
539 540
540 541 if (iface != NULL) {
541 542 if ((idx = if_nametoindex(iface)) == 0) {
542 543 lxi_warn("unable to get interface index for %s: %s\n",
543 544 iface, strerror(errno));
544 545 return (-1);
545 546 }
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
546 547 rtm->rtm_index = idx;
547 548 }
548 549
549 550 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
550 551 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
551 552 return (-1);
552 553 }
553 554
554 555 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
555 556 lxi_warn("could not write rtmsg: %s", strerror(errno));
556 - close(sockfd);
557 + (void) close(sockfd);
557 558 return (-1);
558 559 } else if (len < rtm->rtm_msglen) {
559 560 lxi_warn("write() rtmsg incomplete");
560 - close(sockfd);
561 + (void) close(sockfd);
561 562 return (-1);
562 563 }
563 564
564 - close(sockfd);
565 + (void) close(sockfd);
565 566 return (0);
566 567 }
567 568
568 569 static void
569 570 lxi_net_loopback()
570 571 {
571 572 const char *iface = "lo0";
572 573 boolean_t first_ipv4_configured = B_FALSE;
573 574
574 575 lxi_net_plumb(iface);
575 576 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
576 577 (void) lxi_iface_ipv6_link_local(iface);
577 578 }
578 579
579 580
580 581
581 582 #if 0 /* XXX KEBE SAYS NOT YET */
582 583 /*
583 584 * This function is used when the "ips" property doesn't exist in a zone's
584 585 * configuration. It may be an older configuration, so we should search for
585 586 * "ip" and "netmask" and convert them into the new format.
586 587 */
587 588 static int
588 589 lxi_get_old_ip(struct zone_res_attrtab *attrs, const char **ipaddrs,
589 590 char *cidraddr, int len)
590 591 {
591 592
592 593 const char *netmask;
593 594 int prefixlen;
594 595 struct sockaddr_in mask_sin;
595 596
596 597 lxi_warn("Could not find \"ips\" property for zone. Looking "
597 598 "for older \"ip\" and \"netmask\" properties, instead.");
598 599
599 600 if (zone_find_attr(attrs, "ip", ipaddrs) != 0) {
600 601 return (-1);
601 602 }
602 603
603 604 if (strcmp(*ipaddrs, "dhcp") == 0) {
604 605 return (0);
605 606 }
606 607
607 608 if (zone_find_attr(attrs, "netmask", &netmask) != 0) {
608 609 lxi_err("could not find netmask for interface");
609 610 /* NOTREACHED */
610 611 }
611 612
612 613 /* Convert the netmask to a number */
613 614 mask_sin.sin_family = AF_INET;
614 615 if (inet_pton(AF_INET, netmask, &mask_sin.sin_addr) != 1) {
615 616 lxi_err("invalid netmask address: %s\n",
616 617 strerror(errno));
617 618 /* NOTREACHED */
618 619 }
619 620 prefixlen = mask2plen((struct sockaddr *)&mask_sin);
620 621
621 622 /*
622 623 * Write out the IP address in the new format and use
623 624 * that instead
624 625 */
625 626 (void) snprintf(cidraddr, len, "%s/%d", *ipaddrs, prefixlen);
626 627
627 628 *ipaddrs = cidraddr;
628 629 return (0);
629 630 }
630 631 #endif /* XXX KEBE SAYS NOT YET */
631 632
632 633 static void
633 634 lxi_net_setup(zone_dochandle_t handle)
634 635 {
635 636 struct zone_nwiftab lookup;
636 637 boolean_t do_addrconf = B_FALSE;
637 638
638 639 if (zonecfg_setnwifent(handle) != Z_OK)
639 640 return;
640 641 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
641 642 const char *iface = lookup.zone_nwif_physical;
642 643 #if 0 /* XXX KEBE SAYS NOT YET */
643 644 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
644 645 const char *ipaddrs, *primary, *gateway;
645 646 char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
646 647 *ipaddr, *tmp, *lasts;
647 648 boolean_t first_ipv4_configured = B_FALSE;
648 649 boolean_t *ficp = &first_ipv4_configured;
649 650 #endif /* XXX KEBE */
650 651
651 652 lxi_net_plumb(iface);
652 653
653 654 /* XXX KEBE SAYS this bit was shuffled around. */
654 655 if (lxi_iface_ipv6_link_local(iface) != 0) {
655 656 lxi_warn("unable to bring up link-local address on "
656 657 "interface %s", iface);
657 658 } else {
658 659 /* XXX KEBE SAYS this bit is new. */
659 660 do_addrconf = B_TRUE;
660 661 }
661 662
662 663 #if 0 /* XXX KEBE SAYS NOT YET */
663 664 if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
664 665 lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
665 666 lxi_warn("Could not find a valid network configuration "
666 667 "for the %s interface", iface);
667 668 continue;
668 669 }
669 670
670 671 /*
671 672 * If we're going to be doing DHCP, we have to do it first since
672 673 * dhcpagent doesn't like to operate on non-zero logical
673 674 * interfaces.
674 675 */
675 676 if (strstr(ipaddrs, "dhcp") != NULL &&
676 677 lxi_iface_dhcp(iface, ficp) != 0) {
677 678 lxi_warn("Failed to start DHCP on %s\n", iface);
678 679 }
679 680
680 681 /*
681 682 * Copy the ipaddrs string, since strtok_r will write NUL
682 683 * characters into it.
683 684 */
684 685 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
685 686 tmp = ipaddrs_copy;
686 687
687 688 /*
688 689 * Iterate over each IP and then set it up on the interface.
689 690 */
690 691 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
691 692 tmp = NULL;
692 693 if (strcmp(ipaddr, "addrconf") == 0) {
693 694 do_addrconf = B_TRUE;
694 695 } else if (strcmp(ipaddr, "dhcp") == 0) {
695 696 continue;
696 697 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
697 698 lxi_warn("Unable to add new IP address (%s) "
698 699 "to interface %s", ipaddr, iface);
699 700 }
700 701 }
701 702
702 703 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
703 704 strncmp(primary, "true", MAXNAMELEN) == 0 &&
704 705 zone_find_attr(attrs, "gateway", &gateway) == 0) {
705 706 lxi_iface_gateway(iface, NULL, 0, gateway);
706 707 }
707 708 #endif /* XXX KEBE */
708 709 }
709 710
710 711 if (do_addrconf) {
711 712 lxi_net_ndpd_start();
712 713 }
713 714
714 715 (void) zonecfg_endnwifent(handle);
715 716 }
716 717
717 718 static void
718 719 lxi_net_static_route(const char *line)
719 720 {
720 721 /*
721 722 * Each static route line is a string of the form:
722 723 *
723 724 * "10.77.77.2|10.1.1.0/24|false"
724 725 *
725 726 * i.e. gateway address, destination network, and whether this is
726 727 * a "link local" route or a next hop route.
727 728 */
728 729 custr_t *cu = NULL;
729 730 char *gw = NULL, *dst = NULL;
730 731 int pfx = -1;
731 732 int i;
732 733
733 734 if (custr_alloc(&cu) != 0) {
734 735 lxi_err("custr_alloc failure");
735 736 }
736 737
737 738 for (i = 0; line[i] != '\0'; i++) {
738 739 if (gw == NULL) {
739 740 if (line[i] == '|') {
740 741 if ((gw = strdup(custr_cstr(cu))) == NULL) {
741 742 lxi_err("strdup failure");
742 743 }
743 744 custr_reset(cu);
744 745 } else {
745 746 if (custr_appendc(cu, line[i]) != 0) {
746 747 lxi_err("custr_appendc failure");
747 748 }
748 749 }
749 750 continue;
750 751 }
751 752
752 753 if (dst == NULL) {
753 754 if (line[i] == '/') {
754 755 if ((dst = strdup(custr_cstr(cu))) == NULL) {
755 756 lxi_err("strdup failure");
756 757 }
757 758 custr_reset(cu);
758 759 } else {
759 760 if (custr_appendc(cu, line[i]) != 0) {
760 761 lxi_err("custr_appendc failure");
761 762 }
762 763 }
763 764 continue;
764 765 }
765 766
766 767 if (pfx == -1) {
767 768 if (line[i] == '|') {
768 769 pfx = atoi(custr_cstr(cu));
769 770 custr_reset(cu);
770 771 } else {
771 772 if (custr_appendc(cu, line[i]) != 0) {
772 773 lxi_err("custr_appendc failure");
773 774 }
774 775 }
775 776 continue;
776 777 }
777 778
778 779 if (custr_appendc(cu, line[i]) != 0) {
779 780 lxi_err("custr_appendc failure");
780 781 }
781 782 }
782 783
783 784 /*
784 785 * We currently only support "next hop" routes, so ensure that
785 786 * "linklocal" is false:
786 787 */
787 788 if (strcmp(custr_cstr(cu), "false") != 0) {
788 789 lxi_warn("invalid static route: %s", line);
789 790 }
790 791
791 792 if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
792 793 lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
793 794 }
794 795
795 796 custr_free(cu);
796 797 free(gw);
797 798 free(dst);
798 799 }
799 800
800 801 static void
801 802 lxi_net_static_routes(void)
802 803 {
803 804 const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
804 805 char *const argv[] = { "routeinfo", NULL };
805 806 char *const envp[] = { NULL };
806 807 int code;
807 808 struct stat st;
808 809 char errbuf[512];
809 810
810 811 if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
811 812 /*
812 813 * This binary is (potentially) shipped from another
813 814 * consolidation. If it does not exist, then the platform does
814 815 * not currently support static routes for LX-branded zones.
815 816 */
816 817 return;
817 818 }
818 819
819 820 /*
820 821 * Run the command, firing the callback for each line that it
821 822 * outputs. When this function returns, static route processing
822 823 * is complete.
823 824 */
824 825 if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
825 826 lxi_net_static_route, &code) != 0 || code != 0) {
826 827 lxi_err("failed to run \"%s\": %s", cmd, errbuf);
827 828 }
828 829 }
829 830
830 831 static void
831 832 lxi_config_close(zone_dochandle_t handle)
832 833 {
833 834 zonecfg_fini_handle(handle);
834 835 }
835 836
836 837 static void
837 838 lxi_init_exec(char **argv)
838 839 {
839 840 const char *cmd = "/sbin/init";
840 841 char *const envp[] = { "container=zone", NULL };
|
↓ open down ↓ |
266 lines elided |
↑ open up ↑ |
841 842 int e;
842 843
843 844 argv[0] = "init";
844 845
845 846 /*
846 847 * systemd uses the 'container' env var to determine it is running
847 848 * inside a container. It only supports a few well-known types and
848 849 * treats anything else as 'other' but this is enough to make it
849 850 * behave better inside a zone. See 'detect_container' in systemd.
850 851 */
851 - execve(cmd, argv, envp);
852 + (void) execve(cmd, argv, envp);
852 853 e = errno;
853 854
854 855 /*
855 856 * Because stdout was closed prior to exec, it must be opened again in
856 857 * the face of failure to log the error.
857 858 */
858 859 lxi_log_open();
859 860 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
860 861 }
861 862
862 863 /*ARGSUSED*/
863 864 int
864 865 main(int argc, char *argv[])
865 866 {
866 867 zone_dochandle_t handle;
867 868
868 869 lxi_log_open();
869 870
870 871 lxi_net_ipmgmtd_start();
871 872 lxi_net_ipadm_open();
872 873
873 874 handle = lxi_config_open();
874 875 lxi_net_loopback();
875 876 lxi_net_setup(handle);
876 877 lxi_config_close(handle);
877 878
878 879 lxi_net_static_routes();
879 880
880 881 lxi_net_ipadm_close();
881 882
882 883 lxi_log_close();
883 884
884 885 lxi_init_exec(argv);
885 886
886 887 /* NOTREACHED */
887 888 return (0);
888 889 }
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX