4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2017 Joyent, Inc.
24 * Copyright 2015 Garrett D'Amore <garrett@damore.org>
25 * Copyright 2020 RackTop Systems, Inc.
26 * Copyright 2023 Oxide Computer Company
35 #include <sys/types.h>
41 #include <libdevinfo.h>
43 #include <libdllink.h>
44 #include <libdladm_impl.h>
45 #include <libdlwlan_impl.h>
46 #include <libdlwlan.h>
47 #include <libdlvlan.h>
48 #include <libdlvnic.h>
53 #include <inet/wifi_ioctl.h>
55 #include <libdlstat.h>
56 #include <sys/param.h>
57 #include <sys/debug.h>
60 #include <sys/ethernet.h>
61 #include <inet/iptun.h>
63 #include <sys/sysmacros.h>
65 #include <libdlbridge.h>
67 #include <netinet/dhcp.h>
68 #include <netinet/dhcp6.h>
69 #include <net/if_types.h>
70 #include <libinetutil.h>
72 #include <libdlaggr.h>
73 #include <sys/mac_ether.h>
76 * The linkprop get() callback.
77 * - pd: pointer to the prop_desc_t
78 * - propstrp: a property string array to keep the returned property.
80 * - cntp: number of returned properties.
81 * Caller also uses it to indicate how many it expects.
84 typedef struct prop_desc prop_desc_t
;
86 typedef dladm_status_t
pd_getf_t(dladm_handle_t
, prop_desc_t
*pdp
,
87 datalink_id_t
, char **propstp
, uint_t
*cntp
,
88 datalink_media_t
, uint_t
, uint_t
*);
91 * The linkprop set() callback.
92 * - propval: a val_desc_t array which keeps the property values to be set.
93 * - cnt: number of properties to be set.
94 * - flags: additional flags passed down the system call.
96 * pd_set takes val_desc_t given by pd_check(), translates it into
97 * a format suitable for kernel consumption. This may require allocation
98 * of ioctl buffers etc. pd_set() may call another common routine (used
99 * by all other pd_sets) which invokes the ioctl.
101 typedef dladm_status_t
pd_setf_t(dladm_handle_t
, prop_desc_t
*, datalink_id_t
,
102 val_desc_t
*propval
, uint_t cnt
, uint_t flags
,
106 * The linkprop check() callback.
107 * - propstrp: property string array which keeps the property to be checked.
108 * - cnt: number of properties.
109 * - propval: return value; the property values of the given property strings.
111 * pd_check checks that the input values are valid. It does so by
112 * iteraring through the pd_modval list for the property. If
113 * the modifiable values cannot be expressed as a list, a pd_check
114 * specific to this property can be used. If the input values are
115 * verified to be valid, pd_check allocates a val_desc_t and fills it
116 * with either a val_desc_t found on the pd_modval list or something
117 * generated on the fly.
119 typedef dladm_status_t
pd_checkf_t(dladm_handle_t
, prop_desc_t
*pdp
,
120 datalink_id_t
, char **propstrp
, uint_t
*cnt
,
121 uint_t flags
, val_desc_t
**propval
,
124 typedef struct link_attr_s
{
130 typedef struct dladm_linkprop_args_s
{
131 dladm_status_t dla_status
;
133 } dladm_linkprop_args_t
;
135 static dld_ioc_macprop_t
*i_dladm_buf_alloc_by_name(size_t, datalink_id_t
,
136 const char *, uint_t
, dladm_status_t
*);
137 static dld_ioc_macprop_t
*i_dladm_buf_alloc_by_id(size_t, datalink_id_t
,
138 mac_prop_id_t
, uint_t
, dladm_status_t
*);
139 static dladm_status_t
i_dladm_get_public_prop(dladm_handle_t
, datalink_id_t
,
140 char *, uint_t
, uint_t
*, void *, size_t);
142 static dladm_status_t
i_dladm_set_private_prop(dladm_handle_t
, datalink_id_t
,
143 const char *, char **, uint_t
, uint_t
);
144 static dladm_status_t
i_dladm_get_priv_prop(dladm_handle_t
, datalink_id_t
,
145 const char *, char **, uint_t
*, dladm_prop_type_t
,
147 static dladm_status_t
i_dladm_macprop(dladm_handle_t
, void *, boolean_t
);
148 static const char *dladm_perm2str(uint_t
, char *);
149 static link_attr_t
*dladm_name2prop(const char *);
150 static link_attr_t
*dladm_id2prop(mac_prop_id_t
);
152 static pd_getf_t get_zone
, get_autopush
, get_rate_mod
, get_rate
,
153 get_speed
, get_channel
, get_powermode
, get_radio
,
154 get_duplex
, get_link_state
, get_binary
, get_uint32
,
155 get_flowctl
, get_maxbw
, get_cpus
, get_priority
,
156 get_tagmode
, get_range
, get_stp
, get_bridge_forward
,
157 get_bridge_pvid
, get_protection
, get_rxrings
,
158 get_txrings
, get_cntavail
, get_secondary_macs
,
159 get_allowedips
, get_allowedcids
, get_pool
,
160 get_rings_range
, get_linkmode_prop
, get_bits
,
161 get_promisc_filtered
, get_media
;
163 static pd_setf_t set_zone
, set_rate
, set_powermode
, set_radio
,
164 set_public_prop
, set_resource
, set_stp_prop
,
165 set_bridge_forward
, set_bridge_pvid
, set_secondary_macs
,
166 set_promisc_filtered
, set_public_bitprop
;
168 static pd_checkf_t check_zone
, check_autopush
, check_rate
, check_hoplimit
,
169 check_encaplim
, check_uint32
, check_maxbw
, check_cpus
,
170 check_stp_prop
, check_bridge_pvid
, check_allowedips
,
171 check_allowedcids
, check_secondary_macs
, check_rings
,
172 check_pool
, check_prop
;
181 * default property value, can be set to { "", NULL }
183 val_desc_t pd_defval
;
186 * list of optional property values, can be NULL.
188 * This is set to non-NULL if there is a list of possible property
189 * values. pd_optval would point to the array of possible values.
191 val_desc_t
*pd_optval
;
194 * count of the above optional property values. 0 if pd_optval is NULL.
199 * callback to set link property; set to NULL if this property is
200 * read-only and may be called before or after permanent update; see
206 * callback to get modifiable link property
208 pd_getf_t
*pd_getmod
;
211 * callback to get current link property
216 * callback to validate link property value, set to NULL if pd_optval
217 * is not NULL. In that case, validate the value by comparing it with
218 * the pd_optval. Return a val_desc_t array pointer if the value is
221 pd_checkf_t
*pd_check
;
224 #define PD_TEMPONLY 0x1 /* property is temporary only */
225 #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */
226 #define PD_AFTER_PERM 0x4 /* pd_set after db update; no temporary */
228 * indicate link classes this property applies to.
230 datalink_class_t pd_class
;
233 * indicate link media type this property applies to.
235 datalink_media_t pd_dmedia
;
238 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1
241 * Supported link properties enumerated in the prop_table[] array are
242 * computed using the callback functions in that array. To compute the
243 * property value, multiple distinct system calls may be needed (e.g.,
244 * for wifi speed, we need to issue system calls to get desired/supported
245 * rates). The link_attr[] table enumerates the interfaces to the kernel,
246 * and the type/size of the data passed in the user-kernel interface.
248 static link_attr_t link_attr
[] = {
249 { MAC_PROP_DUPLEX
, sizeof (link_duplex_t
), "duplex"},
251 { MAC_PROP_SPEED
, sizeof (uint64_t), "speed"},
253 { MAC_PROP_STATUS
, sizeof (link_state_t
), "state"},
255 { MAC_PROP_AUTONEG
, sizeof (uint8_t), "adv_autoneg_cap"},
257 { MAC_PROP_MTU
, sizeof (uint32_t), "mtu"},
259 { MAC_PROP_FLOWCTRL
, sizeof (link_flowctrl_t
), "flowctrl"},
261 { MAC_PROP_ADV_FEC_CAP
, sizeof (link_fec_t
), "adv_fec_cap"},
263 { MAC_PROP_EN_FEC_CAP
, sizeof (link_fec_t
), "en_fec_cap"},
265 { MAC_PROP_ZONE
, sizeof (dld_ioc_zid_t
), "zone"},
267 { MAC_PROP_AUTOPUSH
, sizeof (struct dlautopush
), "autopush"},
269 { MAC_PROP_ADV_5000FDX_CAP
, sizeof (uint8_t), "adv_5000fdx_cap"},
271 { MAC_PROP_EN_5000FDX_CAP
, sizeof (uint8_t), "en_5000fdx_cap"},
273 { MAC_PROP_ADV_2500FDX_CAP
, sizeof (uint8_t), "adv_2500fdx_cap"},
275 { MAC_PROP_EN_2500FDX_CAP
, sizeof (uint8_t), "en_2500fdx_cap"},
277 { MAC_PROP_ADV_400GFDX_CAP
, sizeof (uint8_t), "adv_400gfdx_cap"},
279 { MAC_PROP_EN_400GFDX_CAP
, sizeof (uint8_t), "en_400gfdx_cap"},
281 { MAC_PROP_ADV_200GFDX_CAP
, sizeof (uint8_t), "adv_200gfdx_cap"},
283 { MAC_PROP_EN_200GFDX_CAP
, sizeof (uint8_t), "en_200gfdx_cap"},
285 { MAC_PROP_ADV_100GFDX_CAP
, sizeof (uint8_t), "adv_100gfdx_cap"},
287 { MAC_PROP_EN_100GFDX_CAP
, sizeof (uint8_t), "en_100gfdx_cap"},
289 { MAC_PROP_ADV_50GFDX_CAP
, sizeof (uint8_t), "adv_50gfdx_cap"},
291 { MAC_PROP_EN_50GFDX_CAP
, sizeof (uint8_t), "en_50gfdx_cap"},
293 { MAC_PROP_ADV_40GFDX_CAP
, sizeof (uint8_t), "adv_40gfdx_cap"},
295 { MAC_PROP_EN_40GFDX_CAP
, sizeof (uint8_t), "en_40gfdx_cap"},
297 { MAC_PROP_ADV_25GFDX_CAP
, sizeof (uint8_t), "adv_25gfdx_cap"},
299 { MAC_PROP_EN_25GFDX_CAP
, sizeof (uint8_t), "en_25gfdx_cap"},
301 { MAC_PROP_ADV_10GFDX_CAP
, sizeof (uint8_t), "adv_10gfdx_cap"},
303 { MAC_PROP_EN_10GFDX_CAP
, sizeof (uint8_t), "en_10gfdx_cap"},
305 { MAC_PROP_ADV_1000FDX_CAP
, sizeof (uint8_t), "adv_1000fdx_cap"},
307 { MAC_PROP_EN_1000FDX_CAP
, sizeof (uint8_t), "en_1000fdx_cap"},
309 { MAC_PROP_ADV_1000HDX_CAP
, sizeof (uint8_t), "adv_1000hdx_cap"},
311 { MAC_PROP_EN_1000HDX_CAP
, sizeof (uint8_t), "en_1000hdx_cap"},
313 { MAC_PROP_ADV_100FDX_CAP
, sizeof (uint8_t), "adv_100fdx_cap"},
315 { MAC_PROP_EN_100FDX_CAP
, sizeof (uint8_t), "en_100fdx_cap"},
317 { MAC_PROP_ADV_100HDX_CAP
, sizeof (uint8_t), "adv_100hdx_cap"},
319 { MAC_PROP_EN_100HDX_CAP
, sizeof (uint8_t), "en_100hdx_cap"},
321 { MAC_PROP_ADV_10FDX_CAP
, sizeof (uint8_t), "adv_10fdx_cap"},
323 { MAC_PROP_EN_10FDX_CAP
, sizeof (uint8_t), "en_10fdx_cap"},
325 { MAC_PROP_ADV_10HDX_CAP
, sizeof (uint8_t), "adv_10hdx_cap"},
327 { MAC_PROP_EN_10HDX_CAP
, sizeof (uint8_t), "en_10hdx_cap"},
329 { MAC_PROP_WL_ESSID
, sizeof (wl_linkstatus_t
), "essid"},
331 { MAC_PROP_WL_BSSID
, sizeof (wl_bssid_t
), "bssid"},
333 { MAC_PROP_WL_BSSTYPE
, sizeof (wl_bss_type_t
), "bsstype"},
335 { MAC_PROP_WL_LINKSTATUS
, sizeof (wl_linkstatus_t
), "wl_linkstatus"},
337 /* wl_rates_t has variable length */
338 { MAC_PROP_WL_DESIRED_RATES
, sizeof (wl_rates_t
), "desired_rates"},
340 /* wl_rates_t has variable length */
341 { MAC_PROP_WL_SUPPORTED_RATES
, sizeof (wl_rates_t
), "supported_rates"},
343 { MAC_PROP_WL_AUTH_MODE
, sizeof (wl_authmode_t
), "authmode"},
345 { MAC_PROP_WL_ENCRYPTION
, sizeof (wl_encryption_t
), "encryption"},
347 { MAC_PROP_WL_RSSI
, sizeof (wl_rssi_t
), "signal"},
349 { MAC_PROP_WL_PHY_CONFIG
, sizeof (wl_phy_conf_t
), "phy_conf"},
351 { MAC_PROP_WL_CAPABILITY
, sizeof (wl_capability_t
), "capability"},
353 { MAC_PROP_WL_WPA
, sizeof (wl_wpa_t
), "wpa"},
355 /* wl_wpa_ess_t has variable length */
356 { MAC_PROP_WL_SCANRESULTS
, sizeof (wl_wpa_ess_t
), "scan_results"},
358 { MAC_PROP_WL_POWER_MODE
, sizeof (wl_ps_mode_t
), "powermode"},
360 { MAC_PROP_WL_RADIO
, sizeof (dladm_wlan_radio_t
), "wl_radio"},
362 { MAC_PROP_WL_ESS_LIST
, sizeof (wl_ess_list_t
), "wl_ess_list"},
364 { MAC_PROP_WL_KEY_TAB
, sizeof (wl_wep_key_tab_t
), "wl_wep_key"},
366 { MAC_PROP_WL_CREATE_IBSS
, sizeof (wl_create_ibss_t
), "createibss"},
368 /* wl_wpa_ie_t has variable length */
369 { MAC_PROP_WL_SETOPTIE
, sizeof (wl_wpa_ie_t
), "set_ie"},
371 { MAC_PROP_WL_DELKEY
, sizeof (wl_del_key_t
), "wpa_del_key"},
373 { MAC_PROP_WL_KEY
, sizeof (wl_key_t
), "wl_key"},
375 { MAC_PROP_WL_MLME
, sizeof (wl_mlme_t
), "mlme"},
377 { MAC_PROP_TAGMODE
, sizeof (link_tagmode_t
), "tagmode"},
379 { MAC_PROP_IPTUN_HOPLIMIT
, sizeof (uint32_t), "hoplimit"},
381 { MAC_PROP_IPTUN_ENCAPLIMIT
, sizeof (uint32_t), "encaplimit"},
383 { MAC_PROP_PVID
, sizeof (uint16_t), "default_tag"},
385 { MAC_PROP_LLIMIT
, sizeof (uint32_t), "learn_limit"},
387 { MAC_PROP_LDECAY
, sizeof (uint32_t), "learn_decay"},
389 { MAC_PROP_RESOURCE
, sizeof (mac_resource_props_t
), "resource"},
391 { MAC_PROP_RESOURCE_EFF
, sizeof (mac_resource_props_t
),
392 "resource-effective"},
394 { MAC_PROP_RXRINGSRANGE
, sizeof (mac_propval_range_t
), "rxrings"},
396 { MAC_PROP_TXRINGSRANGE
, sizeof (mac_propval_range_t
), "txrings"},
398 { MAC_PROP_MAX_TX_RINGS_AVAIL
, sizeof (uint_t
),
399 "txrings-available"},
401 { MAC_PROP_MAX_RX_RINGS_AVAIL
, sizeof (uint_t
),
402 "rxrings-available"},
404 { MAC_PROP_MAX_RXHWCLNT_AVAIL
, sizeof (uint_t
), "rxhwclnt-available"},
406 { MAC_PROP_MAX_TXHWCLNT_AVAIL
, sizeof (uint_t
), "txhwclnt-available"},
408 { MAC_PROP_IB_LINKMODE
, sizeof (uint32_t), "linkmode"},
410 { MAC_PROP_VN_PROMISC_FILTERED
, sizeof (boolean_t
), "promisc-filtered"},
412 { MAC_PROP_SECONDARY_ADDRS
, sizeof (mac_secondary_addr_t
),
415 { MAC_PROP_MEDIA
, sizeof (uint32_t), "media" },
417 { MAC_PROP_PRIVATE
, 0, "driver-private"}
420 typedef struct bridge_public_prop_s
{
421 const char *bpp_name
;
423 } bridge_public_prop_t
;
425 static const bridge_public_prop_t bridge_prop
[] = {
426 { "stp", PT_CFG_NON_STP
},
427 { "stp_priority", PT_CFG_PRIO
},
428 { "stp_cost", PT_CFG_COST
},
429 { "stp_edge", PT_CFG_EDGE
},
430 { "stp_p2p", PT_CFG_P2P
},
431 { "stp_mcheck", PT_CFG_MCHECK
},
435 static val_desc_t link_duplex_vals
[] = {
436 { "half", LINK_DUPLEX_HALF
},
437 { "full", LINK_DUPLEX_HALF
}
439 static val_desc_t link_status_vals
[] = {
440 { "up", LINK_STATE_UP
},
441 { "down", LINK_STATE_DOWN
}
443 static val_desc_t link_01_vals
[] = {
447 static val_desc_t link_flow_vals
[] = {
448 { "no", LINK_FLOWCTRL_NONE
},
449 { "tx", LINK_FLOWCTRL_TX
},
450 { "rx", LINK_FLOWCTRL_RX
},
451 { "bi", LINK_FLOWCTRL_BI
}
453 static val_desc_t link_fec_vals
[] = {
454 { "none", LINK_FEC_NONE
},
455 { "auto", LINK_FEC_AUTO
},
456 { "rs", LINK_FEC_RS
},
457 { "base-r", LINK_FEC_BASE_R
}
459 static val_desc_t link_priority_vals
[] = {
461 { "medium", MPL_MEDIUM
},
465 static val_desc_t link_tagmode_vals
[] = {
466 { "normal", LINK_TAGMODE_NORMAL
},
467 { "vlanonly", LINK_TAGMODE_VLANONLY
}
470 static val_desc_t link_protect_vals
[] = {
471 { "mac-nospoof", MPT_MACNOSPOOF
},
472 { "restricted", MPT_RESTRICTED
},
473 { "ip-nospoof", MPT_IPNOSPOOF
},
474 { "dhcp-nospoof", MPT_DHCPNOSPOOF
},
477 static val_desc_t link_promisc_filtered_vals
[] = {
482 static val_desc_t dladm_wlan_radio_vals
[] = {
483 { "on", DLADM_WLAN_RADIO_ON
},
484 { "off", DLADM_WLAN_RADIO_OFF
}
487 static val_desc_t dladm_wlan_powermode_vals
[] = {
488 { "off", DLADM_WLAN_PM_OFF
},
489 { "fast", DLADM_WLAN_PM_FAST
},
490 { "max", DLADM_WLAN_PM_MAX
}
493 static val_desc_t stp_p2p_vals
[] = {
494 { "true", P2P_FORCE_TRUE
},
495 { "false", P2P_FORCE_FALSE
},
499 static val_desc_t dladm_part_linkmode_vals
[] = {
500 { "cm", DLADM_PART_CM_MODE
},
501 { "ud", DLADM_PART_UD_MODE
},
504 static val_desc_t dladm_ether_media_vals
[] = {
505 { "unknown", ETHER_MEDIA_UNKNOWN
},
506 { "none", ETHER_MEDIA_NONE
},
507 { "10BASE-T", ETHER_MEDIA_10BASE_T
},
508 { "100BASE-T4", ETHER_MEDIA_100BASE_T4
},
509 { "100BASE-X", ETHER_MEDIA_100BASE_X
},
510 { "100BASE-T2", ETHER_MEDIA_100BASE_T2
},
511 { "1000BASE-X", ETHER_MEDIA_1000BASE_X
},
512 { "1000BASE-T", ETHER_MEDIA_1000BASE_T
},
513 { "1000BASE-KX", ETHER_MEDIA_1000BASE_KX
},
514 { "1000BASE-T1", ETHER_MEDIA_1000BASE_T1
},
515 { "1000BASE-CX", ETHER_MEDIA_1000BASE_CX
},
516 { "1000BASE-SX", ETHER_MEDIA_1000BASE_SX
},
517 { "1000BASE-LX", ETHER_MEDIA_1000BASE_LX
},
518 { "1000BASE-BX", ETHER_MEDIA_1000BASE_BX
},
519 { "1000-SGMII", ETHER_MEDIA_1000_SGMII
},
520 { "100BASE-TX", ETHER_MEDIA_100BASE_TX
},
521 { "100BASE-FX", ETHER_MEDIA_100BASE_FX
},
522 { "100-SGMII", ETHER_MEDIA_100_SGMII
},
523 { "10BASE-T1", ETHER_MEDIA_10BASE_T1
},
524 { "100BASE-T1", ETHER_MEDIA_100BASE_T1
},
525 { "2500BASE-T", ETHER_MEDIA_2500BASE_T
},
526 { "2500BASE-KX", ETHER_MEDIA_2500BASE_KX
},
527 { "2500BASE-X", ETHER_MEDIA_2500BASE_X
},
528 { "5000BASE-T", ETHER_MEDIA_5000BASE_T
},
529 { "5000BASE-KR", ETHER_MEDIA_5000BASE_KR
},
530 { "10GBASE-T", ETHER_MEDIA_10GBASE_T
},
531 { "10GBASE-SR", ETHER_MEDIA_10GBASE_SR
},
532 { "10GBASE-LR", ETHER_MEDIA_10GBASE_LR
},
533 { "10GBASE-LRM", ETHER_MEDIA_10GBASE_LRM
},
534 { "10GBASE-KR", ETHER_MEDIA_10GBASE_KR
},
535 { "10GBASE-CX4", ETHER_MEDIA_10GBASE_CX4
},
536 { "10GBASE-KX4", ETHER_MEDIA_10GBASE_KX4
},
537 { "10G-XAUI", ETHER_MEDIA_10G_XAUI
},
538 { "10GBASE-AOC", ETHER_MEDIA_10GBASE_AOC
},
539 { "10GBASE-ACC", ETHER_MEDIA_10GBASE_ACC
},
540 { "10GBASE-CR", ETHER_MEDIA_10GBASE_CR
},
541 { "10GBASE-ER", ETHER_MEDIA_10GBASE_ER
},
542 { "10G-SFI", ETHER_MEDIA_10G_SFI
},
543 { "10G-XFI", ETHER_MEDIA_10G_XFI
},
544 { "25GBASE-T", ETHER_MEDIA_25GBASE_T
},
545 { "25GBASE-SR", ETHER_MEDIA_25GBASE_SR
},
546 { "25GBASE-LR", ETHER_MEDIA_25GBASE_LR
},
547 { "25GBASE-ER", ETHER_MEDIA_25GBASE_ER
},
548 { "25GBASE-KR", ETHER_MEDIA_25GBASE_KR
},
549 { "25GBASE-CR", ETHER_MEDIA_25GBASE_CR
},
550 { "25GBASE-AOC", ETHER_MEDIA_25GBASE_AOC
},
551 { "25GBASE-ACC", ETHER_MEDIA_25GBASE_ACC
},
552 { "25G-AUI", ETHER_MEDIA_25G_AUI
},
553 { "40GBASE-T", ETHER_MEDIA_40GBASE_T
},
554 { "40GBASE-CR4", ETHER_MEDIA_40GBASE_CR4
},
555 { "40GBASE-KR4", ETHER_MEDIA_40GBASE_KR4
},
556 { "40GBASE-LR4", ETHER_MEDIA_40GBASE_LR4
},
557 { "40GBASE-SR4", ETHER_MEDIA_40GBASE_SR4
},
558 { "40GBASE-ER4", ETHER_MEDIA_40GBASE_ER4
},
559 { "40GBASE-LM4", ETHER_MEDIA_40GBASE_LM4
},
560 { "40GBASE-AOC4", ETHER_MEDIA_40GBASE_AOC4
},
561 { "40GBASE-ACC4", ETHER_MEDIA_40GBASE_ACC4
},
562 { "40G-XLAUI", ETHER_MEDIA_40G_XLAUI
},
563 { "40G-XLPPI", ETHER_MEDIA_40G_XLPPI
},
564 { "50GBASE-KR2", ETHER_MEDIA_50GBASE_KR2
},
565 { "50GBASE-CR2", ETHER_MEDIA_50GBASE_CR2
},
566 { "50GBASE-SR2", ETHER_MEDIA_50GBASE_SR2
},
567 { "50GBASE-LR2", ETHER_MEDIA_50GBASE_LR2
},
568 { "50GBASE-AOC2", ETHER_MEDIA_50GBASE_AOC2
},
569 { "50GBASE-ACC2", ETHER_MEDIA_50GBASE_ACC2
},
570 { "50GBASE-KR", ETHER_MEDIA_50GBASE_KR
},
571 { "50GBASE-CR", ETHER_MEDIA_50GBASE_CR
},
572 { "50GBASE-SR", ETHER_MEDIA_50GBASE_SR
},
573 { "50GBASE-LR", ETHER_MEDIA_50GBASE_LR
},
574 { "50GBASE-FR", ETHER_MEDIA_50GBASE_FR
},
575 { "50GBASE-ER", ETHER_MEDIA_50GBASE_ER
},
576 { "50GBASE-AOC", ETHER_MEDIA_50GBASE_AOC
},
577 { "50GBASE-ACC", ETHER_MEDIA_50GBASE_ACC
},
578 { "100GBASE-CR10", ETHER_MEDIA_100GBASE_CR10
},
579 { "100GBASE-SR10", ETHER_MEDIA_100GBASE_SR10
},
580 { "100GBASE-SR4", ETHER_MEDIA_100GBASE_SR4
},
581 { "100GBASE-LR4", ETHER_MEDIA_100GBASE_LR4
},
582 { "100GBASE-ER4", ETHER_MEDIA_100GBASE_ER4
},
583 { "100GBASE-KR4", ETHER_MEDIA_100GBASE_KR4
},
584 { "100GBASE-CR4", ETHER_MEDIA_100GBASE_CR4
},
585 { "100GBASE-CAUI4", ETHER_MEDIA_100GBASE_CAUI4
},
586 { "100GBASE-AOC4", ETHER_MEDIA_100GBASE_AOC4
},
587 { "100GBASE-ACC4", ETHER_MEDIA_100GBASE_ACC4
},
588 { "100GBASE-KR2", ETHER_MEDIA_100GBASE_KR2
},
589 { "100GBASE-CR2", ETHER_MEDIA_100GBASE_CR2
},
590 { "100GBASE-SR2", ETHER_MEDIA_100GBASE_SR2
},
591 { "100GBASE-KR", ETHER_MEDIA_100GBASE_KR
},
592 { "100GBASE-CR", ETHER_MEDIA_100GBASE_CR
},
593 { "100GBASE-SR", ETHER_MEDIA_100GBASE_SR
},
594 { "100GBASE-DR", ETHER_MEDIA_100GBASE_DR
},
595 { "100GBASE-LR", ETHER_MEDIA_100GBASE_LR
},
596 { "100GBASE-FR", ETHER_MEDIA_100GBASE_FR
},
597 { "200GAUI-4", ETHER_MEDIA_200GAUI_4
},
598 { "200GBASE-CR4", ETHER_MEDIA_200GBASE_CR4
},
599 { "200GBASE-KR4", ETHER_MEDIA_200GBASE_KR4
},
600 { "200GBASE-SR4", ETHER_MEDIA_200GBASE_SR4
},
601 { "200GBASE-DR4", ETHER_MEDIA_200GBASE_DR4
},
602 { "200GBASE-FR4", ETHER_MEDIA_200GBASE_FR4
},
603 { "200GBASE-LR4", ETHER_MEDIA_200GBASE_LR4
},
604 { "200GBASE-ER4", ETHER_MEDIA_200GBASE_ER4
},
605 { "200GAUI-2", ETHER_MEDIA_200GAUI_2
},
606 { "200GBASE-KR2", ETHER_MEDIA_200GBASE_KR2
},
607 { "200GBASE-CR2", ETHER_MEDIA_200GBASE_CR2
},
608 { "200GBASE-SR2", ETHER_MEDIA_200GBASE_SR2
},
609 { "400GAUI-8", ETHER_MEDIA_400GAUI_8
},
610 { "400GBASE-KR8", ETHER_MEDIA_400GBASE_KR8
},
611 { "400GBASE-FR8", ETHER_MEDIA_400GBASE_FR8
},
612 { "400GBASE-LR8", ETHER_MEDIA_400GBASE_LR8
},
613 { "400GBASE-ER8", ETHER_MEDIA_400GBASE_ER8
},
614 { "400GAUI-4", ETHER_MEDIA_400GAUI_4
},
615 { "400GBASE-KR4", ETHER_MEDIA_400GBASE_KR4
},
616 { "400GBASE-CR4", ETHER_MEDIA_400GBASE_CR4
},
617 { "400GBASE-SR4", ETHER_MEDIA_400GBASE_SR4
},
618 { "400GBASE-DR4", ETHER_MEDIA_400GBASE_DR4
},
619 { "400GBASE-FR4", ETHER_MEDIA_400GBASE_FR4
}
622 #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
623 #define RESET_VAL ((uintptr_t)-1)
624 #define UNSPEC_VAL ((uintptr_t)-2)
627 * For the default, if defaults are not defined for the property,
628 * pd_defval.vd_name should be null. If the driver has to be contacted for the
629 * value, vd_name should be the empty string (""). Otherwise, dladm will
630 * just print whatever is in the table.
632 static prop_desc_t prop_table
[] = {
633 { "channel", { NULL
, 0 },
635 get_channel
, NULL
, 0,
636 DATALINK_CLASS_PHYS
, DL_WIFI
},
638 { "powermode", { "off", DLADM_WLAN_PM_OFF
},
639 dladm_wlan_powermode_vals
, VALCNT(dladm_wlan_powermode_vals
),
641 get_powermode
, NULL
, 0,
642 DATALINK_CLASS_PHYS
, DL_WIFI
},
644 { "radio", { "on", DLADM_WLAN_RADIO_ON
},
645 dladm_wlan_radio_vals
, VALCNT(dladm_wlan_radio_vals
),
648 DATALINK_CLASS_PHYS
, DL_WIFI
},
650 { "linkmode", { "cm", DLADM_PART_CM_MODE
},
651 dladm_part_linkmode_vals
, VALCNT(dladm_part_linkmode_vals
),
652 set_public_prop
, NULL
, get_linkmode_prop
, NULL
, 0,
653 DATALINK_CLASS_PART
, DL_IB
},
655 { "speed", { "", 0 }, NULL
, 0,
656 set_rate
, get_rate_mod
,
657 get_rate
, check_rate
, 0,
658 DATALINK_CLASS_PHYS
, DATALINK_ANY_MEDIATYPE
},
660 { "autopush", { "", 0 }, NULL
, 0,
661 set_public_prop
, NULL
,
662 get_autopush
, check_autopush
, PD_CHECK_ALLOC
,
663 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
665 { "zone", { "", 0 }, NULL
, 0,
667 get_zone
, check_zone
, PD_TEMPONLY
|PD_CHECK_ALLOC
,
668 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
670 { "duplex", { "", 0 },
671 link_duplex_vals
, VALCNT(link_duplex_vals
),
672 NULL
, NULL
, get_duplex
, NULL
,
673 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
675 { "state", { "up", LINK_STATE_UP
},
676 link_status_vals
, VALCNT(link_status_vals
),
677 NULL
, NULL
, get_link_state
, NULL
,
678 0, DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
680 { "adv_autoneg_cap", { "", 0 },
681 link_01_vals
, VALCNT(link_01_vals
),
682 set_public_prop
, NULL
, get_binary
, NULL
,
683 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
685 { "mtu", { "", 0 }, NULL
, 0,
686 set_public_prop
, get_range
,
687 get_uint32
, check_uint32
, 0, DATALINK_CLASS_ALL
,
688 DATALINK_ANY_MEDIATYPE
},
690 { "flowctrl", { "", 0 },
691 link_flow_vals
, VALCNT(link_flow_vals
),
692 set_public_prop
, NULL
, get_flowctl
, NULL
,
693 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
695 { "adv_fec_cap", { "", LINK_FEC_AUTO
},
696 link_fec_vals
, VALCNT(link_fec_vals
),
697 NULL
, NULL
, get_bits
, NULL
,
698 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
700 { "en_fec_cap", { "", LINK_FEC_AUTO
},
701 link_fec_vals
, VALCNT(link_fec_vals
),
702 set_public_bitprop
, NULL
, get_bits
, NULL
,
703 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
705 { "secondary-macs", { "--", 0 }, NULL
, 0,
706 set_secondary_macs
, NULL
,
707 get_secondary_macs
, check_secondary_macs
, PD_CHECK_ALLOC
,
708 DATALINK_CLASS_VNIC
, DL_ETHER
},
710 { "adv_400gfdx_cap", { "", 0 },
711 link_01_vals
, VALCNT(link_01_vals
),
712 NULL
, NULL
, get_binary
, NULL
,
713 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
715 { "en_400gfdx_cap", { "", 0 },
716 link_01_vals
, VALCNT(link_01_vals
),
717 set_public_prop
, NULL
, get_binary
, NULL
,
718 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
720 { "adv_200gfdx_cap", { "", 0 },
721 link_01_vals
, VALCNT(link_01_vals
),
722 NULL
, NULL
, get_binary
, NULL
,
723 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
725 { "en_200gfdx_cap", { "", 0 },
726 link_01_vals
, VALCNT(link_01_vals
),
727 set_public_prop
, NULL
, get_binary
, NULL
,
728 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
730 { "adv_100gfdx_cap", { "", 0 },
731 link_01_vals
, VALCNT(link_01_vals
),
732 NULL
, NULL
, get_binary
, NULL
,
733 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
735 { "en_100gfdx_cap", { "", 0 },
736 link_01_vals
, VALCNT(link_01_vals
),
737 set_public_prop
, NULL
, get_binary
, NULL
,
738 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
740 { "adv_50gfdx_cap", { "", 0 },
741 link_01_vals
, VALCNT(link_01_vals
),
742 NULL
, NULL
, get_binary
, NULL
,
743 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
745 { "en_50gfdx_cap", { "", 0 },
746 link_01_vals
, VALCNT(link_01_vals
),
747 set_public_prop
, NULL
, get_binary
, NULL
,
748 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
750 { "adv_40gfdx_cap", { "", 0 },
751 link_01_vals
, VALCNT(link_01_vals
),
752 NULL
, NULL
, get_binary
, NULL
,
753 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
755 { "en_40gfdx_cap", { "", 0 },
756 link_01_vals
, VALCNT(link_01_vals
),
757 set_public_prop
, NULL
, get_binary
, NULL
,
758 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
760 { "adv_25gfdx_cap", { "", 0 },
761 link_01_vals
, VALCNT(link_01_vals
),
762 NULL
, NULL
, get_binary
, NULL
,
763 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
765 { "en_25gfdx_cap", { "", 0 },
766 link_01_vals
, VALCNT(link_01_vals
),
767 set_public_prop
, NULL
, get_binary
, NULL
,
768 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
770 { "adv_10gfdx_cap", { "", 0 },
771 link_01_vals
, VALCNT(link_01_vals
),
772 NULL
, NULL
, get_binary
, NULL
,
773 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
775 { "en_10gfdx_cap", { "", 0 },
776 link_01_vals
, VALCNT(link_01_vals
),
777 set_public_prop
, NULL
, get_binary
, NULL
,
778 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
780 { "adv_5000fdx_cap", { "", 0 },
781 link_01_vals
, VALCNT(link_01_vals
),
782 NULL
, NULL
, get_binary
, NULL
,
783 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
785 { "en_5000fdx_cap", { "", 0 },
786 link_01_vals
, VALCNT(link_01_vals
),
787 set_public_prop
, NULL
, get_binary
, NULL
,
788 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
790 { "adv_2500fdx_cap", { "", 0 },
791 link_01_vals
, VALCNT(link_01_vals
),
792 NULL
, NULL
, get_binary
, NULL
,
793 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
795 { "en_2500fdx_cap", { "", 0 },
796 link_01_vals
, VALCNT(link_01_vals
),
797 set_public_prop
, NULL
, get_binary
, NULL
,
798 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
800 { "adv_1000fdx_cap", { "", 0 },
801 link_01_vals
, VALCNT(link_01_vals
),
802 NULL
, NULL
, get_binary
, NULL
,
803 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
805 { "en_1000fdx_cap", { "", 0 },
806 link_01_vals
, VALCNT(link_01_vals
),
807 set_public_prop
, NULL
, get_binary
, NULL
,
808 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
810 { "adv_1000hdx_cap", { "", 0 },
811 link_01_vals
, VALCNT(link_01_vals
),
812 NULL
, NULL
, get_binary
, NULL
,
813 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
815 { "en_1000hdx_cap", { "", 0 },
816 link_01_vals
, VALCNT(link_01_vals
),
817 set_public_prop
, NULL
, get_binary
, NULL
,
818 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
820 { "adv_100fdx_cap", { "", 0 },
821 link_01_vals
, VALCNT(link_01_vals
),
822 NULL
, NULL
, get_binary
, NULL
,
823 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
825 { "en_100fdx_cap", { "", 0 },
826 link_01_vals
, VALCNT(link_01_vals
),
827 set_public_prop
, NULL
, get_binary
, NULL
,
828 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
830 { "adv_100hdx_cap", { "", 0 },
831 link_01_vals
, VALCNT(link_01_vals
),
832 NULL
, NULL
, get_binary
, NULL
,
833 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
835 { "en_100hdx_cap", { "", 0 },
836 link_01_vals
, VALCNT(link_01_vals
),
837 set_public_prop
, NULL
, get_binary
, NULL
,
838 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
840 { "adv_10fdx_cap", { "", 0 },
841 link_01_vals
, VALCNT(link_01_vals
),
842 NULL
, NULL
, get_binary
, NULL
,
843 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
845 { "en_10fdx_cap", { "", 0 },
846 link_01_vals
, VALCNT(link_01_vals
),
847 set_public_prop
, NULL
, get_binary
, NULL
,
848 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
850 { "adv_10hdx_cap", { "", 0 },
851 link_01_vals
, VALCNT(link_01_vals
),
852 NULL
, NULL
, get_binary
, NULL
,
853 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
855 { "en_10hdx_cap", { "", 0 },
856 link_01_vals
, VALCNT(link_01_vals
),
857 set_public_prop
, NULL
, get_binary
, NULL
,
858 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
860 { "maxbw", { "--", RESET_VAL
}, NULL
, 0,
862 get_maxbw
, check_maxbw
, PD_CHECK_ALLOC
,
863 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
865 { "cpus", { "--", RESET_VAL
}, NULL
, 0,
867 get_cpus
, check_cpus
, 0,
868 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
870 { "cpus-effective", { "--", 0 },
873 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
875 { "pool", { "--", RESET_VAL
}, NULL
, 0,
877 get_pool
, check_pool
, 0,
878 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
880 { "pool-effective", { "--", 0 },
883 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
885 { "priority", { "high", MPL_RESET
},
886 link_priority_vals
, VALCNT(link_priority_vals
), set_resource
,
887 NULL
, get_priority
, check_prop
, 0,
888 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
890 { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY
},
891 link_tagmode_vals
, VALCNT(link_tagmode_vals
),
892 set_public_prop
, NULL
, get_tagmode
,
894 DATALINK_CLASS_PHYS
| DATALINK_CLASS_AGGR
| DATALINK_CLASS_VNIC
,
897 { "hoplimit", { "", 0 }, NULL
, 0,
898 set_public_prop
, get_range
, get_uint32
,
899 check_hoplimit
, 0, DATALINK_CLASS_IPTUN
, DATALINK_ANY_MEDIATYPE
},
901 { "encaplimit", { "", 0 }, NULL
, 0,
902 set_public_prop
, get_range
, get_uint32
,
903 check_encaplim
, 0, DATALINK_CLASS_IPTUN
, DL_IPV6
},
905 { "forward", { "1", 1 },
906 link_01_vals
, VALCNT(link_01_vals
),
907 set_bridge_forward
, NULL
, get_bridge_forward
, NULL
, PD_AFTER_PERM
,
908 DATALINK_CLASS_ALL
& ~DATALINK_CLASS_VNIC
, DL_ETHER
},
910 { "default_tag", { "1", 1 }, NULL
, 0,
911 set_bridge_pvid
, NULL
, get_bridge_pvid
, check_bridge_pvid
,
912 0, DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
913 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
915 { "learn_limit", { "1000", 1000 }, NULL
, 0,
916 set_public_prop
, NULL
, get_uint32
,
918 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
919 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
921 { "learn_decay", { "200", 200 }, NULL
, 0,
922 set_public_prop
, NULL
, get_uint32
,
924 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
925 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
928 link_01_vals
, VALCNT(link_01_vals
),
929 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
930 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
931 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
933 { "stp_priority", { "128", 128 }, NULL
, 0,
934 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
935 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
936 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
938 { "stp_cost", { "auto", 0 }, NULL
, 0,
939 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
940 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
941 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
943 { "stp_edge", { "1", 1 },
944 link_01_vals
, VALCNT(link_01_vals
),
945 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
946 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
947 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
949 { "stp_p2p", { "auto", P2P_AUTO
},
950 stp_p2p_vals
, VALCNT(stp_p2p_vals
),
951 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
952 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
953 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
955 { "stp_mcheck", { "0", 0 },
956 link_01_vals
, VALCNT(link_01_vals
),
957 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
958 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
959 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
961 { "protection", { "--", RESET_VAL
},
962 link_protect_vals
, VALCNT(link_protect_vals
),
963 set_resource
, NULL
, get_protection
, check_prop
, 0,
964 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
966 { "promisc-filtered", { "on", 1 },
967 link_promisc_filtered_vals
, VALCNT(link_promisc_filtered_vals
),
968 set_promisc_filtered
, NULL
, get_promisc_filtered
, check_prop
, 0,
969 DATALINK_CLASS_VNIC
, DATALINK_ANY_MEDIATYPE
},
972 { "allowed-ips", { "--", 0 },
973 NULL
, 0, set_resource
, NULL
,
974 get_allowedips
, check_allowedips
, PD_CHECK_ALLOC
,
975 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
977 { "allowed-dhcp-cids", { "--", 0 },
978 NULL
, 0, set_resource
, NULL
,
979 get_allowedcids
, check_allowedcids
, PD_CHECK_ALLOC
,
980 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
982 { "rxrings", { "--", RESET_VAL
}, NULL
, 0,
983 set_resource
, get_rings_range
, get_rxrings
, check_rings
, 0,
984 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
986 { "rxrings-effective", { "--", 0 },
988 get_rxrings
, NULL
, 0,
989 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
991 { "txrings", { "--", RESET_VAL
}, NULL
, 0,
992 set_resource
, get_rings_range
, get_txrings
, check_rings
, 0,
993 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
995 { "txrings-effective", { "--", 0 },
997 get_txrings
, NULL
, 0,
998 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
1000 { "txrings-available", { "", 0 }, NULL
, 0,
1001 NULL
, NULL
, get_cntavail
, NULL
, 0,
1002 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
1004 { "rxrings-available", { "", 0 }, NULL
, 0,
1005 NULL
, NULL
, get_cntavail
, NULL
, 0,
1006 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
1008 { "rxhwclnt-available", { "", 0 }, NULL
, 0,
1009 NULL
, NULL
, get_cntavail
, NULL
, 0,
1010 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
1012 { "txhwclnt-available", { "", 0 }, NULL
, 0,
1013 NULL
, NULL
, get_cntavail
, NULL
, 0,
1014 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
1016 { "media", { NULL
, 0 }, NULL
, 0, NULL
, NULL
, get_media
, NULL
, 0,
1017 DATALINK_CLASS_PHYS
, DATALINK_ANY_MEDIATYPE
}
1020 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
1022 static resource_prop_t rsrc_prop_table
[] = {
1023 {"maxbw", extract_maxbw
},
1024 {"priority", extract_priority
},
1025 {"cpus", extract_cpus
},
1026 {"cpus-effective", extract_cpus
},
1027 {"pool", extract_pool
},
1028 {"pool-effective", extract_pool
},
1029 {"protection", extract_protection
},
1030 {"allowed-ips", extract_allowedips
},
1031 {"allowed-dhcp-cids", extract_allowedcids
},
1032 {"rxrings", extract_rxrings
},
1033 {"rxrings-effective", extract_rxrings
},
1034 {"txrings", extract_txrings
},
1035 {"txrings-effective", extract_txrings
}
1037 #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
1038 sizeof (resource_prop_t))
1041 * when retrieving private properties, we pass down a buffer with
1042 * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
1044 #define DLADM_PROP_BUF_CHUNK 1024
1046 static dladm_status_t
i_dladm_set_linkprop_db(dladm_handle_t
, datalink_id_t
,
1047 const char *, char **, uint_t
);
1048 static dladm_status_t
i_dladm_get_linkprop_db(dladm_handle_t
, datalink_id_t
,
1049 const char *, char **, uint_t
*);
1050 static dladm_status_t
i_dladm_walk_linkprop_priv_db(dladm_handle_t
,
1051 datalink_id_t
, void *, int (*)(dladm_handle_t
,
1052 datalink_id_t
, const char *, void *));
1053 static dladm_status_t
i_dladm_set_single_prop(dladm_handle_t
, datalink_id_t
,
1054 datalink_class_t
, uint32_t, prop_desc_t
*, char **,
1056 static dladm_status_t
i_dladm_set_linkprop(dladm_handle_t
, datalink_id_t
,
1057 const char *, char **, uint_t
, uint_t
,
1058 datalink_class_t
, uint32_t);
1059 static dladm_status_t
i_dladm_getset_defval(dladm_handle_t
, prop_desc_t
*,
1060 datalink_id_t
, datalink_media_t
, uint_t
);
1063 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
1064 * rates to be retrieved. However, we cannot increase it at this
1065 * time because it will break binary compatibility with unbundled
1066 * WiFi drivers and utilities. So for now we define an additional
1067 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
1069 #define MAX_SUPPORT_RATES 64
1071 #define AP_ANCHOR "[anchor]"
1072 #define AP_DELIMITER '.'
1074 static dladm_status_t
1075 check_prop(dladm_handle_t handle __unused
, prop_desc_t
*pdp
,
1076 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
1077 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
1080 uint_t val_cnt
= *val_cntp
;
1081 val_desc_t
*vdp
= *vdpp
;
1083 for (j
= 0; j
< val_cnt
; j
++) {
1084 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
1085 if (strcasecmp(prop_val
[j
],
1086 pdp
->pd_optval
[i
].vd_name
) == 0) {
1090 if (i
== pdp
->pd_noptval
)
1091 return (DLADM_STATUS_BADVAL
);
1093 (void) memcpy(&vdp
[j
], &pdp
->pd_optval
[i
], sizeof (val_desc_t
));
1095 return (DLADM_STATUS_OK
);
1098 static dladm_status_t
1099 i_dladm_set_single_prop(dladm_handle_t handle
, datalink_id_t linkid
,
1100 datalink_class_t
class, uint32_t media
, prop_desc_t
*pdp
, char **prop_val
,
1101 uint_t val_cnt
, uint_t flags
)
1103 dladm_status_t status
= DLADM_STATUS_OK
;
1104 val_desc_t
*vdp
= NULL
;
1105 boolean_t needfree
= B_FALSE
;
1108 if (!(pdp
->pd_class
& class))
1109 return (DLADM_STATUS_BADARG
);
1111 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1112 return (DLADM_STATUS_BADARG
);
1114 if ((flags
& DLADM_OPT_PERSIST
) && (pdp
->pd_flags
& PD_TEMPONLY
))
1115 return (DLADM_STATUS_TEMPONLY
);
1117 if (!(flags
& DLADM_OPT_ACTIVE
))
1118 return (DLADM_STATUS_OK
);
1120 if (pdp
->pd_set
== NULL
)
1121 return (DLADM_STATUS_PROPRDONLY
);
1123 if (prop_val
!= NULL
) {
1124 vdp
= calloc(val_cnt
, sizeof (val_desc_t
));
1126 return (DLADM_STATUS_NOMEM
);
1128 if (pdp
->pd_check
!= NULL
) {
1129 needfree
= ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0);
1130 status
= pdp
->pd_check(handle
, pdp
, linkid
, prop_val
,
1131 &val_cnt
, flags
, &vdp
, media
);
1132 } else if (pdp
->pd_optval
!= NULL
) {
1133 status
= check_prop(handle
, pdp
, linkid
, prop_val
,
1134 &val_cnt
, flags
, &vdp
, media
);
1136 status
= DLADM_STATUS_BADARG
;
1139 if (status
!= DLADM_STATUS_OK
)
1146 if (pdp
->pd_defval
.vd_name
== NULL
)
1147 return (DLADM_STATUS_NOTSUP
);
1150 defval
= (strlen(pdp
->pd_defval
.vd_name
) > 0);
1151 if ((pdp
->pd_flags
& PD_CHECK_ALLOC
) == 0 && !defval
) {
1152 status
= i_dladm_getset_defval(handle
, pdp
, linkid
,
1157 vdp
= calloc(1, sizeof (val_desc_t
));
1159 return (DLADM_STATUS_NOMEM
);
1162 (void) memcpy(vdp
, &pdp
->pd_defval
,
1163 sizeof (val_desc_t
));
1164 } else if (pdp
->pd_check
!= NULL
) {
1165 needfree
= ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0);
1166 status
= pdp
->pd_check(handle
, pdp
, linkid
, prop_val
,
1167 &cnt
, flags
, &vdp
, media
);
1168 if (status
!= DLADM_STATUS_OK
)
1172 if (pdp
->pd_flags
& PD_AFTER_PERM
)
1173 status
= (flags
& DLADM_OPT_PERSIST
) ? DLADM_STATUS_OK
:
1174 DLADM_STATUS_PERMONLY
;
1176 status
= pdp
->pd_set(handle
, pdp
, linkid
, vdp
, cnt
, flags
,
1179 for (i
= 0; i
< cnt
; i
++)
1180 free((void *)((val_desc_t
*)vdp
+ i
)->vd_val
);
1187 static dladm_status_t
1188 i_dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1189 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
,
1190 datalink_class_t
class, uint32_t media
)
1193 boolean_t found
= B_FALSE
;
1194 dladm_status_t status
= DLADM_STATUS_OK
;
1196 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1197 prop_desc_t
*pdp
= &prop_table
[i
];
1200 if (prop_name
!= NULL
&&
1201 (strcasecmp(prop_name
, pdp
->pd_name
) != 0))
1204 s
= i_dladm_set_single_prop(handle
, linkid
, class, media
, pdp
,
1205 prop_val
, val_cnt
, flags
);
1207 if (prop_name
!= NULL
) {
1212 * Some consumers of this function pass a
1213 * prop_name of NULL to indicate that all
1214 * properties should reset to their default
1215 * value. Some properties don't support a
1216 * default value and will return NOTSUP -- for
1217 * the purpose of resetting property values we
1218 * treat it the same as success. We need the
1219 * separate status variable 's' so that we can
1220 * record any failed calls in 'status' and
1221 * continue resetting the rest of the
1224 if (s
!= DLADM_STATUS_OK
&&
1225 s
!= DLADM_STATUS_NOTSUP
)
1230 if (prop_name
[0] == '_') {
1231 /* other private properties */
1232 status
= i_dladm_set_private_prop(handle
, linkid
,
1233 prop_name
, prop_val
, val_cnt
, flags
);
1235 status
= DLADM_STATUS_NOTFOUND
;
1242 * Set/reset link property for specific link
1245 dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1246 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
1248 dladm_status_t status
= DLADM_STATUS_OK
;
1249 datalink_class_t
class;
1251 uint32_t link_flags
;
1253 if ((linkid
== DATALINK_INVALID_LINKID
) || (flags
== 0) ||
1254 (prop_val
== NULL
&& val_cnt
> 0) ||
1255 (prop_val
!= NULL
&& val_cnt
== 0) ||
1256 (prop_name
== NULL
&& prop_val
!= NULL
)) {
1257 return (DLADM_STATUS_BADARG
);
1261 * For well-known property names, normalize the case. We can also
1262 * save the property name itself, so that we can just do a pointer
1263 * equality test later and avoid an extra strcmp.
1265 if (prop_name
!= NULL
) {
1268 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1269 if (strcasecmp(prop_name
, prop_table
[i
].pd_name
) == 0) {
1270 prop_name
= prop_table
[i
].pd_name
;
1277 * Check for valid link property against the flags passed
1278 * and set the link property when active flag is passed.
1280 status
= dladm_datalink_id2info(handle
, linkid
, &link_flags
, &class,
1282 if (status
!= DLADM_STATUS_OK
)
1284 status
= i_dladm_set_linkprop(handle
, linkid
, prop_name
, prop_val
,
1285 val_cnt
, flags
, class, media
);
1286 if (status
!= DLADM_STATUS_OK
)
1290 * Write an entry to the persistent configuration database if
1291 * and only if the user has requested the property to be
1292 * persistent and the link is a persistent link.
1294 if ((flags
& DLADM_OPT_PERSIST
) && (link_flags
& DLMGMT_PERSIST
)) {
1295 status
= i_dladm_set_linkprop_db(handle
, linkid
, prop_name
,
1298 if (status
== DLADM_STATUS_OK
&& (flags
& DLADM_OPT_ACTIVE
)) {
1299 prop_desc_t
*pdp
= prop_table
;
1302 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++, pdp
++) {
1303 if (!(pdp
->pd_flags
& PD_AFTER_PERM
))
1305 if (prop_name
!= NULL
&&
1306 prop_name
!= pdp
->pd_name
)
1308 status
= pdp
->pd_set(handle
, pdp
, linkid
, NULL
,
1317 * Walk all link properties of the given specific link.
1319 * Note: this function currently lacks the ability to walk _all_ private
1320 * properties if the link, because there is no kernel interface to
1321 * retrieve all known private property names. Once such an interface
1322 * is added, this function should be fixed accordingly.
1325 dladm_walk_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
,
1326 int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
1328 dladm_status_t status
;
1329 datalink_class_t
class;
1333 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
1334 return (DLADM_STATUS_BADARG
);
1336 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1338 if (status
!= DLADM_STATUS_OK
)
1342 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1343 if (!(prop_table
[i
].pd_class
& class))
1346 if (!DATALINK_MEDIA_ACCEPTED(prop_table
[i
].pd_dmedia
, media
))
1349 if (func(handle
, linkid
, prop_table
[i
].pd_name
, arg
) ==
1350 DLADM_WALK_TERMINATE
) {
1356 status
= i_dladm_walk_linkprop_priv_db(handle
, linkid
, arg
, func
);
1362 * Get linkprop of the given specific link.
1365 dladm_get_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1366 dladm_prop_type_t type
, const char *prop_name
, char **prop_val
,
1369 dladm_status_t status
= DLADM_STATUS_OK
;
1370 datalink_class_t
class;
1373 uint_t cnt
, dld_flags
= 0;
1377 if (type
== DLADM_PROP_VAL_DEFAULT
)
1378 dld_flags
|= DLD_PROP_DEFAULT
;
1379 else if (type
== DLADM_PROP_VAL_MODIFIABLE
)
1380 dld_flags
|= DLD_PROP_POSSIBLE
;
1382 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1383 prop_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1384 return (DLADM_STATUS_BADARG
);
1386 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1387 if (strcasecmp(prop_name
, prop_table
[i
].pd_name
) == 0) {
1388 prop_name
= prop_table
[i
].pd_name
;
1393 if (i
== DLADM_MAX_PROPS
) {
1394 if (prop_name
[0] == '_') {
1398 if (type
== DLADM_PROP_VAL_PERSISTENT
)
1399 return (i_dladm_get_linkprop_db(handle
, linkid
,
1400 prop_name
, prop_val
, val_cntp
));
1402 return (i_dladm_get_priv_prop(handle
, linkid
,
1403 prop_name
, prop_val
, val_cntp
, type
,
1406 return (DLADM_STATUS_NOTFOUND
);
1410 pdp
= &prop_table
[i
];
1412 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1414 if (status
!= DLADM_STATUS_OK
)
1417 if (!(pdp
->pd_class
& class))
1418 return (DLADM_STATUS_BADARG
);
1420 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1421 return (DLADM_STATUS_BADARG
);
1424 case DLADM_PROP_VAL_CURRENT
:
1425 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1426 media
, dld_flags
, &perm_flags
);
1429 case DLADM_PROP_VAL_PERM
:
1430 if (pdp
->pd_set
== NULL
) {
1431 perm_flags
= MAC_PROP_PERM_READ
;
1433 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1434 val_cntp
, media
, dld_flags
, &perm_flags
);
1437 *prop_val
[0] = '\0';
1439 if (status
== DLADM_STATUS_OK
)
1440 (void) dladm_perm2str(perm_flags
, *prop_val
);
1443 case DLADM_PROP_VAL_DEFAULT
:
1445 * If defaults are not defined for the property,
1446 * pd_defval.vd_name should be null. If the driver
1447 * has to be contacted for the value, vd_name should
1448 * be the empty string (""). Otherwise, dladm will
1449 * just print whatever is in the table.
1451 if (pdp
->pd_defval
.vd_name
== NULL
) {
1452 status
= DLADM_STATUS_NOTSUP
;
1456 if (strlen(pdp
->pd_defval
.vd_name
) == 0) {
1457 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1458 val_cntp
, media
, dld_flags
, &perm_flags
);
1460 (void) strcpy(*prop_val
, pdp
->pd_defval
.vd_name
);
1465 case DLADM_PROP_VAL_MODIFIABLE
:
1466 if (pdp
->pd_getmod
!= NULL
) {
1467 status
= pdp
->pd_getmod(handle
, pdp
, linkid
, prop_val
,
1468 val_cntp
, media
, dld_flags
, &perm_flags
);
1471 cnt
= pdp
->pd_noptval
;
1473 status
= DLADM_STATUS_NOTSUP
;
1474 } else if (cnt
> *val_cntp
) {
1475 status
= DLADM_STATUS_TOOSMALL
;
1477 for (i
= 0; i
< cnt
; i
++) {
1478 (void) strcpy(prop_val
[i
],
1479 pdp
->pd_optval
[i
].vd_name
);
1484 case DLADM_PROP_VAL_PERSISTENT
:
1485 if (pdp
->pd_flags
& PD_TEMPONLY
)
1486 return (DLADM_STATUS_TEMPONLY
);
1487 status
= i_dladm_get_linkprop_db(handle
, linkid
, prop_name
,
1488 prop_val
, val_cntp
);
1491 status
= DLADM_STATUS_BADARG
;
1499 * Get linkprop of the given specific link and run any possible conversion
1500 * of the values using the check function for the property. Fails if the
1501 * check function doesn't succeed for the property value.
1504 dladm_get_linkprop_values(dladm_handle_t handle
, datalink_id_t linkid
,
1505 dladm_prop_type_t type
, const char *prop_name
, uint_t
*ret_val
,
1508 dladm_status_t status
;
1509 datalink_class_t
class;
1517 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1518 ret_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1519 return (DLADM_STATUS_BADARG
);
1521 for (pdp
= prop_table
; pdp
< prop_table
+ DLADM_MAX_PROPS
; pdp
++) {
1522 if (strcasecmp(prop_name
, pdp
->pd_name
) == 0) {
1523 prop_name
= pdp
->pd_name
;
1528 if (pdp
== prop_table
+ DLADM_MAX_PROPS
)
1529 return (DLADM_STATUS_NOTFOUND
);
1531 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
1532 return (DLADM_STATUS_BADARG
);
1534 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1536 if (status
!= DLADM_STATUS_OK
)
1539 if (!(pdp
->pd_class
& class))
1540 return (DLADM_STATUS_BADARG
);
1542 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1543 return (DLADM_STATUS_BADARG
);
1545 prop_val
= malloc(*val_cntp
* sizeof (*prop_val
) +
1546 *val_cntp
* DLADM_PROP_VAL_MAX
);
1547 if (prop_val
== NULL
)
1548 return (DLADM_STATUS_NOMEM
);
1549 for (valc
= 0; valc
< *val_cntp
; valc
++)
1550 prop_val
[valc
] = (char *)(prop_val
+ *val_cntp
) +
1551 valc
* DLADM_PROP_VAL_MAX
;
1553 dld_flags
= (type
== DLADM_PROP_VAL_DEFAULT
) ? DLD_PROP_DEFAULT
: 0;
1556 case DLADM_PROP_VAL_CURRENT
:
1557 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1558 media
, dld_flags
, &perm_flags
);
1561 case DLADM_PROP_VAL_DEFAULT
:
1563 * If defaults are not defined for the property,
1564 * pd_defval.vd_name should be null. If the driver
1565 * has to be contacted for the value, vd_name should
1566 * be the empty string (""). Otherwise, dladm will
1567 * just print whatever is in the table.
1569 if (pdp
->pd_defval
.vd_name
== NULL
) {
1570 status
= DLADM_STATUS_NOTSUP
;
1574 if (pdp
->pd_defval
.vd_name
[0] != '\0') {
1576 *ret_val
= pdp
->pd_defval
.vd_val
;
1578 return (DLADM_STATUS_OK
);
1580 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1581 media
, dld_flags
, &perm_flags
);
1584 case DLADM_PROP_VAL_PERSISTENT
:
1585 if (pdp
->pd_flags
& PD_TEMPONLY
)
1586 status
= DLADM_STATUS_TEMPONLY
;
1588 status
= i_dladm_get_linkprop_db(handle
, linkid
,
1589 prop_name
, prop_val
, val_cntp
);
1593 status
= DLADM_STATUS_BADARG
;
1597 if (status
== DLADM_STATUS_OK
) {
1598 if (pdp
->pd_check
!= NULL
) {
1601 vdp
= malloc(sizeof (val_desc_t
) * *val_cntp
);
1603 status
= DLADM_STATUS_NOMEM
;
1605 status
= pdp
->pd_check(handle
, pdp
, linkid
,
1606 prop_val
, val_cntp
, 0, &vdp
, media
);
1607 if (status
== DLADM_STATUS_OK
) {
1608 for (valc
= 0; valc
< *val_cntp
; valc
++)
1609 ret_val
[valc
] = vdp
[valc
].vd_val
;
1613 for (valc
= 0; valc
< *val_cntp
; valc
++) {
1614 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
1615 if (strcmp(pdp
->pd_optval
[i
].vd_name
,
1616 prop_val
[valc
]) == 0) {
1618 pdp
->pd_optval
[i
].vd_val
;
1622 if (i
== pdp
->pd_noptval
) {
1623 status
= DLADM_STATUS_FAILED
;
1636 i_dladm_init_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
1637 const char *prop_name
, void *arg
)
1639 char *buf
, **propvals
;
1640 uint_t i
, valcnt
= DLADM_MAX_PROP_VALCNT
;
1641 dladm_status_t status
;
1642 dladm_linkprop_args_t
*dla
= arg
;
1644 if ((buf
= malloc((sizeof (char *) + DLADM_PROP_VAL_MAX
) *
1645 DLADM_MAX_PROP_VALCNT
)) == NULL
) {
1646 return (DLADM_WALK_CONTINUE
);
1649 propvals
= (char **)(void *)buf
;
1650 for (i
= 0; i
< valcnt
; i
++) {
1652 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
1653 i
* DLADM_PROP_VAL_MAX
;
1656 if (dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
1657 prop_name
, propvals
, &valcnt
) != DLADM_STATUS_OK
) {
1661 status
= dladm_set_linkprop(handle
, linkid
, prop_name
, propvals
,
1662 valcnt
, dla
->dla_flags
| DLADM_OPT_ACTIVE
);
1664 if (status
!= DLADM_STATUS_OK
)
1665 dla
->dla_status
= status
;
1671 return (DLADM_WALK_CONTINUE
);
1675 i_dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1678 datalink_class_t
class;
1679 dladm_status_t status
;
1681 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, NULL
,
1683 if (status
!= DLADM_STATUS_OK
)
1684 return (DLADM_WALK_TERMINATE
);
1686 if ((class & (DATALINK_CLASS_VNIC
| DATALINK_CLASS_VLAN
)) == 0)
1687 (void) dladm_init_linkprop(handle
, linkid
, B_TRUE
);
1689 return (DLADM_WALK_CONTINUE
);
1693 dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1694 boolean_t any_media
)
1696 dladm_status_t status
= DLADM_STATUS_OK
;
1697 datalink_media_t dmedia
;
1699 dladm_linkprop_args_t
*dla
;
1701 dmedia
= any_media
? DATALINK_ANY_MEDIATYPE
: DL_WIFI
;
1703 dla
= malloc(sizeof (dladm_linkprop_args_t
));
1705 return (DLADM_STATUS_NOMEM
);
1706 dla
->dla_flags
= DLADM_OPT_BOOT
;
1707 dla
->dla_status
= DLADM_STATUS_OK
;
1709 if (linkid
== DATALINK_ALL_LINKID
) {
1710 (void) dladm_walk_datalink_id(i_dladm_init_linkprop
, handle
,
1711 NULL
, DATALINK_CLASS_ALL
, dmedia
, DLADM_OPT_PERSIST
);
1712 } else if (any_media
||
1713 ((dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, &media
, NULL
,
1714 0) == DLADM_STATUS_OK
) &&
1715 DATALINK_MEDIA_ACCEPTED(dmedia
, media
))) {
1716 (void) dladm_walk_linkprop(handle
, linkid
, (void *)dla
,
1717 i_dladm_init_one_prop
);
1718 status
= dla
->dla_status
;
1724 static dladm_status_t
1725 get_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1726 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
1727 uint_t flags
, uint_t
*perm_flags
)
1729 char zone_name
[ZONENAME_MAX
];
1731 dladm_status_t status
;
1734 return (DLADM_STATUS_NOTSUP
);
1736 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1737 perm_flags
, &zid
, sizeof (zid
));
1738 if (status
!= DLADM_STATUS_OK
)
1742 if (zid
!= GLOBAL_ZONEID
) {
1743 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0) {
1744 return (dladm_errno2status(errno
));
1747 (void) strncpy(*prop_val
, zone_name
, DLADM_PROP_VAL_MAX
);
1749 *prop_val
[0] = '\0';
1752 return (DLADM_STATUS_OK
);
1755 typedef int (*zone_get_devroot_t
)(char *, char *, size_t);
1758 i_dladm_get_zone_dev(char *zone_name
, char *dev
, size_t devlen
)
1760 char root
[MAXPATHLEN
];
1761 zone_get_devroot_t real_zone_get_devroot
;
1766 if ((dlhandle
= dlopen("libzonecfg.so.1", RTLD_LAZY
)) == NULL
)
1769 if ((sym
= dlsym(dlhandle
, "zone_get_devroot")) == NULL
) {
1770 (void) dlclose(dlhandle
);
1774 real_zone_get_devroot
= (zone_get_devroot_t
)sym
;
1776 if ((ret
= real_zone_get_devroot(zone_name
, root
, sizeof (root
))) == 0)
1777 (void) snprintf(dev
, devlen
, "%s%s", root
, "/dev");
1778 (void) dlclose(dlhandle
);
1782 static dladm_status_t
1783 i_dladm_update_deventry(dladm_handle_t handle
, zoneid_t zid
,
1784 datalink_id_t linkid
, boolean_t add
)
1786 char path
[MAXPATHLEN
];
1787 char name
[MAXLINKNAMELEN
];
1788 di_prof_t prof
= NULL
;
1789 char zone_name
[ZONENAME_MAX
];
1790 dladm_status_t status
;
1793 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0)
1794 return (dladm_errno2status(errno
));
1795 if (i_dladm_get_zone_dev(zone_name
, path
, sizeof (path
)) != 0)
1796 return (dladm_errno2status(errno
));
1797 if (di_prof_init(path
, &prof
) != 0)
1798 return (dladm_errno2status(errno
));
1800 status
= dladm_linkid2legacyname(handle
, linkid
, name
, MAXLINKNAMELEN
);
1801 if (status
!= DLADM_STATUS_OK
)
1805 ret
= di_prof_add_dev(prof
, name
);
1807 ret
= di_prof_add_exclude(prof
, name
);
1810 status
= dladm_errno2status(errno
);
1814 if (di_prof_commit(prof
) != 0)
1815 status
= dladm_errno2status(errno
);
1823 static dladm_status_t
1824 set_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1825 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
1827 dladm_status_t status
= DLADM_STATUS_OK
;
1828 zoneid_t zid_old
, zid_new
;
1832 return (DLADM_STATUS_BADVALCNT
);
1834 dzp
= (dld_ioc_zid_t
*)vdp
->vd_val
;
1836 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1837 NULL
, &zid_old
, sizeof (zid_old
));
1838 if (status
!= DLADM_STATUS_OK
)
1841 zid_new
= dzp
->diz_zid
;
1842 if (zid_new
== zid_old
)
1843 return (DLADM_STATUS_OK
);
1845 if ((status
= set_public_prop(handle
, pdp
, linkid
, vdp
, val_cnt
,
1846 flags
, media
)) != DLADM_STATUS_OK
)
1850 * It is okay to fail to update the /dev entry (some vanity-named
1851 * links do not have a /dev entry).
1853 if (zid_old
!= GLOBAL_ZONEID
) {
1854 (void) i_dladm_update_deventry(handle
, zid_old
, linkid
,
1857 if (zid_new
!= GLOBAL_ZONEID
)
1858 (void) i_dladm_update_deventry(handle
, zid_new
, linkid
, B_TRUE
);
1860 return (DLADM_STATUS_OK
);
1863 static dladm_status_t
1864 check_zone(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
1865 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
1866 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
1870 dladm_status_t status
= DLADM_STATUS_OK
;
1872 uint_t val_cnt
= *val_cntp
;
1873 val_desc_t
*vdp
= *vdpp
;
1876 return (DLADM_STATUS_BADVALCNT
);
1878 dzp
= malloc(sizeof (dld_ioc_zid_t
));
1880 return (DLADM_STATUS_NOMEM
);
1882 zone_name
= (prop_val
!= NULL
) ? *prop_val
: GLOBAL_ZONENAME
;
1883 if ((zoneid
= getzoneidbyname(zone_name
)) == -1) {
1884 status
= DLADM_STATUS_BADVAL
;
1888 if (zoneid
!= GLOBAL_ZONEID
) {
1891 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &flags
,
1892 sizeof (flags
)) < 0) {
1893 status
= dladm_errno2status(errno
);
1897 if (!(flags
& ZF_NET_EXCL
)) {
1898 status
= DLADM_STATUS_BADVAL
;
1903 (void) memset(dzp
, 0, sizeof (dld_ioc_zid_t
));
1905 dzp
->diz_zid
= zoneid
;
1906 dzp
->diz_linkid
= linkid
;
1908 vdp
->vd_val
= (uintptr_t)dzp
;
1909 return (DLADM_STATUS_OK
);
1915 static dladm_status_t
1916 get_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
1917 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
1918 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
1920 mac_resource_props_t mrp
;
1921 dladm_status_t status
;
1923 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
1924 perm_flags
, &mrp
, sizeof (mrp
));
1925 if (status
!= DLADM_STATUS_OK
)
1928 if ((mrp
.mrp_mask
& MRP_MAXBW
) == 0) {
1930 return (DLADM_STATUS_OK
);
1933 (void) dladm_bw2str(mrp
.mrp_maxbw
, prop_val
[0]);
1935 return (DLADM_STATUS_OK
);
1938 static dladm_status_t
1939 check_maxbw(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
1940 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
1941 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
1944 dladm_status_t status
= DLADM_STATUS_OK
;
1945 uint_t val_cnt
= *val_cntp
;
1946 val_desc_t
*vdp
= *vdpp
;
1949 return (DLADM_STATUS_BADVALCNT
);
1951 maxbw
= malloc(sizeof (uint64_t));
1953 return (DLADM_STATUS_NOMEM
);
1955 status
= dladm_str2bw(*prop_val
, maxbw
);
1956 if (status
!= DLADM_STATUS_OK
) {
1961 if ((*maxbw
< MRP_MAXBW_MINVAL
) && (*maxbw
!= 0)) {
1963 return (DLADM_STATUS_MINMAXBW
);
1966 vdp
->vd_val
= (uintptr_t)maxbw
;
1967 return (DLADM_STATUS_OK
);
1971 extract_maxbw(val_desc_t
*vdp
, uint_t cnt __unused
, void *arg
)
1973 mac_resource_props_t
*mrp
= arg
;
1975 if (vdp
->vd_val
== RESET_VAL
) {
1976 mrp
->mrp_maxbw
= MRP_MAXBW_RESETVAL
;
1978 bcopy((char *)vdp
->vd_val
, &mrp
->mrp_maxbw
, sizeof (uint64_t));
1980 mrp
->mrp_mask
|= MRP_MAXBW
;
1982 return (DLADM_STATUS_OK
);
1985 static dladm_status_t
1986 get_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1987 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
1988 uint_t flags
, uint_t
*perm_flags
)
1990 dladm_status_t status
;
1991 mac_resource_props_t mrp
;
1992 mac_propval_range_t
*pv_range
;
1995 if (strcmp(pdp
->pd_name
, "cpus-effective") == 0) {
1996 status
= i_dladm_get_public_prop(handle
, linkid
,
1997 "resource-effective", flags
, perm_flags
, &mrp
,
2000 status
= i_dladm_get_public_prop(handle
, linkid
,
2001 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
2004 if (status
!= DLADM_STATUS_OK
)
2007 if (mrp
.mrp_ncpus
> *val_cnt
)
2008 return (DLADM_STATUS_TOOSMALL
);
2010 if (mrp
.mrp_ncpus
== 0) {
2012 return (DLADM_STATUS_OK
);
2015 /* Sort CPU list and convert it to a mac_propval_range */
2016 status
= dladm_list2range(mrp
.mrp_cpu
, mrp
.mrp_ncpus
,
2017 MAC_PROPVAL_UINT32
, &pv_range
);
2018 if (status
!= DLADM_STATUS_OK
)
2021 /* Write CPU ranges and individual CPUs */
2022 err
= dladm_range2strs(pv_range
, prop_val
);
2025 return (dladm_errno2status(err
));
2028 *val_cnt
= pv_range
->mpr_count
;
2031 return (DLADM_STATUS_OK
);
2034 static dladm_status_t
2035 check_cpus(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2036 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
2037 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
2041 long nproc
= sysconf(_SC_NPROCESSORS_CONF
);
2042 mac_resource_props_t mrp
;
2043 mac_propval_range_t
*pv_range
;
2046 uint32_t *cpus
= mrp
.mrp_cpu
;
2047 val_desc_t
*vdp
= *vdpp
;
2048 val_desc_t
*newvdp
= NULL
;
2049 uint_t val_cnt
= *val_cntp
;
2050 dladm_status_t status
= DLADM_STATUS_OK
;
2052 /* Get the current pool property */
2053 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
2054 &perm_flags
, &mrp
, sizeof (mrp
));
2056 if (status
== DLADM_STATUS_OK
) {
2057 /* Can't set cpus if a pool is set */
2058 if (strlen(mrp
.mrp_pool
) != 0)
2059 return (DLADM_STATUS_POOLCPU
);
2062 /* Read ranges and convert to mac_propval_range */
2063 status
= dladm_strs2range(prop_val
, val_cnt
, MAC_PROPVAL_UINT32
,
2065 if (status
!= DLADM_STATUS_OK
)
2068 /* Convert mac_propval_range to a single CPU list */
2070 status
= dladm_range2list(pv_range
, cpus
, &ncpus
);
2071 if (status
!= DLADM_STATUS_OK
)
2075 * If a range of CPUs was entered, update value count and reallocate
2076 * the array of val_desc_t's. The array allocated was sized for
2077 * indvidual elements, but needs to be reallocated to accomodate the
2078 * expanded list of CPUs.
2080 if (val_cnt
< ncpus
) {
2081 newvdp
= calloc(*val_cntp
, sizeof (val_desc_t
));
2082 if (newvdp
== NULL
) {
2083 status
= DLADM_STATUS_NOMEM
;
2089 /* Check if all CPUs in the list are online */
2090 for (i
= 0; i
< ncpus
; i
++) {
2091 if (cpus
[i
] >= (uint32_t)nproc
) {
2092 status
= DLADM_STATUS_BADCPUID
;
2096 rc
= p_online(cpus
[i
], P_STATUS
);
2098 status
= DLADM_STATUS_CPUERR
;
2102 if (rc
!= P_ONLINE
) {
2103 status
= DLADM_STATUS_CPUNOTONLINE
;
2107 vdp
[i
].vd_val
= (uintptr_t)cpus
[i
];
2110 /* Check for duplicate CPUs */
2111 for (i
= 0; i
< *val_cntp
; i
++) {
2112 for (j
= 0; j
< *val_cntp
; j
++) {
2113 if (i
!= j
&& vdp
[i
].vd_val
== vdp
[j
].vd_val
) {
2114 status
= DLADM_STATUS_BADVAL
;
2120 /* Update *val_cntp and *vdpp if everything was OK */
2121 if (val_cnt
< ncpus
) {
2127 status
= DLADM_STATUS_OK
;
2138 extract_cpus(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2140 mac_resource_props_t
*mrp
= arg
;
2143 if (vdp
[0].vd_val
== RESET_VAL
) {
2144 bzero(&mrp
->mrp_cpus
, sizeof (mac_cpus_t
));
2145 mrp
->mrp_mask
|= MRP_CPUS
;
2146 return (DLADM_STATUS_OK
);
2149 for (i
= 0; i
< cnt
; i
++)
2150 mrp
->mrp_cpu
[i
] = (uint32_t)vdp
[i
].vd_val
;
2152 mrp
->mrp_ncpus
= cnt
;
2153 mrp
->mrp_mask
|= (MRP_CPUS
|MRP_CPUS_USERSPEC
);
2154 mrp
->mrp_fanout_mode
= MCM_CPUS
;
2155 mrp
->mrp_rx_intr_cpu
= -1;
2157 return (DLADM_STATUS_OK
);
2161 * Get the pool datalink property from the kernel. This is used
2162 * for both the user specified pool and effective pool properties.
2164 static dladm_status_t
2165 get_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2166 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
2167 uint_t flags
, uint_t
*perm_flags
)
2169 mac_resource_props_t mrp
;
2170 dladm_status_t status
;
2172 if (strcmp(pdp
->pd_name
, "pool-effective") == 0) {
2173 status
= i_dladm_get_public_prop(handle
, linkid
,
2174 "resource-effective", flags
, perm_flags
, &mrp
,
2177 status
= i_dladm_get_public_prop(handle
, linkid
,
2178 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
2181 if (status
!= DLADM_STATUS_OK
)
2184 if (strlen(mrp
.mrp_pool
) == 0) {
2185 (*prop_val
)[0] = '\0';
2187 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
2188 "%s", mrp
.mrp_pool
);
2192 return (DLADM_STATUS_OK
);
2195 static dladm_status_t
2196 check_pool(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2197 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp __unused
,
2198 uint_t flags
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
2200 pool_conf_t
*poolconf
;
2202 mac_resource_props_t mrp
;
2203 dladm_status_t status
;
2206 val_desc_t
*vdp
= *vdpp
;
2208 /* Get the current cpus property */
2209 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
2210 &perm_flags
, &mrp
, sizeof (mrp
));
2212 if (status
== DLADM_STATUS_OK
) {
2213 /* Can't set pool if cpus are set */
2214 if (mrp
.mrp_ncpus
!= 0)
2215 return (DLADM_STATUS_POOLCPU
);
2218 poolname
= malloc(sizeof (mrp
.mrp_pool
));
2219 if (poolname
== NULL
)
2220 return (DLADM_STATUS_NOMEM
);
2222 /* Check for pool's availability if not booting */
2223 if ((flags
& DLADM_OPT_BOOT
) == 0) {
2225 /* Allocate and open pool configuration */
2226 if ((poolconf
= pool_conf_alloc()) == NULL
)
2227 return (DLADM_STATUS_BADVAL
);
2229 if (pool_conf_open(poolconf
, pool_dynamic_location(), PO_RDONLY
)
2231 pool_conf_free(poolconf
);
2232 return (DLADM_STATUS_BADVAL
);
2235 /* Look for pool name */
2236 if ((pool
= pool_get_pool(poolconf
, *prop_val
)) == NULL
) {
2237 pool_conf_free(poolconf
);
2238 return (DLADM_STATUS_BADVAL
);
2241 pool_conf_free(poolconf
);
2245 (void) strlcpy(poolname
, *prop_val
, sizeof (mrp
.mrp_pool
));
2246 vdp
->vd_val
= (uintptr_t)poolname
;
2248 return (DLADM_STATUS_OK
);
2252 extract_pool(val_desc_t
*vdp
, uint_t cnt __unused
, void *arg
)
2254 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2256 if (vdp
->vd_val
== RESET_VAL
) {
2257 bzero(&mrp
->mrp_pool
, sizeof (mrp
->mrp_pool
));
2258 mrp
->mrp_mask
|= MRP_POOL
;
2259 return (DLADM_STATUS_OK
);
2262 (void) strlcpy(mrp
->mrp_pool
, (char *)vdp
->vd_val
,
2263 sizeof (mrp
->mrp_pool
));
2264 mrp
->mrp_mask
|= MRP_POOL
;
2266 * Use MCM_CPUS since the fanout count is not user specified
2267 * and will be determined by the cpu list generated from the
2270 mrp
->mrp_fanout_mode
= MCM_CPUS
;
2272 return (DLADM_STATUS_OK
);
2275 static dladm_status_t
2276 get_priority(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2277 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2278 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
2280 mac_resource_props_t mrp
;
2281 mac_priority_level_t pri
;
2282 dladm_status_t status
;
2284 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2285 perm_flags
, &mrp
, sizeof (mrp
));
2286 if (status
!= DLADM_STATUS_OK
)
2289 pri
= ((mrp
.mrp_mask
& MRP_PRIORITY
) == 0) ? MPL_HIGH
:
2292 (void) dladm_pri2str(pri
, prop_val
[0]);
2294 return (DLADM_STATUS_OK
);
2298 extract_priority(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2300 mac_resource_props_t
*mrp
= arg
;
2303 return (DLADM_STATUS_BADVAL
);
2305 mrp
->mrp_priority
= (mac_priority_level_t
)vdp
->vd_val
;
2306 mrp
->mrp_mask
|= MRP_PRIORITY
;
2308 return (DLADM_STATUS_OK
);
2312 * Determines the size of the structure that needs to be sent to drivers
2313 * for retrieving the property range values.
2316 i_dladm_range_size(mac_propval_range_t
*r
, size_t *sz
, uint_t
*rcount
)
2318 uint_t count
= r
->mpr_count
;
2320 *sz
= sizeof (mac_propval_range_t
);
2324 switch (r
->mpr_type
) {
2325 case MAC_PROPVAL_UINT32
:
2326 *sz
+= (count
* sizeof (mac_propval_uint32_range_t
));
2337 static dladm_status_t
2338 check_rings(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
2339 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
2340 uint_t flags __unused
, val_desc_t
**vp
, datalink_media_t media __unused
)
2342 uint_t val_cnt
= *val_cntp
;
2343 val_desc_t
*v
= *vp
;
2346 return (DLADM_STATUS_BADVAL
);
2347 if (strncasecmp(prop_val
[0], "hw", strlen("hw")) == 0) {
2348 v
->vd_val
= UNSPEC_VAL
;
2349 } else if (strncasecmp(prop_val
[0], "sw", strlen("sw")) == 0) {
2352 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
2354 return (DLADM_STATUS_BADVAL
);
2356 return (DLADM_STATUS_OK
);
2359 static dladm_status_t
2360 get_rings_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
2361 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2362 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags __unused
)
2364 dld_ioc_macprop_t
*dip
;
2365 dladm_status_t status
= DLADM_STATUS_OK
;
2366 mac_propval_range_t
*rangep
;
2368 mac_propval_uint32_range_t
*ur
;
2370 sz
= sizeof (mac_propval_range_t
);
2372 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
2376 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
2377 if (status
!= DLADM_STATUS_OK
)
2380 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
2382 ur
= &rangep
->mpr_range_uint32
[0];
2383 /* This is the case where the dev doesn't have any rings/groups */
2384 if (rangep
->mpr_count
== 0) {
2385 (*prop_val
)[0] = '\0';
2387 * This is the case where the dev supports rings, but static
2390 } else if (ur
->mpur_min
== ur
->mpur_max
&&
2391 ur
->mpur_max
== 0) {
2392 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw");
2394 * This is the case where the dev supports rings and dynamic
2395 * grouping, but has only one value (say 2 rings and 2 groups).
2397 } else if (ur
->mpur_min
== ur
->mpur_max
) {
2398 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw,%d",
2401 * This is the case where the dev supports rings and dynamic
2402 * grouping and has a range of rings.
2405 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
,
2406 "sw,hw,<%ld-%ld>", ur
->mpur_min
, ur
->mpur_max
);
2413 static dladm_status_t
2414 get_rxrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2415 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
2416 uint_t flags
, uint_t
*perm_flags
)
2418 mac_resource_props_t mrp
;
2419 dladm_status_t status
;
2420 uint32_t nrings
= 0;
2423 * Get the number of (effective-)rings from the resource property.
2425 if (strcmp(pdp
->pd_name
, "rxrings-effective") == 0) {
2426 status
= i_dladm_get_public_prop(handle
, linkid
,
2427 "resource-effective", flags
, perm_flags
, &mrp
,
2431 * Get the permissions from the "rxrings" property.
2433 status
= i_dladm_get_public_prop(handle
, linkid
, "rxrings",
2434 flags
, perm_flags
, NULL
, 0);
2435 if (status
!= DLADM_STATUS_OK
)
2438 status
= i_dladm_get_public_prop(handle
, linkid
,
2439 "resource", flags
, NULL
, &mrp
, sizeof (mrp
));
2442 if (status
!= DLADM_STATUS_OK
)
2445 if ((mrp
.mrp_mask
& MRP_RX_RINGS
) == 0) {
2447 return (DLADM_STATUS_OK
);
2449 nrings
= mrp
.mrp_nrxrings
;
2451 if (mrp
.mrp_mask
& MRP_RXRINGS_UNSPEC
)
2452 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2453 else if (nrings
== 0)
2454 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2456 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2457 return (DLADM_STATUS_OK
);
2461 extract_rxrings(val_desc_t
*vdp
, uint_t cnt __unused
, void *arg
)
2463 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2465 mrp
->mrp_nrxrings
= 0;
2466 if (vdp
->vd_val
== RESET_VAL
)
2467 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2468 else if (vdp
->vd_val
== UNSPEC_VAL
)
2469 mrp
->mrp_mask
= MRP_RXRINGS_UNSPEC
;
2471 mrp
->mrp_nrxrings
= vdp
->vd_val
;
2472 mrp
->mrp_mask
|= MRP_RX_RINGS
;
2474 return (DLADM_STATUS_OK
);
2477 static dladm_status_t
2478 get_txrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2479 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
2480 uint_t flags
, uint_t
*perm_flags
)
2482 mac_resource_props_t mrp
;
2483 dladm_status_t status
;
2484 uint32_t nrings
= 0;
2488 * Get the number of (effective-)rings from the resource property.
2490 if (strcmp(pdp
->pd_name
, "txrings-effective") == 0) {
2491 status
= i_dladm_get_public_prop(handle
, linkid
,
2492 "resource-effective", flags
, perm_flags
, &mrp
,
2496 * Get the permissions from the "txrings" property.
2498 status
= i_dladm_get_public_prop(handle
, linkid
, "txrings",
2499 flags
, perm_flags
, NULL
, 0);
2500 if (status
!= DLADM_STATUS_OK
)
2504 * Get the number of rings from the "resource" property.
2506 status
= i_dladm_get_public_prop(handle
, linkid
, "resource",
2507 flags
, NULL
, &mrp
, sizeof (mrp
));
2510 if (status
!= DLADM_STATUS_OK
)
2513 if ((mrp
.mrp_mask
& MRP_TX_RINGS
) == 0) {
2515 return (DLADM_STATUS_OK
);
2517 nrings
= mrp
.mrp_ntxrings
;
2519 if (mrp
.mrp_mask
& MRP_TXRINGS_UNSPEC
)
2520 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2521 else if (nrings
== 0)
2522 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2524 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2525 return (DLADM_STATUS_OK
);
2529 extract_txrings(val_desc_t
*vdp
, uint_t cnt __unused
, void *arg
)
2531 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2533 mrp
->mrp_ntxrings
= 0;
2534 if (vdp
->vd_val
== RESET_VAL
)
2535 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2536 else if (vdp
->vd_val
== UNSPEC_VAL
)
2537 mrp
->mrp_mask
= MRP_TXRINGS_UNSPEC
;
2539 mrp
->mrp_ntxrings
= vdp
->vd_val
;
2540 mrp
->mrp_mask
|= MRP_TX_RINGS
;
2542 return (DLADM_STATUS_OK
);
2545 static dladm_status_t
2546 get_cntavail(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2547 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
2550 if (flags
& DLD_PROP_DEFAULT
)
2551 return (DLADM_STATUS_NOTDEFINED
);
2553 return (get_uint32(handle
, pdp
, linkid
, prop_val
, val_cnt
, media
,
2554 flags
, perm_flags
));
2557 static dladm_status_t
2558 set_resource(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2559 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
2560 uint_t flags
, datalink_media_t media __unused
)
2562 mac_resource_props_t mrp
;
2563 dladm_status_t status
= DLADM_STATUS_OK
;
2564 dld_ioc_macprop_t
*dip
;
2567 bzero(&mrp
, sizeof (mac_resource_props_t
));
2568 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "resource",
2574 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
2575 resource_prop_t
*rp
= &rsrc_prop_table
[i
];
2577 if (strcmp(pdp
->pd_name
, rp
->rp_name
) != 0)
2580 status
= rp
->rp_extract(vdp
, val_cnt
, &mrp
);
2581 if (status
!= DLADM_STATUS_OK
)
2587 (void) memcpy(dip
->pr_val
, &mrp
, dip
->pr_valsize
);
2588 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
2595 static dladm_status_t
2596 get_protection(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2597 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2598 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
2600 mac_resource_props_t mrp
;
2602 dladm_status_t status
;
2603 uint32_t i
, cnt
= 0, setbits
[32];
2605 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2606 perm_flags
, &mrp
, sizeof (mrp
));
2607 if (status
!= DLADM_STATUS_OK
)
2610 p
= &mrp
.mrp_protect
;
2611 if ((mrp
.mrp_mask
& MRP_PROTECT
) == 0) {
2613 return (DLADM_STATUS_OK
);
2615 dladm_find_setbits32(p
->mp_types
, setbits
, &cnt
);
2617 return (DLADM_STATUS_BADVALCNT
);
2619 for (i
= 0; i
< cnt
; i
++)
2620 (void) dladm_protect2str(setbits
[i
], prop_val
[i
]);
2623 return (DLADM_STATUS_OK
);
2626 static dladm_status_t
2627 get_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
2628 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2629 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
2631 mac_resource_props_t mrp
;
2633 dladm_status_t status
;
2636 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2637 perm_flags
, &mrp
, sizeof (mrp
));
2638 if (status
!= DLADM_STATUS_OK
)
2641 p
= &mrp
.mrp_protect
;
2642 if (p
->mp_ipaddrcnt
== 0) {
2644 return (DLADM_STATUS_OK
);
2646 if (p
->mp_ipaddrcnt
> *val_cnt
)
2647 return (DLADM_STATUS_BADVALCNT
);
2649 for (i
= 0; i
< p
->mp_ipaddrcnt
; i
++) {
2651 if (p
->mp_ipaddrs
[i
].ip_version
== IPV4_VERSION
) {
2654 v4addr
= V4_PART_OF_V6(p
->mp_ipaddrs
[i
].ip_addr
);
2655 (void) dladm_ipv4addr2str(&v4addr
, prop_val
[i
]);
2657 (void) dladm_ipv6addr2str(&p
->mp_ipaddrs
[i
].ip_addr
,
2660 len
= strlen(prop_val
[i
]);
2661 (void) sprintf(prop_val
[i
] + len
, "/%d",
2662 p
->mp_ipaddrs
[i
].ip_netmask
);
2664 *val_cnt
= p
->mp_ipaddrcnt
;
2665 return (DLADM_STATUS_OK
);
2669 extract_protection(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2671 mac_resource_props_t
*mrp
= arg
;
2675 for (i
= 0; i
< cnt
; i
++)
2676 types
|= (uint32_t)vdp
[i
].vd_val
;
2678 mrp
->mrp_protect
.mp_types
= types
;
2679 mrp
->mrp_mask
|= MRP_PROTECT
;
2680 return (DLADM_STATUS_OK
);
2684 extract_allowedips(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2686 mac_resource_props_t
*mrp
= arg
;
2687 mac_protect_t
*p
= &mrp
->mrp_protect
;
2690 if (vdp
->vd_val
== 0) {
2693 for (i
= 0; i
< cnt
; i
++) {
2694 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_ipaddrs
[i
],
2695 sizeof (mac_ipaddr_t
));
2698 p
->mp_ipaddrcnt
= cnt
;
2699 mrp
->mrp_mask
|= MRP_PROTECT
;
2700 return (DLADM_STATUS_OK
);
2703 static dladm_status_t
2704 check_single_ip(char *buf
, mac_ipaddr_t
*addr
)
2706 dladm_status_t status
;
2709 boolean_t isv4
= B_TRUE
;
2714 * If the IP address is in CIDR format, parse the bits component
2715 * seperately. An address in this style will be used to indicate an
2716 * entire subnet, so it must be a network number with no host address.
2718 if ((p
= strchr(buf
, '/')) != NULL
) {
2723 return (DLADM_STATUS_INVALID_IP
);
2724 mask
= strtol(p
, &end
, 10);
2725 if (end
!= NULL
&& *end
!= '\0')
2726 return (DLADM_STATUS_INVALID_IP
);
2727 if (mask
> 128|| mask
< 1)
2728 return (DLADM_STATUS_INVALID_IP
);
2731 status
= dladm_str2ipv4addr(buf
, &v4addr
);
2732 if (status
== DLADM_STATUS_INVALID_IP
) {
2733 status
= dladm_str2ipv6addr(buf
, &v6addr
);
2734 if (status
== DLADM_STATUS_OK
)
2737 if (status
!= DLADM_STATUS_OK
)
2741 if (v4addr
== INADDR_ANY
)
2742 return (DLADM_STATUS_INVALID_IP
);
2744 IN6_IPADDR_TO_V4MAPPED(v4addr
, &addr
->ip_addr
);
2745 addr
->ip_version
= IPV4_VERSION
;
2750 * Validate the netmask is in the proper range for v4
2752 if (mask
> 32 || mask
< 1)
2753 return (DLADM_STATUS_INVALID_IP
);
2756 * We have a CIDR style address, confirm that only the
2757 * network number is set.
2759 smask
= 0xFFFFFFFFu
<< (32 - mask
);
2760 if (htonl(v4addr
) & ~smask
)
2761 return (DLADM_STATUS_INVALID_IP
);
2765 addr
->ip_netmask
= mask
;
2767 if (IN6_IS_ADDR_UNSPECIFIED(&v6addr
))
2768 return (DLADM_STATUS_INVALID_IP
);
2770 if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr
))
2771 return (DLADM_STATUS_INVALID_IP
);
2777 * Note that the address in our buffer is stored in
2778 * network byte order.
2781 for (i
= 3; i
>= 0; i
--) {
2782 high
= ffsl(ntohl(v6addr
._S6_un
._S6_u32
[i
]));
2788 if (128 - off
>= (int)mask
)
2789 return (DLADM_STATUS_INVALID_IP
);
2794 addr
->ip_addr
= v6addr
;
2795 addr
->ip_version
= IPV6_VERSION
;
2796 addr
->ip_netmask
= mask
;
2798 return (DLADM_STATUS_OK
);
2801 static dladm_status_t
2802 check_allowedips(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
2803 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
2804 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
2806 dladm_status_t status
;
2809 uint_t val_cnt
= *val_cntp
;
2810 val_desc_t
*vdp
= *vdpp
;
2812 if (val_cnt
> MPT_MAXIPADDR
)
2813 return (DLADM_STATUS_BADVALCNT
);
2815 for (i
= 0; i
< val_cnt
; i
++) {
2816 if ((addr
= calloc(1, sizeof (mac_ipaddr_t
))) == NULL
) {
2817 status
= DLADM_STATUS_NOMEM
;
2820 vdp
[i
].vd_val
= (uintptr_t)addr
;
2822 status
= check_single_ip(prop_val
[i
], addr
);
2823 if (status
!= DLADM_STATUS_OK
)
2826 return (DLADM_STATUS_OK
);
2829 for (i
= 0; i
< val_cnt
; i
++) {
2830 free((void *)vdp
[i
].vd_val
);
2837 dladm_cid2str(mac_dhcpcid_t
*cid
, char *buf
)
2839 char tmp_buf
[DLADM_STRSIZE
];
2842 switch (cid
->dc_form
) {
2843 case CIDFORM_TYPED
: {
2844 uint16_t duidtype
, hwtype
;
2845 uint32_t timestamp
, ennum
;
2848 if (cid
->dc_len
< sizeof (duidtype
))
2851 bcopy(cid
->dc_id
, &duidtype
, sizeof (duidtype
));
2852 duidtype
= ntohs(duidtype
);
2854 case DHCPV6_DUID_LLT
: {
2857 if (cid
->dc_len
< sizeof (llt
))
2860 bcopy(cid
->dc_id
, &llt
, sizeof (llt
));
2861 hwtype
= ntohs(llt
.dllt_hwtype
);
2862 timestamp
= ntohl(llt
.dllt_time
);
2863 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (llt
),
2864 NULL
, cid
->dc_len
- sizeof (llt
), IFT_OTHER
);
2868 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%d.%s",
2869 duidtype
, hwtype
, timestamp
, lladdr
);
2873 case DHCPV6_DUID_EN
: {
2876 if (cid
->dc_len
< sizeof (en
))
2879 bcopy(cid
->dc_id
, &en
, sizeof (en
));
2880 ennum
= DHCPV6_GET_ENTNUM(&en
);
2881 hexlen
= sizeof (tmp_buf
);
2882 if (octet_to_hexascii(cid
->dc_id
+ sizeof (en
),
2883 cid
->dc_len
- sizeof (en
), tmp_buf
, &hexlen
) != 0)
2886 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2887 duidtype
, ennum
, tmp_buf
);
2890 case DHCPV6_DUID_LL
: {
2893 if (cid
->dc_len
< sizeof (ll
))
2896 bcopy(cid
->dc_id
, &ll
, sizeof (ll
));
2897 hwtype
= ntohs(ll
.dll_hwtype
);
2898 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (ll
),
2899 NULL
, cid
->dc_len
- sizeof (ll
), IFT_OTHER
);
2903 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2904 duidtype
, hwtype
, lladdr
);
2909 hexlen
= sizeof (tmp_buf
);
2910 if (octet_to_hexascii(cid
->dc_id
+ sizeof (duidtype
),
2911 cid
->dc_len
- sizeof (duidtype
),
2912 tmp_buf
, &hexlen
) != 0)
2915 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%s",
2922 hexlen
= sizeof (tmp_buf
);
2923 if (octet_to_hexascii(cid
->dc_id
, cid
->dc_len
,
2924 tmp_buf
, &hexlen
) != 0)
2927 (void) snprintf(buf
, DLADM_STRSIZE
, "0x%s", tmp_buf
);
2933 for (i
= 0; i
< cid
->dc_len
; i
++) {
2934 if (!isprint(cid
->dc_id
[i
]))
2937 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", cid
->dc_id
);
2946 (void) snprintf(buf
, DLADM_STRSIZE
, "<unknown>");
2949 static dladm_status_t
2950 dladm_str2cid(char *buf
, mac_dhcpcid_t
*cid
)
2953 char tmp_buf
[DLADM_STRSIZE
];
2954 uint_t hexlen
, cidlen
;
2956 bzero(cid
, sizeof (*cid
));
2957 if (isdigit(*ptr
) &&
2958 ptr
[strspn(ptr
, "0123456789")] == '.') {
2961 ulong_t subtype
= 0;
2967 duidtype
= strtoul(ptr
, &cp
, 0);
2968 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.' ||
2969 duidtype
> USHRT_MAX
)
2970 return (DLADM_STATUS_BADARG
);
2973 if (duidtype
!= 0 && duidtype
<= DHCPV6_DUID_LL
) {
2975 subtype
= strtoul(ptr
, &cp
, 0);
2976 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2977 return (DLADM_STATUS_BADARG
);
2981 case DHCPV6_DUID_LLT
: {
2985 timestamp
= strtoul(ptr
, &cp
, 0);
2986 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2987 return (DLADM_STATUS_BADARG
);
2990 lladdr
= _link_aton(ptr
, &addrlen
);
2992 return (DLADM_STATUS_BADARG
);
2994 cidlen
= sizeof (llt
) + addrlen
;
2995 if (cidlen
> sizeof (cid
->dc_id
)) {
2997 return (DLADM_STATUS_TOOSMALL
);
2999 llt
.dllt_dutype
= htons(duidtype
);
3000 llt
.dllt_hwtype
= htons(subtype
);
3001 llt
.dllt_time
= htonl(timestamp
);
3002 bcopy(&llt
, cid
->dc_id
, sizeof (llt
));
3003 bcopy(lladdr
, cid
->dc_id
+ sizeof (llt
), addrlen
);
3007 case DHCPV6_DUID_LL
: {
3010 lladdr
= _link_aton(ptr
, &addrlen
);
3012 return (DLADM_STATUS_BADARG
);
3014 cidlen
= sizeof (ll
) + addrlen
;
3015 if (cidlen
> sizeof (cid
->dc_id
)) {
3017 return (DLADM_STATUS_TOOSMALL
);
3019 ll
.dll_dutype
= htons(duidtype
);
3020 ll
.dll_hwtype
= htons(subtype
);
3021 bcopy(&ll
, cid
->dc_id
, sizeof (ll
));
3022 bcopy(lladdr
, cid
->dc_id
+ sizeof (ll
), addrlen
);
3027 hexlen
= sizeof (tmp_buf
);
3028 if (hexascii_to_octet(ptr
, strlen(ptr
),
3029 tmp_buf
, &hexlen
) != 0)
3030 return (DLADM_STATUS_BADARG
);
3032 if (duidtype
== DHCPV6_DUID_EN
) {
3035 en
.den_dutype
= htons(duidtype
);
3036 DHCPV6_SET_ENTNUM(&en
, subtype
);
3038 cidlen
= sizeof (en
) + hexlen
;
3039 if (cidlen
> sizeof (cid
->dc_id
))
3040 return (DLADM_STATUS_TOOSMALL
);
3042 bcopy(&en
, cid
->dc_id
, sizeof (en
));
3043 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (en
),
3046 uint16_t dutype
= htons(duidtype
);
3048 cidlen
= sizeof (dutype
) + hexlen
;
3049 if (cidlen
> sizeof (cid
->dc_id
))
3050 return (DLADM_STATUS_TOOSMALL
);
3052 bcopy(&dutype
, cid
->dc_id
, sizeof (dutype
));
3053 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (dutype
),
3059 cid
->dc_form
= CIDFORM_TYPED
;
3060 } else if (strncasecmp("0x", ptr
, 2) == 0 && ptr
[2] != '\0') {
3062 hexlen
= sizeof (tmp_buf
);
3063 if (hexascii_to_octet(ptr
, strlen(ptr
), tmp_buf
,
3065 return (DLADM_STATUS_BADARG
);
3068 if (cidlen
> sizeof (cid
->dc_id
))
3069 return (DLADM_STATUS_TOOSMALL
);
3071 bcopy(tmp_buf
, cid
->dc_id
, cidlen
);
3072 cid
->dc_form
= CIDFORM_HEX
;
3074 cidlen
= strlen(ptr
);
3075 if (cidlen
> sizeof (cid
->dc_id
))
3076 return (DLADM_STATUS_TOOSMALL
);
3078 bcopy(ptr
, cid
->dc_id
, cidlen
);
3079 cid
->dc_form
= CIDFORM_STR
;
3081 cid
->dc_len
= cidlen
;
3082 return (DLADM_STATUS_OK
);
3085 static dladm_status_t
3086 get_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3087 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3088 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
3090 mac_resource_props_t mrp
;
3092 dladm_status_t status
;
3095 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
3096 perm_flags
, &mrp
, sizeof (mrp
));
3097 if (status
!= DLADM_STATUS_OK
)
3100 p
= &mrp
.mrp_protect
;
3101 if (p
->mp_cidcnt
== 0) {
3103 return (DLADM_STATUS_OK
);
3105 if (p
->mp_cidcnt
> *val_cnt
)
3106 return (DLADM_STATUS_BADVALCNT
);
3108 for (i
= 0; i
< p
->mp_cidcnt
; i
++) {
3109 mac_dhcpcid_t
*cid
= &p
->mp_cids
[i
];
3111 dladm_cid2str(cid
, prop_val
[i
]);
3113 *val_cnt
= p
->mp_cidcnt
;
3114 return (DLADM_STATUS_OK
);
3118 extract_allowedcids(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
3120 mac_resource_props_t
*mrp
= arg
;
3121 mac_protect_t
*p
= &mrp
->mrp_protect
;
3124 if (vdp
->vd_val
== 0) {
3127 for (i
= 0; i
< cnt
; i
++) {
3128 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_cids
[i
],
3129 sizeof (mac_dhcpcid_t
));
3133 mrp
->mrp_mask
|= MRP_PROTECT
;
3134 return (DLADM_STATUS_OK
);
3137 static dladm_status_t
3138 check_allowedcids(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
3139 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
3140 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
3142 dladm_status_t status
;
3145 uint_t val_cnt
= *val_cntp
;
3146 val_desc_t
*vdp
= *vdpp
;
3148 if (val_cnt
> MPT_MAXCID
)
3149 return (DLADM_STATUS_BADVALCNT
);
3151 for (i
= 0; i
< val_cnt
; i
++) {
3152 if ((cid
= calloc(1, sizeof (mac_dhcpcid_t
))) == NULL
) {
3153 status
= DLADM_STATUS_NOMEM
;
3156 vdp
[i
].vd_val
= (uintptr_t)cid
;
3158 status
= dladm_str2cid(prop_val
[i
], cid
);
3159 if (status
!= DLADM_STATUS_OK
)
3162 return (DLADM_STATUS_OK
);
3165 for (i
= 0; i
< val_cnt
; i
++) {
3166 free((void *)vdp
[i
].vd_val
);
3172 static dladm_status_t
3173 get_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
3174 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3175 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
3177 mac_secondary_addr_t sa
;
3178 dladm_status_t status
;
3181 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3182 perm_flags
, &sa
, sizeof (sa
));
3183 if (status
!= DLADM_STATUS_OK
)
3186 if (sa
.ms_addrcnt
> *val_cnt
)
3187 return (DLADM_STATUS_BADVALCNT
);
3189 for (i
= 0; i
< sa
.ms_addrcnt
; i
++) {
3190 if (dladm_aggr_macaddr2str(
3191 (const unsigned char *)&sa
.ms_addrs
[i
], prop_val
[i
]) ==
3194 return (DLADM_STATUS_NOMEM
);
3197 *val_cnt
= sa
.ms_addrcnt
;
3198 return (DLADM_STATUS_OK
);
3201 static dladm_status_t
3202 check_secondary_macs(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
3203 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
3204 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
3206 dladm_status_t status
;
3210 uint_t val_cnt
= *val_cntp
;
3211 val_desc_t
*vdp
= *vdpp
;
3213 if (val_cnt
>= MPT_MAXMACADDR
)
3214 return (DLADM_STATUS_BADVALCNT
);
3216 for (i
= 0; i
< val_cnt
; i
++) {
3217 addr
= _link_aton(prop_val
[i
], (int *)&len
);
3219 if (len
== (uint_t
)-1)
3220 status
= DLADM_STATUS_MACADDRINVAL
;
3222 status
= DLADM_STATUS_NOMEM
;
3226 vdp
[i
].vd_val
= (uintptr_t)addr
;
3228 return (DLADM_STATUS_OK
);
3231 for (i
= 0; i
< val_cnt
; i
++) {
3232 free((void *)vdp
[i
].vd_val
);
3238 static dladm_status_t
3239 set_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pd __unused
,
3240 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
3241 uint_t flags __unused
, datalink_media_t media __unused
)
3243 dladm_status_t status
;
3244 dld_ioc_macprop_t
*dip
;
3246 mac_secondary_addr_t msa
;
3248 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "secondary-macs", 0,
3253 if (vdp
->vd_val
== 0) {
3254 val_cnt
= (uint_t
)-1;
3256 for (i
= 0; i
< val_cnt
; i
++) {
3257 bcopy((void *)vdp
[i
].vd_val
, msa
.ms_addrs
[i
],
3261 msa
.ms_addrcnt
= val_cnt
;
3262 bcopy(&msa
, dip
->pr_val
, dip
->pr_valsize
);
3264 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3270 static dladm_status_t
3271 get_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3272 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
3273 uint_t flags
, uint_t
*perm_flags
)
3275 struct dlautopush dlap
;
3278 dladm_status_t status
;
3280 if (flags
& DLD_PROP_DEFAULT
)
3281 return (DLADM_STATUS_NOTDEFINED
);
3283 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3284 perm_flags
, &dlap
, sizeof (dlap
));
3285 if (status
!= DLADM_STATUS_OK
)
3288 if (dlap
.dap_npush
== 0) {
3290 return (DLADM_STATUS_OK
);
3292 for (i
= 0, len
= 0; i
< dlap
.dap_npush
; i
++) {
3294 (void) snprintf(*prop_val
+ len
,
3295 DLADM_PROP_VAL_MAX
- len
, "%c", AP_DELIMITER
);
3298 (void) snprintf(*prop_val
+ len
, DLADM_PROP_VAL_MAX
- len
,
3299 "%s", dlap
.dap_aplist
[i
]);
3300 len
+= strlen(dlap
.dap_aplist
[i
]);
3301 if (dlap
.dap_anchor
- 1 == i
) {
3302 (void) snprintf(*prop_val
+ len
,
3303 DLADM_PROP_VAL_MAX
- len
, "%c%s", AP_DELIMITER
,
3305 len
+= (strlen(AP_ANCHOR
) + 1);
3309 return (DLADM_STATUS_OK
);
3313 * Add the specified module to the dlautopush structure; returns a
3314 * DLADM_STATUS_* code.
3317 i_dladm_add_ap_module(const char *module
, struct dlautopush
*dlap
)
3319 if ((strlen(module
) == 0) || (strlen(module
) > FMNAMESZ
))
3320 return (DLADM_STATUS_BADVAL
);
3322 if (strncasecmp(module
, AP_ANCHOR
, strlen(AP_ANCHOR
)) == 0) {
3324 * We don't allow multiple anchors, and the anchor must
3325 * be after at least one module.
3327 if (dlap
->dap_anchor
!= 0)
3328 return (DLADM_STATUS_BADVAL
);
3329 if (dlap
->dap_npush
== 0)
3330 return (DLADM_STATUS_BADVAL
);
3332 dlap
->dap_anchor
= dlap
->dap_npush
;
3333 return (DLADM_STATUS_OK
);
3335 if (dlap
->dap_npush
>= MAXAPUSH
)
3336 return (DLADM_STATUS_BADVALCNT
);
3338 (void) strlcpy(dlap
->dap_aplist
[dlap
->dap_npush
++], module
,
3341 return (DLADM_STATUS_OK
);
3345 * Currently, both '.' and ' '(space) can be used as the delimiters between
3346 * autopush modules. The former is used in dladm set-linkprop, and the
3347 * latter is used in the autopush(8) file.
3349 static dladm_status_t
3350 check_autopush(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
3351 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
3352 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
3355 struct dlautopush
*dlap
;
3356 dladm_status_t status
;
3357 char val
[DLADM_PROP_VAL_MAX
];
3359 uint_t val_cnt
= *val_cntp
;
3360 val_desc_t
*vdp
= *vdpp
;
3363 return (DLADM_STATUS_BADVALCNT
);
3365 if (prop_val
!= NULL
) {
3366 dlap
= malloc(sizeof (struct dlautopush
));
3368 return (DLADM_STATUS_NOMEM
);
3370 (void) memset(dlap
, 0, sizeof (struct dlautopush
));
3371 (void) snprintf(delimiters
, 4, " %c\n", AP_DELIMITER
);
3372 bcopy(*prop_val
, val
, DLADM_PROP_VAL_MAX
);
3373 module
= strtok(val
, delimiters
);
3374 while (module
!= NULL
) {
3375 status
= i_dladm_add_ap_module(module
, dlap
);
3376 if (status
!= DLADM_STATUS_OK
)
3378 module
= strtok(NULL
, delimiters
);
3381 vdp
->vd_val
= (uintptr_t)dlap
;
3385 return (DLADM_STATUS_OK
);
3388 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3390 static dladm_status_t
3391 get_rate_common(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3392 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
, uint_t id
,
3397 dladm_status_t status
= DLADM_STATUS_OK
;
3399 wrp
= malloc(WLDP_BUFSIZE
);
3401 return (DLADM_STATUS_NOMEM
);
3403 status
= i_dladm_wlan_param(handle
, linkid
, wrp
, id
, WLDP_BUFSIZE
,
3405 if (status
!= DLADM_STATUS_OK
)
3408 if (wrp
->wl_rates_num
> *val_cnt
) {
3409 status
= DLADM_STATUS_TOOSMALL
;
3413 if (wrp
->wl_rates_rates
[0] == 0) {
3414 prop_val
[0][0] = '\0';
3419 for (i
= 0; i
< wrp
->wl_rates_num
; i
++) {
3420 (void) snprintf(prop_val
[i
], DLADM_STRSIZE
, "%.*f",
3421 wrp
->wl_rates_rates
[i
] % 2,
3422 (float)wrp
->wl_rates_rates
[i
] / 2);
3424 *val_cnt
= wrp
->wl_rates_num
;
3425 *perm_flags
= MAC_PROP_PERM_RW
;
3432 static dladm_status_t
3433 get_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3434 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3435 uint_t flags
, uint_t
*perm_flags
)
3437 if (media
!= DL_WIFI
) {
3438 return (get_speed(handle
, pdp
, linkid
, prop_val
,
3439 val_cnt
, media
, flags
, perm_flags
));
3442 return (get_rate_common(handle
, pdp
, linkid
, prop_val
, val_cnt
,
3443 MAC_PROP_WL_DESIRED_RATES
, perm_flags
));
3446 static dladm_status_t
3447 get_rate_mod(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3448 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3449 uint_t flags __unused
, uint_t
*perm_flags
)
3454 * Speed for ethernet links is unbounded. E.g., 802.11b
3455 * links can have a speed of 5.5 Gbps.
3457 return (DLADM_STATUS_NOTSUP
);
3460 return (get_rate_common(handle
, pdp
, linkid
, prop_val
,
3461 val_cnt
, MAC_PROP_WL_SUPPORTED_RATES
, perm_flags
));
3463 return (DLADM_STATUS_BADARG
);
3467 static dladm_status_t
3468 set_wlan_rate(dladm_handle_t handle
, datalink_id_t linkid
,
3469 dladm_wlan_rates_t
*rates
)
3474 dladm_status_t status
= DLADM_STATUS_OK
;
3476 wrp
= malloc(WLDP_BUFSIZE
);
3478 return (DLADM_STATUS_NOMEM
);
3480 bzero(wrp
, WLDP_BUFSIZE
);
3481 for (i
= 0; i
< rates
->wr_cnt
; i
++)
3482 wrp
->wl_rates_rates
[i
] = rates
->wr_rates
[i
];
3483 wrp
->wl_rates_num
= rates
->wr_cnt
;
3485 len
= offsetof(wl_rates_t
, wl_rates_rates
) +
3486 (rates
->wr_cnt
* sizeof (char)) + WIFI_BUF_OFFSET
;
3487 status
= i_dladm_wlan_param(handle
, linkid
, wrp
,
3488 MAC_PROP_WL_DESIRED_RATES
, len
, B_TRUE
);
3494 static dladm_status_t
3495 set_rate(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3496 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
3497 uint_t flags __unused
, datalink_media_t media
)
3499 dladm_wlan_rates_t rates
;
3500 dladm_status_t status
;
3503 * can currently set rate on WIFI links only.
3505 if (media
!= DL_WIFI
)
3506 return (DLADM_STATUS_PROPRDONLY
);
3509 return (DLADM_STATUS_BADVALCNT
);
3512 rates
.wr_rates
[0] = vdp
[0].vd_val
;
3514 status
= set_wlan_rate(handle
, linkid
, &rates
);
3519 static dladm_status_t
3520 check_rate(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3521 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
3522 uint_t flags __unused
,
3523 val_desc_t
**vdpp
, datalink_media_t media
)
3526 uint_t modval_cnt
= MAX_SUPPORT_RATES
;
3527 char *buf
, **modval
;
3528 dladm_status_t status
;
3530 uint_t val_cnt
= *val_cntp
;
3531 val_desc_t
*vdp
= *vdpp
;
3534 return (DLADM_STATUS_BADVALCNT
);
3536 buf
= malloc((sizeof (char *) + DLADM_STRSIZE
) *
3539 status
= DLADM_STATUS_NOMEM
;
3543 modval
= (char **)(void *)buf
;
3544 for (i
= 0; i
< MAX_SUPPORT_RATES
; i
++) {
3545 modval
[i
] = buf
+ sizeof (char *) * MAX_SUPPORT_RATES
+
3549 status
= get_rate_mod(handle
, NULL
, linkid
, modval
, &modval_cnt
,
3550 media
, 0, &perm_flags
);
3551 if (status
!= DLADM_STATUS_OK
)
3554 for (i
= 0; i
< modval_cnt
; i
++) {
3555 if (strcasecmp(*prop_val
, modval
[i
]) == 0) {
3556 vdp
->vd_val
= (uintptr_t)(uint_t
)
3557 (atof(*prop_val
) * 2);
3558 status
= DLADM_STATUS_OK
;
3562 if (i
== modval_cnt
)
3563 status
= DLADM_STATUS_BADVAL
;
3569 static dladm_status_t
3570 get_phyconf(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
3573 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_PHY_CONFIG
,
3577 static dladm_status_t
3578 get_channel(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3579 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3580 datalink_media_t media __unused
, uint_t flags __unused
, uint_t
*perm_flags
)
3583 char buf
[WLDP_BUFSIZE
];
3584 dladm_status_t status
;
3585 wl_phy_conf_t wl_phy_conf
;
3587 if ((status
= get_phyconf(handle
, linkid
, buf
, sizeof (buf
)))
3591 (void) memcpy(&wl_phy_conf
, buf
, sizeof (wl_phy_conf
));
3592 if (!i_dladm_wlan_convert_chan(&wl_phy_conf
, &channel
))
3593 return (DLADM_STATUS_NOTFOUND
);
3595 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%u", channel
);
3597 *perm_flags
= MAC_PROP_PERM_READ
;
3598 return (DLADM_STATUS_OK
);
3601 static dladm_status_t
3602 get_powermode(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3603 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3604 datalink_media_t media __unused
, uint_t flags __unused
, uint_t
*perm_flags
)
3608 char buf
[WLDP_BUFSIZE
];
3609 dladm_status_t status
;
3611 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3612 MAC_PROP_WL_POWER_MODE
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3615 (void) memcpy(&mode
, buf
, sizeof (mode
));
3616 switch (mode
.wl_ps_mode
) {
3627 return (DLADM_STATUS_NOTFOUND
);
3629 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3631 *perm_flags
= MAC_PROP_PERM_RW
;
3632 return (DLADM_STATUS_OK
);
3635 static dladm_status_t
3636 set_powermode(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3637 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
3638 uint_t flags __unused
, datalink_media_t media __unused
)
3640 dladm_wlan_powermode_t powermode
= vdp
->vd_val
;
3641 wl_ps_mode_t ps_mode
;
3644 return (DLADM_STATUS_BADVALCNT
);
3646 (void) memset(&ps_mode
, 0xff, sizeof (ps_mode
));
3648 switch (powermode
) {
3649 case DLADM_WLAN_PM_OFF
:
3650 ps_mode
.wl_ps_mode
= WL_PM_AM
;
3652 case DLADM_WLAN_PM_MAX
:
3653 ps_mode
.wl_ps_mode
= WL_PM_MPS
;
3655 case DLADM_WLAN_PM_FAST
:
3656 ps_mode
.wl_ps_mode
= WL_PM_FAST
;
3659 return (DLADM_STATUS_NOTSUP
);
3661 return (i_dladm_wlan_param(handle
, linkid
, &ps_mode
,
3662 MAC_PROP_WL_POWER_MODE
, sizeof (ps_mode
), B_TRUE
));
3665 static dladm_status_t
3666 get_radio(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3667 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3668 datalink_media_t media __unused
, uint_t flags __unused
, uint_t
*perm_flags
)
3672 char buf
[WLDP_BUFSIZE
];
3673 dladm_status_t status
;
3675 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3676 MAC_PROP_WL_RADIO
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3679 (void) memcpy(&radio
, buf
, sizeof (radio
));
3688 return (DLADM_STATUS_NOTFOUND
);
3690 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3692 *perm_flags
= MAC_PROP_PERM_RW
;
3693 return (DLADM_STATUS_OK
);
3696 static dladm_status_t
3697 set_radio(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
3698 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
3699 uint_t flags __unused
, datalink_media_t media __unused
)
3701 dladm_wlan_radio_t radio
= vdp
->vd_val
;
3705 return (DLADM_STATUS_BADVALCNT
);
3708 case DLADM_WLAN_RADIO_ON
:
3711 case DLADM_WLAN_RADIO_OFF
:
3715 return (DLADM_STATUS_NOTSUP
);
3717 return (i_dladm_wlan_param(handle
, linkid
, &r
, MAC_PROP_WL_RADIO
,
3718 sizeof (r
), B_TRUE
));
3721 static dladm_status_t
3722 check_hoplimit(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
3723 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
3724 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
3728 uint_t val_cnt
= *val_cntp
;
3729 val_desc_t
*vdp
= *vdpp
;
3732 return (DLADM_STATUS_BADVALCNT
);
3735 hlim
= strtol(*prop_val
, &ep
, 10);
3736 if (errno
!= 0 || ep
== *prop_val
|| hlim
< 1 ||
3737 hlim
> (int32_t)UINT8_MAX
)
3738 return (DLADM_STATUS_BADVAL
);
3740 return (DLADM_STATUS_OK
);
3743 static dladm_status_t
3744 check_encaplim(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
3745 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
3746 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media
)
3750 uint_t val_cnt
= *val_cntp
;
3751 val_desc_t
*vdp
= *vdpp
;
3753 if (media
!= DL_IPV6
)
3754 return (DLADM_STATUS_BADARG
);
3757 return (DLADM_STATUS_BADVALCNT
);
3760 elim
= strtol(*prop_val
, &ep
, 10);
3761 if (errno
!= 0 || ep
== *prop_val
|| elim
< 0 ||
3762 elim
> (int32_t)UINT8_MAX
)
3763 return (DLADM_STATUS_BADVAL
);
3765 return (DLADM_STATUS_OK
);
3768 static dladm_status_t
3769 i_dladm_set_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3770 const char *prop_name
, char **prop_val
, uint_t val_cnt
)
3772 char buf
[MAXLINELEN
];
3775 dladm_status_t status
;
3777 status
= dladm_open_conf(handle
, linkid
, &conf
);
3778 if (status
!= DLADM_STATUS_OK
)
3785 status
= dladm_unset_conf_field(handle
, conf
, prop_name
);
3786 if (status
== DLADM_STATUS_OK
)
3787 status
= dladm_write_conf(handle
, conf
);
3792 for (i
= 0; i
< val_cnt
; i
++) {
3793 (void) strlcat(buf
, prop_val
[i
], MAXLINELEN
);
3794 if (i
!= val_cnt
- 1)
3795 (void) strlcat(buf
, ",", MAXLINELEN
);
3798 status
= dladm_set_conf_field(handle
, conf
, prop_name
, DLADM_TYPE_STR
,
3800 if (status
== DLADM_STATUS_OK
)
3801 status
= dladm_write_conf(handle
, conf
);
3804 dladm_destroy_conf(handle
, conf
);
3808 static dladm_status_t
3809 i_dladm_get_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3810 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
3812 char buf
[MAXLINELEN
], *str
;
3815 dladm_status_t status
;
3817 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3818 if (status
!= DLADM_STATUS_OK
)
3821 status
= dladm_get_conf_field(handle
, conf
, prop_name
, buf
, MAXLINELEN
);
3822 if (status
!= DLADM_STATUS_OK
)
3825 str
= strtok(buf
, ",");
3826 while (str
!= NULL
) {
3827 if (cnt
== *val_cntp
) {
3828 status
= DLADM_STATUS_TOOSMALL
;
3831 (void) strlcpy(prop_val
[cnt
++], str
, DLADM_PROP_VAL_MAX
);
3832 str
= strtok(NULL
, ",");
3838 dladm_destroy_conf(handle
, conf
);
3843 * Walk persistent private link properties of a link.
3845 static dladm_status_t
3846 i_dladm_walk_linkprop_priv_db(dladm_handle_t handle
, datalink_id_t linkid
,
3847 void *arg
, int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
3849 dladm_status_t status
;
3851 char last_attr
[MAXLINKATTRLEN
];
3852 char attr
[MAXLINKATTRLEN
];
3853 char attrval
[MAXLINKATTRVALLEN
];
3856 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
3857 return (DLADM_STATUS_BADARG
);
3859 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3860 if (status
!= DLADM_STATUS_OK
)
3863 last_attr
[0] = '\0';
3864 while ((status
= dladm_getnext_conf_linkprop(handle
, conf
, last_attr
,
3865 attr
, attrval
, MAXLINKATTRVALLEN
, &attrsz
)) == DLADM_STATUS_OK
) {
3866 if (attr
[0] == '_') {
3867 if (func(handle
, linkid
, attr
, arg
) ==
3868 DLADM_WALK_TERMINATE
)
3871 (void) strlcpy(last_attr
, attr
, MAXLINKATTRLEN
);
3874 dladm_destroy_conf(handle
, conf
);
3875 return (DLADM_STATUS_OK
);
3878 static link_attr_t
*
3879 dladm_name2prop(const char *prop_name
)
3883 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3884 if (strcmp(p
->pp_name
, prop_name
) == 0)
3890 static link_attr_t
*
3891 dladm_id2prop(mac_prop_id_t propid
)
3895 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3896 if (p
->pp_id
== propid
)
3902 static dld_ioc_macprop_t
*
3903 i_dladm_buf_alloc_impl(size_t valsize
, datalink_id_t linkid
,
3904 const char *prop_name
, mac_prop_id_t propid
, uint_t flags
,
3905 dladm_status_t
*status
)
3908 dld_ioc_macprop_t
*dip
;
3910 *status
= DLADM_STATUS_OK
;
3911 dsize
= MAC_PROP_BUFSIZE(valsize
);
3912 dip
= malloc(dsize
);
3914 *status
= DLADM_STATUS_NOMEM
;
3918 dip
->pr_valsize
= valsize
;
3919 (void) strlcpy(dip
->pr_name
, prop_name
, sizeof (dip
->pr_name
));
3920 dip
->pr_linkid
= linkid
;
3921 dip
->pr_num
= propid
;
3922 dip
->pr_flags
= flags
;
3926 static dld_ioc_macprop_t
*
3927 i_dladm_buf_alloc_by_name(size_t valsize
, datalink_id_t linkid
,
3928 const char *prop_name
, uint_t flags
, dladm_status_t
*status
)
3932 p
= dladm_name2prop(prop_name
);
3933 valsize
= MAX(p
->pp_valsize
, valsize
);
3934 return (i_dladm_buf_alloc_impl(valsize
, linkid
, prop_name
, p
->pp_id
,
3938 static dld_ioc_macprop_t
*
3939 i_dladm_buf_alloc_by_id(size_t valsize
, datalink_id_t linkid
,
3940 mac_prop_id_t propid
, uint_t flags
, dladm_status_t
*status
)
3944 p
= dladm_id2prop(propid
);
3945 valsize
= MAX(p
->pp_valsize
, valsize
);
3946 return (i_dladm_buf_alloc_impl(valsize
, linkid
, p
->pp_name
, propid
,
3950 static dladm_status_t
3951 set_public_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
3952 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt __unused
,
3953 uint_t flags __unused
, datalink_media_t media __unused
)
3955 dld_ioc_macprop_t
*dip
;
3956 dladm_status_t status
= DLADM_STATUS_OK
;
3962 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
, 0, &status
);
3966 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
3967 val
= (void *)vdp
->vd_val
;
3970 * Currently all 1/2/4-byte size properties are byte/word/int.
3971 * No need (yet) to distinguish these from arrays of same size.
3973 switch (dip
->pr_valsize
) {
3993 (void) memcpy(dip
->pr_val
, val
, dip
->pr_valsize
);
3995 dip
->pr_valsize
= 0;
3997 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4003 static dladm_status_t
4004 set_public_bitprop(dladm_handle_t handle
, prop_desc_t
*pdp
,
4005 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
4006 datalink_media_t media
)
4009 val_desc_t vd
= { 0 };
4011 if ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0)
4012 return (DLADM_STATUS_BADARG
);
4014 for (i
= 0; i
< val_cnt
; i
++) {
4015 for (j
= 0; j
< pdp
->pd_noptval
; j
++) {
4016 if (strcasecmp(vdp
[i
].vd_name
,
4017 pdp
->pd_optval
[j
].vd_name
) == 0) {
4018 vd
.vd_val
|= pdp
->pd_optval
[j
].vd_val
;
4025 return (DLADM_STATUS_BADARG
);
4027 return (set_public_prop(handle
, pdp
, linkid
, &vd
, 1, flags
, media
));
4031 i_dladm_macprop(dladm_handle_t handle
, void *dip
, boolean_t set
)
4033 dladm_status_t status
= DLADM_STATUS_OK
;
4035 if (ioctl(dladm_dld_fd(handle
),
4036 (set
? DLDIOC_SETMACPROP
: DLDIOC_GETMACPROP
), dip
))
4037 status
= dladm_errno2status(errno
);
4042 static dladm_status_t
4043 i_dladm_get_public_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4044 char *prop_name
, uint_t flags
, uint_t
*perm_flags
, void *arg
, size_t size
)
4046 dld_ioc_macprop_t
*dip
;
4047 dladm_status_t status
;
4049 dip
= i_dladm_buf_alloc_by_name(0, linkid
, prop_name
, flags
, &status
);
4051 return (DLADM_STATUS_NOMEM
);
4053 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4054 if (status
!= DLADM_STATUS_OK
) {
4059 if (perm_flags
!= NULL
)
4060 *perm_flags
= dip
->pr_perm_flags
;
4063 (void) memcpy(arg
, dip
->pr_val
, size
);
4065 return (DLADM_STATUS_OK
);
4068 static dladm_status_t
4069 check_uint32(dladm_handle_t handle __unused
, prop_desc_t
*pdp __unused
,
4070 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
4071 uint_t flags __unused
, val_desc_t
**vp
, datalink_media_t media __unused
)
4073 uint_t val_cnt
= *val_cntp
;
4074 val_desc_t
*v
= *vp
;
4077 return (DLADM_STATUS_BADVAL
);
4078 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
4079 return (DLADM_STATUS_OK
);
4082 static dladm_status_t
4083 get_duplex(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
4084 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4085 datalink_media_t media __unused
, uint_t flags __unused
,
4086 uint_t
*perm_flags __unused
)
4088 link_duplex_t link_duplex
;
4089 dladm_status_t status
;
4091 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "link_duplex",
4092 KSTAT_DATA_UINT32
, &link_duplex
)) != 0)
4095 switch (link_duplex
) {
4096 case LINK_DUPLEX_FULL
:
4097 (void) strcpy(*prop_val
, "full");
4099 case LINK_DUPLEX_HALF
:
4100 (void) strcpy(*prop_val
, "half");
4103 (void) strcpy(*prop_val
, "unknown");
4107 return (DLADM_STATUS_OK
);
4110 static dladm_status_t
4111 get_speed(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
4112 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4113 datalink_media_t media __unused
, uint_t flags __unused
,
4116 uint64_t ifspeed
= 0;
4117 dladm_status_t status
;
4119 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "ifspeed",
4120 KSTAT_DATA_UINT64
, &ifspeed
)) != 0)
4123 if ((ifspeed
% 1000000) != 0) {
4124 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
4125 "%llf", ifspeed
/ (float)1000000); /* Mbps */
4127 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
4128 "%llu", ifspeed
/ 1000000); /* Mbps */
4131 *perm_flags
= MAC_PROP_PERM_READ
;
4132 return (DLADM_STATUS_OK
);
4135 static dladm_status_t
4136 get_link_state(dladm_handle_t handle
, prop_desc_t
*pdp __unused
,
4137 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4138 datalink_media_t media __unused
, uint_t flags __unused
, uint_t
*perm_flags
)
4140 link_state_t link_state
;
4141 dladm_status_t status
;
4143 status
= dladm_get_state(handle
, linkid
, &link_state
);
4144 if (status
!= DLADM_STATUS_OK
)
4147 switch (link_state
) {
4149 (void) strcpy(*prop_val
, "up");
4151 case LINK_STATE_DOWN
:
4152 (void) strcpy(*prop_val
, "down");
4155 (void) strcpy(*prop_val
, "unknown");
4159 *perm_flags
= MAC_PROP_PERM_READ
;
4160 return (DLADM_STATUS_OK
);
4163 static dladm_status_t
4164 get_binary(dladm_handle_t handle
, prop_desc_t
*pdp
,
4165 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4166 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4168 dladm_status_t status
;
4171 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4172 perm_flags
, &v
, sizeof (v
));
4173 if (status
!= DLADM_STATUS_OK
)
4176 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%d", (uint_t
)(v
> 0));
4178 return (DLADM_STATUS_OK
);
4181 static dladm_status_t
4182 get_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
4183 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4184 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4186 dladm_status_t status
;
4189 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4190 perm_flags
, &v
, sizeof (v
));
4191 if (status
!= DLADM_STATUS_OK
)
4194 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", v
);
4196 return (DLADM_STATUS_OK
);
4199 static dladm_status_t
4200 get_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
4201 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4202 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags __unused
)
4204 dld_ioc_macprop_t
*dip
;
4205 dladm_status_t status
= DLADM_STATUS_OK
;
4208 mac_propval_range_t
*rangep
;
4211 * As caller we don't know number of value ranges, the driver
4212 * supports. To begin with we assume that number to be 1. If the
4213 * buffer size is insufficient, driver returns back with the
4214 * actual count of value ranges. See mac.h for more details.
4216 sz
= sizeof (mac_propval_range_t
);
4219 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
4223 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
4224 rangep
->mpr_count
= rcount
;
4226 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4227 if (status
!= DLADM_STATUS_OK
) {
4228 if (status
== DLADM_STATUS_TOOSMALL
) {
4231 if ((err
= i_dladm_range_size(rangep
, &sz
, &rcount
))
4236 status
= dladm_errno2status(err
);
4243 if (rangep
->mpr_count
== 0) {
4245 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "--");
4249 switch (rangep
->mpr_type
) {
4250 case MAC_PROPVAL_UINT32
: {
4251 mac_propval_uint32_range_t
*ur
;
4252 uint_t count
= rangep
->mpr_count
, i
;
4254 ur
= &rangep
->mpr_range_uint32
[0];
4256 for (i
= 0; i
< count
; i
++, ur
++) {
4257 if (ur
->mpur_min
== ur
->mpur_max
) {
4258 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4259 "%ld", ur
->mpur_min
);
4261 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4262 "%ld-%ld", ur
->mpur_min
, ur
->mpur_max
);
4269 status
= DLADM_STATUS_BADARG
;
4277 static dladm_status_t
4278 get_tagmode(dladm_handle_t handle
, prop_desc_t
*pdp
,
4279 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4280 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4282 link_tagmode_t mode
;
4283 dladm_status_t status
;
4285 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4286 perm_flags
, &mode
, sizeof (mode
));
4287 if (status
!= DLADM_STATUS_OK
)
4291 case LINK_TAGMODE_NORMAL
:
4292 (void) strlcpy(*prop_val
, "normal", DLADM_PROP_VAL_MAX
);
4294 case LINK_TAGMODE_VLANONLY
:
4295 (void) strlcpy(*prop_val
, "vlanonly", DLADM_PROP_VAL_MAX
);
4298 (void) strlcpy(*prop_val
, "unknown", DLADM_PROP_VAL_MAX
);
4301 return (DLADM_STATUS_OK
);
4304 static dladm_status_t
4305 get_flowctl(dladm_handle_t handle
, prop_desc_t
*pdp
,
4306 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4307 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4310 dladm_status_t status
;
4312 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4313 perm_flags
, &v
, sizeof (v
));
4314 if (status
!= DLADM_STATUS_OK
)
4318 case LINK_FLOWCTRL_NONE
:
4319 (void) sprintf(*prop_val
, "no");
4321 case LINK_FLOWCTRL_RX
:
4322 (void) sprintf(*prop_val
, "rx");
4324 case LINK_FLOWCTRL_TX
:
4325 (void) sprintf(*prop_val
, "tx");
4327 case LINK_FLOWCTRL_BI
:
4328 (void) sprintf(*prop_val
, "bi");
4332 return (DLADM_STATUS_OK
);
4335 static dladm_status_t
4336 get_bits(dladm_handle_t handle
, prop_desc_t
*pdp
,
4337 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4338 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4341 dladm_status_t status
;
4344 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4345 perm_flags
, &v
, sizeof (v
));
4346 if (status
!= DLADM_STATUS_OK
)
4350 for (i
= 0; cnt
< *val_cnt
&& i
< pdp
->pd_noptval
; i
++) {
4351 if ((v
& pdp
->pd_optval
[i
].vd_val
) != 0) {
4352 (void) snprintf(prop_val
[cnt
++], DLADM_STRSIZE
,
4353 pdp
->pd_optval
[i
].vd_name
);
4357 if (i
< pdp
->pd_noptval
)
4358 return (DLADM_STATUS_BADVALCNT
);
4361 return (DLADM_STATUS_OK
);
4364 static dladm_status_t
4365 i_dladm_set_private_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4366 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
4371 dld_ioc_macprop_t
*dip
= NULL
;
4374 dladm_status_t status
= DLADM_STATUS_OK
;
4376 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4377 (prop_val
!= NULL
&& val_cnt
== 0))
4378 return (DLADM_STATUS_BADARG
);
4379 p
= dladm_name2prop(prop_name
);
4380 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4381 return (DLADM_STATUS_BADARG
);
4383 if (!(flags
& DLADM_OPT_ACTIVE
))
4384 return (DLADM_STATUS_OK
);
4387 * private properties: all parsing is done in the kernel.
4388 * allocate a enough space for each property + its separator (',').
4390 for (i
= 0; i
< val_cnt
; i
++) {
4391 bufsize
+= strlen(prop_val
[i
]) + 1;
4394 if (prop_val
== NULL
) {
4396 * getting default value. so use more buffer space.
4398 bufsize
+= DLADM_PROP_BUF_CHUNK
;
4401 dip
= i_dladm_buf_alloc_by_name(bufsize
+ 1, linkid
, prop_name
,
4402 (prop_val
!= NULL
? 0 : DLD_PROP_DEFAULT
), &status
);
4406 dp
= (uchar_t
*)dip
->pr_val
;
4409 if (prop_val
== NULL
) {
4410 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4413 for (i
= 0; i
< val_cnt
; i
++) {
4416 plen
= strlen(prop_val
[i
]);
4417 bcopy(prop_val
[i
], dp
, plen
);
4420 * add a "," separator and update dp.
4422 if (i
!= (val_cnt
- 1))
4427 if (status
== DLADM_STATUS_OK
)
4428 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4434 static dladm_status_t
4435 i_dladm_get_priv_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4436 const char *prop_name
, char **prop_val
, uint_t
*val_cnt
,
4437 dladm_prop_type_t type
, uint_t dld_flags
)
4439 dladm_status_t status
= DLADM_STATUS_OK
;
4440 dld_ioc_macprop_t
*dip
= NULL
;
4443 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4444 (prop_val
!= NULL
&& val_cnt
== 0))
4445 return (DLADM_STATUS_BADARG
);
4447 p
= dladm_name2prop(prop_name
);
4448 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4449 return (DLADM_STATUS_BADARG
);
4452 * private properties: all parsing is done in the kernel.
4454 dip
= i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK
, linkid
, prop_name
,
4455 dld_flags
, &status
);
4459 if ((status
= i_dladm_macprop(handle
, dip
, B_FALSE
)) ==
4461 if (type
== DLADM_PROP_VAL_PERM
) {
4462 (void) dladm_perm2str(dip
->pr_perm_flags
, *prop_val
);
4463 } else if (type
== DLADM_PROP_VAL_MODIFIABLE
) {
4464 *prop_val
[0] = '\0';
4466 (void) strncpy(*prop_val
, dip
->pr_val
,
4467 DLADM_PROP_VAL_MAX
);
4470 } else if ((status
== DLADM_STATUS_NOTSUP
) &&
4471 (type
== DLADM_PROP_VAL_CURRENT
)) {
4472 status
= DLADM_STATUS_NOTFOUND
;
4479 static dladm_status_t
4480 i_dladm_getset_defval(dladm_handle_t handle
, prop_desc_t
*pdp
,
4481 datalink_id_t linkid
, datalink_media_t media
, uint_t flags
)
4483 dladm_status_t status
;
4484 char **prop_vals
= NULL
, *buf
;
4491 * Allocate buffer needed for prop_vals array. We can have at most
4492 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4493 * each entry has max size DLADM_PROP_VAL_MAX
4496 (sizeof (char *) + DLADM_PROP_VAL_MAX
) * DLADM_MAX_PROP_VALCNT
;
4497 buf
= malloc(bufsize
);
4498 prop_vals
= (char **)(void *)buf
;
4499 for (i
= 0; i
< DLADM_MAX_PROP_VALCNT
; i
++) {
4500 prop_vals
[i
] = buf
+
4501 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4502 i
* DLADM_PROP_VAL_MAX
;
4506 * For properties which have pdp->pd_defval.vd_name as a non-empty
4507 * string, the "" itself is used to reset the property (exceptions
4508 * are zone and autopush, which populate vdp->vd_val). So
4509 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4510 * down on the setprop using the global values in the table. For
4511 * other cases (vd_name is ""), doing reset-linkprop will cause
4512 * libdladm to do a getprop to find the default value and then do
4513 * a setprop to reset the value to default.
4515 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_vals
, &cnt
, media
,
4516 DLD_PROP_DEFAULT
, &perm_flags
);
4517 if (status
== DLADM_STATUS_OK
) {
4518 if (perm_flags
== MAC_PROP_PERM_RW
) {
4519 status
= i_dladm_set_single_prop(handle
, linkid
,
4520 pdp
->pd_class
, media
, pdp
, prop_vals
, cnt
, flags
);
4523 status
= DLADM_STATUS_NOTSUP
;
4529 static dladm_status_t
4530 get_stp(dladm_handle_t handle
, struct prop_desc
*pd
, datalink_id_t linkid
,
4531 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media __unused
,
4532 uint_t flags
, uint_t
*perm_flags
)
4534 const bridge_public_prop_t
*bpp
;
4535 dladm_status_t retv
;
4540 return (DLADM_STATUS_NOTSUP
);
4541 *perm_flags
= MAC_PROP_PERM_RW
;
4543 for (bpp
= bridge_prop
; bpp
->bpp_name
!= NULL
; bpp
++)
4544 if (strcmp(bpp
->bpp_name
, pd
->pd_name
) == 0)
4546 retv
= dladm_bridge_get_port_cfg(handle
, linkid
, bpp
->bpp_code
, &val
);
4547 /* If the daemon isn't running, then return the persistent value */
4548 if (retv
== DLADM_STATUS_NOTFOUND
) {
4549 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4550 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4551 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4552 DLADM_PROP_VAL_MAX
);
4553 return (DLADM_STATUS_OK
);
4555 if (retv
!= DLADM_STATUS_OK
) {
4556 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4559 if ((uintptr_t)val
== pd
->pd_defval
.vd_val
&&
4560 pd
->pd_defval
.vd_name
[0] != '\0') {
4561 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4562 DLADM_PROP_VAL_MAX
);
4563 return (DLADM_STATUS_OK
);
4565 for (i
= 0; i
< pd
->pd_noptval
; i
++) {
4566 if ((uintptr_t)val
== pd
->pd_optval
[i
].vd_val
) {
4567 (void) strlcpy(*prop_val
, pd
->pd_optval
[i
].vd_name
,
4568 DLADM_PROP_VAL_MAX
);
4569 return (DLADM_STATUS_OK
);
4572 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", (unsigned)val
);
4573 return (DLADM_STATUS_OK
);
4576 static dladm_status_t
4577 set_stp_prop(dladm_handle_t handle
, prop_desc_t
*pd __unused
,
4578 datalink_id_t linkid
, val_desc_t
*vdp __unused
, uint_t val_cnt __unused
,
4579 uint_t flags
, datalink_media_t media __unused
)
4582 * Special case for mcheck: the daemon resets the value to zero, and we
4583 * don't want the daemon to refresh itself; it leads to deadlock.
4585 if (flags
& DLADM_OPT_NOREFRESH
)
4586 return (DLADM_STATUS_OK
);
4588 /* Tell the running daemon, if any */
4589 return (dladm_bridge_refresh(handle
, linkid
));
4593 * This is used only for stp_priority, stp_cost, and stp_mcheck.
4595 static dladm_status_t
4596 check_stp_prop(dladm_handle_t handle
, struct prop_desc
*pd
,
4597 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
4598 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
4601 boolean_t iscost
= B_FALSE
;
4602 uint_t val_cnt
= *val_cntp
;
4603 val_desc_t
*vdp
= *vdpp
;
4606 return (DLADM_STATUS_BADVALCNT
);
4608 if (prop_val
== NULL
) {
4611 /* Only stp_priority and stp_cost use this function */
4612 iscost
= strcmp(pd
->pd_name
, "stp_cost") == 0;
4614 if (iscost
&& strcmp(prop_val
[0], "auto") == 0) {
4615 /* Illegal value 0 is allowed to mean "automatic" */
4619 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4620 if (errno
!= 0 || *cp
!= '\0')
4621 return (DLADM_STATUS_BADVAL
);
4626 return (vdp
->vd_val
> 65535 ? DLADM_STATUS_BADVAL
:
4629 if (vdp
->vd_val
> 255)
4630 return (DLADM_STATUS_BADVAL
);
4632 * If the user is setting stp_mcheck non-zero, then (per the
4633 * IEEE management standards and UNH testing) we need to check
4634 * whether this link is part of a bridge that is running RSTP.
4635 * If it's not, then setting the flag is an error. Note that
4636 * errors are intentionally discarded here; it's the value
4637 * that's the problem -- it's not a bad value, merely one that
4638 * can't be used now.
4640 if (strcmp(pd
->pd_name
, "stp_mcheck") == 0 &&
4642 char bridge
[MAXLINKNAMELEN
];
4644 dladm_bridge_prot_t brprot
;
4646 if (dladm_bridge_getlink(handle
, linkid
, bridge
,
4647 sizeof (bridge
)) != DLADM_STATUS_OK
||
4648 dladm_bridge_get_properties(bridge
, &cfg
,
4649 &brprot
) != DLADM_STATUS_OK
)
4650 return (DLADM_STATUS_FAILED
);
4651 if (cfg
.force_version
<= 1)
4652 return (DLADM_STATUS_FAILED
);
4654 return (DLADM_STATUS_OK
);
4658 static dladm_status_t
4659 get_bridge_forward(dladm_handle_t handle
, struct prop_desc
*pd
,
4660 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4661 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4663 dladm_status_t retv
;
4667 return (DLADM_STATUS_NOTSUP
);
4668 *perm_flags
= MAC_PROP_PERM_RW
;
4670 retv
= dladm_bridge_get_forwarding(handle
, linkid
, &val
);
4671 if (retv
== DLADM_STATUS_NOTFOUND
) {
4672 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4673 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4674 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4675 DLADM_PROP_VAL_MAX
);
4676 return (DLADM_STATUS_OK
);
4678 if (retv
== DLADM_STATUS_OK
)
4679 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", val
);
4681 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4685 static dladm_status_t
4686 set_bridge_forward(dladm_handle_t handle
, prop_desc_t
*pd __unused
,
4687 datalink_id_t linkid
, val_desc_t
*vdp __unused
, uint_t val_cnt __unused
,
4688 uint_t flags __unused
, datalink_media_t media __unused
)
4690 /* Tell the running daemon, if any */
4691 return (dladm_bridge_refresh(handle
, linkid
));
4694 static dladm_status_t
4695 get_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd __unused
,
4696 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4697 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
4699 dladm_status_t status
;
4700 dld_ioc_macprop_t
*dip
;
4704 return (DLADM_STATUS_NOTSUP
);
4705 *perm_flags
= MAC_PROP_PERM_RW
;
4707 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4711 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4712 if (status
== DLADM_STATUS_OK
) {
4713 (void) memcpy(&pvid
, dip
->pr_val
, sizeof (pvid
));
4714 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", pvid
);
4716 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4722 static dladm_status_t
4723 set_bridge_pvid(dladm_handle_t handle
, prop_desc_t
*pd __unused
,
4724 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt __unused
,
4725 uint_t flags __unused
, datalink_media_t media __unused
)
4727 dladm_status_t status
;
4728 dld_ioc_macprop_t
*dip
;
4731 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4736 (void) memcpy(dip
->pr_val
, &pvid
, sizeof (pvid
));
4737 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4739 if (status
!= DLADM_STATUS_OK
)
4742 /* Tell the running daemon, if any */
4743 return (dladm_bridge_refresh(handle
, linkid
));
4746 static dladm_status_t
4747 check_bridge_pvid(dladm_handle_t handle __unused
, struct prop_desc
*pd __unused
,
4748 datalink_id_t linkid __unused
, char **prop_val
, uint_t
*val_cntp
,
4749 uint_t flags __unused
, val_desc_t
**vdpp
, datalink_media_t media __unused
)
4752 uint_t val_cnt
= *val_cntp
;
4753 val_desc_t
*vdp
= *vdpp
;
4756 return (DLADM_STATUS_BADVALCNT
);
4758 if (prop_val
== NULL
) {
4762 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4763 if (errno
!= 0 || *cp
!= '\0')
4764 return (DLADM_STATUS_BADVAL
);
4767 return (vdp
->vd_val
> VLAN_ID_MAX
? DLADM_STATUS_BADVAL
:
4772 i_dladm_wlan_param(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
4773 mac_prop_id_t cmd
, size_t len
, boolean_t set
)
4776 dladm_status_t status
;
4778 dld_ioc_macprop_t
*dip
;
4781 if ((status
= dladm_datalink_id2info(handle
, linkid
, &flags
, NULL
,
4782 &media
, NULL
, 0)) != DLADM_STATUS_OK
) {
4786 if (media
!= DL_WIFI
)
4787 return (DLADM_STATUS_BADARG
);
4789 if (!(flags
& DLADM_OPT_ACTIVE
))
4790 return (DLADM_STATUS_TEMPONLY
);
4792 if (len
== (MAX_BUF_LEN
- WIFI_BUF_OFFSET
))
4793 len
= MAX_BUF_LEN
- sizeof (dld_ioc_macprop_t
) - 1;
4795 dip
= i_dladm_buf_alloc_by_id(len
, linkid
, cmd
, 0, &status
);
4797 return (DLADM_STATUS_NOMEM
);
4799 dp
= (uchar_t
*)dip
->pr_val
;
4801 (void) memcpy(dp
, buf
, len
);
4803 status
= i_dladm_macprop(handle
, dip
, set
);
4804 if (status
== DLADM_STATUS_OK
) {
4806 (void) memcpy(buf
, dp
, len
);
4814 dladm_parse_link_props(char *str
, dladm_arg_list_t
**listp
, boolean_t novalues
)
4816 return (dladm_parse_args(str
, listp
, novalues
));
4820 * Retrieve the one link property from the database
4823 i_dladm_get_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4824 const char *prop_name
, void *arg
)
4826 dladm_arg_list_t
*proplist
= arg
;
4827 dladm_arg_info_t
*aip
= NULL
;
4829 aip
= &proplist
->al_info
[proplist
->al_count
];
4831 * it is fine to point to prop_name since prop_name points to the
4832 * prop_table[n].pd_name.
4834 aip
->ai_name
= prop_name
;
4836 (void) dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
4837 prop_name
, aip
->ai_val
, &aip
->ai_count
);
4839 if (aip
->ai_count
!= 0)
4840 proplist
->al_count
++;
4842 return (DLADM_WALK_CONTINUE
);
4847 * Retrieve all link properties for a link from the database and
4848 * return a property list.
4851 dladm_link_get_proplist(dladm_handle_t handle
, datalink_id_t linkid
,
4852 dladm_arg_list_t
**listp
)
4854 dladm_arg_list_t
*list
;
4855 dladm_status_t status
= DLADM_STATUS_OK
;
4857 list
= calloc(1, sizeof (dladm_arg_list_t
));
4859 return (dladm_errno2status(errno
));
4861 status
= dladm_walk_linkprop(handle
, linkid
, list
,
4862 i_dladm_get_one_prop
);
4869 * Retrieve the named property from a proplist, check the value and
4870 * convert to a kernel structure.
4872 static dladm_status_t
4873 i_dladm_link_proplist_extract_one(dladm_handle_t handle
,
4874 dladm_arg_list_t
*proplist
, const char *name
, uint_t flags
, void *arg
)
4876 dladm_status_t status
= DLADM_STATUS_OK
;
4877 dladm_arg_info_t
*aip
= NULL
;
4880 /* Find named property in proplist */
4881 for (i
= 0; i
< proplist
->al_count
; i
++) {
4882 aip
= &proplist
->al_info
[i
];
4883 if (strcasecmp(aip
->ai_name
, name
) == 0)
4887 /* Property not in list */
4888 if (i
== proplist
->al_count
)
4891 if (aip
->ai_val
[0] == NULL
)
4892 return (DLADM_STATUS_BADARG
);
4894 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
4895 prop_desc_t
*pdp
= &prop_table
[i
];
4898 vdp
= malloc(sizeof (val_desc_t
) * aip
->ai_count
);
4900 return (DLADM_STATUS_NOMEM
);
4902 if (strcasecmp(aip
->ai_name
, pdp
->pd_name
) != 0)
4905 /* Check property value */
4906 if (pdp
->pd_check
!= NULL
) {
4907 status
= pdp
->pd_check(handle
, pdp
, 0, aip
->ai_val
,
4908 &(aip
->ai_count
), flags
, &vdp
, 0);
4910 status
= DLADM_STATUS_BADARG
;
4913 if (status
!= DLADM_STATUS_OK
)
4916 for (j
= 0; j
< DLADM_MAX_RSRC_PROP
; j
++) {
4917 resource_prop_t
*rpp
= &rsrc_prop_table
[j
];
4919 if (strcasecmp(aip
->ai_name
, rpp
->rp_name
) != 0)
4922 /* Extract kernel structure */
4923 if (rpp
->rp_extract
!= NULL
) {
4924 status
= rpp
->rp_extract(vdp
,
4925 aip
->ai_count
, arg
);
4927 status
= DLADM_STATUS_BADARG
;
4932 if (status
!= DLADM_STATUS_OK
)
4941 * Extract properties from a proplist and convert to mac_resource_props_t.
4944 dladm_link_proplist_extract(dladm_handle_t handle
, dladm_arg_list_t
*proplist
,
4945 mac_resource_props_t
*mrp
, uint_t flags
)
4947 dladm_status_t status
;
4950 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
4951 status
= i_dladm_link_proplist_extract_one(handle
,
4952 proplist
, rsrc_prop_table
[i
].rp_name
, flags
, mrp
);
4953 if (status
!= DLADM_STATUS_OK
)
4960 dladm_perm2str(uint_t perm
, char *buf
)
4962 (void) snprintf(buf
, DLADM_STRSIZE
, "%c%c",
4963 ((perm
& MAC_PROP_PERM_READ
) != 0) ? 'r' : '-',
4964 ((perm
& MAC_PROP_PERM_WRITE
) != 0) ? 'w' : '-');
4969 dladm_get_state(dladm_handle_t handle
, datalink_id_t linkid
,
4970 link_state_t
*state
)
4974 return (i_dladm_get_public_prop(handle
, linkid
, "state", 0,
4975 &perms
, state
, sizeof (*state
)));
4979 dladm_attr_is_linkprop(const char *name
)
4981 /* non-property attribute names */
4982 const char *nonprop
[] = {
4983 /* dlmgmtd core attributes */
4991 /* other attributes for vlan, aggr, etc */
4994 boolean_t is_nonprop
= B_FALSE
;
4997 for (i
= 0; i
< sizeof (nonprop
) / sizeof (nonprop
[0]); i
++) {
4998 if (strcmp(name
, nonprop
[i
]) == 0) {
4999 is_nonprop
= B_TRUE
;
5004 return (!is_nonprop
);
5008 dladm_linkprop_is_set(dladm_handle_t handle
, datalink_id_t linkid
,
5009 dladm_prop_type_t type
, const char *prop_name
, boolean_t
*is_set
)
5011 char *buf
, **propvals
;
5012 uint_t valcnt
= DLADM_MAX_PROP_VALCNT
;
5014 dladm_status_t status
= DLADM_STATUS_OK
;
5019 bufsize
= (sizeof (char *) + DLADM_PROP_VAL_MAX
) *
5020 DLADM_MAX_PROP_VALCNT
;
5021 if ((buf
= calloc(1, bufsize
)) == NULL
)
5022 return (DLADM_STATUS_NOMEM
);
5024 propvals
= (char **)(void *)buf
;
5025 for (i
= 0; i
< valcnt
; i
++) {
5027 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
5028 i
* DLADM_PROP_VAL_MAX
;
5031 if (dladm_get_linkprop(handle
, linkid
, type
, prop_name
, propvals
,
5032 &valcnt
) != DLADM_STATUS_OK
) {
5037 * valcnt is always set to 1 by get_pool(), hence we need to check
5038 * for a non-null string to see if it is set. For protection,
5039 * secondary-macs and allowed-ips, we can check either the *propval
5042 if ((strcmp(prop_name
, "pool") == 0 ||
5043 strcmp(prop_name
, "protection") == 0 ||
5044 strcmp(prop_name
, "secondary-macs") == 0 ||
5045 strcmp(prop_name
, "allowed-ips") == 0) &&
5046 (strlen(*propvals
) != 0)) {
5048 } else if ((strcmp(prop_name
, "cpus") == 0) && (valcnt
!= 0)) {
5050 } else if ((strcmp(prop_name
, "_softmac") == 0) && (valcnt
!= 0) &&
5051 (strcmp(propvals
[0], "true") == 0)) {
5061 static dladm_status_t
5062 get_linkmode_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
5063 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
5064 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
5068 dladm_status_t status
;
5070 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
5071 perm_flags
, &v
, sizeof (v
));
5072 if (status
!= DLADM_STATUS_OK
)
5076 case DLADM_PART_CM_MODE
:
5079 case DLADM_PART_UD_MODE
:
5086 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
5089 return (DLADM_STATUS_OK
);
5092 static dladm_status_t
5093 get_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
5094 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
5095 datalink_media_t media __unused
, uint_t flags
, uint_t
*perm_flags
)
5098 dladm_status_t status
;
5101 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
5102 perm_flags
, &filt
, sizeof (filt
));
5103 if (status
!= DLADM_STATUS_OK
)
5107 s
= link_promisc_filtered_vals
[1].vd_name
;
5109 s
= link_promisc_filtered_vals
[0].vd_name
;
5110 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
5113 return (DLADM_STATUS_OK
);
5116 static dladm_status_t
5117 set_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
5118 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt __unused
,
5119 uint_t flags __unused
, datalink_media_t media __unused
)
5121 dld_ioc_macprop_t
*dip
;
5122 dladm_status_t status
= DLADM_STATUS_OK
;
5124 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
,
5130 (void) memcpy(dip
->pr_val
, &vdp
->vd_val
, dip
->pr_valsize
);
5131 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
5137 static dladm_status_t
5138 get_media(dladm_handle_t handle
, prop_desc_t
*pdp
,
5139 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
5140 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
5142 dladm_status_t status
= DLADM_STATUS_OK
;
5148 return (DLADM_STATUS_TOOSMALL
);
5150 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
5151 perm_flags
, &raw_val
, sizeof (raw_val
));
5152 if (status
!= DLADM_STATUS_OK
)
5156 * To translate the property into a string we need to know the actual
5157 * datalink_media_t type to use as these values are media-type specific.
5161 descs
= dladm_ether_media_vals
;
5162 desc_count
= VALCNT(dladm_ether_media_vals
);
5171 for (size_t i
= 0; i
< desc_count
; i
++) {
5172 if (descs
[i
].vd_val
== raw_val
) {
5173 (void) strlcpy(prop_val
[0], descs
[i
].vd_name
,
5174 DLADM_PROP_VAL_MAX
);
5175 return (DLADM_STATUS_OK
);
5179 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "unknown (0x%x)",
5181 return (DLADM_STATUS_OK
);