summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-inet
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cmd-inet')
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile2
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c56
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h3
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c173
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c201
-rw-r--r--usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c17
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c3
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c46
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/route.c6
9 files changed, 465 insertions, 42 deletions
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile
index 4e7f342ed5..73ec4241c2 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile
@@ -44,7 +44,7 @@ $(ROOTCFGFILES) := FILEMODE= 644
ROOTCMDDIR= $(ROOTFS_LIBDIR)/inet
-LDLIBS += -lipadm -lnvpair -lsecdb -lnsl -lumem
+LDLIBS += -lipadm -lnvpair -lsecdb -lnsl -lumem -lscf
#
# Instrument ipmgmtd with CTF data to ease debugging.
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
index 54472333d2..8e9e153b21 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
@@ -554,33 +554,9 @@ i_ipmgmt_delif_aobjs(char *ifname, sa_family_t af, uint32_t flags)
static void
ipmgmt_setif_handler(void *argp)
{
- ipmgmt_if_arg_t *sargp = argp;
ipmgmt_retval_t rval;
- ipadm_dbwrite_cbarg_t cb;
- uint32_t flags = sargp->ia_flags;
- nvlist_t *nvl = NULL;
- int err = 0;
- char strval[IPMGMT_STRSIZE];
- if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
- sargp->ia_ifname[0] == '\0') {
- err = EINVAL;
- goto ret;
- }
- if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
- goto ret;
- if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
- sargp->ia_ifname)) != 0)
- goto ret;
- (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
- if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
- goto ret;
- cb.dbw_nvl = nvl;
- cb.dbw_flags = 0;
- err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
-ret:
- rval.ir_err = err;
- nvlist_free(nvl);
+ rval.ir_err = ipmgmt_persist_if(argp);
(void) door_return((char *)&rval, sizeof (rval), NULL, 0);
}
@@ -856,3 +832,33 @@ fail:
rvalp->ir_err = err;
(void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
}
+
+int
+ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
+{
+ ipadm_dbwrite_cbarg_t cb;
+ uint32_t flags = sargp->ia_flags;
+ nvlist_t *nvl = NULL;
+ int err = 0;
+ char strval[IPMGMT_STRSIZE];
+
+ if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
+ sargp->ia_ifname[0] == '\0') {
+ err = EINVAL;
+ goto ret;
+ }
+ if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
+ goto ret;
+ if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
+ sargp->ia_ifname)) != 0)
+ goto ret;
+ (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
+ if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
+ goto ret;
+ cb.dbw_nvl = nvl;
+ cb.dbw_flags = 0;
+ err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
+ret:
+ nvlist_free(nvl);
+ return (err);
+}
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h
index f693a34266..36768b5ae0 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h
@@ -38,6 +38,7 @@ extern "C" {
#include <pthread.h>
#define IPMGMT_STRSIZE 256
+#define IPMGMTD_FMRI "svc:/network/ip-interface-management:default"
/* ipmgmt_door.c */
extern void ipmgmt_handler(void *, char *, size_t, door_desc_t *, uint_t);
@@ -145,6 +146,8 @@ extern boolean_t ipmgmt_aobjmap_init(void *, nvlist_t *, char *,
extern int ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *,
ipadm_db_op_t);
+extern boolean_t ipmgmt_first_boot();
+extern int ipmgmt_persist_if(ipmgmt_if_arg_t *);
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c
index 011126d010..63b1e48a89 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -63,6 +62,13 @@
#include <sys/stat.h>
#include <unistd.h>
#include "ipmgmt_impl.h"
+#include <zone.h>
+#include <libipadm.h>
+#include <libdladm.h>
+#include <libdllink.h>
+#include <net/route.h>
+#include <ipadm_ipmgmt.h>
+#include <sys/brand.h>
const char *progname;
@@ -81,6 +87,18 @@ static int ipmgmt_door_fd = -1;
static void ipmgmt_exit(int);
static int ipmgmt_init();
static int ipmgmt_init_privileges();
+static void ipmgmt_ngz_init();
+static void ipmgmt_ngz_persist_if();
+
+static ipadm_handle_t iph;
+typedef struct ipmgmt_pif_s {
+ struct ipmgmt_pif_s *pif_next;
+ char pif_ifname[LIFNAMSIZ];
+ boolean_t pif_v4;
+ boolean_t pif_v6;
+} ipmgmt_pif_t;
+
+static ipmgmt_pif_t *ngz_pifs;
static int
ipmgmt_db_init()
@@ -115,6 +133,9 @@ ipmgmt_db_init()
}
(void) pthread_rwlock_init(&ipmgmt_dbconf_lock, NULL);
+
+ ipmgmt_ngz_persist_if(); /* create persistent interface info for NGZ */
+
return (err);
}
@@ -214,11 +235,89 @@ ipmgmt_exit(int signo)
}
/*
- * Set the uid of this daemon to the "ipadm" user. Finish the following
+ * On the first reboot after installation of an ipkg zone,
+ * ipmgmt_persist_if_cb() is used in non-global zones to track the interfaces
+ * that have IP address configuration assignments from the global zone.
+ * Persistent configuration for the interfaces is created on the first boot
+ * by ipmgmtd, and the addresses assigned to the interfaces by the GZ
+ * will be subsequently configured when the interface is enabled.
+ * Note that ipmgmt_persist_if_cb() only sets up a list of interfaces
+ * that need to be persisted- the actual update of the ipadm data-store happens
+ * in ipmgmt_persist_if() after the appropriate privs/uid state has been set up.
+ */
+static void
+ipmgmt_persist_if_cb(char *ifname, boolean_t v4, boolean_t v6)
+{
+ ipmgmt_pif_t *pif;
+
+ pif = calloc(1, sizeof (*pif));
+ if (pif == NULL) {
+ ipmgmt_log(LOG_WARNING,
+ "Could not allocate memory to configure %s", ifname);
+ return;
+ }
+ (void) strlcpy(pif->pif_ifname, ifname, sizeof (pif->pif_ifname));
+ pif->pif_v4 = v4;
+ pif->pif_v6 = v6;
+ pif->pif_next = ngz_pifs;
+ ngz_pifs = pif;
+}
+
+/*
+ * ipmgmt_ngz_init() initializes exclusive-IP stack non-global zones by
+ * extracting configuration that has been saved in the kernel and applying
+ * it at zone boot.
+ */
+static void
+ipmgmt_ngz_init()
+{
+ zoneid_t zoneid;
+ boolean_t firstboot = B_TRUE, s10c = B_FALSE;
+ char brand[MAXNAMELEN];
+ ipadm_status_t ipstatus;
+
+ zoneid = getzoneid();
+ if (zoneid != GLOBAL_ZONEID) {
+
+ if (zone_getattr(zoneid, ZONE_ATTR_BRAND, brand,
+ sizeof (brand)) < 0) {
+ ipmgmt_log(LOG_ERR, "Could not get brand name");
+ return;
+ }
+ /*
+ * firstboot is always true for S10C zones, where ipadm is not
+ * available for restoring persistent configuration.
+ */
+ if (strcmp(brand, NATIVE_BRAND_NAME) == 0)
+ firstboot = ipmgmt_first_boot();
+ else
+ s10c = B_TRUE;
+
+ if (!firstboot)
+ return;
+
+ ipstatus = ipadm_open(&iph, IPH_IPMGMTD);
+ if (ipstatus != IPADM_SUCCESS) {
+ ipmgmt_log(LOG_ERR, "could not open ipadm handle",
+ ipadm_status2str(ipstatus));
+ return;
+ }
+ /*
+ * Only pass down the callback to persist the interface
+ * for NATIVE (ipkg) zones.
+ */
+ (void) ipadm_init_net_from_gz(iph, NULL,
+ (s10c ? NULL : ipmgmt_persist_if_cb));
+ ipadm_close(iph);
+ }
+}
+
+/*
+ * Set the uid of this daemon to the "netadm" user. Finish the following
* operations before setuid() because they need root privileges:
*
* - create the /etc/svc/volatile/ipadm directory;
- * - change its uid/gid to "ipadm"/"sys";
+ * - change its uid/gid to "netadm"/"netadm";
*/
static int
ipmgmt_init_privileges()
@@ -246,6 +345,14 @@ ipmgmt_init_privileges()
}
/*
+ * initialize any NGZ specific network information before dropping
+ * privileges. We need these privileges to plumb IP interfaces handed
+ * down from the GZ (for dlpi_open() etc.) and also to configure the
+ * address itself (for any IPI_PRIV ioctls like SLIFADDR)
+ */
+ ipmgmt_ngz_init();
+
+ /*
* limit the privileges of this daemon and set the uid of this
* daemon to UID_NETADM
*/
@@ -380,3 +487,61 @@ child_out:
ipmgmt_inform_parent_exit(EXIT_FAILURE);
return (EXIT_FAILURE);
}
+
+/*
+ * Return TRUE if `ifname' has persistent configuration for the `af' address
+ * family in the datastore
+ */
+static boolean_t
+ipmgmt_persist_if_exists(char *ifname, sa_family_t af)
+{
+ ipmgmt_getif_cbarg_t cbarg;
+ boolean_t exists = B_FALSE;
+ ipadm_if_info_t *ifp;
+
+ bzero(&cbarg, sizeof (cbarg));
+ cbarg.cb_ifname = ifname;
+ (void) ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
+ if ((ifp = cbarg.cb_ifinfo) != NULL) {
+ if ((af == AF_INET && (ifp->ifi_pflags & IFIF_IPV4)) ||
+ (af == AF_INET6 && (ifp->ifi_pflags & IFIF_IPV6))) {
+ exists = B_TRUE;
+ }
+ }
+ free(ifp);
+ return (exists);
+}
+
+/*
+ * Persist any NGZ interfaces assigned to us from the global zone if they do
+ * not already exist in the persistent db. We need to
+ * do this before any calls to ipadm_enable_if() can succeed (i.e.,
+ * before opening up for door_calls), and after setuid to 'netadm' so that
+ * the persistent db is created with the right permissions.
+ */
+static void
+ipmgmt_ngz_persist_if()
+{
+ ipmgmt_pif_t *pif, *next;
+ ipmgmt_if_arg_t ifarg;
+
+ for (pif = ngz_pifs; pif != NULL; pif = next) {
+ next = pif->pif_next;
+ bzero(&ifarg, sizeof (ifarg));
+ (void) strlcpy(ifarg.ia_ifname, pif->pif_ifname,
+ sizeof (ifarg.ia_ifname));
+ ifarg.ia_flags = IPMGMT_PERSIST;
+ if (pif->pif_v4 &&
+ !ipmgmt_persist_if_exists(pif->pif_ifname, AF_INET)) {
+ ifarg.ia_family = AF_INET;
+ (void) ipmgmt_persist_if(&ifarg);
+ }
+ if (pif->pif_v6 &&
+ !ipmgmt_persist_if_exists(pif->pif_ifname, AF_INET6)) {
+ ifarg.ia_family = AF_INET6;
+ (void) ipmgmt_persist_if(&ifarg);
+ }
+ free(pif);
+ }
+ ngz_pifs = NULL; /* no red herrings */
+}
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
index 09275519a6..25e2f3a5ee 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
@@ -56,6 +56,7 @@
#include <arpa/inet.h>
#include <unistd.h>
#include "ipmgmt_impl.h"
+#include <libscf.h>
#define ATYPE "_atype" /* name of the address type nvpair */
#define FLAGS "_flags" /* name of the flags nvpair */
@@ -1164,3 +1165,203 @@ ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op)
}
return (err);
}
+
+typedef struct scf_resources {
+ scf_handle_t *sr_handle;
+ scf_instance_t *sr_inst;
+ scf_propertygroup_t *sr_pg;
+ scf_property_t *sr_prop;
+ scf_value_t *sr_val;
+ scf_transaction_t *sr_tx;
+ scf_transaction_entry_t *sr_ent;
+} scf_resources_t;
+
+/*
+ * Inputs:
+ * res is a pointer to the scf_resources_t to be released.
+ */
+static void
+ipmgmt_release_scf_resources(scf_resources_t *res)
+{
+ scf_entry_destroy(res->sr_ent);
+ scf_transaction_destroy(res->sr_tx);
+ scf_value_destroy(res->sr_val);
+ scf_property_destroy(res->sr_prop);
+ scf_pg_destroy(res->sr_pg);
+ scf_instance_destroy(res->sr_inst);
+ (void) scf_handle_unbind(res->sr_handle);
+ scf_handle_destroy(res->sr_handle);
+}
+
+/*
+ * Inputs:
+ * fmri is the instance to look up
+ * Outputs:
+ * res is a pointer to an scf_resources_t. This is an internal
+ * structure that holds all the handles needed to get a specific
+ * property from the running snapshot; on a successful return it
+ * contains the scf_value_t that should be passed to the desired
+ * scf_value_get_foo() function, and must be freed after use by
+ * calling release_scf_resources(). On a failure return, any
+ * resources that may have been assigned to res are released, so
+ * the caller does not need to do any cleanup in the failure case.
+ * Returns:
+ * 0 on success
+ * -1 on failure
+ */
+
+static int
+ipmgmt_create_scf_resources(const char *fmri, scf_resources_t *res)
+{
+ res->sr_tx = NULL;
+ res->sr_ent = NULL;
+ res->sr_inst = NULL;
+ res->sr_pg = NULL;
+ res->sr_prop = NULL;
+ res->sr_val = NULL;
+
+ if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) {
+ return (-1);
+ }
+
+ if (scf_handle_bind(res->sr_handle) != 0) {
+ scf_handle_destroy(res->sr_handle);
+ return (-1);
+ }
+ if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL,
+ res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
+ goto failure;
+ }
+ if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) {
+ goto failure;
+ }
+ return (0);
+
+failure:
+ ipmgmt_release_scf_resources(res);
+ return (-1);
+}
+
+static int
+ipmgmt_set_property_value(scf_resources_t *res, const char *propname,
+ scf_type_t proptype)
+{
+ int result = -1;
+ boolean_t new;
+
+retry:
+ new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0);
+
+ if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) {
+ goto failure;
+ }
+ if (new) {
+ if (scf_transaction_property_new(res->sr_tx, res->sr_ent,
+ propname, proptype) == -1) {
+ goto failure;
+ }
+ } else {
+ if (scf_transaction_property_change(res->sr_tx, res->sr_ent,
+ propname, proptype) == -1) {
+ goto failure;
+ }
+ }
+
+ if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) {
+ goto failure;
+ }
+
+ result = scf_transaction_commit(res->sr_tx);
+ if (result == 0) {
+ scf_transaction_reset(res->sr_tx);
+ if (scf_pg_update(res->sr_pg) == -1) {
+ goto failure;
+ }
+ goto retry;
+ }
+ if (result == -1)
+ goto failure;
+ return (0);
+
+failure:
+ return (-1);
+}
+
+/*
+ * Returns TRUE if this is the first boot, else return FALSE. The
+ * "ipmgmtd/first_boot_done" property is persistently set up on
+ * IPMGMTD_FMRI on the first boot. Note that the presence of
+ * "first_boot_done" itself is sufficient to indicate that this is
+ * not the first boot i.e., the value of the property is immaterial.
+ */
+extern boolean_t
+ipmgmt_first_boot()
+{
+ scf_simple_prop_t *prop;
+ ssize_t numvals;
+ scf_resources_t res;
+ scf_error_t err;
+
+ if (ipmgmt_create_scf_resources(IPMGMTD_FMRI, &res) != 0)
+ return (B_TRUE); /* err on the side of caution */
+ prop = scf_simple_prop_get(res.sr_handle,
+ IPMGMTD_FMRI, "ipmgmtd", "first_boot_done");
+ numvals = scf_simple_prop_numvalues(prop);
+ if (numvals > 0) {
+ scf_simple_prop_free(prop);
+ ipmgmt_release_scf_resources(&res);
+ return (B_FALSE);
+ }
+
+ /*
+ * mark the first boot by setting ipmgmtd/first_boot_done to true
+ */
+ if (scf_instance_add_pg(res.sr_inst, "ipmgmtd", SCF_GROUP_APPLICATION,
+ 0, res.sr_pg) != 0) {
+ if ((err = scf_error()) != SCF_ERROR_EXISTS)
+ goto failure;
+ /*
+ * err == SCF_ERROR_EXISTS is by itself sufficient to declare
+ * that this is not the first boot, but we create a simple
+ * property as a place-holder, so that we don't leave an
+ * empty process group behind.
+ */
+ if (scf_instance_get_pg_composed(res.sr_inst, NULL, "ipmgmtd",
+ res.sr_pg) != 0) {
+ err = scf_error();
+ goto failure;
+ }
+ }
+
+ if (scf_value_set_astring(res.sr_val, "true") != 0) {
+ err = scf_error();
+ goto failure;
+ }
+
+ if (ipmgmt_set_property_value(&res, "first_boot_done",
+ SCF_TYPE_ASTRING) != 0) {
+ ipmgmt_log(LOG_WARNING,
+ "Could not set rval of first_boot_done");
+ }
+
+failure:
+ ipmgmt_log(LOG_WARNING, "ipmgmt_first_boot scf error %s",
+ scf_strerror(err));
+ ipmgmt_release_scf_resources(&res);
+ return (B_TRUE);
+}
diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
index 65c9d83cfb..119293f472 100644
--- a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
+++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
@@ -19,11 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1990 Mentat Inc.
* netstat.c 2.2, last change 9/9/91
* MROUTING Revision 3.5
@@ -314,8 +310,9 @@ static m_label_t *zone_security_label = NULL;
#define FLF_I 0x00000400 /* RTF_INDIRECT */
#define FLF_R 0x00000800 /* RTF_REJECT */
#define FLF_B 0x00001000 /* RTF_BLACKHOLE */
+#define FLF_Z 0x00100000 /* RTF_ZONE */
-static const char flag_list[] = "AbDGHLUMSCIRB";
+static const char flag_list[] = "AbDGHLUMSCIRBZ";
typedef struct filter_rule filter_t;
@@ -4342,6 +4339,10 @@ form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags)
(void) strcat(flags, "B");
flag_b |= FLF_B;
}
+ if (rp->ipRouteInfo.re_flags & RTF_ZONE) {
+ (void) strcat(flags, "Z");
+ flag_b |= FLF_Z;
+ }
return (flag_b);
}
@@ -4589,6 +4590,10 @@ form_v6_route_flags(const mib2_ipv6RouteEntry_t *rp6, char *flags)
(void) strcat(flags, "B");
flag_b |= FLF_B;
}
+ if (rp6->ipv6RouteInfo.re_flags & RTF_ZONE) {
+ (void) strcat(flags, "Z");
+ flag_b |= FLF_Z;
+ }
return (flag_b);
}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
index b1409d8420..a2b477c06b 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
@@ -73,7 +73,8 @@ static if_flags_t if_flags_tbl[] = {
{ IFF_DUPLICATE, "DUPLICATE" },
{ IFF_IPMP, "IPMP"},
{ IFF_VRRP, "VRRP"},
- { IFF_NOACCEPT, "NOACCEPT"}
+ { IFF_NOACCEPT, "NOACCEPT"},
+ { IFF_L3PROTECT, "L3PROTECT"}
};
typedef struct {
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
index bae4b9915e..a3b2fcd19e 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
@@ -308,7 +308,7 @@ static ofmt_field_t show_if_fields[] = {
/* name, field width, id, callback */
{ "IFNAME", 11, SI_IFNAME, print_si_cb},
{ "STATE", 9, SI_STATE, print_si_cb},
-{ "CURRENT", 12, SI_CURRENT, print_si_cb},
+{ "CURRENT", 13, SI_CURRENT, print_si_cb},
{ "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
{ NULL, 0, 0, NULL}
};
@@ -1604,6 +1604,43 @@ flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
}
}
+/*
+ * return true if the address for lifname comes to us from the global zone
+ * with 'allowed-ips' constraints.
+ */
+static boolean_t
+is_from_gz(const char *lifname)
+{
+ ipadm_if_info_t *if_info;
+ char phyname[LIFNAMSIZ], *cp;
+ boolean_t ret = _B_FALSE;
+ ipadm_status_t status;
+ zoneid_t zoneid;
+ ushort_t zflags;
+
+ if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
+ return (_B_FALSE); /* from-gz only makes sense in a NGZ */
+
+ if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
+ return (_B_FALSE);
+
+ if (!(zflags & ZF_NET_EXCL))
+ return (_B_TRUE); /* everything is from the GZ for shared-ip */
+
+ (void) strncpy(phyname, lifname, sizeof (phyname));
+ if ((cp = strchr(phyname, ':')) != NULL)
+ *cp = '\0';
+ status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
+ if (status != IPADM_SUCCESS)
+ return (ret);
+
+ if (if_info->ifi_cflags & IFIF_L3PROTECT)
+ ret = _B_TRUE;
+ if (if_info)
+ ipadm_free_if_info(if_info);
+ return (ret);
+}
+
static boolean_t
print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
@@ -1668,7 +1705,11 @@ print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
buf, bufsize);
break;
case SA_TYPE:
- flags2str(ainfo->ia_atype, type, _B_FALSE, buf, bufsize);
+ if (is_from_gz(ifa->ifa_name))
+ (void) snprintf(buf, bufsize, "from-gz");
+ else
+ flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
+ bufsize);
break;
case SA_CURRENT:
flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
@@ -1877,6 +1918,7 @@ print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{ "i", IFIF_INACTIVE, IFIF_INACTIVE },
{ "V", IFIF_VRRP, IFIF_VRRP },
{ "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
+ { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
{ "4", IFIF_IPV4, IFIF_IPV4 },
{ "6", IFIF_IPV6, IFIF_IPV6 },
{ NULL, 0, 0 }
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/route.c b/usr/src/cmd/cmd-inet/usr.sbin/route.c
index e078d9df38..a2fd0d2d17 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/route.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/route.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -2567,7 +2566,8 @@ static char metricnames[] =
static char routeflags[] =
"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT"
"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
- "\016PRIVATE\017PROTO2\020PROTO1\021MULTIRT\022SETSRC\023INDIRECT";
+ "\016PRIVATE\017PROTO2\020PROTO1\021MULTIRT\022SETSRC\023INDIRECT"
+ "\024KERNEL\025ZONE";
static char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP"
"\011PPROMISC\012ALLMULTI\013INTELLIGENT\014MULTICAST"