summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/inet/ip.h2
-rw-r--r--usr/src/uts/common/inet/ip/ip.c4
-rw-r--r--usr/src/uts/common/inet/ip/ip6_if.c7
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c86
-rw-r--r--usr/src/uts/common/inet/ip_if.h9
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c3
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c37
-rw-r--r--usr/src/uts/common/io/mac/mac_protect.c79
-rw-r--r--usr/src/uts/common/net/if.h6
-rw-r--r--usr/src/uts/common/net/route.h4
-rw-r--r--usr/src/uts/common/os/zone.c154
-rw-r--r--usr/src/uts/common/sys/dlpi.h4
-rw-r--r--usr/src/uts/common/sys/mac.h1
-rw-r--r--usr/src/uts/common/sys/mac_provider.h5
-rw-r--r--usr/src/uts/common/sys/zone.h18
15 files changed, 374 insertions, 45 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 5e4f19b23e..16e45960ac 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -1801,6 +1801,8 @@ typedef struct ill_s {
timeout_id_t ill_refresh_tid; /* ill refresh retry timeout id */
uint32_t ill_mrouter_cnt; /* mrouter allmulti joins */
+ uint32_t ill_allowed_ips_cnt;
+ in6_addr_t *ill_allowed_ips;
} ill_t;
/*
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 5df30d18d9..4510d37f6a 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -8579,6 +8579,10 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
ill_capability_reset(ill, B_TRUE);
ipsq_current_finish(ipsq);
break;
+
+ case DL_NOTE_ALLOWED_IPS:
+ ill_set_allowed_ips(ill, mp);
+ break;
default:
ip0dbg(("ip_rput_dlpi_writer: unknown notification "
"type 0x%x for DL_NOTIFY_IND\n",
diff --git a/usr/src/uts/common/inet/ip/ip6_if.c b/usr/src/uts/common/inet/ip/ip6_if.c
index e4826bb1a2..c7fc05e2e0 100644
--- a/usr/src/uts/common/inet/ip/ip6_if.c
+++ b/usr/src/uts/common/inet/ip/ip6_if.c
@@ -19,10 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1990 Mentat Inc.
*/
@@ -2302,7 +2299,7 @@ ill_dl_phys(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
(DL_NOTE_PHYS_ADDR | DL_NOTE_SDU_SIZE | DL_NOTE_FASTPATH_FLUSH |
DL_NOTE_LINK_UP | DL_NOTE_LINK_DOWN | DL_NOTE_CAPAB_RENEG |
DL_NOTE_PROMISC_ON_PHYS | DL_NOTE_PROMISC_OFF_PHYS |
- DL_NOTE_REPLUMB);
+ DL_NOTE_REPLUMB | DL_NOTE_ALLOWED_IPS);
phys_mp = ip_dlpi_alloc(sizeof (dl_phys_addr_req_t) +
sizeof (t_scalar_t), DL_PHYS_ADDR_REQ);
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 689c66d66a..19a6821595 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -94,6 +94,7 @@
#include <inet/ipclassifier.h>
#include <sys/mac_client.h>
#include <sys/dld.h>
+#include <sys/mac_flow.h>
#include <sys/systeminfo.h>
#include <sys/bootconf.h>
@@ -546,6 +547,15 @@ ill_delete_tail(ill_t *ill)
ill->ill_dld_capab = NULL;
}
+ /* Clean up ill_allowed_ips* related state */
+ if (ill->ill_allowed_ips != NULL) {
+ ASSERT(ill->ill_allowed_ips_cnt > 0);
+ kmem_free(ill->ill_allowed_ips,
+ ill->ill_allowed_ips_cnt * sizeof (in6_addr_t));
+ ill->ill_allowed_ips = NULL;
+ ill->ill_allowed_ips_cnt = 0;
+ }
+
while (ill->ill_ipif != NULL)
ipif_free_tail(ill->ill_ipif);
@@ -2683,6 +2693,9 @@ ill_forward_set(ill_t *ill, boolean_t enable)
if (IS_LOOPBACK(ill))
return (EINVAL);
+ if (enable && ill->ill_allowed_ips_cnt > 0)
+ return (EPERM);
+
if (IS_IPMP(ill) || IS_UNDER_IPMP(ill)) {
/*
* Update all of the interfaces in the group.
@@ -9656,15 +9669,17 @@ ip_sioctl_addr(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
int err = 0;
in6_addr_t v6addr;
boolean_t need_up = B_FALSE;
+ ill_t *ill;
+ int i;
ip1dbg(("ip_sioctl_addr(%s:%u %p)\n",
ipif->ipif_ill->ill_name, ipif->ipif_id, (void *)ipif));
ASSERT(IAM_WRITER_IPIF(ipif));
+ ill = ipif->ipif_ill;
if (ipif->ipif_isv6) {
sin6_t *sin6;
- ill_t *ill;
phyint_t *phyi;
if (sin->sin_family != AF_INET6)
@@ -9672,7 +9687,6 @@ ip_sioctl_addr(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
sin6 = (sin6_t *)sin;
v6addr = sin6->sin6_addr;
- ill = ipif->ipif_ill;
phyi = ill->ill_phyint;
/*
@@ -9731,7 +9745,21 @@ ip_sioctl_addr(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
IN6_IPADDR_TO_V4MAPPED(addr, &v6addr);
}
-
+ /*
+ * verify that the address being configured is permitted by the
+ * ill_allowed_ips[] for the interface.
+ */
+ if (ill->ill_allowed_ips_cnt > 0) {
+ for (i = 0; i < ill->ill_allowed_ips_cnt; i++) {
+ if (IN6_ARE_ADDR_EQUAL(&ill->ill_allowed_ips[i],
+ &v6addr))
+ break;
+ }
+ if (i == ill->ill_allowed_ips_cnt) {
+ pr_addr_dbg("!allowed addr %s\n", AF_INET6, &v6addr);
+ return (EPERM);
+ }
+ }
/*
* Even if there is no change we redo things just to rerun
* ipif_set_default.
@@ -10373,8 +10401,11 @@ ip_sioctl_flags(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
* If ILLF_ROUTER changes, we need to change the ip forwarding
* status of the interface.
*/
- if ((turn_on | turn_off) & ILLF_ROUTER)
- (void) ill_forward_set(ill, ((turn_on & ILLF_ROUTER) != 0));
+ if ((turn_on | turn_off) & ILLF_ROUTER) {
+ err = ill_forward_set(ill, ((turn_on & ILLF_ROUTER) != 0));
+ if (err != 0)
+ return (err);
+ }
/*
* If the interface is not UP and we are not going to
@@ -17781,6 +17812,51 @@ ill_set_phys_addr(ill_t *ill, mblk_t *mp)
}
/*
+ * When the allowed-ips link property is set on the datalink, IP receives a
+ * DL_NOTE_ALLOWED_IPS notification that is processed in ill_set_allowed_ips()
+ * to initialize the ill_allowed_ips[] array in the ill_t. This array is then
+ * used to vet addresses passed to ip_sioctl_addr() and to ensure that the
+ * only IP addresses configured on the ill_t are those in the ill_allowed_ips[]
+ * array.
+ */
+void
+ill_set_allowed_ips(ill_t *ill, mblk_t *mp)
+{
+ ipsq_t *ipsq = ill->ill_phyint->phyint_ipsq;
+ dl_notify_ind_t *dlip = (dl_notify_ind_t *)mp->b_rptr;
+ mac_protect_t *mrp;
+ int i;
+
+ ASSERT(IAM_WRITER_IPSQ(ipsq));
+ mrp = (mac_protect_t *)&dlip[1];
+
+ if (mrp->mp_ipaddrcnt == 0) { /* reset allowed-ips */
+ kmem_free(ill->ill_allowed_ips,
+ ill->ill_allowed_ips_cnt * sizeof (in6_addr_t));
+ ill->ill_allowed_ips_cnt = 0;
+ ill->ill_allowed_ips = NULL;
+ mutex_enter(&ill->ill_phyint->phyint_lock);
+ ill->ill_phyint->phyint_flags &= ~PHYI_L3PROTECT;
+ mutex_exit(&ill->ill_phyint->phyint_lock);
+ return;
+ }
+
+ if (ill->ill_allowed_ips != NULL) {
+ kmem_free(ill->ill_allowed_ips,
+ ill->ill_allowed_ips_cnt * sizeof (in6_addr_t));
+ }
+ ill->ill_allowed_ips_cnt = mrp->mp_ipaddrcnt;
+ ill->ill_allowed_ips = kmem_alloc(
+ ill->ill_allowed_ips_cnt * sizeof (in6_addr_t), KM_SLEEP);
+ for (i = 0; i < mrp->mp_ipaddrcnt; i++)
+ ill->ill_allowed_ips[i] = mrp->mp_ipaddrs[i].ip_addr;
+
+ mutex_enter(&ill->ill_phyint->phyint_lock);
+ ill->ill_phyint->phyint_flags |= PHYI_L3PROTECT;
+ mutex_exit(&ill->ill_phyint->phyint_lock);
+}
+
+/*
* Once the ill associated with `q' has quiesced, set its physical address
* information to the values in `addrmp'. Note that two copies of `addrmp'
* are passed (linked by b_cont), since we sometimes need to save two distinct
diff --git a/usr/src/uts/common/inet/ip_if.h b/usr/src/uts/common/inet/ip_if.h
index c1ffa33189..08dfc920f3 100644
--- a/usr/src/uts/common/inet/ip_if.h
+++ b/usr/src/uts/common/inet/ip_if.h
@@ -19,10 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1990 Mentat Inc.
*/
-/* Copyright (c) 1990 Mentat Inc. */
#ifndef _INET_IP_IF_H
#define _INET_IP_IF_H
@@ -76,7 +75,7 @@ extern "C" {
*/
#define IFF_PHYINT_FLAGS (IFF_LOOPBACK|IFF_RUNNING|IFF_PROMISC| \
IFF_ALLMULTI|IFF_INTELLIGENT|IFF_MULTI_BCAST|IFF_FAILED|IFF_STANDBY| \
- IFF_INACTIVE|IFF_OFFLINE|IFF_VIRTUAL|IFF_IPMP)
+ IFF_INACTIVE|IFF_OFFLINE|IFF_VIRTUAL|IFF_IPMP|IFF_L3PROTECT)
#define IFF_PHYINTINST_FLAGS (IFF_DEBUG|IFF_NOTRAILERS|IFF_NOARP| \
IFF_MULTICAST|IFF_ROUTER|IFF_NONUD|IFF_NORTEXCH|IFF_IPV4|IFF_IPV6| \
@@ -99,6 +98,7 @@ extern "C" {
#define PHYI_OFFLINE IFF_OFFLINE /* NIC has been offlined */
#define PHYI_VIRTUAL IFF_VIRTUAL /* Will not send or recv pkts */
#define PHYI_IPMP IFF_IPMP /* IPMP meta-interface */
+#define PHYI_L3PROTECT IFF_L3PROTECT /* Layer-3 protected */
#define ILLF_DEBUG IFF_DEBUG /* turn on debugging */
#define ILLF_NOTRAILERS IFF_NOTRAILERS /* avoid use of trailers */
@@ -195,6 +195,7 @@ extern void ill_setdesttoken(ill_t *);
extern void ill_set_inputfn(ill_t *);
extern void ill_set_inputfn_all(ip_stack_t *);
extern int ill_set_phys_addr(ill_t *, mblk_t *);
+extern void ill_set_allowed_ips(ill_t *, mblk_t *);
extern int ill_replumb(ill_t *, mblk_t *);
extern void ill_set_ndmp(ill_t *, mblk_t *, uint_t, uint_t);
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 1231a0cced..facd2fbfb8 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -1127,7 +1127,8 @@ proto_notify_req(dld_str_t *dsp, mblk_t *mp)
DL_NOTE_CAPAB_RENEG |
DL_NOTE_FASTPATH_FLUSH |
DL_NOTE_SPEED |
- DL_NOTE_SDU_SIZE;
+ DL_NOTE_SDU_SIZE|
+ DL_NOTE_ALLOWED_IPS;
if (MBLKL(mp) < sizeof (dl_notify_req_t)) {
dl_err = DL_BADPRIM;
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index 63d2bb6511..c4d46090c1 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -38,6 +37,7 @@
#include <sys/list.h>
#include <sys/mac_client.h>
#include <sys/mac_client_priv.h>
+#include <sys/mac_flow.h>
static int str_constructor(void *, void *, int);
static void str_destructor(void *, void *);
@@ -1719,6 +1719,35 @@ str_notify_fastpath_flush(dld_str_t *dsp)
qreply(dsp->ds_wq, mp);
}
+static void
+str_notify_allowed_ips(dld_str_t *dsp)
+{
+ mblk_t *mp;
+ dl_notify_ind_t *dlip;
+ size_t mp_size;
+ mac_protect_t mrp;
+
+ if (!(dsp->ds_notifications & DL_NOTE_ALLOWED_IPS))
+ return;
+
+ mp_size = sizeof (mac_protect_t) + sizeof (dl_notify_ind_t);
+ if ((mp = mexchange(dsp->ds_wq, NULL, mp_size, M_PROTO, 0)) == NULL)
+ return;
+
+ mac_protect_get(dsp->ds_mh, &mrp);
+ bzero(mp->b_rptr, mp_size);
+ dlip = (dl_notify_ind_t *)mp->b_rptr;
+ dlip->dl_primitive = DL_NOTIFY_IND;
+ dlip->dl_notification = DL_NOTE_ALLOWED_IPS;
+ dlip->dl_data = 0;
+ dlip->dl_addr_offset = sizeof (dl_notify_ind_t);
+ dlip->dl_addr_length = sizeof (mac_protect_t);
+ bcopy(&mrp, mp->b_rptr + sizeof (dl_notify_ind_t),
+ sizeof (mac_protect_t));
+
+ qreply(dsp->ds_wq, mp);
+}
+
/*
* MAC notification callback.
*/
@@ -1849,6 +1878,10 @@ str_notify(void *arg, mac_notify_type_t type)
case MAC_NOTE_MARGIN:
break;
+ case MAC_NOTE_ALLOWED_IPS:
+ str_notify_allowed_ips(dsp);
+ break;
+
default:
ASSERT(B_FALSE);
break;
diff --git a/usr/src/uts/common/io/mac/mac_protect.c b/usr/src/uts/common/io/mac/mac_protect.c
index c923bcdbe2..30b6b18bc4 100644
--- a/usr/src/uts/common/io/mac/mac_protect.c
+++ b/usr/src/uts/common/io/mac/mac_protect.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/strsun.h>
@@ -194,6 +193,7 @@ typedef struct dhcpv6_txn {
} dhcpv6_txn_t;
static void start_txn_cleanup_timer(mac_client_impl_t *);
+static boolean_t allowed_ips_set(mac_resource_props_t *, uint32_t);
#define BUMP_STAT(m, s) (m)->mci_misc_stat.mms_##s++
@@ -552,29 +552,34 @@ txn_cleanup_v4(mac_client_impl_t *mcip)
/*
* Core logic for intercepting outbound DHCPv4 packets.
*/
-static void
+static boolean_t
intercept_dhcpv4_outbound(mac_client_impl_t *mcip, ipha_t *ipha, uchar_t *end)
{
- struct dhcp *dh4;
- uchar_t *opt;
- dhcpv4_txn_t *txn, *ctxn;
- ipaddr_t ipaddr;
- uint8_t opt_len, mtype, cid[DHCP_MAX_OPT_SIZE], cid_len;
+ struct dhcp *dh4;
+ uchar_t *opt;
+ dhcpv4_txn_t *txn, *ctxn;
+ ipaddr_t ipaddr;
+ uint8_t opt_len, mtype, cid[DHCP_MAX_OPT_SIZE], cid_len;
+ mac_resource_props_t *mrp = MCIP_RESOURCE_PROPS(mcip);
if (get_dhcpv4_info(ipha, end, &dh4) != 0)
- return;
+ return (B_TRUE);
+
+ /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
+ if (allowed_ips_set(mrp, IPV4_VERSION))
+ return (B_FALSE);
if (get_dhcpv4_option(dh4, end, CD_DHCP_TYPE, &opt, &opt_len) != 0 ||
opt_len != 1) {
DTRACE_PROBE2(mtype__not__found, mac_client_impl_t *, mcip,
struct dhcp *, dh4);
- return;
+ return (B_TRUE);
}
mtype = *opt;
if (mtype != REQUEST && mtype != RELEASE) {
DTRACE_PROBE3(ignored__mtype, mac_client_impl_t *, mcip,
struct dhcp *, dh4, uint8_t, mtype);
- return;
+ return (B_TRUE);
}
/* client ID is optional for IPv4 */
@@ -639,6 +644,7 @@ intercept_dhcpv4_outbound(mac_client_impl_t *mcip, ipha_t *ipha, uchar_t *end)
done:
mutex_exit(&mcip->mci_protect_lock);
+ return (B_TRUE);
}
/*
@@ -1208,7 +1214,7 @@ txn_cleanup_v6(mac_client_impl_t *mcip)
/*
* Core logic for intercepting outbound DHCPv6 packets.
*/
-static void
+static boolean_t
intercept_dhcpv6_outbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end)
{
dhcpv6_message_t *dh6;
@@ -1216,17 +1222,22 @@ intercept_dhcpv6_outbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end)
dhcpv6_cid_t *cid = NULL;
uint32_t xid;
uint8_t mtype;
+ mac_resource_props_t *mrp = MCIP_RESOURCE_PROPS(mcip);
if (get_dhcpv6_info(ip6h, end, &dh6) != 0)
- return;
+ return (B_TRUE);
+
+ /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
+ if (allowed_ips_set(mrp, IPV6_VERSION))
+ return (B_FALSE);
mtype = dh6->d6m_msg_type;
if (mtype != DHCPV6_MSG_REQUEST && mtype != DHCPV6_MSG_RENEW &&
mtype != DHCPV6_MSG_REBIND && mtype != DHCPV6_MSG_RELEASE)
- return;
+ return (B_TRUE);
if ((cid = create_dhcpv6_cid(dh6, end)) == NULL)
- return;
+ return (B_TRUE);
mutex_enter(&mcip->mci_protect_lock);
if (mtype == DHCPV6_MSG_RELEASE) {
@@ -1260,6 +1271,7 @@ done:
free_dhcpv6_cid(cid);
mutex_exit(&mcip->mci_protect_lock);
+ return (B_TRUE);
}
/*
@@ -1524,7 +1536,8 @@ ipnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *protect,
V4_PART_OF_V6(v4addr->ip_addr) == *addr)
return (B_TRUE);
}
- return (check_dhcpv4_dyn_ip(mcip, *addr));
+ return (protect->mp_ipaddrcnt == 0 ?
+ check_dhcpv4_dyn_ip(mcip, *addr) : B_FALSE);
}
static boolean_t
@@ -1549,7 +1562,8 @@ ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
IN6_ARE_ADDR_EQUAL(&v6addr->ip_addr, addr))
return (B_TRUE);
}
- return (check_dhcpv6_dyn_ip(mcip, addr));
+ return (protect->mp_ipaddrcnt == 0 ?
+ check_dhcpv6_dyn_ip(mcip, addr) : B_FALSE);
}
/*
@@ -1694,7 +1708,8 @@ ipnospoof_check(mac_client_impl_t *mcip, mac_protect_t *protect,
if (!ipnospoof_check_v4(mcip, protect, &ipha->ipha_src))
goto fail;
- intercept_dhcpv4_outbound(mcip, ipha, end);
+ if (!intercept_dhcpv4_outbound(mcip, ipha, end))
+ goto fail;
break;
}
case ETHERTYPE_ARP: {
@@ -1739,7 +1754,8 @@ ipnospoof_check(mac_client_impl_t *mcip, mac_protect_t *protect,
if (!ipnospoof_check_ndp(mcip, protect, ip6h, end))
goto fail;
- intercept_dhcpv6_outbound(mcip, ip6h, end);
+ if (!intercept_dhcpv6_outbound(mcip, ip6h, end))
+ goto fail;
break;
}
}
@@ -2187,7 +2203,12 @@ mac_protect_set(mac_client_handle_t mch, mac_resource_props_t *mrp)
if ((err = mac_protect_validate(mrp)) != 0)
return (err);
+ if (err != 0)
+ return (err);
+
mac_update_resources(mrp, MCIP_RESOURCE_PROPS(mcip), B_FALSE);
+ i_mac_notify(((mcip->mci_state_flags & MCIS_IS_VNIC) != 0 ?
+ mcip->mci_upper_mip : mip), MAC_NOTE_ALLOWED_IPS);
return (0);
}
@@ -2261,3 +2282,23 @@ mac_protect_fini(mac_client_impl_t *mcip)
mcip->mci_protect_flags = 0;
mutex_destroy(&mcip->mci_protect_lock);
}
+
+static boolean_t
+allowed_ips_set(mac_resource_props_t *mrp, uint32_t af)
+{
+ int i;
+
+ for (i = 0; i < mrp->mrp_protect.mp_ipaddrcnt; i++) {
+ if (mrp->mrp_protect.mp_ipaddrs[i].ip_version == af)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+void
+mac_protect_get(mac_handle_t mh, mac_protect_t *mrp)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ *mrp = mip->mi_resource_props.mrp_protect;
+}
diff --git a/usr/src/uts/common/net/if.h b/usr/src/uts/common/net/if.h
index 68ed7b6078..53d6996961 100644
--- a/usr/src/uts/common/net/if.h
+++ b/usr/src/uts/common/net/if.h
@@ -1,6 +1,5 @@
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -171,6 +170,7 @@ struct ifnet {
#define IFF_VRRP 0x10000000000ll /* Managed by VRRP */
#define IFF_NOLINKLOCAL 0x20000000000ll /* No default linklocal */
+#define IFF_L3PROTECT 0x40000000000ll /* Layer-3 protection enforced */
/* flags that cannot be changed by userland on any interface */
#define IFF_CANTCHANGE \
@@ -178,7 +178,7 @@ struct ifnet {
IFF_MULTICAST | IFF_MULTI_BCAST | IFF_UNNUMBERED | IFF_IPV4 | \
IFF_IPV6 | IFF_IPMP | IFF_FIXEDMTU | IFF_VIRTUAL | \
IFF_LOOPBACK | IFF_ALLMULTI | IFF_DUPLICATE | IFF_COS_ENABLED | \
- IFF_VRRP | IFF_NOLINKLOCAL)
+ IFF_VRRP | IFF_NOLINKLOCAL | IFF_L3PROTECT)
/* flags that cannot be changed by userland on an IPMP interface */
#define IFF_IPMP_CANTCHANGE IFF_FAILED
diff --git a/usr/src/uts/common/net/route.h b/usr/src/uts/common/net/route.h
index ee31935863..af42382b06 100644
--- a/usr/src/uts/common/net/route.h
+++ b/usr/src/uts/common/net/route.h
@@ -1,6 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (c) 1980, 1986, 1993
@@ -132,6 +131,7 @@ struct rtentry {
#define RTF_SETSRC 0x20000 /* set default outgoing src address */
#define RTF_INDIRECT 0x40000 /* gateway not directly reachable */
#define RTF_KERNEL 0x80000 /* created by kernel; can't delete */
+#define RTF_ZONE 0x100000 /* (NGZ only) route from global zone */
/*
* OLD statistics not used by the kernel. The kernel uses <inet/mib2.h>.
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c
index caf10ee8df..bbc91e3fa7 100644
--- a/usr/src/uts/common/os/zone.c
+++ b/usr/src/uts/common/os/zone.c
@@ -252,6 +252,7 @@
/* List of data link IDs which are accessible from the zone */
typedef struct zone_dl {
datalink_id_t zdl_id;
+ nvlist_t *zdl_net;
list_node_t zdl_linkage;
} zone_dl_t;
@@ -364,6 +365,8 @@ static int zone_shutdown(zoneid_t zoneid);
static int zone_add_datalink(zoneid_t, datalink_id_t);
static int zone_remove_datalink(zoneid_t, datalink_id_t);
static int zone_list_datalink(zoneid_t, int *, datalink_id_t *);
+static int zone_set_network(zoneid_t, zone_net_data_t *);
+static int zone_get_network(zoneid_t, zone_net_data_t *);
typedef boolean_t zsd_applyfn_t(kmutex_t *, boolean_t, zone_t *, zone_key_t);
@@ -4719,6 +4722,7 @@ zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
boolean_t global = (curzone == global_zone);
boolean_t inzone = (curzone->zone_id == zoneid);
ushort_t flags;
+ zone_net_data_t *zbuf;
mutex_enter(&zonehash_lock);
if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
@@ -4973,6 +4977,17 @@ zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
error = EFAULT;
}
break;
+ case ZONE_ATTR_NETWORK:
+ zbuf = kmem_alloc(bufsize, KM_SLEEP);
+ if (copyin(buf, zbuf, bufsize) != 0) {
+ error = EFAULT;
+ } else {
+ error = zone_get_network(zoneid, zbuf);
+ if (error == 0 && copyout(zbuf, buf, bufsize) != 0)
+ error = EFAULT;
+ }
+ kmem_free(zbuf, bufsize);
+ break;
default:
if ((attr >= ZONE_ATTR_BRAND_ATTRS) && ZONE_IS_BRANDED(zone)) {
size = bufsize;
@@ -4998,6 +5013,7 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
zone_t *zone;
zone_status_t zone_status;
int err;
+ zone_net_data_t *zbuf;
if (secpolicy_zone_config(CRED()) != 0)
return (set_errno(EPERM));
@@ -5055,6 +5071,19 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
err = EINVAL;
}
break;
+ case ZONE_ATTR_NETWORK:
+ if (bufsize > (PIPE_BUF + sizeof (zone_net_data_t))) {
+ err = EINVAL;
+ goto done;
+ }
+ zbuf = kmem_alloc(bufsize, KM_SLEEP);
+ if (copyin(buf, zbuf, bufsize) != 0) {
+ err = EFAULT;
+ goto done;
+ }
+ err = zone_set_network(zoneid, zbuf);
+ kmem_free(zbuf, bufsize);
+ break;
default:
if ((attr >= ZONE_ATTR_BRAND_ATTRS) && ZONE_IS_BRANDED(zone))
err = ZBROP(zone)->b_setattr(zone, attr, buf, bufsize);
@@ -6328,6 +6357,7 @@ zone_add_datalink(zoneid_t zoneid, datalink_id_t linkid)
zdl = kmem_zalloc(sizeof (*zdl), KM_SLEEP);
zdl->zdl_id = linkid;
+ zdl->zdl_net = NULL;
mutex_enter(&thiszone->zone_lock);
list_insert_head(&thiszone->zone_dl_list, zdl);
mutex_exit(&thiszone->zone_lock);
@@ -6351,6 +6381,8 @@ zone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid)
err = ENXIO;
} else {
list_remove(&zone->zone_dl_list, zdl);
+ if (zdl->zdl_net != NULL)
+ nvlist_free(zdl->zdl_net);
kmem_free(zdl, sizeof (zone_dl_t));
}
mutex_exit(&zone->zone_lock);
@@ -6524,3 +6556,125 @@ zone_datalink_walk(zoneid_t zoneid, int (*cb)(datalink_id_t, void *),
kmem_free(idarray, sizeof (datalink_id_t) * idcount);
return (ret);
}
+
+static char *
+zone_net_type2name(int type)
+{
+ switch (type) {
+ case ZONE_NETWORK_ADDRESS:
+ return (ZONE_NET_ADDRNAME);
+ case ZONE_NETWORK_DEFROUTER:
+ return (ZONE_NET_RTRNAME);
+ default:
+ return (NULL);
+ }
+}
+
+static int
+zone_set_network(zoneid_t zoneid, zone_net_data_t *znbuf)
+{
+ zone_t *zone;
+ zone_dl_t *zdl;
+ nvlist_t *nvl;
+ int err = 0;
+ uint8_t *new = NULL;
+ char *nvname;
+ int bufsize;
+ datalink_id_t linkid = znbuf->zn_linkid;
+
+ if (secpolicy_zone_config(CRED()) != 0)
+ return (set_errno(EPERM));
+
+ if (zoneid == GLOBAL_ZONEID)
+ return (set_errno(EINVAL));
+
+ nvname = zone_net_type2name(znbuf->zn_type);
+ bufsize = znbuf->zn_len;
+ new = znbuf->zn_val;
+ if (nvname == NULL)
+ return (set_errno(EINVAL));
+
+ if ((zone = zone_find_by_id(zoneid)) == NULL) {
+ return (set_errno(EINVAL));
+ }
+
+ mutex_enter(&zone->zone_lock);
+ if ((zdl = zone_find_dl(zone, linkid)) == NULL) {
+ err = ENXIO;
+ goto done;
+ }
+ if ((nvl = zdl->zdl_net) == NULL) {
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP)) {
+ err = ENOMEM;
+ goto done;
+ } else {
+ zdl->zdl_net = nvl;
+ }
+ }
+ if (nvlist_exists(nvl, nvname)) {
+ err = EINVAL;
+ goto done;
+ }
+ err = nvlist_add_uint8_array(nvl, nvname, new, bufsize);
+ ASSERT(err == 0);
+done:
+ mutex_exit(&zone->zone_lock);
+ zone_rele(zone);
+ if (err != 0)
+ return (set_errno(err));
+ else
+ return (0);
+}
+
+static int
+zone_get_network(zoneid_t zoneid, zone_net_data_t *znbuf)
+{
+ zone_t *zone;
+ zone_dl_t *zdl;
+ nvlist_t *nvl;
+ uint8_t *ptr;
+ uint_t psize;
+ int err = 0;
+ char *nvname;
+ int bufsize;
+ void *buf;
+ datalink_id_t linkid = znbuf->zn_linkid;
+
+ if (zoneid == GLOBAL_ZONEID)
+ return (set_errno(EINVAL));
+
+ nvname = zone_net_type2name(znbuf->zn_type);
+ bufsize = znbuf->zn_len;
+ buf = znbuf->zn_val;
+
+ if (nvname == NULL)
+ return (set_errno(EINVAL));
+ if ((zone = zone_find_by_id(zoneid)) == NULL)
+ return (set_errno(EINVAL));
+
+ mutex_enter(&zone->zone_lock);
+ if ((zdl = zone_find_dl(zone, linkid)) == NULL) {
+ err = ENXIO;
+ goto done;
+ }
+ if ((nvl = zdl->zdl_net) == NULL || !nvlist_exists(nvl, nvname)) {
+ err = ENOENT;
+ goto done;
+ }
+ err = nvlist_lookup_uint8_array(nvl, nvname, &ptr, &psize);
+ ASSERT(err == 0);
+
+ if (psize > bufsize) {
+ err = ENOBUFS;
+ goto done;
+ }
+ znbuf->zn_len = psize;
+ bcopy(ptr, buf, psize);
+done:
+ mutex_exit(&zone->zone_lock);
+ zone_rele(zone);
+ if (err != 0)
+ return (set_errno(err));
+ else
+ return (0);
+}
diff --git a/usr/src/uts/common/sys/dlpi.h b/usr/src/uts/common/sys/dlpi.h
index 9613c6491c..72e2c890da 100644
--- a/usr/src/uts/common/sys/dlpi.h
+++ b/usr/src/uts/common/sys/dlpi.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -407,6 +406,7 @@ typedef struct dl_ipnetinfo {
#define DL_NOTE_FASTPATH_FLUSH 0x0200 /* Fast Path info changes */
#define DL_NOTE_CAPAB_RENEG 0x0400 /* Initiate capability renegotiation */
#define DL_NOTE_REPLUMB 0x0800 /* Inform the link to replumb */
+#define DL_NOTE_ALLOWED_IPS 0x1000 /* "allowed-ips" notification */
/*
* DLPI notification codes for DL_NOTIFY_CONF primitives.
diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h
index 224987e220..7288db385c 100644
--- a/usr/src/uts/common/sys/mac.h
+++ b/usr/src/uts/common/sys/mac.h
@@ -349,6 +349,7 @@ typedef enum {
MAC_NOTE_MARGIN,
MAC_NOTE_CAPAB_CHG,
MAC_NOTE_LOWLINK,
+ MAC_NOTE_ALLOWED_IPS,
MAC_NNOTE /* must be the last entry */
} mac_notify_type_t;
diff --git a/usr/src/uts/common/sys/mac_provider.h b/usr/src/uts/common/sys/mac_provider.h
index c96d07b594..3dd8024904 100644
--- a/usr/src/uts/common/sys/mac_provider.h
+++ b/usr/src/uts/common/sys/mac_provider.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_MAC_PROVIDER_H
@@ -33,6 +32,7 @@
#include <sys/stream.h>
#include <sys/mkdev.h>
#include <sys/mac.h>
+#include <sys/mac_flow.h>
/*
* MAC Provider Interface
@@ -455,6 +455,7 @@ typedef struct mac_register_s {
/*
* Driver interface functions.
*/
+extern void mac_protect_get(mac_handle_t, mac_protect_t *);
extern void mac_sdu_get(mac_handle_t, uint_t *, uint_t *);
extern int mac_maxsdu_update(mac_handle_t, uint_t);
diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h
index 0a513f8cf7..b89a6902db 100644
--- a/usr/src/uts/common/sys/zone.h
+++ b/usr/src/uts/common/sys/zone.h
@@ -36,6 +36,8 @@
#include <sys/netstack.h>
#include <sys/uadmin.h>
#include <sys/ksynch.h>
+#include <sys/socket_impl.h>
+#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
@@ -97,6 +99,7 @@ extern "C" {
#define ZONE_ATTR_FLAGS 14
#define ZONE_ATTR_HOSTID 15
#define ZONE_ATTR_FS_ALLOWED 16
+#define ZONE_ATTR_NETWORK 17
/* Start of the brand-specific attribute namespace */
#define ZONE_ATTR_BRAND_ATTRS 32768
@@ -279,6 +282,21 @@ typedef struct zone_cmd_rval {
/* zone_create flags */
#define ZCF_NET_EXCL 0x1 /* Create a zone with exclusive IP */
+/* zone network properties */
+#define ZONE_NETWORK_ADDRESS 1
+#define ZONE_NETWORK_DEFROUTER 2
+
+#define ZONE_NET_ADDRNAME "address"
+#define ZONE_NET_RTRNAME "route"
+
+typedef struct zone_net_data {
+ int zn_type;
+ int zn_len;
+ datalink_id_t zn_linkid;
+ uint8_t zn_val[1];
+} zone_net_data_t;
+
+
#ifdef _KERNEL
/*
* We need to protect the definition of 'list_t' from userland applications and