summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet')
-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
5 files changed, 94 insertions, 14 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);