86 static void
87 lxi_err(char *msg, ...)
88 {
89 char buf[1024];
90 int len;
91 va_list ap;
92
93 va_start(ap, msg);
94 /*LINTED*/
95 len = vsnprintf(buf, sizeof (buf), msg, ap);
96 va_end(ap);
97
98 (void) write(1, PREFIX_LOG_ERR, strlen(PREFIX_LOG_ERR));
99 (void) write(1, buf, len);
100 (void) write(1, "\n", 1);
101
102 /*
103 * Since a non-zero exit will cause the zone to reboot, a pause here
104 * will prevent a mis-configured zone from spinning in a reboot loop.
105 */
106 pause();
107 exit(1);
108 /*NOTREACHED*/
109 }
110
111 static void
112 lxi_warn(char *msg, ...)
113 {
114 char buf[1024];
115 int len;
116 va_list ap;
117
118 va_start(ap, msg);
119 /*LINTED*/
120 len = vsnprintf(buf, sizeof (buf), msg, ap);
121 va_end(ap);
122
123 (void) write(1, PREFIX_LOG_WARN, strlen(PREFIX_LOG_WARN));
124 (void) write(1, buf, len);
125 (void) write(1, "\n", 1);
126 }
187
188 }
189
190 #if 0 /* XXX KEBE SAYS NOT YET */
191 static int
192 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
193 const char **result)
194 {
195 while (attrs != NULL) {
196 if (strncmp(attrs->zone_res_attr_name, name,
197 MAXNAMELEN) == 0) {
198 *result = attrs->zone_res_attr_value;
199 return (0);
200 }
201 attrs = attrs->zone_res_attr_next;
202 }
203 return (-1);
204 }
205 #endif /* XXX KEBE SAYS NOT YET */
206
207 void
208 lxi_svc_start(char *name, char *path, char *fmri)
209 {
210 pid_t pid;
211 int status;
212 char *const argv[] = {
213 name,
214 NULL
215 };
216 char *const envp[] = {
217 fmri,
218 NULL
219 };
220
221 pid = fork();
222 if (pid == -1) {
223 lxi_err("fork() failed: %s", strerror(errno));
224 }
225
226 if (pid == 0) {
227 /* child */
228 const char *zroot = zone_get_nroot();
229 char cmd[MAXPATHLEN];
230
231 /*
232 * Construct the full path to the binary, including the native
233 * system root (e.g. "/native") if in use for this zone:
234 */
235 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot != NULL ?
236 zroot : "", path);
237
238 execve(cmd, argv, envp);
239
240 lxi_err("execve(%s) failed: %s", cmd, strerror(errno));
241 /* NOTREACHED */
242 }
243
244 /* parent */
245 while (wait(&status) != pid) {
246 /* EMPTY */;
247 }
248
249 if (WIFEXITED(status)) {
250 if (WEXITSTATUS(status) != 0) {
251 lxi_err("%s[%d] exited: %d", name,
252 (int)pid, WEXITSTATUS(status));
253 }
254 } else if (WIFSIGNALED(status)) {
255 lxi_err("%s[%d] died on signal: %d", name,
256 (int)pid, WTERMSIG(status));
257 } else {
258 lxi_err("%s[%d] failed in unknown way", name,
259 (int)pid);
260 }
261 }
262
263 void
264 lxi_net_ipmgmtd_start()
265 {
266 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
267 "SMF_FMRI=svc:/network/ip-interface-management:default");
481 errno, iface, strerror(errno));
482 return (-1);
483 }
484
485 lifr.lifr_flags |= IFF_UP;
486 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
487 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
488 errno, iface, strerror(errno));
489 return (-1);
490 }
491
492 (void) close(s);
493 return (0);
494 }
495
496 static int
497 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
498 const char *gwaddr)
499 {
500 int idx, len, sockfd;
501 char rtbuf[RTMBUFSZ];
502 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 *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
506 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
507
508 (void) bzero(rtm, RTMBUFSZ);
509 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
510 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
511 rtm->rtm_msglen = sizeof (rtbuf);
512 rtm->rtm_pid = getpid();
513 rtm->rtm_type = RTM_ADD;
514 rtm->rtm_version = RTM_VERSION;
515
516
517 /*
518 * The destination and netmask components have already been zeroed,
519 * which represents the default gateway. If we were passed a more
520 * specific destination network, use that instead.
521 */
522 dst_sin->sin_family = AF_INET;
523 netmask_sin->sin_family = AF_INET;
524 if (dst != NULL) {
536 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
537 return (-1);
538 }
539
540 if (iface != NULL) {
541 if ((idx = if_nametoindex(iface)) == 0) {
542 lxi_warn("unable to get interface index for %s: %s\n",
543 iface, strerror(errno));
544 return (-1);
545 }
546 rtm->rtm_index = idx;
547 }
548
549 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
550 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
551 return (-1);
552 }
553
554 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
555 lxi_warn("could not write rtmsg: %s", strerror(errno));
556 close(sockfd);
557 return (-1);
558 } else if (len < rtm->rtm_msglen) {
559 lxi_warn("write() rtmsg incomplete");
560 close(sockfd);
561 return (-1);
562 }
563
564 close(sockfd);
565 return (0);
566 }
567
568 static void
569 lxi_net_loopback()
570 {
571 const char *iface = "lo0";
572 boolean_t first_ipv4_configured = B_FALSE;
573
574 lxi_net_plumb(iface);
575 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
576 (void) lxi_iface_ipv6_link_local(iface);
577 }
578
579
580
581 #if 0 /* XXX KEBE SAYS NOT YET */
582 /*
583 * This function is used when the "ips" property doesn't exist in a zone's
584 * configuration. It may be an older configuration, so we should search for
831 lxi_config_close(zone_dochandle_t handle)
832 {
833 zonecfg_fini_handle(handle);
834 }
835
836 static void
837 lxi_init_exec(char **argv)
838 {
839 const char *cmd = "/sbin/init";
840 char *const envp[] = { "container=zone", NULL };
841 int e;
842
843 argv[0] = "init";
844
845 /*
846 * systemd uses the 'container' env var to determine it is running
847 * inside a container. It only supports a few well-known types and
848 * treats anything else as 'other' but this is enough to make it
849 * behave better inside a zone. See 'detect_container' in systemd.
850 */
851 execve(cmd, argv, envp);
852 e = errno;
853
854 /*
855 * Because stdout was closed prior to exec, it must be opened again in
856 * the face of failure to log the error.
857 */
858 lxi_log_open();
859 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
860 }
861
862 /*ARGSUSED*/
863 int
864 main(int argc, char *argv[])
865 {
866 zone_dochandle_t handle;
867
868 lxi_log_open();
869
870 lxi_net_ipmgmtd_start();
871 lxi_net_ipadm_open();
|
86 static void
87 lxi_err(char *msg, ...)
88 {
89 char buf[1024];
90 int len;
91 va_list ap;
92
93 va_start(ap, msg);
94 /*LINTED*/
95 len = vsnprintf(buf, sizeof (buf), msg, ap);
96 va_end(ap);
97
98 (void) write(1, PREFIX_LOG_ERR, strlen(PREFIX_LOG_ERR));
99 (void) write(1, buf, len);
100 (void) write(1, "\n", 1);
101
102 /*
103 * Since a non-zero exit will cause the zone to reboot, a pause here
104 * will prevent a mis-configured zone from spinning in a reboot loop.
105 */
106 (void) pause();
107 exit(1);
108 /*NOTREACHED*/
109 }
110
111 static void
112 lxi_warn(char *msg, ...)
113 {
114 char buf[1024];
115 int len;
116 va_list ap;
117
118 va_start(ap, msg);
119 /*LINTED*/
120 len = vsnprintf(buf, sizeof (buf), msg, ap);
121 va_end(ap);
122
123 (void) write(1, PREFIX_LOG_WARN, strlen(PREFIX_LOG_WARN));
124 (void) write(1, buf, len);
125 (void) write(1, "\n", 1);
126 }
187
188 }
189
190 #if 0 /* XXX KEBE SAYS NOT YET */
191 static int
192 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
193 const char **result)
194 {
195 while (attrs != NULL) {
196 if (strncmp(attrs->zone_res_attr_name, name,
197 MAXNAMELEN) == 0) {
198 *result = attrs->zone_res_attr_value;
199 return (0);
200 }
201 attrs = attrs->zone_res_attr_next;
202 }
203 return (-1);
204 }
205 #endif /* XXX KEBE SAYS NOT YET */
206
207 static void
208 lxi_svc_start(char *name, char *path, char *fmri)
209 {
210 pid_t pid;
211 int status;
212 char *argv[] = {
213 NULL,
214 NULL
215 };
216 char *envp[] = {
217 NULL,
218 NULL
219 };
220 argv[0] = name;
221 envp[0] = fmri;
222
223 pid = fork();
224 if (pid == -1) {
225 lxi_err("fork() failed: %s", strerror(errno));
226 }
227
228 if (pid == 0) {
229 /* child */
230 const char *zroot = zone_get_nroot();
231 char cmd[MAXPATHLEN];
232
233 /*
234 * Construct the full path to the binary, including the native
235 * system root (e.g. "/native") if in use for this zone:
236 */
237 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot != NULL ?
238 zroot : "", path);
239
240 (void) execve(cmd, argv, envp);
241
242 lxi_err("execve(%s) failed: %s", cmd, strerror(errno));
243 /* NOTREACHED */
244 }
245
246 /* parent */
247 while (wait(&status) != pid)
248 ;
249
250 if (WIFEXITED(status)) {
251 if (WEXITSTATUS(status) != 0) {
252 lxi_err("%s[%d] exited: %d", name,
253 (int)pid, WEXITSTATUS(status));
254 }
255 } else if (WIFSIGNALED(status)) {
256 lxi_err("%s[%d] died on signal: %d", name,
257 (int)pid, WTERMSIG(status));
258 } else {
259 lxi_err("%s[%d] failed in unknown way", name,
260 (int)pid);
261 }
262 }
263
264 void
265 lxi_net_ipmgmtd_start()
266 {
267 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
268 "SMF_FMRI=svc:/network/ip-interface-management:default");
482 errno, iface, strerror(errno));
483 return (-1);
484 }
485
486 lifr.lifr_flags |= IFF_UP;
487 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
488 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
489 errno, iface, strerror(errno));
490 return (-1);
491 }
492
493 (void) close(s);
494 return (0);
495 }
496
497 static int
498 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
499 const char *gwaddr)
500 {
501 int idx, len, sockfd;
502 /* For lint-happy alignment, use a uint32_t array... */
503 uint32_t rtbuf[RTMBUFSZ / sizeof (uint32_t)];
504 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
505 struct sockaddr_in *dst_sin = (struct sockaddr_in *)(rtm + 1);
506 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
507 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
508
509 (void) bzero(rtm, RTMBUFSZ);
510 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
511 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
512 rtm->rtm_msglen = sizeof (rtbuf);
513 rtm->rtm_pid = getpid();
514 rtm->rtm_type = RTM_ADD;
515 rtm->rtm_version = RTM_VERSION;
516
517
518 /*
519 * The destination and netmask components have already been zeroed,
520 * which represents the default gateway. If we were passed a more
521 * specific destination network, use that instead.
522 */
523 dst_sin->sin_family = AF_INET;
524 netmask_sin->sin_family = AF_INET;
525 if (dst != NULL) {
537 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
538 return (-1);
539 }
540
541 if (iface != NULL) {
542 if ((idx = if_nametoindex(iface)) == 0) {
543 lxi_warn("unable to get interface index for %s: %s\n",
544 iface, strerror(errno));
545 return (-1);
546 }
547 rtm->rtm_index = idx;
548 }
549
550 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
551 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
552 return (-1);
553 }
554
555 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
556 lxi_warn("could not write rtmsg: %s", strerror(errno));
557 (void) close(sockfd);
558 return (-1);
559 } else if (len < rtm->rtm_msglen) {
560 lxi_warn("write() rtmsg incomplete");
561 (void) close(sockfd);
562 return (-1);
563 }
564
565 (void) close(sockfd);
566 return (0);
567 }
568
569 static void
570 lxi_net_loopback()
571 {
572 const char *iface = "lo0";
573 boolean_t first_ipv4_configured = B_FALSE;
574
575 lxi_net_plumb(iface);
576 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
577 (void) lxi_iface_ipv6_link_local(iface);
578 }
579
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
832 lxi_config_close(zone_dochandle_t handle)
833 {
834 zonecfg_fini_handle(handle);
835 }
836
837 static void
838 lxi_init_exec(char **argv)
839 {
840 const char *cmd = "/sbin/init";
841 char *const envp[] = { "container=zone", NULL };
842 int e;
843
844 argv[0] = "init";
845
846 /*
847 * systemd uses the 'container' env var to determine it is running
848 * inside a container. It only supports a few well-known types and
849 * treats anything else as 'other' but this is enough to make it
850 * behave better inside a zone. See 'detect_container' in systemd.
851 */
852 (void) execve(cmd, argv, envp);
853 e = errno;
854
855 /*
856 * Because stdout was closed prior to exec, it must be opened again in
857 * the face of failure to log the error.
858 */
859 lxi_log_open();
860 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
861 }
862
863 /*ARGSUSED*/
864 int
865 main(int argc, char *argv[])
866 {
867 zone_dochandle_t handle;
868
869 lxi_log_open();
870
871 lxi_net_ipmgmtd_start();
872 lxi_net_ipadm_open();
|