diff options
Diffstat (limited to 'usr/src/uts')
-rw-r--r-- | usr/src/uts/common/inet/ip.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip6_if.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_if.c | 86 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip_if.h | 9 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_proto.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_str.c | 37 | ||||
-rw-r--r-- | usr/src/uts/common/io/mac/mac_protect.c | 79 | ||||
-rw-r--r-- | usr/src/uts/common/net/if.h | 6 | ||||
-rw-r--r-- | usr/src/uts/common/net/route.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/zone.c | 154 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dlpi.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac_provider.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/zone.h | 18 |
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 |