diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet')
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c | 56 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h | 3 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c | 173 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c | 201 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c | 17 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c | 46 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/route.c | 6 |
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" |