Print this page
want lxinit to support link-local routes
*** 488,512 ****
(void) close(s);
return (0);
}
static int
lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
! const char *gwaddr)
{
! int idx, 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 *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
(void) bzero(rtm, RTMBUFSZ);
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
rtm->rtm_msglen = sizeof (rtbuf);
rtm->rtm_pid = getpid();
rtm->rtm_type = RTM_ADD;
rtm->rtm_version = RTM_VERSION;
--- 488,538 ----
(void) close(s);
return (0);
}
+ static int lxi_route_send_msg(struct rt_msghdr * rtm)
+ {
+ int sockfd, len;
+
+ 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, (const void *)rtm, 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, int llroute)
{
! int idx;
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 *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
(void) bzero(rtm, RTMBUFSZ);
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+
+ if(!llroute)
rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
+
rtm->rtm_msglen = sizeof (rtbuf);
rtm->rtm_pid = getpid();
rtm->rtm_type = RTM_ADD;
rtm->rtm_version = RTM_VERSION;
*** 514,523 ****
--- 540,558 ----
/*
* 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.
*/
+
+ if(dstpfx == -1) {
+ /*
+ * no prefix was specified; assume a prefix length of 32,
+ * which seems in line with the behavior of vmadm.
+ */
+ dstpfx = 32;
+ }
+
dst_sin->sin_family = AF_INET;
netmask_sin->sin_family = AF_INET;
if (dst != NULL) {
struct sockaddr *mask = (struct sockaddr *)netmask_sin;
*** 541,567 ****
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 void
lxi_net_loopback()
{
--- 576,586 ----
return (-1);
}
rtm->rtm_index = idx;
}
! return lxi_route_send_msg(rtm);
}
static void
lxi_net_loopback()
{
*** 632,642 ****
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 *ipaddrs, *primary, *gateway;
char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
*ipaddr, *tmp, *lasts;
boolean_t first_ipv4_configured = B_FALSE;
boolean_t *ficp = &first_ipv4_configured;
--- 651,661 ----
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 *ipaddrs;
char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
*ipaddr, *tmp, *lasts;
boolean_t first_ipv4_configured = B_FALSE;
boolean_t *ficp = &first_ipv4_configured;
*** 682,731 ****
} else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
lxi_warn("Unable to add new IP address (%s) "
"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) {
lxi_net_ndpd_start();
}
(void) zonecfg_endnwifent(handle);
}
static void
! lxi_net_static_route(const char *line)
{
! /*
! * Each static route line is a string of the form:
! *
! * "10.77.77.2|10.1.1.0/24|false"
! *
! * 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");
--- 701,754 ----
} else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
lxi_warn("Unable to add new IP address (%s) "
"to interface %s", ipaddr, iface);
}
}
}
if (do_addrconf) {
lxi_net_ndpd_start();
}
(void) zonecfg_endnwifent(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, 0);
}
+ }
+ (void) zonecfg_endnwifent(handle);
+ }
+
+ static void
+ lxi_parse_route_line(const char *line, custr_t *cu, char *gw, char *dst, int* pfx, int gwlen, int dstlen)
+ {
+ int i;
+ int havegw = 0, havedst = 0, nopfx = 0;
+
for (i = 0; line[i] != '\0'; i++) {
! if (!havegw) {
if (line[i] == '|') {
! if ((strlcpy(gw, custr_cstr(cu), gwlen) ) == 0) {
! lxi_err("strlcpy failure");
! } else {
! havegw = 1;
}
custr_reset(cu);
} else {
if (custr_appendc(cu, line[i]) != 0) {
lxi_err("custr_appendc failure");
*** 732,758 ****
}
}
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");
}
--- 755,786 ----
}
}
continue;
}
! if (!havedst) {
! if (line[i] == '/' || line[i] == '|') {
! if ((strlcpy(dst, custr_cstr(cu), dstlen)) == 0) {
! lxi_err("strlcpy failure");
! } else {
! havedst = 1;
! if(line[i] == '|') {
! nopfx = 1;
}
+ }
custr_reset(cu);
} else {
if (custr_appendc(cu, line[i]) != 0) {
lxi_err("custr_appendc failure");
}
}
continue;
}
! if (*pfx == -1 && !nopfx) {
if (line[i] == '|') {
! *pfx = atoi(custr_cstr(cu));
custr_reset(cu);
} else {
if (custr_appendc(cu, line[i]) != 0) {
lxi_err("custr_appendc failure");
}
*** 763,791 ****
if (custr_appendc(cu, line[i]) != 0) {
lxi_err("custr_appendc failure");
}
}
/*
! * We currently only support "next hop" routes, so ensure that
! * "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_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
}
custr_free(cu);
- free(gw);
- free(dst);
}
static void
! lxi_net_static_routes(void)
{
const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
char *const argv[] = { "routeinfo", NULL };
char *const envp[] = { NULL };
int code;
--- 791,864 ----
if (custr_appendc(cu, line[i]) != 0) {
lxi_err("custr_appendc failure");
}
}
+ return;
+ }
+
+ static void
+ lxi_net_process_route_line(const char *line, int llonly)
+ {
/*
! * Each static route line is a string of the form:
! *
! * "10.77.77.2|10.1.1.0/24|false"
! *
! * i.e. gateway address, destination network, and whether this is
! * a "link local" route or a next hop route.
! *
! * passing a true value to the llonly argument to this method causes only
! * those lines with the link-local flag to be processed and vice-versa
*/
! custr_t *cu = NULL;
! int pfx = -1;
! char gw[INET6_ADDRSTRLEN];
! char dst[INET6_ADDRSTRLEN];
!
! if (custr_alloc(&cu) != 0) {
! lxi_err("custr_alloc failure");
}
! lxi_parse_route_line(line, cu, gw, dst, &pfx, sizeof(gw), sizeof(dst));
!
! if (llonly && strcmp(custr_cstr(cu), "true") == 0) {
! if (lxi_iface_gateway(NULL, dst, pfx, gw, 1) != 0) {
! lxi_err("failed to add link-local route: %s/%d -> %s", dst, pfx, gw);
}
+ } else if(!llonly && strcmp(custr_cstr(cu), "false") == 0) {
+ if (lxi_iface_gateway(NULL, dst, pfx, gw, 0) != 0) {
+ lxi_err("failed to add next-hop route: %s/%d -> %s", dst, pfx, gw);
+ }
+ } else if(strcmp(custr_cstr(cu), "true") != 0 && strcmp(custr_cstr(cu), "false") != 0) {
+ /*
+ * try to be helpful when we encounter something we don't expect.
+ */
+ lxi_warn("skipping unknown static route defined in line %s, parsed link-local flag=%s", line, custr_cstr(cu));
+ }
custr_free(cu);
}
static void
! lxi_net_static_route(const char * line) {
! /*
! * process only those lines where the link-local field is false.
! */
! lxi_net_process_route_line(line, 0);
! }
!
! static void
! lxi_net_linklocal_route(const char * line) {
! /*
! * processes only those lines where the link-local field is true.
! */
! lxi_net_process_route_line(line, 1);
! }
!
! static void
! lxi_run_routeinfo(void * callback)
{
const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
char *const argv[] = { "routeinfo", NULL };
char *const envp[] = { NULL };
int code;
*** 794,804 ****
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;
}
/*
--- 867,877 ----
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 link-local or static routes for LX-branded zones.
*/
return;
}
/*
*** 805,820 ****
* 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_static_route, &code) != 0 || code != 0) {
lxi_err("failed to run \"%s\": %s", cmd, errbuf);
}
}
static void
lxi_config_close(zone_dochandle_t handle)
{
zonecfg_fini_handle(handle);
}
--- 878,906 ----
* 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),
! callback, &code) != 0 || code != 0) {
lxi_err("failed to run \"%s\": %s", cmd, errbuf);
}
}
static void
+ lxi_net_linklocal_routes(void)
+ {
+ lxi_run_routeinfo(lxi_net_linklocal_route);
+ }
+
+
+ static void
+ lxi_net_static_routes(void)
+ {
+ lxi_run_routeinfo(lxi_net_static_route);
+ }
+
+ static void
lxi_config_close(zone_dochandle_t handle)
{
zonecfg_fini_handle(handle);
}
*** 915,924 ****
--- 1001,1014 ----
lxi_net_ipadm_open();
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();
lxi_net_ipadm_close();