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 }
185
186 return (handle);
187
188 }
189
190 static int
191 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
192 const char **result)
193 {
194 while (attrs != NULL) {
195 if (strncmp(attrs->zone_res_attr_name, name,
196 MAXNAMELEN) == 0) {
197 *result = attrs->zone_res_attr_value;
198 return (0);
199 }
200 attrs = attrs->zone_res_attr_next;
201 }
202 return (-1);
203 }
204
205 void
206 lxi_svc_start(char *name, char *path, char *fmri)
207 {
208 pid_t pid;
209 int status;
210 char *const argv[] = {
211 name,
212 NULL
213 };
214 char *const envp[] = {
215 fmri,
216 NULL
217 };
218
219 pid = fork();
220 if (pid == -1) {
221 lxi_err("fork() failed: %s", strerror(errno));
222 }
223
224 if (pid == 0) {
225 /* child */
226 const char *zroot = zone_get_nroot();
227 char cmd[MAXPATHLEN];
228
229 /*
230 * Construct the full path to the binary, including the native
231 * system root (e.g. "/native") if in use for this zone:
232 */
233 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot != NULL ?
234 zroot : "", path);
235
236 execve(cmd, argv, envp);
237
238 lxi_err("execve(%s) failed: %s", cmd, strerror(errno));
239 /* NOTREACHED */
240 }
241
242 /* parent */
243 while (wait(&status) != pid) {
244 /* EMPTY */;
245 }
246
247 if (WIFEXITED(status)) {
248 if (WEXITSTATUS(status) != 0) {
249 lxi_err("%s[%d] exited: %d", name,
250 (int)pid, WEXITSTATUS(status));
251 }
252 } else if (WIFSIGNALED(status)) {
253 lxi_err("%s[%d] died on signal: %d", name,
254 (int)pid, WTERMSIG(status));
255 } else {
256 lxi_err("%s[%d] failed in unknown way", name,
257 (int)pid);
258 }
259 }
260
261 void
262 lxi_net_ipmgmtd_start()
263 {
264 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
265 "SMF_FMRI=svc:/network/ip-interface-management:default");
477 errno, iface, strerror(errno));
478 return (-1);
479 }
480
481 lifr.lifr_flags |= IFF_UP;
482 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
483 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
484 errno, iface, strerror(errno));
485 return (-1);
486 }
487
488 (void) close(s);
489 return (0);
490 }
491
492 static int
493 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
494 const char *gwaddr)
495 {
496 int idx, len, sockfd;
497 char rtbuf[RTMBUFSZ];
498 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
499 struct sockaddr_in *dst_sin = (struct sockaddr_in *)
500 (rtbuf + sizeof (struct rt_msghdr));
501 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
502 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
503
504 (void) bzero(rtm, RTMBUFSZ);
505 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
506 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
507 rtm->rtm_msglen = sizeof (rtbuf);
508 rtm->rtm_pid = getpid();
509 rtm->rtm_type = RTM_ADD;
510 rtm->rtm_version = RTM_VERSION;
511
512
513 /*
514 * The destination and netmask components have already been zeroed,
515 * which represents the default gateway. If we were passed a more
516 * specific destination network, use that instead.
517 */
518 dst_sin->sin_family = AF_INET;
519 netmask_sin->sin_family = AF_INET;
520 if (dst != NULL) {
532 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
533 return (-1);
534 }
535
536 if (iface != NULL) {
537 if ((idx = if_nametoindex(iface)) == 0) {
538 lxi_warn("unable to get interface index for %s: %s\n",
539 iface, strerror(errno));
540 return (-1);
541 }
542 rtm->rtm_index = idx;
543 }
544
545 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
546 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
547 return (-1);
548 }
549
550 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
551 lxi_warn("could not write rtmsg: %s", strerror(errno));
552 close(sockfd);
553 return (-1);
554 } else if (len < rtm->rtm_msglen) {
555 lxi_warn("write() rtmsg incomplete");
556 close(sockfd);
557 return (-1);
558 }
559
560 close(sockfd);
561 return (0);
562 }
563
564 static void
565 lxi_net_loopback()
566 {
567 const char *iface = "lo0";
568 boolean_t first_ipv4_configured = B_FALSE;
569
570 lxi_net_plumb(iface);
571 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
572 (void) lxi_iface_ipv6_link_local(iface);
573 }
574
575
576 /*
577 * This function is used when the "ips" property doesn't exist in a zone's
578 * configuration. It may be an older configuration, so we should search for
579 * "ip" and "netmask" and convert them into the new format.
580 */
581 static int
582 lxi_get_old_ip(struct zone_res_attrtab *attrs, const char **ipaddrs,
583 char *cidraddr, int len)
584 {
585
586 const char *netmask;
587 int prefixlen;
588 struct sockaddr_in mask_sin;
589
590 lxi_warn("Could not find \"ips\" property for zone. Looking "
591 "for older \"ip\" and \"netmask\" properties, instead.");
592
593 if (zone_find_attr(attrs, "ip", ipaddrs) != 0) {
594 return (-1);
595 }
596
597 if (strcmp(*ipaddrs, "dhcp") == 0) {
598 return (0);
599 }
600
601 if (zone_find_attr(attrs, "netmask", &netmask) != 0) {
602 lxi_err("could not find netmask for interface");
603 /* NOTREACHED */
604 }
605
606 /* Convert the netmask to a number */
607 mask_sin.sin_family = AF_INET;
608 if (inet_pton(AF_INET, netmask, &mask_sin.sin_addr) != 1) {
609 lxi_err("invalid netmask address: %s\n",
610 strerror(errno));
611 /* NOTREACHED */
612 }
613 prefixlen = mask2plen((struct sockaddr *)&mask_sin);
614
615 /*
616 * Write out the IP address in the new format and use
617 * that instead
618 */
619 (void) snprintf(cidraddr, len, "%s/%d", *ipaddrs, prefixlen);
620
621 *ipaddrs = cidraddr;
622 return (0);
623 }
624
625 static void
626 lxi_net_setup(zone_dochandle_t handle)
627 {
628 struct zone_nwiftab lookup;
629 boolean_t do_addrconf = B_FALSE;
630
631 if (zonecfg_setnwifent(handle) != Z_OK)
632 return;
633 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
634 const char *iface = lookup.zone_nwif_physical;
635 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
636 const char *ipaddrs, *primary, *gateway;
637 char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
638 *ipaddr, *tmp, *lasts;
639 boolean_t first_ipv4_configured = B_FALSE;
640 boolean_t *ficp = &first_ipv4_configured;
641
642 lxi_net_plumb(iface);
643 if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
644 lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
645 lxi_warn("Could not find a valid network configuration "
646 "for the %s interface", iface);
647 continue;
648 }
649
650 if (lxi_iface_ipv6_link_local(iface) != 0) {
651 lxi_warn("unable to bring up link-local address on "
652 "interface %s", iface);
653 }
654
655 /*
656 * If we're going to be doing DHCP, we have to do it first since
657 * dhcpagent doesn't like to operate on non-zero logical
658 * interfaces.
659 */
660 if (strstr(ipaddrs, "dhcp") != NULL &&
661 lxi_iface_dhcp(iface, ficp) != 0) {
662 lxi_warn("Failed to start DHCP on %s\n", iface);
663 }
664
665 /*
666 * Copy the ipaddrs string, since strtok_r will write NUL
667 * characters into it.
668 */
669 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
670 tmp = ipaddrs_copy;
671
672 /*
673 * Iterate over each IP and then set it up on the interface.
674 */
675 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
676 tmp = NULL;
677 if (strcmp(ipaddr, "addrconf") == 0) {
678 do_addrconf = B_TRUE;
679 } else if (strcmp(ipaddr, "dhcp") == 0) {
680 continue;
681 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
682 lxi_warn("Unable to add new IP address (%s) "
683 "to interface %s", ipaddr, iface);
684 }
685 }
686
687 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
688 strncmp(primary, "true", MAXNAMELEN) == 0 &&
689 zone_find_attr(attrs, "gateway", &gateway) == 0) {
690 lxi_iface_gateway(iface, NULL, 0, gateway);
691 }
692 }
693
694 if (do_addrconf) {
695 lxi_net_ndpd_start();
696 }
697
698 (void) zonecfg_endnwifent(handle);
699 }
700
701 static void
702 lxi_net_static_route(const char *line)
703 {
704 /*
705 * Each static route line is a string of the form:
706 *
707 * "10.77.77.2|10.1.1.0/24|false"
708 *
709 * i.e. gateway address, destination network, and whether this is
710 * a "link local" route or a next hop route.
711 */
712 custr_t *cu = NULL;
815 lxi_config_close(zone_dochandle_t handle)
816 {
817 zonecfg_fini_handle(handle);
818 }
819
820 static void
821 lxi_init_exec(char **argv)
822 {
823 const char *cmd = "/sbin/init";
824 char *const envp[] = { "container=zone", NULL };
825 int e;
826
827 argv[0] = "init";
828
829 /*
830 * systemd uses the 'container' env var to determine it is running
831 * inside a container. It only supports a few well-known types and
832 * treats anything else as 'other' but this is enough to make it
833 * behave better inside a zone. See 'detect_container' in systemd.
834 */
835 execve(cmd, argv, envp);
836 e = errno;
837
838 /*
839 * Because stdout was closed prior to exec, it must be opened again in
840 * the face of failure to log the error.
841 */
842 lxi_log_open();
843 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
844 }
845
846 /*ARGSUSED*/
847 int
848 main(int argc, char *argv[])
849 {
850 zone_dochandle_t handle;
851
852 lxi_log_open();
853
854 lxi_net_ipmgmtd_start();
855 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 }
185
186 return (handle);
187
188 }
189
190 static int
191 zone_find_attr(struct zone_res_attrtab *attrs, const char *name,
192 const char **result)
193 {
194 while (attrs != NULL) {
195 if (strncmp(attrs->zone_res_attr_name, name,
196 MAXNAMELEN) == 0) {
197 *result = attrs->zone_res_attr_value;
198 return (0);
199 }
200 attrs = attrs->zone_res_attr_next;
201 }
202 return (-1);
203 }
204
205 static void
206 lxi_svc_start(char *name, char *path, char *fmri)
207 {
208 pid_t pid;
209 int status;
210 char *argv[] = {
211 NULL,
212 NULL
213 };
214 char *envp[] = {
215 NULL,
216 NULL
217 };
218 argv[0] = name;
219 envp[0] = fmri;
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 (void) 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 ;
247
248 if (WIFEXITED(status)) {
249 if (WEXITSTATUS(status) != 0) {
250 lxi_err("%s[%d] exited: %d", name,
251 (int)pid, WEXITSTATUS(status));
252 }
253 } else if (WIFSIGNALED(status)) {
254 lxi_err("%s[%d] died on signal: %d", name,
255 (int)pid, WTERMSIG(status));
256 } else {
257 lxi_err("%s[%d] failed in unknown way", name,
258 (int)pid);
259 }
260 }
261
262 void
263 lxi_net_ipmgmtd_start()
264 {
265 lxi_svc_start("ipmgmtd", IPMGMTD_PATH,
266 "SMF_FMRI=svc:/network/ip-interface-management:default");
478 errno, iface, strerror(errno));
479 return (-1);
480 }
481
482 lifr.lifr_flags |= IFF_UP;
483 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
484 lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
485 errno, iface, strerror(errno));
486 return (-1);
487 }
488
489 (void) close(s);
490 return (0);
491 }
492
493 static int
494 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
495 const char *gwaddr)
496 {
497 int idx, len, sockfd;
498 /* For lint-happy alignment, use a uint32_t array... */
499 uint32_t rtbuf[RTMBUFSZ / sizeof (uint32_t)];
500 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
501 struct sockaddr_in *dst_sin = (struct sockaddr_in *)(rtm + 1);
502 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
503 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
504
505 (void) bzero(rtm, RTMBUFSZ);
506 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
507 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
508 rtm->rtm_msglen = sizeof (rtbuf);
509 rtm->rtm_pid = getpid();
510 rtm->rtm_type = RTM_ADD;
511 rtm->rtm_version = RTM_VERSION;
512
513
514 /*
515 * The destination and netmask components have already been zeroed,
516 * which represents the default gateway. If we were passed a more
517 * specific destination network, use that instead.
518 */
519 dst_sin->sin_family = AF_INET;
520 netmask_sin->sin_family = AF_INET;
521 if (dst != NULL) {
533 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
534 return (-1);
535 }
536
537 if (iface != NULL) {
538 if ((idx = if_nametoindex(iface)) == 0) {
539 lxi_warn("unable to get interface index for %s: %s\n",
540 iface, strerror(errno));
541 return (-1);
542 }
543 rtm->rtm_index = idx;
544 }
545
546 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
547 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
548 return (-1);
549 }
550
551 if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
552 lxi_warn("could not write rtmsg: %s", strerror(errno));
553 (void) close(sockfd);
554 return (-1);
555 } else if (len < rtm->rtm_msglen) {
556 lxi_warn("write() rtmsg incomplete");
557 (void) close(sockfd);
558 return (-1);
559 }
560
561 (void) close(sockfd);
562 return (0);
563 }
564
565 static void
566 lxi_net_loopback()
567 {
568 const char *iface = "lo0";
569 boolean_t first_ipv4_configured = B_FALSE;
570
571 lxi_net_plumb(iface);
572 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
573 (void) lxi_iface_ipv6_link_local(iface);
574 }
575
576 static void
577 lxi_net_setup(zone_dochandle_t handle)
578 {
579 struct zone_nwiftab lookup;
580 boolean_t do_addrconf = B_FALSE;
581
582 if (zonecfg_setnwifent(handle) != Z_OK)
583 return;
584 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
585 const char *iface = lookup.zone_nwif_physical;
586 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
587 const char *ipaddrs, *primary, *gateway;
588 char ipaddrs_copy[MAXNAMELEN], /* cidraddr[BUFSIZ], */
589 *ipaddr, *tmp, *lasts;
590 boolean_t first_ipv4_configured = B_FALSE;
591 boolean_t *ficp = &first_ipv4_configured;
592 boolean_t no_zonecfg;
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 */
599 lxi_net_plumb(iface);
600
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 for now.
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
614 if (lxi_iface_ipv6_link_local(iface) != 0) {
615 lxi_warn("unable to bring up link-local address on "
616 "interface %s", iface);
617 }
618
619 /*
620 * Every thing else below only happens if we have zonecfg(1M)
621 * network configuration.
622 */
623 if (no_zonecfg)
624 continue;
625
626 /*
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
629 * interfaces.
630 */
631 if (strstr(ipaddrs, "dhcp") != NULL &&
632 lxi_iface_dhcp(iface, ficp) != 0) {
633 lxi_warn("Failed to start DHCP on %s\n", iface);
634 }
635
636 /*
637 * Copy the ipaddrs string, since strtok_r will write NUL
638 * characters into it.
639 */
640 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
641 tmp = ipaddrs_copy;
642
643 /*
644 * Iterate over each IP and then set it up on the interface.
645 */
646 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
647 tmp = NULL;
648 if (strcmp(ipaddr, "addrconf") == 0) {
649 do_addrconf = B_TRUE;
650 } else if (strcmp(ipaddr, "dhcp") == 0) {
651 continue;
652 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
653 lxi_warn("Unable to add new IP address (%s) "
654 "to interface %s", ipaddr, iface);
655 }
656 }
657
658 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
659 strncmp(primary, "true", MAXNAMELEN) == 0 &&
660 zone_find_attr(attrs, "gateway", &gateway) == 0) {
661 if (lxi_iface_gateway(iface, NULL, 0, gateway) != 0) {
662 lxi_err("default route on %s -> %s failed",
663 iface, gateway);
664 }
665 }
666 }
667
668 if (do_addrconf) {
669 lxi_net_ndpd_start();
670 }
671
672 (void) zonecfg_endnwifent(handle);
673 }
674
675 static void
676 lxi_net_static_route(const char *line)
677 {
678 /*
679 * Each static route line is a string of the form:
680 *
681 * "10.77.77.2|10.1.1.0/24|false"
682 *
683 * i.e. gateway address, destination network, and whether this is
684 * a "link local" route or a next hop route.
685 */
686 custr_t *cu = NULL;
789 lxi_config_close(zone_dochandle_t handle)
790 {
791 zonecfg_fini_handle(handle);
792 }
793
794 static void
795 lxi_init_exec(char **argv)
796 {
797 const char *cmd = "/sbin/init";
798 char *const envp[] = { "container=zone", NULL };
799 int e;
800
801 argv[0] = "init";
802
803 /*
804 * systemd uses the 'container' env var to determine it is running
805 * inside a container. It only supports a few well-known types and
806 * treats anything else as 'other' but this is enough to make it
807 * behave better inside a zone. See 'detect_container' in systemd.
808 */
809 (void) execve(cmd, argv, envp);
810 e = errno;
811
812 /*
813 * Because stdout was closed prior to exec, it must be opened again in
814 * the face of failure to log the error.
815 */
816 lxi_log_open();
817 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
818 }
819
820 /*ARGSUSED*/
821 int
822 main(int argc, char *argv[])
823 {
824 zone_dochandle_t handle;
825
826 lxi_log_open();
827
828 lxi_net_ipmgmtd_start();
829 lxi_net_ipadm_open();
|