Print this page
want lxinit to support link-local routes


 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 }