PSARC 2006/366 IP Instances
6289221 RFE: Need virtualized ip-stack for each local zone
6512601 panic in ipsec_in_tag - allocation failure
6514637 error message from dhcpagent: add_pkt_opt: option type 60 is missing required value
6364643 RFE: allow persistent setting of interface flags per zone
6307539 RFE: Invalid network address causes zone boot failure
5041214 Allow IPMP configuration with zones
5005887 RFE: zoneadmd should support plumbing an interface via DHCP
4991139 RFE: zones should provide a mechanism to configure a defaultrouter for a zone
6218378 zoneadmd doesn't set the netmask for non-loopback addresses hosted on lo0
4963280 zones: need to virtualize the IPv6 default address selection mechanism
4963285 zones: need support of stateless address autoconfiguration for IPv6
5048068 zones don't boot if one of its interfaces has failed
5057154 RFE: ability to change interface status from within a zone
4963287 zones should support the plumbing of the first (and only) logical interface
4978517 TCP privileged port space should be partitioned per zone
5023347 zones don't work well with network routes other than default
4963372 investigate whether global zone can act as a router for local zones
6378364 RFE: Allow each zone to have its own virtual IPFilter
diff --git a/usr/src/Makefile b/usr/src/Makefile
index 0e3d6f5..b69335d 100644
--- a/usr/src/Makefile
+++ b/usr/src/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -134,13 +134,12 @@
$(SUBDIRS) head ucbhead pkgdefs: FRC
@cd $@; pwd; $(MAKE) $(TARGET)
-.PARALLEL: sysheaders userheaders libheaders ucbheaders cmdheaders \
- commonheaders
+.PARALLEL: sysheaders userheaders libheaders ucbheaders cmdheaders
# librpcsvc has a dependency on headers installed by
# userheaders, hence the .WAIT before libheaders.
sgs: rootdirs .WAIT sysheaders userheaders .WAIT \
- libheaders ucbheaders cmdheaders commonheaders
+ libheaders ucbheaders cmdheaders
#
# top-level setup target to setup the development environment
@@ -182,9 +181,6 @@
@cd cmd/fm; pwd; $(MAKE) install_h
@cd cmd/mdb; pwd; $(MAKE) install_h
-commonheaders: FRC
- @cd uts/common/inet/ipf/netinet; pwd; $(MAKE) install_h
-
# each xmod target depends on a corresponding MACH-specific pseudotarget
# before doing common xmod work
#
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index a433e01..b5af375 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -144,6 +144,9 @@
CHGRP= $(TRUE)
MV= /usr/bin/mv -f
RM= /usr/bin/rm -f
+CUT= /usr/bin/cut
+NM= /usr/ccs/bin/nm
+DIFF= /usr/bin/diff
GREP= /usr/bin/grep
EGREP= /usr/bin/egrep
SED= /usr/bin/sed
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/inform.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/inform.c
index f4ba297..e742e91 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/inform.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/inform.c
@@ -87,7 +87,10 @@
(void) add_pkt_opt16(dpkt, CD_MAX_DHCP_SIZE,
htons(dsmp->dsm_lif->lif_pif->pif_max -
sizeof (struct udpiphdr)));
- (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
+ if (class_id_len != 0) {
+ (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id,
+ class_id_len);
+ }
(void) add_pkt_prl(dpkt, dsmp);
(void) add_pkt_opt(dpkt, CD_END, NULL, 0);
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/init_reboot.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/init_reboot.c
index 16f7dbb..497a3e9 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/init_reboot.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/init_reboot.c
@@ -78,7 +78,8 @@
(void) add_pkt_opt16(dpkt, CD_MAX_DHCP_SIZE,
htons(dsmp->dsm_lif->lif_pif->pif_max - sizeof (struct udpiphdr)));
- (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
+ if (class_id_len != 0)
+ (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
(void) add_pkt_prl(dpkt, dsmp);
/*
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/renew.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/renew.c
index d6a81ad..dd65950 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/renew.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/renew.c
@@ -480,7 +480,10 @@
htons(lif->lif_max - sizeof (struct udpiphdr)));
(void) add_pkt_opt32(dpkt, CD_LEASE_TIME, htonl(DHCP_PERM));
- (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
+ if (class_id_len != 0) {
+ (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id,
+ class_id_len);
+ }
(void) add_pkt_prl(dpkt, dsmp);
/*
* dsm_reqhost was set for this state machine in
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
index f6e418f..936965e 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
@@ -304,7 +304,10 @@
offer->opts[CD_SERVER_ID]->value,
offer->opts[CD_SERVER_ID]->len);
- (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
+ if (class_id_len != 0) {
+ (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id,
+ class_id_len);
+ }
(void) add_pkt_prl(dpkt, dsmp);
/*
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
index 41cc76f..9dfead3 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
@@ -169,7 +169,10 @@
htons(dsmp->dsm_lif->lif_max - sizeof (struct udpiphdr)));
(void) add_pkt_opt32(dpkt, CD_LEASE_TIME, htonl(DHCP_PERM));
- (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
+ if (class_id_len != 0) {
+ (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id,
+ class_id_len);
+ }
(void) add_pkt_prl(dpkt, dsmp);
if (df_get_bool(dsmp->dsm_name, dsmp->dsm_isv6,
@@ -280,7 +283,7 @@
return;
}
- if (pkt_v4_match(recv_type, DHCP_PACK | DHCP_PNAK)) {
+ if (pkt_v4_match(recv_type, DHCP_PACK)) {
if (!dhcp_bound(dsmp, plp)) {
dhcpmsg(MSG_WARNING, "dhcp_collect_dlpi: dhcp_bound "
"failed for %s", dsmp->dsm_name);
@@ -289,6 +292,9 @@
}
dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: %s on %s",
pname, dsmp->dsm_name);
+ } else if (pkt_v4_match(recv_type, DHCP_PNAK)) {
+ free_pkt_entry(plp);
+ dhcp_restart(dsmp);
} else {
pkt_smach_enqueue(dsmp, plp);
}
diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/svc-ndp b/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/svc-ndp
index 0937c37..fe52065 100644
--- a/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/svc-ndp
+++ b/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/svc-ndp
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,7 @@
. /lib/svc/share/smf_include.sh
. /lib/svc/share/routing_include.sh
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
daemon_args=`get_daemon_args $SMF_FMRI`
options="adtf:"
diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/ripng.xml b/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/ripng.xml
index 05391c8..5b65c94 100644
--- a/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/ripng.xml
+++ b/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/ripng.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
@@ -75,7 +75,7 @@
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root'
-privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_net_config,net_privaddr,net_icmpaccess,net_rawaccess'/>
+privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_ip_config,net_privaddr,net_icmpaccess,net_rawaccess'/>
</method_context>
</exec_method>
diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/svc-ripng b/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/svc-ripng
index 6e0bea0..f0fb43c 100644
--- a/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/svc-ripng
+++ b/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/svc-ripng
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,7 @@
. /lib/svc/share/smf_include.sh
. /lib/svc/share/routing_include.sh
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
daemon_args=`get_daemon_args $SMF_FMRI`
options="sqp:Ptv"
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 c1f32fd..c297c2c 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
@@ -193,6 +193,10 @@
static void selectifs(int argc, char *argv[], int af,
struct lifreq *lifrp);
static int updownifs(iface_t *ifs, int up);
+static int find_all_global_interfaces(struct lifconf *lifcp, char **buf,
+ int64_t lifc_flags);
+static int find_all_zone_interfaces(struct lifconf *lifcp, char **buf,
+ int64_t lifc_flags);
#define max(a, b) ((a) < (b) ? (b) : (a))
@@ -484,59 +488,30 @@
struct lifreq lifrl; /* Local lifreq struct */
int numifs;
unsigned bufsize;
- ni_t *nip;
int plumball = 0;
int save_af = af;
+ buf = NULL;
/*
* Special case:
* ifconfig -a plumb should find all network interfaces
- * in the machine by traversing the devinfo tree.
+ * in the machine by traversing the devinfo tree for global zone.
+ * For non-global zones, only find the assigned interfaces.
* Also, there is no need to SIOCGLIF* ioctls, since
* those interfaces have already been plumbed
*/
if (argc > 0 && (strcmp(*argv, "plumb") == 0)) {
- /*
- * Look through the kernel's devinfo tree for
- * network devices
- */
- di_node_t root;
-
- /*
- * DINFOCACHE is equivalent to DINFOSUBTREE | DINFOMINOR |
- * DINFOPROP | DINFOFORCE.
- */
- if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
- (void) fprintf(stderr, "ifconfig: di_init failed;"
- " check the devinfo driver.\n");
- exit(1);
+ if (getzoneid() == GLOBAL_ZONEID) {
+ if (find_all_global_interfaces(&lifc, &buf,
+ lifc_flags) != 0)
+ return;
+ } else {
+ if (find_all_zone_interfaces(&lifc, &buf,
+ lifc_flags) != 0)
+ return;
}
-
- (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, NULL,
- devfs_entry);
- di_fini(root);
-
- /*
- * Now, translate the linked list into
- * a struct lifreq buffer
- */
- bufsize = num_ni * sizeof (struct lifreq);
- if ((buf = malloc(bufsize)) == NULL)
- Perror0_exit("foreachinterface: malloc failed");
-
- lifc.lifc_family = AF_UNSPEC;
- lifc.lifc_flags = lifc_flags;
- lifc.lifc_len = bufsize;
- lifc.lifc_buf = buf;
-
- for (n = 0, lifrp = lifc.lifc_req; n < num_ni; n++, lifrp++) {
- nip = ni_list;
- (void) strncpy(lifrp->lifr_name, nip->ni_name,
- sizeof (lifr.lifr_name));
- ni_list = nip->ni_next;
- free(nip);
- }
-
+ if (lifc.lifc_len == 0)
+ return;
plumball = 1;
} else {
lifn.lifn_family = AF_UNSPEC;
@@ -664,7 +639,8 @@
/* the func could have overwritten origname, so restore */
(void) strncpy(name, origname, sizeof (name));
}
- free(buf);
+ if (buf != NULL)
+ free(buf);
}
static void
@@ -1781,6 +1757,161 @@
}
/*
+ * static int find_all_global_interfaces(struct lifconf *lifcp, char **buf,
+ * int64_t lifc_flags)
+ *
+ * It finds all interfaces for the global zone, that is all
+ * the physical interfaces, using the kernel's devinfo tree.
+ *
+ * It takes in input a pointer to struct lifconf to receive interfaces
+ * informations, a **char to hold allocated buffer, and a lifc_flags.
+ *
+ * Return values:
+ * 0 = everything OK
+ * -1 = problem
+ */
+static int
+find_all_global_interfaces(struct lifconf *lifcp, char **buf,
+ int64_t lifc_flags)
+{
+ unsigned bufsize;
+ int n;
+ di_node_t root;
+ ni_t *nip;
+ struct lifreq *lifrp;
+
+ /*
+ * DINFOCACHE is equivalent to DINFOSUBTREE | DINFOMINOR |
+ * DINFOPROP | DINFOFORCE.
+ */
+ if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ (void) fprintf(stderr, "ifconfig: di_init "
+ "failed; check the devinfo driver.\n");
+ exit(1);
+ }
+
+ (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS,
+ NULL, devfs_entry);
+ di_fini(root);
+
+ /*
+ * Now, translate the linked list into
+ * a struct lifreq buffer
+ */
+ if (num_ni == 0) {
+ lifcp->lifc_family = AF_UNSPEC;
+ lifcp->lifc_flags = lifc_flags;
+ lifcp->lifc_len = 0;
+ lifcp->lifc_buf = NULL;
+ return (0);
+ }
+
+ bufsize = num_ni * sizeof (struct lifreq);
+ if ((*buf = malloc(bufsize)) == NULL)
+ Perror0_exit("find_all_interfaces: malloc failed");
+
+ lifcp->lifc_family = AF_UNSPEC;
+ lifcp->lifc_flags = lifc_flags;
+ lifcp->lifc_len = bufsize;
+ lifcp->lifc_buf = *buf;
+
+ for (n = 0, lifrp = lifcp->lifc_req; n < num_ni; n++, lifrp++) {
+ nip = ni_list;
+ (void) strncpy(lifrp->lifr_name, nip->ni_name,
+ sizeof (lifr.lifr_name));
+ ni_list = nip->ni_next;
+ free(nip);
+ }
+ return (0);
+}
+
+/*
+ * static int find_all_zone_interfaces(struct lifconf *lifcp, char **buf,
+ * int64_t lifc_flags)
+ *
+ * It finds all interfaces for an exclusive-IP zone, that is all the interfaces
+ * assigned to it.
+ *
+ * It takes in input a pointer to struct lifconf to receive interfaces
+ * informations, a **char to hold allocated buffer, and a lifc_flags.
+ *
+ * Return values:
+ * 0 = everything OK
+ * -1 = problem
+ */
+static int
+find_all_zone_interfaces(struct lifconf *lifcp, char **buf, int64_t lifc_flags)
+{
+ zoneid_t zoneid;
+ unsigned bufsize;
+ char *dlnames, *ptr;
+ struct lifreq *lifrp;
+ int num_ni_saved, i;
+
+ zoneid = getzoneid();
+
+ num_ni = 0;
+ if (zone_list_datalink(zoneid, &num_ni, NULL) != 0)
+ Perror0_exit("find_all_interfaces: list interfaces failed");
+again:
+ /* this zone doesn't have any data-links */
+ if (num_ni == 0) {
+ lifcp->lifc_family = AF_UNSPEC;
+ lifcp->lifc_flags = lifc_flags;
+ lifcp->lifc_len = 0;
+ lifcp->lifc_buf = NULL;
+ return (0);
+ }
+
+ dlnames = malloc(num_ni * LIFNAMSIZ);
+ if (dlnames == NULL)
+ Perror0_exit("find_all_interfaces: out of memory");
+ num_ni_saved = num_ni;
+
+ if (zone_list_datalink(zoneid, &num_ni, dlnames) != 0)
+ Perror0_exit("find_all_interfaces: list interfaces failed");
+
+ if (num_ni_saved < num_ni) {
+ /* list increased, try again */
+ free(dlnames);
+ goto again;
+ }
+
+ /* this zone doesn't have any data-links now */
+ if (num_ni == 0) {
+ free(dlnames);
+ lifcp->lifc_family = AF_UNSPEC;
+ lifcp->lifc_flags = lifc_flags;
+ lifcp->lifc_len = 0;
+ lifcp->lifc_buf = NULL;
+ return (0);
+ }
+
+ bufsize = num_ni * sizeof (struct lifreq);
+ if ((*buf = malloc(bufsize)) == NULL) {
+ free(dlnames);
+ Perror0_exit("find_all_interfaces: malloc failed");
+ }
+
+ lifrp = (struct lifreq *)*buf;
+ ptr = dlnames;
+ for (i = 0; i < num_ni; i++) {
+ if (strlcpy(lifrp->lifr_name, ptr, LIFNAMSIZ) >=
+ LIFNAMSIZ)
+ Perror0_exit("find_all_interfaces: overflow");
+ ptr += LIFNAMSIZ;
+ lifrp++;
+ }
+
+ free(dlnames);
+ lifcp->lifc_family = AF_UNSPEC;
+ lifcp->lifc_flags = lifc_flags;
+ lifcp->lifc_len = bufsize;
+ lifcp->lifc_buf = *buf;
+ return (0);
+}
+
+/*
* Create the next unused logical interface using the original name
* and assign the address (and mask if '/<n>' is part of the address).
* Use the new logical interface for subsequent subcommands by updating
@@ -2760,8 +2891,13 @@
if (!v4compat) {
if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) >= 0)
(void) printf(" index %d", lifr.lifr_index);
+ /*
+ * Stack instances use GLOBAL_ZONEID for IP data structures
+ * even in the non-global zone.
+ */
if (ioctl(s, SIOCGLIFZONE, (caddr_t)&lifr) >= 0 &&
- lifr.lifr_zoneid != getzoneid()) {
+ lifr.lifr_zoneid != getzoneid() &&
+ lifr.lifr_zoneid != GLOBAL_ZONEID) {
char zone_name[ZONENAME_MAX];
if (lifr.lifr_zoneid == ALL_ZONES) {
@@ -3928,6 +4064,7 @@
int dev_fd;
dlpi_if_attr_t dia;
boolean_t islo;
+ zoneid_t zoneid;
strptr = strchr(name, ':');
islo = (strcmp(name, LOOPBACK_IF) == 0);
@@ -3962,6 +4099,27 @@
return (0);
}
+ /*
+ * For global zone, check if the interface is used by a non-global
+ * zone, note that the non-global zones doesn't need this check,
+ * because zoneadm has taken care of this when the zone boots.
+ */
+ zoneid = getzoneid();
+ if (zoneid == GLOBAL_ZONEID) {
+ int ret;
+
+ zoneid = ALL_ZONES;
+ ret = zone_check_datalink(&zoneid, name);
+ if (ret == 0) {
+ char zonename[ZONENAME_MAX];
+
+ (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX);
+ (void) fprintf(stderr, "%s is used by non-global"
+ "zone: %s\n", name, zonename);
+ return (1);
+ }
+ }
+
if (debug)
(void) printf("inetplumb: %s af %d\n", name, afp->af_af);
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/rdisc.xml b/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/rdisc.xml
index 7ae84f1..005b491 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/rdisc.xml
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/rdisc.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
@@ -58,7 +58,7 @@
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root'
-privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_net_config,net_icmpaccess,net_rawaccess'/>
+privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_ip_config,net_icmpaccess,net_rawaccess'/>
</method_context>
</exec_method>
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/svc-rdisc b/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/svc-rdisc
index 76cdda3..1bdb4dc 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/svc-rdisc
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.rdisc/svc-rdisc
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,7 @@
. /lib/svc/share/smf_include.sh
. /lib/svc/share/routing_include.sh
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
daemon_args=`get_daemon_args $SMF_FMRI`
options="afsp:T:r"
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/route.xml b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/route.xml
index c7867bb..8982aba 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/route.xml
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/route.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
@@ -58,7 +58,7 @@
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root'
-privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_net_config,net_privaddr,net_icmpaccess,net_rawaccess'/>
+privileges='basic,proc_owner,proc_fork,proc_exec,proc_info,proc_session,file_chown,sys_ip_config,net_privaddr,net_icmpaccess,net_rawaccess'/>
</method_context>
</exec_method>
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/svc-route b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/svc-route
index aa67456..a0a82c8 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/svc-route
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/svc-route
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,7 @@
. /lib/svc/share/smf_include.sh
. /lib/svc/share/routing_include.sh
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
daemon_args=`get_daemon_args $SMF_FMRI`
options="AdghmnqsStvVzT:F:P:"
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
index a0ea8b8..17891ff 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
@@ -18,7 +18,7 @@
*
* CDDL HEADER END
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -246,25 +246,25 @@
char tmp_buf[INET6_ADDRSTRLEN];
int c;
int i;
- boolean_t has_sys_net_config;
+ boolean_t has_sys_ip_config;
progname = argv[0];
/*
* This program needs the net_icmpaccess privilege for creating
- * raw ICMP sockets. It needs sys_net_config for using the
+ * raw ICMP sockets. It needs sys_ip_config for using the
* IP_NEXTHOP socket option (IPv4 only). We'll fail
* on the socket call and report the error there when we have
* insufficient privileges.
*
- * Non-global zones don't have the sys_net_config privilege, so
+ * Shared-IP zones don't have the sys_ip_config privilege, so
* we need to check for it in our limit set before trying
* to set it.
*/
- has_sys_net_config = priv_ineffect(PRIV_SYS_NET_CONFIG);
+ has_sys_ip_config = priv_ineffect(PRIV_SYS_IP_CONFIG);
(void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_NET_ICMPACCESS,
- has_sys_net_config ? PRIV_SYS_NET_CONFIG : (char *)NULL,
+ has_sys_ip_config ? PRIV_SYS_IP_CONFIG : (char *)NULL,
(char *)NULL);
setbuf(stdout, (char *)0);
@@ -1228,7 +1228,7 @@
nh = ((struct sockaddr_in *)ai_nexthop->
ai_addr)->sin_addr.s_addr;
- /* now we need the sys_net_config privilege */
+ /* now we need the sys_ip_config privilege */
(void) __priv_bracket(PRIV_ON);
if (setsockopt(sock, IPPROTO_IP, IP_NEXTHOP,
&nh, sizeof (ipaddr_t)) < 0) {
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-forwarding b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-forwarding
index fc9c5e3..db3ead4 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-forwarding
+++ b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-forwarding
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -61,7 +61,7 @@
case "$1" in
'start' | 'refresh' )
- smf_is_globalzone || exit $SMF_EXIT_OK
+ smf_configure_ip || exit $SMF_EXIT_OK
#
# Start ip forwarding.
#
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-legacy-routing b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-legacy-routing
index dcf8b39..d063801 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-legacy-routing
+++ b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/svc-legacy-routing
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -55,7 +55,7 @@
echo "${proto}-routing-stop-cmd not specified by routeadm."
exit $SMF_EXIT_ERR_CONFIG
fi
- smf_is_globalzone || exit $SMF_EXIT_OK
+ smf_configure_ip || exit $SMF_EXIT_OK
# Run daemon - fail if it does not successfully daemonize.
eval "$daemon_prog $daemon_args"
@@ -65,10 +65,16 @@
fi
# Create pidfile.
daemon_name=`/usr/bin/basename $daemon_prog`
- /usr/bin/pgrep -P 1 -f $daemon_prog > /var/tmp/${daemon_name}.pid
+ if smf_is_globalzone; then
+ /usr/bin/pgrep -P 1 -z `smf_zonename` -f $daemon_prog > \
+ /var/tmp/${daemon_name}.pid
+ else
+ /usr/bin/pgrep -z `smf_zonename` -f $daemon_prog > \
+ /var/tmp/${daemon_name}.pid
+ fi
;;
'stop' )
- smf_is_globalzone || exit $SMF_EXIT_OK
+ smf_configure_ip || exit $SMF_EXIT_OK
# Stop daemon - ignore result.
if [ -n "$daemon_stop" ]; then
diff --git a/usr/src/cmd/diff/Makefile b/usr/src/cmd/diff/Makefile
index 1c44145..d5443bb 100644
--- a/usr/src/cmd/diff/Makefile
+++ b/usr/src/cmd/diff/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -22,14 +21,14 @@
#
#ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
PROG= diff diffh
SRCS= $(PROG:%=%.c)
-DIFF= diff
-DIFFH= diffh
+BINDIFF= diff
+LIBDIFFH= diffh
include ../Makefile.cmd
#
@@ -39,8 +38,8 @@
DCFILE= diff.dc
#XGETFLAGS += -a -x diff.xcl
-ROOTBINDIFF = $(DIFF:%=$(ROOTBIN)/%)
-ROOTLIBDIFFH = $(DIFFH:%=$(ROOTLIB)/%)
+ROOTBINDIFF = $(BINDIFF:%=$(ROOTBIN)/%)
+ROOTLIBDIFFH = $(LIBDIFFH:%=$(ROOTLIB)/%)
.KEEP_STATE:
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index cd07c7c..c088f44 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -116,6 +116,8 @@
static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj;
static cmdfunc_t do_init_linkprop, do_init_secobj;
+static void show_linkprop_onelink(void *, const char *);
+
static void link_stats(const char *, uint_t);
static void aggr_stats(uint32_t, uint_t);
static void dev_stats(const char *dev, uint32_t);
@@ -2340,6 +2342,7 @@
const char *ls_link;
char *ls_line;
char **ls_propvals;
+ prop_list_t *ls_proplist;
boolean_t ls_parseable;
boolean_t ls_persist;
boolean_t ls_header;
@@ -2420,8 +2423,8 @@
static void
print_linkprop_head(void)
{
- (void) printf("%-15s %-14s %-14s %-30s \n",
- "PROPERTY", "VALUE", "DEFAULT", "POSSIBLE");
+ (void) printf("%-12s %-15s %-14s %-14s %-20s \n",
+ "LINK", "PROPERTY", "VALUE", "DEFAULT", "POSSIBLE");
}
static void
@@ -2481,6 +2484,15 @@
char *ptr = statep->ls_line;
char *lim = ptr + MAX_PROP_LINE;
+ if (statep->ls_persist && dladm_is_prop_temponly(propname, NULL))
+ return (B_TRUE);
+
+ if (statep->ls_parseable)
+ ptr += snprintf(ptr, lim - ptr, "LINK=\"%s\" ",
+ statep->ls_link);
+ else
+ ptr += snprintf(ptr, lim - ptr, "%-12s ", statep->ls_link);
+
if (statep->ls_parseable)
ptr += snprintf(ptr, lim - ptr, "PROPERTY=\"%s\" ", propname);
else
@@ -2492,7 +2504,7 @@
print_linkprop(statep, propname, DLADM_PROP_VAL_DEFAULT,
"DEFAULT", "%-14s ", &ptr);
print_linkprop(statep, propname, DLADM_PROP_VAL_MODIFIABLE,
- "POSSIBLE", "%-30s ", &ptr);
+ "POSSIBLE", "%-20s ", &ptr);
if (statep->ls_header) {
statep->ls_header = B_FALSE;
@@ -2506,11 +2518,8 @@
static void
do_show_linkprop(int argc, char **argv)
{
- int i, option, fd;
- char linkname[MAXPATHLEN];
+ int option;
prop_list_t *proplist = NULL;
- char *buf;
- dladm_status_t status;
show_linkprop_state_t state;
opterr = 0;
@@ -2544,8 +2553,31 @@
else if (optind != argc)
usage();
- if (state.ls_link == NULL)
- die("link name must be specified");
+ state.ls_proplist = proplist;
+
+ if (state.ls_link == NULL) {
+ (void) dladm_walk(show_linkprop_onelink, &state);
+ } else {
+ show_linkprop_onelink(&state, state.ls_link);
+ }
+ free_props(proplist);
+}
+
+static void
+show_linkprop_onelink(void *arg, const char *link)
+{
+ int i, fd;
+ char linkname[MAXPATHLEN];
+ char *buf;
+ dladm_status_t status;
+ prop_list_t *proplist = NULL;
+ show_linkprop_state_t *statep;
+ const char *savep;
+
+ statep = (show_linkprop_state_t *)arg;
+ savep = statep->ls_link;
+ statep->ls_link = link;
+ proplist = statep->ls_proplist;
/*
* When some WiFi links are opened for the first time, their hardware
@@ -2553,37 +2585,37 @@
* if there are no open links, the retrieval of link properties
* (below) will proceed slowly unless we hold the link open.
*/
- (void) snprintf(linkname, MAXPATHLEN, "/dev/%s", state.ls_link);
+ (void) snprintf(linkname, MAXPATHLEN, "/dev/%s", link);
if ((fd = open(linkname, O_RDWR)) < 0)
- die("cannot open %s: %s", state.ls_link, strerror(errno));
+ die("cannot open %s: %s", link, strerror(errno));
buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS +
MAX_PROP_LINE);
if (buf == NULL)
die("insufficient memory");
- state.ls_propvals = (char **)(void *)buf;
+ statep->ls_propvals = (char **)(void *)buf;
for (i = 0; i < MAX_PROP_VALS; i++) {
- state.ls_propvals[i] = buf + sizeof (char *) * MAX_PROP_VALS +
+ statep->ls_propvals[i] = buf + sizeof (char *) * MAX_PROP_VALS +
i * DLADM_PROP_VAL_MAX;
}
- state.ls_line = buf +
+ statep->ls_line = buf +
(sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS;
if (proplist != NULL) {
for (i = 0; i < proplist->pl_count; i++) {
- if (!show_linkprop(&state,
+ if (!show_linkprop(statep,
proplist->pl_info[i].pi_name))
break;
}
} else {
- status = dladm_walk_prop(state.ls_link, &state, show_linkprop);
+ status = dladm_walk_prop(link, statep, show_linkprop);
if (status != DLADM_STATUS_OK)
die_dlerr(status, "show-linkprop");
}
(void) close(fd);
free(buf);
- free_props(proplist);
+ statep->ls_link = savep;
}
static dladm_status_t
@@ -2591,17 +2623,18 @@
uint_t val_cnt, boolean_t reset)
{
dladm_status_t status;
+ char *errprop;
status = dladm_set_prop(link, prop_name, prop_val, val_cnt,
- DLADM_OPT_PERSIST);
+ DLADM_OPT_PERSIST, &errprop);
if (status != DLADM_STATUS_OK) {
if (reset) {
warn_dlerr(status, "cannot persistently reset link "
- "property '%s' on '%s'", prop_name, link);
+ "property '%s' on '%s'", errprop, link);
} else {
warn_dlerr(status, "cannot persistently set link "
- "property '%s' on '%s'", prop_name, link);
+ "property '%s' on '%s'", errprop, link);
}
}
return (status);
@@ -2650,13 +2683,16 @@
die("link name must be specified");
if (proplist == NULL) {
+ char *errprop;
+
if (!reset)
die("link property must be specified");
- status = dladm_set_prop(link, NULL, NULL, 0, DLADM_OPT_TEMP);
+ status = dladm_set_prop(link, NULL, NULL, 0, DLADM_OPT_TEMP,
+ &errprop);
if (status != DLADM_STATUS_OK) {
- warn_dlerr(status, "cannot reset link properties "
- "on '%s'", link);
+ warn_dlerr(status, "cannot reset link property '%s' "
+ "on '%s'", errprop, link);
}
if (!temp) {
dladm_status_t s;
@@ -2688,7 +2724,7 @@
}
}
s = dladm_set_prop(link, pip->pi_name, val, count,
- DLADM_OPT_TEMP);
+ DLADM_OPT_TEMP, NULL);
if (s == DLADM_STATUS_OK) {
if (!temp) {
s = set_linkprop_persist(link,
@@ -2734,10 +2770,12 @@
if (ptr >= lim)
break;
}
- if (ptr > errmsg)
+ if (ptr > errmsg) {
*(ptr - 1) = '\0';
- warn("link property '%s' must be one of: %s",
- pip->pi_name, errmsg);
+ warn("link property '%s' must be one of: %s",
+ pip->pi_name, errmsg);
+ } else
+ warn("invalid link property '%s'", *val);
free(propvals);
break;
}
diff --git a/usr/src/cmd/ipf/lib/Makefile.com b/usr/src/cmd/ipf/lib/Makefile.com
index e6bf79f..8019bb8 100644
--- a/usr/src/cmd/ipf/lib/Makefile.com
+++ b/usr/src/cmd/ipf/lib/Makefile.com
@@ -1,5 +1,25 @@
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -35,7 +55,9 @@
remove_pool.o remove_poolnode.o remove_hash.o \
remove_hashnode.o resetlexer.o rwlock_emul.o \
tcpflags.o var.o verbose.o \
- v6ionames.o v6optvalue.o
+ v6ionames.o v6optvalue.o printpool_live.o \
+ printpooldata.o printhash_live.o printhashdata.o \
+ printactivenat.o
include $(SRC)/lib/Makefile.lib
include ../../Makefile.ipf
diff --git a/usr/src/cmd/ipf/lib/common/getifname.c b/usr/src/cmd/ipf/lib/common/getifname.c
index ec3ae92..ef25075 100644
--- a/usr/src/cmd/ipf/lib/common/getifname.c
+++ b/usr/src/cmd/ipf/lib/common/getifname.c
@@ -3,7 +3,7 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,7 +38,7 @@
int len;
# endif
struct ifnet netif;
-
+#define SOLARIS_PFHOOKS 1
# ifdef SOLARIS_PFHOOKS
if ((opts & OPT_DONOTHING) == 0)
return "@";
diff --git a/usr/src/cmd/ipf/lib/common/getnattype.c b/usr/src/cmd/ipf/lib/common/getnattype.c
index 312a862..2c89b2b 100644
--- a/usr/src/cmd/ipf/lib/common/getnattype.c
+++ b/usr/src/cmd/ipf/lib/common/getnattype.c
@@ -4,7 +4,13 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "ipf.h"
#include "kmem.h"
@@ -16,19 +22,27 @@
/*
* Get a nat filter type given its kernel address.
*/
-char *getnattype(ipnat)
-ipnat_t *ipnat;
+char *getnattype(nat, alive)
+nat_t *nat;
+int alive;
{
static char unknownbuf[20];
- ipnat_t ipnatbuff;
+ ipnat_t *ipn, ipnatbuff;
char *which;
+ int type;
- if (!ipnat)
+ if (!nat)
return "???";
- if (kmemcpy((char *)&ipnatbuff, (long)ipnat, sizeof(ipnatbuff)))
- return "!!!";
+ if (alive) {
+ type = nat->nat_redir;
+ } else {
+ ipn = nat->nat_ptr;
+ if (kmemcpy((char *)&ipnatbuff, (long)ipn, sizeof(ipnatbuff)))
+ return "!!!";
+ type = ipnatbuff.in_redir;
+ }
- switch (ipnatbuff.in_redir)
+ switch (type)
{
case NAT_MAP :
which = "MAP";
@@ -43,8 +57,7 @@
which = "BIMAP";
break;
default :
- sprintf(unknownbuf, "unknown(%04x)",
- ipnatbuff.in_redir & 0xffffffff);
+ sprintf(unknownbuf, "unknown(%04x)", type & 0xffffffff);
which = unknownbuf;
break;
}
diff --git a/usr/src/cmd/ipf/lib/common/load_pool.c b/usr/src/cmd/ipf/lib/common/load_pool.c
index d27b6c3..b8146c0 100644
--- a/usr/src/cmd/ipf/lib/common/load_pool.c
+++ b/usr/src/cmd/ipf/lib/common/load_pool.c
@@ -4,8 +4,13 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: load_pool.c,v 1.14.2.2 2005/02/01 02:44:06 darrenr Exp $
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include <fcntl.h>
#include <sys/ioctl.h>
#include "ipf.h"
diff --git a/usr/src/cmd/ipf/lib/common/printactivenat.c b/usr/src/cmd/ipf/lib/common/printactivenat.c
index 389818b..ace6b6c 100644
--- a/usr/src/cmd/ipf/lib/common/printactivenat.c
+++ b/usr/src/cmd/ipf/lib/common/printactivenat.c
@@ -4,8 +4,13 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "ipf.h"
@@ -14,12 +19,12 @@
#endif
-void printactivenat(nat, opts)
+void printactivenat(nat, opts, alive)
nat_t *nat;
-int opts;
+int opts, alive;
{
- printf("%s", getnattype(nat->nat_ptr));
+ printf("%s", getnattype(nat, alive));
if (nat->nat_flags & SI_CLONE)
printf(" CLONE");
diff --git a/usr/src/cmd/ipf/lib/common/printhash_live.c b/usr/src/cmd/ipf/lib/common/printhash_live.c
new file mode 100755
index 0000000..082ee74
--- /dev/null
+++ b/usr/src/cmd/ipf/lib/common/printhash_live.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ipl.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+
+iphtable_t *printhash_live(hp, fd, name, opts)
+iphtable_t *hp;
+int fd;
+char *name;
+int opts;
+{
+ iphtent_t entry, *top, *node;
+ ipflookupiter_t iter;
+ int i, printed, last;
+ ipfobj_t obj;
+
+ if ((name != NULL) && strncmp(name, hp->iph_name, FR_GROUPLEN))
+ return hp->iph_next;
+
+ printhashdata(hp, opts);
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF("\t{");
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_LOOKUPITER;
+ obj.ipfo_ptr = &iter;
+ obj.ipfo_size = sizeof(iter);
+
+ iter.ili_data = &entry;
+ iter.ili_type = IPLT_HASH;
+ iter.ili_otype = IPFLOOKUPITER_NODE;
+ iter.ili_ival = IPFGENITER_LOOKUP;
+ iter.ili_unit = hp->iph_unit;
+ strncpy(iter.ili_name, hp->iph_name, FR_GROUPLEN);
+
+ last = 0;
+ top = NULL;
+
+ while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) {
+ if (entry.ipe_snext == NULL)
+ last = 1;
+ entry.ipe_snext = top;
+ top = malloc(sizeof(*top));
+ if (top == NULL)
+ break;
+ bcopy(&entry, top, sizeof(entry));
+ }
+
+ while (top != NULL) {
+ node = top;
+ (void) printhashnode(hp, node, bcopywrap, opts);
+ top = node->ipe_snext;
+ free(node);
+ printed++;
+
+ if ((opts & OPT_DEBUG) == 0)
+ putchar(';');
+ }
+
+ if (printed == 0)
+ putchar(';');
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF(" };\n");
+ return hp->iph_next;
+}
diff --git a/usr/src/cmd/ipf/lib/common/printhashdata.c b/usr/src/cmd/ipf/lib/common/printhashdata.c
new file mode 100755
index 0000000..cef1afb
--- /dev/null
+++ b/usr/src/cmd/ipf/lib/common/printhashdata.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+
+void printhashdata(hp, opts)
+iphtable_t *hp;
+int opts;
+{
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON)
+ PRINTF("# 'anonymous' table\n");
+ switch (hp->iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_LOOKUP :
+ PRINTF("table");
+ break;
+ case IPHASH_GROUPMAP :
+ PRINTF("group-map");
+ if (hp->iph_flags & FR_INQUE)
+ PRINTF(" in");
+ else if (hp->iph_flags & FR_OUTQUE)
+ PRINTF(" out");
+ else
+ PRINTF(" ???");
+ break;
+ default :
+ PRINTF("%#x", hp->iph_type);
+ break;
+ }
+ PRINTF(" role = ");
+ } else {
+ PRINTF("Hash Table Number: %s", hp->iph_name);
+ if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON)
+ PRINTF("(anon)");
+ putchar(' ');
+ PRINTF("Role: ");
+ }
+
+ switch (hp->iph_unit)
+ {
+ case IPL_LOGNAT :
+ PRINTF("nat");
+ break;
+ case IPL_LOGIPF :
+ PRINTF("ipf");
+ break;
+ case IPL_LOGAUTH :
+ PRINTF("auth");
+ break;
+ case IPL_LOGCOUNT :
+ PRINTF("count");
+ break;
+ default :
+ PRINTF("#%d", hp->iph_unit);
+ break;
+ }
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP)
+ PRINTF(" type = hash");
+ PRINTF(" number = %s size = %lu",
+ hp->iph_name, (u_long)hp->iph_size);
+ if (hp->iph_seed != 0)
+ PRINTF(" seed = %lu", hp->iph_seed);
+ putchar('\n');
+ } else {
+ PRINTF(" Type: ");
+ switch (hp->iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_LOOKUP :
+ PRINTF("lookup");
+ break;
+ case IPHASH_GROUPMAP :
+ PRINTF("groupmap Group. %s", hp->iph_name);
+ break;
+ default :
+ break;
+ }
+
+ putchar('\n');
+ PRINTF("\t\tSize: %lu\tSeed: %lu",
+ (u_long)hp->iph_size, hp->iph_seed);
+ PRINTF("\tRef. Count: %d\tMasks: %#x\n", hp->iph_ref,
+ hp->iph_masks[0]);
+ }
+
+ if ((opts & OPT_DEBUG) != 0) {
+ struct in_addr m;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if ((1 << i) & hp->iph_masks[0]) {
+ ntomask(4, i, &m.s_addr);
+ PRINTF("\t\tMask: %s\n", inet_ntoa(m));
+ }
+ }
+ }
+}
diff --git a/usr/src/cmd/ipf/lib/common/printpool_live.c b/usr/src/cmd/ipf/lib/common/printpool_live.c
new file mode 100644
index 0000000..77f95d8
--- /dev/null
+++ b/usr/src/cmd/ipf/lib/common/printpool_live.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ipl.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+
+ip_pool_t *printpool_live(pool, fd, name, opts)
+ip_pool_t *pool;
+int fd;
+char *name;
+int opts;
+{
+ ip_pool_node_t entry, *top, *node;
+ ipflookupiter_t iter;
+ int i, printed, last;
+ ipfobj_t obj;
+
+ if ((name != NULL) && strncmp(name, pool->ipo_name, FR_GROUPLEN))
+ return pool->ipo_next;
+
+ printpooldata(pool, opts);
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF("\t{");
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_LOOKUPITER;
+ obj.ipfo_ptr = &iter;
+ obj.ipfo_size = sizeof(iter);
+
+ iter.ili_data = &entry;
+ iter.ili_type = IPLT_POOL;
+ iter.ili_otype = IPFLOOKUPITER_NODE;
+ iter.ili_ival = IPFGENITER_LOOKUP;
+ iter.ili_unit = pool->ipo_unit;
+ strncpy(iter.ili_name, pool->ipo_name, FR_GROUPLEN);
+
+ last = 0;
+ top = NULL;
+
+ while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) {
+ if (entry.ipn_next == NULL)
+ last = 1;
+ entry.ipn_next = top;
+ top = malloc(sizeof(*top));
+ if (top == NULL)
+ break;
+ bcopy(&entry, top, sizeof(entry));
+ }
+
+ while (top != NULL) {
+ node = top;
+ (void) printpoolnode(node, opts);
+ top = node->ipn_next;
+ free(node);
+ printed++;
+
+ if ((opts & OPT_DEBUG) == 0)
+ putchar(';');
+ }
+
+ if (printed == 0)
+ putchar(';');
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF(" };\n");
+ return pool->ipo_next;
+}
diff --git a/usr/src/cmd/ipf/lib/common/printpooldata.c b/usr/src/cmd/ipf/lib/common/printpooldata.c
new file mode 100644
index 0000000..a699af6
--- /dev/null
+++ b/usr/src/cmd/ipf/lib/common/printpooldata.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+void printpooldata(pool, opts)
+ip_pool_t *pool;
+int opts;
+{
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((pool->ipo_flags & IPOOL_ANON) != 0)
+ PRINTF("# 'anonymous' tree %s\n", pool->ipo_name);
+ PRINTF("table role = ");
+ } else {
+ PRINTF("Name: %s", pool->ipo_name);
+ if ((pool->ipo_flags & IPOOL_ANON) == IPOOL_ANON)
+ PRINTF("(anon)");
+ putchar(' ');
+ PRINTF("Role: ");
+ }
+
+ switch (pool->ipo_unit)
+ {
+ case IPL_LOGIPF :
+ PRINTF("ipf");
+ break;
+ case IPL_LOGNAT :
+ PRINTF("nat");
+ break;
+ case IPL_LOGSTATE :
+ PRINTF("state");
+ break;
+ case IPL_LOGAUTH :
+ PRINTF("auth");
+ break;
+ case IPL_LOGSYNC :
+ PRINTF("sync");
+ break;
+ case IPL_LOGSCAN :
+ PRINTF("scan");
+ break;
+ case IPL_LOGLOOKUP :
+ PRINTF("lookup");
+ break;
+ case IPL_LOGCOUNT :
+ PRINTF("count");
+ break;
+ default :
+ PRINTF("unknown(%d)", pool->ipo_unit);
+ }
+
+ if ((opts & OPT_DEBUG) == 0) {
+ PRINTF(" type = tree number = %s\n", pool->ipo_name);
+ } else {
+ putchar(' ');
+
+ PRINTF("\tReferences: %d\tHits: %lu\n", pool->ipo_ref,
+ pool->ipo_hits);
+ PRINTF("\tNodes Starting at %p\n", pool->ipo_list);
+ }
+}
diff --git a/usr/src/cmd/ipf/svc/ipfilter b/usr/src/cmd/ipf/svc/ipfilter
index 43d25c4..0709018 100644
--- a/usr/src/cmd/ipf/svc/ipfilter
+++ b/usr/src/cmd/ipf/svc/ipfilter
@@ -22,7 +22,7 @@
#
# ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -36,11 +36,12 @@
IPPOOLCONF=/etc/ipf/ippool.conf
PFILCHECKED=no
+zone=`smf_zonename`
ipfid=`/usr/sbin/modinfo 2>&1 | awk '/ipf/ { print $1 } ' - 2>/dev/null`
if [ -f $PIDFILE ] ; then
pid=`cat $PIDFILE 2>/dev/null`
else
- pid=`pgrep ipmon`
+ pid=`pgrep -z $zone ipmon`
fi
logmsg()
diff --git a/usr/src/cmd/ipf/tools/Makefile.tools b/usr/src/cmd/ipf/tools/Makefile.tools
index e346756..2cb3585 100644
--- a/usr/src/cmd/ipf/tools/Makefile.tools
+++ b/usr/src/cmd/ipf/tools/Makefile.tools
@@ -1,5 +1,25 @@
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
@@ -48,7 +68,7 @@
ipfstat := LDLIBS += -lsocket -lnsl -lkvm -lelf
ipmon := LDLIBS += -lsocket -lnsl
ipnat := LDLIBS += -lsocket -lnsl -lkvm -lelf
-ippool := LDLIBS += -lsocket -lnsl -lkvm
+ippool := LDLIBS += -lsocket -lnsl -lkvm -lelf
CLEANFILES += $(OBJS)
diff --git a/usr/src/cmd/ipf/tools/ip_fil.c b/usr/src/cmd/ipf/tools/ip_fil.c
index 4aaa993..daf170f 100644
--- a/usr/src/cmd/ipf/tools/ip_fil.c
+++ b/usr/src/cmd/ipf/tools/ip_fil.c
@@ -3,7 +3,7 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -68,6 +68,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
+#include <sys/zone.h>
#include <arpa/inet.h>
#ifdef __hpux
@@ -133,6 +134,7 @@
#ifdef IPFILTER_COMPILED
# include "netinet/ip_rules.h"
#endif
+#include "netinet/ipf_stack.h"
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
#endif
@@ -150,7 +152,7 @@
static struct ifnet **ifneta = NULL;
static int nifs = 0;
-static int frzerostats __P((caddr_t));
+static int frzerostats __P((caddr_t, ipf_stack_t *ifs));
static void fr_setifpaddr __P((struct ifnet *, char *));
void init_ifp __P((void));
#if defined(__sgi) && (IRIX < 60500)
@@ -173,32 +175,36 @@
#endif
-int iplattach()
+int iplattach(ifs, ns)
+ipf_stack_t *ifs;
+netstack_t *ns;
{
- fr_running = 1;
+ ifs->ifs_fr_running = 1;
return 0;
}
-int ipldetach()
+int ipldetach(ifs)
+ipf_stack_t *ifs;
{
- fr_running = -1;
+ ifs->ifs_fr_running = -1;
return 0;
}
-static int frzerostats(data)
+static int frzerostats(data, ifs)
caddr_t data;
+ipf_stack_t *ifs;
{
friostat_t fio;
int error;
- fr_getstat(&fio);
+ fr_getstat(&fio, ifs);
error = copyoutptr(&fio, data, sizeof(fio));
if (error)
return EFAULT;
- bzero((char *)frstats, sizeof(*frstats) * 2);
+ bzero((char *)ifs->ifs_frstats, sizeof(*ifs->ifs_frstats) * 2);
return 0;
}
@@ -213,41 +219,46 @@
caddr_t data;
int mode;
{
- int error = 0, unit = 0, tmp;
+ int error = 0, unit = 0, tmp, uid;
friostat_t fio;
+ ipf_stack_t *ifs;
+ extern ipf_stack_t *get_ifs();
unit = dev;
+ uid = getuid();
+
+ ifs = get_ifs();
SPL_NET(s);
if (unit == IPL_LOGNAT) {
- if (fr_running > 0)
- error = fr_nat_ioctl(data, cmd, mode);
+ if (ifs->ifs_fr_running > 0)
+ error = fr_nat_ioctl(data, cmd, mode, uid, NULL, ifs);
else
error = EIO;
SPL_X(s);
return error;
}
if (unit == IPL_LOGSTATE) {
- if (fr_running > 0)
- error = fr_state_ioctl(data, cmd, mode);
+ if (ifs->ifs_fr_running > 0)
+ error = fr_state_ioctl(data, cmd, mode, uid, NULL, ifs);
else
error = EIO;
SPL_X(s);
return error;
}
if (unit == IPL_LOGAUTH) {
- if (fr_running > 0) {
+ if (ifs->ifs_fr_running > 0) {
if ((cmd == (ioctlcmd_t)SIOCADAFR) ||
(cmd == (ioctlcmd_t)SIOCRMAFR)) {
if (!(mode & FWRITE)) {
error = EPERM;
} else {
error = frrequest(unit, cmd, data,
- fr_active, 1);
+ ifs->ifs_fr_active, 1, ifs);
}
} else {
- error = fr_auth_ioctl(data, mode, cmd);
+ error = fr_auth_ioctl(data, mode, cmd, uid, NULL, ifs);
}
} else
error = EIO;
@@ -256,7 +267,7 @@
}
if (unit == IPL_LOGSYNC) {
#ifdef IPFILTER_SYNC
- if (fr_running > 0)
+ if (ifs->ifs_fr_running > 0)
error = fr_sync_ioctl(data, cmd, mode);
else
#endif
@@ -266,7 +277,7 @@
}
if (unit == IPL_LOGSCAN) {
#ifdef IPFILTER_SCAN
- if (fr_running > 0)
+ if (ifs->ifs_fr_running > 0)
error = fr_scan_ioctl(data, cmd, mode);
else
#endif
@@ -275,8 +286,9 @@
return error;
}
if (unit == IPL_LOGLOOKUP) {
- if (fr_running > 0)
- error = ip_lookup_ioctl(data, cmd, mode);
+ if (ifs->ifs_fr_running > 0)
+ error = ip_lookup_ioctl(data, cmd, mode, uid,
+ NULL, ifs);
else
error = EIO;
SPL_X(s);
@@ -287,8 +299,8 @@
{
case FIONREAD :
#ifdef IPFILTER_LOG
- error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
- sizeof(iplused[IPL_LOGIPF]));
+ error = COPYOUT(&ifs->ifs_iplused[IPL_LOGIPF], (caddr_t)data,
+ sizeof(ifs->ifs_iplused[IPL_LOGIPF]));
#endif
break;
case SIOCFRENB :
@@ -299,9 +311,9 @@
if (error)
break;
if (tmp)
- error = iplattach();
+ error = iplattach(ifs, NULL);
else
- error = ipldetach();
+ error = ipldetach(ifs);
}
break;
case SIOCIPFSET :
@@ -311,16 +323,18 @@
}
case SIOCIPFGETNEXT :
case SIOCIPFGET :
- error = fr_ipftune(cmd, (void *)data);
+ error = fr_ipftune(cmd, (void *)data, ifs);
break;
case SIOCSETFF :
if (!(mode & FWRITE))
error = EPERM;
else
- error = COPYIN(data, &fr_flags, sizeof(fr_flags));
+ error = COPYIN(data, &ifs->ifs_fr_flags,
+ sizeof(ifs->ifs_fr_flags));
break;
case SIOCGETFF :
- error = COPYOUT(&fr_flags, data, sizeof(fr_flags));
+ error = COPYOUT(&ifs->ifs_fr_flags, data,
+ sizeof(ifs->ifs_fr_flags));
break;
case SIOCFUNCL :
error = fr_resolvefunc(data);
@@ -332,7 +346,8 @@
if (!(mode & FWRITE))
error = EPERM;
else
- error = frrequest(unit, cmd, data, fr_active, 1);
+ error = frrequest(unit, cmd, data,
+ ifs->ifs_fr_active, 1, ifs);
break;
case SIOCINIFR :
case SIOCRMIFR :
@@ -340,26 +355,28 @@
if (!(mode & FWRITE))
error = EPERM;
else
- error = frrequest(unit, cmd, data, 1 - fr_active, 1);
+ error = frrequest(unit, cmd, data,
+ 1 - ifs->ifs_fr_active, 1, ifs);
break;
case SIOCSWAPA :
if (!(mode & FWRITE))
error = EPERM;
else {
- bzero((char *)frcache, sizeof(frcache[0]) * 2);
- *(u_int *)data = fr_active;
- fr_active = 1 - fr_active;
+ bzero((char *)ifs->ifs_frcache,
+ sizeof(ifs->ifs_frcache[0]) * 2);
+ *(u_int *)data = ifs->ifs_fr_active;
+ ifs->ifs_fr_active = 1 - ifs->ifs_fr_active;
}
break;
case SIOCGETFS :
- fr_getstat(&fio);
+ fr_getstat(&fio, ifs);
error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
break;
case SIOCFRZST :
if (!(mode & FWRITE))
error = EPERM;
else
- error = frzerostats(data);
+ error = frzerostats(data, ifs);
break;
case SIOCIPFFL :
if (!(mode & FWRITE))
@@ -367,7 +384,7 @@
else {
error = COPYIN(data, &tmp, sizeof(tmp));
if (!error) {
- tmp = frflush(unit, 4, tmp);
+ tmp = frflush(unit, 4, tmp, ifs);
error = COPYOUT(&tmp, data, sizeof(tmp));
}
}
@@ -379,7 +396,7 @@
else {
error = COPYIN(data, &tmp, sizeof(tmp));
if (!error) {
- tmp = frflush(unit, 6, tmp);
+ tmp = frflush(unit, 6, tmp, ifs);
error = COPYOUT(&tmp, data, sizeof(tmp));
}
}
@@ -388,10 +405,10 @@
case SIOCSTLCK :
error = COPYIN(data, &tmp, sizeof(tmp));
if (error == 0) {
- fr_state_lock = tmp;
- fr_nat_lock = tmp;
- fr_frag_lock = tmp;
- fr_auth_lock = tmp;
+ ifs->ifs_fr_state_lock = tmp;
+ ifs->ifs_fr_nat_lock = tmp;
+ ifs->ifs_fr_frag_lock = tmp;
+ ifs->ifs_fr_auth_lock = tmp;
} else
error = EFAULT;
break;
@@ -400,17 +417,17 @@
if (!(mode & FWRITE))
error = EPERM;
else
- *(int *)data = ipflog_clear(unit);
+ *(int *)data = ipflog_clear(unit, ifs);
break;
#endif /* IPFILTER_LOG */
case SIOCGFRST :
- error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
+ error = fr_outobj(data, fr_fragstats(ifs), IPFOBJ_FRAGSTAT);
break;
case SIOCFRSYN :
if (!(mode & FWRITE))
error = EPERM;
else {
- frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL);
+ frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL, ifs);
}
break;
default :
@@ -422,51 +439,61 @@
}
-void fr_forgetifp(ifp)
+void fr_forgetifp(ifp, ifs)
void *ifp;
+ipf_stack_t *ifs;
{
register frentry_t *f;
- WRITE_ENTER(&ipf_mutex);
- for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
+ WRITE_ENTER(&ifs->ifs_ipf_mutex);
+ for (f = ifs->ifs_ipacct[0][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipacct[1][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipfilter[0][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipfilter[1][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
#ifdef USE_INET6
- for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipacct6[0][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipacct6[1][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipfilter6[0][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
- for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
+ for (f = ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]; (f != NULL);
+ f = f->fr_next)
if (f->fr_ifa == ifp)
f->fr_ifa = (void *)-1;
#endif
- RWLOCK_EXIT(&ipf_mutex);
- fr_natifpsync(IPFSYNC_OLDIFP, ifp, NULL);
+ RWLOCK_EXIT(&ifs->ifs_ipf_mutex);
+ fr_natifpsync(IPFSYNC_OLDIFP, ifp, NULL, ifs);
}
-void fr_resolvedest(fdp, v)
+void fr_resolvedest(fdp, v, ifs)
frdest_t *fdp;
int v;
+ipf_stack_t *ifs;
{
fdp->fd_ifp = NULL;
if (*fdp->fd_ifname) {
- fdp->fd_ifp = GETIFP(fdp->fd_ifname, v);
+ fdp->fd_ifp = GETIFP(fdp->fd_ifname, v, ifs);
if (!fdp->fd_ifp)
fdp->fd_ifp = (struct ifnet *)-1;
}
@@ -579,9 +606,11 @@
}
}
-struct ifnet *get_unit(name, v)
+/*ARGSUSED*/
+struct ifnet *get_unit(name, v, ifs)
char *name;
int v;
+ipf_stack_t *ifs;
{
struct ifnet *ifp, **ifpp, **old_ifneta;
char *addr;
@@ -781,10 +810,11 @@
}
-void frsync(command, version, nic, data)
+void frsync(command, version, nic, data, ifs)
int command, version;
void *nic;
char *data;
+ipf_stack_t *ifs;
{
return;
}
@@ -897,10 +927,11 @@
{
static u_short ipid = 0;
u_short id;
+ ipf_stack_t *ifs = fin->fin_ifs;
- MUTEX_ENTER(&ipf_rw);
+ MUTEX_ENTER(&ifs->ifs_ipf_rw);
id = ipid++;
- MUTEX_EXIT(&ipf_rw);
+ MUTEX_EXIT(&ifs->ifs_ipf_rw);
return id;
}
@@ -957,10 +988,11 @@
/*
* return the first IP Address associated with an interface
*/
-int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
+int fr_ifpaddr(v, atype, ifptr, inp, inpmask, ifs)
int v, atype;
void *ifptr;
struct in_addr *inp, *inpmask;
+ipf_stack_t *ifs;
{
struct ifnet *ifp = ifptr;
#ifdef __sgi
diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c
index b2f3195..de7d9c9 100644
--- a/usr/src/cmd/ipf/tools/ipfstat.c
+++ b/usr/src/cmd/ipf/tools/ipfstat.c
@@ -3,7 +3,7 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -143,6 +143,8 @@
static void showauthstates __P((fr_authstat_t *));
static void showgroups __P((friostat_t *));
static void usage __P((char *));
+static void printlivelist __P((int, int, frentry_t *, char *, char *));
+static void printdeadlist __P((int, int, frentry_t *, char *, char *));
static void printlist __P((frentry_t *, char *));
static void parse_ipportstr __P((const char *, i6addr_t *, int *));
static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
@@ -261,13 +263,12 @@
if (kern != NULL || memf != NULL) {
(void)setgid(getgid());
(void)setreuid(getuid(), getuid());
+ if (openkmem(kern, memf) == -1)
+ exit(-1);
}
if (live_kernel == 1)
(void) checkrev(device);
- if (openkmem(kern, memf) == -1)
- exit(-1);
-
(void)setgid(getgid());
(void)setreuid(getuid(), getuid());
@@ -778,21 +779,52 @@
/*
* Print out a list of rules from the kernel, starting at the one passed.
*/
-static void printlist(fp, comment)
+static void printlivelist(out, set, fp, group, comment)
+int out, set;
frentry_t *fp;
-char *comment;
+char *group, *comment;
{
+ frgroup_t *grtop, *grtail, *g;
struct frentry fb, *fg;
- char *data;
- u_32_t type;
int n;
+ ipfruleiter_t rule;
+ ipfobj_t obj;
- for (n = 1; fp; n++) {
- if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
- perror("kmemcpy");
+ fb.fr_next = fp;
+ n = 0;
+
+ grtop = NULL;
+ grtail = NULL;
+ rule.iri_ver = use_inet6? AF_INET6 : AF_INET;
+ rule.iri_inout = out;
+ rule.iri_active = set;
+ rule.iri_rule = &fb;
+ if (group != NULL)
+ strncpy(rule.iri_group, group, FR_GROUPLEN);
+ else
+ rule.iri_group[0] = '\0';
+
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_IPFITER;
+ obj.ipfo_size = sizeof(rule);
+ obj.ipfo_ptr = &rule;
+
+ do {
+ u_long array[1000];
+
+ memset(array, 0xff, sizeof(array));
+ fp = (frentry_t *)array;
+ rule.iri_rule = fp;
+ if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) {
+ perror("ioctl(SIOCIPFITER)");
return;
}
- fp = &fb;
+ if (fp->fr_data != NULL)
+ fp->fr_data = (char *)fp + sizeof(*fp);
+
+ n++;
+
if (opts & (OPT_HITS|OPT_VERBOSE))
#ifdef USE_QUAD_T
PRINTF("%qu ", (unsigned long long) fp->fr_hits);
@@ -807,24 +839,6 @@
#endif
if (opts & OPT_SHOWLINENO)
PRINTF("@%d ", n);
- data = NULL;
- type = fp->fr_type & ~FR_T_BUILTIN;
- if (type == FR_T_IPF || type == FR_T_BPFOPC) {
- if (fp->fr_dsize) {
- data = malloc(fp->fr_dsize);
- if (data == NULL) {
- perror("malloc");
- exit(1);
- }
-
- if (kmemcpy(data, (u_long)fp->fr_data,
- fp->fr_dsize) == -1) {
- perror("kmemcpy");
- return;
- }
- fp->fr_data = data;
- }
- }
printfr(fp, ioctl);
if (opts & OPT_DEBUG) {
@@ -832,20 +846,125 @@
if (fp->fr_data != NULL && fp->fr_dsize > 0)
binprint(fp->fr_data, fp->fr_dsize);
}
- if (data != NULL)
- free(data);
- if (fp->fr_grp != NULL) {
- if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp,
- sizeof(fg)))
- printlist(fg, comment);
+
+ if (fp->fr_grhead[0] != '\0') {
+ g = calloc(1, sizeof(*g));
+
+ if (g != NULL) {
+ strncpy(g->fg_name, fp->fr_grhead,
+ FR_GROUPLEN);
+ if (grtop == NULL) {
+ grtop = g;
+ grtail = g;
+ } else {
+ grtail->fg_next = g;
+ grtail = g;
+ }
+ }
}
- if (type == FR_T_CALLFUNC) {
- printlist(fp->fr_data, "# callfunc: ");
- }
- fp = fp->fr_next;
+ } while (fp->fr_next != NULL);
+
+ while ((g = grtop) != NULL) {
+ printlivelist(out, set, NULL, g->fg_name, comment);
+ grtop = g->fg_next;
+ free(g);
}
}
+
+static void printdeadlist(out, set, fp, group, comment)
+int out, set;
+frentry_t *fp;
+char *group, *comment;
+{
+ frgroup_t *grtop, *grtail, *g;
+ struct frentry fb, *fg;
+ char *data;
+ u_32_t type;
+ int n;
+
+ fb.fr_next = fp;
+ n = 0;
+ grtop = NULL;
+ grtail = NULL;
+
+ do {
+ fp = fb.fr_next;
+ if (kmemcpy((char *)&fb, (u_long)fb.fr_next,
+ sizeof(fb)) == -1) {
+ perror("kmemcpy");
+ return;
+ }
+
+ data = NULL;
+ type = fb.fr_type & ~FR_T_BUILTIN;
+ if (type == FR_T_IPF || type == FR_T_BPFOPC) {
+ if (fb.fr_dsize) {
+ data = malloc(fb.fr_dsize);
+
+ if (kmemcpy(data, (u_long)fb.fr_data,
+ fb.fr_dsize) == -1) {
+ perror("kmemcpy");
+ return;
+ }
+ fb.fr_data = data;
+ }
+ }
+
+ n++;
+
+ if (opts & (OPT_HITS|OPT_VERBOSE))
+#ifdef USE_QUAD_T
+ PRINTF("%qu ", (unsigned long long) fb.fr_hits);
+#else
+ PRINTF("%lu ", fb.fr_hits);
+#endif
+ if (opts & (OPT_ACCNT|OPT_VERBOSE))
+#ifdef USE_QUAD_T
+ PRINTF("%qu ", (unsigned long long) fb.fr_bytes);
+#else
+ PRINTF("%lu ", fb.fr_bytes);
+#endif
+ if (opts & OPT_SHOWLINENO)
+ PRINTF("@%d ", n);
+
+ printfr(fp, ioctl);
+ if (opts & OPT_DEBUG) {
+ binprint(fp, sizeof(*fp));
+ if (fb.fr_data != NULL && fb.fr_dsize > 0)
+ binprint(fb.fr_data, fb.fr_dsize);
+ }
+ if (data != NULL)
+ free(data);
+ if (fb.fr_grhead[0] != '\0') {
+ g = calloc(1, sizeof(*g));
+
+ if (g != NULL) {
+ strncpy(g->fg_name, fb.fr_grhead,
+ FR_GROUPLEN);
+ if (grtop == NULL) {
+ grtop = g;
+ grtail = g;
+ } else {
+ grtail->fg_next = g;
+ grtail = g;
+ }
+ }
+ }
+ if (type == FR_T_CALLFUNC) {
+ printdeadlist(out, set, fb.fr_data, group,
+ "# callfunc: ");
+ }
+ } while (fb.fr_next != NULL);
+
+ while ((g = grtop) != NULL) {
+ printdeadlist(out, set, NULL, g->fg_name, comment);
+ grtop = g->fg_next;
+ free(g);
+ }
+}
+
+
/*
* print out all of the asked for rule sets, using the stats struct as
* the base from which to get the pointers.
@@ -908,7 +1027,10 @@
(opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
return;
}
- printlist(fp, NULL);
+ if (live_kernel == 1)
+ printlivelist(i, set, fp, NULL, NULL);
+ else
+ printdeadlist(i, set, fp, NULL, NULL);
}
diff --git a/usr/src/cmd/ipf/tools/ipftest.c b/usr/src/cmd/ipf/tools/ipftest.c
index e523386..37b47b6 100644
--- a/usr/src/cmd/ipf/tools/ipftest.c
+++ b/usr/src/cmd/ipf/tools/ipftest.c
@@ -3,7 +3,7 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -22,14 +22,9 @@
extern char *optarg;
extern struct frentry *ipfilter[2][2];
extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex;
-extern struct ifnet *get_unit __P((char *, int));
+extern struct ifnet *get_unit __P((char *, int, ipf_stack_t *));
extern void init_ifp __P((void));
-extern int fr_running;
-ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
-ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
-ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache;
-ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
int opts = OPT_DONOTHING;
int use_inet6 = 0;
int pfil_delayed_copy = 0;
@@ -37,12 +32,16 @@
int loadrules __P((char *, int));
int kmemcpy __P((char *, long, int));
int kstrncpy __P((char *, long, int n));
-void dumpnat __P((void));
-void dumpstate __P((void));
-void dumplookups __P((void));
-void dumpgroups __P((void));
-void drain_log __P((char *));
+void dumpnat __P((ipf_stack_t *ifs));
+void dumpstate __P((ipf_stack_t *ifs));
+void dumplookups __P((ipf_stack_t *ifs));
+void dumpgroups __P((ipf_stack_t *ifs));
+void drain_log __P((char *, ipf_stack_t *ifs));
void fixv4sums __P((mb_t *, ip_t *));
+ipf_stack_t *get_ifs __P((void));
+ipf_stack_t *create_ifs __P((void));
+netstack_t *create_ns __P((void));
+
#if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
@@ -84,6 +83,8 @@
struct ipread *r;
mb_t mb, *m;
ip_t *ip;
+ ipf_stack_t *ifs;
+ netstack_t *ns;
m = &mb;
dir = 0;
@@ -96,17 +97,34 @@
ifname = "anon0";
datain = NULL;
- MUTEX_INIT(&ipf_rw, "ipf rw mutex");
- MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock");
- RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
- RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
- RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
- RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
-
initparse();
- if (fr_initialise() == -1)
- abort();
- fr_running = 1;
+ ifs = create_ifs();
+ ns = create_ns();
+ ifs->ifs_netstack = ns;
+
+#if defined(IPFILTER_DEFAULT_BLOCK)
+ ifs->ifs_fr_pass = FR_BLOCK|FR_NOMATCH;
+#else
+ ifs->ifs_fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH;
+#endif
+ ipftuneable_alloc(ifs);
+
+ bzero((char *)ifs->ifs_frcache, sizeof(ifs->ifs_frcache));
+ MUTEX_INIT(&ifs->ifs_ipf_rw, "ipf rw mutex");
+ MUTEX_INIT(&ifs->ifs_ipf_timeoutlock, "ipf timeout lock");
+ RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
+ RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
+ RWLOCK_INIT(&ifs->ifs_ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
+ RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
+
+ fr_loginit(ifs);
+ fr_authinit(ifs);
+ fr_fraginit(ifs);
+ fr_stateinit(ifs);
+ fr_natinit(ifs);
+ appr_init(ifs);
+ ip_lookup_init(ifs);
+ ifs->ifs_fr_running = 1;
while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1)
switch (c)
@@ -207,7 +225,7 @@
&iface, &dir)) > 0) {
if (iface == NULL || *iface == '\0')
iface = ifname;
- ifp = get_unit(iface, IP_V(ip));
+ ifp = get_unit(iface, IP_V(ip), ifs);
if (ifp == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
@@ -226,7 +244,7 @@
/* ipfr_slowtimer(); */
m = &mb;
m->mb_len = i;
- i = fr_check(ip, hlen, ifp, dir, &m);
+ i = fr_check(ip, hlen, ifp, dir, &m, ifs);
if ((opts & OPT_NAT) == 0)
switch (i)
{
@@ -294,17 +312,17 @@
(*r->r_close)();
if (logout != NULL) {
- drain_log(logout);
+ drain_log(logout, ifs);
}
if (dump == 1) {
- dumpnat();
- dumpstate();
- dumplookups();
- dumpgroups();
+ dumpnat(ifs);
+ dumpstate(ifs);
+ dumplookups(ifs);
+ dumpgroups(ifs);
}
- fr_deinitialise();
+ fr_deinitialise(ifs);
return 0;
}
@@ -621,17 +639,18 @@
/*
* Display the built up NAT table rules and mapping entries.
*/
-void dumpnat()
+void dumpnat(ifs)
+ ipf_stack_t *ifs;
{
ipnat_t *ipn;
nat_t *nat;
printf("List of active MAP/Redirect filters:\n");
- for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next)
+ for (ipn = ifs->ifs_nat_list; ipn != NULL; ipn = ipn->in_next)
printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
printf("\nList of active sessions:\n");
- for (nat = nat_instances; nat; nat = nat->nat_next) {
- printactivenat(nat, opts);
+ for (nat = ifs->ifs_nat_instances; nat; nat = nat->nat_next) {
+ printactivenat(nat, opts, 0);
if (nat->nat_aps)
printaps(nat->nat_aps, opts);
}
@@ -641,18 +660,20 @@
/*
* Display the built up state table rules and mapping entries.
*/
-void dumpstate()
+void dumpstate(ifs)
+ ipf_stack_t *ifs;
{
ipstate_t *ips;
printf("List of active state sessions:\n");
- for (ips = ips_list; ips != NULL; )
+ for (ips = ifs->ifs_ips_list; ips != NULL; )
ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE),
- fr_ticks);
+ ifs->ifs_fr_ticks);
}
-void dumplookups()
+void dumplookups(ifs)
+ ipf_stack_t *ifs;
{
iphtable_t *iph;
ip_pool_t *ipl;
@@ -660,17 +681,20 @@
printf("List of configured pools\n");
for (i = 0; i < IPL_LOGSIZE; i++)
- for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next)
+ for (ipl = ifs->ifs_ip_pool_list[i]; ipl != NULL;
+ ipl = ipl->ipo_next)
printpool(ipl, bcopywrap, NULL, opts);
printf("List of configured hash tables\n");
for (i = 0; i < IPL_LOGSIZE; i++)
- for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next)
+ for (iph = ifs->ifs_ipf_htables[i]; iph != NULL;
+ iph = iph->iph_next)
printhash(iph, bcopywrap, NULL, opts);
}
-void dumpgroups()
+void dumpgroups(ifs)
+ ipf_stack_t *ifs;
{
frgroup_t *fg;
frentry_t *fr;
@@ -678,7 +702,8 @@
printf("List of groups configured (set 0)\n");
for (i = 0; i < IPL_LOGSIZE; i++)
- for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) {
+ for (fg = ifs->ifs_ipfgroups[i][0]; fg != NULL;
+ fg = fg->fg_next) {
printf("Dev.%d. Group %s Ref %d Flags %#x\n",
i, fg->fg_name, fg->fg_ref, fg->fg_flags);
for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
@@ -693,7 +718,8 @@
printf("List of groups configured (set 1)\n");
for (i = 0; i < IPL_LOGSIZE; i++)
- for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) {
+ for (fg = ifs->ifs_ipfgroups[i][1]; fg != NULL;
+ fg = fg->fg_next) {
printf("Dev.%d. Group %s Ref %d Flags %#x\n",
i, fg->fg_name, fg->fg_ref, fg->fg_flags);
for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
@@ -708,8 +734,9 @@
}
-void drain_log(filename)
+void drain_log(filename, ifs)
char *filename;
+ipf_stack_t *ifs;
{
char buffer[DEFAULT_IPFLOGSIZE];
struct iovec iov;
@@ -735,7 +762,7 @@
uio.uio_resid = iov.iov_len;
resid = uio.uio_resid;
- if (ipflog_read(i, &uio) == 0) {
+ if (ipflog_read(i, &uio, ifs) == 0) {
/*
* If nothing was read then break out.
*/
@@ -782,3 +809,35 @@
*(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr);
}
}
+
+ipf_stack_t *gifs;
+
+/*
+ * Allocate and keep pointer for get_ifs()
+ */
+ipf_stack_t *
+create_ifs()
+{
+ ipf_stack_t *ifs;
+
+ KMALLOCS(ifs, ipf_stack_t *, sizeof (*ifs));
+ bzero(ifs, sizeof (*ifs));
+ gifs = ifs;
+ return (ifs);
+}
+
+ipf_stack_t *
+get_ifs()
+{
+ return (gifs);
+}
+
+netstack_t *
+create_ns()
+{
+ netstack_t *ns;
+
+ KMALLOCS(ns, netstack_t *, sizeof (*ns));
+ bzero(ns, sizeof (*ns));
+ return (ns);
+}
diff --git a/usr/src/cmd/ipf/tools/ipnat.c b/usr/src/cmd/ipf/tools/ipnat.c
index df64e0d..421472e 100644
--- a/usr/src/cmd/ipf/tools/ipnat.c
+++ b/usr/src/cmd/ipf/tools/ipnat.c
@@ -5,7 +5,7 @@
*
* Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -83,11 +83,14 @@
extern char *optarg;
-void dostats __P((natstat_t *, int)), flushtable __P((int, int));
+void dostats __P((int, natstat_t *, int, int));
+void flushtable __P((int, int));
void usage __P((char *));
int main __P((int, char*[]));
void showhostmap __P((natstat_t *nsp));
void natstat_dead __P((natstat_t *, char *));
+void dostats_live __P((int, natstat_t *, int));
+void showhostmap_live __P((int, natstat_t *));
int opts;
@@ -183,9 +186,10 @@
if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) {
+#ifdef notdef
if (openkmem(kernel, core) == -1)
exit(1);
-
+#endif
if (((fd = open(IPNAT_NAME, mode)) == -1) &&
((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) {
(void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME,
@@ -210,7 +214,7 @@
natstat_dead(nsp, kernel);
if (opts & (OPT_LIST|OPT_STAT))
- dostats(nsp, opts);
+ dostats(fd, nsp, opts, 0);
exit(0);
}
@@ -220,7 +224,7 @@
ipnat_parsefile(fd, ipnat_addrule, ioctl, file);
}
if (opts & (OPT_LIST|OPT_STAT))
- dostats(nsp, opts);
+ dostats(fd, nsp, opts, 1);
return 0;
}
@@ -283,9 +287,9 @@
/*
* Display NAT statistics.
*/
-void dostats(nsp, opts)
+void dostats(fd, nsp, opts, alive)
natstat_t *nsp;
-int opts;
+int fd, opts, alive;
{
nat_t *np, nat;
ipnat_t ipn;
@@ -312,6 +316,10 @@
* Show list of NAT rules and NAT sessions ?
*/
if (opts & OPT_LIST) {
+ if (alive) {
+ dostats_live(fd, nsp, opts);
+ return;
+ }
printf("List of active MAP/Redirect filters:\n");
while (nsp->ns_list) {
if (kmemcpy((char *)&ipn, (long)nsp->ns_list,
@@ -330,7 +338,7 @@
for (np = nsp->ns_instances; np; np = nat.nat_next) {
if (kmemcpy((char *)&nat, (long)np, sizeof(nat)))
break;
- printactivenat(&nat, opts);
+ printactivenat(&nat, opts, 0);
if (nat.nat_aps)
printaps(nat.nat_aps, opts);
}
@@ -406,3 +414,87 @@
printf("%d entries flushed from NAT list\n", n);
}
}
+
+/*
+ * Display NAT statistics.
+ */
+void dostats_live(fd, nsp, opts)
+natstat_t *nsp;
+int fd, opts;
+{
+ ipfgeniter_t iter;
+ ipfobj_t obj;
+ ipnat_t ipn;
+ nat_t nat;
+
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_GENITER;
+ obj.ipfo_size = sizeof(iter);
+ obj.ipfo_ptr = &iter;
+
+ iter.igi_type = IPFGENITER_IPNAT;
+ iter.igi_data = &ipn;
+
+ /*
+ * Show list of NAT rules and NAT sessions ?
+ */
+ printf("List of active MAP/Redirect filters:\n");
+ while (nsp->ns_list) {
+ if (ioctl(fd, SIOCGENITER, &obj) == -1)
+ break;
+ if (opts & OPT_HITS)
+ printf("%lu ", ipn.in_hits);
+ printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
+ nsp->ns_list = ipn.in_next;
+ }
+
+ printf("\nList of active sessions:\n");
+
+ iter.igi_type = IPFGENITER_NAT;
+ iter.igi_data = &nat;
+
+ while (nsp->ns_instances != NULL) {
+ if (ioctl(fd, SIOCGENITER, &obj) == -1)
+ break;
+ printactivenat(&nat, opts, 1);
+ if (nat.nat_aps)
+ printaps(nat.nat_aps, opts);
+ nsp->ns_instances = nat.nat_next;
+ }
+
+ if (opts & OPT_VERBOSE)
+ showhostmap_live(fd, nsp);
+}
+
+/*
+ * Display the active host mapping table.
+ */
+void showhostmap_live(fd, nsp)
+int fd;
+natstat_t *nsp;
+{
+ hostmap_t hm, *hmp;
+ ipfgeniter_t iter;
+ ipfobj_t obj;
+
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_GENITER;
+ obj.ipfo_size = sizeof(iter);
+ obj.ipfo_ptr = &iter;
+
+ iter.igi_type = IPFGENITER_HOSTMAP;
+ iter.igi_data = &hm;
+
+ printf("\nList of active host mappings:\n");
+
+ while (nsp->ns_maplist != NULL) {
+ if (ioctl(fd, SIOCGENITER, &obj) == -1)
+ break;
+ printhostmap(&hm, 0);
+ nsp->ns_maplist = hm.hm_next;
+ }
+}
+
+
diff --git a/usr/src/cmd/ipf/tools/ippool.c b/usr/src/cmd/ipf/tools/ippool.c
index edf6793..5f18379 100644
--- a/usr/src/cmd/ipf/tools/ippool.c
+++ b/usr/src/cmd/ipf/tools/ippool.c
@@ -3,7 +3,7 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,14 +33,15 @@
#include <netdb.h>
#include <ctype.h>
#include <unistd.h>
+#include <nlist.h>
#include "ipf.h"
+#include "netinet/ipl.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_pool.h"
#include "netinet/ip_htable.h"
#include "kmem.h"
-
extern int ippool_yyparse __P((void));
extern int ippool_yydebug;
extern FILE *ippool_yyin;
@@ -58,6 +59,9 @@
int poolstats __P((int, char *[]));
int gettype __P((char *, u_int *));
int getrole __P((char *));
+void poollist_dead __P((int, char *, int, char *, char *));
+void showpools_live(int, int, ip_pool_stat_t *, char *, int);
+void showhashs_live(int, int, iphtstat_t *, char *, int);
int opts = 0;
int fd = -1;
@@ -418,29 +422,109 @@
}
op.iplo_unit = role;
- if (openkmem(kernel, core) == -1)
- exit(-1);
+ if (live_kernel == 0) {
+ poollist_dead(role, poolname, type, kernel, core);
+ return (0);
+ }
if (type == IPLT_ALL || type == IPLT_POOL) {
plstp = &plstat;
op.iplo_type = IPLT_POOL;
op.iplo_size = sizeof(plstat);
op.iplo_struct = &plstat;
- c = ioctl(fd, SIOCLOOKUPSTAT, &op);
- if (c == -1) {
- perror("ioctl(SIOCLOOKUPSTAT)");
- return -1;
- }
+ op.iplo_name[0] = '\0';
+ op.iplo_arg = 0;
if (role != IPL_LOGALL) {
- ptr = plstp->ipls_list[role];
+ op.iplo_unit = role;
+
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+
+ showpools_live(fd, role, &plstat, poolname, opts);
+ } else {
+ for (role = 0; role <= IPL_LOGMAX; role++) {
+ op.iplo_unit = role;
+
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+
+ showpools_live(fd, role, &plstat, poolname, opts);
+ }
+
+ role = IPL_LOGALL;
+ }
+ }
+ if (type == IPLT_ALL || type == IPLT_HASH) {
+ htstp = &htstat;
+ op.iplo_type = IPLT_HASH;
+ op.iplo_size = sizeof(htstat);
+ op.iplo_struct = &htstat;
+ op.iplo_name[0] = '\0';
+ op.iplo_arg = 0;
+
+ if (role != IPL_LOGALL) {
+ op.iplo_unit = role;
+
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+ showhashs_live(fd, role, &htstat, poolname, opts);
+ } else {
+ for (role = 0; role <= IPL_LOGMAX; role++) {
+
+ op.iplo_unit = role;
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+
+ showhashs_live(fd, role, &htstat, poolname, opts);
+ }
+ }
+ }
+ return 0;
+}
+
+void poollist_dead(role, poolname, type, kernel, core)
+int role, type;
+char *poolname, *kernel, *core;
+{
+ iphtable_t *hptr;
+ ip_pool_t *ptr;
+
+ if (openkmem(kernel, core) == -1)
+ exit(-1);
+
+ if (type == IPLT_ALL || type == IPLT_POOL) {
+ ip_pool_t *pools[IPL_LOGSIZE];
+ struct nlist names[2] = { { "ip_pool_list" } , { "" } };
+
+ if (nlist(kernel, names) != 1)
+ return;
+
+ bzero(&pools, sizeof(pools));
+ if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
+ return;
+
+ if (role != IPL_LOGALL) {
+ ptr = pools[role];
while (ptr != NULL) {
- ptr = printpool(ptr, kmemcpywrap, poolname,
- opts);
+ ptr = printpool(ptr, kmemcpywrap,
+ poolname, opts);
}
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
- ptr = plstp->ipls_list[role];
+ ptr = pools[role];
while (ptr != NULL) {
ptr = printpool(ptr, kmemcpywrap,
poolname, opts);
@@ -450,43 +534,69 @@
}
}
if (type == IPLT_ALL || type == IPLT_HASH) {
- htstp = &htstat;
- op.iplo_type = IPLT_HASH;
- op.iplo_size = sizeof(htstat);
- op.iplo_struct = &htstat;
- c = ioctl(fd, SIOCLOOKUPSTAT, &op);
- if (c == -1) {
- perror("ioctl(SIOCLOOKUPSTAT)");
- return -1;
- }
+ iphtable_t *tables[IPL_LOGSIZE];
+ struct nlist names[2] = { { "ipf_htables" } , { "" } };
+
+ if (nlist(kernel, names) != 1)
+ return;
+
+ bzero(&tables, sizeof(tables));
+ if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
+ return;
if (role != IPL_LOGALL) {
- hptr = htstp->iphs_tables;
+ hptr = tables[role];
while (hptr != NULL) {
hptr = printhash(hptr, kmemcpywrap,
poolname, opts);
}
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
- hptr = htstp->iphs_tables;
+ hptr = tables[role];
while (hptr != NULL) {
hptr = printhash(hptr, kmemcpywrap,
poolname, opts);
}
-
- op.iplo_unit = role;
- c = ioctl(fd, SIOCLOOKUPSTAT, &op);
- if (c == -1) {
- perror("ioctl(SIOCLOOKUPSTAT)");
- return -1;
- }
}
}
}
- return 0;
}
+void
+showpools_live(fd, role, plstp, poolname, opts)
+int fd, role;
+ip_pool_stat_t *plstp;
+char *poolname;
+int opts;
+{
+ ipflookupiter_t iter;
+ ip_pool_t pool;
+ ipfobj_t obj;
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_LOOKUPITER;
+ obj.ipfo_size = sizeof(iter);
+ obj.ipfo_ptr = &iter;
+
+ iter.ili_type = IPLT_POOL;
+ iter.ili_otype = IPFLOOKUPITER_LIST;
+ iter.ili_ival = IPFGENITER_LOOKUP;
+ iter.ili_data = &pool;
+ iter.ili_unit = role;
+ *iter.ili_name = '\0';
+
+ while (plstp->ipls_list[role] != NULL) {
+ if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
+ perror("ioctl(SIOCLOOKUPITER)");
+ break;
+ }
+ (void) printpool_live(&pool, fd, poolname, opts);
+
+ plstp->ipls_list[role] = pool.ipo_next;
+ }
+}
+
int poolstats(argc, argv)
int argc;
char *argv[];
@@ -702,3 +812,37 @@
}
return type;
}
+
+void showhashs_live(fd, role, htstp, poolname, opts)
+int fd, role;
+iphtstat_t *htstp;
+char *poolname;
+int opts;
+{
+ ipflookupiter_t iter;
+ iphtable_t table;
+ ipfobj_t obj;
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_LOOKUPITER;
+ obj.ipfo_size = sizeof(iter);
+ obj.ipfo_ptr = &iter;
+
+ iter.ili_type = IPLT_HASH;
+ iter.ili_otype = IPFLOOKUPITER_LIST;
+ iter.ili_ival = IPFGENITER_LOOKUP;
+ iter.ili_data = &table;
+ iter.ili_unit = role;
+ *iter.ili_name = '\0';
+
+ while (htstp->iphs_tables != NULL) {
+ if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
+ perror("ioctl(SIOCLOOKUPITER)");
+ break;
+ }
+
+ printhash_live(&table, fd, poolname, opts);
+
+ htstp->iphs_tables = table.iph_next;
+ }
+}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
index b125e5f..c4fa447 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
+++ b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
@@ -55,6 +55,7 @@
modhash.c \
ndievents.c \
net.c \
+ netstack.c \
nvpair.c \
pg.c \
rctl.c \
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 66acba3..decf655 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -87,6 +87,7 @@
#include "ndievents.h"
#include "mmd.h"
#include "net.h"
+#include "netstack.h"
#include "nvpair.h"
#include "ctxop.h"
#include "tsd.h"
@@ -3418,6 +3419,9 @@
"[-t stream | dgram | raw | #] [-p #]",
"filter and display sonode", sonode },
+ /* from netstack.c */
+ { "netstack", "", "show stack instances", netstack },
+
/* from nvpair.c */
{ NVPAIR_DCMD_NAME, NVPAIR_DCMD_USAGE, NVPAIR_DCMD_DESCR,
nvpair_print },
@@ -3755,20 +3759,28 @@
NULL, modchain_walk_step, NULL },
/* from net.c */
- { "ar", "walk ar_t structures using MI",
- mi_payload_walk_init, mi_payload_walk_step,
- mi_payload_walk_fini, &mi_ar_arg },
- { "icmp", "walk ICMP control structures using MI",
- mi_payload_walk_init, mi_payload_walk_step,
- mi_payload_walk_fini, &mi_icmp_arg },
- { "ill", "walk ill_t structures using MI",
- mi_payload_walk_init, mi_payload_walk_step,
- mi_payload_walk_fini, &mi_ill_arg },
+ { "ar", "walk ar_t structures using MI for all stacks",
+ mi_payload_walk_init, mi_payload_walk_step, NULL, &mi_ar_arg },
+ { "icmp", "walk ICMP control structures using MI for all stacks",
+ mi_payload_walk_init, mi_payload_walk_step, NULL,
+ &mi_icmp_arg },
+ { "ill", "walk ill_t structures using MI for all stacks",
+ mi_payload_walk_init, mi_payload_walk_step, NULL, &mi_ill_arg },
+
{ "mi", "given a MI_O, walk the MI",
mi_walk_init, mi_walk_step, mi_walk_fini, NULL },
{ "sonode", "given a sonode, walk its children",
sonode_walk_init, sonode_walk_step, sonode_walk_fini, NULL },
+ { "ar_stacks", "walk all the ar_stack_t",
+ ar_stacks_walk_init, ar_stacks_walk_step, NULL },
+ { "icmp_stacks", "walk all the icmp_stack_t",
+ icmp_stacks_walk_init, icmp_stacks_walk_step, NULL },
+ { "tcp_stacks", "walk all the tcp_stack_t",
+ tcp_stacks_walk_init, tcp_stacks_walk_step, NULL },
+ { "udp_stacks", "walk all the udp_stack_t",
+ udp_stacks_walk_init, udp_stacks_walk_step, NULL },
+
/* from nvpair.c */
{ NVPAIR_WALKER_NAME, NVPAIR_WALKER_DESCR,
nvpair_walk_init, nvpair_walk_step, NULL },
@@ -3860,6 +3872,10 @@
mdi_phci_ph_next_walk_step,
mdi_phci_ph_next_walk_fini },
+ /* from netstack.c */
+ { "netstack", "walk a list of kernel netstacks",
+ netstack_walk_init, netstack_walk_step, NULL },
+
{ NULL }
};
diff --git a/usr/src/cmd/mdb/common/modules/genunix/net.c b/usr/src/cmd/mdb/common/modules/genunix/net.c
index 0195489..00f295c 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/net.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/net.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,8 +51,6 @@
#include <inet/rawip_impl.h>
#include <inet/mi.h>
-#define MIH2MIO(mihp) (&(mihp)->mh_o)
-
#define ADDR_V6_WIDTH 23
#define ADDR_V4_WIDTH 15
@@ -65,6 +63,104 @@
#define NETSTAT_FIRST 0x80000000u
+
+/* Walkers for various *_stack_t */
+int
+ar_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+ar_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_ARP];
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
+int
+icmp_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+icmp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_ICMP];
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
+int
+tcp_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+tcp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_TCP];
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
+int
+udp_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+udp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_UDP];
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
/*
* Print an IPv4 address and port number in a compact and easy to read format
* The arguments are in network byte order
@@ -228,11 +324,14 @@
return (WALK_ERR);
}
- status = wsp->walk_callback(wsp->walk_addr, miop, wsp->walk_cbdata);
-
/* Only true in the first iteration */
- if (wdp->mi_wd_miofirst == NULL)
+ if (wdp->mi_wd_miofirst == NULL) {
wdp->mi_wd_miofirst = wsp->walk_addr;
+ status = WALK_NEXT;
+ } else {
+ status = wsp->walk_callback(wsp->walk_addr + sizeof (MI_O),
+ &miop[1], wsp->walk_cbdata);
+ }
wsp->walk_addr = (uintptr_t)miop->mi_o_next;
return (status);
@@ -244,21 +343,9 @@
mdb_free(wsp->walk_data, sizeof (struct mi_walk_data));
}
-typedef struct mi_payload_walk_data_s {
- uintptr_t mi_pwd_first;
- void *mi_pwd_data;
-} mi_payload_walk_data_t;
-
-static void
-delete_mi_payload_walk_data(mi_payload_walk_data_t *pwdp, size_t payload_size)
-{
- mdb_free(pwdp->mi_pwd_data, payload_size);
- mdb_free(pwdp, sizeof (mi_payload_walk_data_t));
-}
-
typedef struct mi_payload_walk_arg_s {
- const char *mi_pwa_obj; /* load object of mi_o_head_t * */
- const char *mi_pwa_sym; /* symbol name of mi_o_head_t * */
+ const char *mi_pwa_walker; /* Underlying walker */
+ const off_t mi_pwa_head_off; /* Offset for mi_o_head_t * in stack */
const size_t mi_pwa_size; /* size of mi payload */
const uint_t mi_pwa_flags; /* device and/or module */
} mi_payload_walk_arg_t;
@@ -270,45 +357,11 @@
mi_payload_walk_init(mdb_walk_state_t *wsp)
{
const mi_payload_walk_arg_t *arg = wsp->walk_arg;
- mi_payload_walk_data_t *pwdp;
- GElf_Sym sym;
- mi_head_t *mihp;
- /* Determine the address to start or end the walk with */
- if (mdb_lookup_by_obj(arg->mi_pwa_obj, arg->mi_pwa_sym, &sym) == -1) {
- mdb_warn("failed to lookup %s`%s",
- arg->mi_pwa_obj, arg->mi_pwa_sym);
+ if (mdb_layered_walk(arg->mi_pwa_walker, wsp) == -1) {
+ mdb_warn("can't walk '%s'", arg->mi_pwa_walker);
return (WALK_ERR);
}
-
- if (mdb_vread(&mihp, sizeof (mihp), (uintptr_t)sym.st_value) == -1) {
- mdb_warn("failed to read address of global MI Head "
- "mi_o_head_t at %p", (uintptr_t)sym.st_value);
- return (WALK_ERR);
- }
-
- pwdp = mdb_alloc(sizeof (mi_payload_walk_data_t), UM_SLEEP);
- pwdp->mi_pwd_data = mdb_alloc(arg->mi_pwa_size, UM_SLEEP);
- wsp->walk_data = pwdp;
-
- if (wsp->walk_addr == NULL) {
- /* Do not immediately return WALK_DONE below */
- pwdp->mi_pwd_first = NULL;
- /* We determined where to begin */
- wsp->walk_addr = (uintptr_t)MIH2MIO(mihp);
- } else {
- /* Do not cycle through all of the MI_O objects */
- pwdp->mi_pwd_first = (uintptr_t)MIH2MIO(mihp);
- /* We were given where to begin */
- wsp->walk_addr = (uintptr_t)((MI_OP)wsp->walk_addr - 1);
- }
-
- if (mdb_layered_walk("genunix`mi", wsp) == -1) {
- mdb_warn("failed to walk genunix`mi");
- delete_mi_payload_walk_data(pwdp, arg->mi_pwa_size);
- return (WALK_ERR);
- }
-
return (WALK_NEXT);
}
@@ -316,63 +369,43 @@
mi_payload_walk_step(mdb_walk_state_t *wsp)
{
const mi_payload_walk_arg_t *arg = wsp->walk_arg;
- mi_payload_walk_data_t *pwdp = wsp->walk_data;
- void *payload = pwdp->mi_pwd_data;
- uintptr_t payload_kaddr = (uintptr_t)((MI_OP)wsp->walk_addr + 1);
- const MI_O *mio = wsp->walk_layer;
+ uintptr_t kaddr;
- /* If this is a local walk, prevent cycling */
- if (wsp->walk_addr == pwdp->mi_pwd_first)
- return (WALK_DONE);
+ kaddr = wsp->walk_addr + arg->mi_pwa_head_off;
- /*
- * This was a global walk, prevent reading this payload as the
- * initial MI_O is the head of the list and is not the header
- * to a valid payload
- */
- if (pwdp->mi_pwd_first == NULL) {
- pwdp->mi_pwd_first = wsp->walk_addr;
- return (WALK_NEXT);
- }
-
- if (mio->mi_o_isdev == B_FALSE) {
- /* mio is a module */
- if (!(arg->mi_pwa_flags & MI_PAYLOAD_MODULE))
- return (WALK_NEXT);
- } else {
- /* mio is a device */
- if (!(arg->mi_pwa_flags & MI_PAYLOAD_DEVICE))
- return (WALK_NEXT);
- }
-
- if (mdb_vread(payload, arg->mi_pwa_size, payload_kaddr) == -1) {
- mdb_warn("failed to read payload at %p", payload_kaddr);
+ if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
+ mdb_warn("can't read address of mi head at %p for %s",
+ kaddr, arg->mi_pwa_walker);
return (WALK_ERR);
}
- return (wsp->walk_callback(payload_kaddr, payload, wsp->walk_cbdata));
-}
+ if (kaddr == 0) {
+ /* Empty list */
+ return (WALK_DONE);
+ }
-void
-mi_payload_walk_fini(mdb_walk_state_t *wsp)
-{
- const mi_payload_walk_arg_t *arg = wsp->walk_arg;
-
- delete_mi_payload_walk_data(wsp->walk_data, arg->mi_pwa_size);
+ if (mdb_pwalk("genunix`mi", wsp->walk_callback,
+ wsp->walk_cbdata, kaddr) == -1) {
+ mdb_warn("failed to walk genunix`mi");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
}
const mi_payload_walk_arg_t mi_ar_arg = {
- "arp", "ar_g_head", sizeof (ar_t),
+ "ar_stacks", OFFSETOF(arp_stack_t, as_head), sizeof (ar_t),
MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE
};
const mi_payload_walk_arg_t mi_icmp_arg = {
- "icmp", "icmp_g_head", sizeof (icmp_t),
+ "icmp_stacks", OFFSETOF(icmp_stack_t, is_head), sizeof (icmp_t),
MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE
};
-const mi_payload_walk_arg_t mi_ill_arg =
- { "ip", "ip_g_head", sizeof (ill_t), MI_PAYLOAD_MODULE };
+const mi_payload_walk_arg_t mi_ill_arg = {
+ "ip_stacks", OFFSETOF(ip_stack_t, ips_ip_g_head), sizeof (ill_t),
+ MI_PAYLOAD_MODULE
+};
int
sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -557,6 +590,20 @@
return (DCMD_OK);
}
+static int
+ns_to_stackid(uintptr_t kaddr)
+{
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
+ mdb_warn("failed to read netstack_t %p", kaddr);
+ return (0);
+ }
+ return (nss.netstack_stackid);
+}
+
+
+
static void
netstat_tcp_verbose_pr(const tcp_t *tcp)
{
@@ -620,6 +667,8 @@
mdb_printf(" ");
net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport);
}
+ mdb_printf(" %4i", ns_to_stackid((uintptr_t)connp->conn_netstack));
+
mdb_printf(" %4i\n", connp->conn_zoneid);
if (opts & NETSTAT_VERBOSE)
@@ -676,6 +725,8 @@
mdb_printf(" ");
net_ipv6addrport_pr(&udp.udp_v6dst, udp.udp_dstport);
}
+ mdb_printf(" %4i", ns_to_stackid((uintptr_t)connp.conn_netstack));
+
mdb_printf(" %4i\n", connp.conn_zoneid);
return (WALK_NEXT);
@@ -1158,10 +1209,10 @@
if ((optP == NULL) || (strcmp("tcp", optP) == 0)) {
if ((optf == NULL) || (strcmp("inet", optf) == 0)) {
/* Print TCPv4 connection */
- mdb_printf(
- "%<u>%-?s St %*s %*s %s%</u>\n",
+ mdb_printf("%<u>%-?s St %*s %*s "
+ "%s% %s%</u>\n",
"TCPv4", ADDR_V4_WIDTH, "Local Address",
- ADDR_V4_WIDTH, "Remote Address", "Zone");
+ ADDR_V4_WIDTH, "Remote Address", "Stack", "Zone");
if (opts & NETSTAT_VERBOSE)
netstat_tcp_verbose_header_pr();
@@ -1175,10 +1226,10 @@
if ((optf == NULL) || (strcmp("inet6", optf) == 0)) {
/* Print TCPv6 connection */
- mdb_printf(
- "%<u>%-?s St %*s %*s %s\n%</u>",
+ mdb_printf("%<u>%-?s St %*s %*s "
+ "%s %s%\n%</u>",
"TCPv6", ADDR_V6_WIDTH, "Local Address",
- ADDR_V6_WIDTH, "Remote Address", "Zone");
+ ADDR_V6_WIDTH, "Remote Address", "Stack", "Zone");
if (opts & NETSTAT_VERBOSE)
netstat_tcp_verbose_header_pr();
@@ -1194,10 +1245,10 @@
if ((optP == NULL) || (strcmp("udp", optP) == 0)) {
if ((optf == NULL) || (strcmp("inet", optf) == 0)) {
/* Print UDPv4 connection */
- mdb_printf(
- "%<u>%-?s St %*s %*s %s\n%</u>",
+ mdb_printf("%<u>%-?s St %*s %*s "
+ "%s %s%\n%</u>",
"UDPv4", ADDR_V4_WIDTH, "Local Address",
- ADDR_V4_WIDTH, "Remote Address", "Zone");
+ ADDR_V4_WIDTH, "Remote Address", "Stack", "Zone");
if (mdb_walk("udp_cache", netstat_udpv4_cb,
(void *)(uintptr_t)opts) == -1) {
@@ -1209,10 +1260,10 @@
if ((optf == NULL) || (strcmp("inet6", optf) == 0)) {
/* Print UDPv6 connection */
- mdb_printf(
- "%<u>%-?s St %*s %*s %s\n%</u>",
+ mdb_printf("%<u>%-?s St %*s %*s "
+ "%s %s%\n%</u>",
"UDPv6", ADDR_V6_WIDTH, "Local Address",
- ADDR_V6_WIDTH, "Remote Address", "Zone");
+ ADDR_V6_WIDTH, "Remote Address", "Stack", "Zone");
if (mdb_walk("udp_cache", netstat_udpv6_cb,
(void *)(uintptr_t)opts) == -1) {
diff --git a/usr/src/cmd/mdb/common/modules/genunix/net.h b/usr/src/cmd/mdb/common/modules/genunix/net.h
index 45e03a5..59df026 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/net.h
+++ b/usr/src/cmd/mdb/common/modules/genunix/net.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -45,7 +44,14 @@
extern void mi_walk_fini(mdb_walk_state_t *);
extern int mi_payload_walk_init(mdb_walk_state_t *);
extern int mi_payload_walk_step(mdb_walk_state_t *);
-extern void mi_payload_walk_fini(mdb_walk_state_t *);
+extern int ar_stacks_walk_init(mdb_walk_state_t *);
+extern int ar_stacks_walk_step(mdb_walk_state_t *);
+extern int icmp_stacks_walk_init(mdb_walk_state_t *);
+extern int icmp_stacks_walk_step(mdb_walk_state_t *);
+extern int tcp_stacks_walk_init(mdb_walk_state_t *);
+extern int tcp_stacks_walk_step(mdb_walk_state_t *);
+extern int udp_stacks_walk_init(mdb_walk_state_t *);
+extern int udp_stacks_walk_step(mdb_walk_state_t *);
extern int sonode(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int mi(uintptr_t, uint_t, int, const mdb_arg_t *);
diff --git a/usr/src/cmd/mdb/common/modules/genunix/netstack.c b/usr/src/cmd/mdb/common/modules/genunix/netstack.c
new file mode 100644
index 0000000..588bd6d
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/netstack.c
@@ -0,0 +1,123 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
+#include <sys/types.h>
+#include <sys/netstack.h>
+
+int
+netstack_walk_init(mdb_walk_state_t *wsp)
+{
+ GElf_Sym sym;
+ uintptr_t addr;
+
+ if (mdb_lookup_by_name("netstack_head", &sym) == -1) {
+ mdb_warn("couldn't find netstack_head");
+ return (WALK_ERR);
+ }
+ addr = (uintptr_t)sym.st_value;
+
+ if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), addr) == -1) {
+ mdb_warn("failed to read address of initial netstack "
+ "at %p", addr);
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+netstack_walk_step(mdb_walk_state_t *wsp)
+{
+ int status;
+ netstack_t nss;
+
+ if (wsp->walk_addr == NULL)
+ return (WALK_DONE);
+
+ if (mdb_vread(&nss, sizeof (netstack_t), wsp->walk_addr) == -1) {
+ mdb_warn("failed to read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ status = wsp->walk_callback(wsp->walk_addr, &nss,
+ wsp->walk_cbdata);
+
+ if (status != WALK_NEXT)
+ return (status);
+
+ wsp->walk_addr = (uintptr_t)nss.netstack_next;
+ return (status);
+}
+
+/*ARGSUSED*/
+int
+netstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ netstack_t nss;
+ uint_t quiet = FALSE;
+ uint_t verbose = FALSE;
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ if (mdb_walk_dcmd("genunix`netstack", "genunix`netstack",
+ argc, argv) == -1) {
+ mdb_warn("failed to walk netstack");
+ return (DCMD_ERR);
+ }
+ return (DCMD_OK);
+ }
+ if (mdb_getopts(argc, argv,
+ 'v', MDB_OPT_SETBITS, TRUE, &verbose,
+ 'q', MDB_OPT_SETBITS, TRUE, &quiet,
+ NULL) != argc)
+ return (DCMD_USAGE);
+
+ if (DCMD_HDRSPEC(flags) && !quiet) {
+ mdb_printf("%?s %-7s %6s\n",
+ "ADDR", "STACKID", "FLAGS");
+ }
+
+ if (mdb_vread(&nss, sizeof (nss), addr) == -1) {
+ mdb_warn("couldn't read netstack at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ /*
+ * Options are specified for filtering, so If any option is specified on
+ * the command line, just print address and exit.
+ */
+ if (quiet) {
+ mdb_printf("%0?p\n", addr);
+ return (DCMD_OK);
+ }
+
+ mdb_printf("%0?p %6d %06x\n",
+ addr, nss.netstack_stackid, nss.netstack_flags);
+
+ return (DCMD_OK);
+}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/netstack.h b/usr/src/cmd/mdb/common/modules/genunix/netstack.h
new file mode 100644
index 0000000..392565c
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/netstack.h
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NETSTACK_H
+#define _NETSTACK_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <mdb/mdb_modapi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int netstack_walk_init(mdb_walk_state_t *);
+int netstack_walk_step(mdb_walk_state_t *);
+
+int netstack(uintptr_t, uint_t, int, const mdb_arg_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETSTACK_H */
diff --git a/usr/src/cmd/mdb/common/modules/hook/hook.c b/usr/src/cmd/mdb/common/modules/hook/hook.c
index d9ab29e..ec9679b 100644
--- a/usr/src/cmd/mdb/common/modules/hook/hook.c
+++ b/usr/src/cmd/mdb/common/modules/hook/hook.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,6 +29,7 @@
#include <sys/rwlock.h>
#include <mdb/mdb_modapi.h>
#include <sys/queue.h>
+#include <inet/ip.h>
#include <sys/hook.h>
#include <sys/hook_impl.h>
@@ -153,6 +154,7 @@
int
hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
+ struct hook_stack *hks;
hook_family_int_head_t hfh;
hook_family_int_t hf, *hfp;
char hrrstr[MAX_LENGTH];
@@ -160,8 +162,15 @@
if (argc)
return (DCMD_USAGE);
- if (mdb_readvar(&hfh, "familylist") == -1) {
- mdb_warn("couldn't read symbol 'familylist'");
+ if (mdb_vread((void *)&hks, sizeof (hks),
+ (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_hook))) == -1) {
+ mdb_warn("couldn't read netstack_hook");
+ return (DCMD_ERR);
+ }
+
+ if (mdb_vread((void *)&hfh, sizeof (hfh), (uintptr_t)((uintptr_t)hks +
+ OFFSETOF(hook_stack_t, hks_familylist))) == -1) {
+ mdb_warn("couldn't read hook family head");
return (DCMD_ERR);
}
@@ -192,7 +201,7 @@
static int
-hookevent_walk_init(mdb_walk_state_t *wsp)
+hookevent_stack_walk_init(mdb_walk_state_t *wsp)
{
hook_family_int_t hf;
@@ -212,7 +221,7 @@
}
static int
-hookevent_walk_step(mdb_walk_state_t *wsp)
+hookevent_stack_walk_step(mdb_walk_state_t *wsp)
{
hook_event_int_t hr;
@@ -228,7 +237,6 @@
wsp->walk_cbdata));
}
-
static const mdb_dcmd_t dcmds[] = {
{ "hookrootlist", "", "display hook family information", hookrootlist },
{ "hookeventlist", "", "display hook event information",
@@ -238,8 +246,8 @@
};
static const mdb_walker_t walkers[] = {
- { "hookevent", "walk a list of hooks",
- hookevent_walk_init, hookevent_walk_step, NULL },
+ { "hookevent_stack", "walk list of hooks",
+ hookevent_stack_walk_init, hookevent_stack_walk_step, NULL },
{ NULL }
};
diff --git a/usr/src/cmd/mdb/common/modules/ip/ip.c b/usr/src/cmd/mdb/common/modules/ip/ip.c
index 8320fee..8a24af3 100644
--- a/usr/src/cmd/mdb/common/modules/ip/ip.c
+++ b/usr/src/cmd/mdb/common/modules/ip/ip.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -76,34 +76,92 @@
static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *);
static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *);
+static int ire_format(uintptr_t addr, const ire_t *irep, uint_t *verbose);
+
+/*
+ * Given the kernel address of an ip_stack_t, return the stackid
+ */
+static int
+ips_to_stackid(uintptr_t kaddr)
+{
+ ip_stack_t ipss;
+ netstack_t nss;
+
+ if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) {
+ mdb_warn("failed to read ip_stack_t %p", kaddr);
+ return (0);
+ }
+ kaddr = (uintptr_t)ipss.ips_netstack;
+ if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
+ mdb_warn("failed to read netstack_t %p", kaddr);
+ return (0);
+ }
+ return (nss.netstack_stackid);
+}
+
int
-illif_walk_init(mdb_walk_state_t *wsp)
+ip_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+ip_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+#ifdef DEBUG
+ mdb_printf("DEBUG: ip_stacks_walk_step: addr %p\n", wsp->walk_addr);
+#endif
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_IP];
+
+#ifdef DEBUG
+ mdb_printf("DEBUG: ip_stacks_walk_step: ip_stack_t at %p\n", kaddr);
+#endif
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
+/*
+ * Called with walk_addr being the address of ips_ill_g_heads
+ */
+int
+illif_stack_walk_init(mdb_walk_state_t *wsp)
{
illif_walk_data_t *iw;
- if (wsp->walk_addr != NULL) {
- mdb_warn("illif supports only global walks\n");
+ if (wsp->walk_addr == NULL) {
+ mdb_warn("illif_stack supports only local walks\n");
return (WALK_ERR);
}
iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP);
- if (mdb_readsym(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t),
- "ill_g_heads") == -1) {
- mdb_warn("failed to read 'ill_g_heads'");
+ if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t),
+ wsp->walk_addr) == -1) {
+ mdb_warn("failed to read 'ips_ill_g_heads' at %p",
+ wsp->walk_addr);
mdb_free(iw, sizeof (illif_walk_data_t));
return (WALK_ERR);
}
iw->ill_list = 0;
- wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(0);
+ wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head;
wsp->walk_data = iw;
return (WALK_NEXT);
}
int
-illif_walk_step(mdb_walk_state_t *wsp)
+illif_stack_walk_step(mdb_walk_state_t *wsp)
{
uintptr_t addr = wsp->walk_addr;
illif_walk_data_t *iw = wsp->walk_data;
@@ -116,13 +174,15 @@
wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next;
- if (wsp->walk_addr == (uintptr_t)iw->IP_VX_ILL_G_LIST(list)) {
+ if (wsp->walk_addr ==
+ (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) {
if (++list >= MAX_G_HEADS)
return (WALK_DONE);
iw->ill_list = list;
- wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(list);
+ wsp->walk_addr =
+ (uintptr_t)iw->ill_g_heads[list].ill_g_list_head;
return (WALK_NEXT);
}
@@ -130,7 +190,7 @@
}
void
-illif_walk_fini(mdb_walk_state_t *wsp)
+illif_stack_walk_fini(mdb_walk_state_t *wsp)
{
mdb_free(wsp->walk_data, sizeof (illif_walk_data_t));
}
@@ -176,6 +236,45 @@
}
int
+illif_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("ip_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'ip_stacks'");
+ return (WALK_ERR);
+ }
+
+ return (WALK_NEXT);
+}
+
+int
+illif_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+
+#ifdef DEBUG
+ mdb_printf("DEBUG: illif_walk_step: addr %p\n", wsp->walk_addr);
+#endif
+
+ kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads);
+
+ if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
+ mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
+ return (WALK_ERR);
+ }
+#ifdef DEBUG
+ mdb_printf("DEBUG: illif_walk_step: ips_ill_g_heads %p\n", kaddr);
+#endif
+
+ if (mdb_pwalk("illif_stack", wsp->walk_callback,
+ wsp->walk_cbdata, kaddr) == -1) {
+ mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p",
+ kaddr);
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
illif_cbdata_t id;
@@ -265,6 +364,112 @@
return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata));
}
+int
+ire_ctable_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("ip_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'ip_stacks'");
+ return (WALK_ERR);
+ }
+
+ return (WALK_NEXT);
+}
+
+int
+ire_ctable_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ irb_t *irb;
+ int verbose = 0;
+ uint32_t cache_table_size;
+ int i;
+
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_ctable_walk_step: addr %p\n", wsp->walk_addr);
+#endif
+
+ kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table_size);
+
+ if (mdb_vread(&cache_table_size, sizeof (uint32_t), kaddr) == -1) {
+ mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
+ return (WALK_ERR);
+ }
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_ctable_walk_step: ips_ip_cache_table_size %u\n",
+ cache_table_size);
+#endif
+
+ kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table);
+ if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
+ mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
+ return (WALK_ERR);
+ }
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_ctable_walk_step: ips_ip_cache_table %p\n",
+ kaddr);
+#endif
+
+ irb = mdb_alloc(sizeof (irb_t) * cache_table_size, UM_SLEEP|UM_GC);
+ if (mdb_vread(irb, sizeof (irb_t) * cache_table_size, kaddr) == -1) {
+ mdb_warn("can't read irb at %p", kaddr);
+ return (WALK_ERR);
+ }
+ for (i = 0; i < cache_table_size; i++) {
+ kaddr = (uintptr_t)irb[i].irb_ire;
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_ctable_walk_step: %d ire %p\n",
+ i, kaddr);
+#endif
+
+ if (mdb_pwalk("ire_next", (mdb_walk_cb_t)ire_format, &verbose,
+ kaddr) == -1) {
+ mdb_warn("can't walk 'ire_next' for ire %p", kaddr);
+ return (WALK_ERR);
+ }
+ }
+ return (WALK_NEXT);
+}
+
+/* ARGSUSED */
+int
+ire_next_walk_init(mdb_walk_state_t *wsp)
+{
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_next_walk_init: addr %p\n", wsp->walk_addr);
+#endif
+ return (WALK_NEXT);
+}
+
+int
+ire_next_walk_step(mdb_walk_state_t *wsp)
+{
+ ire_t ire;
+ int status;
+
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_next_walk_step: addr %p\n", wsp->walk_addr);
+#endif
+
+ if (wsp->walk_addr == NULL)
+ return (WALK_DONE);
+
+ if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
+ mdb_warn("can't read ire at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ status = wsp->walk_callback(wsp->walk_addr, &ire,
+ wsp->walk_cbdata);
+
+ if (status != WALK_NEXT)
+ return (status);
+
+ wsp->walk_addr = (uintptr_t)ire.ire_next;
+#ifdef DEBUG
+ mdb_printf("DEBUG: ire_ctable_walk_step: next %p\n", wsp->walk_addr);
+#endif
+ return (status);
+}
+
static int
ire_format(uintptr_t addr, const ire_t *irep, uint_t *verbose)
{
@@ -318,15 +523,20 @@
mdb_printf("%<b>%?p%</b> %40N <%hb>\n"
"%?s %40N <%hb>\n"
- "%?s %40d <%hb>\n",
+ "%?s %40d %4d <%hb>\n",
addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks,
"", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks,
- "", irep->ire_zoneid, irep->ire_flags, fmasks);
+ "", ips_to_stackid((uintptr_t)irep->ire_ipst),
+ irep->ire_zoneid,
+ irep->ire_flags, fmasks);
} else if (irep->ire_ipversion == 6) {
- mdb_printf("%?p %30N %30N %4d\n", addr, &irep->ire_src_addr_v6,
- &irep->ire_addr_v6, irep->ire_zoneid);
+ mdb_printf("%?p %30N %30N %5d %4d\n",
+ addr, &irep->ire_src_addr_v6,
+ &irep->ire_addr_v6,
+ ips_to_stackid((uintptr_t)irep->ire_ipst),
+ irep->ire_zoneid);
} else if (*verbose) {
@@ -335,12 +545,14 @@
"%?s %40d <%hb>\n",
addr, irep->ire_src_addr, irep->ire_type, tmasks,
"", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks,
- "", irep->ire_zoneid, irep->ire_flags, fmasks);
+ "", ips_to_stackid((uintptr_t)irep->ire_ipst),
+ irep->ire_zoneid, irep->ire_flags, fmasks);
} else {
- mdb_printf("%?p %30I %30I %4d\n", addr, irep->ire_src_addr,
- irep->ire_addr, irep->ire_zoneid);
+ mdb_printf("%?p %30I %30I %5d %4d\n", addr, irep->ire_src_addr,
+ irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst),
+ irep->ire_zoneid);
}
return (WALK_NEXT);
@@ -676,13 +888,13 @@
if (verbose) {
mdb_printf("%?s %40s %-20s%\n"
"%?s %40s %-20s%\n"
- "%<u>%?s %40s %-20s%</u>\n",
+ "%<u>%?s %40s %4s %-20s%</u>\n",
"ADDR", "SRC", "TYPE",
"", "DST", "MARKS",
- "", "ZONE", "FLAGS");
+ "", "STACK", "ZONE", "FLAGS");
} else {
- mdb_printf("%<u>%?s %30s %30s %4s%</u>\n",
- "ADDR", "SRC", "DST", "ZONE");
+ mdb_printf("%<u>%?s %30s %30s %5s %4s%</u>\n",
+ "ADDR", "SRC", "DST", "STACK", "ZONE");
}
}
@@ -853,10 +1065,19 @@
};
static const mdb_walker_t walkers[] = {
- { "illif", "walk list of ill interface types",
- illif_walk_init, illif_walk_step, illif_walk_fini },
+ { "illif", "walk list of ill interface types for all stacks",
+ illif_walk_init, illif_walk_step, NULL },
+ { "illif_stack", "walk list of ill interface types",
+ illif_stack_walk_init, illif_stack_walk_step,
+ illif_stack_walk_fini },
{ "ire", "walk active ire_t structures",
ire_walk_init, ire_walk_step, NULL },
+ { "ire_ctable", "walk ire_t structures in the ctable",
+ ire_ctable_walk_init, ire_ctable_walk_step, NULL },
+ { "ire_next", "walk ire_t structures in the ctable",
+ ire_next_walk_init, ire_next_walk_step, NULL },
+ { "ip_stacks", "walk all the ip_stack_t",
+ ip_stacks_walk_init, ip_stacks_walk_step, NULL },
{ NULL }
};
diff --git a/usr/src/cmd/mdb/common/modules/neti/neti.c b/usr/src/cmd/mdb/common/modules/neti/neti.c
index 788099b..e58fa42 100644
--- a/usr/src/cmd/mdb/common/modules/neti/neti.c
+++ b/usr/src/cmd/mdb/common/modules/neti/neti.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,8 +38,6 @@
*/
#define PROT_LENGTH 32
-LIST_HEAD(netd_listhead, net_data);
-
/*
* List pfhooks netinfo information.
*/
@@ -47,6 +45,7 @@
int
netinfolist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
+ struct neti_stack *nts;
struct netd_listhead nlh;
struct net_data nd, *p;
char str[PROT_LENGTH];
@@ -54,8 +53,15 @@
if (argc)
return (DCMD_USAGE);
- if (mdb_readvar(&nlh, "netd_head") == -1) {
- mdb_warn("couldn't read symbol 'netd_head'");
+ if (mdb_vread((void *)&nts, sizeof (nts),
+ (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_neti))) == -1) {
+ mdb_warn("couldn't read netstack_neti");
+ return (DCMD_ERR);
+ }
+
+ if (mdb_vread((void *)&nlh, sizeof (nlh), (uintptr_t)((uintptr_t)nts +
+ OFFSETOF(neti_stack_t, nts_netd_head))) == -1) {
+ mdb_warn("couldn't read netd list head");
return (DCMD_ERR);
}
mdb_printf("%<u>%?s %?s %10s%</u>\n",
diff --git a/usr/src/cmd/mdb/common/modules/sctp/sctp.c b/usr/src/cmd/mdb/common/modules/sctp/sctp.c
index c40d324..aa088b4 100644
--- a/usr/src/cmd/mdb/common/modules/sctp/sctp.c
+++ b/usr/src/cmd/mdb/common/modules/sctp/sctp.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,23 +65,48 @@
#define MDB_SCTP_SHOW_ALL 0xffffffff
-uint_t sctp_conn_hash_size;
-static GElf_Sym sctp_list_sym;
-static list_t sctp_list;
-
-/*
- * Both the ill and ipif global arrays are small, so we just read
- * in the whole arrays.
- */
-static sctp_ill_hash_t local_g_ills[SCTP_ILL_HASH];
-static sctp_ipif_hash_t local_g_ipifs[SCTP_IPIF_HASH];
-
/*
* Copy from usr/src/uts/common/os/list.c. Should we have a generic
* mdb list walker?
*/
#define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
+static int
+ns_to_stackid(uintptr_t kaddr)
+{
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
+ mdb_warn("failed to read netdstack info %p", kaddr);
+ return (0);
+ }
+ return (nss.netstack_stackid);
+}
+
+int
+sctp_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("netstack", wsp) == -1) {
+ mdb_warn("can't walk 'netstack'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+sctp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+ netstack_t nss;
+
+ if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+ mdb_warn("can't read netstack at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ kaddr = (uintptr_t)nss.netstack_modules[NS_SCTP];
+ return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
static char *
sctp_faddr_state(int state)
{
@@ -713,8 +738,9 @@
mdb_nhconvert(&lport, &sctp.sctp_lport, sizeof (lport));
mdb_nhconvert(&fport, &sctp.sctp_fport, sizeof (fport));
- mdb_printf("%<u>%p% %22s S=%-6hu D=%-6hu% ZONE=%d%</u>", addr,
- state2str(&sctp), lport, fport, connp.conn_zoneid);
+ mdb_printf("%<u>%p% %22s S=%-6hu D=%-6hu% STACK=%d ZONE=%d%</u>", addr,
+ state2str(&sctp), lport, fport,
+ ns_to_stackid((uintptr_t)connp.conn_netstack), connp.conn_zoneid);
if (sctp.sctp_faddrs) {
sctp_faddr_t faddr;
@@ -888,8 +914,6 @@
mdb_printf("%<b>Hash Tables%</b>\n");
mdb_printf("conn_hash_next\t%?p\t", sctp.sctp_conn_hash_next);
mdb_printf("conn_hash_prev\t%?p\n", sctp.sctp_conn_hash_prev);
- mdb_printf("[ conn_hash bucket\t%?d ]\n",
- SCTP_CONN_HASH(sctp.sctp_ports));
mdb_printf("listen_hash_next%?p\t",
sctp.sctp_listen_hash_next);
@@ -956,8 +980,9 @@
} fanout_walk_data_t;
typedef struct fanout_init {
- const char *symname;
- int (*getsize)();
+ const char *nested_walker_name;
+ size_t offset; /* for what used to be a symbol */
+ int (*getsize)(sctp_stack_t *);
uintptr_t (*getnext)(sctp_t *);
} fanout_init_t;
@@ -967,8 +992,9 @@
return ((uintptr_t)sctp->sctp_listen_hash_next);
}
+/* ARGSUSED */
static int
-listen_size(void)
+listen_size(sctp_stack_t *sctps)
{
return (SCTP_LISTEN_FANOUT_SIZE);
}
@@ -980,17 +1006,15 @@
}
static int
-conn_size(void)
+conn_size(sctp_stack_t *sctps)
{
- GElf_Sym sym;
int size;
+ uintptr_t kaddr;
- if (mdb_lookup_by_name("sctp_conn_hash_size", &sym) == -1) {
- mdb_warn("can't read 'sctp_conn_hash_size'");
- return (1);
- }
- if (mdb_vread(&size, sizeof (size), sym.st_value) == -1) {
- mdb_warn("can't dereference 'sctp_conn_hash_size'");
+ kaddr = (uintptr_t)&sctps->sctps_conn_hash_size;
+
+ if (mdb_vread(&size, sizeof (size), kaddr) == -1) {
+ mdb_warn("can't read 'sctps_conn_hash_size' at %p", kaddr);
return (1);
}
return (size);
@@ -1002,8 +1026,9 @@
return ((uintptr_t)sctp->sctp_bind_hash);
}
+/* ARGSUSED */
static int
-bind_size(void)
+bind_size(sctp_stack_t *sctps)
{
return (SCTP_BIND_FANOUT_SIZE);
}
@@ -1048,22 +1073,25 @@
}
static int
-fanout_walk_init(mdb_walk_state_t *wsp)
+fanout_stack_walk_init(mdb_walk_state_t *wsp)
{
- GElf_Sym sym;
fanout_walk_data_t *lw;
fanout_init_t *fi = wsp->walk_arg;
+ sctp_stack_t *sctps = (sctp_stack_t *)wsp->walk_addr;
+ uintptr_t kaddr;
- if (mdb_lookup_by_name(fi->symname, &sym) == -1) {
- mdb_warn("failed to read '%s'", fi->symname);
+ if (mdb_vread(&kaddr, sizeof (kaddr),
+ wsp->walk_addr + fi->offset) == -1) {
+ mdb_warn("can't read sctp fanout at %p",
+ wsp->walk_addr + fi->offset);
return (WALK_ERR);
}
lw = mdb_alloc(sizeof (*lw), UM_SLEEP);
lw->index = 0;
- lw->size = fi->getsize();
+ lw->size = fi->getsize(sctps);
lw->sctp = NULL;
- lw->fanout = (sctp_tf_t *)(uintptr_t)sym.st_value;
+ lw->fanout = (sctp_tf_t *)kaddr;
lw->getnext = fi->getnext;
if ((wsp->walk_addr = find_next_hash_item(lw)) == NULL) {
@@ -1074,7 +1102,7 @@
}
static int
-fanout_walk_step(mdb_walk_state_t *wsp)
+fanout_stack_walk_step(mdb_walk_state_t *wsp)
{
fanout_walk_data_t *fw = wsp->walk_data;
uintptr_t addr = wsp->walk_addr;
@@ -1097,43 +1125,62 @@
}
static void
-fanout_walk_fini(mdb_walk_state_t *wsp)
+fanout_stack_walk_fini(mdb_walk_state_t *wsp)
{
fanout_walk_data_t *fw = wsp->walk_data;
mdb_free(fw, sizeof (*fw));
}
-static int
-sctp_walk_init(mdb_walk_state_t *wsp)
+int
+fanout_walk_init(mdb_walk_state_t *wsp)
{
- wsp->walk_addr = (uintptr_t)list_object(&sctp_list,
- sctp_list.list_head.list_next);
+ if (mdb_layered_walk("sctp_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'sctp_stacks'");
+ return (WALK_ERR);
+ }
+
return (WALK_NEXT);
}
-static int
-sctp_walk_step(mdb_walk_state_t *wsp)
+int
+fanout_walk_step(mdb_walk_state_t *wsp)
{
- uintptr_t psctp = wsp->walk_addr;
- sctp_t sctp;
- int status;
+ fanout_init_t *fi = wsp->walk_arg;
- if (mdb_vread(&sctp, sizeof (sctp), psctp) == -1) {
- mdb_warn("failed to read sctp at %p", psctp);
+ if (mdb_pwalk(fi->nested_walker_name, wsp->walk_callback,
+ wsp->walk_cbdata, wsp->walk_addr) == -1) {
+ mdb_warn("couldn't walk '%s'for address %p",
+ fi->nested_walker_name, wsp->walk_addr);
return (WALK_ERR);
}
- status = wsp->walk_callback(psctp, &sctp, wsp->walk_cbdata);
- if (status != WALK_NEXT)
- return (status);
+ return (WALK_NEXT);
+}
- if ((psctp = (uintptr_t)sctp.sctp_list.list_next) ==
- sctp_list_sym.st_value + OFFSETOF(list_t, list_head)) {
- return (WALK_DONE);
- } else {
- wsp->walk_addr = (uintptr_t)list_object(&sctp_list, psctp);
- return (WALK_NEXT);
+int
+sctps_walk_init(mdb_walk_state_t *wsp)
+{
+
+ if (mdb_layered_walk("sctp_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'sctp_stacks'");
+ return (WALK_ERR);
}
+
+ return (WALK_NEXT);
+}
+
+int
+sctps_walk_step(mdb_walk_state_t *wsp)
+{
+ uintptr_t kaddr;
+
+ kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_list);
+ if (mdb_pwalk("list", wsp->walk_callback,
+ wsp->walk_cbdata, kaddr) == -1) {
+ mdb_warn("couldn't walk 'list' for address %p", kaddr);
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
}
static int
@@ -1281,66 +1328,78 @@
mdb_free(swalker, sizeof (saddr_walk_t));
}
-static int
-sctp_walk_ill_init(mdb_walk_state_t *wsp)
+
+typedef struct ill_walk_data {
+ sctp_ill_hash_t ills[SCTP_ILL_HASH];
+ uint32_t count;
+} ill_walk_data_t;
+
+typedef struct ipuf_walk_data {
+ sctp_ipif_hash_t ipifs[SCTP_IPIF_HASH];
+ uint32_t count;
+} ipif_walk_data_t;
+
+
+int
+sctp_ill_walk_init(mdb_walk_state_t *wsp)
{
+ if (mdb_layered_walk("sctp_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'sctp_stacks'");
+ return (WALK_ERR);
+ }
+
+ return (WALK_NEXT);
+}
+
+int
+sctp_ill_walk_step(mdb_walk_state_t *wsp)
+{
+ if (mdb_pwalk("sctp_stack_walk_ill", wsp->walk_callback,
+ wsp->walk_cbdata, wsp->walk_addr) == -1) {
+ mdb_warn("couldn't walk 'sctp_stack_walk_ill' for addr %p",
+ wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+/*
+ * wsp->walk_addr is the address of sctps_ill_list
+ */
+static int
+sctp_stack_ill_walk_init(mdb_walk_state_t *wsp)
+{
+ ill_walk_data_t iw;
intptr_t i;
+ uintptr_t kaddr, uaddr;
+ size_t offset;
+
+ kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_ills_count);
+ if (mdb_vread(&iw.count, sizeof (iw.count), kaddr) == -1) {
+ mdb_warn("can't read sctps_ills_count at %p", kaddr);
+ return (WALK_ERR);
+ }
+ kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ills);
+
+ if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
+ mdb_warn("can't read scpts_g_ills %p", kaddr);
+ return (WALK_ERR);
+ }
+ if (mdb_vread(&iw.ills, sizeof (iw.ills), kaddr) == -1) {
+ mdb_warn("failed to read 'sctps_g_ills'");
+ return (NULL);
+ }
/* Find the first ill. */
for (i = 0; i < SCTP_ILL_HASH; i++) {
- if (local_g_ills[i].ill_count > 0) {
- wsp->walk_addr = (uintptr_t)list_object(
- &local_g_ills[i].sctp_ill_list,
- local_g_ills[i].sctp_ill_list.list_head.list_next);
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)1;
- return (WALK_NEXT);
- }
- }
- return (WALK_DONE);
-}
-
-static int
-sctp_walk_ill_step(mdb_walk_state_t *wsp)
-{
- uintptr_t ill_ptr = wsp->walk_addr;
- sctp_ill_t ill;
- int status;
- intptr_t i, j;
-
- if (mdb_vread(&ill, sizeof (sctp_ill_t), ill_ptr) == -1) {
- mdb_warn("failed to read sctp_ill_t at %p", ill_ptr);
- return (WALK_ERR);
- }
- status = wsp->walk_callback(ill_ptr, &ill, wsp->walk_cbdata);
- if (status != WALK_NEXT)
- return (status);
-
- i = (intptr_t)wsp->walk_data;
- j = (intptr_t)wsp->walk_arg;
-
- /*
- * If there is still an ill in the current list, return it.
- * Otherwise, go to the next list and find another one.
- */
- if (j++ < local_g_ills[i].ill_count) {
- wsp->walk_addr = (uintptr_t)ill.sctp_ills.list_next;
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)j;
- return (WALK_NEXT);
- } else {
- list_t *ill_list;
-
- for (i = i + 1; i < SCTP_ILL_HASH; i++) {
- if (local_g_ills[i].ill_count > 0) {
- ill_list = &local_g_ills[i].sctp_ill_list;
- wsp->walk_addr = (uintptr_t)list_object(
- ill_list, ill_list->list_head.list_next);
-
- /* Record the current position. */
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)1;
- return (WALK_NEXT);
+ if (iw.ills[i].ill_count > 0) {
+ uaddr = (uintptr_t)&iw.ills[i].sctp_ill_list;
+ offset = uaddr - (uintptr_t)&iw.ills;
+ if (mdb_pwalk("list", wsp->walk_callback,
+ wsp->walk_cbdata, kaddr+offset) == -1) {
+ mdb_warn("couldn't walk 'list' for address %p",
+ kaddr);
+ return (WALK_ERR);
}
}
}
@@ -1348,70 +1407,82 @@
}
static int
-sctp_walk_ipif_init(mdb_walk_state_t *wsp)
+sctp_stack_ill_walk_step(mdb_walk_state_t *wsp)
{
+ return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
+ wsp->walk_cbdata));
+}
+
+int
+sctp_ipif_walk_init(mdb_walk_state_t *wsp)
+{
+ if (mdb_layered_walk("sctp_stacks", wsp) == -1) {
+ mdb_warn("can't walk 'sctp_stacks'");
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+int
+sctp_ipif_walk_step(mdb_walk_state_t *wsp)
+{
+ if (mdb_pwalk("sctp_stack_walk_ipif", wsp->walk_callback,
+ wsp->walk_cbdata, wsp->walk_addr) == -1) {
+ mdb_warn("couldn't walk 'sctp_stack_walk_ipif' for addr %p",
+ wsp->walk_addr);
+ return (WALK_ERR);
+ }
+ return (WALK_NEXT);
+}
+
+/*
+ * wsp->walk_addr is the address of sctps_ipif_list
+ */
+static int
+sctp_stack_ipif_walk_init(mdb_walk_state_t *wsp)
+{
+ ipif_walk_data_t iw;
intptr_t i;
- list_t *ipif_list;
+ uintptr_t kaddr, uaddr;
+ size_t offset;
+ kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ipifs_count);
+ if (mdb_vread(&iw.count, sizeof (iw.count), kaddr) == -1) {
+ mdb_warn("can't read sctps_g_ipifs_count at %p", kaddr);
+ return (WALK_ERR);
+ }
+ kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ipifs);
+
+ if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
+ mdb_warn("can't read scpts_g_ipifs %p", kaddr);
+ return (WALK_ERR);
+ }
+ if (mdb_vread(&iw.ipifs, sizeof (iw.ipifs), kaddr) == -1) {
+ mdb_warn("failed to read 'sctps_g_ipifs'");
+ return (NULL);
+ }
+
+ /* Find the first ipif. */
for (i = 0; i < SCTP_IPIF_HASH; i++) {
- if (local_g_ipifs[i].ipif_count > 0) {
- ipif_list = &local_g_ipifs[i].sctp_ipif_list;
-
- wsp->walk_addr = (uintptr_t)list_object(ipif_list,
- ipif_list->list_head.list_next);
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)1;
- return (WALK_NEXT);
+ if (iw.ipifs[i].ipif_count > 0) {
+ uaddr = (uintptr_t)&iw.ipifs[i].sctp_ipif_list;
+ offset = uaddr - (uintptr_t)&iw.ipifs;
+ if (mdb_pwalk("list", wsp->walk_callback,
+ wsp->walk_cbdata, kaddr+offset) == -1) {
+ mdb_warn("couldn't walk 'list' for address %p",
+ kaddr);
+ return (WALK_ERR);
+ }
}
}
return (WALK_DONE);
}
static int
-sctp_walk_ipif_step(mdb_walk_state_t *wsp)
+sctp_stack_ipif_walk_step(mdb_walk_state_t *wsp)
{
- uintptr_t ipif_ptr = wsp->walk_addr;
- sctp_ipif_t ipif;
- int status;
- intptr_t i, j;
-
- if (mdb_vread(&ipif, sizeof (sctp_ipif_t), ipif_ptr) == -1) {
- mdb_warn("failed to read sctp_ipif_t at %p", ipif_ptr);
- return (WALK_ERR);
- }
- status = wsp->walk_callback(ipif_ptr, &ipif, wsp->walk_cbdata);
- if (status != WALK_NEXT)
- return (status);
-
- i = (intptr_t)wsp->walk_data;
- j = (intptr_t)wsp->walk_arg;
-
- /*
- * If there is still an ipif in the current list, return it.
- * Otherwise, go to the next list and find another one.
- */
- if (j++ < local_g_ipifs[i].ipif_count) {
- wsp->walk_addr = (uintptr_t)ipif.sctp_ipifs.list_next;
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)j;
- return (WALK_NEXT);
- } else {
- list_t *ipif_list;
-
- for (i = i + 1; i < SCTP_IPIF_HASH; i++) {
- if (local_g_ipifs[i].ipif_count > 0) {
- ipif_list = &local_g_ipifs[i].sctp_ipif_list;
- wsp->walk_addr = (uintptr_t)list_object(
- ipif_list, ipif_list->list_head.list_next);
-
- /* Record the current position */
- wsp->walk_data = (void *)i;
- wsp->walk_arg = (void *)1;
- return (WALK_NEXT);
- }
- }
- }
- return (WALK_DONE);
+ return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
+ wsp->walk_cbdata));
}
static void
@@ -1455,37 +1526,59 @@
};
static const fanout_init_t listen_fanout_init = {
- "sctp_listen_fanout", listen_size, listen_next
+ "sctp_stack_listen_fanout", OFFSETOF(sctp_stack_t, sctps_listen_fanout),
+ listen_size, listen_next
};
static const fanout_init_t conn_fanout_init = {
- "sctp_conn_fanout", conn_size, conn_next
+ "sctp_stack_conn_fanout", OFFSETOF(sctp_stack_t, sctps_conn_fanout),
+ conn_size, conn_next
};
static const fanout_init_t bind_fanout_init = {
- "sctp_bind_fanout", bind_size, bind_next
+ "sctp_stack_bind_fanout", OFFSETOF(sctp_stack_t, sctps_bind_fanout),
+ bind_size, bind_next
};
static const mdb_walker_t walkers[] = {
- { "sctps", "walk the full chain of sctps",
- sctp_walk_init, sctp_walk_step, NULL },
- { "sctp_listen_fanout", "walk the sctp listen fanout",
- fanout_walk_init, fanout_walk_step, fanout_walk_fini,
+ { "sctps", "walk the full chain of sctps for all stacks",
+ sctps_walk_init, sctps_walk_step, NULL },
+ { "sctp_listen_fanout", "walk the sctp listen fanout for all stacks",
+ fanout_walk_init, fanout_walk_step, NULL,
(void *)&listen_fanout_init },
- { "sctp_conn_fanout", "walk the sctp conn fanout",
- fanout_walk_init, fanout_walk_step, fanout_walk_fini,
+ { "sctp_conn_fanout", "walk the sctp conn fanout for all stacks",
+ fanout_walk_init, fanout_walk_step, NULL,
(void *)&conn_fanout_init },
- { "sctp_bind_fanout", "walk the sctp bind fanout",
- fanout_walk_init, fanout_walk_step, fanout_walk_fini,
+ { "sctp_bind_fanout", "walk the sctp bind fanout for all stacks",
+ fanout_walk_init, fanout_walk_step, NULL,
+ (void *)&bind_fanout_init },
+ { "sctp_stack_listen_fanout",
+ "walk the sctp listen fanout for one stack",
+ fanout_stack_walk_init, fanout_stack_walk_step,
+ fanout_stack_walk_fini,
+ (void *)&listen_fanout_init },
+ { "sctp_stack_conn_fanout", "walk the sctp conn fanout for one stack",
+ fanout_stack_walk_init, fanout_stack_walk_step,
+ fanout_stack_walk_fini,
+ (void *)&conn_fanout_init },
+ { "sctp_stack_bind_fanout", "walk the sctp bind fanoutfor one stack",
+ fanout_stack_walk_init, fanout_stack_walk_step,
+ fanout_stack_walk_fini,
(void *)&bind_fanout_init },
{ "sctp_walk_faddr", "walk the peer address list of a given sctp_t",
sctp_walk_faddr_init, sctp_walk_faddr_step, NULL },
{ "sctp_walk_saddr", "walk the local address list of a given sctp_t",
sctp_walk_saddr_init, sctp_walk_saddr_step, sctp_walk_saddr_fini },
- { "sctp_walk_ill", "walk the sctp_g_ills list",
- sctp_walk_ill_init, sctp_walk_ill_step, NULL },
- { "sctp_walk_ipif", "walk the sctp_g_ipif list",
- sctp_walk_ipif_init, sctp_walk_ipif_step, NULL },
+ { "sctp_walk_ill", "walk the sctp_g_ills list for all stacks",
+ sctp_ill_walk_init, sctp_ill_walk_step, NULL },
+ { "sctp_walk_ipif", "walk the sctp_g_ipif list for all stacks",
+ sctp_ipif_walk_init, sctp_ipif_walk_step, NULL },
+ { "sctp_stack_walk_ill", "walk the sctp_g_ills list for one stack",
+ sctp_stack_ill_walk_init, sctp_stack_ill_walk_step, NULL },
+ { "sctp_stack_walk_ipif", "walk the sctp_g_ipif list for one stack",
+ sctp_stack_ipif_walk_init, sctp_stack_ipif_walk_step, NULL },
+ { "sctp_stacks", "walk all the sctp_stack_t",
+ sctp_stacks_walk_init, sctp_stacks_walk_step, NULL },
{ NULL }
};
@@ -1494,44 +1587,5 @@
const mdb_modinfo_t *
_mdb_init(void)
{
- GElf_Sym sym;
- GElf_Sym ills_sym;
- GElf_Sym ipifs_sym;
-
- if (mdb_lookup_by_name("sctp_g_list", &sctp_list_sym) == -1) {
- mdb_warn("failed to find 'sctp_g_list'");
- return (NULL);
- }
- if (mdb_vread(&sctp_list, sizeof (list_t),
- (uintptr_t)sctp_list_sym.st_value) == -1) {
- mdb_warn("failed to read 'sctp_g_list'");
- return (NULL);
- }
- if (mdb_lookup_by_name("sctp_conn_hash_size", &sym) != -1) {
- if (mdb_vread(&sctp_conn_hash_size,
- sizeof (sctp_conn_hash_size), sym.st_value) == -1) {
- mdb_warn("failed to read 'sctp_conn_hash_size'");
- return (NULL);
- }
- }
- if (mdb_lookup_by_name("sctp_g_ills", &ills_sym) == -1) {
- mdb_warn("failed to find 'sctp_g_ills'");
- return (NULL);
- }
- if (mdb_vread(&local_g_ills, sizeof (local_g_ills),
- (uintptr_t)ills_sym.st_value) == -1) {
- mdb_warn("failed to read 'sctp_g_ills'");
- return (NULL);
- }
- if (mdb_lookup_by_name("sctp_g_ipifs", &ipifs_sym) == -1) {
- mdb_warn("failed to find 'sctp_g_ipifs'");
- return (NULL);
- }
- if (mdb_vread(&local_g_ipifs, sizeof (local_g_ipifs),
- (uintptr_t)ipifs_sym.st_value) == -1) {
- mdb_warn("failed to read 'sctp_g_ipifs'");
- return (NULL);
- }
-
return (&modinfo);
}
diff --git a/usr/src/cmd/svc/milestone/net-init b/usr/src/cmd/svc/milestone/net-init
index 5862c4e..89c0abd 100644
--- a/usr/src/cmd/svc/milestone/net-init
+++ b/usr/src/cmd/svc/milestone/net-init
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -39,11 +39,12 @@
. /lib/svc/share/smf_include.sh
#
-# In a zone we need this service to be up, but all of the work
-# it tries to do is irrelevant (and will actually lead to the service
-# failing if we try to do it), so just bail out.
+# In a shared-IP zone we need this service to be up, but all of the work
+# it tries to do is irrelevant (and will actually lead to the service
+# failing if we try to do it), so just bail out.
+# In the global zone and exclusive-IP zones we proceed.
#
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
# Configure IPv6 Default Address Selection.
if [ -f /etc/inet/ipaddrsel.conf ]; then
@@ -56,7 +57,8 @@
# automatically exit. Note that it may already be running if we're not
# executing as part of system boot.
#
-/usr/bin/pgrep -x -u 0 in.mpathd >/dev/null 2>&1 || /usr/lib/inet/in.mpathd -a
+/usr/bin/pgrep -x -u 0 -z `smf_zonename` in.mpathd >/dev/null 2>&1 || \
+ /usr/lib/inet/in.mpathd -a
#
# Pass to the kernel the list of supported IPsec protocols and algorithms.
diff --git a/usr/src/cmd/svc/milestone/net-loopback b/usr/src/cmd/svc/milestone/net-loopback
index 9a23eb2..3688a20 100644
--- a/usr/src/cmd/svc/milestone/net-loopback
+++ b/usr/src/cmd/svc/milestone/net-loopback
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -28,11 +28,12 @@
. /lib/svc/share/smf_include.sh
#
-# In a zone we need this service to be up, but all of the work
-# it tries to do is irrelevant (and will actually lead to the service
-# failing if we try to do it), so just bail out.
+# In a shared-IP zone we need this service to be up, but all of the work
+# it tries to do is irrelevant (and will actually lead to the service
+# failing if we try to do it), so just bail out.
+# In the global zone and exclusive-IP zones we proceed.
#
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
#
# Cause ifconfig to not automatically start in.mpathd when IPMP groups are
diff --git a/usr/src/cmd/svc/milestone/net-physical b/usr/src/cmd/svc/milestone/net-physical
index 60c4ee8..cc26006 100644
--- a/usr/src/cmd/svc/milestone/net-physical
+++ b/usr/src/cmd/svc/milestone/net-physical
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
@@ -33,11 +33,12 @@
. /lib/svc/share/net_include.sh
#
-# In a zone we need this service to be up, but all of the work
-# it tries to do is irrelevant (and will actually lead to the service
-# failing if we try to do it), so just bail out.
+# In a shared-IP zone we need this service to be up, but all of the work
+# it tries to do is irrelevant (and will actually lead to the service
+# failing if we try to do it), so just bail out.
+# In the global zone and exclusive-IP zones we proceed.
#
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
# Print warnings to console
warn_failed_ifs() {
@@ -57,14 +58,16 @@
smf_netstrategy
-#
-# Bring up link aggregations and initialize security objects.
-# Note that link property initialization is deferred until after
-# IP interfaces are plumbed to ensure that the links will not
-# be unloaded (and the property settings lost).
-#
-/sbin/dladm up-aggr
-/sbin/dladm init-secobj
+if smf_is_globalzone; then
+ #
+ # Bring up link aggregations and initialize security objects.
+ # Note that link property initialization is deferred until after
+ # IP interfaces are plumbed to ensure that the links will not
+ # be unloaded (and the property settings lost).
+ #
+ /sbin/dladm up-aggr
+ /sbin/dladm init-secobj
+fi
#
# If the system was net booted by DHCP, hand DHCP management off to the
@@ -197,13 +200,15 @@
[ -n "$inet6_failed" ] && warn_failed_ifs "plumb IPv6" $inet6_failed
fi
-#
-# Unfortunately, if a driver unloads and then is subsequently reloaded, no
-# mechanism currently exists to restore the properties of its associated
-# links. Hence, we wait until after interfaces have been plumbed (above)
-# to initialize link properties.
-#
-/sbin/dladm init-linkprop
+if smf_is_globalzone; then
+ #
+ # Unfortunately, if a driver unloads and then is subsequently reloaded,
+ # no mechanism currently exists to restore the properties of its
+ # associated links. Hence, we wait until after interfaces have been
+ # plumbed (above) to initialize link properties.
+ #
+ /sbin/dladm init-linkprop
+fi
#
# Process the /etc/hostname.* files of plumbed IPv4 interfaces. If an
diff --git a/usr/src/cmd/svc/milestone/net-routing-setup b/usr/src/cmd/svc/milestone/net-routing-setup
index 09f5f4e..dbc879e 100644
--- a/usr/src/cmd/svc/milestone/net-routing-setup
+++ b/usr/src/cmd/svc/milestone/net-routing-setup
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -30,11 +30,12 @@
. /lib/svc/share/smf_include.sh
#
-# In a zone we need this service to be up, but all of the work
+# In a shared-IP zone we need this service to be up, but all of the work
# it tries to do is irrelevant (and will actually lead to the service
# failing if we try to do it), so just bail out.
+# In the global zone and exclusive-IP zones we proceed.
#
-smf_is_globalzone || exit $SMF_EXIT_OK
+smf_configure_ip || exit $SMF_EXIT_OK
#
# If routing.conf file is in place, and has not already been read in
diff --git a/usr/src/cmd/svc/milestone/net-svc b/usr/src/cmd/svc/milestone/net-svc
index e71e34c..a91d3d0 100644
--- a/usr/src/cmd/svc/milestone/net-svc
+++ b/usr/src/cmd/svc/milestone/net-svc
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -36,11 +36,12 @@
case "$1" in
'start')
#
- # In a zone we need this service to be up, but all of the work
- # it tries to do is irrelevant (and will actually lead to the service
- # failing if we try to do it), so just bail out.
+ # In a shared-IP zone we need this service to be up, but all of the
+ # work it tries to do is irrelevant (and will actually lead to the
+ # service failing if we try to do it), so just bail out.
+ # In the global zone and exclusive-IP zones we proceed.
#
- smf_is_globalzone || exit 0
+ smf_configure_ip || exit 0
;; # Fall through -- rest of script is the initialization code
'stop')
diff --git a/usr/src/cmd/svc/shell/smf_include.sh b/usr/src/cmd/svc/shell/smf_include.sh
index 066993f..9357c1b 100644
--- a/usr/src/cmd/svc/shell/smf_include.sh
+++ b/usr/src/cmd/svc/shell/smf_include.sh
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -74,6 +74,27 @@
return 1
}
+# smf_configure_ip
+#
+# Returns zero (success) if this zone needs IP to be configured i.e.
+# the global zone or has an exclusive stack. 1 otherwise.
+#
+smf_configure_ip() {
+ [ "${SMF_ZONENAME:=`/sbin/zonename`}" = "global" -o \
+ `/sbin/zonename -t` = exclusive ] && return 0
+ return 1
+}
+
+# smf_dont_configure_ip
+#
+# Inverse of smf_configure_ip
+#
+smf_dont_configure_ip() {
+ [ "${SMF_ZONENAME:=`/sbin/zonename`}" != "global" -a \
+ `/sbin/zonename -t` = shared ] && return 0
+ return 1
+}
+
# smf_is_system_labeled
#
# Returns zero (success) if system is labeled (aka Trusted Extensions).
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
index 8171869..09dec70 100644
--- a/usr/src/cmd/truss/print.c
+++ b/usr/src/cmd/truss/print.c
@@ -2326,6 +2326,7 @@
case ZONE_ATTR_INITNAME: s = "ZONE_ATTR_INITNAME"; break;
case ZONE_ATTR_BOOTARGS: s = "ZONE_ATTR_BOOTARGS"; break;
case ZONE_ATTR_BRAND: s = "ZONE_ATTR_BRAND"; break;
+ case ZONE_ATTR_FLAGS: s = "ZONE_ATTR_FLAGS"; break;
case ZONE_ATTR_PHYS_MCAP: s = "ZONE_ATTR_PHYS_MCAP"; break;
}
}
diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c
index a26004d..e9b8c6a 100644
--- a/usr/src/cmd/truss/systable.c
+++ b/usr/src/cmd/truss/systable.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -797,6 +797,10 @@
{"zone_boot", 2, DEC, NOV, HID, DEC}, /* 7 */
{"zone_version", 2, HEX, NOV, HID, DEC}, /* 8 */
{"zone_setattr", 5, DEC, NOV, HID, DEC, ZGA, HEX, DEC}, /* 9 */
+{"zone_add_datalink", 3, DEC, NOV, HID, DEC, STG}, /* 10 */
+{"zone_remove_datalink", 3, DEC, NOV, HID, DEC, STG}, /* 11 */
+{"zone_check_datalink", 3, DEC, NOV, HID, HEX, STG}, /* 12 */
+{"zone_list_datalink", 4, DEC, NOV, HID, DEC, HEX, HEX}, /* 13 */
};
#define NZONECODE (sizeof (zonetable) / sizeof (struct systable))
@@ -963,6 +967,10 @@
{ "getzoneid", SYS_zone },
{ "zone_list", SYS_zone },
{ "zone_shutdown", SYS_zone },
+ { "zone_add_datalink", SYS_zone },
+ { "zone_remove_datalink", SYS_zone },
+ { "zone_check_datalink", SYS_zone },
+ { "zone_list_datalink", SYS_zone },
{ "is_system_labeled", SYS_labelsys },
{ "tnrh", SYS_labelsys },
{ "tnrhtp", SYS_labelsys },
diff --git a/usr/src/cmd/zoneadm/Makefile b/usr/src/cmd/zoneadm/Makefile
index e11609c..27ced72 100644
--- a/usr/src/cmd/zoneadm/Makefile
+++ b/usr/src/cmd/zoneadm/Makefile
@@ -20,7 +20,7 @@
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -34,7 +34,7 @@
ROOTMANIFESTDIR= $(ROOTSVCSYSTEM)
-OBJS= zoneadm.o sw_cmp.o zfs.o
+OBJS= zoneadm.o sw_cmp.o zfs.o dlprims.o
SRCS = $(OBJS:.o=.c)
POFILE=zoneadm_all.po
POFILES= $(OBJS:%.o=%.po)
diff --git a/usr/src/cmd/zoneadm/dlprims.c b/usr/src/cmd/zoneadm/dlprims.c
new file mode 100644
index 0000000..083e5a0
--- /dev/null
+++ b/usr/src/cmd/zoneadm/dlprims.c
@@ -0,0 +1,273 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* FIXME: from snoop. Use common library when it comes into existence */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/stropts.h>
+#include <sys/signal.h>
+#include <sys/dlpi.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <values.h>
+
+#define DLMAXWAIT (10) /* max wait in seconds for response */
+#define DLMAXBUF (80)
+
+typedef union dlbuf {
+ union DL_primitives dl;
+ char *buf[DLMAXBUF];
+} dlbuf_t;
+
+static int timed_getmsg(int, struct strbuf *, struct strbuf *, int *, int);
+static boolean_t expecting(ulong_t, union DL_primitives *);
+
+/*
+ * Issue DL_INFO_REQ and wait for DL_INFO_ACK.
+ */
+static int
+dlinforeq(int fd, dl_info_ack_t *infoackp)
+{
+ dlbuf_t buf;
+ struct strbuf ctl;
+ int flags;
+
+ buf.dl.info_req.dl_primitive = DL_INFO_REQ;
+
+ ctl.maxlen = sizeof (buf);
+ ctl.len = DL_INFO_REQ_SIZE;
+ ctl.buf = (char *)&buf.dl;
+
+ flags = RS_HIPRI;
+
+ if (putmsg(fd, &ctl, NULL, flags) < 0)
+ return (-1);
+ if (timed_getmsg(fd, &ctl, NULL, &flags, DLMAXWAIT) != 0)
+ return (-1);
+
+ if (!expecting(DL_INFO_ACK, &buf.dl))
+ return (-1);
+
+ if (ctl.len < DL_INFO_ACK_SIZE)
+ return (-1);
+ if (flags != RS_HIPRI)
+ return (-1);
+ if (infoackp != NULL)
+ *infoackp = buf.dl.info_ack;
+ return (0);
+}
+
+/*
+ * Issue DL_ATTACH_REQ.
+ * Return zero on success, nonzero on error.
+ */
+static int
+dlattachreq(int fd, ulong_t ppa)
+{
+ dlbuf_t buf;
+ struct strbuf ctl;
+ int flags;
+
+ buf.dl.attach_req.dl_primitive = DL_ATTACH_REQ;
+ buf.dl.attach_req.dl_ppa = ppa;
+
+ ctl.maxlen = sizeof (buf.dl);
+ ctl.len = DL_ATTACH_REQ_SIZE;
+ ctl.buf = (char *)&buf.dl;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, NULL, flags) < 0)
+ return (-1);
+ if (timed_getmsg(fd, &ctl, NULL, &flags, DLMAXWAIT) != 0)
+ return (-1);
+
+ if (!expecting(DL_OK_ACK, &buf.dl))
+ return (-1);
+ return (0);
+}
+
+static int
+timed_getmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp,
+ int timeout)
+{
+ struct pollfd pfd;
+ int rc;
+
+ pfd.fd = fd;
+
+ pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
+ if ((rc = poll(&pfd, 1, timeout * 1000)) == 0)
+ return (0);
+ else if (rc == -1)
+ return (0);
+
+ /* poll returned > 0 for this fd so getmsg should not block */
+ *flagsp = 0;
+
+ if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0)
+ return (0);
+
+ /*
+ * Check for MOREDATA and/or MORECTL.
+ */
+ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
+ return (-1);
+ if (rc & MORECTL)
+ return (-1);
+ if (rc & MOREDATA)
+ return (-1);
+ /*
+ * Check for at least sizeof (long) control data portion.
+ */
+ if (ctlp->len < sizeof (long))
+ return (-1);
+ return (0);
+}
+
+static boolean_t
+expecting(ulong_t prim, union DL_primitives *dlp)
+{
+ if (dlp->dl_primitive == DL_ERROR_ACK || dlp->dl_primitive != prim)
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+/*
+ * Convert a device id to a ppa value
+ * e.g. "le0" -> 0
+ */
+static int
+device_ppa(char *device)
+{
+ char *p;
+ char *tp;
+
+ p = strpbrk(device, "0123456789");
+ if (p == NULL)
+ return (0);
+ /* ignore numbers within device names */
+ for (tp = p; *tp != '\0'; tp++)
+ if (!isdigit(*tp))
+ return (device_ppa(tp));
+ return (atoi(p));
+}
+
+/*
+ * Convert a device id to a pathname.
+ * DLPI style 1 devices: "le0" -> "/dev/le0".
+ * DLPI style 2 devices: "le0" -> "/dev/le".
+ */
+static char *
+device_path(char *device)
+{
+ static char buff[IF_NAMESIZE + 1];
+ struct stat st;
+ char *p;
+
+ (void) strcpy(buff, "/dev/");
+ (void) strlcat(buff, device, IF_NAMESIZE);
+
+ if (stat(buff, &st) == 0)
+ return (buff);
+
+ for (p = buff + (strlen(buff) - 1); p > buff; p--) {
+ if (isdigit(*p))
+ *p = '\0';
+ else
+ break;
+ }
+ return (buff);
+}
+
+/*
+ * Open up the device, and attach if needed.
+ */
+int
+ifname_open(char *device)
+{
+ char *devname;
+ ulong_t ppa;
+ int netfd;
+ dl_info_ack_t netdl;
+
+ /*
+ * Determine which network device
+ * to use if none given.
+ * Should get back a value like "/dev/le0".
+ */
+
+ devname = device_path(device);
+ if ((netfd = open(devname, O_RDWR)) < 0)
+ return (-1);
+
+ ppa = device_ppa(device);
+
+ /*
+ * Check for DLPI Version 2.
+ */
+ if (dlinforeq(netfd, &netdl) != 0) {
+ (void) close(netfd);
+ return (-1);
+ }
+
+ if (netdl.dl_version != DL_VERSION_2) {
+ (void) close(netfd);
+ return (-1);
+ }
+
+ /*
+ * Attach for DLPI Style 2.
+ */
+ if (netdl.dl_provider_style == DL_STYLE2) {
+ if (dlattachreq(netfd, ppa) != 0) {
+ (void) close(netfd);
+ return (-1);
+ }
+
+ /* Reread more specific information */
+ if (dlinforeq(netfd, &netdl) != 0) {
+ (void) close(netfd);
+ return (-1);
+ }
+ }
+
+ return (netfd);
+}
diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c
index 9da3182..f302cdc 100644
--- a/usr/src/cmd/zoneadm/zoneadm.c
+++ b/usr/src/cmd/zoneadm/zoneadm.c
@@ -95,6 +95,7 @@
char zbrand[MAXNAMELEN];
char zroot[MAXPATHLEN];
char zuuid[UUID_PRINTABLE_STRING_LENGTH];
+ zone_iptype_t ziptype;
} zone_entry_t;
static zone_entry_t *zents;
@@ -142,6 +143,8 @@
static int cleanup_zonepath(char *, boolean_t);
+extern int ifname_open(char *);
+
static int help_func(int argc, char *argv[]);
static int ready_func(int argc, char *argv[]);
static int boot_func(int argc, char *argv[]);
@@ -415,12 +418,19 @@
zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
{
static boolean_t firsttime = B_TRUE;
+ char *ip_type_str;
+
+ if (zent->ziptype == ZS_EXCLUSIVE)
+ ip_type_str = "excl";
+ else
+ ip_type_str = "shared";
assert(!(verbose && parsable));
if (firsttime && verbose) {
firsttime = B_FALSE;
- (void) printf("%*s %-16s %-14s %-30s %-10s\n", ZONEID_WIDTH,
- "ID", "NAME", "STATUS", "PATH", "BRAND");
+ (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
+ ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
+ "IP");
}
if (!verbose) {
char *cp, *clim;
@@ -439,7 +449,8 @@
(void) printf("%.*s\\:", clim - cp, cp);
cp = clim + 1;
}
- (void) printf("%s:%s:%s\n", cp, zent->zuuid, zent->zbrand);
+ (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
+ ip_type_str);
return;
}
if (zent->zstate_str != NULL) {
@@ -447,8 +458,8 @@
(void) printf("%*s", ZONEID_WIDTH, "-");
else
(void) printf("%*lu", ZONEID_WIDTH, zent->zid);
- (void) printf(" %-16s %-14s %-30s %-10s\n", zent->zname,
- zent->zstate_str, zent->zroot, zent->zbrand);
+ (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
+ zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
}
}
@@ -524,6 +535,54 @@
return (Z_ERR);
}
+ /*
+ * Get ip type of the zone.
+ * Note for global zone, ZS_SHARED is set always.
+ */
+ if (zid == GLOBAL_ZONEID) {
+ zent->ziptype = ZS_SHARED;
+ } else {
+
+ if (zent->zstate_num == ZONE_STATE_RUNNING) {
+ ushort_t flags;
+
+ if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
+ sizeof (flags)) < 0) {
+ zperror2(zent->zname,
+ gettext("could not get zone flags"));
+ return (Z_ERR);
+ }
+ if (flags & ZF_NET_EXCL)
+ zent->ziptype = ZS_EXCLUSIVE;
+ else
+ zent->ziptype = ZS_SHARED;
+ } else {
+ zone_dochandle_t handle;
+
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zperror2(zent->zname,
+ gettext("could not init handle"));
+ return (Z_ERR);
+ }
+ if ((err = zonecfg_get_handle(zent->zname, handle))
+ != Z_OK) {
+ zperror2(zent->zname,
+ gettext("could not get handle"));
+ zonecfg_fini_handle(handle);
+ return (Z_ERR);
+ }
+
+ if ((err = zonecfg_get_iptype(handle, &zent->ziptype))
+ != Z_OK) {
+ zperror2(zent->zname,
+ gettext("could not get ip-type"));
+ zonecfg_fini_handle(handle);
+ return (Z_ERR);
+ }
+ zonecfg_fini_handle(handle);
+ }
+ }
+
return (Z_OK);
}
@@ -1542,6 +1601,7 @@
ssize_t result;
uuid_t uuid;
FILE *fp;
+ ushort_t flags;
(void) memset(zeptr, 0, sizeof (*zeptr));
@@ -1575,6 +1635,15 @@
if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
!uuid_is_null(uuid))
uuid_unparse(uuid, zeptr->zuuid);
+
+ if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
+ zperror2(zeptr->zname, gettext("could not get zone flags"));
+ exit(Z_ERR);
+ }
+ if (flags & ZF_NET_EXCL)
+ zeptr->ziptype = ZS_EXCLUSIVE;
+ else
+ zeptr->ziptype = ZS_SHARED;
}
static int
@@ -2739,8 +2808,8 @@
if (!found_af && af != AF_UNSPEC) {
(void) fprintf(stderr,
gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
- "family is not configured on this interface in the\n\t"
- "global zone\n"),
+ "family is not configured on this network interface in "
+ "the\n\tglobal zone\n"),
"net", "address", addr, "physical", phys, af2str(af));
return;
}
@@ -2757,11 +2826,19 @@
int return_code = Z_OK;
int err;
boolean_t in_alt_root;
+ zone_iptype_t iptype;
+ int fd;
in_alt_root = zonecfg_in_alt_root();
if (in_alt_root)
goto no_net;
+ if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
+ errno = err;
+ zperror(cmd_to_str(cmd_num), B_TRUE);
+ zonecfg_fini_handle(handle);
+ return (Z_ERR);
+ }
if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
errno = err;
zperror(cmd_to_str(cmd_num), B_TRUE);
@@ -2771,47 +2848,114 @@
while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
struct lifreq lifr;
sa_family_t af = AF_UNSPEC;
- int so, res;
+ char dl_owner_zname[ZONENAME_MAX];
+ zoneid_t dl_owner_zid;
+ zoneid_t target_zid;
+ int res;
/* skip any loopback interfaces */
if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
continue;
- if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address,
- &lifr)) != Z_OK) {
- print_net_err(nwiftab.zone_nwif_physical,
- nwiftab.zone_nwif_address, af,
- zonecfg_strerror(res));
- return_code = Z_ERR;
- continue;
- }
- af = lifr.lifr_addr.ss_family;
- (void) memset(&lifr, 0, sizeof (lifr));
- (void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical,
- sizeof (lifr.lifr_name));
- lifr.lifr_addr.ss_family = af;
- if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
- (void) fprintf(stderr, gettext("could not verify %s "
- "%s=%s %s=%s: could not get socket: %s\n"), "net",
- "address", nwiftab.zone_nwif_address, "physical",
- nwiftab.zone_nwif_physical, strerror(errno));
- return_code = Z_ERR;
- continue;
- }
- if (ioctl(so, SIOCGLIFFLAGS, &lifr) < 0) {
+ switch (iptype) {
+ case ZS_SHARED:
+ if ((res = zonecfg_valid_net_address(
+ nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
+ print_net_err(nwiftab.zone_nwif_physical,
+ nwiftab.zone_nwif_address, af,
+ zonecfg_strerror(res));
+ return_code = Z_ERR;
+ continue;
+ }
+ af = lifr.lifr_addr.ss_family;
+ if (!zonecfg_ifname_exists(af,
+ nwiftab.zone_nwif_physical)) {
+ /*
+ * The interface failed to come up. We continue
+ * on anyway for the sake of consistency: a
+ * zone is not shut down if the interface fails
+ * any time after boot, nor does the global zone
+ * fail to boot if an interface fails.
+ */
+ (void) fprintf(stderr,
+ gettext("WARNING: skipping network "
+ "interface '%s' which may not be "
+ "present/plumbed in the global "
+ "zone.\n"),
+ nwiftab.zone_nwif_physical);
+ }
+ break;
+ case ZS_EXCLUSIVE:
+ /* Warning if it exists for either IPv4 or IPv6 */
+
+ if (zonecfg_ifname_exists(AF_INET,
+ nwiftab.zone_nwif_physical) ||
+ zonecfg_ifname_exists(AF_INET6,
+ nwiftab.zone_nwif_physical)) {
+ (void) fprintf(stderr,
+ gettext("WARNING: skipping network "
+ "interface '%s' which is used in the "
+ "global zone.\n"),
+ nwiftab.zone_nwif_physical);
+ break;
+ }
/*
- * The interface failed to come up. We continue on
- * anyway for the sake of consistency: a zone is not
- * shut down if the interface fails any time after
- * boot, nor does the global zone fail to boot if an
- * interface fails.
+ * Verify that the physical interface can
+ * be opened
+ */
+ fd = ifname_open(nwiftab.zone_nwif_physical);
+ if (fd == -1) {
+ (void) fprintf(stderr,
+ gettext("WARNING: skipping network "
+ "interface '%s' which cannot be opened.\n"),
+ nwiftab.zone_nwif_physical);
+ break;
+ } else {
+ (void) close(fd);
+ }
+ /*
+ * Verify whether the physical interface is already
+ * used by a zone.
+ */
+ dl_owner_zid = ALL_ZONES;
+ if (zone_check_datalink(&dl_owner_zid,
+ nwiftab.zone_nwif_physical) != 0)
+ break;
+
+ /*
+ * If the zone being verified is
+ * running and owns the interface
+ */
+ target_zid = getzoneidbyname(target_zone);
+ if (target_zid == dl_owner_zid)
+ break;
+
+ /* Zone id match failed, use name to check */
+ if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
+ ZONENAME_MAX) < 0) {
+ /* No name, show ID instead */
+ (void) snprintf(dl_owner_zname, ZONENAME_MAX,
+ "<%d>", dl_owner_zid);
+ } else if (strcmp(dl_owner_zname, target_zone) == 0)
+ break;
+
+ /*
+ * Note here we only report a warning that
+ * the interface is already in use by another
+ * running zone, and the verify process just
+ * goes on, if the interface is still in use
+ * when this zone really boots up, zoneadmd
+ * will find it. If the name of the zone which
+ * owns this interface cannot be determined,
+ * then it is not possible to determine if there
+ * is a conflict so just report it as a warning.
*/
(void) fprintf(stderr,
- gettext("WARNING: skipping interface '%s' which "
- "may not be present/plumbed in the global zone.\n"),
- nwiftab.zone_nwif_physical);
-
+ gettext("WARNING: skipping network interface "
+ "'%s' which is used by the non-global zone "
+ "'%s'.\n"), nwiftab.zone_nwif_physical,
+ dl_owner_zname);
+ break;
}
- (void) close(so);
}
(void) zonecfg_endnwifent(handle);
no_net:
@@ -3440,6 +3584,10 @@
!= NULL)
*p = '\0';
+ /* For exclusive-IP zones, address is not specified. */
+ if (strlen(s_nwiftab.zone_nwif_address) == 0)
+ continue;
+
if (strcmp(t_nwiftab.zone_nwif_address,
s_nwiftab.zone_nwif_address) == 0) {
(void) fprintf(stderr,
diff --git a/usr/src/cmd/zoneadmd/Makefile b/usr/src/cmd/zoneadmd/Makefile
index 3491469..2c3077f 100644
--- a/usr/src/cmd/zoneadmd/Makefile
+++ b/usr/src/cmd/zoneadmd/Makefile
@@ -22,7 +22,7 @@
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -43,7 +43,7 @@
LAZYLIBS = $(ZLAZYLOAD) -ltsnet -ltsol $(ZNOLAZYLOAD)
lint := LAZYLIBS = -ltsnet -ltsol
LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \
- -lgen -lbsm -lcontract -lzfs -luuid -lbrand $(LAZYLIBS)
+ -lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm $(LAZYLIBS)
XGETFLAGS += -a -x zoneadmd.xcl
.KEEP_STATE:
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index d12c3ac..68a8592 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -74,6 +74,10 @@
#include <sys/stropts.h>
#include <sys/conf.h>
+#include <sys/dlpi.h>
+#include <libdlpi.h>
+#include <libdladm.h>
+
#include <inet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -974,6 +978,29 @@
return (di_prof_add_symlink(prof, source, target));
}
+static int
+get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
+{
+ zone_dochandle_t handle;
+
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ if (zonecfg_get_iptype(handle, iptypep) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid ip-type configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ zonecfg_fini_handle(handle);
+ return (0);
+}
+
/*
* Apply the standard lists of devices/symlinks/mappings and the user-specified
* list of devices (via zonecfg) to the /dev filesystem. The filesystem will
@@ -989,6 +1016,8 @@
di_prof_t prof = NULL;
int err;
int retval = -1;
+ zone_iptype_t iptype;
+ const char *curr_iptype;
if (di_prof_init(devpath, &prof)) {
zerror(zlogp, B_TRUE, "failed to initialize profile");
@@ -1002,8 +1031,21 @@
goto cleanup;
}
+ if (get_iptype(zlogp, &iptype) < 0) {
+ zerror(zlogp, B_TRUE, "unable to determine ip-type");
+ goto cleanup;
+ }
+ switch (iptype) {
+ case ZS_SHARED:
+ curr_iptype = "shared";
+ break;
+ case ZS_EXCLUSIVE:
+ curr_iptype = "exclusive";
+ break;
+ }
+
if (brand_platform_iter_devices(bh, zone_name,
- mount_one_dev_device_cb, prof) != 0) {
+ mount_one_dev_device_cb, prof, curr_iptype) != 0) {
zerror(zlogp, B_TRUE, "failed to add standard device");
goto cleanup;
}
@@ -1715,7 +1757,7 @@
* If anything goes wrong, log an error message and return an error.
*/
static int
-unconfigure_network_interfaces(zlog_t *zlogp, zoneid_t zone_id)
+unconfigure_shared_network_interfaces(zlog_t *zlogp, zoneid_t zone_id)
{
struct lifnum lifn;
struct lifconf lifc;
@@ -1734,7 +1776,7 @@
lifn.lifn_flags = (int)lifc_flags;
if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
zerror(zlogp, B_TRUE,
- "could not determine number of interfaces");
+ "could not determine number of network interfaces");
ret_code = -1;
goto bad;
}
@@ -1750,7 +1792,8 @@
lifc.lifc_len = bufsize;
lifc.lifc_buf = buf;
if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
- zerror(zlogp, B_TRUE, "could not get configured interfaces");
+ zerror(zlogp, B_TRUE, "could not get configured network "
+ "interfaces");
ret_code = -1;
goto bad;
}
@@ -1776,14 +1819,14 @@
continue;
zerror(zlogp, B_TRUE,
"%s: could not determine the zone to which this "
- "interface is bound", lifrl.lifr_name);
+ "network interface is bound", lifrl.lifr_name);
ret_code = -1;
continue;
}
if (lifrl.lifr_zoneid == zone_id) {
if (ioctl(s, SIOCLIFREMOVEIF, (caddr_t)&lifrl) < 0) {
zerror(zlogp, B_TRUE,
- "%s: could not remove interface",
+ "%s: could not remove network interface",
lifrl.lifr_name);
ret_code = -1;
continue;
@@ -1927,7 +1970,7 @@
return (NULL);
}
if ((rtmsg.hdr.rtm_addrs & RTA_IFP) == 0) {
- zerror(zlogp, B_FALSE, "interface not found");
+ zerror(zlogp, B_FALSE, "network interface not found");
return (NULL);
}
cp = ((char *)(&rtmsg.hdr + 1));
@@ -1945,7 +1988,8 @@
break;
}
if (ifp == NULL) {
- zerror(zlogp, B_FALSE, "interface could not be determined");
+ zerror(zlogp, B_FALSE, "network interface could not be "
+ "determined");
return (NULL);
}
@@ -1964,8 +2008,8 @@
(void) strlcpy(lifr->lifr_name, save_if_name, sizeof (save_if_name));
if (i < 0) {
zerror(zlogp, B_TRUE,
- "%s: could not determine the zone interface belongs to",
- lifr->lifr_name);
+ "%s: could not determine the zone network interface "
+ "belongs to", lifr->lifr_name);
return (NULL);
}
if (getzonenamebyid(lifr->lifr_zoneid, answer, sizeof (answer)) < 0)
@@ -2061,7 +2105,7 @@
* the console by zoneadm(1M) so instead we log the
* message to syslog and continue.
*/
- zerror(&logsys, B_TRUE, "WARNING: skipping interface "
+ zerror(&logsys, B_TRUE, "WARNING: skipping network interface "
"'%s' which may not be present/plumbed in the "
"global zone.", lifr.lifr_name);
(void) close(s);
@@ -2081,8 +2125,8 @@
lifr.lifr_zoneid = zone_id;
if (ioctl(s, SIOCSLIFZONE, (caddr_t)&lifr) < 0) {
- zerror(zlogp, B_TRUE, "%s: could not place interface into zone",
- lifr.lifr_name);
+ zerror(zlogp, B_TRUE, "%s: could not place network interface "
+ "into zone", lifr.lifr_name);
goto bad;
}
@@ -2180,7 +2224,8 @@
*/
if (errno != EADDRNOTAVAIL) {
zerror(zlogp, B_TRUE,
- "%s: could not bring interface up", lifr.lifr_name);
+ "%s: could not bring network interface up",
+ lifr.lifr_name);
goto bad;
}
if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
@@ -2192,11 +2237,12 @@
errno = save_errno;
if (zone_using == NULL)
zerror(zlogp, B_TRUE,
- "%s: could not bring interface up", lifr.lifr_name);
+ "%s: could not bring network interface up",
+ lifr.lifr_name);
else
- zerror(zlogp, B_TRUE, "%s: could not bring interface "
- "up: address in use by zone '%s'", lifr.lifr_name,
- zone_using);
+ zerror(zlogp, B_TRUE, "%s: could not bring network "
+ "interface up: address in use by zone '%s'",
+ lifr.lifr_name, zone_using);
goto bad;
}
if ((lifr.lifr_flags & IFF_MULTICAST) && ((af == AF_INET &&
@@ -2249,13 +2295,13 @@
*/
if (rlen < mcast_rtmsg.m_rtm.rtm_msglen) {
if (rlen < 0) {
- zerror(zlogp, B_TRUE, "WARNING: interface "
- "'%s' not available as default for "
- "multicast.", lifr.lifr_name);
+ zerror(zlogp, B_TRUE, "WARNING: network "
+ "interface '%s' not available as default "
+ "for multicast.", lifr.lifr_name);
} else {
- zerror(zlogp, B_FALSE, "WARNING: interface "
- "'%s' not available as default for "
- "multicast; routing socket returned "
+ zerror(zlogp, B_FALSE, "WARNING: network "
+ "interface '%s' not available as default "
+ "for multicast; routing socket returned "
"unexpected %d bytes.",
lifr.lifr_name, rlen);
}
@@ -2321,7 +2367,7 @@
* whatever we set up, and return an error.
*/
static int
-configure_network_interfaces(zlog_t *zlogp)
+configure_shared_network_interfaces(zlog_t *zlogp)
{
zone_dochandle_t handle;
struct zone_nwiftab nwiftab, loopback_iftab;
@@ -2383,6 +2429,279 @@
return (0);
}
+static void
+show_owner(zlog_t *zlogp, char *dlname)
+{
+ zoneid_t dl_owner_zid;
+ char dl_owner_zname[ZONENAME_MAX];
+
+ dl_owner_zid = ALL_ZONES;
+ if (zone_check_datalink(&dl_owner_zid, dlname) != 0)
+ (void) snprintf(dl_owner_zname, ZONENAME_MAX, "<unknown>");
+ else if (getzonenamebyid(dl_owner_zid, dl_owner_zname, ZONENAME_MAX)
+ < 0)
+ (void) snprintf(dl_owner_zname, ZONENAME_MAX, "<%d>",
+ dl_owner_zid);
+
+ errno = EPERM;
+ zerror(zlogp, B_TRUE, "WARNING: skipping network interface '%s' "
+ "which is used by the non-global zone '%s'.\n",
+ dlname, dl_owner_zname);
+}
+
+static int
+add_datalink(zlog_t *zlogp, zoneid_t zoneid, char *dlname)
+{
+ /* First check if it's in use by global zone. */
+ if (zonecfg_ifname_exists(AF_INET, dlname) ||
+ zonecfg_ifname_exists(AF_INET6, dlname)) {
+ errno = EPERM;
+ zerror(zlogp, B_TRUE, "WARNING: skipping network interface "
+ "'%s' which is used in the global zone.", dlname);
+ return (-1);
+ }
+
+ /* Add access control information */
+ if (zone_add_datalink(zoneid, dlname) != 0) {
+ /* If someone got this link before us, show its name */
+ if (errno == EPERM)
+ show_owner(zlogp, dlname);
+ else
+ zerror(zlogp, B_TRUE, "WARNING: unable to add network "
+ "interface '%s'.", dlname);
+ return (-1);
+ }
+
+ /* Hold the link for this zone */
+ if (dladm_hold_link(dlname, zoneid, B_FALSE) < 0) {
+ zerror(zlogp, B_TRUE, "WARNING: unable to hold network "
+ "interface '%s'.", dlname);
+ (void) zone_remove_datalink(zoneid, dlname);
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+remove_datalink(zlog_t *zlogp, zoneid_t zoneid, char *dlname)
+{
+ /*
+ * Remove access control information.
+ * If the errno is ENXIO, the interface is not added yet,
+ * nothing to report then.
+ */
+ if (zone_remove_datalink(zoneid, dlname) != 0) {
+ if (errno == ENXIO)
+ return (0);
+ zerror(zlogp, B_TRUE, "unable to remove network interface '%s'",
+ dlname);
+ return (-1);
+ }
+
+ if (dladm_rele_link(dlname, 0, B_FALSE) < 0) {
+ zerror(zlogp, B_TRUE, "unable to release network "
+ "interface '%s'", dlname);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Add the kernel access control information for the interface names.
+ * If anything goes wrong, we log a general error message, attempt to tear down
+ * whatever we set up, and return an error.
+ */
+static int
+configure_exclusive_network_interfaces(zlog_t *zlogp)
+{
+ zone_dochandle_t handle;
+ struct zone_nwiftab nwiftab;
+ zoneid_t zoneid;
+ char rootpath[MAXPATHLEN];
+ char path[MAXPATHLEN];
+ di_prof_t prof = NULL;
+ boolean_t added = B_FALSE;
+
+ if ((zoneid = getzoneidbyname(zone_name)) == -1) {
+ zerror(zlogp, B_TRUE, "unable to get zoneid");
+ return (-1);
+ }
+
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
+ if (zonecfg_setnwifent(handle) != Z_OK) {
+ zonecfg_fini_handle(handle);
+ return (0);
+ }
+
+ for (;;) {
+ if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
+ break;
+
+ if (prof == NULL) {
+ if (zone_get_devroot(zone_name, rootpath,
+ sizeof (rootpath)) != Z_OK) {
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ zerror(zlogp, B_TRUE,
+ "unable to determine dev root");
+ return (-1);
+ }
+ (void) snprintf(path, sizeof (path), "%s%s", rootpath,
+ "/dev");
+ if (di_prof_init(path, &prof) != 0) {
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ zerror(zlogp, B_TRUE,
+ "failed to initialize profile");
+ return (-1);
+ }
+ }
+
+ /*
+ * Only create the /dev entry if it's not in use.
+ * Note here the zone still boots when the interfaces
+ * assigned is inaccessible, used by others, etc.
+ */
+ if (add_datalink(zlogp, zoneid, nwiftab.zone_nwif_physical)
+ == 0) {
+ if (di_prof_add_dev(prof, nwiftab.zone_nwif_physical)
+ != 0) {
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ zerror(zlogp, B_TRUE,
+ "failed to add network device");
+ return (-1);
+ }
+ added = B_TRUE;
+ }
+ }
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+
+ if (prof != NULL && added) {
+ if (di_prof_commit(prof) != 0) {
+ zerror(zlogp, B_TRUE, "failed to commit profile");
+ return (-1);
+ }
+ }
+ if (prof != NULL)
+ di_prof_fini(prof);
+
+ return (0);
+}
+
+/*
+ * Get the list of the data-links from kernel, and try to remove it
+ */
+static int
+unconfigure_exclusive_network_interfaces_run(zlog_t *zlogp, zoneid_t zoneid)
+{
+ char *dlnames, *ptr;
+ int dlnum, dlnum_saved, i;
+
+ dlnum = 0;
+ if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
+ zerror(zlogp, B_TRUE, "unable to list network interfaces");
+ return (-1);
+ }
+again:
+ /* this zone doesn't have any data-links */
+ if (dlnum == 0)
+ return (0);
+
+ dlnames = malloc(dlnum * LIFNAMSIZ);
+ if (dlnames == NULL) {
+ zerror(zlogp, B_TRUE, "memory allocation failed");
+ return (-1);
+ }
+ dlnum_saved = dlnum;
+
+ if (zone_list_datalink(zoneid, &dlnum, dlnames) != 0) {
+ zerror(zlogp, B_TRUE, "unable to list network interfaces");
+ free(dlnames);
+ return (-1);
+ }
+ if (dlnum_saved < dlnum) {
+ /* list increased, try again */
+ free(dlnames);
+ goto again;
+ }
+ ptr = dlnames;
+ for (i = 0; i < dlnum; i++) {
+ /* Remove access control information */
+ if (remove_datalink(zlogp, zoneid, ptr) != 0) {
+ free(dlnames);
+ return (-1);
+ }
+ ptr += LIFNAMSIZ;
+ }
+ free(dlnames);
+ return (0);
+}
+
+/*
+ * Get the list of the data-links from configuration, and try to remove it
+ */
+static int
+unconfigure_exclusive_network_interfaces_static(zlog_t *zlogp, zoneid_t zoneid)
+{
+ zone_dochandle_t handle;
+ struct zone_nwiftab nwiftab;
+
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ if (zonecfg_setnwifent(handle) != Z_OK) {
+ zonecfg_fini_handle(handle);
+ return (0);
+ }
+ for (;;) {
+ if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
+ break;
+ /* Remove access control information */
+ if (remove_datalink(zlogp, zoneid, nwiftab.zone_nwif_physical)
+ != 0) {
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ }
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ return (0);
+}
+
+/*
+ * Remove the access control information from the kernel for the exclusive
+ * network interfaces.
+ */
+static int
+unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
+{
+ if (unconfigure_exclusive_network_interfaces_run(zlogp, zoneid) != 0) {
+ return (unconfigure_exclusive_network_interfaces_static(zlogp,
+ zoneid));
+ }
+
+ return (0);
+}
+
static int
tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
@@ -3562,6 +3881,8 @@
tsol_zcent_t *zcent = NULL;
int match = 0;
int doi = 0;
+ int flags;
+ zone_iptype_t iptype;
if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine zone root");
@@ -3570,11 +3891,35 @@
if (zonecfg_in_alt_root())
resolve_lofs(zlogp, rootpath, sizeof (rootpath));
+ if (get_iptype(zlogp, &iptype) < 0) {
+ zerror(zlogp, B_TRUE, "unable to determine ip-type");
+ return (-1);
+ }
+ switch (iptype) {
+ case ZS_SHARED:
+ flags = 0;
+ break;
+ case ZS_EXCLUSIVE:
+ flags = ZCF_NET_EXCL;
+ break;
+ }
+
if ((privs = priv_allocset()) == NULL) {
zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
return (-1);
}
priv_emptyset(privs);
+ if (iptype == ZS_EXCLUSIVE) {
+ /*
+ * add PRIV_NET_RAWACCESS and PRIV_SYS_IP_CONFIG
+ */
+ if (priv_addset(privs, PRIV_NET_RAWACCESS) != 0 ||
+ priv_addset(privs, PRIV_SYS_IP_CONFIG) != 0) {
+ zerror(zlogp, B_TRUE,
+ "Failed to add networking privileges");
+ goto error;
+ }
+ }
if (get_privset(zlogp, privs, mount_cmd) != 0)
goto error;
@@ -3669,7 +4014,8 @@
xerr = 0;
if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
- rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel)) == -1) {
+ rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
+ flags)) == -1) {
if (xerr == ZE_AREMOUNTS) {
if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
zerror(zlogp, B_FALSE,
@@ -3863,9 +4209,31 @@
return (-1);
}
- if (!mount_cmd && configure_network_interfaces(zlogp) != 0) {
- lofs_discard_mnttab();
- return (-1);
+ if (!mount_cmd) {
+ zone_iptype_t iptype;
+
+ if (get_iptype(zlogp, &iptype) < 0) {
+ zerror(zlogp, B_TRUE, "unable to determine ip-type");
+ lofs_discard_mnttab();
+ return (-1);
+ }
+
+ switch (iptype) {
+ case ZS_SHARED:
+ /* Always do this to make lo0 get configured */
+ if (configure_shared_network_interfaces(zlogp) != 0) {
+ lofs_discard_mnttab();
+ return (-1);
+ }
+ break;
+ case ZS_EXCLUSIVE:
+ if (configure_exclusive_network_interfaces(zlogp) !=
+ 0) {
+ lofs_discard_mnttab();
+ return (-1);
+ }
+ break;
+ }
}
write_index_file(zoneid);
@@ -3952,6 +4320,7 @@
char cmdbuf[MAXPATHLEN];
char brand[MAXNAMELEN];
brand_handle_t bh = NULL;
+ ushort_t flags;
kzone = zone_name;
if (zonecfg_in_alt_root()) {
@@ -4016,11 +4385,41 @@
goto error;
}
- if (!unmount_cmd &&
- unconfigure_network_interfaces(zlogp, zoneid) != 0) {
- zerror(zlogp, B_FALSE,
- "unable to unconfigure network interfaces in zone");
- goto error;
+ if (!unmount_cmd) {
+ zone_iptype_t iptype;
+
+ if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
+ sizeof (flags)) < 0) {
+ if (get_iptype(zlogp, &iptype) < 0) {
+ zerror(zlogp, B_TRUE, "unable to determine "
+ "ip-type");
+ goto error;
+ }
+ } else {
+ if (flags & ZF_NET_EXCL)
+ iptype = ZS_EXCLUSIVE;
+ else
+ iptype = ZS_SHARED;
+ }
+
+ switch (iptype) {
+ case ZS_SHARED:
+ if (unconfigure_shared_network_interfaces(zlogp,
+ zoneid) != 0) {
+ zerror(zlogp, B_FALSE, "unable to unconfigure "
+ "network interfaces in zone");
+ goto error;
+ }
+ break;
+ case ZS_EXCLUSIVE:
+ if (unconfigure_exclusive_network_interfaces(zlogp,
+ zoneid) != 0) {
+ zerror(zlogp, B_FALSE, "unable to unconfigure "
+ "network interfaces in zone");
+ goto error;
+ }
+ break;
+ }
}
if (!unmount_cmd && tcp_abort_connections(zlogp, zoneid) != 0) {
diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c
index 34d6b99..443c089 100644
--- a/usr/src/cmd/zonecfg/zonecfg.c
+++ b/usr/src/cmd/zonecfg/zonecfg.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -178,6 +178,7 @@
ALIAS_MAXSEMIDS,
ALIAS_SHARES,
"scheduling-class",
+ "ip-type",
NULL
};
@@ -217,6 +218,7 @@
ALIAS_MAXLOCKEDMEM,
ALIAS_MAXSWAP,
"scheduling-class",
+ "ip-type",
NULL
};
@@ -273,6 +275,7 @@
"clear limitpriv",
"clear bootargs",
"clear scheduling-class",
+ "clear ip-type",
"clear " ALIAS_MAXLWPS,
"clear " ALIAS_MAXSHMMEM,
"clear " ALIAS_MAXSHMIDS,
@@ -317,6 +320,7 @@
"set limitpriv=",
"set bootargs=",
"set scheduling-class=",
+ "set ip-type=",
"set " ALIAS_MAXLWPS "=",
"set " ALIAS_MAXSHMMEM "=",
"set " ALIAS_MAXSHMIDS "=",
@@ -344,6 +348,7 @@
"info bootargs",
"info brand",
"info scheduling-class",
+ "info ip-type",
"info max-lwps",
"info max-shm-memory",
"info max-shm-ids",
@@ -914,6 +919,11 @@
pt_to_str(PT_PHYSICAL), gettext("<interface>"));
(void) fprintf(fp, gettext("See ifconfig(1M) for "
"details of the <interface> string.\n"));
+ (void) fprintf(fp, gettext("%s %s is valid if the %s "
+ "property is set to %s, otherwise it must not be "
+ "set.\n"),
+ cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
+ pt_to_str(PT_IPTYPE), "shared");
break;
case RT_DEVICE:
(void) fprintf(fp, gettext("The '%s' resource scope is "
@@ -1095,6 +1105,8 @@
(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
pt_to_str(PT_SCHED));
(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
+ pt_to_str(PT_IPTYPE));
+ (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
pt_to_str(PT_MAXLWPS));
(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
pt_to_str(PT_MAXSHMMEM));
@@ -1571,6 +1583,7 @@
char *limitpriv;
FILE *of;
boolean_t autoboot;
+ zone_iptype_t iptype;
bool need_to_close = FALSE;
assert(cmd != NULL);
@@ -1651,6 +1664,19 @@
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_SCHED), sched);
+ if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
+ switch (iptype) {
+ case ZS_SHARED:
+ (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
+ pt_to_str(PT_IPTYPE), "shared");
+ break;
+ case ZS_EXCLUSIVE:
+ (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
+ pt_to_str(PT_IPTYPE), "exclusive");
+ break;
+ }
+ }
+
if ((err = zonecfg_setipdent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
@@ -2157,7 +2183,8 @@
{
return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
- type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED));
+ type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
+ type == RT_IPTYPE));
}
static boolean_t
@@ -2165,7 +2192,8 @@
{
return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
- type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED));
+ type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
+ type == PT_IPTYPE));
}
void
@@ -3268,6 +3296,13 @@
else
need_to_commit = TRUE;
return;
+ case PT_IPTYPE:
+ /* shared is default; we'll treat as equivalent to clearing */
+ if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
+ z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, TRUE);
+ else
+ need_to_commit = TRUE;
+ return;
case PT_MAXLWPS:
remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
return;
@@ -3555,6 +3590,30 @@
return (B_TRUE);
}
+static boolean_t
+allow_exclusive()
+{
+ brand_handle_t bh;
+ char brand[MAXNAMELEN];
+ boolean_t ret;
+
+ if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
+ zerr("%s: %s\n", zone, gettext("could not get zone brand"));
+ return (B_FALSE);
+ }
+ if ((bh = brand_open(brand)) == NULL) {
+ zerr("%s: %s\n", zone, gettext("unknown brand."));
+ return (B_FALSE);
+ }
+ ret = brand_allow_exclusive_ip(bh);
+ brand_close(bh);
+ if (!ret)
+ zerr(gettext("%s cannot be '%s' when %s is '%s'."),
+ pt_to_str(PT_IPTYPE), "exclusive",
+ pt_to_str(PT_BRAND), brand);
+ return (ret);
+}
+
static void
set_aliased_rctl(char *alias, int prop_type, char *s)
{
@@ -3605,6 +3664,7 @@
int arg, err, res_type, prop_type;
property_value_ptr_t pp;
boolean_t autoboot;
+ zone_iptype_t iptype;
boolean_t force_set = FALSE;
size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
uint64_t mem_cap, mem_limit;
@@ -3655,6 +3715,8 @@
res_type = RT_BOOTARGS;
} else if (prop_type == PT_SCHED) {
res_type = RT_SCHED;
+ } else if (prop_type == PT_IPTYPE) {
+ res_type = RT_IPTYPE;
} else if (prop_type == PT_MAXLWPS) {
res_type = RT_MAXLWPS;
} else if (prop_type == PT_MAXSHMMEM) {
@@ -3831,6 +3893,26 @@
else
need_to_commit = TRUE;
return;
+ case RT_IPTYPE:
+ if (strcmp(prop_id, "shared") == 0) {
+ iptype = ZS_SHARED;
+ } else if (strcmp(prop_id, "exclusive") == 0) {
+ iptype = ZS_EXCLUSIVE;
+ } else {
+ zerr(gettext("%s value must be '%s' or '%s'."),
+ pt_to_str(PT_IPTYPE), "shared", "exclusive");
+ saw_error = TRUE;
+ return;
+ }
+ if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
+ saw_error = TRUE;
+ return;
+ }
+ if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
+ zone_perror(zone, err, TRUE);
+ else
+ need_to_commit = TRUE;
+ return;
case RT_MAXLWPS:
set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
return;
@@ -4304,6 +4386,28 @@
}
static void
+info_iptype(zone_dochandle_t handle, FILE *fp)
+{
+ zone_iptype_t iptype;
+ int err;
+
+ if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
+ switch (iptype) {
+ case ZS_SHARED:
+ (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
+ "shared");
+ break;
+ case ZS_EXCLUSIVE:
+ (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
+ "exclusive");
+ break;
+ }
+ } else {
+ zone_perror(zone, err, TRUE);
+ }
+}
+
+static void
output_fs(FILE *fp, struct zone_fstab *fstab)
{
zone_fsopt_t *this;
@@ -4430,6 +4534,7 @@
strcmp(user.zone_nwif_physical,
lookup.zone_nwif_physical) != 0)
continue; /* no match */
+ /* If present make sure it matches */
if (strlen(user.zone_nwif_address) > 0 &&
!zonecfg_same_net_address(user.zone_nwif_address,
lookup.zone_nwif_address))
@@ -4822,6 +4927,7 @@
if (!global_zone) {
info_limitpriv(handle, fp);
info_sched(handle, fp);
+ info_iptype(handle, fp);
}
info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
@@ -4867,6 +4973,9 @@
case RT_SCHED:
info_sched(handle, fp);
break;
+ case RT_IPTYPE:
+ info_iptype(handle, fp);
+ break;
case RT_MAXLWPS:
info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
break;
@@ -5051,6 +5160,7 @@
char brand[MAXNAMELEN];
int err, ret_val = Z_OK, arg;
bool save = FALSE;
+ zone_iptype_t iptype;
boolean_t has_cpu_shares = B_FALSE;
optind = 0;
@@ -5102,6 +5212,11 @@
}
}
+ if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
+ zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
+ ret_val = Z_REQD_RESOURCE_MISSING;
+ saw_error = TRUE;
+ }
if ((err = zonecfg_setipdent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
@@ -5130,10 +5245,30 @@
return;
}
while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
- check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
- PT_ADDRESS, &ret_val);
+ /*
+ * physical is required in all cases.
+ * A shared IP requires an address, while
+ * an exclusive IP must not have an address.
+ */
check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
PT_PHYSICAL, &ret_val);
+
+ switch (iptype) {
+ case ZS_SHARED:
+ check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
+ PT_ADDRESS, &ret_val);
+ break;
+ case ZS_EXCLUSIVE:
+ if (strlen(nwiftab.zone_nwif_address) > 0) {
+ zerr(gettext("%s: %s cannot be specified "
+ "for an exclusive IP type"),
+ rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
+ saw_error = TRUE;
+ if (ret_val == Z_OK)
+ ret_val = Z_INVAL;
+ }
+ break;
+ }
}
(void) zonecfg_endnwifent(handle);
@@ -5492,27 +5627,35 @@
}
break;
case RT_NET:
- /* First make sure everything was filled in. */
+ /*
+ * First make sure everything was filled in.
+ * Since we don't know whether IP will be shared
+ * or exclusive here, some checks are deferred until
+ * the verify command.
+ */
(void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
PT_PHYSICAL, &validation_failed);
- (void) end_check_reqd(in_progress_nwiftab.zone_nwif_address,
- PT_ADDRESS, &validation_failed);
if (validation_failed) {
saw_error = TRUE;
return;
}
-
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
+ (void) strlcpy(tmp_nwiftab.zone_nwif_physical,
+ in_progress_nwiftab.zone_nwif_physical,
+ sizeof (tmp_nwiftab.zone_nwif_physical));
(void) strlcpy(tmp_nwiftab.zone_nwif_address,
in_progress_nwiftab.zone_nwif_address,
sizeof (tmp_nwiftab.zone_nwif_address));
if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
- zerr(gettext("A %s resource "
- "with the %s '%s' already exists."),
- rt_to_str(RT_NET), pt_to_str(PT_ADDRESS),
+ zerr(gettext("A %s resource with the %s '%s', "
+ "and %s '%s' already exists."),
+ rt_to_str(RT_NET),
+ pt_to_str(PT_PHYSICAL),
+ in_progress_nwiftab.zone_nwif_physical,
+ pt_to_str(PT_ADDRESS),
in_progress_nwiftab.zone_nwif_address);
saw_error = TRUE;
return;
diff --git a/usr/src/cmd/zonecfg/zonecfg.h b/usr/src/cmd/zonecfg/zonecfg.h
index 64808e9..4f960b5 100644
--- a/usr/src/cmd/zonecfg/zonecfg.h
+++ b/usr/src/cmd/zonecfg/zonecfg.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -93,9 +93,10 @@
#define RT_MAXSEMIDS 21 /* really a rctl alias property, but for info */
#define RT_SHARES 22 /* really a rctl alias property, but for info */
#define RT_SCHED 23 /* really a property, but for info ... */
+#define RT_IPTYPE 24 /* really a property, but for info ... */
#define RT_MIN RT_UNKNOWN
-#define RT_MAX RT_SCHED
+#define RT_MAX RT_IPTYPE
/* property types: increment PT_MAX when expanding this list */
#define PT_UNKNOWN 0
@@ -132,9 +133,10 @@
#define PT_MAXLOCKEDMEM 31
#define PT_MAXSWAP 32
#define PT_SCHED 33
+#define PT_IPTYPE 34
#define PT_MIN PT_UNKNOWN
-#define PT_MAX PT_SCHED
+#define PT_MAX PT_IPTYPE
#define MAX_EQ_PROP_PAIRS 3
diff --git a/usr/src/cmd/zonecfg/zonecfg_grammar.y b/usr/src/cmd/zonecfg/zonecfg_grammar.y
index 5c0dc22..7ee9b4d 100644
--- a/usr/src/cmd/zonecfg/zonecfg_grammar.y
+++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y
@@ -21,7 +21,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,6 +59,7 @@
%token HELP CREATE EXPORT ADD DELETE REMOVE SELECT SET INFO CANCEL END VERIFY
%token COMMIT REVERT EXIT SEMICOLON TOKEN ZONENAME ZONEPATH AUTOBOOT POOL NET
%token FS IPD ATTR DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL
+%token IPTYPE
%token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
%token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET
%token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS
@@ -70,7 +71,7 @@
%type <ival> resource_type NET FS IPD DEVICE RCTL ATTR DATASET PSET MCAP
%type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT
- ACTION BRAND SCHED
+ ACTION BRAND SCHED IPTYPE
%type <cmd> command
%type <cmd> add_command ADD
%type <cmd> cancel_command CANCEL
@@ -442,6 +443,15 @@
$$->cmd_res_type = RT_AUTOBOOT;
$$->cmd_prop_nv_pairs = 0;
}
+ | INFO IPTYPE
+ {
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ cmd = $$;
+ $$->cmd_handler = &info_func;
+ $$->cmd_res_type = RT_IPTYPE;
+ $$->cmd_prop_nv_pairs = 0;
+ }
| INFO POOL
{
if (($$ = alloc_cmd()) == NULL)
@@ -840,6 +850,7 @@
| ZONENAME { $$ = PT_ZONENAME; }
| ZONEPATH { $$ = PT_ZONEPATH; }
| AUTOBOOT { $$ = PT_AUTOBOOT; }
+ | IPTYPE { $$ = PT_IPTYPE; }
| POOL { $$ = PT_POOL; }
| LIMITPRIV { $$ = PT_LIMITPRIV; }
| BOOTARGS { $$ = PT_BOOTARGS; }
diff --git a/usr/src/cmd/zonecfg/zonecfg_lex.l b/usr/src/cmd/zonecfg/zonecfg_lex.l
index 53f726c..81a0594 100644
--- a/usr/src/cmd/zonecfg/zonecfg_lex.l
+++ b/usr/src/cmd/zonecfg/zonecfg_lex.l
@@ -21,7 +21,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -184,6 +184,9 @@
<TSTATE>autoboot { return AUTOBOOT; }
<CSTATE>autoboot { return AUTOBOOT; }
+<TSTATE>ip-type { return IPTYPE; }
+<CSTATE>ip-type { return IPTYPE; }
+
<TSTATE>pool { return POOL; }
<CSTATE>pool { return POOL; }
diff --git a/usr/src/cmd/zonename/zonename.c b/usr/src/cmd/zonename/zonename.c
index 3a3a5df..2ab2f1f 100644
--- a/usr/src/cmd/zonename/zonename.c
+++ b/usr/src/cmd/zonename/zonename.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,21 +32,54 @@
#include <zone.h>
#include <libzonecfg.h>
#include <dlfcn.h>
+#include <sys/zone.h>
#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
#endif
+/*
+ * -t prints "shared" vs. "exclusive"
+ */
int
-main(void)
+main(int argc, char *argv[])
{
+ zoneid_t zoneid;
char zonename[ZONENAME_MAX];
FILE *fp;
+ int arg;
+ boolean_t stacktype = B_FALSE;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
- if (getzonenamebyid(getzoneid(), zonename, sizeof (zonename)) < 0) {
+ opterr = 0;
+ while ((arg = getopt(argc, argv, "t")) != EOF) {
+ switch (arg) {
+ case 't':
+ stacktype = B_TRUE;
+ break;
+ }
+ }
+
+ zoneid = getzoneid();
+
+ if (stacktype) {
+ ushort_t flags;
+
+ if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
+ sizeof (flags)) < 0) {
+ perror("could not determine zone IP type");
+ exit(1);
+ }
+ if (flags & ZF_NET_EXCL)
+ (void) puts("exclusive");
+ else
+ (void) puts("shared");
+ return (0);
+ }
+
+ if (getzonenamebyid(zoneid, zonename, sizeof (zonename)) < 0) {
(void) fputs(gettext("could not determine zone name\n"),
stderr);
return (1);
diff --git a/usr/src/common/net/patricia/radix.c b/usr/src/common/net/patricia/radix.c
index ec8bdf5..a61cbaa 100644
--- a/usr/src/common/net/patricia/radix.c
+++ b/usr/src/common/net/patricia/radix.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1988, 1989, 1993
@@ -1221,6 +1221,7 @@
rnh->rnh_walktree = NULL;
#ifdef _KERNEL
+ RADIX_NODE_HEAD_DESTROY(rnh);
FreeHead(rnh, sizeof (*rnh));
#else
Free(rnh, NULL);
diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h
index 10ee4a2..8272817 100644
--- a/usr/src/head/libzonecfg.h
+++ b/usr/src/head/libzonecfg.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -238,6 +238,11 @@
char *zone_devperm_acl;
};
+typedef enum zone_iptype {
+ ZS_SHARED,
+ ZS_EXCLUSIVE
+} zone_iptype_t;
+
/*
* Basic configuration management routines.
*/
@@ -277,6 +282,8 @@
extern int zonecfg_set_zonepath(zone_dochandle_t, char *);
extern int zonecfg_get_autoboot(zone_dochandle_t, boolean_t *);
extern int zonecfg_set_autoboot(zone_dochandle_t, boolean_t);
+extern int zonecfg_get_iptype(zone_dochandle_t, zone_iptype_t *);
+extern int zonecfg_set_iptype(zone_dochandle_t, zone_iptype_t);
extern int zonecfg_get_pool(zone_dochandle_t, char *, size_t);
extern int zonecfg_set_pool(zone_dochandle_t, char *);
extern int zonecfg_get_bootargs(zone_dochandle_t, char *, size_t);
@@ -500,6 +507,7 @@
*/
extern boolean_t zonecfg_same_net_address(char *, char *);
extern int zonecfg_valid_net_address(char *, struct lifreq *);
+extern boolean_t zonecfg_ifname_exists(sa_family_t, char *);
/*
* Rctl-related common functions.
diff --git a/usr/src/head/zone.h b/usr/src/head/zone.h
index 5250aab..c4077c0 100644
--- a/usr/src/head/zone.h
+++ b/usr/src/head/zone.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -58,7 +58,7 @@
/* System call API */
extern zoneid_t zone_create(const char *, const char *,
const struct priv_set *, const char *, size_t, const char *, size_t, int *,
- int, int, const bslabel_t *);
+ int, int, const bslabel_t *, int);
extern int zone_boot(zoneid_t);
extern int zone_destroy(zoneid_t);
extern ssize_t zone_getattr(zoneid_t, int, void *, size_t);
@@ -67,6 +67,10 @@
extern int zone_list(zoneid_t *, uint_t *);
extern int zone_shutdown(zoneid_t);
extern int zone_version(int *);
+extern int zone_add_datalink(zoneid_t, char *);
+extern int zone_remove_datalink(zoneid_t, char *);
+extern int zone_check_datalink(zoneid_t *, char *);
+extern int zone_list_datalink(zoneid_t, int *, char *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/brand/lx/lx_support/lx_support.c b/usr/src/lib/brand/lx/lx_support/lx_support.c
index ab2fcdb..714fc38 100644
--- a/usr/src/lib/brand/lx/lx_support/lx_support.c
+++ b/usr/src/lib/brand/lx/lx_support/lx_support.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -420,6 +420,7 @@
struct zone_devtab devtab;
boolean_t audio, restart;
char *idev, *odev;
+ zone_iptype_t iptype;
if ((handle = zonecfg_init_handle()) == NULL)
lxs_err(gettext("internal libzonecfg.so.1 error"), 0);
@@ -469,6 +470,20 @@
lxs_err(gettext("lx zones do not support added devices"));
}
+ /*
+ * Check to see whether the zone has ip-type configured as exclusive
+ */
+ if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
+ zonecfg_fini_handle(handle);
+ lxs_err(gettext("zonecfg provided an invalid XML file"));
+ }
+
+ if (iptype == ZS_EXCLUSIVE) {
+ zonecfg_fini_handle(handle);
+ lxs_err(gettext("lx zones do not support an 'exclusive' "
+ "ip-type"));
+ }
+
/* Extract any relevant attributes from the config file. */
lxs_getattrs(handle, &restart, &audio, &idev, &odev);
zonecfg_fini_handle(handle);
diff --git a/usr/src/lib/brand/lx/zone/platform.xml b/usr/src/lib/brand/lx/zone/platform.xml
index 85e763f..a53f0ee 100644
--- a/usr/src/lib/brand/lx/zone/platform.xml
+++ b/usr/src/lib/brand/lx/zone/platform.xml
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
@@ -31,7 +31,7 @@
<!DOCTYPE platform PUBLIC "-//Sun Microsystems Inc//Zones Platform//EN"
"file:///usr/share/lib/xml/dtd/zone_platform.dtd.1">
-<platform name="lx">
+<platform name="lx" allow-exclusive-ip="false">
<!-- Global filesystems to mount when booting the zone -->
<global_mount special="/dev" directory="/native/dev" type="dev"
opt="attrdir=%R/dev" />
diff --git a/usr/src/lib/brand/native/zone/platform.xml b/usr/src/lib/brand/native/zone/platform.xml
index d2bbc83..0919348 100644
--- a/usr/src/lib/brand/native/zone/platform.xml
+++ b/usr/src/lib/brand/native/zone/platform.xml
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
@@ -31,7 +31,7 @@
<!DOCTYPE platform PUBLIC "-//Sun Microsystems Inc//Zones Platform//EN"
"file:///usr/share/lib/xml/dtd/zone_platform.dtd.1">
-<platform name="native">
+<platform name="native" allow-exclusive-ip="true">
<!-- Global filesystems to mount when booting the zone -->
<global_mount special="/dev" directory="/dev" type="dev"
@@ -86,6 +86,29 @@
<device match="zero" />
<device match="zfs" />
+ <!-- Devices to create in exclusive IP zone only -->
+ <device match="icmp" ip-type="exclusive" />
+ <device match="icmp6" ip-type="exclusive" />
+ <device match="ip" ip-type="exclusive" />
+ <device match="ip6" ip-type="exclusive" />
+ <device match="ipauth" ip-type="exclusive" />
+ <device match="ipf" ip-type="exclusive" />
+ <device match="ipl" ip-type="exclusive" />
+ <device match="iplookup" ip-type="exclusive" />
+ <device match="ipnat" ip-type="exclusive" />
+ <device match="ipscan" ip-type="exclusive" />
+ <device match="ipsecah" ip-type="exclusive" />
+ <device match="ipsecesp" ip-type="exclusive" />
+ <device match="ipstate" ip-type="exclusive" />
+ <device match="ipsync" ip-type="exclusive" />
+ <device match="keysock" ip-type="exclusive" />
+ <device match="rawip" ip-type="exclusive" />
+ <device match="rawip6" ip-type="exclusive" />
+ <device match="rts" ip-type="exclusive" />
+ <device match="sctp" ip-type="exclusive" />
+ <device match="sctp6" ip-type="exclusive" />
+ <device match="spdsock" ip-type="exclusive" />
+
<!-- Renamed devices to create under /dev -->
<device match="zcons/%z/zoneconsole" name="zconsole" />
diff --git a/usr/src/lib/brand/sn1/zone/platform.xml b/usr/src/lib/brand/sn1/zone/platform.xml
index 01b0348..326f2e2 100644
--- a/usr/src/lib/brand/sn1/zone/platform.xml
+++ b/usr/src/lib/brand/sn1/zone/platform.xml
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
@@ -31,7 +31,7 @@
<!DOCTYPE platform PUBLIC "-//Sun Microsystems Inc//Zones Platform//EN"
"file:///usr/share/lib/xml/dtd/zone_platform.dtd.1">
-<platform name="native">
+<platform name="native" allow-exclusive-ip="true">
<!-- Global filesystems to mount when booting the zone -->
<global_mount special="/dev" directory="/dev" type="dev"
@@ -86,6 +86,29 @@
<device match="zero" />
<device match="zfs" />
+ <!-- Devices to create in exclusive IP zone only -->
+ <device match="icmp" ip-type="exclusive" />
+ <device match="icmp6" ip-type="exclusive" />
+ <device match="ip" ip-type="exclusive" />
+ <device match="ip6" ip-type="exclusive" />
+ <device match="ipauth" ip-type="exclusive" />
+ <device match="ipf" ip-type="exclusive" />
+ <device match="ipl" ip-type="exclusive" />
+ <device match="iplookup" ip-type="exclusive" />
+ <device match="ipnat" ip-type="exclusive" />
+ <device match="ipscan" ip-type="exclusive" />
+ <device match="ipsecah" ip-type="exclusive" />
+ <device match="ipsecesp" ip-type="exclusive" />
+ <device match="ipstate" ip-type="exclusive" />
+ <device match="ipsync" ip-type="exclusive" />
+ <device match="keysock" ip-type="exclusive" />
+ <device match="rawip" ip-type="exclusive" />
+ <device match="rawip6" ip-type="exclusive" />
+ <device match="rts" ip-type="exclusive" />
+ <device match="sctp" ip-type="exclusive" />
+ <device match="sctp6" ip-type="exclusive" />
+ <device match="spdsock" ip-type="exclusive" />
+
<!-- Renamed devices to create under /dev -->
<device match="zcons/%z/zoneconsole" name="zconsole" />
diff --git a/usr/src/lib/libbrand/common/libbrand.c b/usr/src/lib/libbrand/common/libbrand.c
index 0ce5a93..068d720 100644
--- a/usr/src/lib/libbrand/common/libbrand.c
+++ b/usr/src/lib/libbrand/common/libbrand.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,8 +65,10 @@
#define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg")
#define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm")
+#define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip")
#define DTD_ATTR_ARCH ((const xmlChar *) "arch")
#define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory")
+#define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type")
#define DTD_ATTR_MATCH ((const xmlChar *) "match")
#define DTD_ATTR_MODE ((const xmlChar *) "mode")
#define DTD_ATTR_NAME ((const xmlChar *) "name")
@@ -78,6 +80,8 @@
#define DTD_ATTR_TARGET ((const xmlChar *) "target")
#define DTD_ATTR_TYPE ((const xmlChar *) "type")
+#define DTD_ENTITY_TRUE "true"
+
static volatile boolean_t libbrand_initialized = B_FALSE;
static char i_curr_arch[MAXNAMELEN];
static char i_curr_zone[ZONENAME_MAX];
@@ -538,6 +542,34 @@
return ((strcmp(bhp->bh_name, NATIVE_BRAND_NAME) == 0) ? 1 : 0);
}
+boolean_t
+brand_allow_exclusive_ip(brand_handle_t bh)
+{
+ struct brand_handle *bhp = (struct brand_handle *)bh;
+ xmlNodePtr node;
+ xmlChar *allow_excl;
+ boolean_t ret;
+
+ assert(bhp != NULL);
+
+ if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
+ return (B_FALSE);
+
+ allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL);
+ if (allow_excl == NULL)
+ return (B_FALSE);
+
+ /* Note: only return B_TRUE if it's "true" */
+ if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0)
+ ret = B_TRUE;
+ else
+ ret = B_FALSE;
+
+ xmlFree(allow_excl);
+
+ return (ret);
+}
+
/*
* Iterate over brand privileges
*
@@ -738,12 +770,13 @@
*/
int
brand_platform_iter_devices(brand_handle_t bh, const char *zonename,
- int (*func)(void *, const char *, const char *), void *data)
+ int (*func)(void *, const char *, const char *), void *data,
+ const char *curr_iptype)
{
struct brand_handle *bhp = (struct brand_handle *)bh;
const char *curr_arch = get_curr_arch();
xmlNodePtr node;
- xmlChar *match, *name, *arch;
+ xmlChar *match, *name, *arch, *iptype;
char match_exp[MAXPATHLEN];
boolean_t err = B_FALSE;
int ret = 0;
@@ -752,6 +785,7 @@
assert(bhp != NULL);
assert(zonename != NULL);
assert(func != NULL);
+ assert(curr_iptype != NULL);
if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
return (-1);
@@ -764,7 +798,9 @@
match = xmlGetProp(node, DTD_ATTR_MATCH);
name = xmlGetProp(node, DTD_ATTR_NAME);
arch = xmlGetProp(node, DTD_ATTR_ARCH);
- if ((match == NULL) || (name == NULL) || (arch == NULL)) {
+ iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
+ if ((match == NULL) || (name == NULL) || (arch == NULL) ||
+ (iptype == NULL)) {
err = B_TRUE;
goto next;
}
@@ -774,6 +810,11 @@
(strcmp((char *)arch, curr_arch) != 0))
goto next;
+ /* check if the iptype matches */
+ if ((strcmp((char *)iptype, "all") != 0) &&
+ (strcmp((char *)iptype, curr_iptype) != 0))
+ goto next;
+
/* Substitute token values as needed. */
if ((ret = i_substitute_tokens((char *)match,
match_exp, sizeof (match_exp),
@@ -798,6 +839,8 @@
xmlFree(name);
if (arch != NULL)
xmlFree(arch);
+ if (iptype != NULL)
+ xmlFree(iptype);
if (err)
return (-1);
if (ret != 0)
diff --git a/usr/src/lib/libbrand/common/libbrand.h b/usr/src/lib/libbrand/common/libbrand.h
index bb31cee..0254a9f 100644
--- a/usr/src/lib/libbrand/common/libbrand.h
+++ b/usr/src/lib/libbrand/common/libbrand.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,6 +42,8 @@
extern int brand_is_native(brand_handle_t);
+extern boolean_t brand_allow_exclusive_ip(brand_handle_t);
+
extern int brand_get_boot(brand_handle_t, const char *, const char *,
char *, size_t, int, char **);
extern int brand_get_brandname(brand_handle_t, char *, size_t);
@@ -63,7 +65,7 @@
int (*func)(void *, const char *, const char *), void *);
extern int brand_platform_iter_devices(brand_handle_t, const char *,
- int (*)(void *, const char *, const char *), void *);
+ int (*)(void *, const char *, const char *), void *, const char *);
extern int brand_platform_iter_gmounts(brand_handle_t, const char *,
int (*)(void *, const char *, const char *, const char *, const char *),
void *);
diff --git a/usr/src/lib/libbrand/common/mapfile-vers b/usr/src/lib/libbrand/common/mapfile-vers
index a9daa75..f420114 100644
--- a/usr/src/lib/libbrand/common/mapfile-vers
+++ b/usr/src/lib/libbrand/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -27,6 +27,7 @@
SUNWprivate {
global:
+ brand_allow_exclusive_ip;
brand_close;
brand_config_iter_privilege;
brand_get_boot;
diff --git a/usr/src/lib/libbrand/dtd/zone_platform.dtd.1 b/usr/src/lib/libbrand/dtd/zone_platform.dtd.1
index a9e8c07..28ac8d4 100644
--- a/usr/src/lib/libbrand/dtd/zone_platform.dtd.1
+++ b/usr/src/lib/libbrand/dtd/zone_platform.dtd.1
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
@@ -45,11 +45,16 @@
arch Identifies devices only available for certain architectures.
Can be "sparc" or "i386".
+ ip-type Optional, identifies devices only available for certain IP
+ types. Can be "shared" or "exclusive". If it's not specified,
+ the default value "all" will be used, which means it's
+ available regardless the IP type.
+
For example, the following entry:
<device match="brand/windows/foo" name="bar" arch="sparc" />
would result in mapping the following global zone device:
/dev/brand/windows/foo
- into the zone as:
+ into the zone (disregarding its IP type) as:
/dev/bar
but the mapping would only exist on sparc machines.
@@ -58,7 +63,8 @@
<!ATTLIST device match CDATA #REQUIRED
name CDATA ""
- arch ( sparc | i386 ) "all" >
+ arch ( sparc | i386 ) "all"
+ ip-type ( shared | exclusive ) "all" >
<!--
symlink
@@ -138,7 +144,10 @@
name The name of the brand. This must match the name of the
directory in which this file is stored, as well as the name
of the brand that refers to it.
+ allow-exclusive-ip Whether the zones of this brand can have their
+ own exclusive IP stack. It is a boolean value.
-->
<!ELEMENT platform (device | global_mount | mount | symlink)* >
-<!ATTLIST platform name CDATA #REQUIRED>
+<!ATTLIST platform name CDATA #REQUIRED
+ allow-exclusive-ip (true | false) #REQUIRED>
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 8e1b399..560ac9d 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -2219,14 +2219,18 @@
_xgetwidth;
__xpg6 = NODIRECT;
_yield;
+ zone_add_datalink;
zone_boot;
+ zone_check_datalink;
zone_create;
zone_destroy;
zone_enter;
zone_getattr;
zone_get_id;
zone_list;
+ zone_list_datalink;
zonept;
+ zone_remove_datalink;
zone_setattr;
zone_shutdown;
zone_version;
diff --git a/usr/src/lib/libc/port/sys/zone.c b/usr/src/lib/libc/port/sys/zone.c
index 609cf38..7c747d9 100644
--- a/usr/src/lib/libc/port/sys/zone.c
+++ b/usr/src/lib/libc/port/sys/zone.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,7 +44,7 @@
zoneid_t
zone_create(const char *name, const char *root, const struct priv_set *privs,
const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz,
- int *extended_error, int match, int doi, const bslabel_t *label)
+ int *extended_error, int match, int doi, const bslabel_t *label, int flags)
{
zone_def zd;
priv_data_t *d;
@@ -63,6 +63,7 @@
zd.match = match;
zd.doi = doi;
zd.label = label;
+ zd.flags = flags;
return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd));
}
@@ -221,3 +222,28 @@
{
return (syscall(SYS_zone, ZONE_VERSION, version));
}
+
+
+int
+zone_add_datalink(zoneid_t zoneid, char *dlname)
+{
+ return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, dlname));
+}
+
+int
+zone_remove_datalink(zoneid_t zoneid, char *dlname)
+{
+ return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, dlname));
+}
+
+int
+zone_check_datalink(zoneid_t *zoneidp, char *dlname)
+{
+ return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, dlname));
+}
+
+int
+zone_list_datalink(zoneid_t zoneid, int *dlnump, char *buf)
+{
+ return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, buf));
+}
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index 154fc08..2a62bb8 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -19,12 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <ctype.h>
#include <unistd.h>
#include <stropts.h>
#include <errno.h>
@@ -38,6 +39,7 @@
#include <libdevinfo.h>
#include <libdladm_impl.h>
#include <libintl.h>
+#include <sys/vlan.h>
typedef struct dladm_dev {
char dd_name[IFNAMSIZ];
@@ -162,6 +164,74 @@
}
/*
+ * Hold a data-link.
+ */
+static int
+i_dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+ int fd;
+ dld_hold_vlan_t dhv;
+
+ if (strlen(name) >= IFNAMSIZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (-1);
+
+ bzero(&dhv, sizeof (dld_hold_vlan_t));
+ (void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
+ dhv.dhv_zid = zoneid;
+ dhv.dhv_docheck = docheck;
+
+ if (i_dladm_ioctl(fd, DLDIOCHOLDVLAN, &dhv, sizeof (dhv)) < 0) {
+ int olderrno = errno;
+
+ (void) close(fd);
+ errno = olderrno;
+ return (-1);
+ }
+
+ (void) close(fd);
+ return (0);
+}
+
+/*
+ * Release a data-link.
+ */
+static int
+i_dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+ int fd;
+ dld_hold_vlan_t dhv;
+
+ if (strlen(name) >= IFNAMSIZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (-1);
+
+ bzero(&dhv, sizeof (dld_hold_vlan_t));
+ (void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
+ dhv.dhv_zid = zoneid;
+ dhv.dhv_docheck = docheck;
+
+ if (i_dladm_ioctl(fd, DLDIOCRELEVLAN, &dhv, sizeof (dhv)) < 0) {
+ int olderrno = errno;
+
+ (void) close(fd);
+ errno = olderrno;
+ return (-1);
+ }
+
+ (void) close(fd);
+ return (0);
+}
+
+/*
* Invoke the specified callback function for each active DDI_NT_NET
* node.
*/
@@ -186,7 +256,6 @@
ddp = dw.dw_dev_list;
while (ddp) {
fn(arg, ddp->dd_name);
- (void) dladm_walk_vlan(fn, arg, ddp->dd_name);
last_ddp = ddp;
ddp = ddp->dd_next;
free(last_ddp);
@@ -304,6 +373,9 @@
case DLADM_STATUS_IOERR:
s = "I/O error";
break;
+ case DLADM_STATUS_TEMPONLY:
+ s = "change cannot be persistent, specify -t please";
+ break;
default:
s = "<unknown error>";
break;
@@ -506,3 +578,21 @@
(void) closedir(dp);
return (DLADM_STATUS_OK);
}
+
+/*
+ * Do a "hold" operation to a link.
+ */
+int
+dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+ return (i_dladm_hold_link(name, zoneid, docheck));
+}
+
+/*
+ * Do a "release" operation to a link.
+ */
+int
+dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+ return (i_dladm_rele_link(name, zoneid, docheck));
+}
diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h
index 1cf3700..7421ab1 100644
--- a/usr/src/lib/libdladm/common/libdladm.h
+++ b/usr/src/lib/libdladm/common/libdladm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -64,7 +64,8 @@
DLADM_STATUS_BADVALCNT,
DLADM_STATUS_DBNOTFOUND,
DLADM_STATUS_DENIED,
- DLADM_STATUS_IOERR
+ DLADM_STATUS_IOERR,
+ DLADM_STATUS_TEMPONLY
} dladm_status_t;
typedef enum {
@@ -82,13 +83,16 @@
extern int dladm_walk(dladm_walkcb_t *, void *);
extern int dladm_walk_vlan(dladm_walkcb_t *, void *, const char *);
extern int dladm_info(const char *, dladm_attr_t *);
+extern int dladm_hold_link(const char *, zoneid_t, boolean_t);
+extern int dladm_rele_link(const char *, zoneid_t, boolean_t);
extern dladm_status_t dladm_set_prop(const char *, const char *,
- char **, uint_t, uint_t);
+ char **, uint_t, uint_t, char **);
extern dladm_status_t dladm_get_prop(const char *, dladm_prop_type_t,
const char *, char **, uint_t *);
extern dladm_status_t dladm_walk_prop(const char *, void *,
boolean_t (*)(void *, const char *));
+extern boolean_t dladm_is_prop_temponly(const char *, char **);
extern dladm_status_t dladm_set_secobj(const char *, dladm_secobj_class_t,
uint8_t *, uint_t, uint_t);
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index 8e1ef84..e3b9ed3 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,14 +29,66 @@
#include <strings.h>
#include <errno.h>
#include <ctype.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/dld.h>
+#include <sys/zone.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libdevinfo.h>
+#include <zone.h>
#include <libwladm.h>
#include <libdladm_impl.h>
+#include <dlfcn.h>
+#include <link.h>
+
static dladm_status_t i_dladm_set_prop_db(const char *, const char *,
char **, uint_t);
static dladm_status_t i_dladm_get_prop_db(const char *, const char *,
char **, uint_t *);
+static dladm_status_t i_dladm_get_prop_temp(const char *, dladm_prop_type_t,
+ const char *, char **, uint_t *);
+static dladm_status_t i_dladm_set_prop_temp(const char *, const char *,
+ char **, uint_t, uint_t, char **);
+static boolean_t i_dladm_is_prop_temponly(const char *prop_name,
+ char **);
+
+typedef struct val_desc {
+ char *vd_name;
+ void *vd_val;
+} val_desc_t;
+
+struct prop_desc;
+
+typedef dladm_status_t pd_getf_t(const char *, char **, uint_t *);
+typedef dladm_status_t pd_setf_t(const char *, val_desc_t *, uint_t);
+typedef dladm_status_t pd_checkf_t(struct prop_desc *, char **,
+ uint_t, val_desc_t **);
+
+static pd_getf_t do_get_zone;
+static pd_setf_t do_set_zone;
+static pd_checkf_t do_check_zone;
+
+typedef struct prop_desc {
+ char *pd_name;
+ val_desc_t pd_defval;
+ val_desc_t *pd_modval;
+ uint_t pd_nmodval;
+ boolean_t pd_temponly;
+ pd_setf_t *pd_set;
+ pd_getf_t *pd_getmod;
+ pd_getf_t *pd_get;
+ pd_checkf_t *pd_check;
+} prop_desc_t;
+
+static prop_desc_t prop_table[] = {
+ { "zone", { "", NULL }, NULL, 0, B_TRUE,
+ do_set_zone, NULL,
+ do_get_zone, do_check_zone}
+};
+
+#define MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
/*
* Convert a wladm_status_t to a dladm_status_t. This is used by wrappers
@@ -79,7 +131,7 @@
dladm_status_t
dladm_set_prop(const char *link, const char *prop_name, char **prop_val,
- uint_t val_cnt, uint_t flags)
+ uint_t val_cnt, uint_t flags, char **errprop)
{
dladm_status_t status = DLADM_STATUS_BADARG;
@@ -88,15 +140,27 @@
return (DLADM_STATUS_BADARG);
if ((flags & DLADM_OPT_TEMP) != 0) {
- if (wladm_is_valid(link)) {
- status = dladm_wladmstatus2status(
- wladm_set_prop(link, prop_name,
- prop_val, val_cnt));
+ status = i_dladm_set_prop_temp(link, prop_name, prop_val,
+ val_cnt, flags, errprop);
+ if (status == DLADM_STATUS_TEMPONLY &&
+ (flags & DLADM_OPT_PERSIST) != 0)
+ return (DLADM_STATUS_TEMPONLY);
+
+ if (status == DLADM_STATUS_NOTFOUND) {
+ status = DLADM_STATUS_BADARG;
+ if (wladm_is_valid(link)) {
+ status = dladm_wladmstatus2status(
+ wladm_set_prop(link, prop_name,
+ prop_val, val_cnt, errprop));
+ }
}
if (status != DLADM_STATUS_OK)
return (status);
}
if ((flags & DLADM_OPT_PERSIST) != 0) {
+ if (i_dladm_is_prop_temponly(prop_name, errprop))
+ return (DLADM_STATUS_TEMPONLY);
+
status = i_dladm_set_prop_db(link, prop_name,
prop_val, val_cnt);
}
@@ -107,20 +171,35 @@
dladm_walk_prop(const char *link, void *arg,
boolean_t (*func)(void *, const char *))
{
+ int i;
+
if (link == NULL || func == NULL)
return (DLADM_STATUS_BADARG);
+ /* For wifi links, show wifi properties first */
if (wladm_is_valid(link)) {
- return (dladm_wladmstatus2status(
- wladm_walk_prop(link, arg, func)));
+ dladm_status_t status;
+
+ status = dladm_wladmstatus2status(
+ wladm_walk_prop(link, arg, func));
+ if (status != DLADM_STATUS_OK)
+ return (status);
}
- return (DLADM_STATUS_BADARG);
+
+ /* Then show data-link properties if there are any */
+ for (i = 0; i < MAX_PROPS; i++) {
+ if (!func(arg, prop_table[i].pd_name))
+ break;
+ }
+ return (DLADM_STATUS_OK);
}
dladm_status_t
dladm_get_prop(const char *link, dladm_prop_type_t type,
const char *prop_name, char **prop_val, uint_t *val_cntp)
{
+ dladm_status_t status;
+
if (link == NULL || prop_name == NULL || prop_val == NULL ||
val_cntp == NULL || *val_cntp == 0)
return (DLADM_STATUS_BADARG);
@@ -130,6 +209,11 @@
prop_val, val_cntp));
}
+ status = i_dladm_get_prop_temp(link, type, prop_name,
+ prop_val, val_cntp);
+ if (status != DLADM_STATUS_NOTFOUND)
+ return (status);
+
if (wladm_is_valid(link)) {
wladm_prop_type_t wtype;
@@ -421,7 +505,7 @@
propval[i] = (char *)lvp->lv_name;
status = dladm_set_prop(lsp->ls_link, lip->li_name,
- propval, valcnt, DLADM_OPT_TEMP);
+ propval, valcnt, DLADM_OPT_TEMP, NULL);
/*
* We continue with initializing other properties even
@@ -698,3 +782,422 @@
return (LINKPROP_RW_DB(&state, B_FALSE));
}
+
+static dladm_status_t
+i_dladm_get_zoneid(const char *link, zoneid_t *zidp)
+{
+ int fd;
+ dld_hold_vlan_t dhv;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ bzero(&dhv, sizeof (dld_hold_vlan_t));
+ (void) strlcpy(dhv.dhv_name, link, IFNAMSIZ);
+ dhv.dhv_zid = -1;
+
+ if (i_dladm_ioctl(fd, DLDIOCZIDGET, &dhv, sizeof (dhv)) < 0 &&
+ errno != ENOENT) {
+ dladm_status_t status = dladm_errno2status(errno);
+
+ (void) close(fd);
+ return (status);
+ }
+
+ if (errno == ENOENT)
+ *zidp = GLOBAL_ZONEID;
+ else
+ *zidp = dhv.dhv_zid;
+
+ (void) close(fd);
+ return (DLADM_STATUS_OK);
+}
+
+typedef int (*zone_get_devroot_t)(char *, char *, size_t);
+
+static int
+i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
+{
+ char root[MAXPATHLEN];
+ zone_get_devroot_t real_zone_get_devroot;
+ void *dlhandle;
+ void *sym;
+ int ret;
+
+ if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
+ return (-1);
+
+ if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
+ (void) dlclose(dlhandle);
+ return (-1);
+ }
+
+ real_zone_get_devroot = (zone_get_devroot_t)sym;
+
+ if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
+ (void) snprintf(dev, devlen, "%s%s", root, "/dev");
+ (void) dlclose(dlhandle);
+ return (ret);
+}
+
+static dladm_status_t
+i_dladm_add_deventry(zoneid_t zid, const char *link)
+{
+ char path[MAXPATHLEN];
+ di_prof_t prof = NULL;
+ char zone_name[ZONENAME_MAX];
+ dladm_status_t status;
+
+ if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
+ return (dladm_errno2status(errno));
+ if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
+ return (dladm_errno2status(errno));
+ if (di_prof_init(path, &prof) != 0)
+ return (dladm_errno2status(errno));
+
+ status = DLADM_STATUS_OK;
+ if (di_prof_add_dev(prof, link) != 0) {
+ status = dladm_errno2status(errno);
+ goto cleanup;
+ }
+ if (di_prof_commit(prof) != 0)
+ status = dladm_errno2status(errno);
+cleanup:
+ if (prof)
+ di_prof_fini(prof);
+
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_remove_deventry(zoneid_t zid, const char *link)
+{
+ char path[MAXPATHLEN];
+ di_prof_t prof = NULL;
+ char zone_name[ZONENAME_MAX];
+ dladm_status_t status;
+
+ if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
+ return (dladm_errno2status(errno));
+ if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
+ return (dladm_errno2status(errno));
+ if (di_prof_init(path, &prof) != 0)
+ return (dladm_errno2status(errno));
+
+ status = DLADM_STATUS_OK;
+ if (di_prof_add_exclude(prof, link) != 0) {
+ status = dladm_errno2status(errno);
+ goto cleanup;
+ }
+ if (di_prof_commit(prof) != 0)
+ status = dladm_errno2status(errno);
+cleanup:
+ if (prof)
+ di_prof_fini(prof);
+
+ return (status);
+}
+
+static dladm_status_t
+do_get_zone(const char *link, char **prop_val, uint_t *val_cnt)
+{
+ char zone_name[ZONENAME_MAX];
+ zoneid_t zid;
+ dladm_status_t status;
+
+ status = i_dladm_get_zoneid(link, &zid);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ *val_cnt = 1;
+ if (zid != GLOBAL_ZONEID) {
+ if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
+ return (dladm_errno2status(errno));
+
+ (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
+ } else {
+ *prop_val[0] = '\0';
+ }
+
+ return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+do_set_zone(const char *link, val_desc_t *vdp, uint_t val_cnt)
+{
+ dladm_status_t status;
+ zoneid_t zid_old, zid_new;
+ char buff[IF_NAMESIZE + 1];
+ struct stat st;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ status = i_dladm_get_zoneid(link, &zid_old);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ /* Do nothing if setting to current value */
+ zid_new = (zoneid_t)vdp->vd_val;
+ if (zid_new == zid_old)
+ return (DLADM_STATUS_OK);
+
+ /* Do a stat to get the vlan created by MAC, if it's not there */
+ (void) strcpy(buff, "/dev/");
+ (void) strlcat(buff, link, IF_NAMESIZE);
+ (void) stat(buff, &st);
+
+ if (zid_old != GLOBAL_ZONEID) {
+ if (dladm_rele_link(link, GLOBAL_ZONEID, B_TRUE) < 0)
+ return (dladm_errno2status(errno));
+
+ if (zone_remove_datalink(zid_old, (char *)link) != 0 &&
+ errno != ENXIO) {
+ status = dladm_errno2status(errno);
+ goto rollback1;
+ }
+
+ status = i_dladm_remove_deventry(zid_old, link);
+ if (status != DLADM_STATUS_OK)
+ goto rollback2;
+ }
+
+ if (zid_new != GLOBAL_ZONEID) {
+ if (zone_add_datalink(zid_new, (char *)link) != 0) {
+ status = dladm_errno2status(errno);
+ goto rollback3;
+ }
+
+ if (dladm_hold_link(link, zid_new, B_TRUE) < 0) {
+ (void) zone_remove_datalink(zid_new, (char *)link);
+ status = dladm_errno2status(errno);
+ goto rollback3;
+ }
+
+ status = i_dladm_add_deventry(zid_new, link);
+ if (status != DLADM_STATUS_OK) {
+ (void) dladm_rele_link(link, GLOBAL_ZONEID, B_FALSE);
+ (void) zone_remove_datalink(zid_new, (char *)link);
+ goto rollback3;
+ }
+ }
+ return (DLADM_STATUS_OK);
+
+rollback3:
+ if (zid_old != GLOBAL_ZONEID)
+ (void) i_dladm_add_deventry(zid_old, link);
+rollback2:
+ if (zid_old != GLOBAL_ZONEID)
+ (void) zone_add_datalink(zid_old, (char *)link);
+rollback1:
+ (void) dladm_hold_link(link, zid_old, B_FALSE);
+cleanexit:
+ return (status);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
+ val_desc_t **vdpp)
+{
+ zoneid_t zid;
+ val_desc_t *vdp = NULL;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ if ((zid = getzoneidbyname(*prop_val)) == -1)
+ return (DLADM_STATUS_BADVAL);
+
+ if (zid != GLOBAL_ZONEID) {
+ ushort_t flags;
+
+ if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
+ sizeof (flags)) < 0) {
+ return (dladm_errno2status(errno));
+ }
+
+ if (!(flags & ZF_NET_EXCL)) {
+ return (DLADM_STATUS_BADVAL);
+ }
+ }
+
+ vdp = malloc(sizeof (val_desc_t));
+ if (vdp == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ vdp->vd_val = (void *)zid;
+ *vdpp = vdp;
+ return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+i_dladm_get_prop_temp(const char *link, dladm_prop_type_t type,
+ const char *prop_name, char **prop_val, uint_t *val_cntp)
+{
+ int i;
+ dladm_status_t status;
+ uint_t cnt;
+ prop_desc_t *pdp;
+
+ if (link == NULL || prop_name == NULL || prop_val == NULL ||
+ val_cntp == NULL || *val_cntp == 0)
+ return (DLADM_STATUS_BADARG);
+
+ for (i = 0; i < MAX_PROPS; i++)
+ if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
+ break;
+
+ if (i == MAX_PROPS)
+ return (DLADM_STATUS_NOTFOUND);
+
+ pdp = &prop_table[i];
+ status = DLADM_STATUS_OK;
+
+ switch (type) {
+ case DLADM_PROP_VAL_CURRENT:
+ status = pdp->pd_get(link, prop_val, val_cntp);
+ break;
+ case DLADM_PROP_VAL_DEFAULT:
+ if (pdp->pd_defval.vd_name == NULL) {
+ status = DLADM_STATUS_NOTSUP;
+ break;
+ }
+ (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
+ *val_cntp = 1;
+ break;
+
+ case DLADM_PROP_VAL_MODIFIABLE:
+ if (pdp->pd_getmod != NULL) {
+ status = pdp->pd_getmod(link, prop_val, val_cntp);
+ break;
+ }
+ cnt = pdp->pd_nmodval;
+ if (cnt == 0) {
+ status = DLADM_STATUS_NOTSUP;
+ } else if (cnt > *val_cntp) {
+ status = DLADM_STATUS_TOOSMALL;
+ } else {
+ for (i = 0; i < cnt; i++) {
+ (void) strcpy(prop_val[i],
+ pdp->pd_modval[i].vd_name);
+ }
+ *val_cntp = cnt;
+ }
+ break;
+ default:
+ status = DLADM_STATUS_BADARG;
+ break;
+ }
+
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_set_one_prop_temp(const char *link, prop_desc_t *pdp, char **prop_val,
+ uint_t val_cnt, uint_t flags)
+{
+ dladm_status_t status;
+ val_desc_t *vdp = NULL;
+ uint_t cnt;
+
+ if (pdp->pd_temponly && (flags & DLADM_OPT_PERSIST) != 0)
+ return (DLADM_STATUS_TEMPONLY);
+
+ if (pdp->pd_set == NULL)
+ return (DLADM_STATUS_PROPRDONLY);
+
+ if (prop_val != NULL) {
+ if (pdp->pd_check != NULL)
+ status = pdp->pd_check(pdp, prop_val, val_cnt, &vdp);
+ else
+ status = DLADM_STATUS_BADARG;
+
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ cnt = val_cnt;
+ } else {
+ if (pdp->pd_defval.vd_name == NULL)
+ return (DLADM_STATUS_NOTSUP);
+
+ if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t));
+ cnt = 1;
+ }
+
+ status = pdp->pd_set(link, vdp, cnt);
+
+ free(vdp);
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_set_prop_temp(const char *link, const char *prop_name, char **prop_val,
+ uint_t val_cnt, uint_t flags, char **errprop)
+{
+ int i;
+ dladm_status_t status = DLADM_STATUS_OK;
+ boolean_t found = B_FALSE;
+
+ for (i = 0; i < MAX_PROPS; i++) {
+ prop_desc_t *pdp = &prop_table[i];
+ dladm_status_t s;
+
+ if (prop_name != NULL &&
+ (strcasecmp(prop_name, pdp->pd_name) != 0))
+ continue;
+
+ found = B_TRUE;
+ s = i_dladm_set_one_prop_temp(link, pdp, prop_val, val_cnt,
+ flags);
+
+ if (prop_name != NULL) {
+ status = s;
+ break;
+ } else {
+ if (s != DLADM_STATUS_OK &&
+ s != DLADM_STATUS_NOTSUP) {
+ if (errprop != NULL)
+ *errprop = pdp->pd_name;
+ status = s;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ status = DLADM_STATUS_NOTFOUND;
+
+ return (status);
+}
+
+static boolean_t
+i_dladm_is_prop_temponly(const char *prop_name, char **errprop)
+{
+ int i;
+
+ for (i = 0; i < MAX_PROPS; i++) {
+ prop_desc_t *pdp = &prop_table[i];
+
+ if (prop_name != NULL &&
+ (strcasecmp(prop_name, pdp->pd_name) != 0))
+ continue;
+
+ if (errprop != NULL)
+ *errprop = pdp->pd_name;
+
+ if (pdp->pd_temponly)
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+boolean_t
+dladm_is_prop_temponly(const char *prop_name, char **errprop)
+{
+ return (i_dladm_is_prop_temponly(prop_name, errprop));
+}
diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers
index 2af8201..34d1e2c 100644
--- a/usr/src/lib/libdladm/common/mapfile-vers
+++ b/usr/src/lib/libdladm/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -33,6 +33,7 @@
dladm_get_prop;
dladm_set_prop;
dladm_walk_prop;
+ dladm_is_prop_temponly;
dladm_get_secobj;
dladm_set_secobj;
dladm_unset_secobj;
@@ -44,6 +45,8 @@
dladm_init_secobj;
dladm_set_rootdir;
+ dladm_hold_link;
+ dladm_rele_link;
local:
*;
};
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index 40de76e..e568985 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -104,12 +104,12 @@
File System Management:suser:cmd:::/usr/sbin/umountall:uid=0
File System Management:suser:cmd:::/usr/sbin/unshare:uid=0;gid=root
File System Management:suser:cmd:::/usr/sbin/unshareall:uid=0;gid=root
-IP Filter Management:solaris:cmd:::/usr/sbin/ipf:privs=sys_net_config
-IP Filter Management:solaris:cmd:::/usr/sbin/ipfs:privs=sys_net_config
-IP Filter Management:solaris:cmd:::/usr/sbin/ipmon:privs=sys_net_config
-IP Filter Management:solaris:cmd:::/usr/sbin/ipfstat:privs=sys_net_config;gid=sys
-IP Filter Management:solaris:cmd:::/usr/sbin/ipnat:privs=sys_net_config;gid=sys
-IP Filter Management:solaris:cmd:::/usr/sbin/ippool:privs=sys_net_config;gid=sys
+IP Filter Management:solaris:cmd:::/usr/sbin/ipf:privs=sys_ip_config
+IP Filter Management:solaris:cmd:::/usr/sbin/ipfs:privs=sys_ip_config
+IP Filter Management:solaris:cmd:::/usr/sbin/ipmon:privs=sys_ip_config
+IP Filter Management:solaris:cmd:::/usr/sbin/ipfstat:privs=sys_ip_config;gid=sys
+IP Filter Management:solaris:cmd:::/usr/sbin/ipnat:privs=sys_ip_config;gid=sys
+IP Filter Management:solaris:cmd:::/usr/sbin/ippool:privs=sys_ip_config;gid=sys
Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/krb5kdc:uid=0
Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/kadmind:uid=0
Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/kprop:euid=0;privs=none
@@ -175,9 +175,9 @@
Name Service Security:suser:cmd:::/usr/sbin/nislog:euid=0
Name Service Security:suser:cmd:::/usr/sbin/rpc.nisd:uid=0;gid=0
Network Management:solaris:cmd:::/sbin/ifconfig:uid=0
-Network Management:solaris:cmd:::/sbin/route:privs=sys_net_config
+Network Management:solaris:cmd:::/sbin/route:privs=sys_ip_config
Network Management:solaris:cmd:::/sbin/routeadm:euid=0;\
- privs=proc_chroot,proc_owner,sys_net_config
+ privs=proc_chroot,proc_owner,sys_ip_config
Network Management:solaris:cmd:::/sbin/dladm:euid=dladm;egid=sys;\
privs=sys_net_config,net_rawaccess,proc_audit
Network Management:suser:cmd:::/usr/bin/netstat:uid=0
@@ -194,15 +194,15 @@
Network Management:suser:cmd:::/usr/sbin/spray:euid=0
Network Link Security:solaris:cmd:::/sbin/dladm:euid=dladm;egid=sys;\
privs=sys_net_config,net_rawaccess,proc_audit
-Network Security:solaris:cmd:::/usr/lib/inet/certdb:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/lib/inet/certlocal:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/lib/inet/certrldb:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/lib/inet/in.iked:privs=sys_net_config,net_privaddr
-Network Security:solaris:cmd:::/usr/sbin/ikeadm:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/sbin/ikecert:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/sbin/ipsecconf:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/sbin/ipseckey:privs=sys_net_config
-Network Security:solaris:cmd:::/usr/sbin/ipsecalgs:privs=sys_net_config
+Network Security:solaris:cmd:::/usr/lib/inet/certdb:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/lib/inet/certlocal:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/lib/inet/certrldb:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/lib/inet/in.iked:privs=sys_ip_config,net_privaddr
+Network Security:solaris:cmd:::/usr/sbin/ikeadm:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/sbin/ikecert:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/sbin/ipsecconf:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/sbin/ipseckey:privs=sys_ip_config
+Network Security:solaris:cmd:::/usr/sbin/ipsecalgs:privs=sys_ip_config
Network Security:solaris:cmd:::/usr/sbin/ksslcfg:euid=0
Network Security:suser:cmd:::/usr/bin/ssh-keygen:uid=0;gid=sys
Network Security:suser:cmd:::/usr/lib/inet/certdb:euid=0
diff --git a/usr/src/lib/libwladm/common/libwladm.c b/usr/src/lib/libwladm/common/libwladm.c
index 567be61..7724008 100644
--- a/usr/src/lib/libwladm/common/libwladm.c
+++ b/usr/src/lib/libwladm/common/libwladm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1054,7 +1054,7 @@
wladm_status_t
wladm_set_prop(const char *link, const char *prop_name,
- char **prop_val, uint_t val_cnt)
+ char **prop_val, uint_t val_cnt, char **errprop)
{
int fd, i;
wldp_t *gbuf = NULL;
@@ -1089,8 +1089,12 @@
break;
} else {
if (s != WLADM_STATUS_OK &&
- s != WLADM_STATUS_NOTSUP)
+ s != WLADM_STATUS_NOTSUP) {
+ if (errprop != NULL)
+ *errprop = pdp->pd_name;
status = s;
+ break;
+ }
}
}
if (!found)
diff --git a/usr/src/lib/libwladm/common/libwladm.h b/usr/src/lib/libwladm/common/libwladm.h
index 0a5d24d..45122cf 100644
--- a/usr/src/lib/libwladm/common/libwladm.h
+++ b/usr/src/lib/libwladm/common/libwladm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -174,7 +174,7 @@
extern wladm_status_t wladm_walk(void *, boolean_t (*)(void *, const char *));
extern boolean_t wladm_is_valid(const char *);
extern wladm_status_t wladm_set_prop(const char *, const char *, char **,
- uint_t);
+ uint_t, char **);
extern wladm_status_t wladm_walk_prop(const char *, void *,
boolean_t (*)(void *, const char *));
extern wladm_status_t wladm_get_prop(const char *, wladm_prop_type_t,
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 1a3fb37..cce47ce 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -45,6 +45,7 @@
#include <sys/mnttab.h>
#include <sys/nvpair.h>
#include <sys/types.h>
+#include <sys/sockio.h>
#include <ftw.h>
#include <pool.h>
#include <libscf.h>
@@ -65,7 +66,6 @@
#include <libzonecfg.h>
#include "zonecfg_impl.h"
-
#define _PATH_TMPFILE "/zonecfg.XXXXXX"
#define ZONE_CB_RETRY_COUNT 10
#define ZONE_EVENT_PING_SUBCLASS "ping"
@@ -95,6 +95,7 @@
#define DTD_ATTR_ACTION (const xmlChar *) "action"
#define DTD_ATTR_ADDRESS (const xmlChar *) "address"
#define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot"
+#define DTD_ATTR_IPTYPE (const xmlChar *) "ip-type"
#define DTD_ATTR_DIR (const xmlChar *) "directory"
#define DTD_ATTR_LIMIT (const xmlChar *) "limit"
#define DTD_ATTR_LIMITPRIV (const xmlChar *) "limitpriv"
@@ -1497,6 +1498,69 @@
return (error);
}
+int
+zonecfg_get_iptype(zone_dochandle_t handle, zone_iptype_t *iptypep)
+{
+ char property[10]; /* 10 is big enough for "shared"/"exclusive" */
+ int err;
+
+ err = getrootattr(handle, DTD_ATTR_IPTYPE, property, sizeof (property));
+ if (err == Z_BAD_PROPERTY) {
+ /* Return default value */
+ *iptypep = ZS_SHARED;
+ return (Z_OK);
+ } else if (err != Z_OK) {
+ return (err);
+ }
+
+ if (strlen(property) == 0 ||
+ strcmp(property, "shared") == 0)
+ *iptypep = ZS_SHARED;
+ else if (strcmp(property, "exclusive") == 0)
+ *iptypep = ZS_EXCLUSIVE;
+ else
+ return (Z_INVAL);
+
+ return (Z_OK);
+}
+
+int
+zonecfg_set_iptype(zone_dochandle_t handle, zone_iptype_t iptype)
+{
+ xmlNodePtr cur;
+
+ if (handle == NULL)
+ return (Z_INVAL);
+
+ cur = xmlDocGetRootElement(handle->zone_dh_doc);
+ if (cur == NULL) {
+ return (Z_EMPTY_DOCUMENT);
+ }
+
+ if (xmlStrcmp(cur->name, DTD_ELEM_ZONE) != 0) {
+ return (Z_WRONG_DOC_TYPE);
+ }
+ switch (iptype) {
+ case ZS_SHARED:
+ /*
+ * Since "shared" is the default, we don't write it to the
+ * configuration file, so that it's easier to migrate those
+ * zones elsewhere, eg., to systems which are not IP-Instances
+ * aware.
+ * xmlUnsetProp only fails when the attribute doesn't exist,
+ * which we don't care.
+ */
+ (void) xmlUnsetProp(cur, DTD_ATTR_IPTYPE);
+ break;
+ case ZS_EXCLUSIVE:
+ if (xmlSetProp(cur, DTD_ATTR_IPTYPE,
+ (const xmlChar *) "exclusive") == NULL)
+ return (Z_INVAL);
+ break;
+ }
+ return (Z_OK);
+}
+
static int
newprop(xmlNodePtr node, const xmlChar *attrname, char *src)
{
@@ -2038,6 +2102,30 @@
return (Z_OK);
}
+boolean_t
+zonecfg_ifname_exists(sa_family_t af, char *ifname)
+{
+ struct lifreq lifr;
+ int so;
+ int save_errno;
+
+ (void) memset(&lifr, 0, sizeof (lifr));
+ (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
+ lifr.lifr_addr.ss_family = af;
+ if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
+ /* Odd - can't tell if the ifname exists */
+ return (B_FALSE);
+ }
+ if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
+ save_errno = errno;
+ (void) close(so);
+ errno = save_errno;
+ return (B_FALSE);
+ }
+ (void) close(so);
+ return (B_TRUE);
+}
+
int
zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
{
diff --git a/usr/src/lib/libzonecfg/common/mapfile-vers b/usr/src/lib/libzonecfg/common/mapfile-vers
index e2bb782..384641b 100644
--- a/usr/src/lib/libzonecfg/common/mapfile-vers
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -106,6 +106,7 @@
zonecfg_getfsent;
zonecfg_get_handle;
zonecfg_getipdent;
+ zonecfg_get_iptype;
zonecfg_get_limitpriv;
zonecfg_getmcapent;
zonecfg_get_name;
@@ -125,6 +126,7 @@
zonecfg_get_uuid;
zonecfg_get_xml_handle;
zonecfg_get_zonepath;
+ zonecfg_ifname_exists;
zonecfg_in_alt_root;
zonecfg_init_handle;
zonecfg_is_rctl;
@@ -172,6 +174,7 @@
zonecfg_setdsent;
zonecfg_setfsent;
zonecfg_setipdent;
+ zonecfg_set_iptype;
zonecfg_set_limitpriv;
zonecfg_set_name;
zonecfg_setnwifent;
diff --git a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
index c51e89a..5de8176 100644
--- a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
+++ b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
@@ -44,7 +44,7 @@
<!ELEMENT network EMPTY>
-<!ATTLIST network address CDATA #REQUIRED
+<!ATTLIST network address CDATA ""
physical CDATA #REQUIRED>
<!ELEMENT device EMPTY>
@@ -136,6 +136,7 @@
<!ATTLIST zone name CDATA #REQUIRED
zonepath CDATA #REQUIRED
autoboot (true | false) #REQUIRED
+ ip-type CDATA ""
pool CDATA ""
limitpriv CDATA ""
bootargs CDATA ""
diff --git a/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl b/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
index 5a9803a..ddf799c 100644
--- a/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
+++ b/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
@@ -48,7 +48,7 @@
BASEDIR=/
SUNW_PKGVERS="1.0"
SUNW_PKG_ALLZONES="true"
-SUNW_PKG_HOLLOW="true"
+SUNW_PKG_HOLLOW="false"
SUNW_PKG_THISZONE="false"
#VSTOCK="<reserved by Release Engineering for package part #>"
#ISTATES="<developer defined>"
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index fc2a8c7..3a53f96 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -141,10 +141,13 @@
f none usr/include/inet/ip_multi.h 644 root bin
f none usr/include/inet/ip_netinfo.h 644 root bin
f none usr/include/inet/ip_rts.h 644 root bin
+f none usr/include/inet/ip_stack.h 644 root bin
f none usr/include/inet/ip6.h 644 root bin
f none usr/include/inet/ip6_asp.h 644 root bin
f none usr/include/inet/ipclassifier.h 644 root bin
f none usr/include/inet/ipp_common.h 644 root bin
+d none usr/include/inet/kssl 755 root bin
+f none usr/include/inet/kssl/ksslapi.h 644 root bin
f none usr/include/inet/led.h 644 root bin
f none usr/include/inet/mi.h 644 root bin
f none usr/include/inet/mib2.h 644 root bin
@@ -154,9 +157,8 @@
f none usr/include/inet/snmpcom.h 644 root bin
f none usr/include/inet/tcp.h 644 root bin
f none usr/include/inet/tcp_sack.h 644 root bin
+f none usr/include/inet/tcp_stack.h 644 root bin
f none usr/include/inet/wifi_ioctl.h 644 root bin
-d none usr/include/inet/kssl 755 root bin
-f none usr/include/inet/kssl/ksslapi.h 644 root bin
f none usr/include/inttypes.h 644 root bin
f none usr/include/ipmp.h 644 root bin
f none usr/include/ipmp_mpathd.h 644 root bin
@@ -904,6 +906,7 @@
f none usr/include/sys/ndifm.h 644 root bin
f none usr/include/sys/ndi_impldefs.h 644 root bin
f none usr/include/sys/neti.h 644 root bin
+f none usr/include/sys/netstack.h 644 root bin
f none usr/include/sys/note.h 644 root bin
f none usr/include/sys/nvpair.h 644 root bin
f none usr/include/sys/nvpair_impl.h 644 root bin
diff --git a/usr/src/pkgdefs/SUNWipfh/prototype_com b/usr/src/pkgdefs/SUNWipfh/prototype_com
index 4e9f9ce..466c971 100644
--- a/usr/src/pkgdefs/SUNWipfh/prototype_com
+++ b/usr/src/pkgdefs/SUNWipfh/prototype_com
@@ -1,5 +1,5 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -26,9 +26,15 @@
d none usr 755 root sys
d none usr/include 755 root bin
d none usr/include/netinet 755 root bin
+f none usr/include/netinet/ipf_stack.h 644 root bin
f none usr/include/netinet/ip_compat.h 644 root bin
f none usr/include/netinet/ip_fil.h 644 root bin
f none usr/include/netinet/ip_nat.h 644 root bin
f none usr/include/netinet/ip_state.h 644 root bin
f none usr/include/netinet/ip_proxy.h 644 root bin
f none usr/include/netinet/ipl.h 644 root bin
+f none usr/include/netinet/ip_frag.h 644 root bin
+f none usr/include/netinet/ip_auth.h 644 root bin
+f none usr/include/netinet/ip_pool.h 644 root bin
+f none usr/include/netinet/ip_htable.h 644 root bin
+f none usr/include/netinet/ip_lookup.h 644 root bin
diff --git a/usr/src/pkgdefs/SUNWipfr/pkginfo.tmpl b/usr/src/pkgdefs/SUNWipfr/pkginfo.tmpl
index ce2abc2..8133ef2 100644
--- a/usr/src/pkgdefs/SUNWipfr/pkginfo.tmpl
+++ b/usr/src/pkgdefs/SUNWipfr/pkginfo.tmpl
@@ -1,5 +1,5 @@
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -27,7 +27,7 @@
BASEDIR=/
SUNW_PKGVERS="1.0"
SUNW_PKG_ALLZONES="true"
-SUNW_PKG_HOLLOW="true"
+SUNW_PKG_HOLLOW="false"
SUNW_PKG_THISZONE="false"
#VSTOCK="<reserved by Release Engineering for package part #>"
#ISTATES="<developer defined>"
diff --git a/usr/src/pkgdefs/SUNWipfr/prototype_com b/usr/src/pkgdefs/SUNWipfr/prototype_com
index 39bf9a0..261071a 100644
--- a/usr/src/pkgdefs/SUNWipfr/prototype_com
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_com
@@ -54,9 +54,6 @@
d none lib/svc 0755 root bin
d none lib/svc/method 0755 root bin
f none lib/svc/method/ipfilter 0555 root bin
-d none kernel 755 root sys
-d none kernel/drv 755 root sys
-d none kernel/strmod 755 root sys
d none var 755 root sys
d none var/db 755 root sys
d none var/db/ipf 755 root sys
diff --git a/usr/src/pkgdefs/common_files/i.devpolicy b/usr/src/pkgdefs/common_files/i.devpolicy
index 811a2db..16df7b2 100644
--- a/usr/src/pkgdefs/common_files/i.devpolicy
+++ b/usr/src/pkgdefs/common_files/i.devpolicy
@@ -22,7 +22,7 @@
#
# ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# NOTE: When a change is made to the source file for
@@ -41,12 +41,17 @@
sed < $dest.$$ > $dest \
-e '/md:admin/s/read_priv_set=sys_config/ /' \
-e '/^icmp[ ]*read_priv_set=net_rawaccess[ ]*write_priv_set=net_rawaccess$/d' \
- -e '/^icmp6[ ]*read_priv_set=net_rawaccess[ ]*write_priv_set=net_rawaccess$/d'
+ -e '/^icmp6[ ]*read_priv_set=net_rawaccess[ ]*write_priv_set=net_rawaccess$/d' \
+ -e '/^keysock[ ]*read_priv_set=sys_net_config[ ]*write_priv_set=sys_net_config$/d' \
+ -e '/^ipsecah[ ]*read_priv_set=sys_net_config[ ]*write_priv_set=sys_net_config$/d' \
+ -e '/^ipsecesp[ ]*read_priv_set=sys_net_config[ ]*write_priv_set=sys_net_config$/d' \
+ -e '/^spdsock[ ]*read_priv_set=sys_net_config[ ]*write_priv_set=sys_net_config$/d' \
+ -e '/^ipf[ ]*read_priv_set=sys_net_config[ ]*write_priv_set=sys_net_config$/d'
rm -f $dest.$$
# potential additions
- additions="aggr aggr:ctl bge dld:ctl dnet ibd icmp icmp6 openeepr random vni ipf pfil scsi_vhci"
+ additions="aggr aggr:ctl bge dld:ctl dnet keysock ibd icmp icmp6 ipsecah ipsecesp openeepr random spdsock vni ipf pfil scsi_vhci"
for dev in $additions
do
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index 08ba1a2..694bc9b 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -99,6 +99,8 @@
etc/inet/*
etc/init.d/*
etc/inittab
+ etc/ipf/ipf.conf
+ etc/iu.ap
etc/krb5/kadm5.acl
etc/krb5/kdc.conf
etc/krb5/kpropd.acl
@@ -185,9 +187,6 @@
etc/devlink.tab
etc/driver_aliases
etc/driver_classes
- etc/ipf/ipf.conf
- etc/ipf/pfil.ap
- etc/iu.ap
etc/lvm/devpath
etc/lvm/lock
etc/lvm/md.cf
@@ -240,7 +239,6 @@
dev/pts
dev/rdsk
dev/rmt
- dev/sad
dev/stderr
dev/stdin
dev/stdout
@@ -249,66 +247,45 @@
devices
etc/dacf.conf
etc/dat
- etc/default/dhcpagent
- etc/default/inetinit
- etc/default/ipsec
etc/default/metassist.xml
- etc/default/mpathd
etc/default/power
etc/flash/postdeployment/svm.cleanup
etc/flash/predeployment/svm.save
- etc/inet/datemsk.ndpd
- etc/inet/ike
etc/inet/ipqosconf.1.sample
etc/inet/ipqosconf.2.sample
etc/inet/ipqosconf.3.sample
- etc/inet/ipsecalgs
- etc/inet/ipsecinit.sample
- etc/inet/mipagent.conf-sample
- etc/inet/mipagent.conf.fa-sample
- etc/inet/mipagent.conf.ha-sample
- etc/inet/secret
etc/inet/sock2path
etc/init.d/devlinks
etc/init.d/dodatadm.udaplt
etc/init.d/drvconfig
etc/init.d/llc2
- etc/init.d/mipagent
etc/init.d/ncakmod
etc/init.d/ncalogd
etc/init.d/pcmcia
etc/init.d/pppd
etc/init.d/wrsmcfg
- etc/ipf
etc/llc2
etc/lvm
etc/nca
etc/openwin
etc/ppp
- etc/rc0.d/K06mipagent
etc/rc0.d/K34ncalogd
etc/rc0.d/K50pppd
etc/rc0.d/K52llc2
- etc/rc1.d/K06mipagent
etc/rc1.d/K34ncalogd
etc/rc1.d/K50pppd
etc/rc1.d/K52llc2
- etc/rc2.d/K06mipagent
etc/rc2.d/S40llc2
etc/rc2.d/S42ncakmod
etc/rc2.d/S47pppd
etc/rc2.d/S81dodatadm.udaplt
etc/rc2.d/S94ncalogd
- etc/rc3.d/S80mipagent
- etc/rcS.d/K06mipagent
etc/rcS.d/K34ncalogd
etc/rcS.d/K44wrsmcfg
etc/rcS.d/K50pppd
etc/rcS.d/K52llc2
etc/rcS.d/S29wrsmcfg
etc/rcm
- etc/snmp/conf/mipagent.acl
- etc/snmp/conf/mipagent.reg
etc/sock2path
etc/usb
etc/wrsm
@@ -316,7 +293,6 @@
kernel
lib/libmeta.so
lib/libmeta.so.1
- lib/svc/method/ipfilter
lib/svc/method/sf880dr
lib/svc/method/svc-cvcd
lib/svc/method/svc-dcs
@@ -354,18 +330,11 @@
platform/sun4u/wanboot
platform/sun4v/ufsboot
platform/sun4v/wanboot
- sbin/dladm
sbin/metadb
sbin/metadevadm
sbin/metainit
sbin/metarecover
sbin/metastat
- usr/include/netinet/ip_compat.h
- usr/include/netinet/ip_fil.h
- usr/include/netinet/ip_nat.h
- usr/include/netinet/ip_proxy.h
- usr/include/netinet/ip_state.h
- usr/include/netinet/ipl.h
usr/include/sys/dcam
usr/lib/devfsadm/linkmod/SUNW_dcam1394_link.so
usr/lib/ldoms
@@ -375,9 +344,7 @@
usr/platform/SUNW,SPARC-Enterprise/lib/llib-ldscp.ln
usr/platform/SUNW,SPARC-Enterprise/sbin/prtdscp
var/adm/pool
- var/db/ipf
var/log/pool
- var/svc/manifest/network/ipfilter.xml
var/svc/manifest/network/rpc/mdcomm.xml
var/svc/manifest/network/rpc/meta.xml
var/svc/manifest/network/rpc/metamed.xml
diff --git a/usr/src/uts/Makefile b/usr/src/uts/Makefile
index a3a6e1a..7ed3239 100644
--- a/usr/src/uts/Makefile
+++ b/usr/src/uts/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -48,6 +47,7 @@
lint := TARGET= lint
clean.lint := TARGET= clean.lint
check := TARGET= check
+sis_check := TARGET= sis_check
modlist := TARGET= modlist
modlist := NO_STATE= -K $$MODSTATE$$$$
@@ -95,7 +95,19 @@
COMMON_HDRDIRS= common/des common/fs common/gssapi common/inet common/net \
common/netinet common/nfs common/rpc common/sys common/vm \
common/c2 common/pcmcia/sys common/rpcsvc common/inet/kssl \
- common/inet/nca common/ipp
+ common/inet/nca common/inet/ipf/netinet common/ipp
+
+#
+# Kernel modules which support the sis_check target for symbol checking
+#
+i386_SIS_MODULES= intel/arp intel/hook intel/icmp intel/ip intel/ipf \
+ intel/ipsecah intel/ipsecesp intel/keysock intel/neti \
+ intel/rts intel/spdsock intel/tun
+sparc_SIS_MODULES= sparc/arp sparc/hook sparc/icmp sparc/ip sparc/ipf \
+ sparc/ipsecah sparc/ipsecesp sparc/keysock sparc/neti \
+ sparc/rts sparc/spdsock sparc/tun
+
+SIS_MODULES=$($(MACH)_SIS_MODULES)
# These aren't the only headers in closed. But the other directories
# are simple enough that they can be driven from the src tree.
@@ -119,6 +131,12 @@
@cd common/rpcsvc; pwd; $(MAKE) $@
@cd common/gssapi; pwd; $(MAKE) $@
+# run stack instances global symbol checking to make sure
+# you do intend to add a global variable
+sis_check: $(SIS_MODULES)
+$(SIS_MODULES): FRC
+ cd $@; pwd; $(MAKE) $(TARGET)
+
ONC_FILES= common/io/timod.c \
common/os/sig.c \
common/os/flock.c \
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 927ded7..a78f4e9 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -198,6 +198,7 @@
nbmlock.o \
ndifm.o \
nice.o \
+ netstack.o \
ntptime.o \
nvpair.o \
nvpair_alloc_system.o \
diff --git a/usr/src/uts/common/inet/Makefile b/usr/src/uts/common/inet/Makefile
index 8f6c111..4a2141e 100644
--- a/usr/src/uts/common/inet/Makefile
+++ b/usr/src/uts/common/inet/Makefile
@@ -21,7 +21,7 @@
#
# ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# uts/common/inet/Makefile
@@ -33,8 +33,8 @@
ipsecesp.h ipsec_info.h ip6_asp.h ip_if.h ip_ire.h ip_multi.h \
ip_netinfo.h ip_ndp.h ip_rts.h ipsec_impl.h keysock.h led.h mi.h \
mib2.h nd.h optcom.h sadb.h sctp_itf.h snmpcom.h tcp.h tcp_sack.h \
- tun.h udp_impl.h rawip_impl.h ipp_common.h ip_ftable.h ip_impl.h \
- tcp_impl.h wifi_ioctl.h
+ tcp_stack.h tun.h udp_impl.h rawip_impl.h ipp_common.h ip_ftable.h \
+ ip_impl.h tcp_impl.h wifi_ioctl.h ip_stack.h
ROOTDIRS= $(ROOT)/usr/include/inet
diff --git a/usr/src/uts/common/inet/arp/arp.c b/usr/src/uts/common/inet/arp/arp.c
index 92f98a3..9677c55 100644
--- a/usr/src/uts/common/inet/arp/arp.c
+++ b/usr/src/uts/common/inet/arp/arp.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -45,6 +45,7 @@
#include <sys/vtrace.h>
#include <sys/strsun.h>
#include <sys/policy.h>
+#include <sys/zone.h>
#include <sys/ethernet.h>
#include <sys/zone.h>
#include <sys/random.h>
@@ -132,10 +133,6 @@
(mp->b_prev != AR_DRAINING && (arl->arl_queue != NULL || \
arl->arl_dlpi_pending != DL_PRIM_INVAL))
-#define ACE_EXTERNAL_FLAGS_MASK \
- (ACE_F_PERMANENT | ACE_F_PUBLISH | ACE_F_MAPPING | ACE_F_MYADDR | \
- ACE_F_AUTHORITY)
-
#define ARH_FIXED_LEN 8
/*
@@ -149,21 +146,11 @@
uint32_t ar_mac_hw_addr_length;
} ar_m_t;
-/* Named Dispatch Parameter Management Structure */
-typedef struct arpparam_s {
- uint32_t arp_param_min;
- uint32_t arp_param_max;
- uint32_t arp_param_value;
- char *arp_param_name;
-} arpparam_t;
-
typedef struct msg2_args {
mblk_t *m2a_mpdata;
mblk_t *m2a_mptail;
} msg2_args_t;
-extern ire_stats_t ire_stats_v4;
-
static mblk_t *ar_alloc(uint32_t cmd, int);
static int ar_ce_create(arl_t *arl, uint32_t proto, uchar_t *hw_addr,
uint32_t hw_addr_len, uchar_t *proto_addr,
@@ -172,23 +159,24 @@
uint32_t flags);
static void ar_ce_delete(ace_t *ace);
static void ar_ce_delete_per_arl(ace_t *ace, void *arg);
-static ace_t **ar_ce_hash(uint32_t proto, const uchar_t *proto_addr,
- uint32_t proto_addr_length);
+static ace_t **ar_ce_hash(arp_stack_t *as, uint32_t proto,
+ const uchar_t *proto_addr, uint32_t proto_addr_length);
static ace_t *ar_ce_lookup(arl_t *arl, uint32_t proto,
const uchar_t *proto_addr, uint32_t proto_addr_length);
static ace_t *ar_ce_lookup_entry(arl_t *arl, uint32_t proto,
const uchar_t *proto_addr, uint32_t proto_addr_length);
-static ace_t *ar_ce_lookup_from_area(mblk_t *mp, ace_t *matchfn());
+static ace_t *ar_ce_lookup_from_area(arp_stack_t *as, mblk_t *mp,
+ ace_t *matchfn());
static ace_t *ar_ce_lookup_mapping(arl_t *arl, uint32_t proto,
const uchar_t *proto_addr, uint32_t proto_addr_length);
static boolean_t ar_ce_resolve(ace_t *ace, const uchar_t *hw_addr,
uint32_t hw_addr_length);
-static void ar_ce_walk(void (*pfi)(ace_t *, void *), void *arg1);
+static void ar_ce_walk(arp_stack_t *as, void (*pfi)(ace_t *, void *),
+ void *arg1);
-static void ar_cleanup(void);
static void ar_client_notify(const arl_t *arl, mblk_t *mp, int code);
static int ar_close(queue_t *q);
-static int ar_cmd_dispatch(queue_t *q, mblk_t *mp);
+static int ar_cmd_dispatch(queue_t *q, mblk_t *mp, boolean_t from_wput);
static void ar_cmd_done(arl_t *arl);
static mblk_t *ar_dlpi_comm(t_uscalar_t prim, size_t size);
static void ar_dlpi_send(arl_t *, mblk_t *);
@@ -203,9 +191,9 @@
static int ar_interface_off(queue_t *q, mblk_t *mp);
static void ar_ll_cleanup_arl_queue(queue_t *q);
static void ar_ll_down(arl_t *arl);
-static arl_t *ar_ll_lookup_by_name(const char *name);
-static arl_t *ar_ll_lookup_from_mp(mblk_t *mp);
-static void ar_ll_init(ar_t *, mblk_t *mp);
+static arl_t *ar_ll_lookup_by_name(arp_stack_t *as, const char *name);
+static arl_t *ar_ll_lookup_from_mp(arp_stack_t *as, mblk_t *mp);
+static void ar_ll_init(arp_stack_t *, ar_t *, mblk_t *mp);
static void ar_ll_set_defaults(arl_t *, mblk_t *mp);
static void ar_ll_clear_defaults(arl_t *);
static int ar_ll_up(arl_t *arl);
@@ -216,13 +204,13 @@
static int ar_open(queue_t *q, dev_t *devp, int flag, int sflag,
cred_t *credp);
static int ar_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
-static boolean_t ar_param_register(arpparam_t *arppa, int cnt);
+static boolean_t ar_param_register(IDP *ndp, arpparam_t *arppa, int cnt);
static int ar_param_set(queue_t *q, mblk_t *mp, char *value,
caddr_t cp, cred_t *cr);
static void ar_query_delete(ace_t *ace, void *ar);
static void ar_query_reply(ace_t *ace, int ret_val,
uchar_t *proto_addr, uint32_t proto_addr_len);
-static clock_t ar_query_xmit(ace_t *ace, ace_t *src_ace);
+static clock_t ar_query_xmit(arp_stack_t *as, ace_t *ace, ace_t *src_ace);
static void ar_rput(queue_t *q, mblk_t *mp_orig);
static void ar_rput_dlpi(queue_t *q, mblk_t *mp);
static void ar_set_address(ace_t *ace, uchar_t *addrpos,
@@ -235,11 +223,14 @@
static void ar_wsrv(queue_t *q);
static void ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto,
uint32_t plen, const uchar_t *haddr1, const uchar_t *paddr1,
- const uchar_t *haddr2, const uchar_t *paddr2, const uchar_t *dstaddr);
+ const uchar_t *haddr2, const uchar_t *paddr2, const uchar_t *dstaddr,
+ arp_stack_t *as);
static void ar_cmd_enqueue(arl_t *arl, mblk_t *mp, queue_t *q,
ushort_t cmd, boolean_t);
static mblk_t *ar_cmd_dequeue(arl_t *arl);
+static void *arp_stack_init(netstackid_t stackid, netstack_t *ns);
+static void arp_stack_fini(netstackid_t stackid, void *arg);
/*
* All of these are alterable, within the min/max values given,
* at run time. arp_publish_interval and arp_publish_count are
@@ -264,20 +255,19 @@
{ 0, 3600000, 15000, "arp_broadcast_interval"},
{ 5, 86400, 3600, "arp_defend_period"}
};
-
-#define arp_cleanup_interval arp_param_arr[0].arp_param_value
-#define arp_publish_interval arp_param_arr[1].arp_param_value
-#define arp_publish_count arp_param_arr[2].arp_param_value
-#define arp_probe_delay arp_param_arr[3].arp_param_value
-#define arp_probe_interval arp_param_arr[4].arp_param_value
-#define arp_probe_count arp_param_arr[5].arp_param_value
-#define arp_fastprobe_delay arp_param_arr[6].arp_param_value
-#define arp_fastprobe_interval arp_param_arr[7].arp_param_value
-#define arp_fastprobe_count arp_param_arr[8].arp_param_value
-#define arp_defend_interval arp_param_arr[9].arp_param_value
-#define arp_defend_rate arp_param_arr[10].arp_param_value
-#define arp_broadcast_interval arp_param_arr[11].arp_param_value
-#define arp_defend_period arp_param_arr[12].arp_param_value
+#define as_cleanup_interval as_param_arr[0].arp_param_value
+#define as_publish_interval as_param_arr[1].arp_param_value
+#define as_publish_count as_param_arr[2].arp_param_value
+#define as_probe_delay as_param_arr[3].arp_param_value
+#define as_probe_interval as_param_arr[4].arp_param_value
+#define as_probe_count as_param_arr[5].arp_param_value
+#define as_fastprobe_delay as_param_arr[6].arp_param_value
+#define as_fastprobe_interval as_param_arr[7].arp_param_value
+#define as_fastprobe_count as_param_arr[8].arp_param_value
+#define as_defend_interval as_param_arr[9].arp_param_value
+#define as_defend_rate as_param_arr[10].arp_param_value
+#define as_broadcast_interval as_param_arr[11].arp_param_value
+#define as_defend_period as_param_arr[12].arp_param_value
static struct module_info info = {
0, "arp", 0, INFPSZ, 512, 128
@@ -295,18 +285,6 @@
&rinit, &winit
};
-static void *ar_g_head; /* AR Instance Data List Head */
-static caddr_t ar_g_nd; /* AR Named Dispatch Head */
-
-/*
- * With the introduction of netinfo (neti kernel module), it is now possible
- * to access data structures in the ARP module without the code being
- * executed in the context of the IP module, thus there is no locking being
- * enforced through the use of STREAMS.
- */
-krwlock_t arl_g_lock;
-arl_t *arl_g_head; /* ARL List Head */
-
/*
* TODO: we need a better mechanism to set the ARP hardware type since
* the DLPI mac type does not include enough predefined values.
@@ -322,14 +300,6 @@
{ DL_OTHER, ARPHRD_ETHER, -2, 6}, /* unknown */
};
-/* ARP Cache Entry Hash Table */
-static ace_t *ar_ce_hash_tbl[ARP_HASH_SIZE];
-
-static ace_t *ar_ce_mask_entries; /* proto_mask not all ones */
-
-static uint32_t arp_index_counter = 1;
-static uint32_t arp_counter_wrapped = 0;
-
/*
* Note that all routines which need to queue the message for later
* processing have to be ioctl_aware to be able to queue the complete message.
@@ -337,6 +307,7 @@
*/
#define ARF_IOCTL_AWARE 0x1 /* Arp command can come down as M_IOCTL */
#define ARF_ONLY_CMD 0x2 /* Command is exclusive to ARP */
+#define ARF_WPUT_OK 0x4 /* Command is allowed from ar_wput */
/* ARP Cmd Table entry */
typedef struct arct_s {
@@ -348,15 +319,22 @@
const char *arct_txt;
} arct_t;
+/*
+ * AR_ENTRY_ADD, QUERY and SQUERY are used by sdp, hence they need to
+ * have ARF_WPUT_OK set.
+ */
static arct_t ar_cmd_tbl[] = {
{ ar_entry_add, AR_ENTRY_ADD, sizeof (area_t),
- ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_CONFIG, "AR_ENTRY_ADD" },
+ ARF_IOCTL_AWARE | ARF_ONLY_CMD | ARF_WPUT_OK, OP_CONFIG,
+ "AR_ENTRY_ADD" },
{ ar_entry_delete, AR_ENTRY_DELETE, sizeof (ared_t),
ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_CONFIG, "AR_ENTRY_DELETE" },
{ ar_entry_query, AR_ENTRY_QUERY, sizeof (areq_t),
- ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_NP, "AR_ENTRY_QUERY" },
+ ARF_IOCTL_AWARE | ARF_ONLY_CMD | ARF_WPUT_OK, OP_NP,
+ "AR_ENTRY_QUERY" },
{ ar_entry_squery, AR_ENTRY_SQUERY, sizeof (area_t),
- ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_NP, "AR_ENTRY_SQUERY" },
+ ARF_IOCTL_AWARE | ARF_ONLY_CMD | ARF_WPUT_OK, OP_NP,
+ "AR_ENTRY_SQUERY" },
{ ar_mapping_add, AR_MAPPING_ADD, sizeof (arma_t),
ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_CONFIG, "AR_MAPPING_ADD" },
{ ar_interface_up, AR_INTERFACE_UP, sizeof (arc_t),
@@ -368,15 +346,16 @@
{ ar_interface_off, AR_INTERFACE_OFF, sizeof (arc_t),
ARF_ONLY_CMD, OP_CONFIG, "AR_INTERFACE_OFF" },
{ ar_set_ppa, (uint32_t)IF_UNITSEL, sizeof (int),
- ARF_IOCTL_AWARE, OP_CONFIG, "IF_UNITSEL" },
+ ARF_IOCTL_AWARE | ARF_WPUT_OK, OP_CONFIG, "IF_UNITSEL" },
{ ar_nd_ioctl, ND_GET, 1,
- ARF_IOCTL_AWARE, OP_NP, "ND_GET" },
+ ARF_IOCTL_AWARE | ARF_WPUT_OK, OP_NP, "ND_GET" },
{ ar_nd_ioctl, ND_SET, 1,
- ARF_IOCTL_AWARE, OP_CONFIG, "ND_SET" },
+ ARF_IOCTL_AWARE | ARF_WPUT_OK, OP_CONFIG, "ND_SET" },
{ ar_snmp_msg, AR_SNMP_MSG, sizeof (struct T_optmgmt_ack),
- ARF_IOCTL_AWARE | ARF_ONLY_CMD, OP_NP, "AR_SNMP_MSG" },
+ ARF_IOCTL_AWARE | ARF_WPUT_OK | ARF_ONLY_CMD, OP_NP,
+ "AR_SNMP_MSG" },
{ ar_slifname, (uint32_t)SIOCSLIFNAME, sizeof (struct lifreq),
- ARF_IOCTL_AWARE, OP_CONFIG, "SIOCSLIFNAME" }
+ ARF_IOCTL_AWARE | ARF_WPUT_OK, OP_CONFIG, "SIOCSLIFNAME" }
};
/*
@@ -394,6 +373,7 @@
ace_t **acep;
uchar_t *dst;
mblk_t *mp;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
arlphy_t *ap;
if ((flags & ~ACE_EXTERNAL_FLAGS_MASK) || arl == NULL)
@@ -491,13 +471,12 @@
}
ace->ace_flags = flags;
-
if (ar_mask_all_ones(ace->ace_proto_mask,
ace->ace_proto_addr_length)) {
- acep = ar_ce_hash(ace->ace_proto, ace->ace_proto_addr,
+ acep = ar_ce_hash(as, ace->ace_proto, ace->ace_proto_addr,
ace->ace_proto_addr_length);
} else {
- acep = &ar_ce_mask_entries;
+ acep = &as->as_ce_mask_entries;
}
if ((ace->ace_next = *acep) != NULL)
ace->ace_next->ace_ptpn = &ace->ace_next;
@@ -540,7 +519,7 @@
/* Cache entry hash routine, based on protocol and protocol address. */
static ace_t **
-ar_ce_hash(uint32_t proto, const uchar_t *proto_addr,
+ar_ce_hash(arp_stack_t *as, uint32_t proto, const uchar_t *proto_addr,
uint32_t proto_addr_length)
{
const uchar_t *up = proto_addr;
@@ -549,7 +528,7 @@
while (--len >= 0)
hval ^= *up++;
- return (&ar_ce_hash_tbl[hval % A_CNT(ar_ce_hash_tbl)]);
+ return (&as->as_ce_hash_tbl[hval % ARP_HASH_SIZE]);
}
/* Cache entry lookup. Try to find an ace matching the parameters passed. */
@@ -575,10 +554,11 @@
uint32_t proto_addr_length)
{
ace_t *ace;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
if (!proto_addr)
return (NULL);
- ace = *ar_ce_hash(proto, proto_addr, proto_addr_length);
+ ace = *ar_ce_hash(as, proto, proto_addr, proto_addr_length);
for (; ace; ace = ace->ace_next) {
if (ace->ace_arl == arl &&
ace->ace_proto_addr_length == proto_addr_length &&
@@ -604,7 +584,7 @@
* call the supplied match function.
*/
static ace_t *
-ar_ce_lookup_from_area(mblk_t *mp, ace_t *matchfn())
+ar_ce_lookup_from_area(arp_stack_t *as, mblk_t *mp, ace_t *matchfn())
{
uchar_t *proto_addr;
area_t *area = (area_t *)mp->b_rptr;
@@ -613,7 +593,7 @@
area->area_proto_addr_length);
if (!proto_addr)
return (NULL);
- return ((*matchfn)(ar_ll_lookup_from_mp(mp), area->area_proto,
+ return ((*matchfn)(ar_ll_lookup_from_mp(as, mp), area->area_proto,
proto_addr, area->area_proto_addr_length));
}
@@ -626,10 +606,11 @@
uint32_t proto_addr_length)
{
ace_t *ace;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
if (!proto_addr)
return (NULL);
- ace = ar_ce_mask_entries;
+ ace = as->as_ce_mask_entries;
for (; ace; ace = ace->ace_next) {
if (ace->ace_arl == arl &&
ace->ace_proto_addr_length == proto_addr_length &&
@@ -661,12 +642,12 @@
* mapping to avoid arp interpreting it as a duplicate.
*/
static ace_t *
-ar_ce_lookup_permanent(uint32_t proto, uchar_t *proto_addr,
+ar_ce_lookup_permanent(arp_stack_t *as, uint32_t proto, uchar_t *proto_addr,
uint32_t proto_addr_length)
{
ace_t *ace;
- ace = *ar_ce_hash(proto, proto_addr, proto_addr_length);
+ ace = *ar_ce_hash(as, proto, proto_addr, proto_addr_length);
for (; ace != NULL; ace = ace->ace_next) {
if (!(ace->ace_flags & ACE_F_PERMANENT))
continue;
@@ -771,8 +752,9 @@
uchar_t *ace_addr;
uchar_t *mask;
int retv = AR_NOTFOUND;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
- ace = *ar_ce_hash(proto, src_paddr, plen);
+ ace = *ar_ce_hash(as, proto, src_paddr, plen);
for (; ace != NULL; ace = ace_next) {
/* ar_ce_resolve may delete the ace; fetch next pointer now */
@@ -853,36 +835,28 @@
/* Pass arg1 to the pfi supplied, along with each ace in existence. */
static void
-ar_ce_walk(void (*pfi)(ace_t *, void *), void *arg1)
+ar_ce_walk(arp_stack_t *as, void (*pfi)(ace_t *, void *), void *arg1)
{
ace_t *ace;
ace_t *ace1;
- ace_t **acep;
+ int i;
- for (acep = ar_ce_hash_tbl; acep < A_END(ar_ce_hash_tbl); acep++) {
+ for (i = 0; i < ARP_HASH_SIZE; i++) {
/*
* We walk the hash chain in a way that allows the current
* ace to get blown off by the called routine.
*/
- for (ace = *acep; ace; ace = ace1) {
+ for (ace = as->as_ce_hash_tbl[i]; ace; ace = ace1) {
ace1 = ace->ace_next;
(*pfi)(ace, arg1);
}
}
- for (ace = ar_ce_mask_entries; ace; ace = ace1) {
+ for (ace = as->as_ce_mask_entries; ace; ace = ace1) {
ace1 = ace->ace_next;
(*pfi)(ace, arg1);
}
}
-/* Free the ND tables if the last ar has gone away. */
-static void
-ar_cleanup(void)
-{
- if (!ar_g_head)
- nd_free(&ar_g_nd);
-}
-
/*
* Send a copy of interesting packets to the corresponding IP instance.
* The corresponding IP instance is the ARP-IP-DEV instance for this
@@ -969,6 +943,7 @@
arc_t *arc;
mblk_t *mp1;
int index;
+ arp_stack_t *as = ar->ar_as;
TRACE_1(TR_FAC_ARP, TR_ARP_CLOSE,
"arp_close: q %p", q);
@@ -997,7 +972,7 @@
}
}
/* Delete all our pending queries, 'arl' is not dereferenced */
- ar_ce_walk(ar_query_delete, ar);
+ ar_ce_walk(as, ar_query_delete, ar);
/*
* The request could be pending on some arl_queue also. This
* happens if the arl is not yet bound, and bind is pending.
@@ -1021,11 +996,12 @@
* If this is the control stream for an arl, delete anything
* hanging off our arl.
*/
- ar_ce_walk(ar_ce_delete_per_arl, arl);
+ ar_ce_walk(as, ar_ce_delete_per_arl, arl);
/* Free any messages waiting for a bind_ack */
/* Get the arl out of the chain. */
- rw_enter(&arl_g_lock, RW_WRITER);
- for (arlp = &arl_g_head; *arlp; arlp = &(*arlp)->arl_next) {
+ rw_enter(&as->as_arl_g_lock, RW_WRITER);
+ for (arlp = &as->as_arl_head; *arlp;
+ arlp = &(*arlp)->arl_next) {
if (*arlp == arl) {
*arlp = arl->arl_next;
break;
@@ -1034,7 +1010,7 @@
ASSERT(arl->arl_dlpi_deferred == NULL);
ar->ar_arl = NULL;
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
mi_free((char *)arl);
}
@@ -1047,8 +1023,7 @@
}
cr = ar->ar_credp;
/* mi_close_comm frees the instance data. */
- (void) mi_close_comm(&ar_g_head, q);
- ar_cleanup();
+ (void) mi_close_comm(&as->as_head, q);
qprocsoff(q);
crfree(cr);
@@ -1060,8 +1035,10 @@
info.hne_event = NE_UNPLUMB;
info.hne_data = name;
info.hne_datalen = strlen(name);
- (void) hook_run(arpnicevents, (hook_data_t)&info);
+ (void) hook_run(as->as_arpnicevents, (hook_data_t)&info,
+ as->as_netstack);
}
+ netstack_rele(as->as_netstack);
return (0);
}
@@ -1071,7 +1048,7 @@
*/
/* TODO: error reporting for M_PROTO case */
static int
-ar_cmd_dispatch(queue_t *q, mblk_t *mp_orig)
+ar_cmd_dispatch(queue_t *q, mblk_t *mp_orig, boolean_t from_wput)
{
arct_t *arct;
uint32_t cmd;
@@ -1117,10 +1094,15 @@
if (cr == NULL)
cr = DB_CREDDEF(mp_orig, ((ar_t *)q->q_ptr)->ar_credp);
- if ((error = secpolicy_net(cr, arct->arct_priv_req,
+ if ((error = secpolicy_ip(cr, arct->arct_priv_req,
B_FALSE)) != 0)
return (error);
}
+ /* Disallow many commands except if from rput i.e. from IP */
+ if (from_wput && !(arct->arct_flags & ARF_WPUT_OK)) {
+ return (EINVAL);
+ }
+
if (arct->arct_flags & ARF_IOCTL_AWARE)
mp = mp_orig;
@@ -1436,11 +1418,12 @@
int err;
uint_t aflags;
boolean_t unverified;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
/* We handle both M_IOCTL and M_PROTO messages. */
if (DB_TYPE(mp) == M_IOCTL)
mp = mp->b_cont;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL)
return (EINVAL);
/*
@@ -1462,7 +1445,8 @@
* duplicate address detection state. If it's a new entry, then we're
* obligated to do duplicate address detection now.
*/
- if ((ace = ar_ce_lookup_from_area(mp, ar_ce_lookup_entry)) != NULL) {
+ ace = ar_ce_lookup_from_area(as, mp, ar_ce_lookup_entry);
+ if (ace != NULL) {
unverified = (ace->ace_flags & ACE_F_UNVERIFIED) != 0;
ar_ce_delete(ace);
} else {
@@ -1525,11 +1509,11 @@
ASSERT(ace != NULL);
if (ace->ace_flags & ACE_F_FAST) {
- ace->ace_xmit_count = arp_fastprobe_count;
- ace->ace_xmit_interval = arp_fastprobe_delay;
+ ace->ace_xmit_count = as->as_fastprobe_count;
+ ace->ace_xmit_interval = as->as_fastprobe_delay;
} else {
- ace->ace_xmit_count = arp_probe_count;
- ace->ace_xmit_interval = arp_probe_delay;
+ ace->ace_xmit_count = as->as_probe_count;
+ ace->ace_xmit_interval = as->as_probe_delay;
}
/*
@@ -1558,12 +1542,12 @@
area_t *, area);
ar_xmit(arl, ARP_REQUEST, area->area_proto,
proto_addr_len, hw_addr, NULL, NULL,
- proto_addr, NULL);
+ proto_addr, NULL, as);
ace->ace_xmit_count--;
ace->ace_xmit_interval =
(ace->ace_flags & ACE_F_FAST) ?
- arp_fastprobe_interval :
- arp_probe_interval;
+ as->as_fastprobe_interval :
+ as->as_probe_interval;
ace_set_timer(ace, B_FALSE);
} else {
DTRACE_PROBE2(eadd_delay, ace_t *, ace,
@@ -1576,7 +1560,7 @@
area_t *, area);
ar_xmit(arl, ARP_REQUEST, area->area_proto,
proto_addr_len, hw_addr, proto_addr,
- ap->ap_arp_addr, proto_addr, NULL);
+ ap->ap_arp_addr, proto_addr, NULL, as);
ace->ace_last_bcast = ddi_get_lbolt();
/*
@@ -1590,10 +1574,11 @@
*/
if ((aflags & ACE_F_AUTHORITY) &&
!(aflags & ACE_F_DEFEND) &&
- arp_publish_count > 0) {
+ as->as_publish_count > 0) {
/* Account for the xmit we just did */
- ace->ace_xmit_count = arp_publish_count - 1;
- ace->ace_xmit_interval = arp_publish_interval;
+ ace->ace_xmit_count = as->as_publish_count - 1;
+ ace->ace_xmit_interval =
+ as->as_publish_interval;
if (ace->ace_xmit_count > 0)
ace_set_timer(ace, B_FALSE);
}
@@ -1609,11 +1594,12 @@
ace_t *ace;
arl_t *arl;
mblk_t *mp = mp_orig;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
/* We handle both M_IOCTL and M_PROTO messages. */
if (DB_TYPE(mp) == M_IOCTL)
mp = mp->b_cont;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL)
return (EINVAL);
/*
@@ -1631,7 +1617,7 @@
* Need to know if it is a mapping or an exact match. Check exact
* match first.
*/
- ace = ar_ce_lookup_from_area(mp, ar_ce_lookup);
+ ace = ar_ce_lookup_from_area(as, mp, ar_ce_lookup);
if (ace != NULL) {
/*
* If it's a permanent entry, then the client is the one who
@@ -1667,13 +1653,14 @@
uint32_t proto_addr_len;
clock_t ms;
boolean_t is_mproto = B_TRUE;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
/* We handle both M_IOCTL and M_PROTO messages. */
if (DB_TYPE(mp) == M_IOCTL) {
is_mproto = B_FALSE;
mp = mp->b_cont;
}
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL) {
DTRACE_PROBE2(query_no_arl, queue_t *, q, mblk_t *, mp);
err = EINVAL;
@@ -1830,8 +1817,8 @@
* search the other arl for a resolved ACE. If we find one,
* we resolve it rather than sending out a ARP request.
*/
- src_ace = ar_ce_lookup_permanent(areq->areq_proto, sender_addr,
- areq->areq_sender_addr_length);
+ src_ace = ar_ce_lookup_permanent(as, areq->areq_proto,
+ sender_addr, areq->areq_sender_addr_length);
if (src_ace == NULL) {
DTRACE_PROBE3(query_source_missing, arl_t *, arl,
areq_t *, areq, ace_t *, ace);
@@ -1861,7 +1848,7 @@
}
}
}
- ms = ar_query_xmit(ace, src_ace);
+ ms = ar_query_xmit(as, ace, src_ace);
if (ms == 0) {
/* Immediate reply requested. */
ar_query_reply(ace, ENXIO, NULL, (uint32_t)0);
@@ -1870,8 +1857,11 @@
}
return (EINPROGRESS);
err_ret:
- if (is_mproto)
- BUMP_IRE_STATS(ire_stats_v4, ire_stats_freed);
+ if (is_mproto) {
+ ip_stack_t *ipst = as->as_netstack->netstack_ip;
+
+ BUMP_IRE_STATS(ipst->ips_ire_stats_v4, ire_stats_freed);
+ }
return (err);
}
@@ -1887,10 +1877,11 @@
mblk_t *mp = mp_orig;
uchar_t *proto_addr;
int proto_addr_len;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
if (DB_TYPE(mp) == M_IOCTL)
mp = mp->b_cont;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL)
return (EINVAL);
/*
@@ -1952,8 +1943,9 @@
ar_interface_down(queue_t *q, mblk_t *mp)
{
arl_t *arl;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL || arl->arl_closing) {
DTRACE_PROBE2(down_no_arl, queue_t *, q, mblk_t *, mp);
return (EINVAL);
@@ -1987,7 +1979,7 @@
ASSERT(arl->arl_state == ARL_S_UP);
/* Free all arp entries for this interface */
- ar_ce_walk(ar_ce_delete_per_arl, arl);
+ ar_ce_walk(as, ar_ce_delete_per_arl, arl);
ar_ll_down(arl);
/* Return EINPROGRESS so that ar_rput does not free the 'mp' */
@@ -2003,8 +1995,9 @@
arl_t *arl;
int err;
mblk_t *mp1;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL || arl->arl_closing) {
DTRACE_PROBE2(up_no_arl, queue_t *, q, mblk_t *, mp);
err = EINVAL;
@@ -2063,8 +2056,9 @@
ar_interface_on(queue_t *q, mblk_t *mp)
{
arl_t *arl;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL) {
DTRACE_PROBE2(on_no_arl, queue_t *, q, mblk_t *, mp);
return (EINVAL);
@@ -2084,8 +2078,9 @@
ar_interface_off(queue_t *q, mblk_t *mp)
{
arl_t *arl;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL) {
DTRACE_PROBE2(off_no_arl, queue_t *, q, mblk_t *, mp);
return (EINVAL);
@@ -2108,8 +2103,10 @@
mblk_t *mp;
mblk_t *mpnext;
mblk_t *prev;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
+ ip_stack_t *ipst = as->as_netstack->netstack_ip;
- for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+ for (arl = as->as_arl_head; arl != NULL; arl = arl->arl_next) {
for (prev = NULL, mp = arl->arl_queue; mp != NULL;
mp = mpnext) {
mpnext = mp->b_next;
@@ -2123,7 +2120,7 @@
arl->arl_queue_tail = prev;
if (DB_TYPE(mp) == M_PROTO &&
*(uint32_t *)mp->b_rptr == AR_ENTRY_QUERY) {
- BUMP_IRE_STATS(ire_stats_v4,
+ BUMP_IRE_STATS(ipst->ips_ire_stats_v4,
ire_stats_freed);
}
inet_freemsg(mp);
@@ -2138,11 +2135,11 @@
* Look up a lower level tap by name.
*/
static arl_t *
-ar_ll_lookup_by_name(const char *name)
+ar_ll_lookup_by_name(arp_stack_t *as, const char *name)
{
arl_t *arl;
- for (arl = arl_g_head; arl; arl = arl->arl_next) {
+ for (arl = as->as_arl_head; arl; arl = arl->arl_next) {
if (strcmp(arl->arl_name, name) == 0) {
return (arl);
}
@@ -2155,7 +2152,7 @@
* portion of the ARP command.
*/
static arl_t *
-ar_ll_lookup_from_mp(mblk_t *mp)
+ar_ll_lookup_from_mp(arp_stack_t *as, mblk_t *mp)
{
arc_t *arc = (arc_t *)mp->b_rptr;
uint8_t *name;
@@ -2164,11 +2161,11 @@
name = mi_offset_param(mp, arc->arc_name_offset, namelen);
if (name == NULL || name[namelen - 1] != '\0')
return (NULL);
- return (ar_ll_lookup_by_name((char *)name));
+ return (ar_ll_lookup_by_name(as, (char *)name));
}
static void
-ar_ll_init(ar_t *ar, mblk_t *mp)
+ar_ll_init(arp_stack_t *as, ar_t *ar, mblk_t *mp)
{
arl_t *arl;
dl_info_ack_t *dlia = (dl_info_ack_t *)mp->b_rptr;
@@ -2200,27 +2197,29 @@
* second of every day (non-leap year) for it to wrap around and the
* for() loop below to kick in as a performance concern.
*/
- if (arp_counter_wrapped) {
- arl_t *as;
+ if (as->as_arp_counter_wrapped) {
+ arl_t *arl1;
do {
- for (as = arl_g_head; as != NULL; as = as->arl_next)
- if (as->arl_index == arp_index_counter) {
- arp_index_counter++;
- if (arp_index_counter == 0) {
- arp_counter_wrapped++;
- arp_index_counter = 1;
+ for (arl1 = as->as_arl_g_head; arl1 != NULL;
+ arl1 = arl1->arl_next)
+ if (arl1->arl_index ==
+ as->as_arp_index_counter) {
+ as->as_arp_index_counter++;
+ if (as->as_arp_index_counter == 0) {
+ as->as_arp_counter_wrapped++;
+ as->as_arp_index_counter = 1;
}
break;
}
- } while (as != NULL);
+ } while (arl1 != NULL);
} else {
- arl->arl_index = arp_index_counter;
+ arl->arl_index = as->as_arp_index_counter;
}
- arp_index_counter++;
- if (arp_index_counter == 0) {
- arp_counter_wrapped++;
- arp_index_counter = 1;
+ as->as_arp_index_counter++;
+ if (as->as_arp_index_counter == 0) {
+ as->as_arp_counter_wrapped++;
+ as->as_arp_index_counter = 1;
}
}
@@ -2454,11 +2453,12 @@
uchar_t *proto_extract_mask;
uint32_t hw_extract_start;
arl_t *arl;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
/* We handle both M_IOCTL and M_PROTO messages. */
if (DB_TYPE(mp) == M_IOCTL)
mp = mp->b_cont;
- arl = ar_ll_lookup_from_mp(mp);
+ arl = ar_ll_lookup_from_mp(as, mp);
if (arl == NULL)
return (EINVAL);
/*
@@ -2473,7 +2473,8 @@
mp_orig->b_prev = NULL;
arma = (arma_t *)mp->b_rptr;
- if ((ace = ar_ce_lookup_from_area(mp, ar_ce_lookup_mapping)) != NULL)
+ ace = ar_ce_lookup_from_area(as, mp, ar_ce_lookup_mapping);
+ if (ace != NULL)
ar_ce_delete(ace);
hw_addr_len = arma->arma_hw_addr_length;
hw_addr = mi_offset_paramc(mp, arma->arma_hw_addr_offset, hw_addr_len);
@@ -2533,7 +2534,10 @@
static int
ar_nd_ioctl(queue_t *q, mblk_t *mp)
{
- if (DB_TYPE(mp) == M_IOCTL && nd_getset(q, ar_g_nd, mp))
+ ar_t *ar = (ar_t *)q->q_ptr;
+ arp_stack_t *as = ar->ar_as;
+
+ if (DB_TYPE(mp) == M_IOCTL && nd_getset(q, as->as_nd, mp))
return (0);
return (ENOENT);
}
@@ -2546,6 +2550,8 @@
int err;
queue_t *tmp_q;
mblk_t *mp;
+ netstack_t *ns;
+ arp_stack_t *as;
TRACE_1(TR_FAC_ARP, TR_ARP_OPEN,
"arp_open: q %p", q);
@@ -2553,17 +2559,17 @@
if (q->q_ptr != NULL) {
return (0);
}
- /* Load up the Named Dispatch tables, if not already done. */
- if (ar_g_nd == NULL &&
- !ar_param_register(arp_param_arr, A_CNT(arp_param_arr))) {
- ar_cleanup();
- return (ENOMEM);
- }
+
+ ns = netstack_find_by_cred(credp);
+ ASSERT(ns != NULL);
+ as = ns->netstack_arp;
+ ASSERT(as != NULL);
+
/* mi_open_comm allocates the instance data structure, etc. */
- err = mi_open_comm(&ar_g_head, sizeof (ar_t), q, devp, flag, sflag,
+ err = mi_open_comm(&as->as_head, sizeof (ar_t), q, devp, flag, sflag,
credp);
if (err) {
- ar_cleanup();
+ netstack_rele(as->as_netstack);
return (err);
}
@@ -2579,6 +2585,7 @@
ar->ar_wq = q;
crhold(credp);
ar->ar_credp = credp;
+ ar->ar_as = as;
/*
* Probe for the DLPI info if we are not pushed on IP. Wait for
@@ -2668,14 +2675,14 @@
* named dispatch handler.
*/
static boolean_t
-ar_param_register(arpparam_t *arppa, int cnt)
+ar_param_register(IDP *ndp, arpparam_t *arppa, int cnt)
{
for (; cnt-- > 0; arppa++) {
if (arppa->arp_param_name && arppa->arp_param_name[0]) {
- if (!nd_load(&ar_g_nd, arppa->arp_param_name,
+ if (!nd_load(ndp, arppa->arp_param_name,
ar_param_get, ar_param_set,
(caddr_t)arppa)) {
- nd_free(&ar_g_nd);
+ nd_free(ndp);
return (B_FALSE);
}
}
@@ -2715,7 +2722,8 @@
char *name;
mblk_t *muxmp;
mblk_t *mp1;
- ar_t *ar;
+ ar_t *ar = (ar_t *)q->q_ptr;
+ arp_stack_t *as = ar->ar_as;
struct linkblk *li;
struct ipmx_s *ipmxp;
queue_t *arpwq;
@@ -2764,8 +2772,8 @@
* for use by IP. IP will send the M_IOCACK.
*/
if (arpwq != NULL) {
- for (ar = (ar_t *)mi_first_ptr(&ar_g_head); ar != NULL;
- ar = (ar_t *)mi_next_ptr(&ar_g_head, (void *)ar)) {
+ for (ar = (ar_t *)mi_first_ptr(&as->as_head); ar != NULL;
+ ar = (ar_t *)mi_next_ptr(&as->as_head, (void *)ar)) {
if ((ar->ar_wq == arpwq) && (ar->ar_arl != NULL)) {
ipmxp->ipmx_arpdev_stream = 1;
(void) strcpy((char *)ipmxp->ipmx_name,
@@ -2789,6 +2797,8 @@
ar_t *ar = arg;
mblk_t **mpp = &ace->ace_query_mp;
mblk_t *mp;
+ arp_stack_t *as = ar->ar_as;
+ ip_stack_t *ipst = as->as_netstack->netstack_ip;
while ((mp = *mpp) != NULL) {
/* The response queue was stored in the query b_prev. */
@@ -2797,7 +2807,8 @@
*mpp = mp->b_next;
if (DB_TYPE(mp) == M_PROTO &&
*(uint32_t *)mp->b_rptr == AR_ENTRY_QUERY) {
- BUMP_IRE_STATS(ire_stats_v4, ire_stats_freed);
+ BUMP_IRE_STATS(ipst->ips_ire_stats_v4,
+ ire_stats_freed);
}
inet_freemsg(mp);
} else {
@@ -2822,6 +2833,8 @@
arl_t *arl = ace->ace_arl;
mblk_t *mp;
mblk_t *xmit_mp;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
+ ip_stack_t *ipst = as->as_netstack->netstack_ip;
arlphy_t *ap = arl->arl_phy;
/* Cancel any outstanding timer. */
@@ -2870,7 +2883,8 @@
if (ret_val != 0) {
/* TODO: find some way to let the guy know? */
inet_freemsg(mp);
- BUMP_IRE_STATS(ire_stats_v4, ire_stats_freed);
+ BUMP_IRE_STATS(ipst->ips_ire_stats_v4,
+ ire_stats_freed);
continue;
}
/*
@@ -2928,7 +2942,7 @@
ar_ce_delete(ace);
} else {
mi_timer(arl->arl_wq, ace->ace_mp,
- arp_cleanup_interval);
+ as->as_cleanup_interval);
}
}
}
@@ -2939,7 +2953,7 @@
* to the source address in the areq sent by IP.
*/
static clock_t
-ar_query_xmit(ace_t *ace, ace_t *src_ace)
+ar_query_xmit(arp_stack_t *as, ace_t *ace, ace_t *src_ace)
{
areq_t *areq;
mblk_t *mp;
@@ -2967,8 +2981,8 @@
* interface.
*/
if (src_ace == NULL) {
- src_ace = ar_ce_lookup_permanent(areq->areq_proto, sender_addr,
- areq->areq_sender_addr_length);
+ src_ace = ar_ce_lookup_permanent(as, areq->areq_proto,
+ sender_addr, areq->areq_sender_addr_length);
if (src_ace == NULL) {
DTRACE_PROBE3(xmit_no_source, ace_t *, ace,
areq_t *, areq, uchar_t *, sender_addr);
@@ -3001,7 +3015,7 @@
areq_t *, areq);
ar_xmit(src_arl, ARP_REQUEST, areq->areq_proto,
areq->areq_sender_addr_length, src_arl->arl_phy->ap_hw_addr,
- sender_addr, src_arl->arl_phy->ap_arp_addr, proto_addr, NULL);
+ sender_addr, src_arl->arl_phy->ap_arp_addr, proto_addr, NULL, as);
src_ace->ace_last_bcast = ddi_get_lbolt();
return (areq->areq_xmit_interval);
}
@@ -3025,6 +3039,7 @@
uchar_t *src_paddr;
boolean_t is_probe;
int i;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
TRACE_1(TR_FAC_ARP, TR_ARP_RPUT_START,
"arp_rput_start: q %p", q);
@@ -3036,7 +3051,7 @@
*/
switch (DB_TYPE(mp)) {
case M_IOCTL:
- err = ar_cmd_dispatch(q, mp);
+ err = ar_cmd_dispatch(q, mp, B_FALSE);
switch (err) {
case ENOENT:
DB_TYPE(mp) = M_IOCNAK;
@@ -3092,7 +3107,7 @@
"arp_rput_end: q %p (%S)", q, "default");
return;
}
- err = ar_cmd_dispatch(q, mp);
+ err = ar_cmd_dispatch(q, mp, B_FALSE);
switch (err) {
case ENOENT:
/* Miscellaneous DLPI messages get shuffled off. */
@@ -3179,8 +3194,8 @@
DTRACE_PROBE3(arp__physical__in__start,
arl_t *, arl, arh_t *, arh, mblk_t *, mp);
- ARP_HOOK_IN(arp_physical_in_event, arp_physical_in,
- arl->arl_index, arh, mp, mp1);
+ ARP_HOOK_IN(as->as_arp_physical_in_event, as->as_arp_physical_in,
+ arl->arl_index, arh, mp, mp1, as);
DTRACE_PROBE1(arp__physical__in__end, mblk_t *, mp);
@@ -3318,7 +3333,7 @@
*/
now = ddi_get_lbolt();
if ((now - dst_ace->ace_last_bcast) >
- MSEC_TO_TICK(arp_broadcast_interval)) {
+ MSEC_TO_TICK(as->as_broadcast_interval)) {
DTRACE_PROBE3(rput_bcast_reply, arl_t *, arl,
arh_t *, arh, ace_t *, dst_ace);
dst_ace->ace_last_bcast = now;
@@ -3334,7 +3349,7 @@
ar_xmit(arl, ARP_RESPONSE, dst_ace->ace_proto, plen,
dst_ace->ace_hw_addr, dst_ace->ace_proto_addr,
- src_haddr, src_paddr, dstaddr);
+ src_haddr, src_paddr, dstaddr, as);
if (!is_probe && err == AR_NOTFOUND &&
ar_ce_create(arl, proto, src_haddr, hlen, src_paddr, plen,
NULL, NULL, 0, 0) == 0) {
@@ -3343,7 +3358,7 @@
ace = ar_ce_lookup(arl, proto, src_paddr, plen);
ASSERT(ace != NULL);
mi_timer(arl->arl_wq, ace->ace_mp,
- arp_cleanup_interval);
+ as->as_cleanup_interval);
}
}
if (err == AR_CHANGED) {
@@ -3359,8 +3374,11 @@
}
static void
-ar_ce_restart_dad(ace_t *ace, void *arl)
+ar_ce_restart_dad(ace_t *ace, void *arl_arg)
{
+ arl_t *arl = arl_arg;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
+
if ((ace->ace_arl == arl) &&
(ace->ace_flags & (ACE_F_UNVERIFIED|ACE_F_DAD_ABORTED)) ==
(ACE_F_UNVERIFIED|ACE_F_DAD_ABORTED)) {
@@ -3369,11 +3387,11 @@
* in this obscure case.
*/
if (ace->ace_flags & ACE_F_FAST) {
- ace->ace_xmit_count = arp_fastprobe_count;
- ace->ace_xmit_interval = arp_fastprobe_interval;
+ ace->ace_xmit_count = as->as_fastprobe_count;
+ ace->ace_xmit_interval = as->as_fastprobe_interval;
} else {
- ace->ace_xmit_count = arp_probe_count;
- ace->ace_xmit_interval = arp_probe_interval;
+ ace->ace_xmit_count = as->as_probe_count;
+ ace->ace_xmit_interval = as->as_probe_interval;
}
ace->ace_flags &= ~ACE_F_DAD_ABORTED;
ace_set_timer(ace, B_FALSE);
@@ -3389,6 +3407,7 @@
arlphy_t *ap = NULL;
union DL_primitives *dlp;
const char *err_str;
+ arp_stack_t *as = ar->ar_as;
if (arl != NULL)
ap = arl->arl_phy;
@@ -3451,7 +3470,7 @@
ar_ll_set_defaults(arl, mp);
ar_dlpi_done(arl, DL_INFO_REQ);
} else if (arl == NULL) {
- ar_ll_init(ar, mp);
+ ar_ll_init(as, ar, mp);
}
/* Kick off any awaiting messages */
qenable(WR(q));
@@ -3509,7 +3528,7 @@
switch (dlp->notify_ind.dl_notification) {
case DL_NOTE_LINK_UP:
ap->ap_link_down = B_FALSE;
- ar_ce_walk(ar_ce_restart_dad, arl);
+ ar_ce_walk(as, ar_ce_restart_dad, arl);
break;
case DL_NOTE_LINK_DOWN:
ap->ap_link_down = B_TRUE;
@@ -3570,6 +3589,7 @@
mblk_t *ioccpy;
struct iocblk *iocp;
hook_nic_event_t info;
+ arp_stack_t *as = ar->ar_as;
if (ar->ar_on_ill_stream) {
/*
@@ -3613,7 +3633,7 @@
/* Check whether the name is already in use. */
- old_arl = ar_ll_lookup_by_name(lifr->lifr_name);
+ old_arl = ar_ll_lookup_by_name(as, lifr->lifr_name);
if (old_arl != NULL) {
DTRACE_PROBE2(slifname_exists, arl_t *, arl, arl_t *, old_arl);
return (EEXIST);
@@ -3644,12 +3664,13 @@
info.hne_event = NE_PLUMB;
info.hne_data = arl->arl_name;
info.hne_datalen = strlen(arl->arl_name);
- (void) hook_run(arpnicevents, (hook_data_t)&info);
+ (void) hook_run(as->as_arpnicevents, (hook_data_t)&info,
+ as->as_netstack);
/* Chain in the new arl. */
- rw_enter(&arl_g_lock, RW_WRITER);
- arl->arl_next = arl_g_head;
- arl_g_head = arl;
+ rw_enter(&as->as_arl_g_lock, RW_WRITER);
+ arl->arl_next = as->as_arl_head;
+ as->as_arl_head = arl;
DTRACE_PROBE1(slifname_set, arl_t *, arl);
/*
@@ -3663,7 +3684,7 @@
iocp->ioc_count = msgsize(ioccpy->b_cont);
ioccpy->b_wptr = (uchar_t *)(iocp + 1);
putnext(arl->arl_wq, ioccpy);
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
return (0);
}
@@ -3677,6 +3698,7 @@
char *cp;
mblk_t *mp = mp_orig;
arl_t *old_arl;
+ arp_stack_t *as = ar->ar_as;
if (ar->ar_on_ill_stream) {
/*
@@ -3714,7 +3736,7 @@
ppa = *(int *)(mp->b_rptr);
(void) snprintf(arl->arl_name, sizeof (arl->arl_name), "%s%d", cp, ppa);
- old_arl = ar_ll_lookup_by_name(arl->arl_name);
+ old_arl = ar_ll_lookup_by_name(as, arl->arl_name);
if (old_arl != NULL) {
DTRACE_PROBE2(setppa_exists, arl_t *, arl, arl_t *, old_arl);
/* Make it a null string again */
@@ -3725,10 +3747,10 @@
arl->arl_ppa = ppa;
DTRACE_PROBE1(setppa_done, arl_t *, arl);
/* Chain in the new arl. */
- rw_enter(&arl_g_lock, RW_WRITER);
- arl->arl_next = arl_g_head;
- arl_g_head = arl;
- rw_exit(&arl_g_lock);
+ rw_enter(&as->as_arl_g_lock, RW_WRITER);
+ arl->arl_next = as->as_arl_head;
+ as->as_arl_head = arl;
+ rw_exit(&as->as_arl_g_lock);
return (0);
}
@@ -3739,6 +3761,7 @@
mblk_t *mpdata, *mp = mp_orig;
struct opthdr *optp;
msg2_args_t args;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
if (mp == NULL)
return (0);
@@ -3761,7 +3784,7 @@
args.m2a_mpdata = mpdata;
args.m2a_mptail = NULL;
- ar_ce_walk(ar_snmp_msg2, &args);
+ ar_ce_walk(as, ar_snmp_msg2, &args);
optp->len = msgdsize(mpdata);
}
putnext(q, mp_orig);
@@ -3828,7 +3851,7 @@
*/
switch (DB_TYPE(mp)) {
case M_IOCTL:
- switch (err = ar_cmd_dispatch(q, mp)) {
+ switch (err = ar_cmd_dispatch(q, mp, B_TRUE)) {
case ENOENT:
/*
* If it is an I_PLINK, process it. Otherwise
@@ -3913,7 +3936,7 @@
* Commands in the form of PROTO messages are handled very
* much the same as IOCTLs, but no response is returned.
*/
- switch (err = ar_cmd_dispatch(q, mp)) {
+ switch (err = ar_cmd_dispatch(q, mp, B_TRUE)) {
case ENOENT:
if (q->q_next) {
putnext(q, mp);
@@ -4041,23 +4064,24 @@
ace_resched_t art;
int i;
ace_t *ace;
+ arp_stack_t *as = ARL_TO_ARPSTACK(arl);
i = ap->ap_defend_count;
ap->ap_defend_count = 0;
/* If none could be sitting around, then don't reschedule */
- if (i < arp_defend_rate) {
+ if (i < as->as_defend_rate) {
DTRACE_PROBE1(reschedule_none, arl_t *, arl);
return;
}
art.art_arl = arl;
- while (ap->ap_defend_count < arp_defend_rate) {
+ while (ap->ap_defend_count < as->as_defend_rate) {
art.art_naces = 0;
- ar_ce_walk(ace_reschedule, &art);
+ ar_ce_walk(as, ace_reschedule, &art);
for (i = 0; i < art.art_naces; i++) {
ace = art.art_aces[i];
ace->ace_flags |= ACE_F_DELAYED;
ace_set_timer(ace, B_FALSE);
- if (++ap->ap_defend_count >= arp_defend_rate)
+ if (++ap->ap_defend_count >= as->as_defend_rate)
break;
}
if (art.art_naces < ACE_RESCHED_LIST_LEN)
@@ -4079,6 +4103,7 @@
arlphy_t *ap;
mblk_t *mp;
clock_t ms;
+ arp_stack_t *as = ((ar_t *)q->q_ptr)->ar_as;
TRACE_1(TR_FAC_ARP, TR_ARP_WSRV_START,
"arp_wsrv_start: q %p", q);
@@ -4115,15 +4140,16 @@
ace->ace_proto,
ace->ace_proto_addr_length,
ace->ace_hw_addr, NULL, NULL,
- ace->ace_proto_addr, NULL);
+ ace->ace_proto_addr, NULL, as);
ace_set_timer(ace, B_FALSE);
continue;
}
if (!arp_say_ready(ace))
continue;
DTRACE_PROBE1(timer_ready, ace_t *, ace);
- ace->ace_xmit_interval = arp_publish_interval;
- ace->ace_xmit_count = arp_publish_count;
+ ace->ace_xmit_interval =
+ as->as_publish_interval;
+ ace->ace_xmit_count = as->as_publish_count;
if (ace->ace_xmit_count == 0)
ace->ace_xmit_count++;
ace->ace_flags &= ~ACE_F_UNVERIFIED;
@@ -4137,9 +4163,9 @@
* them.
*/
now = ddi_get_lbolt();
- if (arp_defend_rate > 0 &&
+ if (as->as_defend_rate > 0 &&
now - ap->ap_defend_start >
- SEC_TO_TICK(arp_defend_period)) {
+ SEC_TO_TICK(as->as_defend_period)) {
ap->ap_defend_start = now;
arl_reschedule(arl);
}
@@ -4164,9 +4190,11 @@
DTRACE_PROBE1(timer_send_delayed,
ace_t *, ace);
ace->ace_flags &= ~ACE_F_DELAYED;
- } else if (arp_defend_rate > 0 &&
- (ap->ap_defend_count >= arp_defend_rate ||
- ++ap->ap_defend_count >= arp_defend_rate)) {
+ } else if (as->as_defend_rate > 0 &&
+ (ap->ap_defend_count >=
+ as->as_defend_rate ||
+ ++ap->ap_defend_count >=
+ as->as_defend_rate)) {
/*
* If we're no longer allowed to send
* unbidden defense messages, then just
@@ -4186,11 +4214,11 @@
ace->ace_hw_addr,
ace->ace_proto_addr,
ap->ap_arp_addr,
- ace->ace_proto_addr, NULL);
+ ace->ace_proto_addr, NULL, as);
ace->ace_last_bcast = now;
if (ace->ace_xmit_count == 0)
ace->ace_xmit_interval =
- arp_defend_interval;
+ as->as_defend_interval;
if (ace->ace_xmit_interval != 0)
ace_set_timer(ace, B_FALSE);
continue;
@@ -4206,10 +4234,10 @@
if (ACE_NONPERM(ace)) {
if (ace->ace_proto == IP_ARP_PROTO_TYPE &&
ndp_lookup_ipaddr(*(ipaddr_t *)
- ace->ace_proto_addr)) {
+ ace->ace_proto_addr, as->as_netstack)) {
ace->ace_flags |= ACE_F_OLD;
mi_timer(arl->arl_wq, ace->ace_mp,
- arp_cleanup_interval);
+ as->as_cleanup_interval);
} else {
ar_delete_notify(ace);
ar_ce_delete(ace);
@@ -4226,7 +4254,7 @@
* Otherwise, we restart the timer.
*/
ASSERT(ace->ace_query_mp != NULL);
- ms = ar_query_xmit(ace, NULL);
+ ms = ar_query_xmit(as, ace, NULL);
if (ms == 0)
ar_query_reply(ace, ENXIO, NULL, (uint32_t)0);
else
@@ -4245,7 +4273,7 @@
static void
ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen,
const uchar_t *haddr1, const uchar_t *paddr1, const uchar_t *haddr2,
- const uchar_t *paddr2, const uchar_t *dstaddr)
+ const uchar_t *paddr2, const uchar_t *dstaddr, arp_stack_t *as)
{
arh_t *arh;
uint8_t *cp;
@@ -4320,8 +4348,8 @@
DTRACE_PROBE3(arp__physical__out__start,
arl_t *, arl, arh_t *, arh, mblk_t *, mp);
- ARP_HOOK_OUT(arp_physical_out_event, arp_physical_out,
- arl->arl_index, arh, mp, mp->b_cont);
+ ARP_HOOK_OUT(as->as_arp_physical_out_event, as->as_arp_physical_out,
+ arl->arl_index, arh, mp, mp->b_cont, as);
DTRACE_PROBE1(arp__physical__out__end, mblk_t *, mp);
@@ -4370,3 +4398,69 @@
linkb(mp, mp1);
return (mp);
}
+
+void
+arp_ddi_init(void)
+{
+ /*
+ * We want to be informed each time a stack is created or
+ * destroyed in the kernel, so we can maintain the
+ * set of arp_stack_t's.
+ */
+ netstack_register(NS_ARP, arp_stack_init, NULL, arp_stack_fini);
+}
+
+void
+arp_ddi_destroy(void)
+{
+ netstack_unregister(NS_ARP);
+}
+
+/*
+ * Initialize the ARP stack instance.
+ */
+/* ARGSUSED */
+static void *
+arp_stack_init(netstackid_t stackid, netstack_t *ns)
+{
+ arp_stack_t *as;
+ arpparam_t *pa;
+
+ as = (arp_stack_t *)kmem_zalloc(sizeof (*as), KM_SLEEP);
+ as->as_netstack = ns;
+
+ pa = (arpparam_t *)kmem_alloc(sizeof (arp_param_arr), KM_SLEEP);
+ as->as_param_arr = pa;
+ bcopy(arp_param_arr, as->as_param_arr, sizeof (arp_param_arr));
+
+ (void) ar_param_register(&as->as_nd,
+ as->as_param_arr, A_CNT(arp_param_arr));
+
+ as->as_arp_index_counter = 1;
+ as->as_arp_counter_wrapped = 0;
+
+ rw_init(&as->as_arl_g_lock, "ARP ARl lock", RW_DRIVER, NULL);
+ arp_net_init(as, ns);
+ arp_hook_init(as);
+
+ return (as);
+}
+
+/*
+ * Free the ARP stack instance.
+ */
+/* ARGSUSED */
+static void
+arp_stack_fini(netstackid_t stackid, void *arg)
+{
+ arp_stack_t *as = (arp_stack_t *)arg;
+
+ arp_hook_destroy(as);
+ arp_net_destroy(as);
+ rw_destroy(&as->as_arl_g_lock);
+
+ nd_free(&as->as_nd);
+ kmem_free(as->as_param_arr, sizeof (arp_param_arr));
+ as->as_param_arr = NULL;
+ kmem_free(as, sizeof (*as));
+}
diff --git a/usr/src/uts/common/inet/arp/arp_netinfo.c b/usr/src/uts/common/inet/arp/arp_netinfo.c
index 0d2f55e..4869053 100644
--- a/usr/src/uts/common/inet/arp/arp_netinfo.c
+++ b/usr/src/uts/common/inet/arp/arp_netinfo.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,6 +33,7 @@
#include <sys/sunddi.h>
#include <sys/hook.h>
#include <sys/hook_impl.h>
+#include <sys/netstack.h>
#include <net/if.h>
#include <sys/neti.h>
@@ -42,16 +43,16 @@
/*
* ARP netinfo entry point declarations.
*/
-static int arp_getifname(phy_if_t, char *, const size_t);
-static int arp_getmtu(phy_if_t, lif_if_t);
-static int arp_getpmtuenabled(void);
+static int arp_getifname(phy_if_t, char *, const size_t, netstack_t *);
+static int arp_getmtu(phy_if_t, lif_if_t, netstack_t *);
+static int arp_getpmtuenabled(netstack_t *);
static int arp_getlifaddr(phy_if_t, lif_if_t, size_t,
- net_ifaddr_t [], void *);
-static phy_if_t arp_phygetnext(phy_if_t);
-static phy_if_t arp_phylookup(const char *);
-static lif_if_t arp_lifgetnext(phy_if_t, lif_if_t);
-static int arp_inject(inject_t, net_inject_t *);
-static phy_if_t arp_routeto(struct sockaddr *);
+ net_ifaddr_t [], void *, netstack_t *);
+static phy_if_t arp_phygetnext(phy_if_t, netstack_t *);
+static phy_if_t arp_phylookup(const char *, netstack_t *);
+static lif_if_t arp_lifgetnext(phy_if_t, lif_if_t, netstack_t *);
+static int arp_inject(inject_t, net_inject_t *, netstack_t *);
+static phy_if_t arp_routeto(struct sockaddr *, netstack_t *);
static int arp_ispartialchecksum(mblk_t *);
static int arp_isvalidchecksum(mblk_t *);
@@ -71,115 +72,109 @@
arp_isvalidchecksum
};
-static hook_family_t arproot;
-
-/*
- * Hooks for ARP
- */
-
-hook_event_t arp_physical_in_event;
-hook_event_t arp_physical_out_event;
-hook_event_t arp_nic_events;
-
-hook_event_token_t arp_physical_in;
-hook_event_token_t arp_physical_out;
-hook_event_token_t arpnicevents;
-
-net_data_t arp = NULL;
-
/*
* Register ARP netinfo functions.
*/
void
-arp_net_init()
+arp_net_init(arp_stack_t *as, netstack_t *ns)
{
- arp = net_register(&arp_netinfo);
- ASSERT(arp != NULL);
+ as->as_net_data = net_register_impl(&arp_netinfo, ns);
+ ASSERT(as->as_net_data != NULL);
}
/*
* Unregister ARP netinfo functions.
*/
void
-arp_net_destroy()
+arp_net_destroy(arp_stack_t *as)
{
- (void) net_unregister(arp);
+ (void) net_unregister(as->as_net_data);
}
/*
* Initialize ARP hook family and events
*/
void
-arp_hook_init()
+arp_hook_init(arp_stack_t *as)
{
- HOOK_FAMILY_INIT(&arproot, Hn_ARP);
- if (net_register_family(arp, &arproot) != 0) {
+ HOOK_FAMILY_INIT(&as->as_arproot, Hn_ARP);
+ if (net_register_family(as->as_net_data, &as->as_arproot) != 0) {
cmn_err(CE_NOTE, "arp_hook_init: "
"net_register_family failed for arp");
}
- HOOK_EVENT_INIT(&arp_physical_in_event, NH_PHYSICAL_IN);
- arp_physical_in = net_register_event(arp, &arp_physical_in_event);
- if (arp_physical_in == NULL) {
+ HOOK_EVENT_INIT(&as->as_arp_physical_in_event, NH_PHYSICAL_IN);
+ as->as_arp_physical_in = net_register_event(as->as_net_data,
+ &as->as_arp_physical_in_event);
+ if (as->as_arp_physical_in == NULL) {
cmn_err(CE_NOTE, "arp_hook_init: "
"net_register_event failed for arp/physical_in");
}
- HOOK_EVENT_INIT(&arp_physical_out_event, NH_PHYSICAL_OUT);
- arp_physical_out = net_register_event(arp, &arp_physical_out_event);
- if (arp_physical_out == NULL) {
+ HOOK_EVENT_INIT(&as->as_arp_physical_out_event, NH_PHYSICAL_OUT);
+ as->as_arp_physical_out = net_register_event(as->as_net_data,
+ &as->as_arp_physical_out_event);
+ if (as->as_arp_physical_out == NULL) {
cmn_err(CE_NOTE, "arp_hook_init: "
"net_register_event failed for arp/physical_out");
}
- HOOK_EVENT_INIT(&arp_nic_events, NH_NIC_EVENTS);
- arpnicevents = net_register_event(arp, &arp_nic_events);
- if (arpnicevents == NULL) {
+ HOOK_EVENT_INIT(&as->as_arp_nic_events, NH_NIC_EVENTS);
+ as->as_arpnicevents = net_register_event(as->as_net_data,
+ &as->as_arp_nic_events);
+ if (as->as_arpnicevents == NULL) {
cmn_err(CE_NOTE, "arp_hook_init: "
"net_register_event failed for arp/nic_events");
}
}
void
-arp_hook_destroy()
+arp_hook_destroy(arp_stack_t *as)
{
- if (arpnicevents != NULL) {
- if (net_unregister_event(arp, &arp_nic_events) == 0)
- arpnicevents = NULL;
+ if (as->as_arpnicevents != NULL) {
+ if (net_unregister_event(as->as_net_data,
+ &as->as_arp_nic_events) == 0)
+ as->as_arpnicevents = NULL;
}
- if (arp_physical_out != NULL) {
- if (net_unregister_event(arp, &arp_physical_out_event) == 0)
- arp_physical_out = NULL;
+ if (as->as_arp_physical_out != NULL) {
+ if (net_unregister_event(as->as_net_data,
+ &as->as_arp_physical_out_event) == 0)
+ as->as_arp_physical_out = NULL;
}
- if (arp_physical_in != NULL) {
- if (net_unregister_event(arp, &arp_physical_in_event) == 0)
- arp_physical_in = NULL;
+ if (as->as_arp_physical_in != NULL) {
+ if (net_unregister_event(as->as_net_data,
+ &as->as_arp_physical_in_event) == 0)
+ as->as_arp_physical_in = NULL;
}
- (void) net_unregister_family(arp, &arproot);
+ (void) net_unregister_family(as->as_net_data, &as->as_arproot);
}
/*
* Determine the name of the lower level interface
*/
-int
-arp_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen)
+static int
+arp_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen,
+ netstack_t *ns)
{
arl_t *arl;
+ arp_stack_t *as;
ASSERT(buffer != NULL);
+ ASSERT(ns != NULL);
- rw_enter(&arl_g_lock, RW_READER);
- for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+ as = ns->netstack_arp;
+ rw_enter(&as->as_arl_g_lock, RW_READER);
+ for (arl = as->as_arl_g_head; arl != NULL; arl = arl->arl_next) {
if (arl->arl_index == phy_ifdata) {
(void) strlcpy(buffer, arl->arl_name, buflen);
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
return (0);
}
}
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
return (1);
}
@@ -188,8 +183,8 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-int
-arp_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata)
+static int
+arp_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns)
{
return (-1);
}
@@ -198,8 +193,8 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-int
-arp_getpmtuenabled(void)
+static int
+arp_getpmtuenabled(netstack_t *ns)
{
return (-1);
}
@@ -208,9 +203,9 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-int
+static int
arp_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
- net_ifaddr_t type[], void *storage)
+ net_ifaddr_t type[], void *storage, netstack_t *ns)
{
return (-1);
}
@@ -218,17 +213,22 @@
/*
* Determine the instance number of the next lower level interface
*/
-phy_if_t
-arp_phygetnext(phy_if_t phy_ifdata)
+static phy_if_t
+arp_phygetnext(phy_if_t phy_ifdata, netstack_t *ns)
{
arl_t *arl;
int index;
+ arp_stack_t *as;
- rw_enter(&arl_g_lock, RW_READER);
+ ASSERT(ns != NULL);
+
+ as = ns->netstack_arp;
+ rw_enter(&as->as_arl_g_lock, RW_READER);
if (phy_ifdata == 0) {
- arl = arl_g_head;
+ arl = as->as_arl_g_head;
} else {
- for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+ for (arl = as->as_arl_g_head; arl != NULL;
+ arl = arl->arl_next) {
if (arl->arl_index == phy_ifdata) {
arl = arl->arl_next;
break;
@@ -238,7 +238,7 @@
index = (arl != NULL) ? arl->arl_index : 0;
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
return (index);
}
@@ -246,24 +246,26 @@
/*
* Given a network interface name, find its ARP layer instance number.
*/
-phy_if_t
-arp_phylookup(const char *name)
+static phy_if_t
+arp_phylookup(const char *name, netstack_t *ns)
{
arl_t *arl;
int index;
+ arp_stack_t *as;
ASSERT(name != NULL);
+ ASSERT(ns != NULL);
index = 0;
-
- rw_enter(&arl_g_lock, RW_READER);
- for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+ as = ns->netstack_arp;
+ rw_enter(&as->as_arl_g_lock, RW_READER);
+ for (arl = as->as_arl_g_head; arl != NULL; arl = arl->arl_next) {
if (strcmp(name, arl->arl_name) == 0) {
index = arl->arl_index;
break;
}
}
- rw_exit(&arl_g_lock);
+ rw_exit(&as->as_arl_g_lock);
return (index);
@@ -273,8 +275,8 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-lif_if_t
-arp_lifgetnext(phy_if_t ifp, lif_if_t lif)
+static lif_if_t
+arp_lifgetnext(phy_if_t ifp, lif_if_t lif, netstack_t *ns)
{
return ((lif_if_t)-1);
}
@@ -283,8 +285,8 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-int
-arp_inject(inject_t injection, net_inject_t *neti)
+static int
+arp_inject(inject_t injection, net_inject_t *neti, netstack_t *ns)
{
return (-1);
}
@@ -293,8 +295,8 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-phy_if_t
-arp_routeto(struct sockaddr *addr)
+static phy_if_t
+arp_routeto(struct sockaddr *addr, netstack_t *ns)
{
return ((phy_if_t)-1);
}
@@ -313,7 +315,7 @@
* Unsupported with ARP.
*/
/*ARGSUSED*/
-int
+static int
arp_isvalidchecksum(mblk_t *mb)
{
return (-1);
diff --git a/usr/src/uts/common/inet/arp/arpddi.c b/usr/src/uts/common/inet/arp/arpddi.c
index 5ca60b1..edd5cd4 100644
--- a/usr/src/uts/common/inet/arp/arpddi.c
+++ b/usr/src/uts/common/inet/arp/arpddi.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -42,29 +42,35 @@
#define INET_DEVMTFLAGS IP_DEVMTFLAGS /* since as a driver we're ip */
#define INET_MODMTFLAGS (D_MP | D_MTPERMOD)
-static void arp_ddi_destroy();
-static void arp_ddi_init();
-
#include "../inetddi.c"
+extern void arp_ddi_init(void);
+extern void arp_ddi_destroy(void);
+
int
_init(void)
{
- int error;
+ int error;
- arp_ddi_init();
INET_BECOME_IP();
+ /*
+ * Note: After mod_install succeeds, another thread can enter
+ * therefore all initialization is done before it and any
+ * de-initialization needed done if it fails.
+ */
+ arp_ddi_init();
error = mod_install(&modlinkage);
if (error != 0)
arp_ddi_destroy();
+
return (error);
}
int
_fini(void)
{
- int error;
+ int error;
error = mod_remove(&modlinkage);
if (error == 0)
@@ -77,21 +83,3 @@
{
return (mod_info(&modlinkage, modinfop));
}
-
-
-static void
-arp_ddi_init()
-{
- rw_init(&arl_g_lock, "ARP ARl lock", RW_DRIVER, NULL);
- arp_net_init();
- arp_hook_init();
-}
-
-
-static void
-arp_ddi_destroy()
-{
- arp_hook_destroy();
- arp_net_destroy();
- rw_destroy(&arl_g_lock);
-}
diff --git a/usr/src/uts/common/inet/arp_impl.h b/usr/src/uts/common/inet/arp_impl.h
index c6e12bc..567e2b8 100644
--- a/usr/src/uts/common/inet/arp_impl.h
+++ b/usr/src/uts/common/inet/arp_impl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,10 +37,19 @@
#include <sys/types.h>
#include <sys/stream.h>
#include <net/if.h>
+#include <sys/netstack.h>
/* ARP kernel hash size; used for mdb support */
#define ARP_HASH_SIZE 256
+/* Named Dispatch Parameter Management Structure */
+typedef struct arpparam_s {
+ uint32_t arp_param_min;
+ uint32_t arp_param_max;
+ uint32_t arp_param_value;
+ char *arp_param_name;
+} arpparam_t;
+
/* ARL Structure, one per link level device */
typedef struct arl_s {
struct arl_s *arl_next; /* ARL chain at arl_g_head */
@@ -62,6 +71,12 @@
struct arlphy_s *arl_phy; /* physical info, if any */
} arl_t;
+/*
+ * There is no field to get from an arl_t to an arp_stack_t, but this
+ * macro does it.
+ */
+#define ARL_TO_ARPSTACK(_arl) (((ar_t *)(_arl)->arl_rq->q_ptr)->ar_as)
+
/* ARL physical info structure for a link level device */
typedef struct arlphy_s {
uint32_t ap_arp_hw_type; /* hardware type */
@@ -78,27 +93,6 @@
ap_link_down : 1; /* DL_NOTE status */
} arlphy_t;
-extern arl_t *arl_g_head; /* ARL chain head */
-extern krwlock_t arl_g_lock;
-
-#define ARL_F_NOARP 0x01
-
-#define ARL_S_DOWN 0x00
-#define ARL_S_PENDING 0x01
-#define ARL_S_UP 0x02
-
-/* AR Structure, one per upper stream */
-typedef struct ar_s {
- queue_t *ar_rq; /* Read queue pointer */
- queue_t *ar_wq; /* Write queue pointer */
- arl_t *ar_arl; /* Associated arl */
- cred_t *ar_credp; /* Credentials associated w/ open */
- struct ar_s *ar_arl_ip_assoc; /* ARL - IP association */
- uint32_t
- ar_ip_acked_close : 1, /* IP has acked the close */
- ar_on_ill_stream : 1; /* Module below is IP */
-} ar_t;
-
/* ARP Cache Entry */
typedef struct ace_s {
struct ace_s *ace_next; /* Hash chain next pointer */
@@ -120,23 +114,12 @@
int ace_xmit_count;
} ace_t;
-/*
- * Hooks structures used inside of arp
- */
-extern hook_event_token_t arp_physical_in;
-extern hook_event_token_t arp_physical_out;
-extern hook_event_token_t arpnicevents;
+#define ARPHOOK_INTERESTED_PHYSICAL_IN(as) \
+ (as->as_arp_physical_in_event.he_interested)
+#define ARPHOOK_INTERESTED_PHYSICAL_OUT(as) \
+ (as->as_arp_physical_out_event.he_interested)
-extern hook_event_t arp_physical_in_event;
-extern hook_event_t arp_physical_out_event;
-extern hook_event_t arp_nic_events;
-
-#define ARPHOOK_INTERESTED_PHYSICAL_IN \
- (arp_physical_in_event.he_interested)
-#define ARPHOOK_INTERESTED_PHYSICAL_OUT \
- (arp_physical_out_event.he_interested)
-
-#define ARP_HOOK_IN(_hook, _event, _ilp, _hdr, _fm, _m) \
+#define ARP_HOOK_IN(_hook, _event, _ilp, _hdr, _fm, _m, as) \
\
if ((_hook).he_interested) { \
hook_pkt_event_t info; \
@@ -146,7 +129,8 @@
info.hpe_hdr = _hdr; \
info.hpe_mp = &(_fm); \
info.hpe_mb = _m; \
- if (hook_run(_event, (hook_data_t)&info) != 0) {\
+ if (hook_run(_event, (hook_data_t)&info, \
+ as->as_netstack) != 0) { \
if (_fm != NULL) { \
freemsg(_fm); \
_fm = NULL; \
@@ -159,7 +143,7 @@
} \
}
-#define ARP_HOOK_OUT(_hook, _event, _olp, _hdr, _fm, _m) \
+#define ARP_HOOK_OUT(_hook, _event, _olp, _hdr, _fm, _m, as) \
\
if ((_hook).he_interested) { \
hook_pkt_event_t info; \
@@ -169,8 +153,8 @@
info.hpe_hdr = _hdr; \
info.hpe_mp = &(_fm); \
info.hpe_mb = _m; \
- if (hook_run(_event, \
- (hook_data_t)&info) != 0) { \
+ if (hook_run(_event, (hook_data_t)&info, \
+ as->as_netstack) != 0) { \
if (_fm != NULL) { \
freemsg(_fm); \
_fm = NULL; \
@@ -183,10 +167,77 @@
} \
}
-extern void arp_hook_init();
-extern void arp_hook_destroy();
-extern void arp_net_init();
-extern void arp_net_destroy();
+#define ACE_EXTERNAL_FLAGS_MASK \
+ (ACE_F_PERMANENT | ACE_F_PUBLISH | ACE_F_MAPPING | ACE_F_MYADDR | \
+ ACE_F_AUTHORITY)
+
+/*
+ * ARP stack instances
+ */
+struct arp_stack {
+ netstack_t *as_netstack; /* Common netstack */
+ void *as_head; /* AR Instance Data List Head */
+ caddr_t as_nd; /* AR Named Dispatch Head */
+ struct arl_s *as_arl_head; /* ARL List Head */
+ arpparam_t *as_param_arr; /* ndd variable table */
+
+ /* ARP Cache Entry Hash Table */
+ ace_t *as_ce_hash_tbl[ARP_HASH_SIZE];
+ ace_t *as_ce_mask_entries;
+
+ /*
+ * With the introduction of netinfo (neti kernel module),
+ * it is now possible to access data structures in the ARP module
+ * without the code being executed in the context of the IP module,
+ * thus there is no locking being enforced through the use of STREAMS.
+ */
+ krwlock_t as_arl_g_lock;
+ arl_t *as_arl_g_head; /* ARL List Head */
+
+ uint32_t as_arp_index_counter;
+ uint32_t as_arp_counter_wrapped;
+
+ /* arp_neti.c */
+ hook_family_t as_arproot;
+
+ /*
+ * Hooks for ARP
+ */
+ hook_event_t as_arp_physical_in_event;
+ hook_event_t as_arp_physical_out_event;
+ hook_event_t as_arp_nic_events;
+
+ hook_event_token_t as_arp_physical_in;
+ hook_event_token_t as_arp_physical_out;
+ hook_event_token_t as_arpnicevents;
+
+ net_data_t as_net_data;
+};
+typedef struct arp_stack arp_stack_t;
+
+#define ARL_F_NOARP 0x01
+
+#define ARL_S_DOWN 0x00
+#define ARL_S_PENDING 0x01
+#define ARL_S_UP 0x02
+
+/* AR Structure, one per upper stream */
+typedef struct ar_s {
+ queue_t *ar_rq; /* Read queue pointer */
+ queue_t *ar_wq; /* Write queue pointer */
+ arl_t *ar_arl; /* Associated arl */
+ cred_t *ar_credp; /* Credentials associated w/ open */
+ struct ar_s *ar_arl_ip_assoc; /* ARL - IP association */
+ uint32_t
+ ar_ip_acked_close : 1, /* IP has acked the close */
+ ar_on_ill_stream : 1; /* Module below is IP */
+ arp_stack_t *ar_as;
+} ar_t;
+
+extern void arp_hook_init(arp_stack_t *);
+extern void arp_hook_destroy(arp_stack_t *);
+extern void arp_net_init(arp_stack_t *, netstack_t *);
+extern void arp_net_destroy(arp_stack_t *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/inet/inetddi.c b/usr/src/uts/common/inet/inetddi.c
index 476de3d..e6a0395 100644
--- a/usr/src/uts/common/inet/inetddi.c
+++ b/usr/src/uts/common/inet/inetddi.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -98,10 +97,10 @@
{"icmp6", PRIVONLY_DEV, PRIV_NET_ICMPACCESS, PRIV_NET_ICMPACCESS},
{"ip", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS},
{"ip6", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS},
- {"keysock", PRIVONLY_DEV, PRIV_SYS_NET_CONFIG, PRIV_SYS_NET_CONFIG},
- {"ipsecah", PRIVONLY_DEV, PRIV_SYS_NET_CONFIG, PRIV_SYS_NET_CONFIG},
- {"ipsecesp", PRIVONLY_DEV, PRIV_SYS_NET_CONFIG, PRIV_SYS_NET_CONFIG},
- {"spdsock", PRIVONLY_DEV, PRIV_SYS_NET_CONFIG, PRIV_SYS_NET_CONFIG},
+ {"keysock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG},
+ {"ipsecah", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG},
+ {"ipsecesp", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG},
+ {"spdsock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG},
{NULL, 0, NULL, NULL}
};
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index ab4e145..993cafb 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -47,6 +47,7 @@
#include <sys/hook.h>
#include <sys/hook_event.h>
#include <sys/hook_impl.h>
+#include <inet/ip_stack.h>
#ifdef _KERNEL
#include <netinet/ip6.h>
@@ -225,7 +226,7 @@
#define IP_FORWARD_NEVER 0
#define IP_FORWARD_ALWAYS 1
-#define WE_ARE_FORWARDING (ip_g_forward == IP_FORWARD_ALWAYS)
+#define WE_ARE_FORWARDING(ipst) ((ipst)->ips_ip_g_forward == IP_FORWARD_ALWAYS)
#define IPH_HDR_LENGTH(ipha) \
((int)(((ipha_t *)ipha)->ipha_version_and_hdr_length & 0xF) << 2)
@@ -447,9 +448,10 @@
* - when the nce is created or reinit-ed
* - every time we get a sane arp response for the nce.
*/
-#define NCE_EXPIRED(nce) (nce->nce_last > 0 && \
- ((nce->nce_flags & NCE_F_PERMANENT) == 0) && \
- ((TICK_TO_MSEC(lbolt64) - nce->nce_last) > ip_ire_arp_interval))
+#define NCE_EXPIRED(nce, ipst) (nce->nce_last > 0 && \
+ ((nce->nce_flags & NCE_F_PERMANENT) == 0) && \
+ ((TICK_TO_MSEC(lbolt64) - nce->nce_last) > \
+ (ipst)->ips_ip_ire_arp_interval))
#endif /* _KERNEL */
@@ -682,6 +684,18 @@
#define IRE_MARK_UNCACHED 0x0080
+/*
+ * The comment below (and for other netstack_t references) refers
+ * to the fact that we only do netstack_hold in particular cases,
+ * such as the references from open streams (ill_t and conn_t's
+ * pointers). Internally within IP we rely on IP's ability to cleanup e.g.
+ * ire_t's when an ill goes away.
+ */
+typedef struct ire_expire_arg_s {
+ int iea_flush_flag;
+ ip_stack_t *iea_ipst; /* Does not have a netstack_hold */
+} ire_expire_arg_t;
+
/* Flags with ire_expire routine */
#define FLUSH_ARP_TIME 0x0001 /* ARP info potentially stale timer */
#define FLUSH_REDIRECT_TIME 0x0002 /* Redirects potentially stale */
@@ -833,6 +847,12 @@
* ilm_ipif is used by IPv4 as multicast groups are joined using ipif.
* ilm_ill is used by IPv6 as multicast groups are joined using ill.
* ilm_ill is NULL for IPv4 and ilm_ipif is NULL for IPv6.
+ *
+ * The comment below (and for other netstack_t references) refers
+ * to the fact that we only do netstack_hold in particular cases,
+ * such as the references from open streams (ill_t and conn_t's
+ * pointers). Internally within IP we rely on IP's ability to cleanup e.g.
+ * ire_t's when an ill goes away.
*/
#define ILM_DELETED 0x1 /* ilm_flags */
typedef struct ilm_s {
@@ -853,6 +873,7 @@
slist_t *ilm_filter; /* source filter list */
slist_t *ilm_pendsrcs; /* relevant src addrs for pending req */
rtx_state_t ilm_rtx; /* SCR retransmission state */
+ ip_stack_t *ilm_ipst; /* Does not have a netstack_hold */
} ilm_t;
#define ilm_addr V4_PART_OF_V6(ilm_v6addr)
@@ -945,11 +966,11 @@
ASSERT((ipl)->ipl_refcnt != 0); \
}
-#define IPLATCH_REFRELE(ipl) { \
+#define IPLATCH_REFRELE(ipl, ns) { \
ASSERT((ipl)->ipl_refcnt != 0); \
membar_exit(); \
if (atomic_add_32_nv(&(ipl)->ipl_refcnt, -1) == 0) \
- iplatch_free(ipl); \
+ iplatch_free(ipl, ns); \
}
/*
@@ -1107,25 +1128,25 @@
* 2) Or if we have not cached policy on the conn and the global policy is
* non-empty.
*/
-#define CONN_INBOUND_POLICY_PRESENT(connp) \
- ((connp)->conn_in_enforce_policy || \
- (!((connp)->conn_policy_cached) && \
- ipsec_inbound_v4_policy_present))
+#define CONN_INBOUND_POLICY_PRESENT(connp, ipss) \
+ ((connp)->conn_in_enforce_policy || \
+ (!((connp)->conn_policy_cached) && \
+ (ipss)->ipsec_inbound_v4_policy_present))
-#define CONN_INBOUND_POLICY_PRESENT_V6(connp) \
- ((connp)->conn_in_enforce_policy || \
- (!(connp)->conn_policy_cached && \
- ipsec_inbound_v6_policy_present))
+#define CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss) \
+ ((connp)->conn_in_enforce_policy || \
+ (!(connp)->conn_policy_cached && \
+ (ipss)->ipsec_inbound_v6_policy_present))
-#define CONN_OUTBOUND_POLICY_PRESENT(connp) \
- ((connp)->conn_out_enforce_policy || \
- (!((connp)->conn_policy_cached) && \
- ipsec_outbound_v4_policy_present))
+#define CONN_OUTBOUND_POLICY_PRESENT(connp, ipss) \
+ ((connp)->conn_out_enforce_policy || \
+ (!((connp)->conn_policy_cached) && \
+ (ipss)->ipsec_outbound_v4_policy_present))
-#define CONN_OUTBOUND_POLICY_PRESENT_V6(connp) \
- ((connp)->conn_out_enforce_policy || \
- (!(connp)->conn_policy_cached && \
- ipsec_outbound_v6_policy_present))
+#define CONN_OUTBOUND_POLICY_PRESENT_V6(connp, ipss) \
+ ((connp)->conn_out_enforce_policy || \
+ (!(connp)->conn_policy_cached && \
+ (ipss)->ipsec_outbound_v6_policy_present))
/*
* Information cached in IRE for upper layer protocol (ULP).
@@ -1451,6 +1472,7 @@
int ipsq_depth; /* debugging aid */
pc_t ipsq_stack[IP_STACK_DEPTH]; /* debugging aid */
#endif
+ ip_stack_t *ipsq_ipst; /* Does not have a netstack_hold */
} ipsq_t;
/* ipsq_flags */
@@ -1542,8 +1564,6 @@
int illgrp_ill_count;
} ill_group_t;
-extern ill_group_t *illgrp_head_v6;
-
/*
* Fragmentation hash bucket
*/
@@ -1582,6 +1602,7 @@
uint_t irb_tmp_ire_cnt; /* Num of temporary IRE */
struct ire_s *irb_rr_origin; /* origin for round-robin */
int irb_nire; /* Num of ftable ire's that ref irb */
+ ip_stack_t *irb_ipst; /* Does not have a netstack_hold */
} irb_t;
#define IRB2RT(irb) (rt_t *)((caddr_t)(irb) - offsetof(rt_t, rt_irb))
@@ -1619,7 +1640,6 @@
char illif_filler[CACHE_ALIGN(_ill_if_s_)];
} ill_if_t;
-
#define illif_next ill_if_s.illif_next
#define illif_prev ill_if_s.illif_prev
#define illif_avl_by_ppa ill_if_s.illif_avl_by_ppa
@@ -1635,7 +1655,7 @@
} ill_walk_context_t;
/*
- * ill_gheads structure, one for IPV4 and one for IPV6
+ * ill_g_heads structure, one for IPV4 and one for IPV6
*/
struct _ill_g_head_s_ {
ill_if_t *ill_g_list_head;
@@ -1650,20 +1670,19 @@
#define ill_g_list_head ill_g_head_s.ill_g_list_head
#define ill_g_list_tail ill_g_head_s.ill_g_list_tail
-#pragma align CACHE_ALIGN_SIZE(ill_g_heads)
-extern ill_g_head_t ill_g_heads[]; /* ILL List Head */
+#define IP_V4_ILL_G_LIST(ipst) \
+ (ipst)->ips_ill_g_heads[IP_V4_G_HEAD].ill_g_list_head
+#define IP_V6_ILL_G_LIST(ipst) \
+ (ipst)->ips_ill_g_heads[IP_V6_G_HEAD].ill_g_list_head
+#define IP_VX_ILL_G_LIST(i, ipst) \
+ (ipst)->ips_ill_g_heads[i].ill_g_list_head
-
-#define IP_V4_ILL_G_LIST ill_g_heads[IP_V4_G_HEAD].ill_g_list_head
-#define IP_V6_ILL_G_LIST ill_g_heads[IP_V6_G_HEAD].ill_g_list_head
-#define IP_VX_ILL_G_LIST(i) ill_g_heads[i].ill_g_list_head
-
-#define ILL_START_WALK_V4(ctx_ptr) ill_first(IP_V4_G_HEAD, IP_V4_G_HEAD, \
- ctx_ptr)
-#define ILL_START_WALK_V6(ctx_ptr) ill_first(IP_V6_G_HEAD, IP_V6_G_HEAD, \
- ctx_ptr)
-#define ILL_START_WALK_ALL(ctx_ptr) ill_first(MAX_G_HEADS, MAX_G_HEADS, \
- ctx_ptr)
+#define ILL_START_WALK_V4(ctx_ptr, ipst) \
+ ill_first(IP_V4_G_HEAD, IP_V4_G_HEAD, ctx_ptr, ipst)
+#define ILL_START_WALK_V6(ctx_ptr, ipst) \
+ ill_first(IP_V6_G_HEAD, IP_V6_G_HEAD, ctx_ptr, ipst)
+#define ILL_START_WALK_ALL(ctx_ptr, ipst) \
+ ill_first(MAX_G_HEADS, MAX_G_HEADS, ctx_ptr, ipst)
/*
* Capabilities, possible flags for ill_capabilities.
@@ -1973,6 +1992,8 @@
th_trace_t *ill_trace[IP_TR_HASH_MAX];
boolean_t ill_trace_disable; /* True when alloc fails */
#endif
+ zoneid_t ill_zoneid;
+ ip_stack_t *ill_ipst; /* Corresponds to a netstack_hold */
} ill_t;
extern void ill_delete_glist(ill_t *);
@@ -2376,7 +2397,7 @@
if (atomic_add_32_nv(&(ire)->ire_refcnt, -1) == 0) \
ire_inactive(ire); \
}
-#define IRE_REFRELE_NOTR(ire) { \
+#define IRE_REFRELE_NOTR(ire) { \
ASSERT((ire)->ire_refcnt != 0); \
membar_exit(); \
if (atomic_add_32_nv(&(ire)->ire_refcnt, -1) == 0) \
@@ -2530,6 +2551,7 @@
uint_t ire_stq_ifindex;
uint_t ire_defense_count; /* number of ARP conflicts */
uint_t ire_defense_time; /* last time defended (secs) */
+ ip_stack_t *ire_ipst; /* Does not have a netstack_hold */
#ifdef IRE_DEBUG
th_trace_t *ire_trace[IP_TR_HASH_MAX];
boolean_t ire_trace_disable; /* True when alloc fails */
@@ -2612,8 +2634,8 @@
*/
#define COMMON_IP_MTU 1500
#define MAX_FRAG_MIN 10
-#define MAX_FRAG_PKTS \
- MAX(MAX_FRAG_MIN, (2 * (ip_reass_queue_bytes / \
+#define MAX_FRAG_PKTS(ipst) \
+ MAX(MAX_FRAG_MIN, (2 * (ipst->ips_ip_reass_queue_bytes / \
(COMMON_IP_MTU * ILL_FRAG_HASH_TBL_COUNT))))
/*
@@ -2842,104 +2864,96 @@
struct lifreq *ci_lifr; /* the lifreq struct passed down */
} cmd_info_t;
-extern krwlock_t ill_g_lock;
-extern kmutex_t ip_addr_avail_lock;
-extern ipsq_t *ipsq_g_head;
-
-extern ill_t *ip_timer_ill; /* ILL for IRE expiration timer. */
-extern timeout_id_t ip_ire_expire_id; /* IRE expiration timeout id. */
-extern timeout_id_t ip_ire_reclaim_id; /* IRE recalaim timeout id. */
-
-extern kmutex_t ip_mi_lock;
-extern krwlock_t ip_g_nd_lock; /* For adding/removing nd variables */
-extern kmutex_t ip_trash_timer_lock; /* Protects ip_ire_expire_id */
-
-extern kmutex_t igmp_timer_lock; /* Protects the igmp timer */
-extern kmutex_t mld_timer_lock; /* Protects the mld timer */
-
-extern krwlock_t ill_g_usesrc_lock; /* Protects usesrc related fields */
+/*
+ * List of AH and ESP IPsec acceleration capable ills
+ */
+typedef struct ipsec_capab_ill_s {
+ uint_t ill_index;
+ boolean_t ill_isv6;
+ struct ipsec_capab_ill_s *next;
+} ipsec_capab_ill_t;
extern struct kmem_cache *ire_cache;
-extern uint_t ip_redirect_cnt; /* Num of redirect routes in ftable */
-
extern ipaddr_t ip_g_all_ones;
-extern caddr_t ip_g_nd; /* Named Dispatch List Head */
-extern uint_t ip_loopback_mtu;
+extern uint_t ip_loopback_mtu; /* /etc/system */
-extern ipparam_t *ip_param_arr;
-
-extern int ip_g_forward;
-extern int ipv6_forward;
extern vmem_t *ip_minor_arena;
-#define ip_respond_to_address_mask_broadcast ip_param_arr[0].ip_param_value
-#define ip_g_resp_to_echo_bcast ip_param_arr[1].ip_param_value
-#define ip_g_resp_to_echo_mcast ip_param_arr[2].ip_param_value
-#define ip_g_resp_to_timestamp ip_param_arr[3].ip_param_value
-#define ip_g_resp_to_timestamp_bcast ip_param_arr[4].ip_param_value
-#define ip_g_send_redirects ip_param_arr[5].ip_param_value
-#define ip_g_forward_directed_bcast ip_param_arr[6].ip_param_value
-#define ip_debug ip_param_arr[7].ip_param_value
-#define ip_mrtdebug ip_param_arr[8].ip_param_value
-#define ip_timer_interval ip_param_arr[9].ip_param_value
-#define ip_ire_arp_interval ip_param_arr[10].ip_param_value
-#define ip_ire_redir_interval ip_param_arr[11].ip_param_value
-#define ip_def_ttl ip_param_arr[12].ip_param_value
-#define ip_forward_src_routed ip_param_arr[13].ip_param_value
-#define ip_wroff_extra ip_param_arr[14].ip_param_value
-#define ip_ire_pathmtu_interval ip_param_arr[15].ip_param_value
-#define ip_icmp_return ip_param_arr[16].ip_param_value
-#define ip_path_mtu_discovery ip_param_arr[17].ip_param_value
-#define ip_ignore_delete_time ip_param_arr[18].ip_param_value
-#define ip_ignore_redirect ip_param_arr[19].ip_param_value
-#define ip_output_queue ip_param_arr[20].ip_param_value
-#define ip_broadcast_ttl ip_param_arr[21].ip_param_value
-#define ip_icmp_err_interval ip_param_arr[22].ip_param_value
-#define ip_icmp_err_burst ip_param_arr[23].ip_param_value
-#define ip_reass_queue_bytes ip_param_arr[24].ip_param_value
-#define ip_strict_dst_multihoming ip_param_arr[25].ip_param_value
-#define ip_addrs_per_if ip_param_arr[26].ip_param_value
-#define ipsec_override_persocket_policy ip_param_arr[27].ip_param_value
-#define icmp_accept_clear_messages ip_param_arr[28].ip_param_value
-#define igmp_accept_clear_messages ip_param_arr[29].ip_param_value
+/*
+ * ip_g_forward controls IP forwarding. It takes two values:
+ * 0: IP_FORWARD_NEVER Don't forward packets ever.
+ * 1: IP_FORWARD_ALWAYS Forward packets for elsewhere.
+ *
+ * RFC1122 says there must be a configuration switch to control forwarding,
+ * but that the default MUST be to not forward packets ever. Implicit
+ * control based on configuration of multiple interfaces MUST NOT be
+ * implemented (Section 3.1). SunOS 4.1 did provide the "automatic" capability
+ * and, in fact, it was the default. That capability is now provided in the
+ * /etc/rc2.d/S69inet script.
+ */
+
+#define ips_ip_respond_to_address_mask_broadcast ips_param_arr[0].ip_param_value
+#define ips_ip_g_resp_to_echo_bcast ips_param_arr[1].ip_param_value
+#define ips_ip_g_resp_to_echo_mcast ips_param_arr[2].ip_param_value
+#define ips_ip_g_resp_to_timestamp ips_param_arr[3].ip_param_value
+#define ips_ip_g_resp_to_timestamp_bcast ips_param_arr[4].ip_param_value
+#define ips_ip_g_send_redirects ips_param_arr[5].ip_param_value
+#define ips_ip_g_forward_directed_bcast ips_param_arr[6].ip_param_value
+#define ips_ip_debug ips_param_arr[7].ip_param_value
+#define ips_ip_mrtdebug ips_param_arr[8].ip_param_value
+#define ips_ip_timer_interval ips_param_arr[9].ip_param_value
+#define ips_ip_ire_arp_interval ips_param_arr[10].ip_param_value
+#define ips_ip_ire_redir_interval ips_param_arr[11].ip_param_value
+#define ips_ip_def_ttl ips_param_arr[12].ip_param_value
+#define ips_ip_forward_src_routed ips_param_arr[13].ip_param_value
+#define ips_ip_wroff_extra ips_param_arr[14].ip_param_value
+#define ips_ip_ire_pathmtu_interval ips_param_arr[15].ip_param_value
+#define ips_ip_icmp_return ips_param_arr[16].ip_param_value
+#define ips_ip_path_mtu_discovery ips_param_arr[17].ip_param_value
+#define ips_ip_ignore_delete_time ips_param_arr[18].ip_param_value
+#define ips_ip_ignore_redirect ips_param_arr[19].ip_param_value
+#define ips_ip_output_queue ips_param_arr[20].ip_param_value
+#define ips_ip_broadcast_ttl ips_param_arr[21].ip_param_value
+#define ips_ip_icmp_err_interval ips_param_arr[22].ip_param_value
+#define ips_ip_icmp_err_burst ips_param_arr[23].ip_param_value
+#define ips_ip_reass_queue_bytes ips_param_arr[24].ip_param_value
+#define ips_ip_strict_dst_multihoming ips_param_arr[25].ip_param_value
+#define ips_ip_addrs_per_if ips_param_arr[26].ip_param_value
+#define ips_ipsec_override_persocket_policy ips_param_arr[27].ip_param_value
+#define ips_icmp_accept_clear_messages ips_param_arr[28].ip_param_value
+#define ips_igmp_accept_clear_messages ips_param_arr[29].ip_param_value
/* IPv6 configuration knobs */
-#define delay_first_probe_time ip_param_arr[30].ip_param_value
-#define max_unicast_solicit ip_param_arr[31].ip_param_value
-#define ipv6_def_hops ip_param_arr[32].ip_param_value
-#define ipv6_icmp_return ip_param_arr[33].ip_param_value
-#define ipv6_forward_src_routed ip_param_arr[34].ip_param_value
-#define ipv6_resp_echo_mcast ip_param_arr[35].ip_param_value
-#define ipv6_send_redirects ip_param_arr[36].ip_param_value
-#define ipv6_ignore_redirect ip_param_arr[37].ip_param_value
-#define ipv6_strict_dst_multihoming ip_param_arr[38].ip_param_value
-#define ip_ire_reclaim_fraction ip_param_arr[39].ip_param_value
-#define ipsec_policy_log_interval ip_param_arr[40].ip_param_value
-#define pim_accept_clear_messages ip_param_arr[41].ip_param_value
-#define ip_ndp_unsolicit_interval ip_param_arr[42].ip_param_value
-#define ip_ndp_unsolicit_count ip_param_arr[43].ip_param_value
-#define ipv6_ignore_home_address_opt ip_param_arr[44].ip_param_value
-#define ip_policy_mask ip_param_arr[45].ip_param_value
-#define ip_multirt_resolution_interval ip_param_arr[46].ip_param_value
-#define ip_multirt_ttl ip_param_arr[47].ip_param_value
-#define ip_multidata_outbound ip_param_arr[48].ip_param_value
-#define ip_ndp_defense_interval ip_param_arr[49].ip_param_value
-#define ip_max_temp_idle ip_param_arr[50].ip_param_value
-#define ip_max_temp_defend ip_param_arr[51].ip_param_value
-#define ip_max_defend ip_param_arr[52].ip_param_value
-#define ip_defend_interval ip_param_arr[53].ip_param_value
-#define ip_dup_recovery ip_param_arr[54].ip_param_value
-#define ip_restrict_interzone_loopback ip_param_arr[55].ip_param_value
-#define ip_lso_outbound ip_param_arr[56].ip_param_value
-#ifdef DEBUG
-#define ipv6_drop_inbound_icmpv6 ip_param_arr[57].ip_param_value
-#else
-#define ipv6_drop_inbound_icmpv6 0
-#endif
-
-extern hrtime_t ipsec_policy_failure_last;
+#define ips_delay_first_probe_time ips_param_arr[30].ip_param_value
+#define ips_max_unicast_solicit ips_param_arr[31].ip_param_value
+#define ips_ipv6_def_hops ips_param_arr[32].ip_param_value
+#define ips_ipv6_icmp_return ips_param_arr[33].ip_param_value
+#define ips_ipv6_forward_src_routed ips_param_arr[34].ip_param_value
+#define ips_ipv6_resp_echo_mcast ips_param_arr[35].ip_param_value
+#define ips_ipv6_send_redirects ips_param_arr[36].ip_param_value
+#define ips_ipv6_ignore_redirect ips_param_arr[37].ip_param_value
+#define ips_ipv6_strict_dst_multihoming ips_param_arr[38].ip_param_value
+#define ips_ip_ire_reclaim_fraction ips_param_arr[39].ip_param_value
+#define ips_ipsec_policy_log_interval ips_param_arr[40].ip_param_value
+#define ips_pim_accept_clear_messages ips_param_arr[41].ip_param_value
+#define ips_ip_ndp_unsolicit_interval ips_param_arr[42].ip_param_value
+#define ips_ip_ndp_unsolicit_count ips_param_arr[43].ip_param_value
+#define ips_ipv6_ignore_home_address_opt ips_param_arr[44].ip_param_value
+#define ips_ip_policy_mask ips_param_arr[45].ip_param_value
+#define ips_ip_multirt_resolution_interval ips_param_arr[46].ip_param_value
+#define ips_ip_multirt_ttl ips_param_arr[47].ip_param_value
+#define ips_ip_multidata_outbound ips_param_arr[48].ip_param_value
+#define ips_ip_ndp_defense_interval ips_param_arr[49].ip_param_value
+#define ips_ip_max_temp_idle ips_param_arr[50].ip_param_value
+#define ips_ip_max_temp_defend ips_param_arr[51].ip_param_value
+#define ips_ip_max_defend ips_param_arr[52].ip_param_value
+#define ips_ip_defend_interval ips_param_arr[53].ip_param_value
+#define ips_ip_dup_recovery ips_param_arr[54].ip_param_value
+#define ips_ip_restrict_interzone_loopback ips_param_arr[55].ip_param_value
+#define ips_ip_lso_outbound ips_param_arr[56].ip_param_value
+#define ips_ipv6_drop_inbound_icmpv6 ips_param_arr[57].ip_param_value
extern int dohwcksum; /* use h/w cksum if supported by the h/w */
#ifdef ZC_TEST
@@ -2950,76 +2964,35 @@
extern nv_t *ire_nv_tbl;
-extern time_t ip_g_frag_timeout;
-extern clock_t ip_g_frag_timo_ms;
-
-extern mib2_ipIfStatsEntry_t ip_mib; /* For tcpInErrs and udpNoPorts */
-
extern struct module_info ip_mod_info;
-extern timeout_id_t igmp_slowtimeout_id;
-extern timeout_id_t mld_slowtimeout_id;
-
-extern uint_t loopback_packets;
-
-/*
- * Hooks structures used inside of ip
- */
-extern hook_event_token_t ipv4firewall_physical_in;
-extern hook_event_token_t ipv4firewall_physical_out;
-extern hook_event_token_t ipv4firewall_forwarding;
-extern hook_event_token_t ipv4firewall_loopback_in;
-extern hook_event_token_t ipv4firewall_loopback_out;
-extern hook_event_token_t ipv4nicevents;
-
-extern hook_event_token_t ipv6firewall_physical_in;
-extern hook_event_token_t ipv6firewall_physical_out;
-extern hook_event_token_t ipv6firewall_forwarding;
-extern hook_event_token_t ipv6firewall_loopback_in;
-extern hook_event_token_t ipv6firewall_loopback_out;
-extern hook_event_token_t ipv6nicevents;
-
-extern hook_event_t ip4_physical_in_event;
-extern hook_event_t ip4_physical_out_event;
-extern hook_event_t ip4_forwarding_event;
-extern hook_event_t ip4_loopback_in_event;
-extern hook_event_t ip4_loopback_out_event;
-extern hook_event_t ip4_nic_events;
-
-extern hook_event_t ip6_physical_in_event;
-extern hook_event_t ip6_physical_out_event;
-extern hook_event_t ip6_forwarding_event;
-extern hook_event_t ip6_loopback_in_event;
-extern hook_event_t ip6_loopback_out_event;
-extern hook_event_t ip6_nic_events;
-
-#define HOOKS4_INTERESTED_PHYSICAL_IN \
- (ip4_physical_in_event.he_interested)
-#define HOOKS6_INTERESTED_PHYSICAL_IN \
- (ip6_physical_in_event.he_interested)
-#define HOOKS4_INTERESTED_PHYSICAL_OUT \
- (ip4_physical_out_event.he_interested)
-#define HOOKS6_INTERESTED_PHYSICAL_OUT \
- (ip6_physical_out_event.he_interested)
-#define HOOKS4_INTERESTED_FORWARDING \
- (ip4_forwarding_event.he_interested)
-#define HOOKS6_INTERESTED_FORWARDING \
- (ip6_forwarding_event.he_interested)
-#define HOOKS4_INTERESTED_LOOPBACK_IN \
- (ip4_loopback_in_event.he_interested)
-#define HOOKS6_INTERESTED_LOOPBACK_IN \
- (ip6_loopback_in_event.he_interested)
-#define HOOKS4_INTERESTED_LOOPBACK_OUT \
- (ip4_loopback_out_event.he_interested)
-#define HOOKS6_INTERESTED_LOOPBACK_OUT \
- (ip6_loopback_out_event.he_interested)
+#define HOOKS4_INTERESTED_PHYSICAL_IN(ipst) \
+ ((ipst)->ips_ip4_physical_in_event.he_interested)
+#define HOOKS6_INTERESTED_PHYSICAL_IN(ipst) \
+ ((ipst)->ips_ip6_physical_in_event.he_interested)
+#define HOOKS4_INTERESTED_PHYSICAL_OUT(ipst) \
+ ((ipst)->ips_ip4_physical_out_event.he_interested)
+#define HOOKS6_INTERESTED_PHYSICAL_OUT(ipst) \
+ ((ipst)->ips_ip6_physical_out_event.he_interested)
+#define HOOKS4_INTERESTED_FORWARDING(ipst) \
+ ((ipst)->ips_ip4_forwarding_event.he_interested)
+#define HOOKS6_INTERESTED_FORWARDING(ipst) \
+ ((ipst)->ips_ip6_forwarding_event.he_interested)
+#define HOOKS4_INTERESTED_LOOPBACK_IN(ipst) \
+ ((ipst)->ips_ip4_loopback_in_event.he_interested)
+#define HOOKS6_INTERESTED_LOOPBACK_IN(ipst) \
+ ((ipst)->ips_ip6_loopback_in_event.he_interested)
+#define HOOKS4_INTERESTED_LOOPBACK_OUT(ipst) \
+ ((ipst)->ips_ip4_loopback_out_event.he_interested)
+#define HOOKS6_INTERESTED_LOOPBACK_OUT(ipst) \
+ ((ipst)->ips_ip6_loopback_out_event.he_interested)
/*
* Hooks marcos used inside of ip
*/
#define IPHA_VHL ipha_version_and_hdr_length
-#define FW_HOOKS(_hook, _event, _ilp, _olp, _iph, _fm, _m) \
+#define FW_HOOKS(_hook, _event, _ilp, _olp, _iph, _fm, _m, ipst) \
\
if ((_hook).he_interested) { \
hook_pkt_event_t info; \
@@ -3045,7 +3018,8 @@
info.hpe_hdr = _iph; \
info.hpe_mp = &(_fm); \
info.hpe_mb = _m; \
- if (hook_run(_event, (hook_data_t)&info) != 0) { \
+ if (hook_run(_event, (hook_data_t)&info, \
+ ipst->ips_netstack) != 0) { \
ip2dbg(("%s hook dropped mblk chain %p hdr %p\n",\
(_hook).he_name, (void *)_fm, (void *)_m)); \
if (_fm != NULL) { \
@@ -3060,7 +3034,7 @@
} \
}
-#define FW_HOOKS6(_hook, _event, _ilp, _olp, _iph, _fm, _m) \
+#define FW_HOOKS6(_hook, _event, _ilp, _olp, _iph, _fm, _m, ipst) \
\
if ((_hook).he_interested) { \
hook_pkt_event_t info; \
@@ -3086,7 +3060,8 @@
info.hpe_hdr = _iph; \
info.hpe_mp = &(_fm); \
info.hpe_mb = _m; \
- if (hook_run(_event, (hook_data_t)&info) != 0) { \
+ if (hook_run(_event, (hook_data_t)&info, \
+ ipst->ips_netstack) != 0) { \
ip2dbg(("%s hook dropped mblk chain %p hdr %p\n",\
(_hook).he_name, (void *)_fm, (void *)_m)); \
if (_fm != NULL) { \
@@ -3134,6 +3109,8 @@
#define IPSECHW_CALL(f, r, x) {}
#endif
+extern int ip_debug;
+
#ifdef IP_DEBUG
#include <sys/debug.h>
#include <sys/promif.h>
@@ -3159,7 +3136,7 @@
extern const char *dlpi_prim_str(int);
extern const char *dlpi_err_str(int);
extern void ill_frag_timer(void *);
-extern ill_t *ill_first(int, int, ill_walk_context_t *);
+extern ill_t *ill_first(int, int, ill_walk_context_t *, ip_stack_t *);
extern ill_t *ill_next(ill_walk_context_t *, ill_t *);
extern void ill_frag_timer_start(ill_t *);
extern mblk_t *ip_carve_mp(mblk_t **, ssize_t);
@@ -3167,10 +3144,12 @@
extern char *ip_dot_addr(ipaddr_t, char *);
extern const char *mac_colon_addr(const uint8_t *, size_t, char *, size_t);
extern void ip_lwput(queue_t *, mblk_t *);
-extern boolean_t icmp_err_rate_limit(void);
-extern void icmp_time_exceeded(queue_t *, mblk_t *, uint8_t, zoneid_t);
-extern void icmp_unreachable(queue_t *, mblk_t *, uint8_t, zoneid_t);
-extern mblk_t *ip_add_info(mblk_t *, ill_t *, uint_t, zoneid_t);
+extern boolean_t icmp_err_rate_limit(ip_stack_t *);
+extern void icmp_time_exceeded(queue_t *, mblk_t *, uint8_t, zoneid_t,
+ ip_stack_t *);
+extern void icmp_unreachable(queue_t *, mblk_t *, uint8_t, zoneid_t,
+ ip_stack_t *);
+extern mblk_t *ip_add_info(mblk_t *, ill_t *, uint_t, zoneid_t, ip_stack_t *);
extern mblk_t *ip_bind_v4(queue_t *, mblk_t *, conn_t *);
extern int ip_bind_connected(conn_t *, mblk_t *, ipaddr_t *, uint16_t,
ipaddr_t, uint16_t, boolean_t, boolean_t, boolean_t,
@@ -3181,9 +3160,12 @@
extern uint_t ip_cksum(mblk_t *, int, uint32_t);
extern int ip_close(queue_t *, int);
extern uint16_t ip_csum_hdr(ipha_t *);
-extern void ip_proto_not_sup(queue_t *, mblk_t *, uint_t, zoneid_t);
-extern void ip_ire_fini(void);
-extern void ip_ire_init(void);
+extern void ip_proto_not_sup(queue_t *, mblk_t *, uint_t, zoneid_t,
+ ip_stack_t *);
+extern void ip_ire_g_fini(void);
+extern void ip_ire_g_init(void);
+extern void ip_ire_fini(ip_stack_t *);
+extern void ip_ire_init(ip_stack_t *);
extern int ip_open(queue_t *, dev_t *, int, int, cred_t *);
extern int ip_reassemble(mblk_t *, ipf_t *, uint_t, boolean_t, ill_t *,
size_t);
@@ -3205,7 +3187,7 @@
extern void ip_udp_input(queue_t *, mblk_t *, ipha_t *, ire_t *, ill_t *);
extern void ip_proto_input(queue_t *, mblk_t *, ipha_t *, ire_t *, ill_t *);
extern void ip_rput_other(ipsq_t *, queue_t *, mblk_t *, void *);
-extern void ip_setqinfo(queue_t *, minor_t, boolean_t);
+extern void ip_setqinfo(queue_t *, minor_t, boolean_t, ip_stack_t *);
extern void ip_trash_ire_reclaim(void *);
extern void ip_trash_timer_expire(void *);
extern void ip_wput(queue_t *, mblk_t *);
@@ -3224,13 +3206,13 @@
extern char *ip_nv_lookup(nv_t *, int);
extern boolean_t ip_local_addr_ok_v6(const in6_addr_t *, const in6_addr_t *);
extern boolean_t ip_remote_addr_ok_v6(const in6_addr_t *, const in6_addr_t *);
-extern ipaddr_t ip_massage_options(ipha_t *);
+extern ipaddr_t ip_massage_options(ipha_t *, netstack_t *);
extern ipaddr_t ip_net_mask(ipaddr_t);
extern void ip_newroute(queue_t *, mblk_t *, ipaddr_t, ill_t *, conn_t *,
- zoneid_t);
+ zoneid_t, ip_stack_t *);
extern ipxmit_state_t ip_xmit_v4(mblk_t *, ire_t *, struct ipsec_out_s *,
boolean_t);
-extern int ip_hdr_complete(ipha_t *, zoneid_t);
+extern int ip_hdr_complete(ipha_t *, zoneid_t, ip_stack_t *);
extern struct qinit rinit_ipv6;
extern struct qinit winit_ipv6;
@@ -3240,9 +3222,6 @@
extern struct qinit rinit_acceptor_tcp;
extern struct qinit winit_acceptor_tcp;
-extern net_data_t ipv4;
-extern net_data_t ipv6;
-
extern void conn_drain_insert(conn_t *connp);
extern int conn_ipsec_length(conn_t *connp);
extern void ip_wput_ipsec_out(queue_t *, mblk_t *, ipha_t *, ill_t *,
@@ -3250,7 +3229,7 @@
extern ipaddr_t ip_get_dst(ipha_t *);
extern int ipsec_out_extra_length(mblk_t *);
extern int ipsec_in_extra_length(mblk_t *);
-extern mblk_t *ipsec_in_alloc();
+extern mblk_t *ipsec_in_alloc(boolean_t, netstack_t *);
extern boolean_t ipsec_in_is_secure(mblk_t *);
extern void ipsec_out_process(queue_t *, mblk_t *, ire_t *, uint_t);
extern void ipsec_out_to_in(mblk_t *);
@@ -3271,16 +3250,17 @@
extern void ipif_trace_cleanup(ipif_t *);
#endif
-extern int ip_srcid_insert(const in6_addr_t *, zoneid_t);
-extern int ip_srcid_remove(const in6_addr_t *, zoneid_t);
-extern void ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t);
-extern uint_t ip_srcid_find_addr(const in6_addr_t *, zoneid_t);
+extern int ip_srcid_insert(const in6_addr_t *, zoneid_t, ip_stack_t *);
+extern int ip_srcid_remove(const in6_addr_t *, zoneid_t, ip_stack_t *);
+extern void ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t, netstack_t *);
+extern uint_t ip_srcid_find_addr(const in6_addr_t *, zoneid_t, netstack_t *);
extern int ip_srcid_report(queue_t *, mblk_t *, caddr_t, cred_t *);
extern uint8_t ipoptp_next(ipoptp_t *);
extern uint8_t ipoptp_first(ipoptp_t *, ipha_t *);
extern int ip_opt_get_user(const ipha_t *, uchar_t *);
-extern ill_t *ip_grab_attach_ill(ill_t *, mblk_t *, int, boolean_t);
+extern ill_t *ip_grab_attach_ill(ill_t *, mblk_t *, int, boolean_t,
+ ip_stack_t *);
extern ire_t *conn_set_outgoing_ill(conn_t *, ire_t *, ill_t **);
extern int ipsec_req_from_conn(conn_t *, ipsec_req_t *, int);
extern int ip_snmp_get(queue_t *q, mblk_t *mctl);
@@ -3347,6 +3327,12 @@
#define CGTP_MCAST_SUCCESS 1
+/*
+ * The separate CGTP module needs these as globals. It uses the first
+ * to unregister (since there is no ip_cgtp_filter_unregister() function)
+ * and it uses the second one to verify that the filter has been
+ * turned off (a ip_cgtp_filter_active() function would be good for that.)
+ */
extern cgtp_filter_ops_t *ip_cgtp_filter_ops;
extern boolean_t ip_cgtp_filter;
@@ -3520,7 +3506,7 @@
extern void tcp_wput(queue_t *, mblk_t *);
extern int ip_fill_mtuinfo(struct in6_addr *, in_port_t,
- struct ip6_mtuinfo *);
+ struct ip6_mtuinfo *, netstack_t *);
extern ipif_t *conn_get_held_ipif(conn_t *, ipif_t **, int *);
typedef void (*ipsq_func_t)(ipsq_t *, queue_t *, mblk_t *, void *);
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index 475d753..e743959 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -50,6 +50,7 @@
#include <sys/isa_defs.h>
#include <sys/suntpi.h>
#include <sys/xti_inet.h>
+#include <sys/netstack.h>
#include <net/route.h>
#include <net/if.h>
@@ -102,14 +103,6 @@
* exited the shared resource.
*/
-/* Named Dispatch Parameter Management Structure */
-typedef struct icmpparam_s {
- uint_t icmp_param_min;
- uint_t icmp_param_max;
- uint_t icmp_param_value;
- char *icmp_param_name;
-} icmpparam_t;
-
static void icmp_addr_req(queue_t *q, mblk_t *mp);
static void icmp_bind(queue_t *q, mblk_t *mp);
static void icmp_bind_proto(queue_t *q);
@@ -139,7 +132,7 @@
int icmp_opt_get(queue_t *q, int level, int name,
uchar_t *ptr);
static int icmp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
-static boolean_t icmp_param_register(icmpparam_t *icmppa, int cnt);
+static boolean_t icmp_param_register(IDP *ndp, icmpparam_t *icmppa, int cnt);
static int icmp_param_set(queue_t *q, mblk_t *mp, char *value,
caddr_t cp, cred_t *cr);
static void icmp_rput(queue_t *q, mblk_t *mp);
@@ -158,8 +151,11 @@
static void icmp_wput_iocdata(queue_t *q, mblk_t *mp);
static void icmp_wput_restricted(queue_t *q, mblk_t *mp);
-static void rawip_kstat_init(void);
-static void rawip_kstat_fini(void);
+static void *rawip_stack_init(netstackid_t stackid, netstack_t *ns);
+static void rawip_stack_fini(netstackid_t stackid, void *arg);
+
+static void *rawip_kstat_init(netstackid_t stackid);
+static void rawip_kstat_fini(netstackid_t stackid, kstat_t *ksp);
static int rawip_kstat_update(kstat_t *kp, int rw);
@@ -181,12 +177,6 @@
static sin_t sin_null; /* Zero address for quick clears */
static sin6_t sin6_null; /* Zero address for quick clears */
-static void *icmp_g_head; /* Head for list of open icmp streams. */
-static IDP icmp_g_nd; /* Points to table of ICMP ND variables. */
-
-/* MIB-2 stuff for SNMP */
-static mib2_rawip_t rawip_mib; /* SNMP fixed size info */
-static kstat_t *rawip_mibkp; /* kstat exporting rawip_mib data */
/* Default structure copied into T_INFO_ACK messages */
static struct T_info_ack icmp_g_t_info_ack = {
@@ -204,8 +194,8 @@
};
/*
- * Table of ND variables supported by icmp. These are loaded into icmp_g_nd
- * in icmp_open.
+ * Table of ND variables supported by icmp. These are loaded into is_nd
+ * when the stack instance is created.
* All of these are alterable, within the min/max values given, at run time.
*/
static icmpparam_t icmp_param_arr[] = {
@@ -219,14 +209,14 @@
{ 4096, 65536, 8192, "icmp_recv_hiwat"},
{ 65536, 1024*1024*1024, 256*1024, "icmp_max_buf"},
};
-#define icmp_wroff_extra icmp_param_arr[0].icmp_param_value
-#define icmp_ipv4_ttl icmp_param_arr[1].icmp_param_value
-#define icmp_ipv6_hoplimit icmp_param_arr[2].icmp_param_value
-#define icmp_bsd_compat icmp_param_arr[3].icmp_param_value
-#define icmp_xmit_hiwat icmp_param_arr[4].icmp_param_value
-#define icmp_xmit_lowat icmp_param_arr[5].icmp_param_value
-#define icmp_recv_hiwat icmp_param_arr[6].icmp_param_value
-#define icmp_max_buf icmp_param_arr[7].icmp_param_value
+#define is_wroff_extra is_param_arr[0].icmp_param_value
+#define is_ipv4_ttl is_param_arr[1].icmp_param_value
+#define is_ipv6_hoplimit is_param_arr[2].icmp_param_value
+#define is_bsd_compat is_param_arr[3].icmp_param_value
+#define is_xmit_hiwat is_param_arr[4].icmp_param_value
+#define is_xmit_lowat is_param_arr[5].icmp_param_value
+#define is_recv_hiwat is_param_arr[6].icmp_param_value
+#define is_max_buf is_param_arr[7].icmp_param_value
/*
* This routine is called to handle each O_T_BIND_REQ/T_BIND_REQ message
@@ -630,6 +620,7 @@
{
icmp_t *icmp = (icmp_t *)q->q_ptr;
int i1;
+ icmp_stack_t *is = icmp->icmp_is;
/* tell IP that if we're not here, he can't trust labels */
if (is_system_labeled())
@@ -655,9 +646,10 @@
ip6_pkt_free(&icmp->icmp_sticky_ipp);
crfree(icmp->icmp_credp);
+ netstack_rele(icmp->icmp_is->is_netstack);
/* Free the icmp structure and release the minor device number. */
- i1 = mi_close_comm(&icmp_g_head, q);
+ i1 = mi_close_comm(&is->is_head, q);
return (i1);
}
@@ -926,7 +918,7 @@
udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t) +
opt_length;
if ((newmp = allocb(udi_size, BPRI_MED)) == NULL) {
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInErrors);
break;
}
@@ -1329,6 +1321,9 @@
icmp_t *icmp;
mblk_t *mp;
out_labeled_t *olp;
+ netstack_t *ns;
+ icmp_stack_t *is;
+ zoneid_t zoneid;
/* If the stream is already open, return immediately. */
if (q->q_ptr != NULL)
@@ -1345,20 +1340,36 @@
* has an outer perimeter.)
*/
+ ns = netstack_find_by_cred(credp);
+ ASSERT(ns != NULL);
+ is = ns->netstack_icmp;
+ ASSERT(is != NULL);
+
+ /*
+ * For exclusive stacks we set the zoneid to zero
+ * to make ICMP operate as if in the global zone.
+ */
+ if (is->is_netstack->netstack_stackid != GLOBAL_NETSTACKID)
+ zoneid = GLOBAL_ZONEID;
+ else
+ zoneid = crgetzoneid(credp);
+
/*
* Create a icmp_t structure for this stream and link into the
* list of open streams.
*/
- err = mi_open_comm(&icmp_g_head, sizeof (icmp_t), q, devp,
+ err = mi_open_comm(&is->is_head, sizeof (icmp_t), q, devp,
flag, sflag, credp);
- if (err != 0)
+ if (err != 0) {
+ netstack_rele(is->is_netstack);
return (err);
+ }
/*
* The receive hiwat is only looked at on the stream head queue.
* Store in q_hiwat in order to return on SO_RCVBUF getsockopts.
*/
- q->q_hiwat = icmp_recv_hiwat;
+ q->q_hiwat = is->is_recv_hiwat;
/* Set the initial state of the stream and the privilege status. */
icmp = (icmp_t *)q->q_ptr;
@@ -1377,7 +1388,8 @@
if (getpflags(NET_MAC_AWARE, credp) != 0)
icmp->icmp_mac_exempt = B_TRUE;
- icmp->icmp_zoneid = getzoneid();
+ icmp->icmp_zoneid = zoneid;
+ icmp->icmp_is = is;
if (getmajor(*devp) == (major_t)ICMP6_MAJ) {
icmp->icmp_ipversion = IPV6_VERSION;
@@ -1386,14 +1398,14 @@
icmp->icmp_proto = IPPROTO_ICMPV6;
icmp->icmp_checksum_off = 2; /* Offset for icmp6_cksum */
icmp->icmp_max_hdr_len = IPV6_HDR_LEN;
- icmp->icmp_ttl = (uint8_t)icmp_ipv6_hoplimit;
+ icmp->icmp_ttl = (uint8_t)is->is_ipv6_hoplimit;
} else {
icmp->icmp_ipversion = IPV4_VERSION;
icmp->icmp_family = AF_INET;
/* May be changed by a SO_PROTOTYPE socket option. */
icmp->icmp_proto = IPPROTO_ICMP;
icmp->icmp_max_hdr_len = IP_SIMPLE_HDR_LENGTH;
- icmp->icmp_ttl = (uint8_t)icmp_ipv4_ttl;
+ icmp->icmp_ttl = (uint8_t)is->is_ipv4_ttl;
}
qprocson(q);
@@ -1411,9 +1423,9 @@
* Store in q_hiwat in order to return on SO_SNDBUF
* getsockopts.
*/
- WR(q)->q_hiwat = icmp_xmit_hiwat;
+ WR(q)->q_hiwat = is->is_xmit_hiwat;
WR(q)->q_next->q_hiwat = WR(q)->q_hiwat;
- WR(q)->q_lowat = icmp_xmit_lowat;
+ WR(q)->q_lowat = is->is_xmit_lowat;
WR(q)->q_next->q_lowat = WR(q)->q_lowat;
if (icmp->icmp_family == AF_INET6) {
@@ -1423,7 +1435,8 @@
goto open_error;
}
/* Set the Stream head write offset. */
- (void) mi_set_sth_wroff(q, icmp->icmp_max_hdr_len + icmp_wroff_extra);
+ (void) mi_set_sth_wroff(q,
+ icmp->icmp_max_hdr_len + is->is_wroff_extra);
(void) mi_set_sth_hiwat(q, q->q_hiwat);
if (is_system_labeled()) {
@@ -1453,7 +1466,8 @@
open_error:
qprocsoff(q);
crfree(credp);
- (void) mi_close_comm(&icmp_g_head, q);
+ (void) mi_close_comm(&is->is_head, q);
+ netstack_rele(is->is_netstack);
return (err);
}
@@ -1475,6 +1489,8 @@
int
icmp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
{
+ icmp_t *icmp = (icmp_t *)q->q_ptr;
+ icmp_stack_t *is = icmp->icmp_is;
int *i1 = (int *)ptr;
switch (level) {
@@ -1497,7 +1513,7 @@
*i1 = IP_DEFAULT_MULTICAST_LOOP;
return (sizeof (int));
case IPV6_UNICAST_HOPS:
- *i1 = icmp_ipv6_hoplimit;
+ *i1 = is->is_ipv6_hoplimit;
return (sizeof (int));
}
break;
@@ -1523,6 +1539,7 @@
icmp_t *icmp = (icmp_t *)q->q_ptr;
int *i1 = (int *)ptr;
ip6_pkt_t *ipp = &icmp->icmp_sticky_ipp;
+ icmp_stack_t *is = icmp->icmp_is;
switch (level) {
case SOL_SOCKET:
@@ -1817,7 +1834,8 @@
return (0);
return (ip_fill_mtuinfo(&icmp->icmp_v6dst, 0,
- (struct ip6_mtuinfo *)ptr));
+ (struct ip6_mtuinfo *)ptr,
+ is->is_netstack));
case IPV6_TCLASS:
if (ipp->ipp_fields & IPPF_TCLASS)
*i1 = ipp->ipp_tclass;
@@ -1866,6 +1884,7 @@
void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
{
icmp_t *icmp = (icmp_t *)q->q_ptr;
+ icmp_stack_t *is = icmp->icmp_is;
int *i1 = (int *)invalp;
boolean_t onoff = (*i1 == 0) ? 0 : 1;
boolean_t checkonly;
@@ -2022,7 +2041,7 @@
break;
case SO_SNDBUF:
- if (*i1 > icmp_max_buf) {
+ if (*i1 > is->is_max_buf) {
*outlenp = 0;
return (ENOBUFS);
}
@@ -2032,7 +2051,7 @@
}
break;
case SO_RCVBUF:
- if (*i1 > icmp_max_buf) {
+ if (*i1 > is->is_max_buf) {
*outlenp = 0;
return (ENOBUFS);
}
@@ -2107,7 +2126,7 @@
icmp->icmp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
icmp->icmp_ip_snd_options_len;
(void) mi_set_sth_wroff(RD(q), icmp->icmp_max_hdr_len +
- icmp_wroff_extra);
+ is->is_wroff_extra);
break;
case IP_HDRINCL:
if (!checkonly)
@@ -2278,7 +2297,7 @@
if (!checkonly) {
if (*i1 == -1) {
icmp->icmp_ttl = ipp->ipp_unicast_hops =
- icmp_ipv6_hoplimit;
+ is->is_ipv6_hoplimit;
ipp->ipp_fields &= ~IPPF_UNICAST_HOPS;
/* Pass modified value to IP. */
*i1 = ipp->ipp_hoplimit;
@@ -2478,7 +2497,8 @@
if (*i1 > 255 || *i1 < -1)
return (EINVAL);
if (*i1 == -1)
- ipp->ipp_hoplimit = icmp_ipv6_hoplimit;
+ ipp->ipp_hoplimit =
+ is->is_ipv6_hoplimit;
else
ipp->ipp_hoplimit = *i1;
ipp->ipp_fields |= IPPF_HOPLIMIT;
@@ -2814,6 +2834,7 @@
static int
icmp_build_hdrs(queue_t *q, icmp_t *icmp)
{
+ icmp_stack_t *is = icmp->icmp_is;
uchar_t *hdrs;
uint_t hdrs_len;
ip6_t *ip6h;
@@ -2864,7 +2885,7 @@
if (hdrs_len > icmp->icmp_max_hdr_len) {
icmp->icmp_max_hdr_len = hdrs_len;
(void) mi_set_sth_wroff(RD(q), icmp->icmp_max_hdr_len +
- icmp_wroff_extra);
+ is->is_wroff_extra);
}
return (0);
}
@@ -2889,21 +2910,21 @@
* named dispatch (ND) handler.
*/
static boolean_t
-icmp_param_register(icmpparam_t *icmppa, int cnt)
+icmp_param_register(IDP *ndp, icmpparam_t *icmppa, int cnt)
{
for (; cnt-- > 0; icmppa++) {
if (icmppa->icmp_param_name && icmppa->icmp_param_name[0]) {
- if (!nd_load(&icmp_g_nd, icmppa->icmp_param_name,
+ if (!nd_load(ndp, icmppa->icmp_param_name,
icmp_param_get, icmp_param_set,
(caddr_t)icmppa)) {
- nd_free(&icmp_g_nd);
+ nd_free(ndp);
return (B_FALSE);
}
}
}
- if (!nd_load(&icmp_g_nd, "icmp_status", icmp_status_report, NULL,
+ if (!nd_load(ndp, "icmp_status", icmp_status_report, NULL,
NULL)) {
- nd_free(&icmp_g_nd);
+ nd_free(ndp);
return (B_FALSE);
}
return (B_TRUE);
@@ -2937,7 +2958,8 @@
struct T_unitdata_ind *tudi;
uchar_t *rptr;
struct T_error_ack *tea;
- icmp_t *icmp;
+ icmp_t *icmp = (icmp_t *)q->q_ptr;
+ icmp_stack_t *is = icmp->icmp_is;
sin_t *sin;
sin6_t *sin6;
ip6_t *ip6h;
@@ -2956,7 +2978,6 @@
boolean_t icmp_ipv6_recvhoplimit = B_FALSE;
uint_t hopstrip;
- icmp = (icmp_t *)q->q_ptr;
if (icmp->icmp_restricted) {
putnext(q, mp);
return;
@@ -3106,7 +3127,7 @@
freemsg(mp);
if (options_mp != NULL)
freeb(options_mp);
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInErrors);
return;
}
ipvers = IPH_HDR_VERSION((ipha_t *)rptr);
@@ -3133,7 +3154,7 @@
}
}
}
- if (icmp_bsd_compat) {
+ if (is->is_bsd_compat) {
ushort_t len;
len = ntohs(ipha->ipha_length);
@@ -3149,7 +3170,8 @@
freemsg(mp);
if (options_mp != NULL)
freeb(options_mp);
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipInErrors);
return;
}
bcopy(rptr, mp1->b_rptr, hdr_len);
@@ -3199,7 +3221,7 @@
freemsg(mp);
if (options_mp != NULL)
freeb(options_mp);
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInErrors);
return;
}
mp1->b_cont = mp;
@@ -3289,7 +3311,7 @@
ASSERT(udi_size == 0);
}
- BUMP_MIB(&rawip_mib, rawipInDatagrams);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInDatagrams);
putnext(q, mp);
return;
}
@@ -3310,7 +3332,7 @@
IPH_HDR_VERSION((ipha_t *)rptr) != IPV6_VERSION ||
icmp->icmp_family != AF_INET6) {
freemsg(mp);
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInErrors);
return;
}
@@ -3449,7 +3471,8 @@
ip0dbg(("icmp_rput: RAW checksum "
"failed %x\n", sum));
freemsg(mp);
- BUMP_MIB(&rawip_mib, rawipInCksumErrs);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipInCksumErrs);
return;
}
}
@@ -3516,7 +3539,7 @@
mp1 = allocb(udi_size, BPRI_MED);
if (mp1 == NULL) {
freemsg(mp);
- BUMP_MIB(&rawip_mib, rawipInErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInErrors);
return;
}
mp1->b_cont = mp;
@@ -3545,7 +3568,7 @@
sin6->sin6_scope_id = 0;
sin6->__sin6_src_id = ip_srcid_find_addr(&ip6h->ip6_dst,
- icmp->icmp_zoneid);
+ icmp->icmp_zoneid, is->is_netstack);
if (udi_size != 0) {
uchar_t *dstopt;
@@ -3664,7 +3687,7 @@
/* Consumed all of allocated space */
ASSERT(udi_size == 0);
}
- BUMP_MIB(&rawip_mib, rawipInDatagrams);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipInDatagrams);
putnext(q, mp);
}
@@ -3795,6 +3818,7 @@
{
mblk_t *mpdata;
struct opthdr *optp;
+ icmp_t *icmp = (icmp_t *)q->q_ptr;
if (mpctl == NULL ||
(mpdata = mpctl->b_cont) == NULL) {
@@ -3805,7 +3829,8 @@
optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
optp->level = EXPER_RAWIP;
optp->name = 0;
- (void) snmp_append_data(mpdata, (char *)&rawip_mib, sizeof (rawip_mib));
+ (void) snmp_append_data(mpdata, (char *)&icmp->icmp_rawip_mib,
+ sizeof (icmp->icmp_rawip_mib));
optp->len = msgdsize(mpdata);
qreply(q, mpctl);
@@ -3840,6 +3865,10 @@
char *state;
char laddrbuf[INET6_ADDRSTRLEN];
char faddrbuf[INET6_ADDRSTRLEN];
+ icmp_stack_t *is;
+
+ icmp = (icmp_t *)q->q_ptr;
+ is = icmp->icmp_is;
(void) mi_mpprintf(mp,
"RAWIP " MI_COL_HDRPAD_STR
@@ -3848,9 +3877,9 @@
/* xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx UNBOUND */
- for (idp = mi_first_ptr(&icmp_g_head);
+ for (idp = mi_first_ptr(&is->is_head);
(icmp = (icmp_t *)idp) != NULL;
- idp = mi_next_ptr(&icmp_g_head, idp)) {
+ idp = mi_next_ptr(&is->is_head, idp)) {
if (icmp->icmp_state == TS_UNBND)
state = "UNBOUND";
else if (icmp->icmp_state == TS_IDLE)
@@ -3933,6 +3962,7 @@
icmp_wput_hdrincl(queue_t *q, mblk_t *mp, icmp_t *icmp, ip4_pkt_t *pktinfop,
boolean_t use_putnext)
{
+ icmp_stack_t *is = icmp->icmp_is;
ipha_t *ipha;
int ip_hdr_length;
int tp_hdr_len;
@@ -3946,7 +3976,8 @@
ip_hdr_length = IP_SIMPLE_HDR_LENGTH + icmp->icmp_ip_snd_options_len;
if ((mp->b_wptr - mp->b_rptr) < IP_SIMPLE_HDR_LENGTH) {
if (!pullupmsg(mp, IP_SIMPLE_HDR_LENGTH)) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ ASSERT(icmp != NULL);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
freemsg(mp);
return;
}
@@ -3990,7 +4021,8 @@
tp_hdr_len)) {
if (!pullupmsg(mp, IP_SIMPLE_HDR_LENGTH +
tp_hdr_len)) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
freemsg(mp);
return;
}
@@ -4007,12 +4039,12 @@
icmp_ud_err(q, mp, EMSGSIZE);
return;
}
- if (!(mp1 = allocb(ip_hdr_length + icmp_wroff_extra +
+ if (!(mp1 = allocb(ip_hdr_length + is->is_wroff_extra +
tp_hdr_len, BPRI_LO))) {
icmp_ud_err(q, mp, ENOMEM);
return;
}
- mp1->b_rptr += icmp_wroff_extra;
+ mp1->b_rptr += is->is_wroff_extra;
mp1->b_wptr = mp1->b_rptr + ip_hdr_length;
ipha->ipha_length = htons((uint16_t)pkt_len);
@@ -4036,7 +4068,7 @@
* Massage source route putting first source
* route in ipha_dst.
*/
- (void) ip_massage_options(ipha);
+ (void) ip_massage_options(ipha, icmp->icmp_is->is_netstack);
}
if (pktinfop != NULL) {
@@ -4071,14 +4103,15 @@
uchar_t opt_storage[IP_MAX_OPT_LENGTH];
err = tsol_compute_label(DB_CREDDEF(mp, icmp->icmp_credp), dst,
- opt_storage, icmp->icmp_mac_exempt);
+ opt_storage, icmp->icmp_mac_exempt,
+ icmp->icmp_is->is_netstack->netstack_ip);
if (err == 0) {
err = tsol_update_options(&icmp->icmp_ip_snd_options,
&icmp->icmp_ip_snd_options_len, &icmp->icmp_label_len,
opt_storage);
}
if (err != 0) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
DTRACE_PROBE4(
tx__ip__log__drop__updatelabel__icmp,
char *, "queue(1) failed to update options(2) on mp(3)",
@@ -4104,7 +4137,8 @@
int ip_hdr_length;
#define tudr ((struct T_unitdata_req *)rptr)
size_t ip_len;
- icmp_t *icmp;
+ icmp_t *icmp = (icmp_t *)q->q_ptr;
+ icmp_stack_t *is = icmp->icmp_is;
sin6_t *sin6;
sin_t *sin;
ipaddr_t v4dst;
@@ -4114,7 +4148,6 @@
queue_t *ip_wq;
boolean_t use_putnext = B_TRUE;
- icmp = (icmp_t *)q->q_ptr;
if (icmp->icmp_restricted) {
icmp_wput_restricted(q, mp);
return;
@@ -4127,7 +4160,8 @@
ipha = (ipha_t *)mp->b_rptr;
if (mp->b_wptr - mp->b_rptr < IP_SIMPLE_HDR_LENGTH) {
if (!pullupmsg(mp, IP_SIMPLE_HDR_LENGTH)) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
freemsg(mp);
return;
}
@@ -4171,19 +4205,19 @@
if (icmp->icmp_state == TS_UNBND) {
/* If a port has not been bound to the stream, fail. */
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EPROTO);
return;
}
mp1 = mp->b_cont;
if (mp1 == NULL) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EPROTO);
return;
}
if ((rptr + tudr->DEST_offset + tudr->DEST_length) > mp->b_wptr) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EADDRNOTAVAIL);
return;
}
@@ -4194,14 +4228,14 @@
if (!OK_32PTR((char *)sin6) ||
tudr->DEST_length != sizeof (sin6_t) ||
sin6->sin6_family != AF_INET6) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EADDRNOTAVAIL);
return;
}
/* No support for mapped addresses on raw sockets */
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EADDRNOTAVAIL);
return;
}
@@ -4218,7 +4252,7 @@
if (!OK_32PTR((char *)sin) ||
tudr->DEST_length != sizeof (sin_t) ||
sin->sin_family != AF_INET) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EADDRNOTAVAIL);
return;
}
@@ -4246,7 +4280,7 @@
if (icmp_unitdata_opt_process(q, mp, &error,
(void *)pktinfop) < 0) {
/* failure */
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, error);
return;
}
@@ -4298,9 +4332,9 @@
if ((uchar_t *)ipha < mp1->b_datap->db_base ||
mp1->b_datap->db_ref != 1 ||
!OK_32PTR(ipha)) {
- if (!(mp1 = allocb(ip_hdr_length + icmp_wroff_extra,
+ if (!(mp1 = allocb(ip_hdr_length + is->is_wroff_extra,
BPRI_LO))) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, ENOMEM);
return;
}
@@ -4367,7 +4401,7 @@
* as this can cause problems in layers below.
*/
if (ip_len > IP_MAXPACKET) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EMSGSIZE);
return;
}
@@ -4392,11 +4426,11 @@
* Massage source route putting first source route in ipha_dst.
* Ignore the destination in the T_unitdata_req.
*/
- (void) ip_massage_options(ipha);
+ (void) ip_massage_options(ipha, icmp->icmp_is->is_netstack);
}
freeb(mp);
- BUMP_MIB(&rawip_mib, rawipOutDatagrams);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutDatagrams);
mblk_setcred(mp1, icmp->icmp_credp);
if (use_putnext) {
putnext(q, mp1);
@@ -4415,13 +4449,14 @@
uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
err = tsol_compute_label_v6(DB_CREDDEF(mp, icmp->icmp_credp), dst,
- opt_storage, icmp->icmp_mac_exempt);
+ opt_storage, icmp->icmp_mac_exempt,
+ icmp->icmp_is->is_netstack->netstack_ip);
if (err == 0) {
err = tsol_update_sticky(&icmp->icmp_sticky_ipp,
&icmp->icmp_label_len_v6, opt_storage);
}
if (err != 0) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
DTRACE_PROBE4(
tx__ip__log__drop__updatelabel__icmp6,
char *, "queue(1) failed to update options(2) on mp(3)",
@@ -4447,7 +4482,8 @@
mblk_t *mp1;
int ip_hdr_len = IPV6_HDR_LEN;
size_t ip_len;
- icmp_t *icmp;
+ icmp_t *icmp = (icmp_t *)q->q_ptr;
+ icmp_stack_t *is = icmp->icmp_is;
ip6_pkt_t ipp_s; /* For ancillary data options */
ip6_pkt_t *ipp = &ipp_s;
ip6_pkt_t *tipp;
@@ -4458,8 +4494,6 @@
uint8_t *nxthdr_ptr;
in6_addr_t ip6_dst;
- icmp = (icmp_t *)q->q_ptr;
-
/*
* If the local address is a mapped address return
* an error.
@@ -4468,7 +4502,7 @@
* since it is bound to a mapped address.
*/
if (IN6_IS_ADDR_V4MAPPED(&icmp->icmp_v6src)) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EADDRNOTAVAIL);
return;
}
@@ -4485,7 +4519,7 @@
if (icmp_unitdata_opt_process(q, mp, &error,
(void *)ipp) < 0) {
/* failure */
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, error);
return;
}
@@ -4695,11 +4729,11 @@
if (ip_hdr_len > icmp->icmp_max_hdr_len) {
icmp->icmp_max_hdr_len = ip_hdr_len;
(void) mi_set_sth_wroff(RD(q),
- icmp->icmp_max_hdr_len + icmp_wroff_extra);
+ icmp->icmp_max_hdr_len + is->is_wroff_extra);
}
- mp1 = allocb(ip_hdr_len + icmp_wroff_extra, BPRI_LO);
+ mp1 = allocb(ip_hdr_len + is->is_wroff_extra, BPRI_LO);
if (!mp1) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, ENOMEM);
return;
}
@@ -4800,7 +4834,8 @@
if (sin6->__sin6_src_id != 0 &&
IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) {
ip_srcid_find_id(sin6->__sin6_src_id,
- &ip6h->ip6_src, icmp->icmp_zoneid);
+ &ip6h->ip6_src, icmp->icmp_zoneid,
+ is->is_netstack);
}
}
@@ -4900,7 +4935,8 @@
* Notify the application as well.
*/
icmp_ud_err(q, mp, EPROTO);
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
return;
}
/*
@@ -4909,7 +4945,8 @@
*/
if (rth->ip6r_len & 0x1) {
icmp_ud_err(q, mp, EPROTO);
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
return;
}
/*
@@ -4918,7 +4955,8 @@
* between the first hop (in ip6_dst) and
* the destination (in the last routing hdr entry).
*/
- csum = ip_massage_options_v6(ip6h, rth);
+ csum = ip_massage_options_v6(ip6h, rth,
+ icmp->icmp_is->is_netstack);
/*
* Verify that the first hop isn't a mapped address.
* Routers along the path need to do this verification
@@ -4926,7 +4964,8 @@
*/
if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst)) {
icmp_ud_err(q, mp, EADDRNOTAVAIL);
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
return;
}
}
@@ -4943,7 +4982,7 @@
* as this can cause problems in layers below.
*/
if (ip_len > IP_MAXPACKET) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutErrors);
icmp_ud_err(q, mp, EMSGSIZE);
return;
}
@@ -4966,7 +5005,8 @@
cksum_off = ip_hdr_len + icmp->icmp_checksum_off;
if (cksum_off + sizeof (uint16_t) > mp1->b_wptr - mp1->b_rptr) {
if (!pullupmsg(mp1, cksum_off + sizeof (uint16_t))) {
- BUMP_MIB(&rawip_mib, rawipOutErrors);
+ BUMP_MIB(&icmp->icmp_rawip_mib,
+ rawipOutErrors);
freemsg(mp);
return;
}
@@ -4994,7 +5034,7 @@
freeb(mp);
/* We're done. Pass the packet to IP */
- BUMP_MIB(&rawip_mib, rawipOutDatagrams);
+ BUMP_MIB(&icmp->icmp_rawip_mib, rawipOutDatagrams);
mblk_setcred(mp1, icmp->icmp_credp);
putnext(q, mp1);
}
@@ -5117,7 +5157,7 @@
case ND_SET:
/* nd_getset performs the necessary error checking */
case ND_GET:
- if (nd_getset(q, icmp_g_nd, mp)) {
+ if (nd_getset(q, icmp->icmp_is->is_nd, mp)) {
qreply(q, mp);
return;
}
@@ -5367,21 +5407,62 @@
optcom_max_optsize(icmp_opt_obj.odb_opt_des_arr,
icmp_opt_obj.odb_opt_arr_cnt);
- (void) icmp_param_register(icmp_param_arr, A_CNT(icmp_param_arr));
-
- rawip_kstat_init();
+ /*
+ * We want to be informed each time a stack is created or
+ * destroyed in the kernel, so we can maintain the
+ * set of icmp_stack_t's.
+ */
+ netstack_register(NS_ICMP, rawip_stack_init, NULL, rawip_stack_fini);
}
void
icmp_ddi_destroy(void)
{
- nd_free(&icmp_g_nd);
-
- rawip_kstat_fini();
+ netstack_unregister(NS_ICMP);
}
+/*
+ * Initialize the ICMP stack instance.
+ */
+static void *
+rawip_stack_init(netstackid_t stackid, netstack_t *ns)
+{
+ icmp_stack_t *is;
+ icmpparam_t *pa;
+
+ is = (icmp_stack_t *)kmem_zalloc(sizeof (*is), KM_SLEEP);
+ is->is_netstack = ns;
+
+ pa = (icmpparam_t *)kmem_alloc(sizeof (icmp_param_arr), KM_SLEEP);
+ is->is_param_arr = pa;
+ bcopy(icmp_param_arr, is->is_param_arr, sizeof (icmp_param_arr));
+
+ (void) icmp_param_register(&is->is_nd,
+ is->is_param_arr, A_CNT(icmp_param_arr));
+ is->is_ksp = rawip_kstat_init(stackid);
+ return (is);
+}
+
+/*
+ * Free the ICMP stack instance.
+ */
static void
-rawip_kstat_init(void) {
+rawip_stack_fini(netstackid_t stackid, void *arg)
+{
+ icmp_stack_t *is = (icmp_stack_t *)arg;
+
+ nd_free(&is->is_nd);
+ kmem_free(is->is_param_arr, sizeof (icmp_param_arr));
+ is->is_param_arr = NULL;
+
+ rawip_kstat_fini(stackid, is->is_ksp);
+ is->is_ksp = NULL;
+ kmem_free(is, sizeof (*is));
+}
+
+static void *
+rawip_kstat_init(netstackid_t stackid) {
+ kstat_t *ksp;
rawip_named_kstat_t template = {
{ "inDatagrams", KSTAT_DATA_UINT32, 0 },
@@ -5391,45 +5472,59 @@
{ "outErrors", KSTAT_DATA_UINT32, 0 },
};
- rawip_mibkp = kstat_create("icmp", 0, "rawip", "mib2",
+ ksp = kstat_create_netstack("icmp", 0, "rawip", "mib2",
KSTAT_TYPE_NAMED,
NUM_OF_FIELDS(rawip_named_kstat_t),
- 0);
- if (rawip_mibkp == NULL)
- return;
+ 0, stackid);
+ if (ksp == NULL || ksp->ks_data == NULL)
+ return (NULL);
- bcopy(&template, rawip_mibkp->ks_data, sizeof (template));
+ bcopy(&template, ksp->ks_data, sizeof (template));
+ ksp->ks_update = rawip_kstat_update;
+ ksp->ks_private = (void *)(uintptr_t)stackid;
- rawip_mibkp->ks_update = rawip_kstat_update;
-
- kstat_install(rawip_mibkp);
+ kstat_install(ksp);
+ return (ksp);
}
static void
-rawip_kstat_fini(void) {
- if (rawip_mibkp) {
- kstat_delete(rawip_mibkp);
- rawip_mibkp = NULL;
+rawip_kstat_fini(netstackid_t stackid, kstat_t *ksp)
+{
+ if (ksp != NULL) {
+ ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
+ kstat_delete_netstack(ksp, stackid);
}
}
static int
-rawip_kstat_update(kstat_t *kp, int rw) {
+rawip_kstat_update(kstat_t *ksp, int rw)
+{
rawip_named_kstat_t *rawipkp;
+ netstackid_t stackid = (netstackid_t)(uintptr_t)ksp->ks_private;
+ netstack_t *ns;
+ icmp_stack_t *is;
- if ((kp == NULL) || (kp->ks_data == NULL))
+ if ((ksp == NULL) || (ksp->ks_data == NULL))
return (EIO);
if (rw == KSTAT_WRITE)
return (EACCES);
- rawipkp = (rawip_named_kstat_t *)kp->ks_data;
+ rawipkp = (rawip_named_kstat_t *)ksp->ks_data;
- rawipkp->inDatagrams.value.ui32 = rawip_mib.rawipInDatagrams;
- rawipkp->inCksumErrs.value.ui32 = rawip_mib.rawipInCksumErrs;
- rawipkp->inErrors.value.ui32 = rawip_mib.rawipInErrors;
- rawipkp->outDatagrams.value.ui32 = rawip_mib.rawipOutDatagrams;
- rawipkp->outErrors.value.ui32 = rawip_mib.rawipOutErrors;
-
+ ns = netstack_find_by_stackid(stackid);
+ if (ns == NULL)
+ return (-1);
+ is = ns->netstack_icmp;
+ if (is == NULL) {
+ netstack_rele(ns);
+ return (-1);
+ }
+ rawipkp->inDatagrams.value.ui32 = is->is_rawip_mib.rawipInDatagrams;
+ rawipkp->inCksumErrs.value.ui32 = is->is_rawip_mib.rawipInCksumErrs;
+ rawipkp->inErrors.value.ui32 = is->is_rawip_mib.rawipInErrors;
+ rawipkp->outDatagrams.value.ui32 = is->is_rawip_mib.rawipOutDatagrams;
+ rawipkp->outErrors.value.ui32 = is->is_rawip_mib.rawipOutErrors;
+ netstack_rele(ns);
return (0);
}
diff --git a/usr/src/uts/common/inet/ip/icmp_opt_data.c b/usr/src/uts/common/inet/ip/icmp_opt_data.c
index 3a898bb..b4a2041 100644
--- a/usr/src/uts/common/inet/ip/icmp_opt_data.c
+++ b/usr/src/uts/common/inet/ip/icmp_opt_data.c
@@ -155,7 +155,7 @@
(OP_PASSNEXT|OP_NODEFAULT|OP_VARLEN),
sizeof (struct in_pktinfo), -1 /* not initialized */ },
-{ IP_NEXTHOP, IPPROTO_IP, OA_RW, OA_RW, OP_CONFIG, OP_PASSNEXT,
+{ IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT,
sizeof (in_addr_t), -1 /* not initialized */ },
{ MRT_INIT, IPPROTO_IP, 0, OA_X, OP_CONFIG,
diff --git a/usr/src/uts/common/inet/ip/igmp.c b/usr/src/uts/common/inet/ip/igmp.c
index 7e01725..60647c3 100644
--- a/usr/src/uts/common/inet/ip/igmp.c
+++ b/usr/src/uts/common/inet/ip/igmp.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -86,27 +86,6 @@
mcast_record_t rtype, slist_t *flist);
static mrec_t *mcast_merge_rtx(ilm_t *ilm, mrec_t *rp, slist_t *flist);
-/* Following protected by igmp_timer_lock */
-static int igmp_time_to_next; /* Time since last timeout */
-static int igmp_timer_fired_last;
-uint_t igmp_deferred_next = INFINITY;
-timeout_id_t igmp_timeout_id = 0;
-kmutex_t igmp_timer_lock;
-
-/* Protected by igmp_slowtimeout_lock */
-timeout_id_t igmp_slowtimeout_id = 0;
-kmutex_t igmp_slowtimeout_lock;
-
-/* Following protected by mld_timer_lock */
-static int mld_time_to_next; /* Time since last timeout */
-static int mld_timer_fired_last;
-uint_t mld_deferred_next = INFINITY;
-timeout_id_t mld_timeout_id = 0;
-kmutex_t mld_timer_lock;
-
-/* Protected by mld_slowtimeout_lock */
-timeout_id_t mld_slowtimeout_id = 0;
-kmutex_t mld_slowtimeout_lock;
/*
* Macros used to do timer len conversions. Timer values are always
@@ -124,18 +103,16 @@
* The unit for next is milliseconds.
*/
void
-igmp_start_timers(unsigned next)
+igmp_start_timers(unsigned next, ip_stack_t *ipst)
{
int time_left;
- /* Protected by igmp_timer_lock */
- static boolean_t igmp_timer_setter_active;
int ret;
ASSERT(next != 0 && next != INFINITY);
- mutex_enter(&igmp_timer_lock);
+ mutex_enter(&ipst->ips_igmp_timer_lock);
- if (igmp_timer_setter_active) {
+ if (ipst->ips_igmp_timer_setter_active) {
/*
* Serialize timer setters, one at a time. If the
* timer is currently being set by someone,
@@ -143,21 +120,22 @@
* invoked and return. The current setter will
* take care.
*/
- igmp_time_to_next = MIN(igmp_time_to_next, next);
- mutex_exit(&igmp_timer_lock);
+ ipst->ips_igmp_time_to_next =
+ MIN(ipst->ips_igmp_time_to_next, next);
+ mutex_exit(&ipst->ips_igmp_timer_lock);
return;
} else {
- igmp_timer_setter_active = B_TRUE;
+ ipst->ips_igmp_timer_setter_active = B_TRUE;
}
- if (igmp_timeout_id == 0) {
+ if (ipst->ips_igmp_timeout_id == 0) {
/*
* The timer is inactive. We need to start a timer
*/
- igmp_time_to_next = next;
- igmp_timeout_id = timeout(igmp_timeout_handler, NULL,
- MSEC_TO_TICK(igmp_time_to_next));
- igmp_timer_setter_active = B_FALSE;
- mutex_exit(&igmp_timer_lock);
+ ipst->ips_igmp_time_to_next = next;
+ ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler,
+ (void *)ipst, MSEC_TO_TICK(ipst->ips_igmp_time_to_next));
+ ipst->ips_igmp_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
return;
}
@@ -167,17 +145,17 @@
* reschedule the timeout if the new 'next' will happen
* earlier than the currently scheduled timeout
*/
- time_left = igmp_timer_fired_last +
- MSEC_TO_TICK(igmp_time_to_next) - ddi_get_lbolt();
+ time_left = ipst->ips_igmp_timer_fired_last +
+ MSEC_TO_TICK(ipst->ips_igmp_time_to_next) - ddi_get_lbolt();
if (time_left < MSEC_TO_TICK(next)) {
- igmp_timer_setter_active = B_FALSE;
- mutex_exit(&igmp_timer_lock);
+ ipst->ips_igmp_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
return;
}
- mutex_exit(&igmp_timer_lock);
- ret = untimeout(igmp_timeout_id);
- mutex_enter(&igmp_timer_lock);
+ mutex_exit(&ipst->ips_igmp_timer_lock);
+ ret = untimeout(ipst->ips_igmp_timeout_id);
+ mutex_enter(&ipst->ips_igmp_timer_lock);
/*
* The timeout was cancelled, or the timeout handler
* completed, while we were blocked in the untimeout.
@@ -188,18 +166,19 @@
* if needed.
*/
if (ret == -1) {
- ASSERT(igmp_timeout_id == 0);
+ ASSERT(ipst->ips_igmp_timeout_id == 0);
} else {
- ASSERT(igmp_timeout_id != 0);
- igmp_timeout_id = 0;
+ ASSERT(ipst->ips_igmp_timeout_id != 0);
+ ipst->ips_igmp_timeout_id = 0;
}
- if (igmp_time_to_next != 0) {
- igmp_time_to_next = MIN(igmp_time_to_next, next);
- igmp_timeout_id = timeout(igmp_timeout_handler, NULL,
- MSEC_TO_TICK(igmp_time_to_next));
+ if (ipst->ips_igmp_time_to_next != 0) {
+ ipst->ips_igmp_time_to_next =
+ MIN(ipst->ips_igmp_time_to_next, next);
+ ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler,
+ (void *)ipst, MSEC_TO_TICK(ipst->ips_igmp_time_to_next));
}
- igmp_timer_setter_active = B_FALSE;
- mutex_exit(&igmp_timer_lock);
+ ipst->ips_igmp_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
}
/*
@@ -207,17 +186,15 @@
* The unit for next is milliseconds.
*/
void
-mld_start_timers(unsigned next)
+mld_start_timers(unsigned next, ip_stack_t *ipst)
{
int time_left;
- /* Protedted by mld_timer_lock */
- static boolean_t mld_timer_setter_active;
int ret;
ASSERT(next != 0 && next != INFINITY);
- mutex_enter(&mld_timer_lock);
- if (mld_timer_setter_active) {
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ if (ipst->ips_mld_timer_setter_active) {
/*
* Serialize timer setters, one at a time. If the
* timer is currently being set by someone,
@@ -225,21 +202,22 @@
* invoked and return. The current setter will
* take care.
*/
- mld_time_to_next = MIN(mld_time_to_next, next);
- mutex_exit(&mld_timer_lock);
+ ipst->ips_mld_time_to_next =
+ MIN(ipst->ips_mld_time_to_next, next);
+ mutex_exit(&ipst->ips_mld_timer_lock);
return;
} else {
- mld_timer_setter_active = B_TRUE;
+ ipst->ips_mld_timer_setter_active = B_TRUE;
}
- if (mld_timeout_id == 0) {
+ if (ipst->ips_mld_timeout_id == 0) {
/*
* The timer is inactive. We need to start a timer
*/
- mld_time_to_next = next;
- mld_timeout_id = timeout(mld_timeout_handler, NULL,
- MSEC_TO_TICK(mld_time_to_next));
- mld_timer_setter_active = B_FALSE;
- mutex_exit(&mld_timer_lock);
+ ipst->ips_mld_time_to_next = next;
+ ipst->ips_mld_timeout_id = timeout(mld_timeout_handler,
+ (void *)ipst, MSEC_TO_TICK(ipst->ips_mld_time_to_next));
+ ipst->ips_mld_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_mld_timer_lock);
return;
}
@@ -249,17 +227,17 @@
* reschedule the timeout if the new 'next' will happen
* earlier than the currently scheduled timeout
*/
- time_left = mld_timer_fired_last +
- MSEC_TO_TICK(mld_time_to_next) - ddi_get_lbolt();
+ time_left = ipst->ips_mld_timer_fired_last +
+ MSEC_TO_TICK(ipst->ips_mld_time_to_next) - ddi_get_lbolt();
if (time_left < MSEC_TO_TICK(next)) {
- mld_timer_setter_active = B_FALSE;
- mutex_exit(&mld_timer_lock);
+ ipst->ips_mld_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_mld_timer_lock);
return;
}
- mutex_exit(&mld_timer_lock);
- ret = untimeout(mld_timeout_id);
- mutex_enter(&mld_timer_lock);
+ mutex_exit(&ipst->ips_mld_timer_lock);
+ ret = untimeout(ipst->ips_mld_timeout_id);
+ mutex_enter(&ipst->ips_mld_timer_lock);
/*
* The timeout was cancelled, or the timeout handler
* completed, while we were blocked in the untimeout.
@@ -270,18 +248,19 @@
* if needed.
*/
if (ret == -1) {
- ASSERT(mld_timeout_id == 0);
+ ASSERT(ipst->ips_mld_timeout_id == 0);
} else {
- ASSERT(mld_timeout_id != 0);
- mld_timeout_id = 0;
+ ASSERT(ipst->ips_mld_timeout_id != 0);
+ ipst->ips_mld_timeout_id = 0;
}
- if (mld_time_to_next != 0) {
- mld_time_to_next = MIN(mld_time_to_next, next);
- mld_timeout_id = timeout(mld_timeout_handler, NULL,
- MSEC_TO_TICK(mld_time_to_next));
+ if (ipst->ips_mld_time_to_next != 0) {
+ ipst->ips_mld_time_to_next =
+ MIN(ipst->ips_mld_time_to_next, next);
+ ipst->ips_mld_timeout_id = timeout(mld_timeout_handler,
+ (void *)ipst, MSEC_TO_TICK(ipst->ips_mld_time_to_next));
}
- mld_timer_setter_active = B_FALSE;
- mutex_exit(&mld_timer_lock);
+ ipst->ips_mld_timer_setter_active = B_FALSE;
+ mutex_exit(&ipst->ips_mld_timer_lock);
}
/*
@@ -303,14 +282,16 @@
uint32_t group;
uint_t next;
ipif_t *ipif;
+ ip_stack_t *ipst;
ASSERT(ill != NULL);
ASSERT(!ill->ill_isv6);
- ++igmpstat.igps_rcv_total;
+ ipst = ill->ill_ipst;
+ ++ipst->ips_igmpstat.igps_rcv_total;
mblklen = MBLKL(mp);
if (mblklen < 1 || mblklen < (iphlen = IPH_HDR_LENGTH(ipha))) {
- ++igmpstat.igps_rcv_tooshort;
+ ++ipst->ips_igmpstat.igps_rcv_tooshort;
goto bad_pkt;
}
igmplen = ntohs(ipha->ipha_length) - iphlen;
@@ -321,7 +302,7 @@
if (MBLKL(mp) < (igmplen + iphlen)) {
mblk_t *mp1;
if ((mp1 = msgpullup(mp, -1)) == NULL) {
- ++igmpstat.igps_rcv_tooshort;
+ ++ipst->ips_igmpstat.igps_rcv_tooshort;
goto bad_pkt;
}
freemsg(mp);
@@ -333,14 +314,14 @@
* Validate lengths
*/
if (igmplen < IGMP_MINLEN) {
- ++igmpstat.igps_rcv_tooshort;
+ ++ipst->ips_igmpstat.igps_rcv_tooshort;
goto bad_pkt;
}
/*
* Validate checksum
*/
if (IP_CSUM(mp, iphlen, 0)) {
- ++igmpstat.igps_rcv_badsum;
+ ++ipst->ips_igmpstat.igps_rcv_badsum;
goto bad_pkt;
}
@@ -365,14 +346,14 @@
next = igmpv3_query_in((igmp3qa_t *)igmpa, ill,
igmplen);
} else {
- ++igmpstat.igps_rcv_tooshort;
+ ++ipst->ips_igmpstat.igps_rcv_tooshort;
goto bad_pkt;
}
if (next == 0)
goto bad_pkt;
if (next != INFINITY)
- igmp_start_timers(next);
+ igmp_start_timers(next, ipst);
break;
@@ -404,10 +385,10 @@
}
mutex_exit(&ill->ill_lock);
- ++igmpstat.igps_rcv_reports;
+ ++ipst->ips_igmpstat.igps_rcv_reports;
group = igmpa->igmpa_group;
if (!CLASSD(group)) {
- ++igmpstat.igps_rcv_badreports;
+ ++ipst->ips_igmpstat.igps_rcv_badreports;
goto bad_pkt;
}
@@ -445,7 +426,7 @@
ipif = ipif->ipif_next) {
ilm = ilm_lookup_ipif(ipif, group);
if (ilm != NULL) {
- ++igmpstat.igps_rcv_ourreports;
+ ++ipst->ips_igmpstat.igps_rcv_ourreports;
ilm->ilm_timer = INFINITY;
ilm->ilm_state = IGMP_OTHERMEMBER;
}
@@ -478,8 +459,10 @@
ilm_t *ilm;
int timer;
uint_t next;
+ ip_stack_t *ipst;
- ++igmpstat.igps_rcv_queries;
+ ipst = ill->ill_ipst;
+ ++ipst->ips_igmpstat.igps_rcv_queries;
/*
* In the IGMPv2 specification, there are 3 states and a flag.
@@ -516,7 +499,7 @@
if (ipha->ipha_dst != htonl(INADDR_ALLHOSTS_GROUP) ||
igmpa->igmpa_group != 0) {
- ++igmpstat.igps_rcv_badqueries;
+ ++ipst->ips_igmpstat.igps_rcv_badqueries;
return (0);
}
@@ -529,7 +512,7 @@
*/
group = igmpa->igmpa_group;
if (group != 0 && (!CLASSD(group))) {
- ++igmpstat.igps_rcv_badqueries;
+ ++ipst->ips_igmpstat.igps_rcv_badqueries;
return (0);
}
@@ -609,16 +592,18 @@
ilm_t *ilm;
ipaddr_t *src_array;
uint8_t qrv;
+ ip_stack_t *ipst;
+ ipst = ill->ill_ipst;
/* make sure numsrc matches packet size */
numsrc = ntohs(igmp3qa->igmp3qa_numsrc);
if (igmplen < IGMP_V3_QUERY_MINLEN + (numsrc * sizeof (ipaddr_t))) {
- ++igmpstat.igps_rcv_tooshort;
+ ++ipst->ips_igmpstat.igps_rcv_tooshort;
return (0);
}
src_array = (ipaddr_t *)&igmp3qa[1];
- ++igmpstat.igps_rcv_queries;
+ ++ipst->ips_igmpstat.igps_rcv_queries;
if ((mrd = (uint_t)igmp3qa->igmp3qa_mxrc) >= IGMP_V3_MAXRT_FPMIN) {
uint_t hdrval, mant, exp;
@@ -738,6 +723,7 @@
igmp_joingroup(ilm_t *ilm)
{
ill_t *ill;
+ ip_stack_t *ipst = ilm->ilm_ipst;
ill = ilm->ilm_ipif->ipif_ill;
@@ -802,10 +788,10 @@
* acquire the ipsq. Instead we start the timer after we get
* out of the ipsq in ipsq_exit.
*/
- mutex_enter(&igmp_timer_lock);
- igmp_deferred_next = MIN(ilm->ilm_rtx.rtx_timer,
- igmp_deferred_next);
- mutex_exit(&igmp_timer_lock);
+ mutex_enter(&ipst->ips_igmp_timer_lock);
+ ipst->ips_igmp_deferred_next = MIN(ilm->ilm_rtx.rtx_timer,
+ ipst->ips_igmp_deferred_next);
+ mutex_exit(&ipst->ips_igmp_timer_lock);
}
if (ip_debug > 1) {
@@ -820,6 +806,7 @@
mld_joingroup(ilm_t *ilm)
{
ill_t *ill;
+ ip_stack_t *ipst = ilm->ilm_ipst;
ill = ilm->ilm_ill;
@@ -880,10 +867,10 @@
* acquire the ipsq. Instead we start the timer after we get
* out of the ipsq in ipsq_exit
*/
- mutex_enter(&mld_timer_lock);
- mld_deferred_next = MIN(ilm->ilm_rtx.rtx_timer,
- mld_deferred_next);
- mutex_exit(&mld_timer_lock);
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ ipst->ips_mld_deferred_next = MIN(ilm->ilm_rtx.rtx_timer,
+ ipst->ips_mld_deferred_next);
+ mutex_exit(&ipst->ips_mld_timer_lock);
}
if (ip_debug > 1) {
@@ -982,6 +969,7 @@
{
ill_t *ill;
mrec_t *rp;
+ ip_stack_t *ipst = ilm->ilm_ipst;
ASSERT(ilm != NULL);
@@ -1059,10 +1047,10 @@
if (ilm->ilm_rtx.rtx_timer == INFINITY) {
MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer,
SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY));
- mutex_enter(&igmp_timer_lock);
- igmp_deferred_next = MIN(igmp_deferred_next,
+ mutex_enter(&ipst->ips_igmp_timer_lock);
+ ipst->ips_igmp_deferred_next = MIN(ipst->ips_igmp_deferred_next,
ilm->ilm_rtx.rtx_timer);
- mutex_exit(&igmp_timer_lock);
+ mutex_exit(&ipst->ips_igmp_timer_lock);
}
mutex_exit(&ill->ill_lock);
@@ -1074,6 +1062,7 @@
{
ill_t *ill;
mrec_t *rp = NULL;
+ ip_stack_t *ipst = ilm->ilm_ipst;
ASSERT(ilm != NULL);
@@ -1146,10 +1135,10 @@
if (ilm->ilm_rtx.rtx_timer == INFINITY) {
MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer,
SEC_TO_MSEC(ICMP6_MAX_HOST_REPORT_DELAY));
- mutex_enter(&mld_timer_lock);
- mld_deferred_next =
- MIN(mld_deferred_next, ilm->ilm_rtx.rtx_timer);
- mutex_exit(&mld_timer_lock);
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ ipst->ips_mld_deferred_next =
+ MIN(ipst->ips_mld_deferred_next, ilm->ilm_rtx.rtx_timer);
+ mutex_exit(&ipst->ips_mld_timer_lock);
}
mutex_exit(&ill->ill_lock);
@@ -1392,8 +1381,6 @@
* The igmp_slowtimeo() function is called thru another timer.
* igmp_slowtimeout_lock protects the igmp_slowtimeout_id
*/
-
-/* ARGSUSED */
void
igmp_timeout_handler(void *arg)
{
@@ -1403,16 +1390,18 @@
uint_t next;
ill_walk_context_t ctx;
boolean_t success;
+ ip_stack_t *ipst = (ip_stack_t *)arg;
- mutex_enter(&igmp_timer_lock);
- ASSERT(igmp_timeout_id != 0);
- igmp_timer_fired_last = ddi_get_lbolt();
- elapsed = igmp_time_to_next;
- igmp_time_to_next = 0;
- mutex_exit(&igmp_timer_lock);
+ ASSERT(arg != NULL);
+ mutex_enter(&ipst->ips_igmp_timer_lock);
+ ASSERT(ipst->ips_igmp_timeout_id != 0);
+ ipst->ips_igmp_timer_fired_last = ddi_get_lbolt();
+ elapsed = ipst->ips_igmp_time_to_next;
+ ipst->ips_igmp_time_to_next = 0;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
- rw_enter(&ill_g_lock, RW_READER);
- ill = ILL_START_WALK_V4(&ctx);
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
+ ill = ILL_START_WALK_V4(&ctx, ipst);
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
ASSERT(!ill->ill_isv6);
/*
@@ -1422,7 +1411,7 @@
*/
if (!ill_waiter_inc(ill))
continue;
- rw_exit(&ill_g_lock);
+ rw_exit(&ipst->ips_ill_g_lock);
success = ipsq_enter(ill, B_TRUE);
if (success) {
next = igmp_timeout_handler_per_ill(ill, elapsed);
@@ -1431,18 +1420,18 @@
ipsq_exit(ill->ill_phyint->phyint_ipsq, B_FALSE,
B_TRUE);
}
- rw_enter(&ill_g_lock, RW_READER);
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
ill_waiter_dcr(ill);
}
- rw_exit(&ill_g_lock);
+ rw_exit(&ipst->ips_ill_g_lock);
- mutex_enter(&igmp_timer_lock);
- ASSERT(igmp_timeout_id != 0);
- igmp_timeout_id = 0;
- mutex_exit(&igmp_timer_lock);
+ mutex_enter(&ipst->ips_igmp_timer_lock);
+ ASSERT(ipst->ips_igmp_timeout_id != 0);
+ ipst->ips_igmp_timeout_id = 0;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
if (global_next != INFINITY)
- igmp_start_timers(global_next);
+ igmp_start_timers(global_next, ipst);
}
/*
@@ -1645,7 +1634,6 @@
* Returns number of ticks to next event (or 0 if none).
* MT issues are same as igmp_timeout_handler
*/
-/* ARGSUSED */
void
mld_timeout_handler(void *arg)
{
@@ -1655,16 +1643,18 @@
uint_t next;
ill_walk_context_t ctx;
boolean_t success;
+ ip_stack_t *ipst = (ip_stack_t *)arg;
- mutex_enter(&mld_timer_lock);
- ASSERT(mld_timeout_id != 0);
- mld_timer_fired_last = ddi_get_lbolt();
- elapsed = mld_time_to_next;
- mld_time_to_next = 0;
- mutex_exit(&mld_timer_lock);
+ ASSERT(arg != NULL);
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ ASSERT(ipst->ips_mld_timeout_id != 0);
+ ipst->ips_mld_timer_fired_last = ddi_get_lbolt();
+ elapsed = ipst->ips_mld_time_to_next;
+ ipst->ips_mld_time_to_next = 0;
+ mutex_exit(&ipst->ips_mld_timer_lock);
- rw_enter(&ill_g_lock, RW_READER);
- ill = ILL_START_WALK_V6(&ctx);
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
+ ill = ILL_START_WALK_V6(&ctx, ipst);
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
ASSERT(ill->ill_isv6);
/*
@@ -1674,7 +1664,7 @@
*/
if (!ill_waiter_inc(ill))
continue;
- rw_exit(&ill_g_lock);
+ rw_exit(&ipst->ips_ill_g_lock);
success = ipsq_enter(ill, B_TRUE);
if (success) {
next = mld_timeout_handler_per_ill(ill, elapsed);
@@ -1683,18 +1673,18 @@
ipsq_exit(ill->ill_phyint->phyint_ipsq, B_TRUE,
B_FALSE);
}
- rw_enter(&ill_g_lock, RW_READER);
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
ill_waiter_dcr(ill);
}
- rw_exit(&ill_g_lock);
+ rw_exit(&ipst->ips_ill_g_lock);
- mutex_enter(&mld_timer_lock);
- ASSERT(mld_timeout_id != 0);
- mld_timeout_id = 0;
- mutex_exit(&mld_timer_lock);
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ ASSERT(ipst->ips_mld_timeout_id != 0);
+ ipst->ips_mld_timeout_id = 0;
+ mutex_exit(&ipst->ips_mld_timer_lock);
if (global_next != INFINITY)
- mld_start_timers(global_next);
+ mld_start_timers(global_next, ipst);
}
/*
@@ -1711,16 +1701,17 @@
* in IGMP_AGE_THRESHOLD seconds.
* - Resets slowtimeout.
*/
-/* ARGSUSED */
void
igmp_slowtimo(void *arg)
{
ill_t *ill;
ill_if_t *ifp;
avl_tree_t *avl_tree;
+ ip_stack_t *ipst = (ip_stack_t *)arg;
+ ASSERT(arg != NULL);
/* Hold the ill_g_lock so that we can safely walk the ill list */
- rw_enter(&ill_g_lock, RW_READER);
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
/*
* The ill_if_t list is circular, hence the odd loop parameters.
@@ -1730,7 +1721,8 @@
* structure (allowing us to skip if none of the instances have timers
* running).
*/
- for (ifp = IP_V4_ILL_G_LIST; ifp != (ill_if_t *)&IP_V4_ILL_G_LIST;
+ for (ifp = IP_V4_ILL_G_LIST(ipst);
+ ifp != (ill_if_t *)&IP_V4_ILL_G_LIST(ipst);
ifp = ifp->illif_next) {
/*
* illif_mcast_v[12] are set using atomics. If an ill hears
@@ -1785,11 +1777,11 @@
}
}
- rw_exit(&ill_g_lock);
- mutex_enter(&igmp_slowtimeout_lock);
- igmp_slowtimeout_id = timeout(igmp_slowtimo, NULL,
+ rw_exit(&ipst->ips_ill_g_lock);
+ mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
+ ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
- mutex_exit(&igmp_slowtimeout_lock);
+ mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
}
/*
@@ -1805,12 +1797,14 @@
ill_t *ill;
ill_if_t *ifp;
avl_tree_t *avl_tree;
+ ip_stack_t *ipst = (ip_stack_t *)arg;
+ ASSERT(arg != NULL);
/* See comments in igmp_slowtimo() above... */
- rw_enter(&ill_g_lock, RW_READER);
- for (ifp = IP_V6_ILL_G_LIST; ifp != (ill_if_t *)&IP_V6_ILL_G_LIST;
+ rw_enter(&ipst->ips_ill_g_lock, RW_READER);
+ for (ifp = IP_V6_ILL_G_LIST(ipst);
+ ifp != (ill_if_t *)&IP_V6_ILL_G_LIST(ipst);
ifp = ifp->illif_next) {
-
if (ifp->illif_mcast_v1 == 0)
continue;
@@ -1834,11 +1828,11 @@
mutex_exit(&ill->ill_lock);
}
}
- rw_exit(&ill_g_lock);
- mutex_enter(&mld_slowtimeout_lock);
- mld_slowtimeout_id = timeout(mld_slowtimo, NULL,
+ rw_exit(&ipst->ips_ill_g_lock);
+ mutex_enter(&ipst->ips_mld_slowtimeout_lock);
+ ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
- mutex_exit(&mld_slowtimeout_lock);
+ mutex_exit(&ipst->ips_mld_slowtimeout_lock);
}
/*
@@ -1861,6 +1855,7 @@
mblk_t *first_mp;
ipsec_out_t *io;
zoneid_t zoneid;
+ ip_stack_t *ipst = ill->ill_ipst;
/*
* We need to make sure this packet goes out on an ipif. If
@@ -1900,6 +1895,7 @@
if ((zoneid = ilm->ilm_zoneid) == ALL_ZONES)
zoneid = GLOBAL_ZONEID;
io->ipsec_out_zoneid = zoneid;
+ io->ipsec_out_ns = ipst->ips_netstack; /* No netstack_hold */
mp = allocb(size, BPRI_HI);
if (mp == NULL) {
@@ -1951,7 +1947,7 @@
ip_wput_multicast(ill->ill_wq, first_mp, ipif, zoneid);
- ++igmpstat.igps_snd_reports;
+ ++ipst->ips_igmpstat.igps_snd_reports;
}
/*
@@ -1979,6 +1975,7 @@
mrec_t *next_reclist = reclist;
boolean_t morepkts;
zoneid_t zoneid;
+ ip_stack_t *ipst = ill->ill_ipst;
/* if there aren't any records, there's nothing to send */
if (reclist == NULL)
@@ -2134,7 +2131,7 @@
ip_wput_multicast(ill->ill_wq, first_mp, ipif, zoneid);
- ++igmpstat.igps_snd_reports;
+ ++ipst->ips_igmpstat.igps_snd_reports;
if (morepkts) {
if (more_src_cnt > 0) {
@@ -2172,6 +2169,7 @@
in6_addr_t *v6group_ptr, *lcladdr_ptr;
uint_t next;
int mldlen;
+ ip_stack_t *ipst = ill->ill_ipst;
BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembTotal);
@@ -2228,7 +2226,7 @@
}
if (next != INFINITY)
- mld_start_timers(next);
+ mld_start_timers(next, ipst);
break;
case MLD_LISTENER_REPORT: {
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index f941309..83e13a8 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -130,115 +131,11 @@
* IP_SQUEUE_ENTER: squeue_enter
* IP_SQUEUE_FILL: squeue_fill
*/
-int ip_squeue_enter = 2;
+int ip_squeue_enter = 2; /* Setable in /etc/system */
+
squeue_func_t ip_input_proc;
-/*
- * IP statistics.
- */
-#define IP_STAT(x) (ip_statistics.x.value.ui64++)
-#define IP_STAT_UPDATE(x, n) (ip_statistics.x.value.ui64 += (n))
#define SET_BPREV_FLAG(x) ((mblk_t *)(uintptr_t)(x))
-typedef struct ip_stat {
- kstat_named_t ipsec_fanout_proto;
- kstat_named_t ip_udp_fannorm;
- kstat_named_t ip_udp_fanmb;
- kstat_named_t ip_udp_fanothers;
- kstat_named_t ip_udp_fast_path;
- kstat_named_t ip_udp_slow_path;
- kstat_named_t ip_udp_input_err;
- kstat_named_t ip_tcppullup;
- kstat_named_t ip_tcpoptions;
- kstat_named_t ip_multipkttcp;
- kstat_named_t ip_tcp_fast_path;
- kstat_named_t ip_tcp_slow_path;
- kstat_named_t ip_tcp_input_error;
- kstat_named_t ip_db_ref;
- kstat_named_t ip_notaligned1;
- kstat_named_t ip_notaligned2;
- kstat_named_t ip_multimblk3;
- kstat_named_t ip_multimblk4;
- kstat_named_t ip_ipoptions;
- kstat_named_t ip_classify_fail;
- kstat_named_t ip_opt;
- kstat_named_t ip_udp_rput_local;
- kstat_named_t ipsec_proto_ahesp;
- kstat_named_t ip_conn_flputbq;
- kstat_named_t ip_conn_walk_drain;
- kstat_named_t ip_out_sw_cksum;
- kstat_named_t ip_in_sw_cksum;
- kstat_named_t ip_trash_ire_reclaim_calls;
- kstat_named_t ip_trash_ire_reclaim_success;
- kstat_named_t ip_ire_arp_timer_expired;
- kstat_named_t ip_ire_redirect_timer_expired;
- kstat_named_t ip_ire_pmtu_timer_expired;
- kstat_named_t ip_input_multi_squeue;
- kstat_named_t ip_tcp_in_full_hw_cksum_err;
- kstat_named_t ip_tcp_in_part_hw_cksum_err;
- kstat_named_t ip_tcp_in_sw_cksum_err;
- kstat_named_t ip_tcp_out_sw_cksum_bytes;
- kstat_named_t ip_udp_in_full_hw_cksum_err;
- kstat_named_t ip_udp_in_part_hw_cksum_err;
- kstat_named_t ip_udp_in_sw_cksum_err;
- kstat_named_t ip_udp_out_sw_cksum_bytes;
- kstat_named_t ip_frag_mdt_pkt_out;
- kstat_named_t ip_frag_mdt_discarded;
- kstat_named_t ip_frag_mdt_allocfail;
- kstat_named_t ip_frag_mdt_addpdescfail;
- kstat_named_t ip_frag_mdt_allocd;
-} ip_stat_t;
-
-static ip_stat_t ip_statistics = {
- { "ipsec_fanout_proto", KSTAT_DATA_UINT64 },
- { "ip_udp_fannorm", KSTAT_DATA_UINT64 },
- { "ip_udp_fanmb", KSTAT_DATA_UINT64 },
- { "ip_udp_fanothers", KSTAT_DATA_UINT64 },
- { "ip_udp_fast_path", KSTAT_DATA_UINT64 },
- { "ip_udp_slow_path", KSTAT_DATA_UINT64 },
- { "ip_udp_input_err", KSTAT_DATA_UINT64 },
- { "ip_tcppullup", KSTAT_DATA_UINT64 },
- { "ip_tcpoptions", KSTAT_DATA_UINT64 },
- { "ip_multipkttcp", KSTAT_DATA_UINT64 },
- { "ip_tcp_fast_path", KSTAT_DATA_UINT64 },
- { "ip_tcp_slow_path", KSTAT_DATA_UINT64 },
- { "ip_tcp_input_error", KSTAT_DATA_UINT64 },
- { "ip_db_ref", KSTAT_DATA_UINT64 },
- { "ip_notaligned1", KSTAT_DATA_UINT64 },
- { "ip_notaligned2", KSTAT_DATA_UINT64 },
- { "ip_multimblk3", KSTAT_DATA_UINT64 },
- { "ip_multimblk4", KSTAT_DATA_UINT64 },
- { "ip_ipoptions", KSTAT_DATA_UINT64 },
- { "ip_classify_fail", KSTAT_DATA_UINT64 },
- { "ip_opt", KSTAT_DATA_UINT64 },
- { "ip_udp_rput_local", KSTAT_DATA_UINT64 },
- { "ipsec_proto_ahesp", KSTAT_DATA_UINT64 },
- { "ip_conn_flputbq", KSTAT_DATA_UINT64 },
- { "ip_conn_walk_drain", KSTAT_DATA_UINT64 },
- { "ip_out_sw_cksum", KSTAT_DATA_UINT64 },
- { "ip_in_sw_cksum", KSTAT_DATA_UINT64 },
- { "ip_trash_ire_reclaim_calls", KSTAT_DATA_UINT64 },
- { "ip_trash_ire_reclaim_success", KSTAT_DATA_UINT64 },
- { "ip_ire_arp_timer_expired", KSTAT_DATA_UINT64 },
- { "ip_ire_redirect_timer_expired", KSTAT_DATA_UINT64 },
- { "ip_ire_pmtu_timer_expired", KSTAT_DATA_UINT64 },
- { "ip_input_multi_squeue", KSTAT_DATA_UINT64 },
- { "ip_tcp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_tcp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_tcp_in_sw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_tcp_out_sw_cksum_bytes", KSTAT_DATA_UINT64 },
- { "ip_udp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_udp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_udp_in_sw_cksum_err", KSTAT_DATA_UINT64 },
- { "ip_udp_out_sw_cksum_bytes", KSTAT_DATA_UINT64 },
- { "ip_frag_mdt_pkt_out", KSTAT_DATA_UINT64 },
- { "ip_frag_mdt_discarded", KSTAT_DATA_UINT64 },
- { "ip_frag_mdt_allocfail", KSTAT_DATA_UINT64 },
- { "ip_frag_mdt_addpdescfail", KSTAT_DATA_UINT64 },
- { "ip_frag_mdt_allocd", KSTAT_DATA_UINT64 },
-};
-
-static kstat_t *ip_kstat;
-
#define TCP6 "tcp6"
#define TCP "tcp"
#define SCTP "sctp"
@@ -249,6 +146,9 @@
major_t SCTP_MAJ;
major_t SCTP6_MAJ;
+/*
+ * Setable in /etc/system
+ */
int ip_poll_normal_ms = 100;
int ip_poll_normal_ticks = 0;
int ip_modclose_ackwait_ms = 3000;
@@ -709,25 +609,29 @@
static mblk_t *ip_wput_attach_llhdr(mblk_t *, ire_t *, ip_proc_t, uint32_t);
static void ip_ipsec_out_prepend(mblk_t *, mblk_t *, ill_t *);
-static void icmp_frag_needed(queue_t *, mblk_t *, int, zoneid_t);
+static void icmp_frag_needed(queue_t *, mblk_t *, int, zoneid_t,
+ ip_stack_t *);
static void icmp_inbound(queue_t *, mblk_t *, boolean_t, ill_t *, int,
- uint32_t, boolean_t, boolean_t, ill_t *, zoneid_t);
+ uint32_t, boolean_t, boolean_t, ill_t *, zoneid_t);
static ipaddr_t icmp_get_nexthop_addr(ipha_t *, ill_t *, zoneid_t, mblk_t *mp);
static boolean_t icmp_inbound_too_big(icmph_t *, ipha_t *, ill_t *, zoneid_t,
- mblk_t *, int);
+ mblk_t *, int, ip_stack_t *);
static void icmp_inbound_error_fanout(queue_t *, ill_t *, mblk_t *,
icmph_t *, ipha_t *, int, int, boolean_t, boolean_t,
ill_t *, zoneid_t);
static void icmp_options_update(ipha_t *);
-static void icmp_param_problem(queue_t *, mblk_t *, uint8_t, zoneid_t);
+static void icmp_param_problem(queue_t *, mblk_t *, uint8_t, zoneid_t,
+ ip_stack_t *);
static void icmp_pkt(queue_t *, mblk_t *, void *, size_t, boolean_t,
- zoneid_t zoneid);
-static mblk_t *icmp_pkt_err_ok(mblk_t *);
-static void icmp_redirect(mblk_t *);
-static void icmp_send_redirect(queue_t *, mblk_t *, ipaddr_t);
+ zoneid_t zoneid, ip_stack_t *);
+static mblk_t *icmp_pkt_err_ok(mblk_t *, ip_stack_t *);
+static void icmp_redirect(ill_t *, mblk_t *);
+static void icmp_send_redirect(queue_t *, mblk_t *, ipaddr_t,
+ ip_stack_t *);
static void ip_arp_news(queue_t *, mblk_t *);
-static boolean_t ip_bind_insert_ire(mblk_t *, ire_t *, iulp_t *);
+static boolean_t ip_bind_insert_ire(mblk_t *, ire_t *, iulp_t *,
+ ip_stack_t *);
mblk_t *ip_dlpi_alloc(size_t, t_uscalar_t);
char *ip_dot_addr(ipaddr_t, char *);
mblk_t *ip_carve_mp(mblk_t **, ssize_t);
@@ -740,73 +644,90 @@
static void ip_fanout_udp(queue_t *, mblk_t *, ill_t *, ipha_t *, uint32_t,
boolean_t, uint_t, boolean_t, boolean_t, ill_t *, zoneid_t);
static void ip_lrput(queue_t *, mblk_t *);
-ipaddr_t ip_massage_options(ipha_t *);
static void ip_mrtun_forward(ire_t *, ill_t *, mblk_t *);
ipaddr_t ip_net_mask(ipaddr_t);
void ip_newroute(queue_t *, mblk_t *, ipaddr_t, ill_t *, conn_t *,
- zoneid_t);
+ zoneid_t, ip_stack_t *);
static void ip_newroute_ipif(queue_t *, mblk_t *, ipif_t *, ipaddr_t,
conn_t *, uint32_t, zoneid_t, ip_opt_info_t *);
char *ip_nv_lookup(nv_t *, int);
static boolean_t ip_check_for_ipsec_opt(queue_t *, mblk_t *);
static int ip_param_get(queue_t *, mblk_t *, caddr_t, cred_t *);
static int ip_param_generic_get(queue_t *, mblk_t *, caddr_t, cred_t *);
-static boolean_t ip_param_register(ipparam_t *, size_t, ipndp_t *,
- size_t);
+static boolean_t ip_param_register(IDP *ndp, ipparam_t *, size_t,
+ ipndp_t *, size_t);
static int ip_param_set(queue_t *, mblk_t *, char *, caddr_t, cred_t *);
void ip_rput(queue_t *, mblk_t *);
static void ip_rput_dlpi_writer(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp,
void *dummy_arg);
void ip_rput_forward(ire_t *, ipha_t *, mblk_t *, ill_t *);
-static int ip_rput_forward_options(mblk_t *, ipha_t *, ire_t *);
+static int ip_rput_forward_options(mblk_t *, ipha_t *, ire_t *,
+ ip_stack_t *);
static boolean_t ip_rput_local_options(queue_t *, mblk_t *, ipha_t *,
- ire_t *);
+ ire_t *, ip_stack_t *);
static boolean_t ip_rput_multimblk_ipoptions(queue_t *, ill_t *,
- mblk_t *, ipha_t **, ipaddr_t *);
-static int ip_rput_options(queue_t *, mblk_t *, ipha_t *, ipaddr_t *);
+ mblk_t *, ipha_t **, ipaddr_t *, ip_stack_t *);
+static int ip_rput_options(queue_t *, mblk_t *, ipha_t *, ipaddr_t *,
+ ip_stack_t *);
static boolean_t ip_rput_fragment(queue_t *, mblk_t **, ipha_t *, uint32_t *,
uint16_t *);
int ip_snmp_get(queue_t *, mblk_t *);
static mblk_t *ip_snmp_get_mib2_ip(queue_t *, mblk_t *,
- mib2_ipIfStatsEntry_t *);
-static mblk_t *ip_snmp_get_mib2_ip_traffic_stats(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip6(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_icmp(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_icmp6(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_igmp(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_multi(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip_addr(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip6_addr(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip_group_mem(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip6_group_mem(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip_group_src(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip6_group_src(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_virt_multi(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_multi_rtable(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip_route_media(queue_t *, mblk_t *);
-static mblk_t *ip_snmp_get_mib2_ip6_route_media(queue_t *, mblk_t *);
+ mib2_ipIfStatsEntry_t *, ip_stack_t *);
+static mblk_t *ip_snmp_get_mib2_ip_traffic_stats(queue_t *, mblk_t *,
+ ip_stack_t *);
+static mblk_t *ip_snmp_get_mib2_ip6(queue_t *, mblk_t *, ip_stack_t *);
+static mblk_t *ip_snmp_get_mib2_icmp(queue_t *, mblk_t *, ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_icmp6(queue_t *, mblk_t *, ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_igmp(queue_t *, mblk_t *, ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_multi(queue_t *, mblk_t *, ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip_addr(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip6_addr(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip_group_src(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip6_group_src(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip_group_mem(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip6_group_mem(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_virt_multi(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_multi_rtable(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip_route_media(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
+static mblk_t *ip_snmp_get_mib2_ip6_route_media(queue_t *, mblk_t *,
+ ip_stack_t *ipst);
static void ip_snmp_get2_v4(ire_t *, iproutedata_t *);
static void ip_snmp_get2_v6_route(ire_t *, iproutedata_t *);
static int ip_snmp_get2_v6_media(nce_t *, iproutedata_t *);
int ip_snmp_set(queue_t *, int, int, uchar_t *, int);
-static boolean_t ip_source_routed(ipha_t *);
+static boolean_t ip_source_routed(ipha_t *, ip_stack_t *);
static boolean_t ip_source_route_included(ipha_t *);
+static void ip_trash_ire_reclaim_stack(ip_stack_t *);
static void ip_wput_frag(ire_t *, mblk_t *, ip_pkt_t, uint32_t, uint32_t,
- zoneid_t);
-static mblk_t *ip_wput_frag_copyhdr(uchar_t *, int, int);
-static void ip_wput_local_options(ipha_t *);
+ zoneid_t, ip_stack_t *);
+static mblk_t *ip_wput_frag_copyhdr(uchar_t *, int, int, ip_stack_t *);
+static void ip_wput_local_options(ipha_t *, ip_stack_t *);
static int ip_wput_options(queue_t *, mblk_t *, ipha_t *, boolean_t,
- zoneid_t);
+ zoneid_t, ip_stack_t *);
-static void conn_drain_init(void);
-static void conn_drain_fini(void);
+static void conn_drain_init(ip_stack_t *);
+static void conn_drain_fini(ip_stack_t *);
static void conn_drain_tail(conn_t *connp, boolean_t closing);
-static void conn_walk_drain(void);
+static void conn_walk_drain(ip_stack_t *);
static void conn_walk_fanout_table(connf_t *, uint_t, pfv_t, void *,
zoneid_t);
+static void *ip_stack_init(netstackid_t stackid, netstack_t *ns);
+static void ip_stack_shutdown(netstackid_t stackid, void *arg);
+static void ip_stack_fini(netstackid_t stackid, void *arg);
+
static boolean_t conn_wantpacket(conn_t *, ill_t *, ipha_t *, int,
zoneid_t);
static void ip_arp_done(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp,
@@ -832,12 +753,14 @@
cred_t *);
static squeue_func_t ip_squeue_switch(int);
-static void ip_kstat_init(void);
-static void ip_kstat_fini(void);
+static void *ip_kstat_init(netstackid_t, ip_stack_t *);
+static void ip_kstat_fini(netstackid_t, kstat_t *);
static int ip_kstat_update(kstat_t *kp, int rw);
-static void icmp_kstat_init(void);
-static void icmp_kstat_fini(void);
+static void *icmp_kstat_init(netstackid_t);
+static void icmp_kstat_fini(netstackid_t, kstat_t *);
static int icmp_kstat_update(kstat_t *kp, int rw);
+static void *ip_kstat2_init(netstackid_t, ip_stat_t *);
+static void ip_kstat2_fini(netstackid_t, kstat_t *);
static int ip_conn_report(queue_t *, mblk_t *, caddr_t, cred_t *);
@@ -847,21 +770,13 @@
static void ip_rput_process_forward(queue_t *, mblk_t *, ire_t *,
ipha_t *, ill_t *, boolean_t);
-timeout_id_t ip_ire_expire_id; /* IRE expiration timer. */
-static clock_t ip_ire_arp_time_elapsed; /* Time since IRE cache last flushed */
-static clock_t ip_ire_rd_time_elapsed; /* ... redirect IREs last flushed */
-static clock_t ip_ire_pmtu_time_elapsed; /* Time since path mtu increase */
-
+static void ip_rput_process_forward(queue_t *, mblk_t *, ire_t *,
+ ipha_t *, ill_t *, boolean_t);
ipaddr_t ip_g_all_ones = IP_HOST_MASK;
-clock_t icmp_pkt_err_last = 0; /* Time since last icmp_pkt_err */
-uint_t icmp_pkt_err_sent = 0; /* Number of packets sent in burst */
/* How long, in seconds, we allow frags to hang around. */
#define IP_FRAG_TIMEOUT 60
-time_t ip_g_frag_timeout = IP_FRAG_TIMEOUT;
-clock_t ip_g_frag_timo_ms = IP_FRAG_TIMEOUT * 1000;
-
/*
* Threshold which determines whether MDT should be used when
* generating IP fragments; payload size must be greater than
@@ -869,49 +784,26 @@
*/
#define IP_WPUT_FRAG_MDT_MIN 32768
+/* Setable in /etc/system only */
int ip_wput_frag_mdt_min = IP_WPUT_FRAG_MDT_MIN;
-/* Protected by ip_mi_lock */
-static void *ip_g_head; /* Instance Data List Head */
-kmutex_t ip_mi_lock; /* Lock for list of instances */
-
-/* Only modified during _init and _fini thus no locking is needed. */
-caddr_t ip_g_nd; /* Named Dispatch List Head */
-
-
static long ip_rput_pullups;
int dohwcksum = 1; /* use h/w cksum if supported by the hardware */
vmem_t *ip_minor_arena;
-/*
- * MIB-2 stuff for SNMP (both IP and ICMP)
- */
-mib2_ipIfStatsEntry_t ip_mib;
-mib2_icmp_t icmp_mib;
+int ip_debug;
#ifdef DEBUG
uint32_t ipsechw_debug = 0;
#endif
-kstat_t *ip_mibkp; /* kstat exporting ip_mib data */
-kstat_t *icmp_mibkp; /* kstat exporting icmp_mib data */
-
-uint_t loopback_packets = 0;
-
/*
* Multirouting/CGTP stuff
*/
cgtp_filter_ops_t *ip_cgtp_filter_ops; /* CGTP hooks */
int ip_cgtp_filter_rev = CGTP_FILTER_REV; /* CGTP hooks version */
boolean_t ip_cgtp_filter; /* Enable/disable CGTP hooks */
-/* Interval (in ms) between consecutive 'bad MTU' warnings */
-hrtime_t ip_multirt_log_interval = 1000;
-/* Time since last warning issued. */
-static hrtime_t multirt_bad_mtu_last_time = 0;
-
-kmutex_t ip_trash_timer_lock;
-krwlock_t ip_g_nd_lock;
/*
* XXX following really should only be in a header. Would need more
@@ -991,17 +883,23 @@
{ 0, 1, 1, "ip_lso_outbound" },
#ifdef DEBUG
{ 0, 1, 0, "ip6_drop_inbound_icmpv6" },
+#else
+ { 0, 0, 0, "" },
#endif
};
-ipparam_t *ip_param_arr = lcl_param_arr;
-
-/* Extended NDP table */
+/*
+ * Extended NDP table
+ * The addresses for the first two are filled in to be ips_ip_g_forward
+ * and ips_ipv6_forward at init time.
+ */
static ipndp_t lcl_ndp_arr[] = {
/* getf setf data name */
- { ip_param_generic_get, ip_forward_set, (caddr_t)&ip_g_forward,
+#define IPNDP_IP_FORWARDING_OFFSET 0
+ { ip_param_generic_get, ip_forward_set, NULL,
"ip_forwarding" },
- { ip_param_generic_get, ip_forward_set, (caddr_t)&ipv6_forward,
+#define IPNDP_IP6_FORWARDING_OFFSET 1
+ { ip_param_generic_get, ip_forward_set, NULL,
"ip6_forwarding" },
{ ip_ill_report, NULL, NULL,
"ip_ill_status" },
@@ -1031,31 +929,14 @@
(caddr_t)&ip_squeue_enter, "ip_squeue_enter" },
{ ip_param_generic_get, ip_int_set,
(caddr_t)&ip_squeue_fanout, "ip_squeue_fanout" },
- { ip_cgtp_filter_get, ip_cgtp_filter_set, (caddr_t)&ip_cgtp_filter,
+#define IPNDP_CGTP_FILTER_OFFSET 16
+ { ip_cgtp_filter_get, ip_cgtp_filter_set, NULL,
"ip_cgtp_filter" },
{ ip_param_generic_get, ip_int_set,
- (caddr_t)&ip_soft_rings_cnt, "ip_soft_rings_cnt" }
+ (caddr_t)&ip_soft_rings_cnt, "ip_soft_rings_cnt" },
};
/*
- * ip_g_forward controls IP forwarding. It takes two values:
- * 0: IP_FORWARD_NEVER Don't forward packets ever.
- * 1: IP_FORWARD_ALWAYS Forward packets for elsewhere.
- *
- * RFC1122 says there must be a configuration switch to control forwarding,
- * but that the default MUST be to not forward packets ever. Implicit
- * control based on configuration of multiple interfaces MUST NOT be
- * implemented (Section 3.1). SunOS 4.1 did provide the "automatic" capability
- * and, in fact, it was the default. That capability is now provided in the
- * /etc/rc2.d/S69inet script.
- */
-int ip_g_forward = IP_FORWARD_DEFAULT;
-
-/* It also has an IPv6 counterpart. */
-
-int ipv6_forward = IP_FORWARD_DEFAULT;
-
-/*
* Table of IP ioctls encoding the various properties of the ioctl and
* indexed based on the last byte of the ioctl command. Occasionally there
* is a clash, and there is more than 1 ioctl with the same last byte.
@@ -1447,13 +1328,8 @@
int ip_misc_ioctl_count =
sizeof (ip_misc_ioctl_table) / sizeof (ip_ioctl_cmd_t);
-static idl_t *conn_drain_list; /* The array of conn drain lists */
-static uint_t conn_drain_list_cnt; /* Total count of conn_drain_list */
-static int conn_drain_list_index; /* Next drain_list to be used */
int conn_drain_nthreads; /* Number of drainers reqd. */
/* Settable in /etc/system */
-uint_t ip_redirect_cnt; /* Num of redirect routes in ftable */
-
/* Defined in ip_ire.c */
extern uint32_t ip_ire_max_bucket_cnt, ip6_ire_max_bucket_cnt;
extern uint32_t ip_ire_min_bucket_cnt, ip6_ire_min_bucket_cnt;
@@ -1474,15 +1350,9 @@
nv_t *ire_nv_tbl = ire_nv_arr;
-/* Defined in ip_if.c, protect the list of IPsec capable ills */
-extern krwlock_t ipsec_capab_ills_lock;
-
/* Defined in ip_netinfo.c */
extern ddi_taskq_t *eventq_queue_nic;
-/* Packet dropper for IP IPsec processing failures */
-ipdropper_t ip_dropper;
-
/* Simple ICMP IP Header Template */
static ipha_t icmp_ipha = {
IP_SIMPLE_HDR_VERSION, 0, 0, 0, 0, 0, IPPROTO_ICMP
@@ -1532,7 +1402,7 @@
* appropriately.
*/
mblk_t *
-ip_prepend_zoneid(mblk_t *mp, zoneid_t zoneid)
+ip_prepend_zoneid(mblk_t *mp, zoneid_t zoneid, ip_stack_t *ipst)
{
mblk_t *first_mp;
ipsec_out_t *io;
@@ -1545,7 +1415,7 @@
return (mp);
}
- first_mp = ipsec_alloc_ipsec_out();
+ first_mp = ipsec_alloc_ipsec_out(ipst->ips_netstack);
if (first_mp == NULL)
return (NULL);
io = (ipsec_out_t *)first_mp->b_rptr;
@@ -1580,15 +1450,19 @@
nmp = copymsg(mp->b_cont);
- if (in->ipsec_info_type == IPSEC_OUT)
- return (ipsec_out_tag(mp, nmp));
- else
- return (ipsec_in_tag(mp, nmp));
+ if (in->ipsec_info_type == IPSEC_OUT) {
+ return (ipsec_out_tag(mp, nmp,
+ ((ipsec_out_t *)in)->ipsec_out_ns));
+ } else {
+ return (ipsec_in_tag(mp, nmp,
+ ((ipsec_in_t *)in)->ipsec_in_ns));
+ }
}
/* Generate an ICMP fragmentation needed message. */
static void
-icmp_frag_needed(queue_t *q, mblk_t *mp, int mtu, zoneid_t zoneid)
+icmp_frag_needed(queue_t *q, mblk_t *mp, int mtu, zoneid_t zoneid,
+ ip_stack_t *ipst)
{
icmph_t icmph;
mblk_t *first_mp;
@@ -1596,7 +1470,7 @@
EXTRACT_PKT_MP(mp, first_mp, mctl_present);
- if (!(mp = icmp_pkt_err_ok(mp))) {
+ if (!(mp = icmp_pkt_err_ok(mp, ipst))) {
if (mctl_present)
freeb(first_mp);
return;
@@ -1606,9 +1480,10 @@
icmph.icmph_type = ICMP_DEST_UNREACHABLE;
icmph.icmph_code = ICMP_FRAGMENTATION_NEEDED;
icmph.icmph_du_mtu = htons((uint16_t)mtu);
- BUMP_MIB(&icmp_mib, icmpOutFragNeeded);
- BUMP_MIB(&icmp_mib, icmpOutDestUnreachs);
- icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutFragNeeded);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDestUnreachs);
+ icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid,
+ ipst);
}
/*
@@ -1720,8 +1595,10 @@
boolean_t onlink;
timestruc_t now;
uint32_t ill_index;
+ ip_stack_t *ipst;
ASSERT(ill != NULL);
+ ipst = ill->ill_ipst;
first_mp = mp;
if (mctl_present) {
@@ -1730,9 +1607,9 @@
}
ipha = (ipha_t *)mp->b_rptr;
- if (icmp_accept_clear_messages == 0) {
+ if (ipst->ips_icmp_accept_clear_messages == 0) {
first_mp = ipsec_check_global_policy(first_mp, NULL,
- ipha, NULL, mctl_present);
+ ipha, NULL, mctl_present, ipst->ips_netstack);
if (first_mp == NULL)
return;
}
@@ -1747,7 +1624,7 @@
if (!tsol_can_accept_raw(mp, B_FALSE)) {
ip1dbg(("icmp_inbound: zone %d can't receive raw",
zoneid));
- BUMP_MIB(&icmp_mib, icmpInErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInErrors);
freemsg(first_mp);
return;
}
@@ -1762,12 +1639,12 @@
ASSERT(ill != NULL);
- BUMP_MIB(&icmp_mib, icmpInMsgs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInMsgs);
iph_hdr_length = IPH_HDR_LENGTH(ipha);
if ((mp->b_wptr - mp->b_rptr) < (iph_hdr_length + ICMPH_SIZE)) {
/* Last chance to get real. */
if (!pullupmsg(mp, iph_hdr_length + ICMPH_SIZE)) {
- BUMP_MIB(&icmp_mib, icmpInErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInErrors);
freemsg(first_mp);
return;
}
@@ -1777,7 +1654,7 @@
/* ICMP header checksum, including checksum field, should be zero. */
if (sum_valid ? (sum != 0 && sum != 0xFFFF) :
IP_CSUM(mp, iph_hdr_length, 0)) {
- BUMP_MIB(&icmp_mib, icmpInCksumErrs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInCksumErrs);
freemsg(first_mp);
return;
}
@@ -1790,22 +1667,22 @@
interested = B_FALSE;
switch (icmph->icmph_type) {
case ICMP_ECHO_REPLY:
- BUMP_MIB(&icmp_mib, icmpInEchoReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInEchoReps);
break;
case ICMP_DEST_UNREACHABLE:
if (icmph->icmph_code == ICMP_FRAGMENTATION_NEEDED)
- BUMP_MIB(&icmp_mib, icmpInFragNeeded);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInFragNeeded);
interested = B_TRUE; /* Pass up to transport */
- BUMP_MIB(&icmp_mib, icmpInDestUnreachs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInDestUnreachs);
break;
case ICMP_SOURCE_QUENCH:
interested = B_TRUE; /* Pass up to transport */
- BUMP_MIB(&icmp_mib, icmpInSrcQuenchs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInSrcQuenchs);
break;
case ICMP_REDIRECT:
- if (!ip_ignore_redirect)
+ if (!ipst->ips_ip_ignore_redirect)
interested = B_TRUE;
- BUMP_MIB(&icmp_mib, icmpInRedirects);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInRedirects);
break;
case ICMP_ECHO_REQUEST:
/*
@@ -1819,29 +1696,29 @@
interested = B_TRUE;
} else if (CLASSD(ipha->ipha_dst)) {
/* multicast: respond based on tunable */
- interested = ip_g_resp_to_echo_mcast;
+ interested = ipst->ips_ip_g_resp_to_echo_mcast;
} else if (broadcast) {
/* broadcast: respond based on tunable */
- interested = ip_g_resp_to_echo_bcast;
+ interested = ipst->ips_ip_g_resp_to_echo_bcast;
}
- BUMP_MIB(&icmp_mib, icmpInEchos);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInEchos);
break;
case ICMP_ROUTER_ADVERTISEMENT:
case ICMP_ROUTER_SOLICITATION:
break;
case ICMP_TIME_EXCEEDED:
interested = B_TRUE; /* Pass up to transport */
- BUMP_MIB(&icmp_mib, icmpInTimeExcds);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInTimeExcds);
break;
case ICMP_PARAM_PROBLEM:
interested = B_TRUE; /* Pass up to transport */
- BUMP_MIB(&icmp_mib, icmpInParmProbs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInParmProbs);
break;
case ICMP_TIME_STAMP_REQUEST:
/* Response to Time Stamp Requests is local policy. */
- if (ip_g_resp_to_timestamp &&
+ if (ipst->ips_ip_g_resp_to_timestamp &&
/* So is whether to respond if it was an IP broadcast. */
- (!broadcast || ip_g_resp_to_timestamp_bcast)) {
+ (!broadcast || ipst->ips_ip_g_resp_to_timestamp_bcast)) {
int tstamp_len = 3 * sizeof (uint32_t);
if (wptr + tstamp_len > mp->b_wptr) {
@@ -1859,32 +1736,33 @@
}
interested = B_TRUE;
}
- BUMP_MIB(&icmp_mib, icmpInTimestamps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInTimestamps);
break;
case ICMP_TIME_STAMP_REPLY:
- BUMP_MIB(&icmp_mib, icmpInTimestampReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInTimestampReps);
break;
case ICMP_INFO_REQUEST:
/* Per RFC 1122 3.2.2.7, ignore this. */
case ICMP_INFO_REPLY:
break;
case ICMP_ADDRESS_MASK_REQUEST:
- if ((ip_respond_to_address_mask_broadcast || !broadcast) &&
+ if ((ipst->ips_ip_respond_to_address_mask_broadcast ||
+ !broadcast) &&
/* TODO m_pullup of complete header? */
(mp->b_datap->db_lim - wptr) >= IP_ADDR_LEN)
interested = B_TRUE;
- BUMP_MIB(&icmp_mib, icmpInAddrMasks);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInAddrMasks);
break;
case ICMP_ADDRESS_MASK_REPLY:
- BUMP_MIB(&icmp_mib, icmpInAddrMaskReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInAddrMaskReps);
break;
default:
interested = B_TRUE; /* Pass up to transport */
- BUMP_MIB(&icmp_mib, icmpInUnknowns);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInUnknowns);
break;
}
/* See if there is an ICMP client. */
- if (ipcl_proto_search(IPPROTO_ICMP) != NULL) {
+ if (ipst->ips_ipcl_proto_fanout[IPPROTO_ICMP].connf_head != NULL) {
/* If there is an ICMP client and we want one too, copy it. */
mblk_t *first_mp1;
@@ -1906,14 +1784,14 @@
* Initiate policy processing for this packet if ip_policy
* is true.
*/
- if (IPP_ENABLED(IPP_LOCAL_IN) && ip_policy) {
+ if (IPP_ENABLED(IPP_LOCAL_IN, ipst) && ip_policy) {
ill_index = ill->ill_phyint->phyint_ifindex;
ip_process(IPP_LOCAL_IN, &mp, ill_index);
if (mp == NULL) {
if (mctl_present) {
freeb(first_mp);
}
- BUMP_MIB(&icmp_mib, icmpInErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInErrors);
return;
}
}
@@ -1926,7 +1804,7 @@
first_mp1 = ip_copymsg(first_mp);
freemsg(first_mp);
if (!first_mp1) {
- BUMP_MIB(&icmp_mib, icmpOutDrops);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDrops);
return;
}
first_mp = first_mp1;
@@ -1954,11 +1832,11 @@
icmph->icmph_type = ICMP_ADDRESS_MASK_REPLY;
bcopy(&ipif->ipif_net_mask, wptr, IP_ADDR_LEN);
ipif_refrele(ipif);
- BUMP_MIB(&icmp_mib, icmpOutAddrMaskReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutAddrMaskReps);
break;
case ICMP_ECHO_REQUEST:
icmph->icmph_type = ICMP_ECHO_REPLY;
- BUMP_MIB(&icmp_mib, icmpOutEchoReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutEchoReps);
break;
case ICMP_TIME_STAMP_REQUEST: {
uint32_t *tsp;
@@ -1972,7 +1850,7 @@
now.tv_nsec / (NANOSEC / MILLISEC);
*tsp++ = htonl(ts); /* Lay in 'receive time' */
*tsp++ = htonl(ts); /* Lay in 'send time' */
- BUMP_MIB(&icmp_mib, icmpOutTimestampReps);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutTimestampReps);
break;
}
default:
@@ -2016,12 +1894,12 @@
if (mctl_present) {
freeb(first_mp);
}
- icmp_redirect(mp);
+ icmp_redirect(ill, mp);
return;
case ICMP_DEST_UNREACHABLE:
if (icmph->icmph_code == ICMP_FRAGMENTATION_NEEDED) {
if (!icmp_inbound_too_big(icmph, ipha, ill,
- zoneid, mp, iph_hdr_length)) {
+ zoneid, mp, iph_hdr_length, ipst)) {
freemsg(first_mp);
return;
}
@@ -2086,7 +1964,7 @@
ipif_refrele(ipif);
}
/* Reset time to live. */
- ipha->ipha_ttl = ip_def_ttl;
+ ipha->ipha_ttl = ipst->ips_ip_def_ttl;
{
/* Swap source and destination addresses */
ipaddr_t tmp;
@@ -2132,7 +2010,7 @@
* accept packets for them afterwards.
*/
src_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE, ipst);
if (src_ire == NULL) {
ipif = ipif_get_next_ipif(NULL, ill);
if (ipif == NULL) {
@@ -2142,7 +2020,7 @@
}
src_ire = ire_ftable_lookup(ipha->ipha_dst, 0, 0,
IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
- NULL, MATCH_IRE_ILL | MATCH_IRE_TYPE);
+ NULL, MATCH_IRE_ILL | MATCH_IRE_TYPE, ipst);
ipif_refrele(ipif);
if (src_ire != NULL) {
onlink = B_TRUE;
@@ -2160,7 +2038,8 @@
* we attach a IPSEC_IN mp and clear ipsec_in_secure.
*/
ASSERT(first_mp == mp);
- if ((first_mp = ipsec_in_alloc(B_TRUE)) == NULL) {
+ first_mp = ipsec_in_alloc(B_TRUE, ipst->ips_netstack);
+ if (first_mp == NULL) {
BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
freemsg(mp);
return;
@@ -2182,8 +2061,10 @@
ii->ipsec_in_attach_if = B_TRUE;
ii->ipsec_in_ill_index = ill->ill_phyint->phyint_ifindex;
ii->ipsec_in_rill_index = recv_ill->ill_phyint->phyint_ifindex;
+ ii->ipsec_in_ns = ipst->ips_netstack; /* No netstack_hold */
} else {
ii = (ipsec_in_t *)first_mp->b_rptr;
+ ii->ipsec_in_ns = ipst->ips_netstack; /* No netstack_hold */
}
ii->ipsec_in_zoneid = zoneid;
ASSERT(zoneid != ALL_ZONES);
@@ -2191,7 +2072,7 @@
BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
return;
}
- BUMP_MIB(&icmp_mib, icmpOutMsgs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutMsgs);
put(WR(q), first_mp);
}
@@ -2204,6 +2085,7 @@
int hdr_length = IPH_HDR_LENGTH(ipha);
uint16_t *up;
uint32_t ports;
+ ip_stack_t *ipst = ill->ill_ipst;
up = (uint16_t *)((uchar_t *)ipha + hdr_length);
switch (ipha->ipha_protocol) {
@@ -2214,7 +2096,7 @@
/* do a reverse lookup */
tcph = (tcph_t *)((uchar_t *)ipha + hdr_length);
connp = ipcl_tcp_lookup_reversed_ipv4(ipha, tcph,
- TCPS_LISTEN);
+ TCPS_LISTEN, ipst);
break;
}
case IPPROTO_UDP:
@@ -2228,7 +2110,8 @@
dstport = htons(ntohl(ports) & 0xFFFF);
srcport = htons(ntohl(ports) >> 16);
- connfp = &ipcl_udp_fanout[IPCL_UDP_HASH(dstport)];
+ connfp = &ipst->ips_ipcl_udp_fanout[
+ IPCL_UDP_HASH(dstport, ipst)];
mutex_enter(&connfp->connf_lock);
connp = connfp->connf_head;
@@ -2253,10 +2136,11 @@
((uint16_t *)&ports)[0] = up[1];
((uint16_t *)&ports)[1] = up[0];
- if ((connp = sctp_find_conn(&map_src, &map_dst, ports,
- 0, zoneid)) == NULL) {
+ connp = sctp_find_conn(&map_src, &map_dst, ports,
+ 0, zoneid, ipst->ips_netstack->netstack_sctp);
+ if (connp == NULL) {
connp = ipcl_classify_raw(mp, IPPROTO_SCTP,
- zoneid, ports, ipha);
+ zoneid, ports, ipha, ipst);
} else {
CONN_INC_REF(connp);
SCTP_REFRELE(CONN2SCTP(connp));
@@ -2271,7 +2155,8 @@
ripha.ipha_dst = ipha->ipha_src;
ripha.ipha_protocol = ipha->ipha_protocol;
- connfp = &ipcl_proto_fanout[ipha->ipha_protocol];
+ connfp = &ipst->ips_ipcl_proto_fanout[
+ ipha->ipha_protocol];
mutex_enter(&connfp->connf_lock);
connp = connfp->connf_head;
for (connp = connfp->connf_head; connp != NULL;
@@ -2308,7 +2193,8 @@
*/
static boolean_t
icmp_inbound_too_big(icmph_t *icmph, ipha_t *ipha, ill_t *ill,
- zoneid_t zoneid, mblk_t *mp, int iph_hdr_length)
+ zoneid_t zoneid, mblk_t *mp, int iph_hdr_length,
+ ip_stack_t *ipst)
{
ire_t *ire, *first_ire;
int mtu;
@@ -2345,11 +2231,11 @@
/* nexthop set */
first_ire = ire_ctable_lookup(ipha->ipha_dst,
nexthop_addr, 0, NULL, ALL_ZONES, MBLK_GETLABEL(mp),
- MATCH_IRE_MARK_PRIVATE_ADDR | MATCH_IRE_GW);
+ MATCH_IRE_MARK_PRIVATE_ADDR | MATCH_IRE_GW, ipst);
} else {
/* nexthop not set */
first_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_CACHE,
- NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE, ipst);
}
if (!first_ire) {
@@ -2553,9 +2439,13 @@
ipsec_in_t *ii;
tcph_t *tcph;
conn_t *connp;
+ ip_stack_t *ipst;
ASSERT(ill != NULL);
+ ASSERT(recv_ill != NULL);
+ ipst = recv_ill->ill_ipst;
+
first_mp = mp;
if (mctl_present) {
mp = first_mp->b_cont;
@@ -2628,7 +2518,8 @@
* in the form we sent it out.
*/
tcph = (tcph_t *)((uchar_t *)ipha + hdr_length);
- connp = ipcl_tcp_lookup_reversed_ipv4(ipha, tcph, TCPS_LISTEN);
+ connp = ipcl_tcp_lookup_reversed_ipv4(ipha, tcph, TCPS_LISTEN,
+ ipst);
if (connp == NULL)
goto discard_pkt;
@@ -2677,6 +2568,7 @@
case IPPROTO_ESP:
case IPPROTO_AH: {
int ipsec_rc;
+ ipsec_stack_t *ipss = ipst->ips_netstack->netstack_ipsec;
/*
* We need a IPSEC_IN in the front to fanout to AH/ESP.
@@ -2718,7 +2610,7 @@
* to locate the ill.
*/
ASSERT(first_mp == mp);
- first_mp = ipsec_in_alloc(B_TRUE);
+ first_mp = ipsec_in_alloc(B_TRUE, ipst->ips_netstack);
if (first_mp == NULL) {
freemsg(mp);
BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
@@ -2738,8 +2630,8 @@
}
ip2dbg(("icmp_inbound_error: ipsec\n"));
- if (!ipsec_loaded()) {
- ip_proto_not_sup(q, first_mp, 0, zoneid);
+ if (!ipsec_loaded(ipss)) {
+ ip_proto_not_sup(q, first_mp, 0, zoneid, ipst);
return;
}
@@ -3139,9 +3031,8 @@
/*
* Process received ICMP Redirect messages.
*/
-/* ARGSUSED */
static void
-icmp_redirect(mblk_t *mp)
+icmp_redirect(ill_t *ill, mblk_t *mp)
{
ipha_t *ipha;
int iph_hdr_length;
@@ -3153,12 +3044,16 @@
ipaddr_t src, dst, gateway;
iulp_t ulp_info = { 0 };
int error;
+ ip_stack_t *ipst;
+
+ ASSERT(ill != NULL);
+ ipst = ill->ill_ipst;
ipha = (ipha_t *)mp->b_rptr;
iph_hdr_length = IPH_HDR_LENGTH(ipha);
if (((mp->b_wptr - mp->b_rptr) - iph_hdr_length) <
sizeof (icmph_t) + IP_SIMPLE_HDR_LENGTH) {
- BUMP_MIB(&icmp_mib, icmpInErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInErrors);
freemsg(mp);
return;
}
@@ -3169,14 +3064,14 @@
gateway = icmph->icmph_rd_gateway;
/* Make sure the new gateway is reachable somehow. */
ire = ire_route_lookup(gateway, 0, 0, IRE_INTERFACE, NULL, NULL,
- ALL_ZONES, NULL, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE, ipst);
/*
* Make sure we had a route for the dest in question and that
* that route was pointing to the old gateway (the source of the
* redirect packet.)
*/
prev_ire = ire_route_lookup(dst, 0, src, 0, NULL, NULL, ALL_ZONES,
- NULL, MATCH_IRE_GW);
+ NULL, MATCH_IRE_GW, ipst);
/*
* Check that
* the redirect was not from ourselves
@@ -3185,7 +3080,7 @@
if (!prev_ire ||
!ire ||
ire->ire_type == IRE_LOCAL) {
- BUMP_MIB(&icmp_mib, icmpInBadRedirects);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInBadRedirects);
freemsg(mp);
if (ire != NULL)
ire_refrele(ire);
@@ -3217,7 +3112,8 @@
tmp_ire = ire_ftable_lookup(dst, 0, gateway, 0, NULL, &sire,
ALL_ZONES, 0, NULL,
- (MATCH_IRE_RECURSIVE | MATCH_IRE_GW | MATCH_IRE_DEFAULT));
+ (MATCH_IRE_RECURSIVE | MATCH_IRE_GW | MATCH_IRE_DEFAULT),
+ ipst);
if (sire != NULL) {
bcopy(&sire->ire_uinfo, &ulp_info, sizeof (iulp_t));
/*
@@ -3249,7 +3145,7 @@
break;
default:
freemsg(mp);
- BUMP_MIB(&icmp_mib, icmpInBadRedirects);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInBadRedirects);
ire_refrele(ire);
return;
}
@@ -3278,7 +3174,8 @@
(RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST),
&ulp_info,
NULL,
- NULL);
+ NULL,
+ ipst);
if (ire == NULL) {
freemsg(mp);
@@ -3287,14 +3184,14 @@
}
error = ire_add(&ire, NULL, NULL, NULL, B_FALSE);
ire_refrele(save_ire);
- atomic_inc_32(&ip_redirect_cnt);
+ atomic_inc_32(&ipst->ips_ip_redirect_cnt);
if (error == 0) {
ire_refrele(ire); /* Held in ire_add_v4 */
/* tell routing sockets that we received a redirect */
ip_rts_change(RTM_REDIRECT, dst, gateway, IP_HOST_MASK, 0, src,
(RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST), 0,
- (RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_AUTHOR));
+ (RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_AUTHOR), ipst);
}
/*
@@ -3303,7 +3200,7 @@
* modifying an existing redirect.
*/
prev_ire = ire_ftable_lookup(dst, 0, src, IRE_HOST, NULL, NULL,
- ALL_ZONES, 0, NULL, (MATCH_IRE_GW | MATCH_IRE_TYPE));
+ ALL_ZONES, 0, NULL, (MATCH_IRE_GW | MATCH_IRE_TYPE), ipst);
if (prev_ire != NULL) {
if (prev_ire ->ire_flags & RTF_DYNAMIC)
ire_delete(prev_ire);
@@ -3317,7 +3214,8 @@
* Generate an ICMP parameter problem message.
*/
static void
-icmp_param_problem(queue_t *q, mblk_t *mp, uint8_t ptr, zoneid_t zoneid)
+icmp_param_problem(queue_t *q, mblk_t *mp, uint8_t ptr, zoneid_t zoneid,
+ ip_stack_t *ipst)
{
icmph_t icmph;
boolean_t mctl_present;
@@ -3325,7 +3223,7 @@
EXTRACT_PKT_MP(mp, first_mp, mctl_present);
- if (!(mp = icmp_pkt_err_ok(mp))) {
+ if (!(mp = icmp_pkt_err_ok(mp, ipst))) {
if (mctl_present)
freeb(first_mp);
return;
@@ -3334,8 +3232,9 @@
bzero(&icmph, sizeof (icmph_t));
icmph.icmph_type = ICMP_PARAM_PROBLEM;
icmph.icmph_pp_ptr = ptr;
- BUMP_MIB(&icmp_mib, icmpOutParmProbs);
- icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutParmProbs);
+ icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid,
+ ipst);
}
/*
@@ -3352,7 +3251,7 @@
*/
static void
icmp_pkt(queue_t *q, mblk_t *mp, void *stuff, size_t len,
- boolean_t mctl_present, zoneid_t zoneid)
+ boolean_t mctl_present, zoneid_t zoneid, ip_stack_t *ipst)
{
ipaddr_t dst;
icmph_t *icmph;
@@ -3394,7 +3293,8 @@
* Convert the IPSEC_IN to IPSEC_OUT.
*/
if (!ipsec_in_to_out(ipsec_mp, ipha, NULL)) {
- BUMP_MIB(&ip_mib, ipIfStatsOutDiscards);
+ BUMP_MIB(&ipst->ips_ip_mib,
+ ipIfStatsOutDiscards);
return;
}
io = (ipsec_out_t *)ipsec_mp->b_rptr;
@@ -3422,9 +3322,10 @@
*/
ipsec_in_t *ii;
ASSERT(DB_TYPE(mp) == M_DATA);
- if ((ipsec_mp = ipsec_in_alloc(B_TRUE)) == NULL) {
+ ipsec_mp = ipsec_in_alloc(B_TRUE, ipst->ips_netstack);
+ if (ipsec_mp == NULL) {
freemsg(mp);
- BUMP_MIB(&ip_mib, ipIfStatsOutDiscards);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
return;
}
ii = (ipsec_in_t *)ipsec_mp->b_rptr;
@@ -3445,7 +3346,7 @@
* Convert the IPSEC_IN to IPSEC_OUT.
*/
if (!ipsec_in_to_out(ipsec_mp, ipha, NULL)) {
- BUMP_MIB(&ip_mib, ipIfStatsOutDiscards);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
return;
}
io = (ipsec_out_t *)ipsec_mp->b_rptr;
@@ -3455,7 +3356,7 @@
dst = ipha->ipha_src;
ire = ire_route_lookup(ipha->ipha_dst, 0, 0, (IRE_LOCAL|IRE_LOOPBACK),
- NULL, NULL, zoneid, NULL, MATCH_IRE_TYPE);
+ NULL, NULL, zoneid, NULL, MATCH_IRE_TYPE, ipst);
if (ire != NULL &&
(ire->ire_zoneid == zoneid || ire->ire_zoneid == ALL_ZONES)) {
src = ipha->ipha_dst;
@@ -3463,9 +3364,10 @@
if (ire != NULL)
ire_refrele(ire);
ire = ire_route_lookup(dst, 0, 0, 0, NULL, NULL, zoneid, NULL,
- (MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE|MATCH_IRE_ZONEONLY));
+ (MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE|MATCH_IRE_ZONEONLY),
+ ipst);
if (ire == NULL) {
- BUMP_MIB(&ip_mib, ipIfStatsOutNoRoutes);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutNoRoutes);
freemsg(ipsec_mp);
return;
}
@@ -3481,18 +3383,18 @@
*/
if (io == NULL) {
/* This is not a IPSEC_OUT type control msg */
- BUMP_MIB(&ip_mib, ipIfStatsOutNoRoutes);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutNoRoutes);
freemsg(ipsec_mp);
return;
}
ill = ill_lookup_on_ifindex(io->ipsec_out_ill_index, B_FALSE,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, ipst);
if (ill != NULL) {
ipif = ipif_get_next_ipif(NULL, ill);
ill_refrele(ill);
}
if (ipif == NULL) {
- BUMP_MIB(&ip_mib, ipIfStatsOutNoRoutes);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutNoRoutes);
freemsg(ipsec_mp);
return;
}
@@ -3512,7 +3414,7 @@
(uchar_t *)ipha + len_needed + 1 <= mp->b_wptr) {
len_needed += IPH_HDR_LENGTH(((uchar_t *)ipha + len_needed));
}
- len_needed += ip_icmp_return;
+ len_needed += ipst->ips_ip_icmp_return;
msg_len = msgdsize(mp);
if (msg_len > len_needed) {
(void) adjmsg(mp, len_needed - msg_len);
@@ -3520,7 +3422,7 @@
}
mp1 = allocb(sizeof (icmp_ipha) + len, BPRI_HI);
if (mp1 == NULL) {
- BUMP_MIB(&icmp_mib, icmpOutErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutErrors);
freemsg(ipsec_mp);
return;
}
@@ -3551,7 +3453,7 @@
*ipha = icmp_ipha;
ipha->ipha_src = src;
ipha->ipha_dst = dst;
- ipha->ipha_ttl = ip_def_ttl;
+ ipha->ipha_ttl = ipst->ips_ip_def_ttl;
msg_len += sizeof (icmp_ipha) + len;
if (msg_len > IP_MAXPACKET) {
(void) adjmsg(mp, IP_MAXPACKET - msg_len);
@@ -3564,7 +3466,7 @@
icmph->icmph_checksum = IP_CSUM(mp, (int32_t)sizeof (ipha_t), 0);
if (icmph->icmph_checksum == 0)
icmph->icmph_checksum = 0xFFFF;
- BUMP_MIB(&icmp_mib, icmpOutMsgs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutMsgs);
put(q, ipsec_mp);
}
@@ -3579,42 +3481,43 @@
* icmp_pkt_err_sent - number of packets sent in current burst
*/
boolean_t
-icmp_err_rate_limit(void)
+icmp_err_rate_limit(ip_stack_t *ipst)
{
clock_t now = TICK_TO_MSEC(lbolt);
uint_t refilled; /* Number of packets refilled in tbf since last */
- uint_t err_interval = ip_icmp_err_interval; /* Guard against changes */
+ /* Guard against changes by loading into local variable */
+ uint_t err_interval = ipst->ips_ip_icmp_err_interval;
if (err_interval == 0)
return (B_FALSE);
- if (icmp_pkt_err_last > now) {
+ if (ipst->ips_icmp_pkt_err_last > now) {
/* 100HZ lbolt in ms for 32bit arch wraps every 49.7 days */
- icmp_pkt_err_last = 0;
- icmp_pkt_err_sent = 0;
+ ipst->ips_icmp_pkt_err_last = 0;
+ ipst->ips_icmp_pkt_err_sent = 0;
}
/*
* If we are in a burst update the token bucket filter.
* Update the "last" time to be close to "now" but make sure
* we don't loose precision.
*/
- if (icmp_pkt_err_sent != 0) {
- refilled = (now - icmp_pkt_err_last)/err_interval;
- if (refilled > icmp_pkt_err_sent) {
- icmp_pkt_err_sent = 0;
+ if (ipst->ips_icmp_pkt_err_sent != 0) {
+ refilled = (now - ipst->ips_icmp_pkt_err_last)/err_interval;
+ if (refilled > ipst->ips_icmp_pkt_err_sent) {
+ ipst->ips_icmp_pkt_err_sent = 0;
} else {
- icmp_pkt_err_sent -= refilled;
- icmp_pkt_err_last += refilled * err_interval;
+ ipst->ips_icmp_pkt_err_sent -= refilled;
+ ipst->ips_icmp_pkt_err_last += refilled * err_interval;
}
}
- if (icmp_pkt_err_sent == 0) {
+ if (ipst->ips_icmp_pkt_err_sent == 0) {
/* Start of new burst */
- icmp_pkt_err_last = now;
+ ipst->ips_icmp_pkt_err_last = now;
}
- if (icmp_pkt_err_sent < ip_icmp_err_burst) {
- icmp_pkt_err_sent++;
+ if (ipst->ips_icmp_pkt_err_sent < ipst->ips_ip_icmp_err_burst) {
+ ipst->ips_icmp_pkt_err_sent++;
ip1dbg(("icmp_err_rate_limit: %d sent in burst\n",
- icmp_pkt_err_sent));
+ ipst->ips_icmp_pkt_err_sent));
return (B_FALSE);
}
ip1dbg(("icmp_err_rate_limit: dropped\n"));
@@ -3628,7 +3531,7 @@
* ICMP error packet should be sent.
*/
static mblk_t *
-icmp_pkt_err_ok(mblk_t *mp)
+icmp_pkt_err_ok(mblk_t *mp, ip_stack_t *ipst)
{
icmph_t *icmph;
ipha_t *ipha;
@@ -3640,20 +3543,20 @@
return (NULL);
ipha = (ipha_t *)mp->b_rptr;
if (ip_csum_hdr(ipha)) {
- BUMP_MIB(&ip_mib, ipIfStatsInCksumErrs);
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsInCksumErrs);
freemsg(mp);
return (NULL);
}
src_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_BROADCAST,
- NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE, ipst);
dst_ire = ire_ctable_lookup(ipha->ipha_src, 0, IRE_BROADCAST,
- NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE, ipst);
if (src_ire != NULL || dst_ire != NULL ||
CLASSD(ipha->ipha_dst) ||
CLASSD(ipha->ipha_src) ||
(ntohs(ipha->ipha_fragment_offset_and_flags) & IPH_OFFSET)) {
/* Note: only errors to the fragment with offset 0 */
- BUMP_MIB(&icmp_mib, icmpOutDrops);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDrops);
freemsg(mp);
if (src_ire != NULL)
ire_refrele(src_ire);
@@ -3669,7 +3572,7 @@
len_needed = IPH_HDR_LENGTH(ipha) + ICMPH_SIZE;
if (mp->b_wptr - mp->b_rptr < len_needed) {
if (!pullupmsg(mp, len_needed)) {
- BUMP_MIB(&icmp_mib, icmpInErrors);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpInErrors);
freemsg(mp);
return (NULL);
}
@@ -3683,7 +3586,7 @@
case ICMP_TIME_EXCEEDED:
case ICMP_PARAM_PROBLEM:
case ICMP_REDIRECT:
- BUMP_MIB(&icmp_mib, icmpOutDrops);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDrops);
freemsg(mp);
return (NULL);
default:
@@ -3696,11 +3599,11 @@
*/
if (is_system_labeled() && !tsol_can_reply_error(mp)) {
ip2dbg(("icmp_pkt_err_ok: can't respond to packet\n"));
- BUMP_MIB(&icmp_mib, icmpOutDrops);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDrops);
freemsg(mp);
return (NULL);
}
- if (icmp_err_rate_limit()) {
+ if (icmp_err_rate_limit(ipst)) {
/*
* Only send ICMP error packets every so often.
* This should be done on a per port/source basis,
@@ -3716,7 +3619,7 @@
* Generate an ICMP redirect message.
*/
static void
-icmp_send_redirect(queue_t *q, mblk_t *mp, ipaddr_t gateway)
+icmp_send_redirect(queue_t *q, mblk_t *mp, ipaddr_t gateway, ip_stack_t *ipst)
{
icmph_t icmph;
@@ -3726,7 +3629,7 @@
*/
ASSERT(mp->b_datap->db_type == M_DATA);
- if (!(mp = icmp_pkt_err_ok(mp))) {
+ if (!(mp = icmp_pkt_err_ok(mp, ipst))) {
return;
}
@@ -3734,16 +3637,17 @@
icmph.icmph_type = ICMP_REDIRECT;
icmph.icmph_code = 1;
icmph.icmph_rd_gateway = gateway;
- BUMP_MIB(&icmp_mib, icmpOutRedirects);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutRedirects);
/* Redirects sent by router, and router is global zone */
- icmp_pkt(q, mp, &icmph, sizeof (icmph_t), B_FALSE, GLOBAL_ZONEID);
+ icmp_pkt(q, mp, &icmph, sizeof (icmph_t), B_FALSE, GLOBAL_ZONEID, ipst);
}
/*
* Generate an ICMP time exceeded message.
*/
void
-icmp_time_exceeded(queue_t *q, mblk_t *mp, uint8_t code, zoneid_t zoneid)
+icmp_time_exceeded(queue_t *q, mblk_t *mp, uint8_t code, zoneid_t zoneid,
+ ip_stack_t *ipst)
{
icmph_t icmph;
boolean_t mctl_present;
@@ -3751,7 +3655,7 @@
EXTRACT_PKT_MP(mp, first_mp, mctl_present);
- if (!(mp = icmp_pkt_err_ok(mp))) {
+ if (!(mp = icmp_pkt_err_ok(mp, ipst))) {
if (mctl_present)
freeb(first_mp);
return;
@@ -3760,15 +3664,17 @@
bzero(&icmph, sizeof (icmph_t));
icmph.icmph_type = ICMP_TIME_EXCEEDED;
icmph.icmph_code = code;
- BUMP_MIB(&icmp_mib, icmpOutTimeExcds);
- icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutTimeExcds);
+ icmp_pkt(q, first_mp, &icmph, sizeof (icmph_t), mctl_present, zoneid,
+ ipst);
}
/*
* Generate an ICMP unreachable message.
*/
void
-icmp_unreachable(queue_t *q, mblk_t *mp, uint8_t code, zoneid_t zoneid)
+icmp_unreachable(queue_t *q, mblk_t *mp, uint8_t code, zoneid_t zoneid,
+ ip_stack_t *ipst)
{
icmph_t icmph;
mblk_t *first_mp;
@@ -3776,7 +3682,7 @@
EXTRACT_PKT_MP(mp, first_mp, mctl_present);
- if (!(mp = icmp_pkt_err_ok(mp))) {
+ if (!(mp = icmp_pkt_err_ok(mp, ipst))) {
if (mctl_present)
freeb(first_mp);
return;
@@ -3785,10 +3691,10 @@
bzero(&icmph, sizeof (icmph_t));
icmph.icmph_type = ICMP_DEST_UNREACHABLE;
icmph.icmph_code = code;
- BUMP_MIB(&icmp_mib, icmpOutDestUnreachs);
+ BUMP_MIB(&ipst->ips_icmp_mib, icmpOutDestUnreachs);
ip2dbg(("send icmp destination unreachable code %d\n", code));
icmp_pkt(q, first_mp, (char *)&icmph, sizeof (icmph_t), mctl_present,
- zoneid);
+ zoneid, ipst);
}
/*
@@ -3814,6 +3720,7 @@
mblk_t *arp_add_mp;
mblk_t *arp_del_mp;
area_t *area;
+ ip_stack_t *ipst = ill->ill_ipst;
ipif->ipif_recovery_id = 0;
@@ -3853,10 +3760,10 @@
*/
freemsg(arp_add_mp);
mutex_enter(&ill->ill_lock);
- if (ip_dup_recovery > 0 && ipif->ipif_recovery_id == 0 &&
+ if (ipst->ips_ip_dup_recovery > 0 && ipif->ipif_recovery_id == 0 &&
!(ipif->ipif_state_flags & IPIF_CONDEMNED)) {
ipif->ipif_recovery_id = timeout(ipif_dup_recovery, ipif,
- MSEC_TO_TICK(ip_dup_recovery));
+ MSEC_TO_TICK(ipst->ips_ip_dup_recovery));
}
mutex_exit(&ill->ill_lock);
}
@@ -3878,6 +3785,7 @@
char sbuf[INET_ADDRSTRLEN];
const char *failtype;
boolean_t bring_up;
+ ip_stack_t *ipst = ill->ill_ipst;
switch (((arcn_t *)mp->b_rptr)->arcn_code) {
case AR_CN_READY:
@@ -3922,9 +3830,10 @@
!(ipif->ipif_flags & (IPIF_DHCPRUNNING|IPIF_TEMPORARY)) &&
ill->ill_net_type == IRE_IF_RESOLVER &&
!(ipif->ipif_state_flags & IPIF_CONDEMNED) &&
- ip_dup_recovery > 0 && ipif->ipif_recovery_id == 0) {
+ ipst->ips_ip_dup_recovery > 0 &&
+ ipif->ipif_recovery_id == 0) {
ipif->ipif_recovery_id = timeout(ipif_dup_recovery,
- ipif, MSEC_TO_TICK(ip_dup_recovery));
+ ipif, MSEC_TO_TICK(ipst->ips_ip_dup_recovery));
continue;
}
@@ -3979,9 +3888,9 @@
if (!(ipif->ipif_flags & (IPIF_DHCPRUNNING|IPIF_TEMPORARY)) &&
ill->ill_net_type == IRE_IF_RESOLVER &&
!(ipif->ipif_state_flags & IPIF_CONDEMNED) &&
- ip_dup_recovery > 0) {
+ ipst->ips_ip_dup_recovery > 0) {
ipif->ipif_recovery_id = timeout(ipif_dup_recovery,
- ipif, MSEC_TO_TICK(ip_dup_recovery));
+ ipif, MSEC_TO_TICK(ipst->ips_ip_dup_recovery));
}
mutex_exit(&ill->ill_lock);
}
@@ -4029,6 +3938,17 @@
boolean_t isv6 = B_FALSE;
ipif_t *ipif;
ill_t *ill;
+ ip_stack_t *ipst;
+
+ if (CONN_Q(q)) {
+ conn_t *connp = Q_TO_CONN(q);
+
+ ipst = connp->conn_netstack->netstack_ip;
+ } else {
+ ill_t *ill = (ill_t *)q->q_ptr;
+
+ ipst = ill->ill_ipst;
+ }
if ((mp->b_wptr - mp->b_rptr) < sizeof (arcn_t) || !mp->b_cont) {
if (q->q_next) {
@@ -4083,11 +4003,12 @@
(void) mac_colon_addr((uint8_t *)(arh + 1), arh->arh_hlen,
hbuf, sizeof (hbuf));
(void) ip_dot_addr(src, sbuf);
- if (isv6)
- ire = ire_cache_lookup_v6(&v6src, ALL_ZONES, NULL);
- else
- ire = ire_cache_lookup(src, ALL_ZONES, NULL);
-
+ if (isv6) {
+ ire = ire_cache_lookup_v6(&v6src, ALL_ZONES, NULL,
+ ipst);
+ } else {
+ ire = ire_cache_lookup(src, ALL_ZONES, NULL, ipst);
+ }
if (ire != NULL && IRE_IS_LOCAL(ire)) {
uint32_t now;
uint32_t maxage;
@@ -4104,15 +4025,15 @@
ASSERT(ipif != NULL);
now = gethrestime_sec();
maxage = now - ire->ire_create_time;
- if (maxage > ip_max_temp_idle)
- maxage = ip_max_temp_idle;
+ if (maxage > ipst->ips_ip_max_temp_idle)
+ maxage = ipst->ips_ip_max_temp_idle;
lused = drv_hztousec(ddi_get_lbolt() -
ire->ire_last_used_time) / MICROSEC + 1;
if (lused >= maxage && (ipif->ipif_flags &
(IPIF_DHCPRUNNING | IPIF_TEMPORARY)))
- maxdefense = ip_max_temp_defend;
+ maxdefense = ipst->ips_ip_max_temp_defend;
else
- maxdefense = ip_max_defend;
+ maxdefense = ipst->ips_ip_max_defend;
/*
* Now figure out how many times we've defended
@@ -4121,7 +4042,8 @@
*/
mutex_enter(&ire->ire_lock);
if ((defs = ire->ire_defense_count) > 0 &&
- now - ire->ire_defense_time > ip_defend_interval) {
+ now - ire->ire_defense_time >
+ ipst->ips_ip_defend_interval) {
ire->ire_defense_count = defs = 0;
}
ire->ire_defense_count++;
@@ -4171,7 +4093,7 @@
* Delete the IRE cache entry and NCE for this
* v6 address
*/
- ip_ire_clookup_and_delete_v6(&v6src);
+ ip_ire_clookup_and_delete_v6(&v6src, ipst);
/*
* If v6src is a non-zero, it's a router address
* as below. Do the same sort of thing to clean
@@ -4180,7 +4102,7 @@
*/
if (!IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
ire_walk_v6(ire_delete_cache_gw_v6,
- (char *)&v6src, ALL_ZONES);
+ (char *)&v6src, ALL_ZONES, ipst);
}
} else {
nce_hw_map_t hwm;
@@ -4201,7 +4123,7 @@
hwm.hwm_addr = src;
hwm.hwm_hwlen = arh->arh_hlen;
hwm.hwm_hwaddr = (uchar_t *)(arh + 1);
- ndp_walk_common(&ndp4, NULL,
+ ndp_walk_common(ipst->ips_ndp4, NULL,
(pfi_t)nce_delete_hw_changed, &hwm, ALL_ZONES);
}
break;
@@ -4213,7 +4135,7 @@
if (!(ill->ill_phyint->phyint_flags & PHYI_RUNNING))
break;
ipif = ipif_lookup_addr(src, ill, ALL_ZONES, NULL, NULL,
- NULL, NULL);
+ NULL, NULL, ipst);
if (ipif != NULL) {
/*
* If this is a duplicate recovery, then we now need to
@@ -4241,7 +4163,7 @@
ipif->ipif_addr_ready = 1;
ipif_refrele(ipif);
}
- ire = ire_cache_lookup(src, ALL_ZONES, MBLK_GETLABEL(mp));
+ ire = ire_cache_lookup(src, ALL_ZONES, MBLK_GETLABEL(mp), ipst);
if (ire != NULL) {
ire->ire_defense_count = 0;
ire_refrele(ire);
@@ -4266,7 +4188,8 @@
* application.
*/
mblk_t *
-ip_add_info(mblk_t *data_mp, ill_t *ill, uint_t flags, zoneid_t zoneid)
+ip_add_info(mblk_t *data_mp, ill_t *ill, uint_t flags, zoneid_t zoneid,
+ ip_stack_t *ipst)
{
mblk_t *mp;
ip_pktinfo_t *pinfo;
@@ -4305,7 +4228,7 @@
* ZONEONLY.
*/
ire = ire_ctable_lookup(ipha->ipha_dst, 0, 0, ipif,
- zoneid, NULL, MATCH_IRE_ILL_GROUP);
+ zoneid, NULL, MATCH_IRE_ILL_GROUP, ipst);
if (ire == NULL) {
/*
* packet must have come on a different
@@ -4315,7 +4238,7 @@
* for SECATTR and ZONEONLY.
*/
ire = ire_ctable_lookup(ipha->ipha_dst, 0, 0,
- ipif, zoneid, NULL, NULL);
+ ipif, zoneid, NULL, NULL, ipst);
}
if (ire == NULL) {
@@ -4639,6 +4562,7 @@
mblk_t *policy_mp;
ipif_t *ipif;
zoneid_t zoneid;
+ ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
if (ipsec_policy_set) {
policy_mp = mp->b_cont;
@@ -4657,7 +4581,7 @@
if (src_addr) {
src_ire = ire_route_lookup(src_addr, 0, 0, 0,
- NULL, NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
+ NULL, NULL, zoneid, NULL, MATCH_IRE_ZONEONLY, ipst);
/*
* If an address other than 0.0.0.0 is requested,
* we verify that it is a valid address for bind
@@ -4691,7 +4615,7 @@
*mp->b_wptr++ = (char)connp->conn_ulp;
if ((ipif = ipif_lookup_addr(src_addr, NULL, zoneid,
CONNP_TO_WQ(connp), mp, ip_wput_nondata,
- &error)) != NULL) {
+ &error, ipst)) != NULL) {
ipif_refrele(ipif);
} else if (error == EINPROGRESS) {
if (src_ire != NULL)
@@ -4709,7 +4633,8 @@
src_ire = ire_ctable_lookup(
INADDR_BROADCAST, INADDR_ANY,
IRE_BROADCAST, NULL, zoneid, NULL,
- (MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY));
+ (MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY),
+ ipst);
if (src_ire == NULL || !ire_requested)
error = EADDRNOTAVAIL;
} else {
@@ -4767,7 +4692,7 @@
if (error == 0) {
if (ire_requested) {
- if (!ip_bind_insert_ire(mp, src_ire, NULL)) {
+ if (!ip_bind_insert_ire(mp, src_ire, NULL, ipst)) {
error = -1;
/* Falls through to bad_addr */
}
@@ -4836,6 +4761,7 @@
ill_t *ill = NULL;
zoneid_t zoneid;
ipaddr_t src_addr = *src_addrp;
+ ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
src_ire = dst_ire = NULL;
protocol = *mp->b_wptr & 0xFF;
@@ -4857,7 +4783,7 @@
NULL, zoneid, MBLK_GETLABEL(mp),
(MATCH_IRE_RECURSIVE |
MATCH_IRE_DEFAULT | MATCH_IRE_RJ_BHOLE |
- MATCH_IRE_SECATTR));
+ MATCH_IRE_SECATTR), ipst);
} else {
/*
* If conn_dontroute is set or if conn_nexthop_set is set,
@@ -4867,8 +4793,7 @@
ipif_t *ipif;
ipif = ipif_lookup_onlink_addr(connp->conn_dontroute ?
- dst_addr : connp->conn_nexthop_v4,
- connp->conn_zoneid);
+ dst_addr : connp->conn_nexthop_v4, zoneid, ipst);
if (ipif == NULL) {
error = ENETUNREACH;
goto bad_addr;
@@ -4879,13 +4804,13 @@
if (connp->conn_nexthop_set) {
dst_ire = ire_route_lookup(connp->conn_nexthop_v4, 0,
0, 0, NULL, NULL, zoneid, MBLK_GETLABEL(mp),
- MATCH_IRE_SECATTR);
+ MATCH_IRE_SECATTR, ipst);
} else {
dst_ire = ire_route_lookup(dst_addr, 0, 0, 0, NULL,
&sire, zoneid, MBLK_GETLABEL(mp),
(MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE |
- MATCH_IRE_SECATTR));
+ MATCH_IRE_SECATTR), ipst);
}
}
/*
@@ -4943,7 +4868,7 @@
if (dst_ire != NULL && is_system_labeled() &&
!IPCL_IS_TCP(connp) &&
tsol_compute_label(DB_CREDDEF(mp, connp->conn_cred), dst_addr, NULL,
- connp->conn_mac_exempt) != 0) {
+ connp->conn_mac_exempt, ipst) != 0) {
error = EHOSTUNREACH;
if (ip_debug > 2) {
pr_addr_dbg("ip_bind_connected: no label for dst %s\n",
@@ -4983,10 +4908,11 @@
if (!ipsec_policy_set && dst_ire != NULL &&
!(dst_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST)) &&
(ill = ire_to_ill(dst_ire), ill != NULL)) {
- if (ip_lso_outbound && ILL_LSO_CAPABLE(ill)) {
+ if (ipst->ips_ip_lso_outbound && ILL_LSO_CAPABLE(ill)) {
lso_dst_ire = dst_ire;
IRE_REFHOLD(lso_dst_ire);
- } else if (ip_multidata_outbound && ILL_MDT_CAPABLE(ill)) {
+ } else if (ipst->ips_ip_multidata_outbound &&
+ ILL_MDT_CAPABLE(ill)) {
md_dst_ire = dst_ire;
IRE_REFHOLD(md_dst_ire);
}
@@ -5003,7 +4929,7 @@
src_ire = ire_ftable_lookup(dst_addr, 0, 0, 0, NULL, NULL,
zoneid, 0, NULL,
MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_RJ_BHOLE);
+ MATCH_IRE_RJ_BHOLE, ipst);
if (src_ire == NULL) {
error = EHOSTUNREACH;
goto bad_addr;
@@ -5118,7 +5044,7 @@
*/
ASSERT(src_ire == NULL);
src_ire = ire_route_lookup(src_addr, 0, 0, 0, NULL,
- NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
+ NULL, zoneid, NULL, MATCH_IRE_ZONEONLY, ipst);
/* src_ire must be a local|loopback */
if (!IRE_IS_LOCAL(src_ire)) {
if (ip_debug > 2) {
@@ -5180,7 +5106,7 @@
if (sire != NULL) {
ulp_info = &(sire->ire_uinfo);
}
- if (!ip_bind_insert_ire(mp, dst_ire, ulp_info)) {
+ if (!ip_bind_insert_ire(mp, dst_ire, ulp_info, ipst)) {
error = -1;
goto bad_addr;
}
@@ -5282,7 +5208,7 @@
* Prefers dst_ire over src_ire.
*/
static boolean_t
-ip_bind_insert_ire(mblk_t *mp, ire_t *ire, iulp_t *ulp_info)
+ip_bind_insert_ire(mblk_t *mp, ire_t *ire, iulp_t *ulp_info, ip_stack_t *ipst)
{
mblk_t *mp1;
ire_t *ret_ire = NULL;
@@ -5307,7 +5233,7 @@
* Pass the latest setting of the ip_path_mtu_discovery and
* copy the ulp info if any.
*/
- ret_ire->ire_frag_flag |= (ip_path_mtu_discovery) ?
+ ret_ire->ire_frag_flag |= (ipst->ips_ip_path_mtu_discovery) ?
IPH_DF : 0;
if (ulp_info != NULL) {
bcopy(ulp_info, &(ret_ire->ire_uinfo),
@@ -5436,6 +5362,7 @@
ipif_t *ipif;
queue_t *q = ill->ill_rq;
hook_nic_event_t *info;
+ ip_stack_t *ipst = ill->ill_ipst;
clock_t timeout;
/*
@@ -5536,8 +5463,16 @@
mutex_exit(&ill->ill_lock);
+ /*
+ * ill_delete_tail drops reference on ill_ipst, but we need to keep
+ * it held until the end of the function since the cleanup
+ * below needs to be able to use the ip_stack_t.
+ */
+ netstack_hold(ipst->ips_netstack);
+
/* qprocsoff is called in ill_delete_tail */
ill_delete_tail(ill);
+ ASSERT(ill->ill_ipst == NULL);
/*
* Walk through all upper (conn) streams and qenable
@@ -5548,11 +5483,11 @@
* get unblocked.
*/
ip1dbg(("ip_wsrv: walking\n"));
- conn_walk_drain();
+ conn_walk_drain(ipst);
- mutex_enter(&ip_mi_lock);
- mi_close_unlink(&ip_g_head, (IDP)ill);
- mutex_exit(&ip_mi_lock);
+ mutex_enter(&ipst->ips_ip_mi_lock);
+ mi_close_unlink(&ipst->ips_ip_g_head, (IDP)ill);
+ mutex_exit(&ipst->ips_ip_mi_lock);
/*
* credp could be null if the open didn't succeed and ip_modopen
@@ -5566,7 +5501,8 @@
* event taskq.
*/
if ((info = ill->ill_nic_event_info) != NULL) {
- if (ddi_taskq_dispatch(eventq_queue_nic, ip_ne_queue_func,
+ if (ddi_taskq_dispatch(eventq_queue_nic,
+ ip_ne_queue_func,
(void *)info, DDI_SLEEP) == DDI_FAILURE) {
ip2dbg(("ip_ioctl_finish:ddi_taskq_dispatch failed\n"));
if (info->hne_data != NULL)
@@ -5576,6 +5512,12 @@
ill->ill_nic_event_info = NULL;
}
+ /*
+ * Now we are done with the module close pieces that
+ * need the netstack_t.
+ */
+ netstack_rele(ipst->ips_netstack);
+
mi_close_free((IDP)ill);
q->q_ptr = WR(q)->q_ptr = NULL;
@@ -5594,8 +5536,10 @@
boolean_t drain_cleanup_reqd = B_FALSE;
boolean_t conn_ioctl_cleanup_reqd = B_FALSE;
boolean_t ilg_cleanup_reqd = B_FALSE;
+ ip_stack_t *ipst;
ASSERT(!IPCL_IS_TCP(connp));
+ ipst = connp->conn_netstack->netstack_ip;
/*
* Mark the conn as closing, and this conn must not be
@@ -5649,8 +5593,9 @@
if (drain_cleanup_reqd)
conn_drain_tail(connp, B_TRUE);
- if (connp->conn_rq == ip_g_mrouter || connp->conn_wq == ip_g_mrouter)
- (void) ip_mrouter_done(NULL);
+ if (connp->conn_rq == ipst->ips_ip_g_mrouter ||
+ connp->conn_wq == ipst->ips_ip_g_mrouter)
+ (void) ip_mrouter_done(NULL, ipst);
if (ilg_cleanup_reqd)
ilg_delete_all(connp);
@@ -5713,11 +5658,11 @@
ASSERT(!IPCL_IS_UDP(connp));
if (connp->conn_latch != NULL) {
- IPLATCH_REFRELE(connp->conn_latch);
+ IPLATCH_REFRELE(connp->conn_latch, connp->conn_netstack);
connp->conn_latch = NULL;
}
if (connp->conn_policy != NULL) {
- IPPH_REFRELE(connp->conn_policy);
+ IPPH_REFRELE(connp->conn_policy, connp->conn_netstack);
connp->conn_policy = NULL;
}
if (connp->conn_ipsec_opt_mp != NULL) {
@@ -5838,39 +5783,155 @@
return ((uint16_t)sum);
}
+/*
+ * Called when the module is about to be unloaded
+ */
void
ip_ddi_destroy(void)
{
- ipv4_hook_destroy();
- ipv6_hook_destroy();
- ip_net_destroy();
-
tnet_fini();
- tcp_ddi_destroy();
- sctp_ddi_destroy();
- ipsec_loader_destroy();
- ipsec_policy_destroy();
- ipsec_kstat_destroy();
- nd_free(&ip_g_nd);
- mutex_destroy(&igmp_timer_lock);
- mutex_destroy(&mld_timer_lock);
- mutex_destroy(&igmp_slowtimeout_lock);
- mutex_destroy(&mld_slowtimeout_lock);
- mutex_destroy(&ip_mi_lock);
- mutex_destroy(&rts_clients.connf_lock);
- ip_ire_fini();
- ip6_asp_free();
- conn_drain_fini();
- ipcl_destroy();
+
+ sctp_ddi_g_destroy();
+ tcp_ddi_g_destroy();
+ ipsec_policy_g_destroy();
+ ipcl_g_destroy();
+ ip_net_g_destroy();
+ ip_ire_g_fini();
inet_minor_destroy(ip_minor_arena);
- icmp_kstat_fini();
- ip_kstat_fini();
- rw_destroy(&ipsec_capab_ills_lock);
- rw_destroy(&ill_g_usesrc_lock);
- ip_drop_unregister(&ip_dropper);
+
+ netstack_unregister(NS_IP);
}
+/*
+ * First step in cleanup.
+ */
+/* ARGSUSED */
+static void
+ip_stack_shutdown(netstackid_t stackid, void *arg)
+{
+ ip_stack_t *ipst = (ip_stack_t *)arg;
+#ifdef NS_DEBUG
+ printf("ip_stack_shutdown(%p, stack %d)\n", (void *)ipst, stackid);
+#endif
+
+ /* Get rid of loopback interfaces and their IREs */
+ ip_loopback_cleanup(ipst);
+}
+
+/*
+ * Free the IP stack instance.
+ */
+static void
+ip_stack_fini(netstackid_t stackid, void *arg)
+{
+ ip_stack_t *ipst = (ip_stack_t *)arg;
+ int ret;
+
+#ifdef NS_DEBUG
+ printf("ip_stack_fini(%p, stack %d)\n", (void *)ipst, stackid);
+#endif
+ ipv4_hook_destroy(ipst);
+ ipv6_hook_destroy(ipst);
+ ip_net_destroy(ipst);
+
+ rw_destroy(&ipst->ips_srcid_lock);
+
+ ip_kstat_fini(stackid, ipst->ips_ip_mibkp);
+ ipst->ips_ip_mibkp = NULL;
+ icmp_kstat_fini(stackid, ipst->ips_icmp_mibkp);
+ ipst->ips_icmp_mibkp = NULL;
+ ip_kstat2_fini(stackid, ipst->ips_ip_kstat);
+ ipst->ips_ip_kstat = NULL;
+ bzero(&ipst->ips_ip_statistics, sizeof (ipst->ips_ip_statistics));
+ ip6_kstat_fini(stackid, ipst->ips_ip6_kstat);
+ ipst->ips_ip6_kstat = NULL;
+ bzero(&ipst->ips_ip6_statistics, sizeof (ipst->ips_ip6_statistics));
+
+ nd_free(&ipst->ips_ip_g_nd);
+ kmem_free(ipst->ips_param_arr, sizeof (lcl_param_arr));
+ ipst->ips_param_arr = NULL;
+ kmem_free(ipst->ips_ndp_arr, sizeof (lcl_ndp_arr));
+ ipst->ips_ndp_arr = NULL;
+
+ ip_mrouter_stack_destroy(ipst);
+
+ mutex_destroy(&ipst->ips_ip_mi_lock);
+ rw_destroy(&ipst->ips_ipsec_capab_ills_lock);
+ rw_destroy(&ipst->ips_ill_g_usesrc_lock);
+ rw_destroy(&ipst->ips_ip_g_nd_lock);
+
+ ret = untimeout(ipst->ips_igmp_timeout_id);
+ if (ret == -1) {
+ ASSERT(ipst->ips_igmp_timeout_id == 0);
+ } else {
+ ASSERT(ipst->ips_igmp_timeout_id != 0);
+ ipst->ips_igmp_timeout_id = 0;
+ }
+ ret = untimeout(ipst->ips_igmp_slowtimeout_id);
+ if (ret == -1) {
+ ASSERT(ipst->ips_igmp_slowtimeout_id == 0);
+ } else {
+ ASSERT(ipst->ips_igmp_slowtimeout_id != 0);
+ ipst->ips_igmp_slowtimeout_id = 0;
+ }
+ ret = untimeout(ipst->ips_mld_timeout_id);
+ if (ret == -1) {
+ ASSERT(ipst->ips_mld_timeout_id == 0);
+ } else {
+ ASSERT(ipst->ips_mld_timeout_id != 0);
+ ipst->ips_mld_timeout_id = 0;
+ }
+ ret = untimeout(ipst->ips_mld_slowtimeout_id);
+ if (ret == -1) {
+ ASSERT(ipst->ips_mld_slowtimeout_id == 0);
+ } else {
+ ASSERT(ipst->ips_mld_slowtimeout_id