summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorCody Peter Mello <cody.mello@joyent.com>2017-12-06 01:28:51 +0000
committerCody Peter Mello <cody.mello@joyent.com>2018-06-08 18:42:56 +0000
commit12a82dd4a058eb86f2b6b075bde38b01424f8f30 (patch)
treef144354889bae1e4320a5eb915d1014d854246ae /usr/src
parentc6b0ac12851403af18c06800770e65c0314956fb (diff)
downloadillumos-joyent-12a82dd4a058eb86f2b6b075bde38b01424f8f30.tar.gz
OS-4683 Using the allowed-ips property prevents using dynamic addresses
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libdladm/common/libdladm.c40
-rw-r--r--usr/src/lib/libdladm/common/libdladm.h3
-rw-r--r--usr/src/lib/libdladm/common/libdladm_impl.h2
-rw-r--r--usr/src/lib/libdladm/common/linkprop.c59
-rw-r--r--usr/src/man/man1m/dladm.1m18
-rw-r--r--usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh45
-rw-r--r--usr/src/uts/common/inet/ip.h19
-rw-r--r--usr/src/uts/common/inet/ip/ip.c84
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c159
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c36
-rw-r--r--usr/src/uts/common/io/mac/mac_protect.c91
-rw-r--r--usr/src/uts/common/sys/dld.h6
-rw-r--r--usr/src/uts/common/sys/mac_client_priv.h3
-rw-r--r--usr/src/uts/common/sys/mac_flow.h7
14 files changed, 424 insertions, 148 deletions
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index 211a775d89..1616885309 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2017, Joyent, Inc.
*/
#include <unistd.h>
@@ -99,6 +99,18 @@ static link_protect_t link_protect_types[] = {
};
#define LPTYPES (sizeof (link_protect_types) / sizeof (link_protect_t))
+typedef struct {
+ uint32_t ld_type;
+ char *ld_name;
+} link_dynamic_t;
+
+static link_dynamic_t link_dynamic_types[] = {
+ { MPT_DYN_DHCPV4, "dhcpv4" },
+ { MPT_DYN_DHCPV6, "dhcpv6" },
+ { MPT_DYN_SLAAC, "slaac" },
+};
+#define DYNTYPES (sizeof (link_dynamic_types) / sizeof (link_dynamic_t))
+
dladm_status_t
dladm_open(dladm_handle_t *handle)
{
@@ -951,6 +963,28 @@ dladm_protect2str(uint32_t ptype, char *buf)
return (buf);
}
+
+/*
+ * Convert dynamic address method value to a string.
+ */
+const char *
+dladm_dynamic2str(uint32_t dtype, char *buf, size_t size)
+{
+ const char *s = "--";
+ link_dynamic_t *ld;
+ int i;
+
+ for (i = 0; i < DYNTYPES; i++) {
+ ld = &link_dynamic_types[i];
+ if (ld->ld_type == dtype) {
+ s = ld->ld_name;
+ break;
+ }
+ }
+ (void) snprintf(buf, size, "%s", dgettext(TEXT_DOMAIN, s));
+ return (buf);
+}
+
/*
* Convert an IPv4 address to/from a string.
*/
@@ -1092,8 +1126,8 @@ fail:
* is allocated here but should be freed by the caller.
*/
dladm_status_t
-dladm_strs2range(char **prop_val, uint_t val_cnt, mac_propval_type_t type,
- mac_propval_range_t **range)
+dladm_strs2range(char **prop_val, uint_t val_cnt,
+ mac_propval_type_t type, mac_propval_range_t **range)
{
int i;
char *endp;
diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h
index e5da4e3b44..8285517a95 100644
--- a/usr/src/lib/libdladm/common/libdladm.h
+++ b/usr/src/lib/libdladm/common/libdladm.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2017, Joyent, Inc.
*/
#ifndef _LIBDLADM_H
@@ -265,6 +265,7 @@ extern dladm_status_t dladm_str2pri(char *, mac_priority_level_t *);
extern const char *dladm_pri2str(mac_priority_level_t, char *);
extern dladm_status_t dladm_str2protect(char *, uint32_t *);
extern const char *dladm_protect2str(uint32_t, char *);
+extern const char *dladm_dynamic2str(uint32_t, char *, size_t);
extern dladm_status_t dladm_str2ipv4addr(char *, void *);
extern const char *dladm_ipv4addr2str(void *, char *);
extern dladm_status_t dladm_str2ipv6addr(char *, void *);
diff --git a/usr/src/lib/libdladm/common/libdladm_impl.h b/usr/src/lib/libdladm/common/libdladm_impl.h
index 08981ff65f..285cb27aad 100644
--- a/usr/src/lib/libdladm/common/libdladm_impl.h
+++ b/usr/src/lib/libdladm/common/libdladm_impl.h
@@ -147,7 +147,7 @@ extern dladm_status_t dladm_flow_proplist_extract(dladm_arg_list_t *,
* by the pd_check function.
*/
typedef dladm_status_t rp_extractf_t(val_desc_t *, uint_t, void *);
-extern rp_extractf_t extract_priority, extract_cpus,
+extern rp_extractf_t extract_dynamic_methods, extract_priority, extract_cpus,
extract_protection, extract_allowallcids, extract_pool,
extract_allowedips, extract_allowedcids, extract_maxbw,
extract_rxrings, extract_txrings;
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index 643c0968ea..0afd4d8bce 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -155,7 +155,7 @@ static pd_getf_t get_zone, get_autopush, get_rate_mod, get_rate,
get_txrings, get_cntavail, get_secondary_macs,
get_allowallcids, get_allowedips, get_allowedcids,
get_pool, get_rings_range, get_linkmode_prop,
- get_promisc_filtered;
+ get_promisc_filtered, get_dynamic_methods;
static pd_setf_t set_zone, set_rate, set_powermode, set_radio,
set_public_prop, set_resource, set_stp_prop,
@@ -451,6 +451,13 @@ static val_desc_t link_protect_vals[] = {
{ "dhcp-nospoof", MPT_DHCPNOSPOOF },
};
+static val_desc_t link_dynamic_method_vals[] = {
+ { "dhcpv4", MPT_DYN_DHCPV4 },
+ { "dhcpv6", MPT_DYN_DHCPV6 },
+ { "slaac", MPT_DYN_SLAAC },
+ { "addrconf", (MPT_DYN_SLAAC | MPT_DYN_DHCPV6) },
+};
+
static val_desc_t dladm_bool_vals[] = {
{ "false", MPT_FALSE },
{ "true", MPT_TRUE },
@@ -797,6 +804,11 @@ static prop_desc_t prop_table[] = {
set_resource, NULL, get_protection, check_prop, 0,
DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
+ { "dynamic-methods", { "--", RESET_VAL },
+ link_dynamic_method_vals, VALCNT(link_dynamic_method_vals),
+ set_resource, NULL, get_dynamic_methods, check_prop, 0,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
+
{ "promisc-filtered", { "on", 1 },
link_promisc_filtered_vals, VALCNT(link_promisc_filtered_vals),
set_promisc_filtered, NULL, get_promisc_filtered, check_prop, 0,
@@ -864,6 +876,7 @@ static resource_prop_t rsrc_prop_table[] = {
{"pool", extract_pool},
{"pool-effective", extract_pool},
{"protection", extract_protection},
+ {"dynamic-methods", extract_dynamic_methods},
{"allowed-ips", extract_allowedips},
{"allowed-dhcp-cids", extract_allowedcids},
{"allow-all-dhcp-cids", extract_allowallcids},
@@ -2929,6 +2942,50 @@ dladm_str2cid(char *buf, mac_dhcpcid_t *cid)
/* ARGSUSED */
static dladm_status_t
+get_dynamic_methods(dladm_handle_t handle, prop_desc_t *pdp,
+ datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
+ datalink_media_t media, uint_t flags, uint_t *perm_flags)
+{
+ mac_resource_props_t mrp;
+ mac_protect_t *p;
+ dladm_status_t status;
+ uint32_t i, cnt = 0, setbits[32];
+
+ status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
+ perm_flags, &mrp, sizeof (mrp));
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ p = &mrp.mrp_protect;
+ dladm_find_setbits32(p->mp_dynamic, setbits, &cnt);
+ if (cnt > *val_cnt)
+ return (DLADM_STATUS_BADVALCNT);
+
+ for (i = 0; i < cnt; i++)
+ (void) dladm_dynamic2str(
+ setbits[i], prop_val[i], DLADM_STRSIZE);
+
+ *val_cnt = cnt;
+ return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+extract_dynamic_methods(val_desc_t *vdp, uint_t cnt, void *arg)
+{
+ mac_resource_props_t *mrp = arg;
+ uint32_t methods = 0;
+ int i;
+
+ for (i = 0; i < cnt; i++)
+ methods |= (uint32_t)vdp[i].vd_val;
+
+ mrp->mrp_protect.mp_dynamic = methods;
+ mrp->mrp_mask |= MRP_PROTECT;
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
get_allowallcids(dladm_handle_t handle, prop_desc_t *pdp,
datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
datalink_media_t media, uint_t flags, uint_t *perm_flags)
diff --git a/usr/src/man/man1m/dladm.1m b/usr/src/man/man1m/dladm.1m
index 0519cd307f..7a29e88ad7 100644
--- a/usr/src/man/man1m/dladm.1m
+++ b/usr/src/man/man1m/dladm.1m
@@ -4991,6 +4991,24 @@ is not bound to any specific processor or processor set.
.sp
.ne 2
.na
+\fB\fBdynamic-methods\fR\fR
+.ad
+.sp .6
+.RS 4n
+When using IP spoofing protection (see \fBprotection\fR), addresses can be
+learned dynamically by monitoring certain network traffic, like DHCP
+transactions or IPv6 Stateless Address Autoconfiguration (SLAAC). By default,
+all learning methods are permitted, but if \fBallowed-ips\fR contains any
+addresses, then all methods are disabled, and any packets sent from addresses
+previously learned will be dropped. This property allows selecting which ones
+are re-enabled, where valid options are \fBdhcpv4\fR, \fBdhcpv6\fR, and
+\fBslaac\fR. \fBaddrconf\fR is available as an alias for enabling both
+\fBdhcpv6\fR and \fBslaac\fR.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBlearn_limit\fR\fR
.ad
.sp .6
diff --git a/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh b/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh
new file mode 100644
index 0000000000..4ed64a92b4
--- /dev/null
+++ b/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh
@@ -0,0 +1,45 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017 Joyent, Inc.
+#
+
+source ./common.ksh
+
+property="dynamic-methods"
+
+setup
+
+# All valid values on their own
+epass slaac
+epass dhcpv4
+epass dhcpv6
+epass addrconf
+
+# Combinations of values
+epass slaac,dhcpv4
+epass slaac,dhcpv6
+epass dhcpv4,dhcpv6
+epass dhcpv4,addrconf
+epass dhcpv4,dhcpv6,slaac
+
+# Illegal values
+efail dhcpv8
+efail slaac,dhcpv8
+efail slack
+efail ipv6
+efail dhcp
+efail dhcpv
+
+cleanup
+printf "TEST PASS: $ai_arg0\n"
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index cc8c489c8c..456d778cc7 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -22,7 +22,7 @@
/*
* Copyright (c) 1990 Mentat Inc.
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2017, Joyent, Inc. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc.
* Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
*/
@@ -1415,6 +1415,7 @@ typedef union ill_g_head_u {
#define ILL_CAPAB_DLD 0x20 /* DLD capabilities */
#define ILL_CAPAB_DLD_POLL 0x40 /* Polling */
#define ILL_CAPAB_DLD_DIRECT 0x80 /* Direct function call */
+#define ILL_CAPAB_DLD_IPCHECK 0x100 /* Check if IPs are permitted */
/*
* Per-ill Hardware Checksumming capbilities.
@@ -1728,6 +1729,8 @@ typedef struct ill_s {
* Capabilities related fields.
*/
uint_t ill_dlpi_capab_state; /* State of capability query, IDCS_* */
+ kcondvar_t ill_dlpi_capab_cv; /* CV for broadcasting state changes */
+ kmutex_t ill_dlpi_capab_lock; /* Lock for accessing above Cond Var */
uint_t ill_capab_pending_cnt;
uint64_t ill_capabilities; /* Enabled capabilities, ILL_CAPAB_* */
ill_hcksum_capab_t *ill_hcksum_capab; /* H/W cksumming capabilities */
@@ -1769,6 +1772,10 @@ typedef struct ill_s {
* Used to save errors that occur during plumbing
*/
uint_t ill_ifname_pending_err;
+ /*
+ * Used to save errors that occur during binding
+ */
+ uint_t ill_dl_bind_err;
avl_node_t ill_avl_byppa; /* avl node based on ppa */
list_t ill_nce; /* pointer to nce_s list */
uint_t ill_refcnt; /* active refcnt by threads */
@@ -1934,6 +1941,7 @@ typedef struct ill_s {
* ill_nd_lla_len ipsq + down ill only when ill is up
* ill_phys_addr_pend ipsq + down ill only when ill is up
* ill_ifname_pending_err ipsq ipsq
+ * ill_dl_bind_err ipsq ipsq
* ill_avl_byppa ipsq, ill_g_lock write once
*
* ill_fastpath_list ill_lock ill_lock
@@ -3575,6 +3583,8 @@ typedef void (*ip_flow_enable_t)(void *, ip_mac_tx_cookie_t);
typedef void *(*ip_dld_callb_t)(void *,
ip_flow_enable_t, void *);
typedef boolean_t (*ip_dld_fctl_t)(void *, ip_mac_tx_cookie_t);
+typedef boolean_t (*ip_mac_ipcheck_t)(void *, boolean_t,
+ in6_addr_t *);
typedef int (*ip_capab_func_t)(void *, uint_t,
void *, uint_t);
@@ -3627,6 +3637,12 @@ typedef struct ill_dld_direct_s { /* DLD provided driver Tx */
void *idd_tx_fctl_dh; /* mac_client_handle */
} ill_dld_direct_t;
+/* IP - DLD direct function call to check if an IP is allowed */
+typedef struct ill_dld_ipcheck_s {
+ ip_mac_ipcheck_t idi_allowed_df;
+ void *idi_allowed_dh;
+} ill_dld_ipcheck_t;
+
/* IP - DLD polling capability */
typedef struct ill_dld_poll_s {
ill_rx_ring_t idp_ring_tbl[ILL_MAX_RINGS];
@@ -3638,6 +3654,7 @@ struct ill_dld_capab_s {
void *idc_capab_dh; /* dld_str_t *dsp */
ill_dld_direct_t idc_direct;
ill_dld_poll_t idc_poll;
+ ill_dld_ipcheck_t idc_ipcheck;
};
/*
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index aef71717b3..d673a92387 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -4129,6 +4129,8 @@ ip_modclose(ill_t *ill)
rw_destroy(&ill->ill_mcast_lock);
mutex_destroy(&ill->ill_mcast_serializer);
list_destroy(&ill->ill_nce);
+ cv_destroy(&ill->ill_dlpi_capab_cv);
+ mutex_destroy(&ill->ill_dlpi_capab_lock);
/*
* Now we are done with the module close pieces that
@@ -8200,7 +8202,6 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
conn_t *connp = NULL;
t_uscalar_t paddrreq;
mblk_t *mp_hw;
- boolean_t success;
boolean_t ioctl_aborted = B_FALSE;
boolean_t log = B_TRUE;
@@ -8300,7 +8301,8 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
ill->ill_state_flags &= ~ILL_DOWN_IN_PROGRESS;
mutex_exit(&ill->ill_lock);
/*
- * Something went wrong with the bind. We presumably
+ * Something went wrong with the bind. If this was the
+ * result of a DL_NOTE_REPLUMB, then we presumably
* have an IOCTL hanging out waiting for completion.
* Find it, take down the interface that was coming
* up, and complete the IOCTL with the error noted.
@@ -8317,6 +8319,15 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
(void) ipif_down(ipif, NULL, NULL);
/* error is set below the switch */
+ } else {
+ /*
+ * There's no pending IOCTL, so the bind was
+ * most likely started by ill_dl_up(). We save
+ * the error and let it take care of responding
+ * to the IOCTL.
+ */
+ ill->ill_dl_bind_err = dlea->dl_unix_errno ?
+ dlea->dl_unix_errno : ENXIO;
}
break;
case DL_ENABMULTI_REQ:
@@ -8440,55 +8451,7 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
DTRACE_PROBE1(ip__rput__dlpi__bind__ack, ill_t *, ill);
ill_nic_event_dispatch(ill, 0, NE_UP, NULL, 0);
- /*
- * Now bring up the resolver; when that is complete, we'll
- * create IREs. Note that we intentionally mirror what
- * ipif_up() would have done, because we got here by way of
- * ill_dl_up(), which stopped ipif_up()'s processing.
- */
- if (ill->ill_isv6) {
- /*
- * v6 interfaces.
- * Unlike ARP which has to do another bind
- * and attach, once we get here we are
- * done with NDP
- */
- (void) ipif_resolver_up(ipif, Res_act_initial);
- if ((err = ipif_ndp_up(ipif, B_TRUE)) == 0)
- err = ipif_up_done_v6(ipif);
- } else if (ill->ill_net_type == IRE_IF_RESOLVER) {
- /*
- * ARP and other v4 external resolvers.
- * Leave the pending mblk intact so that
- * the ioctl completes in ip_rput().
- */
- if (connp != NULL)
- mutex_enter(&connp->conn_lock);
- mutex_enter(&ill->ill_lock);
- success = ipsq_pending_mp_add(connp, ipif, q, mp1, 0);
- mutex_exit(&ill->ill_lock);
- if (connp != NULL)
- mutex_exit(&connp->conn_lock);
- if (success) {
- err = ipif_resolver_up(ipif, Res_act_initial);
- if (err == EINPROGRESS) {
- freemsg(mp);
- return;
- }
- mp1 = ipsq_pending_mp_get(ipsq, &connp);
- } else {
- /* The conn has started closing */
- err = EINTR;
- }
- } else {
- /*
- * This one is complete. Reply to pending ioctl.
- */
- (void) ipif_resolver_up(ipif, Res_act_initial);
- err = ipif_up_done(ipif);
- }
-
- if ((err == 0) && (ill->ill_up_ipifs)) {
+ if (ill->ill_up_ipifs) {
err = ill_up_ipifs(ill, q, mp1);
if (err == EINPROGRESS) {
freemsg(mp);
@@ -8496,25 +8459,6 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
}
}
- /*
- * If we have a moved ipif to bring up, and everything has
- * succeeded to this point, bring it up on the IPMP ill.
- * Otherwise, leave it down -- the admin can try to bring it
- * up by hand if need be.
- */
- if (ill->ill_move_ipif != NULL) {
- if (err != 0) {
- ill->ill_move_ipif = NULL;
- } else {
- ipif = ill->ill_move_ipif;
- ill->ill_move_ipif = NULL;
- err = ipif_up(ipif, q, mp1);
- if (err == EINPROGRESS) {
- freemsg(mp);
- return;
- }
- }
- }
break;
case DL_NOTIFY_IND: {
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index b88dcae2d1..c4b60daa68 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -174,7 +174,7 @@ static ipif_t *ipif_lookup_on_name_async(char *name, size_t namelen,
static int ill_alloc_ppa(ill_if_t *, ill_t *);
static void ill_delete_interface_type(ill_if_t *);
-static int ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q);
+static int ill_dl_up(ill_t *ill, ipif_t *ipif);
static void ill_dl_down(ill_t *ill);
static void ill_down(ill_t *ill);
static void ill_down_ipifs(ill_t *, boolean_t);
@@ -1380,6 +1380,18 @@ ill_capability_probe(ill_t *ill)
ill->ill_dlpi_capab_state = IDCS_PROBE_SENT;
}
+static void
+ill_capability_wait(ill_t *ill)
+{
+ while (ill->ill_capab_pending_cnt != 0) {
+ mutex_enter(&ill->ill_dlpi_capab_lock);
+ ipsq_exit(ill->ill_phyint->phyint_ipsq);
+ cv_wait(&ill->ill_dlpi_capab_cv, &ill->ill_dlpi_capab_lock);
+ mutex_exit(&ill->ill_dlpi_capab_lock);
+ VERIFY(ipsq_enter(ill, B_FALSE, CUR_OP) == B_TRUE);
+ }
+}
+
void
ill_capability_reset(ill_t *ill, boolean_t reneg)
{
@@ -1390,6 +1402,8 @@ ill_capability_reset(ill_t *ill, boolean_t reneg)
ill->ill_dlpi_capab_state = reneg ? IDCS_RENEG : IDCS_RESET_SENT;
+ ASSERT(ill->ill_capab_reset_mp != NULL);
+
ill_capability_send(ill, ill->ill_capab_reset_mp);
ill->ill_capab_reset_mp = NULL;
/*
@@ -2108,6 +2122,49 @@ ill_capability_lso_enable(ill_t *ill)
}
}
+/*
+ * Check whether or not mac will prevent us from sending with a given IP
+ * address. This requires having the IPCHECK capability, which we should
+ * always be able to successfully negotiate, but if it's somehow missing
+ * then we just permit the caller to use the address, since mac does the
+ * actual enforcement and ip is just performing a courtesy check to help
+ * prevent users from unwittingly setting and attempting to use blocked
+ * addresses.
+ */
+static boolean_t
+ill_ipcheck_addr(ill_t *ill, in6_addr_t *v6addr)
+{
+ if ((ill->ill_capabilities & ILL_CAPAB_DLD_IPCHECK) == 0)
+ return (B_TRUE);
+
+ ill_dld_ipcheck_t *idi = &ill->ill_dld_capab->idc_ipcheck;
+ ip_mac_ipcheck_t ipcheck = idi->idi_allowed_df;
+ return (ipcheck(idi->idi_allowed_dh, ill->ill_isv6, v6addr));
+}
+
+static void
+ill_capability_ipcheck_enable(ill_t *ill)
+{
+ ill_dld_capab_t *idc = ill->ill_dld_capab;
+ ill_dld_ipcheck_t *idi = &idc->idc_ipcheck;
+ dld_capab_ipcheck_t spoof;
+ int rc;
+
+ ASSERT(IAM_WRITER_ILL(ill));
+
+ bzero(&spoof, sizeof (spoof));
+ if ((rc = idc->idc_capab_df(idc->idc_capab_dh, DLD_CAPAB_IPCHECK,
+ &spoof, DLD_ENABLE)) == 0) {
+ idi->idi_allowed_df = (ip_mac_ipcheck_t)spoof.ipc_allowed_df;
+ idi->idi_allowed_dh = spoof.ipc_allowed_dh;
+ ill->ill_capabilities |= ILL_CAPAB_DLD_IPCHECK;
+ } else {
+ cmn_err(CE_WARN, "warning: could not enable IPCHECK "
+ "capability, rc = %d\n", rc);
+ DTRACE_PROBE2(ipcheck__off, (ill_t *), ill, (int), rc);
+ }
+}
+
static void
ill_capability_dld_enable(ill_t *ill)
{
@@ -2115,15 +2172,15 @@ ill_capability_dld_enable(ill_t *ill)
ASSERT(IAM_WRITER_ILL(ill));
- if (ill->ill_isv6)
- return;
-
ill_mac_perim_enter(ill, &mph);
if (!ill->ill_isv6) {
ill_capability_direct_enable(ill);
ill_capability_poll_enable(ill);
ill_capability_lso_enable(ill);
}
+
+ ill_capability_ipcheck_enable(ill);
+
ill->ill_capabilities |= ILL_CAPAB_DLD;
ill_mac_perim_exit(ill, mph);
}
@@ -2188,6 +2245,15 @@ ill_capability_dld_disable(ill_t *ill)
NULL, DLD_DISABLE);
}
+ if ((ill->ill_capabilities & ILL_CAPAB_DLD_IPCHECK) != 0) {
+ ASSERT(ill->ill_dld_capab->idc_ipcheck.idi_allowed_df != NULL);
+ ASSERT(ill->ill_dld_capab->idc_ipcheck.idi_allowed_dh != NULL);
+
+ ill->ill_capabilities &= ~ILL_CAPAB_DLD_IPCHECK;
+ (void) idc->idc_capab_df(idc->idc_capab_dh, DLD_CAPAB_IPCHECK,
+ NULL, DLD_DISABLE);
+ }
+
ill->ill_capabilities &= ~ILL_CAPAB_DLD;
ill_mac_perim_exit(ill, mph);
}
@@ -3429,6 +3495,9 @@ ill_init_common(ill_t *ill, queue_t *q, boolean_t isv6, boolean_t is_loopback,
ill->ill_max_buf = ND_MAX_Q;
ill->ill_refcnt = 0;
+ cv_init(&ill->ill_dlpi_capab_cv, NULL, NULL, NULL);
+ mutex_init(&ill->ill_dlpi_capab_lock, NULL, MUTEX_DEFAULT, NULL);
+
return (0);
}
@@ -9676,7 +9745,6 @@ ip_sioctl_addr(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
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));
@@ -9751,20 +9819,9 @@ 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);
- }
+ /* verify that the address being configured is permitted by mac */
+ if (!ill_ipcheck_addr(ill, &v6addr)) {
+ return (EPERM);
}
/*
* Even if there is no change we redo things just to rerun
@@ -12704,6 +12761,12 @@ ill_dl_down(ill_t *ill)
}
ill->ill_unbind_mp = NULL;
+
+ mutex_enter(&ill->ill_lock);
+ ill->ill_dl_up = 0;
+ ill_nic_event_dispatch(ill, 0, NE_DOWN, NULL, 0);
+ mutex_exit(&ill->ill_lock);
+
if (mp != NULL) {
ip1dbg(("ill_dl_down: %s (%u) for %s\n",
dl_primstr(*(int *)mp->b_rptr), *(int *)mp->b_rptr,
@@ -12726,11 +12789,10 @@ ill_dl_down(ill_t *ill)
ill_capability_dld_disable(ill);
ill_capability_reset(ill, B_FALSE);
ill_dlpi_send(ill, mp);
+
+ /* Wait for the capability reset to finish */
+ ill_capability_wait(ill);
}
- mutex_enter(&ill->ill_lock);
- ill->ill_dl_up = 0;
- ill_nic_event_dispatch(ill, 0, NE_DOWN, NULL, 0);
- mutex_exit(&ill->ill_lock);
}
void
@@ -12859,6 +12921,10 @@ ill_capability_done(ill_t *ill)
if (ill->ill_capab_pending_cnt == 0 &&
ill->ill_dlpi_capab_state == IDCS_OK)
ill_capability_reset_alloc(ill);
+
+ mutex_enter(&ill->ill_dlpi_capab_lock);
+ cv_broadcast(&ill->ill_dlpi_capab_cv);
+ mutex_exit(&ill->ill_dlpi_capab_lock);
}
/*
@@ -14480,7 +14546,14 @@ ipif_up(ipif_t *ipif, queue_t *q, mblk_t *mp)
* address/netmask etc cause a down/up dance, but
* does not cause an unbind (DL_UNBIND) with the driver
*/
- return (ill_dl_up(ill, ipif, mp, q));
+ if ((err = ill_dl_up(ill, ipif)) != 0) {
+ return (err);
+ }
+ }
+
+ /* Reject bringing up interfaces with unusable IP addresses */
+ if (!ill_ipcheck_addr(ill, &ipif->ipif_v6lcl_addr)) {
+ return (EPERM);
}
/*
@@ -14593,24 +14666,22 @@ ill_delete_ires(ill_t *ill)
/*
* Perform a bind for the physical device.
- * When the routine returns EINPROGRESS then mp has been consumed and
- * the ioctl will be acked from ip_rput_dlpi.
- * Allocate an unbind message and save it until ipif_down.
+ *
+ * When the routine returns successfully then dlpi has been bound and
+ * capabilities negotiated. An unbind message will have been allocated
+ * for later use in ipif_down.
*/
static int
-ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
+ill_dl_up(ill_t *ill, ipif_t *ipif)
{
mblk_t *bind_mp = NULL;
mblk_t *unbind_mp = NULL;
- conn_t *connp;
- boolean_t success;
int err;
DTRACE_PROBE2(ill__downup, char *, "ill_dl_up", ill_t *, ill);
ip1dbg(("ill_dl_up(%s)\n", ill->ill_name));
ASSERT(IAM_WRITER_ILL(ill));
- ASSERT(mp != NULL);
/*
* Make sure we have an IRE_MULTICAST in case we immediately
@@ -14645,19 +14716,6 @@ ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
if (unbind_mp == NULL)
goto bad;
}
- /*
- * Record state needed to complete this operation when the
- * DL_BIND_ACK shows up. Also remember the pre-allocated mblks.
- */
- connp = CONN_Q(q) ? Q_TO_CONN(q) : NULL;
- ASSERT(connp != NULL || !CONN_Q(q));
- GRAB_CONN_LOCK(q);
- mutex_enter(&ipif->ipif_ill->ill_lock);
- success = ipsq_pending_mp_add(connp, ipif, q, mp, 0);
- mutex_exit(&ipif->ipif_ill->ill_lock);
- RELEASE_CONN_LOCK(q);
- if (!success)
- goto bad;
/*
* Save the unbind message for ill_dl_down(); it will be consumed when
@@ -14669,6 +14727,13 @@ ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
ill_dlpi_send(ill, bind_mp);
/* Send down link-layer capabilities probe if not already done. */
ill_capability_probe(ill);
+ /* Wait for DLPI to be bound and the capability probe to finish */
+ ill_capability_wait(ill);
+
+ /* DLPI failed to bind. Return the saved error */
+ if (!ill->ill_dl_up) {
+ return (ill->ill_dl_bind_err);
+ }
/*
* Sysid used to rely on the fact that netboots set domainname
@@ -14686,11 +14751,7 @@ ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
cmn_err(CE_WARN, "no cached dhcp response");
}
- /*
- * This operation will complete in ip_rput_dlpi with either
- * a DL_BIND_ACK or DL_ERROR_ACK.
- */
- return (EINPROGRESS);
+ return (0);
bad:
ip1dbg(("ill_dl_up(%s) FAILED\n", ill->ill_name));
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 1ee00681fc..b09d4db0f5 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -1375,6 +1375,9 @@ dld_capab_direct(dld_str_t *dsp, void *data, uint_t flags)
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
+ if (dsp->ds_sap == ETHERTYPE_IPV6)
+ return (ENOTSUP);
+
switch (flags) {
case DLD_ENABLE:
dls_rx_set(dsp, (dls_rx_t)direct->di_rx_cf,
@@ -1484,6 +1487,9 @@ dld_capab_poll(dld_str_t *dsp, void *data, uint_t flags)
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
+ if (dsp->ds_sap == ETHERTYPE_IPV6)
+ return (ENOTSUP);
+
switch (flags) {
case DLD_ENABLE:
return (dld_capab_poll_enable(dsp, poll));
@@ -1494,12 +1500,34 @@ dld_capab_poll(dld_str_t *dsp, void *data, uint_t flags)
}
static int
+dld_capab_ipcheck(dld_str_t *dsp, void *data, uint_t flags)
+{
+ dld_capab_ipcheck_t *ipc = data;
+
+ ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
+
+ switch (flags) {
+ case DLD_ENABLE:
+ ipc->ipc_allowed_df = (uintptr_t)mac_protect_check_addr;
+ ipc->ipc_allowed_dh = dsp->ds_mch;
+ return (0);
+ case DLD_DISABLE:
+ return (0);
+ }
+
+ return (ENOTSUP);
+}
+
+static int
dld_capab_lso(dld_str_t *dsp, void *data, uint_t flags)
{
dld_capab_lso_t *lso = data;
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
+ if (dsp->ds_sap == ETHERTYPE_IPV6)
+ return (ENOTSUP);
+
switch (flags) {
case DLD_ENABLE: {
mac_capab_lso_t mac_lso;
@@ -1545,7 +1573,7 @@ dld_capab(dld_str_t *dsp, uint_t type, void *data, uint_t flags)
* completes. So we limit the check to DLD_ENABLE case.
*/
if ((flags == DLD_ENABLE && type != DLD_CAPAB_PERIM) &&
- ((dsp->ds_sap != ETHERTYPE_IP ||
+ (((dsp->ds_sap != ETHERTYPE_IP && dsp->ds_sap != ETHERTYPE_IPV6) ||
!check_mod_above(dsp->ds_rq, "ip")) &&
!check_mod_above(dsp->ds_rq, "vnd"))) {
return (ENOTSUP);
@@ -1568,6 +1596,10 @@ dld_capab(dld_str_t *dsp, uint_t type, void *data, uint_t flags)
err = dld_capab_lso(dsp, data, flags);
break;
+ case DLD_CAPAB_IPCHECK:
+ err = dld_capab_ipcheck(dsp, data, flags);
+ break;
+
default:
err = ENOTSUP;
break;
@@ -1634,7 +1666,7 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
* native media type so we know that there are no transformations that
* would have to happen to the mac header that it receives.
*/
- if ((dsp->ds_sap == ETHERTYPE_IP &&
+ if (((dsp->ds_sap == ETHERTYPE_IP || dsp->ds_sap == ETHERTYPE_IPV6) &&
check_mod_above(dsp->ds_rq, "ip")) ||
(check_mod_above(dsp->ds_rq, "vnd") &&
dsp->ds_mip->mi_media == dsp->ds_mip->mi_nativemedia)) {
diff --git a/usr/src/uts/common/io/mac/mac_protect.c b/usr/src/uts/common/io/mac/mac_protect.c
index fafb54cef9..ee493bbca1 100644
--- a/usr/src/uts/common/io/mac/mac_protect.c
+++ b/usr/src/uts/common/io/mac/mac_protect.c
@@ -209,7 +209,7 @@ typedef struct slaac_addr {
} slaac_addr_t;
static void start_txn_cleanup_timer(mac_client_impl_t *);
-static boolean_t allowed_ips_set(mac_resource_props_t *, uint32_t);
+static boolean_t dynamic_method_set(mac_protect_t *, uint32_t);
#define BUMP_STAT(m, s) (m)->mci_misc_stat.mms_##s++
@@ -580,8 +580,7 @@ intercept_dhcpv4_outbound(mac_client_impl_t *mcip, ipha_t *ipha, uchar_t *end)
if (get_dhcpv4_info(ipha, end, &dh4) != 0)
return (B_TRUE);
- /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
- if (allowed_ips_set(mrp, IPV4_VERSION))
+ if (!dynamic_method_set(&mrp->mrp_protect, MPT_DYN_DHCPV4))
return (B_FALSE);
if (get_dhcpv4_option(dh4, end, CD_DHCP_TYPE, &opt, &opt_len) != 0 ||
@@ -1310,8 +1309,7 @@ intercept_dhcpv6_outbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end)
if (get_dhcpv6_info(ip6h, end, &dh6) != 0)
return (B_TRUE);
- /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
- if (allowed_ips_set(mrp, IPV6_VERSION))
+ if (!dynamic_method_set(&mrp->mrp_protect, MPT_DYN_DHCPV6))
return (B_FALSE);
/*
@@ -1517,6 +1515,10 @@ intercept_ra_inbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end,
{
struct nd_opt_hdr *opt;
int len, optlen;
+ mac_protect_t *protect = &MCIP_RESOURCE_PROPS(mcip)->mrp_protect;
+
+ if (!dynamic_method_set(protect, MPT_DYN_SLAAC))
+ return;
if (ip6h->ip6_hlim != 255) {
DTRACE_PROBE1(invalid__hoplimit, uint8_t, ip6h->ip6_hlim);
@@ -1755,6 +1757,7 @@ ipnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *protect,
if (*addr == INADDR_ANY)
return (B_TRUE);
+ /* If any specific addresses or subnets are allowed, check them */
for (i = 0; i < protect->mp_ipaddrcnt; i++) {
mac_ipaddr_t *v4addr = &protect->mp_ipaddrs[i];
@@ -1775,14 +1778,19 @@ ipnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *protect,
return (B_TRUE);
}
}
- return (protect->mp_ipaddrcnt == 0 ?
- check_dhcpv4_dyn_ip(mcip, *addr) : B_FALSE);
+
+ if (dynamic_method_set(protect, MPT_DYN_DHCPV4)) {
+ return (check_dhcpv4_dyn_ip(mcip, *addr));
+ }
+
+ return (B_FALSE);
}
static boolean_t
ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
in6_addr_t *addr)
{
+ boolean_t slaac_enabled, dhcpv6_enabled;
uint_t i;
/*
@@ -1793,7 +1801,7 @@ ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
IN6_ARE_ADDR_EQUAL(&mcip->mci_v6_local_addr, addr)))
return (B_TRUE);
-
+ /* If any specific addresses or subnets are allowed, check them */
for (i = 0; i < protect->mp_ipaddrcnt; i++) {
mac_ipaddr_t *v6addr = &protect->mp_ipaddrs[i];
@@ -1804,12 +1812,15 @@ ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
return (B_TRUE);
}
- if (protect->mp_ipaddrcnt == 0) {
- return (check_slaac_ip(mcip, addr) ||
- check_dhcpv6_dyn_ip(mcip, addr));
- } else {
- return (B_FALSE);
- }
+ slaac_enabled = dynamic_method_set(protect, MPT_DYN_SLAAC);
+ if (slaac_enabled && check_slaac_ip(mcip, addr))
+ return (B_TRUE);
+
+ dhcpv6_enabled = dynamic_method_set(protect, MPT_DYN_DHCPV6);
+ if (dhcpv6_enabled && check_dhcpv6_dyn_ip(mcip, addr))
+ return (B_TRUE);
+
+ return (B_FALSE);
}
/*
@@ -2577,6 +2588,11 @@ mac_protect_update(mac_resource_props_t *new, mac_resource_props_t *curr)
} else if (np->mp_allcids != 0) {
cp->mp_allcids = MPT_TRUE;
}
+ if (np->mp_dynamic == MPT_RESET) {
+ cp->mp_dynamic = 0;
+ } else if (np->mp_dynamic != 0) {
+ cp->mp_dynamic = np->mp_dynamic;
+ }
}
void
@@ -2620,15 +2636,50 @@ mac_protect_fini(mac_client_impl_t *mcip)
}
static boolean_t
-allowed_ips_set(mac_resource_props_t *mrp, uint32_t af)
+dynamic_method_set(mac_protect_t *mpt, uint32_t method)
{
- int i;
+ if (mpt->mp_dynamic != 0) {
+ return ((mpt->mp_dynamic & method) != 0);
+ } else {
+ return (mpt->mp_ipaddrcnt == 0);
+ }
+}
- for (i = 0; i < mrp->mrp_protect.mp_ipaddrcnt; i++) {
- if (mrp->mrp_protect.mp_ipaddrs[i].ip_version == af)
- return (B_TRUE);
+boolean_t
+mac_protect_check_addr(mac_client_handle_t mch, boolean_t isv6,
+ in6_addr_t *v6addr)
+{
+ mac_perim_handle_t perim;
+ mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
+ mac_handle_t mh = (mac_handle_t)mcip->mci_mip;
+
+ mac_perim_enter_by_mh(mh, &perim);
+
+ mac_resource_props_t *mrp = MCIP_RESOURCE_PROPS(mcip);
+ mac_protect_t *p;
+ boolean_t allowed;
+
+ ASSERT(mrp != NULL);
+
+ p = &mrp->mrp_protect;
+
+ /* If mac protection/ipnospoof isn't enabled, return true */
+ if ((mrp->mrp_mask & MRP_PROTECT) == 0 ||
+ (p->mp_types & MPT_IPNOSPOOF) == 0) {
+ allowed = B_TRUE;
+ goto done;
}
- return (B_FALSE);
+
+ if (isv6) {
+ allowed = ipnospoof_check_v6(mcip, p, v6addr);
+ } else {
+ in_addr_t *v4addr = &V4_PART_OF_V6((*v6addr));
+ allowed = ipnospoof_check_v4(mcip, p, v4addr);
+ }
+
+done:
+ mac_perim_exit(perim);
+ return (allowed);
}
mac_protect_t *
diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h
index 158a802c4a..26d32ab34b 100644
--- a/usr/src/uts/common/sys/dld.h
+++ b/usr/src/uts/common/sys/dld.h
@@ -358,6 +358,7 @@ typedef struct dld_ioc_led {
#define DLD_CAPAB_POLL 0x00000002
#define DLD_CAPAB_PERIM 0x00000003
#define DLD_CAPAB_LSO 0x00000004
+#define DLD_CAPAB_IPCHECK 0x00000005
#define DLD_ENABLE 0x00000001
#define DLD_DISABLE 0x00000002
@@ -414,6 +415,11 @@ typedef struct dld_capab_direct_s {
uint_t di_flags;
} dld_capab_direct_t;
+typedef struct dld_capab_ipcheck_s {
+ uintptr_t ipc_allowed_df;
+ void *ipc_allowed_dh;
+} dld_capab_ipcheck_t;
+
/*
* Polling/softring capability.
*/
diff --git a/usr/src/uts/common/sys/mac_client_priv.h b/usr/src/uts/common/sys/mac_client_priv.h
index 01cb27644c..97b3fd685a 100644
--- a/usr/src/uts/common/sys/mac_client_priv.h
+++ b/usr/src/uts/common/sys/mac_client_priv.h
@@ -58,6 +58,9 @@ extern const mac_info_t *mac_info(mac_handle_t);
extern boolean_t mac_info_get(const char *, mac_info_t *);
extern boolean_t mac_promisc_get(mac_handle_t);
+extern boolean_t mac_protect_check_addr(mac_client_handle_t, boolean_t,
+ in6_addr_t *);
+
extern int mac_start(mac_handle_t);
extern void mac_stop(mac_handle_t);
diff --git a/usr/src/uts/common/sys/mac_flow.h b/usr/src/uts/common/sys/mac_flow.h
index d269d747c2..d37752ec23 100644
--- a/usr/src/uts/common/sys/mac_flow.h
+++ b/usr/src/uts/common/sys/mac_flow.h
@@ -158,6 +158,12 @@ typedef enum {
#define MPT_FALSE 0x00000000
#define MPT_TRUE 0x00000001
+/* Dynamic address detection types */
+#define MPT_DYN_DHCPV4 0x00000001
+#define MPT_DYN_DHCPV6 0x00000002
+#define MPT_DYN_SLAAC 0x00000004
+#define MPT_DYN_ALL 0x00000007
+
typedef struct mac_ipaddr_s {
uint32_t ip_version;
in6_addr_t ip_addr;
@@ -183,6 +189,7 @@ typedef struct mac_protect_s {
uint32_t mp_cidcnt; /* Count of allowed DHCP CIDs */
mac_dhcpcid_t mp_cids[MPT_MAXCID]; /* Allowed DHCP CIDs */
uint32_t mp_allcids; /* Whether to allow all CIDs through */
+ uint32_t mp_dynamic; /* Enabled dynamic address methods */
} mac_protect_t;
/* The default priority for links */