diff options
Diffstat (limited to 'usr/src/uts/common/inet')
-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 |
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); |