473 }
474
475 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
476 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
477 lxi_warn("SIOCGLIFFLAGS error %d: bringing up %s: %s",
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 char rtbuf[RTMBUFSZ];
499 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
500 struct sockaddr_in *dst_sin = (struct sockaddr_in *)
501 (rtbuf + sizeof (struct rt_msghdr));
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) {
522 struct sockaddr *mask = (struct sockaddr *)netmask_sin;
523
524 if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
525 plen2mask(dstpfx, AF_INET, mask) != 0) {
526 lxi_warn("bad destination network %s/%d: %s", dst,
527 dstpfx, strerror(errno));
528 return (-1);
529 }
530 }
531
532 if ((inet_pton(AF_INET, gwaddr, &(gw_sin->sin_addr))) != 1) {
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 close(sockfd);
554 return (-1);
555 } else if (len < rtm->rtm_msglen) {
556 lxi_warn("write() rtmsg incomplete");
557 close(sockfd);
558 return (-1);
559 }
560
561 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
577 /*
578 * This function is used when the "ips" property doesn't exist in a zone's
579 * configuration. It may be an older configuration, so we should search for
580 * "ip" and "netmask" and convert them into the new format.
581 */
582 static int
617 * Write out the IP address in the new format and use
618 * that instead
619 */
620 (void) snprintf(cidraddr, len, "%s/%d", *ipaddrs, prefixlen);
621
622 *ipaddrs = cidraddr;
623 return (0);
624 }
625
626 static void
627 lxi_net_setup(zone_dochandle_t handle)
628 {
629 struct zone_nwiftab lookup;
630 boolean_t do_addrconf = B_FALSE;
631
632 if (zonecfg_setnwifent(handle) != Z_OK)
633 return;
634 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
635 const char *iface = lookup.zone_nwif_physical;
636 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
637 const char *ipaddrs, *primary, *gateway;
638 char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
639 *ipaddr, *tmp, *lasts;
640 boolean_t first_ipv4_configured = B_FALSE;
641 boolean_t *ficp = &first_ipv4_configured;
642
643 lxi_net_plumb(iface);
644 if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
645 lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
646 lxi_warn("Could not find a valid network configuration "
647 "for the %s interface", iface);
648 continue;
649 }
650
651 if (lxi_iface_ipv6_link_local(iface) != 0) {
652 lxi_warn("unable to bring up link-local address on "
653 "interface %s", iface);
654 }
655
656 /*
657 * If we're going to be doing DHCP, we have to do it first since
667 * Copy the ipaddrs string, since strtok_r will write NUL
668 * characters into it.
669 */
670 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
671 tmp = ipaddrs_copy;
672
673 /*
674 * Iterate over each IP and then set it up on the interface.
675 */
676 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
677 tmp = NULL;
678 if (strcmp(ipaddr, "addrconf") == 0) {
679 do_addrconf = B_TRUE;
680 } else if (strcmp(ipaddr, "dhcp") == 0) {
681 continue;
682 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
683 lxi_warn("Unable to add new IP address (%s) "
684 "to interface %s", ipaddr, iface);
685 }
686 }
687
688 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
689 strncmp(primary, "true", MAXNAMELEN) == 0 &&
690 zone_find_attr(attrs, "gateway", &gateway) == 0) {
691 lxi_iface_gateway(iface, NULL, 0, gateway);
692 }
693 }
694
695 if (do_addrconf) {
696 lxi_net_ndpd_start();
697 }
698
699 (void) zonecfg_endnwifent(handle);
700 }
701
702 static void
703 lxi_net_static_route(const char *line)
704 {
705 /*
706 * Each static route line is a string of the form:
707 *
708 * "10.77.77.2|10.1.1.0/24|false"
709 *
710 * i.e. gateway address, destination network, and whether this is
711 * a "link local" route or a next hop route.
712 */
713 custr_t *cu = NULL;
714 char *gw = NULL, *dst = NULL;
715 int pfx = -1;
716 int i;
717
718 if (custr_alloc(&cu) != 0) {
719 lxi_err("custr_alloc failure");
720 }
721
722 for (i = 0; line[i] != '\0'; i++) {
723 if (gw == NULL) {
724 if (line[i] == '|') {
725 if ((gw = strdup(custr_cstr(cu))) == NULL) {
726 lxi_err("strdup failure");
727 }
728 custr_reset(cu);
729 } else {
730 if (custr_appendc(cu, line[i]) != 0) {
731 lxi_err("custr_appendc failure");
732 }
733 }
734 continue;
735 }
736
737 if (dst == NULL) {
738 if (line[i] == '/') {
739 if ((dst = strdup(custr_cstr(cu))) == NULL) {
740 lxi_err("strdup failure");
741 }
742 custr_reset(cu);
743 } else {
744 if (custr_appendc(cu, line[i]) != 0) {
745 lxi_err("custr_appendc failure");
746 }
747 }
748 continue;
749 }
750
751 if (pfx == -1) {
752 if (line[i] == '|') {
753 pfx = atoi(custr_cstr(cu));
754 custr_reset(cu);
755 } else {
756 if (custr_appendc(cu, line[i]) != 0) {
757 lxi_err("custr_appendc failure");
758 }
759 }
760 continue;
761 }
762
763 if (custr_appendc(cu, line[i]) != 0) {
764 lxi_err("custr_appendc failure");
765 }
766 }
767
768 /*
769 * We currently only support "next hop" routes, so ensure that
770 * "linklocal" is false:
771 */
772 if (strcmp(custr_cstr(cu), "false") != 0) {
773 lxi_warn("invalid static route: %s", line);
774 }
775
776 if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
777 lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
778 }
779
780 custr_free(cu);
781 free(gw);
782 free(dst);
783 }
784
785 static void
786 lxi_net_static_routes(void)
787 {
788 const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
789 char *const argv[] = { "routeinfo", NULL };
790 char *const envp[] = { NULL };
791 int code;
792 struct stat st;
793 char errbuf[512];
794
795 if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
796 /*
797 * This binary is (potentially) shipped from another
798 * consolidation. If it does not exist, then the platform does
799 * not currently support static routes for LX-branded zones.
800 */
801 return;
802 }
803
804 /*
805 * Run the command, firing the callback for each line that it
806 * outputs. When this function returns, static route processing
807 * is complete.
808 */
809 if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
810 lxi_net_static_route, &code) != 0 || code != 0) {
811 lxi_err("failed to run \"%s\": %s", cmd, errbuf);
812 }
813 }
814
815 static void
816 lxi_config_close(zone_dochandle_t handle)
817 {
818 zonecfg_fini_handle(handle);
819 }
820
821 static void
822 lxi_hook_postnet()
823 {
824 char cmd[MAXPATHLEN];
825 const char *zroot = zone_get_nroot();
826 pid_t pid;
827 int status;
828
829 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot, HOOK_POSTNET_PATH);
830 if (access(cmd, X_OK) != 0) {
831 /* If no suitable script is present, soldier on. */
832 return;
833 }
834
835 if ((pid = fork()) < 0) {
900 * the face of failure to log the error.
901 */
902 lxi_log_open();
903 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
904 }
905
906 /*ARGSUSED*/
907 int
908 main(int argc, char *argv[])
909 {
910 zone_dochandle_t handle;
911
912 lxi_log_open();
913
914 lxi_net_ipmgmtd_start();
915 lxi_net_ipadm_open();
916
917 handle = lxi_config_open();
918 lxi_net_loopback();
919 lxi_net_setup(handle);
920 lxi_config_close(handle);
921
922 lxi_net_static_routes();
923
924 lxi_net_ipadm_close();
925
926 lxi_hook_postnet();
927
928 lxi_log_close();
929
930 lxi_init_exec(argv);
931
932 /* NOTREACHED */
933 return (0);
934 }
|
473 }
474
475 (void) strncpy(lifr.lifr_name, iface, sizeof (lifr.lifr_name));
476 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
477 lxi_warn("SIOCGLIFFLAGS error %d: bringing up %s: %s",
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 lxi_route_send_msg(struct rt_msghdr * rtm)
494 {
495 int sockfd, len;
496
497 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
498 lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
499 return (-1);
500 }
501
502 if ((len = write(sockfd, (const void *)rtm, rtm->rtm_msglen)) < 0) {
503 lxi_warn("could not write rtmsg: %s", strerror(errno));
504 close(sockfd);
505 return (-1);
506 } else if (len < rtm->rtm_msglen) {
507 lxi_warn("write() rtmsg incomplete");
508 close(sockfd);
509 return (-1);
510 }
511
512 close(sockfd);
513 return (0);
514 }
515
516 static int
517 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
518 const char *gwaddr, int llroute)
519 {
520 int idx;
521 char rtbuf[RTMBUFSZ];
522 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
523 struct sockaddr_in *dst_sin = (struct sockaddr_in *)
524 (rtbuf + sizeof (struct rt_msghdr));
525 struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
526 struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
527
528 (void) bzero(rtm, RTMBUFSZ);
529 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
530
531 if(!llroute)
532 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
533
534 rtm->rtm_msglen = sizeof (rtbuf);
535 rtm->rtm_pid = getpid();
536 rtm->rtm_type = RTM_ADD;
537 rtm->rtm_version = RTM_VERSION;
538
539
540 /*
541 * The destination and netmask components have already been zeroed,
542 * which represents the default gateway. If we were passed a more
543 * specific destination network, use that instead.
544 */
545
546 if(dstpfx == -1) {
547 /*
548 * no prefix was specified; assume a prefix length of 32,
549 * which seems in line with the behavior of vmadm.
550 */
551 dstpfx = 32;
552 }
553
554 dst_sin->sin_family = AF_INET;
555 netmask_sin->sin_family = AF_INET;
556 if (dst != NULL) {
557 struct sockaddr *mask = (struct sockaddr *)netmask_sin;
558
559 if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
560 plen2mask(dstpfx, AF_INET, mask) != 0) {
561 lxi_warn("bad destination network %s/%d: %s", dst,
562 dstpfx, strerror(errno));
563 return (-1);
564 }
565 }
566
567 if ((inet_pton(AF_INET, gwaddr, &(gw_sin->sin_addr))) != 1) {
568 lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
569 return (-1);
570 }
571
572 if (iface != NULL) {
573 if ((idx = if_nametoindex(iface)) == 0) {
574 lxi_warn("unable to get interface index for %s: %s\n",
575 iface, strerror(errno));
576 return (-1);
577 }
578 rtm->rtm_index = idx;
579 }
580
581 return lxi_route_send_msg(rtm);
582 }
583
584 static void
585 lxi_net_loopback()
586 {
587 const char *iface = "lo0";
588 boolean_t first_ipv4_configured = B_FALSE;
589
590 lxi_net_plumb(iface);
591 (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
592 (void) lxi_iface_ipv6_link_local(iface);
593 }
594
595
596 /*
597 * This function is used when the "ips" property doesn't exist in a zone's
598 * configuration. It may be an older configuration, so we should search for
599 * "ip" and "netmask" and convert them into the new format.
600 */
601 static int
636 * Write out the IP address in the new format and use
637 * that instead
638 */
639 (void) snprintf(cidraddr, len, "%s/%d", *ipaddrs, prefixlen);
640
641 *ipaddrs = cidraddr;
642 return (0);
643 }
644
645 static void
646 lxi_net_setup(zone_dochandle_t handle)
647 {
648 struct zone_nwiftab lookup;
649 boolean_t do_addrconf = B_FALSE;
650
651 if (zonecfg_setnwifent(handle) != Z_OK)
652 return;
653 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
654 const char *iface = lookup.zone_nwif_physical;
655 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
656 const char *ipaddrs;
657 char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
658 *ipaddr, *tmp, *lasts;
659 boolean_t first_ipv4_configured = B_FALSE;
660 boolean_t *ficp = &first_ipv4_configured;
661
662 lxi_net_plumb(iface);
663 if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
664 lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
665 lxi_warn("Could not find a valid network configuration "
666 "for the %s interface", iface);
667 continue;
668 }
669
670 if (lxi_iface_ipv6_link_local(iface) != 0) {
671 lxi_warn("unable to bring up link-local address on "
672 "interface %s", iface);
673 }
674
675 /*
676 * If we're going to be doing DHCP, we have to do it first since
686 * Copy the ipaddrs string, since strtok_r will write NUL
687 * characters into it.
688 */
689 (void) strlcpy(ipaddrs_copy, ipaddrs, MAXNAMELEN);
690 tmp = ipaddrs_copy;
691
692 /*
693 * Iterate over each IP and then set it up on the interface.
694 */
695 while ((ipaddr = strtok_r(tmp, ",", &lasts)) != NULL) {
696 tmp = NULL;
697 if (strcmp(ipaddr, "addrconf") == 0) {
698 do_addrconf = B_TRUE;
699 } else if (strcmp(ipaddr, "dhcp") == 0) {
700 continue;
701 } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
702 lxi_warn("Unable to add new IP address (%s) "
703 "to interface %s", ipaddr, iface);
704 }
705 }
706 }
707
708 if (do_addrconf) {
709 lxi_net_ndpd_start();
710 }
711
712 (void) zonecfg_endnwifent(handle);
713 }
714
715 static void
716 lxi_net_setup_gateways(zone_dochandle_t handle)
717 {
718 struct zone_nwiftab lookup;
719
720 if (zonecfg_setnwifent(handle) != Z_OK)
721 return;
722 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
723 const char *iface = lookup.zone_nwif_physical;
724 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
725 const char *primary, *gateway;
726
727 if (zone_find_attr(attrs, "primary", &primary) == 0 &&
728 strncmp(primary, "true", MAXNAMELEN) == 0 &&
729 zone_find_attr(attrs, "gateway", &gateway) == 0) {
730 lxi_iface_gateway(iface, NULL, 0, gateway, 0);
731 }
732 }
733
734 (void) zonecfg_endnwifent(handle);
735 }
736
737 static void
738 lxi_parse_route_line(const char *line, custr_t *cu, char *gw, char *dst, int* pfx, int gwlen, int dstlen)
739 {
740 int i;
741 int havegw = 0, havedst = 0, nopfx = 0;
742
743 for (i = 0; line[i] != '\0'; i++) {
744 if (!havegw) {
745 if (line[i] == '|') {
746 if ((strlcpy(gw, custr_cstr(cu), gwlen) ) == 0) {
747 lxi_err("strlcpy failure");
748 } else {
749 havegw = 1;
750 }
751 custr_reset(cu);
752 } else {
753 if (custr_appendc(cu, line[i]) != 0) {
754 lxi_err("custr_appendc failure");
755 }
756 }
757 continue;
758 }
759
760 if (!havedst) {
761 if (line[i] == '/' || line[i] == '|') {
762 if ((strlcpy(dst, custr_cstr(cu), dstlen)) == 0) {
763 lxi_err("strlcpy failure");
764 } else {
765 havedst = 1;
766 if(line[i] == '|') {
767 nopfx = 1;
768 }
769 }
770 custr_reset(cu);
771 } else {
772 if (custr_appendc(cu, line[i]) != 0) {
773 lxi_err("custr_appendc failure");
774 }
775 }
776 continue;
777 }
778
779 if (*pfx == -1 && !nopfx) {
780 if (line[i] == '|') {
781 *pfx = atoi(custr_cstr(cu));
782 custr_reset(cu);
783 } else {
784 if (custr_appendc(cu, line[i]) != 0) {
785 lxi_err("custr_appendc failure");
786 }
787 }
788 continue;
789 }
790
791 if (custr_appendc(cu, line[i]) != 0) {
792 lxi_err("custr_appendc failure");
793 }
794 }
795
796 return;
797 }
798
799 static void
800 lxi_net_process_route_line(const char *line, int llonly)
801 {
802 /*
803 * Each static route line is a string of the form:
804 *
805 * "10.77.77.2|10.1.1.0/24|false"
806 *
807 * i.e. gateway address, destination network, and whether this is
808 * a "link local" route or a next hop route.
809 *
810 * passing a true value to the llonly argument to this method causes only
811 * those lines with the link-local flag to be processed and vice-versa
812 */
813 custr_t *cu = NULL;
814 int pfx = -1;
815 char gw[INET6_ADDRSTRLEN];
816 char dst[INET6_ADDRSTRLEN];
817
818 if (custr_alloc(&cu) != 0) {
819 lxi_err("custr_alloc failure");
820 }
821
822 lxi_parse_route_line(line, cu, gw, dst, &pfx, sizeof(gw), sizeof(dst));
823
824 if (llonly && strcmp(custr_cstr(cu), "true") == 0) {
825 if (lxi_iface_gateway(NULL, dst, pfx, gw, 1) != 0) {
826 lxi_err("failed to add link-local route: %s/%d -> %s", dst, pfx, gw);
827 }
828 } else if(!llonly && strcmp(custr_cstr(cu), "false") == 0) {
829 if (lxi_iface_gateway(NULL, dst, pfx, gw, 0) != 0) {
830 lxi_err("failed to add next-hop route: %s/%d -> %s", dst, pfx, gw);
831 }
832 } else if(strcmp(custr_cstr(cu), "true") != 0 && strcmp(custr_cstr(cu), "false") != 0) {
833 /*
834 * try to be helpful when we encounter something we don't expect.
835 */
836 lxi_warn("skipping unknown static route defined in line %s, parsed link-local flag=%s", line, custr_cstr(cu));
837 }
838
839 custr_free(cu);
840 }
841
842 static void
843 lxi_net_static_route(const char * line) {
844 /*
845 * process only those lines where the link-local field is false.
846 */
847 lxi_net_process_route_line(line, 0);
848 }
849
850 static void
851 lxi_net_linklocal_route(const char * line) {
852 /*
853 * processes only those lines where the link-local field is true.
854 */
855 lxi_net_process_route_line(line, 1);
856 }
857
858 static void
859 lxi_run_routeinfo(void * callback)
860 {
861 const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
862 char *const argv[] = { "routeinfo", NULL };
863 char *const envp[] = { NULL };
864 int code;
865 struct stat st;
866 char errbuf[512];
867
868 if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
869 /*
870 * This binary is (potentially) shipped from another
871 * consolidation. If it does not exist, then the platform does
872 * not currently support link-local or static routes for LX-branded zones.
873 */
874 return;
875 }
876
877 /*
878 * Run the command, firing the callback for each line that it
879 * outputs. When this function returns, static route processing
880 * is complete.
881 */
882 if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
883 callback, &code) != 0 || code != 0) {
884 lxi_err("failed to run \"%s\": %s", cmd, errbuf);
885 }
886 }
887
888 static void
889 lxi_net_linklocal_routes(void)
890 {
891 lxi_run_routeinfo(lxi_net_linklocal_route);
892 }
893
894
895 static void
896 lxi_net_static_routes(void)
897 {
898 lxi_run_routeinfo(lxi_net_static_route);
899 }
900
901 static void
902 lxi_config_close(zone_dochandle_t handle)
903 {
904 zonecfg_fini_handle(handle);
905 }
906
907 static void
908 lxi_hook_postnet()
909 {
910 char cmd[MAXPATHLEN];
911 const char *zroot = zone_get_nroot();
912 pid_t pid;
913 int status;
914
915 (void) snprintf(cmd, sizeof (cmd), "%s%s", zroot, HOOK_POSTNET_PATH);
916 if (access(cmd, X_OK) != 0) {
917 /* If no suitable script is present, soldier on. */
918 return;
919 }
920
921 if ((pid = fork()) < 0) {
986 * the face of failure to log the error.
987 */
988 lxi_log_open();
989 lxi_err("execve(%s) failed: %s", cmd, strerror(e));
990 }
991
992 /*ARGSUSED*/
993 int
994 main(int argc, char *argv[])
995 {
996 zone_dochandle_t handle;
997
998 lxi_log_open();
999
1000 lxi_net_ipmgmtd_start();
1001 lxi_net_ipadm_open();
1002
1003 handle = lxi_config_open();
1004 lxi_net_loopback();
1005 lxi_net_setup(handle);
1006
1007 lxi_net_linklocal_routes();
1008 lxi_net_setup_gateways(handle);
1009
1010 lxi_config_close(handle);
1011
1012 lxi_net_static_routes();
1013
1014 lxi_net_ipadm_close();
1015
1016 lxi_hook_postnet();
1017
1018 lxi_log_close();
1019
1020 lxi_init_exec(argv);
1021
1022 /* NOTREACHED */
1023 return (0);
1024 }
|