~hww3/illumos-joyent

ca3ac5d14aed1ff63df95e45864c8a92a4cc18e7 — William Welliver 4 years ago 5cdedf9
Support link-local routes in lx brand zones
1 files changed, 217 insertions(+), 11 deletions(-)

M usr/src/lib/brand/lx/lx_init/lxinit.c
M usr/src/lib/brand/lx/lx_init/lxinit.c => usr/src/lib/brand/lx/lx_init/lxinit.c +217 -11
@@ 491,6 491,79 @@ lxi_iface_ipv6_link_local(const char *iface)
}

static int
lxi_iface_linklocal(const char *dst, int dstpfx, const char *gwaddr)
{
    int len, sockfd;
    char rtbuf[RTMBUFSZ];
    struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
    struct sockaddr_in *dst_sin = (struct sockaddr_in *)
            (rtbuf + sizeof (struct rt_msghdr));
    struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(dst_sin + 1);
    struct sockaddr_in *gw_sin = (struct sockaddr_in *)(netmask_sin + 1);

    (void) bzero(rtm, RTMBUFSZ);
    rtm->rtm_addrs = RTA_IFA | RTA_DST | RTA_NETMASK;
    rtm->rtm_flags = RTF_UP | RTF_STATIC;
    if(dstpfx == 32)
      rtm->rtm_flags |= RTF_HOST;
    rtm->rtm_msglen = sizeof (rtbuf);
    rtm->rtm_pid = getpid();
    rtm->rtm_type = RTM_ADD;
    rtm->rtm_version = RTM_VERSION;


    /*
     * The destination and netmask components have already been zeroed,
     * which represents the default gateway.  If we were passed a more
     * specific destination network, use that instead.
     */
    dst_sin->sin_family = AF_INET;
    netmask_sin->sin_family = AF_INET;
    if (dst != NULL) {
        struct sockaddr *mask = (struct sockaddr *)netmask_sin;

        if ((inet_pton(AF_INET, dst, &(dst_sin->sin_addr))) != 1 ||
            plen2mask(dstpfx, AF_INET, mask) != 0) {
            lxi_warn("bad destination network %s/%d: %s", dst,
                     dstpfx, strerror(errno));
            return (-1);
        }
    }

    if ((inet_pton(AF_INET, gwaddr, &(gw_sin->sin_addr))) != 1) {
        lxi_warn("bad gateway %s: %s", gwaddr, strerror(errno));
        return (-1);
    }

/*    if (iface != NULL) {
        if ((idx = if_nametoindex(iface)) == 0) {
            lxi_warn("unable to get interface index for %s: %s\n",
                     iface, strerror(errno));
            return (-1);
        }
        rtm->rtm_index = idx;
    }*/

    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
        lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
        return (-1);
    }

    if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
        lxi_warn("could not write rtmsg: %s", strerror(errno));
        close(sockfd);
        return (-1);
    } else if (len < rtm->rtm_msglen) {
        lxi_warn("write() rtmsg incomplete");
        close(sockfd);
        return (-1);
    }

    close(sockfd);
    return (0);
}

static int
lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
    const char *gwaddr)
{


@@ 634,7 707,7 @@ lxi_net_setup(zone_dochandle_t handle)
	while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
		const char *iface = lookup.zone_nwif_physical;
		struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
		const char *ipaddrs, *primary, *gateway;
		const char *ipaddrs;
		char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
		    *ipaddr, *tmp, *lasts;
		boolean_t first_ipv4_configured = B_FALSE;


@@ 684,12 757,6 @@ lxi_net_setup(zone_dochandle_t handle)
				    "to interface %s", ipaddr, iface);
			}
		}

		if (zone_find_attr(attrs, "primary", &primary) == 0 &&
		    strncmp(primary, "true", MAXNAMELEN) == 0 &&
		    zone_find_attr(attrs, "gateway", &gateway) == 0) {
			lxi_iface_gateway(iface, NULL, 0, gateway);
		}
	}

	if (do_addrconf) {


@@ 700,6 767,113 @@ lxi_net_setup(zone_dochandle_t handle)
}

static void
lxi_net_setup_gateways(zone_dochandle_t handle)
{
    struct zone_nwiftab lookup;

    if (zonecfg_setnwifent(handle) != Z_OK)
        return;
    while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
        const char *iface = lookup.zone_nwif_physical;
        struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
        const char *primary, *gateway;

        if (zone_find_attr(attrs, "primary", &primary) == 0 &&
            strncmp(primary, "true", MAXNAMELEN) == 0 &&
            zone_find_attr(attrs, "gateway", &gateway) == 0) {
            lxi_iface_gateway(iface, NULL, 0, gateway);
        }
    }

    (void) zonecfg_endnwifent(handle);
}

static void
lxi_net_linklocal_route(const char *line)
{
    /*
     * Each link-local route line is a string of the form:
     *
     *	"10.77.77.2|10.1.1.0/24|true"
     *
     * i.e. gateway address, destination network, and whether this is
     * a "link local" route or a next hop route.
     */
    custr_t *cu = NULL;
    char *gw = NULL, *dst = NULL;
    int pfx = -1;
    int i;

    if (custr_alloc(&cu) != 0) {
        lxi_err("custr_alloc failure");
    }

    for (i = 0; line[i] != '\0'; i++) {
        if (gw == NULL) {
            if (line[i] == '|') {
                if ((gw = strdup(custr_cstr(cu))) == NULL) {
                    lxi_err("strdup failure");
                }
                custr_reset(cu);
            } else {
                if (custr_appendc(cu, line[i]) != 0) {
                    lxi_err("custr_appendc failure");
                }
            }
            continue;
        }

        if (dst == NULL) {
            if (line[i] == '|') {
                if ((dst = strdup(custr_cstr(cu))) == NULL) {
                    lxi_err("strdup failure");
                }
                custr_reset(cu);
            } else {
                if (custr_appendc(cu, line[i]) != 0) {
                    lxi_err("custr_appendc failure");
                }
            }
            continue;
        }

        if (pfx == -1) {
            if (line[i] == '|') {
                pfx = atoi(custr_cstr(cu));
                custr_reset(cu);
            } else {
                if (custr_appendc(cu, line[i]) != 0) {
                    lxi_err("custr_appendc failure");
                }
            }
            continue;
        }

        if (custr_appendc(cu, line[i]) != 0) {
            lxi_err("custr_appendc failure");
        }
    }

    /*
     * We currently only support link-local routes, so ensure that
     * "linklocal" is true:
     */
    lxi_warn("cu: %s\n", custr_cstr(cu));
    if (strcmp(custr_cstr(cu), "true") != 0) {
        lxi_warn("skipping next-hop route: %s", line);
    } else 
      if (lxi_iface_linklocal(dst, pfx, gw) != 0) {
        lxi_err("failed to add link local route: %s/%d -> %s", dst, pfx, gw);
      }
    

    custr_free(cu);
    free(gw);
    free(dst);
}


static void
lxi_net_static_route(const char *line)
{
	/*


@@ 770,10 944,8 @@ lxi_net_static_route(const char *line)
	 * "linklocal" is false:
	 */
	if (strcmp(custr_cstr(cu), "false") != 0) {
		lxi_warn("invalid static route: %s", line);
	}

	if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
		lxi_warn("skipping link-local route: %s", line);
	} else if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
		lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
	}



@@ 783,6 955,36 @@ lxi_net_static_route(const char *line)
}

static void
lxi_net_linklocal_routes(void)
{
    const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
    char *const argv[] = { "routeinfo", NULL };
    char *const envp[] = { NULL };
    int code;
    struct stat st;
    char errbuf[512];

    if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
        /*
         * This binary is (potentially) shipped from another
         * consolidation.  If it does not exist, then the platform does
         * not currently support static routes for LX-branded zones.
         */
        return;
    }

    /*
     * Run the command, firing the callback for each line that it
     * outputs.  When this function returns, static route processing
     * is complete.
     */
    if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
                    lxi_net_linklocal_route, &code) != 0 || code != 0) {
        lxi_err("failed to run \"%s\": %s", cmd, errbuf);
    }
}

static void
lxi_net_static_routes(void)
{
	const char *cmd = "/native/usr/lib/brand/lx/routeinfo";


@@ 917,6 1119,10 @@ main(int argc, char *argv[])
	handle = lxi_config_open();
	lxi_net_loopback();
	lxi_net_setup(handle);

	lxi_net_linklocal_routes();
    lxi_net_setup_gateways(handle);

	lxi_config_close(handle);

	lxi_net_static_routes();