Print this page
want lxinit to support link-local routes

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
↓ open down ↓ 482 lines elided ↑ open up ↑
 483  483          if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
 484  484                  lxi_warn("SIOCSLIFFLAGS error %d: bringing up %s: %s",
 485  485                      errno, iface, strerror(errno));
 486  486                  return (-1);
 487  487          }
 488  488  
 489  489          (void) close(s);
 490  490          return (0);
 491  491  }
 492  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 +
 493  516  static int
 494  517  lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
 495      -    const char *gwaddr)
      518 +    const char *gwaddr, int llroute)
 496  519  {
 497      -        int idx, len, sockfd;
      520 +        int idx;
 498  521          char rtbuf[RTMBUFSZ];
 499  522          struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
 500  523          struct sockaddr_in *dst_sin = (struct sockaddr_in *)
 501  524              (rtbuf + sizeof (struct rt_msghdr));
 502  525          struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
 503  526          struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
 504  527  
 505  528          (void) bzero(rtm, RTMBUFSZ);
 506  529          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);
      530 +        
      531 +        if(!llroute) 
      532 +          rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
      533 +        
      534 +        rtm->rtm_msglen = sizeof (rtbuf);
 509  535          rtm->rtm_pid = getpid();
 510  536          rtm->rtm_type = RTM_ADD;
 511  537          rtm->rtm_version = RTM_VERSION;
 512  538  
 513  539  
 514  540          /*
 515  541           * The destination and netmask components have already been zeroed,
 516  542           * which represents the default gateway.  If we were passed a more
 517  543           * specific destination network, use that instead.
 518  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 +
 519  554          dst_sin->sin_family = AF_INET;
 520  555          netmask_sin->sin_family = AF_INET;
 521  556          if (dst != NULL) {
 522  557                  struct sockaddr *mask = (struct sockaddr *)netmask_sin;
 523  558  
 524  559                  if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
 525  560                      plen2mask(dstpfx, AF_INET, mask) != 0) {
 526  561                          lxi_warn("bad destination network %s/%d: %s", dst,
 527  562                              dstpfx, strerror(errno));
 528  563                          return (-1);
↓ open down ↓ 7 lines elided ↑ open up ↑
 536  571  
 537  572          if (iface != NULL) {
 538  573                  if ((idx = if_nametoindex(iface)) == 0) {
 539  574                          lxi_warn("unable to get interface index for %s: %s\n",
 540  575                              iface, strerror(errno));
 541  576                          return (-1);
 542  577                  }
 543  578                  rtm->rtm_index = idx;
 544  579          }
 545  580  
 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);
      581 +        return lxi_route_send_msg(rtm);
 563  582  }
 564  583  
 565  584  static void
 566  585  lxi_net_loopback()
 567  586  {
 568  587          const char *iface = "lo0";
 569  588          boolean_t first_ipv4_configured = B_FALSE;
 570  589  
 571  590          lxi_net_plumb(iface);
 572  591          (void) lxi_iface_ip(iface, "127.0.0.1/8", &first_ipv4_configured);
↓ open down ↓ 54 lines elided ↑ open up ↑
 627  646  lxi_net_setup(zone_dochandle_t handle)
 628  647  {
 629  648          struct zone_nwiftab lookup;
 630  649          boolean_t do_addrconf = B_FALSE;
 631  650  
 632  651          if (zonecfg_setnwifent(handle) != Z_OK)
 633  652                  return;
 634  653          while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
 635  654                  const char *iface = lookup.zone_nwif_physical;
 636  655                  struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
 637      -                const char *ipaddrs, *primary, *gateway;
      656 +                const char *ipaddrs;
 638  657                  char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
 639  658                      *ipaddr, *tmp, *lasts;
 640  659                  boolean_t first_ipv4_configured = B_FALSE;
 641  660                  boolean_t *ficp = &first_ipv4_configured;
 642  661  
 643  662                  lxi_net_plumb(iface);
 644  663                  if (zone_find_attr(attrs, "ips", &ipaddrs) != 0 &&
 645  664                      lxi_get_old_ip(attrs, &ipaddrs, cidraddr, BUFSIZ) != 0) {
 646  665                          lxi_warn("Could not find a valid network configuration "
 647  666                              "for the %s interface", iface);
↓ open down ↓ 29 lines elided ↑ open up ↑
 677  696                          tmp = NULL;
 678  697                          if (strcmp(ipaddr, "addrconf") == 0) {
 679  698                                  do_addrconf = B_TRUE;
 680  699                          } else if (strcmp(ipaddr, "dhcp") == 0) {
 681  700                                  continue;
 682  701                          } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
 683  702                                  lxi_warn("Unable to add new IP address (%s) "
 684  703                                      "to interface %s", ipaddr, iface);
 685  704                          }
 686  705                  }
 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  706          }
 694  707  
 695  708          if (do_addrconf) {
 696  709                  lxi_net_ndpd_start();
 697  710          }
 698  711  
 699  712          (void) zonecfg_endnwifent(handle);
 700  713  }
 701  714  
 702  715  static void
 703      -lxi_net_static_route(const char *line)
      716 +lxi_net_setup_gateways(zone_dochandle_t handle)
 704  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 +{
 705  802          /*
 706  803           * Each static route line is a string of the form:
 707  804           *
 708  805           *      "10.77.77.2|10.1.1.0/24|false"
 709  806           *
 710  807           * i.e. gateway address, destination network, and whether this is
 711  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
 712  812           */
 713  813          custr_t *cu = NULL;
 714      -        char *gw = NULL, *dst = NULL;
 715  814          int pfx = -1;
 716      -        int i;
      815 +        char gw[INET6_ADDRSTRLEN];
      816 +        char dst[INET6_ADDRSTRLEN];
 717  817  
 718  818          if (custr_alloc(&cu) != 0) {
 719  819                  lxi_err("custr_alloc failure");
 720  820          }
 721  821  
 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      -                }
      822 +        lxi_parse_route_line(line, cu, gw, dst, &pfx, sizeof(gw), sizeof(dst));
 736  823  
 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      -                }
      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 +        }
 750  838  
 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      -                }
      839 +        custr_free(cu);
      840 +}
 762  841  
 763      -                if (custr_appendc(cu, line[i]) != 0) {
 764      -                        lxi_err("custr_appendc failure");
 765      -                }
 766      -        }
      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 +}
 767  849  
      850 +static void 
      851 +lxi_net_linklocal_route(const char * line) {
 768  852          /*
 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      -        }
      853 +         * processes only those lines where the link-local field is true.
      854 +         */
      855 +        lxi_net_process_route_line(line, 1); 
      856 +}
 775  857  
 776      -        if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
 777      -                lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
 778      -        }
      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 +    }
 779  876  
 780      -        custr_free(cu);
 781      -        free(gw);
 782      -        free(dst);
      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 +    }
 783  886  }
 784  887  
 785  888  static void
 786      -lxi_net_static_routes(void)
      889 +lxi_net_linklocal_routes(void)
 787  890  {
 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];
      891 +        lxi_run_routeinfo(lxi_net_linklocal_route);
      892 +}
 794  893  
 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  894  
 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      -        }
      895 +static void
      896 +lxi_net_static_routes(void)
      897 +{
      898 +        lxi_run_routeinfo(lxi_net_static_route);
 813  899  }
 814  900  
 815  901  static void
 816  902  lxi_config_close(zone_dochandle_t handle)
 817  903  {
 818  904          zonecfg_fini_handle(handle);
 819  905  }
 820  906  
 821  907  static void
 822  908  lxi_hook_postnet()
↓ open down ↓ 87 lines elided ↑ open up ↑
 910  996          zone_dochandle_t handle;
 911  997  
 912  998          lxi_log_open();
 913  999  
 914 1000          lxi_net_ipmgmtd_start();
 915 1001          lxi_net_ipadm_open();
 916 1002  
 917 1003          handle = lxi_config_open();
 918 1004          lxi_net_loopback();
 919 1005          lxi_net_setup(handle);
     1006 +
     1007 +        lxi_net_linklocal_routes();
     1008 +        lxi_net_setup_gateways(handle);
     1009 +
 920 1010          lxi_config_close(handle);
 921 1011  
 922 1012          lxi_net_static_routes();
 923 1013  
 924 1014          lxi_net_ipadm_close();
 925 1015  
 926 1016          lxi_hook_postnet();
 927 1017  
 928 1018          lxi_log_close();
 929 1019  
 930 1020          lxi_init_exec(argv);
 931 1021  
 932 1022          /* NOTREACHED */
 933 1023          return (0);
 934 1024  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX