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 2016 Joyent, Inc.
24 * Copyright 2015 Garrett D'Amore <garrett@damore.org>
33 #include <sys/types.h>
39 #include <libdevinfo.h>
41 #include <libdllink.h>
42 #include <libdladm_impl.h>
43 #include <libdlwlan_impl.h>
44 #include <libdlwlan.h>
45 #include <libdlvlan.h>
46 #include <libdlvnic.h>
51 #include <inet/wifi_ioctl.h>
53 #include <libdlstat.h>
54 #include <sys/param.h>
55 #include <sys/debug.h>
58 #include <sys/ethernet.h>
59 #include <inet/iptun.h>
61 #include <sys/sysmacros.h>
63 #include <libdlbridge.h>
65 #include <netinet/dhcp.h>
66 #include <netinet/dhcp6.h>
67 #include <net/if_types.h>
68 #include <libinetutil.h>
70 #include <libdlaggr.h>
73 * The linkprop get() callback.
74 * - pd: pointer to the prop_desc_t
75 * - propstrp: a property string array to keep the returned property.
77 * - cntp: number of returned properties.
78 * Caller also uses it to indicate how many it expects.
81 typedef struct prop_desc prop_desc_t
;
83 typedef dladm_status_t
pd_getf_t(dladm_handle_t
, prop_desc_t
*pdp
,
84 datalink_id_t
, char **propstp
, uint_t
*cntp
,
85 datalink_media_t
, uint_t
, uint_t
*);
88 * The linkprop set() callback.
89 * - propval: a val_desc_t array which keeps the property values to be set.
90 * - cnt: number of properties to be set.
91 * - flags: additional flags passed down the system call.
93 * pd_set takes val_desc_t given by pd_check(), translates it into
94 * a format suitable for kernel consumption. This may require allocation
95 * of ioctl buffers etc. pd_set() may call another common routine (used
96 * by all other pd_sets) which invokes the ioctl.
98 typedef dladm_status_t
pd_setf_t(dladm_handle_t
, prop_desc_t
*, datalink_id_t
,
99 val_desc_t
*propval
, uint_t cnt
, uint_t flags
,
103 * The linkprop check() callback.
104 * - propstrp: property string array which keeps the property to be checked.
105 * - cnt: number of properties.
106 * - propval: return value; the property values of the given property strings.
108 * pd_check checks that the input values are valid. It does so by
109 * iteraring through the pd_modval list for the property. If
110 * the modifiable values cannot be expressed as a list, a pd_check
111 * specific to this property can be used. If the input values are
112 * verified to be valid, pd_check allocates a val_desc_t and fills it
113 * with either a val_desc_t found on the pd_modval list or something
114 * generated on the fly.
116 typedef dladm_status_t
pd_checkf_t(dladm_handle_t
, prop_desc_t
*pdp
,
117 datalink_id_t
, char **propstrp
, uint_t
*cnt
,
118 uint_t flags
, val_desc_t
**propval
,
121 typedef struct link_attr_s
{
127 typedef struct dladm_linkprop_args_s
{
128 dladm_status_t dla_status
;
130 } dladm_linkprop_args_t
;
132 static dld_ioc_macprop_t
*i_dladm_buf_alloc_by_name(size_t, datalink_id_t
,
133 const char *, uint_t
, dladm_status_t
*);
134 static dld_ioc_macprop_t
*i_dladm_buf_alloc_by_id(size_t, datalink_id_t
,
135 mac_prop_id_t
, uint_t
, dladm_status_t
*);
136 static dladm_status_t
i_dladm_get_public_prop(dladm_handle_t
, datalink_id_t
,
137 char *, uint_t
, uint_t
*, void *, size_t);
139 static dladm_status_t
i_dladm_set_private_prop(dladm_handle_t
, datalink_id_t
,
140 const char *, char **, uint_t
, uint_t
);
141 static dladm_status_t
i_dladm_get_priv_prop(dladm_handle_t
, datalink_id_t
,
142 const char *, char **, uint_t
*, dladm_prop_type_t
,
144 static dladm_status_t
i_dladm_macprop(dladm_handle_t
, void *, boolean_t
);
145 static const char *dladm_perm2str(uint_t
, char *);
146 static link_attr_t
*dladm_name2prop(const char *);
147 static link_attr_t
*dladm_id2prop(mac_prop_id_t
);
149 static pd_getf_t get_zone
, get_autopush
, get_rate_mod
, get_rate
,
150 get_speed
, get_channel
, get_powermode
, get_radio
,
151 get_duplex
, get_link_state
, get_binary
, get_uint32
,
152 get_flowctl
, get_maxbw
, get_cpus
, get_priority
,
153 get_tagmode
, get_range
, get_stp
, get_bridge_forward
,
154 get_bridge_pvid
, get_protection
, get_rxrings
,
155 get_txrings
, get_cntavail
, get_secondary_macs
,
156 get_allowedips
, get_allowedcids
, get_pool
,
157 get_rings_range
, get_linkmode_prop
,
158 get_promisc_filtered
;
160 static pd_setf_t set_zone
, set_rate
, set_powermode
, set_radio
,
161 set_public_prop
, set_resource
, set_stp_prop
,
162 set_bridge_forward
, set_bridge_pvid
, set_secondary_macs
,
163 set_promisc_filtered
;
165 static pd_checkf_t check_zone
, check_autopush
, check_rate
, check_hoplimit
,
166 check_encaplim
, check_uint32
, check_maxbw
, check_cpus
,
167 check_stp_prop
, check_bridge_pvid
, check_allowedips
,
168 check_allowedcids
, check_secondary_macs
, check_rings
,
169 check_pool
, check_prop
;
178 * default property value, can be set to { "", NULL }
180 val_desc_t pd_defval
;
183 * list of optional property values, can be NULL.
185 * This is set to non-NULL if there is a list of possible property
186 * values. pd_optval would point to the array of possible values.
188 val_desc_t
*pd_optval
;
191 * count of the above optional property values. 0 if pd_optval is NULL.
196 * callback to set link property; set to NULL if this property is
197 * read-only and may be called before or after permanent update; see
203 * callback to get modifiable link property
205 pd_getf_t
*pd_getmod
;
208 * callback to get current link property
213 * callback to validate link property value, set to NULL if pd_optval
214 * is not NULL. In that case, validate the value by comparing it with
215 * the pd_optval. Return a val_desc_t array pointer if the value is
218 pd_checkf_t
*pd_check
;
221 #define PD_TEMPONLY 0x1 /* property is temporary only */
222 #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */
223 #define PD_AFTER_PERM 0x4 /* pd_set after db update; no temporary */
225 * indicate link classes this property applies to.
227 datalink_class_t pd_class
;
230 * indicate link media type this property applies to.
232 datalink_media_t pd_dmedia
;
235 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1
238 * Supported link properties enumerated in the prop_table[] array are
239 * computed using the callback functions in that array. To compute the
240 * property value, multiple distinct system calls may be needed (e.g.,
241 * for wifi speed, we need to issue system calls to get desired/supported
242 * rates). The link_attr[] table enumerates the interfaces to the kernel,
243 * and the type/size of the data passed in the user-kernel interface.
245 static link_attr_t link_attr
[] = {
246 { MAC_PROP_DUPLEX
, sizeof (link_duplex_t
), "duplex"},
248 { MAC_PROP_SPEED
, sizeof (uint64_t), "speed"},
250 { MAC_PROP_STATUS
, sizeof (link_state_t
), "state"},
252 { MAC_PROP_AUTONEG
, sizeof (uint8_t), "adv_autoneg_cap"},
254 { MAC_PROP_MTU
, sizeof (uint32_t), "mtu"},
256 { MAC_PROP_FLOWCTRL
, sizeof (link_flowctrl_t
), "flowctrl"},
258 { MAC_PROP_ZONE
, sizeof (dld_ioc_zid_t
), "zone"},
260 { MAC_PROP_AUTOPUSH
, sizeof (struct dlautopush
), "autopush"},
262 { MAC_PROP_ADV_5000FDX_CAP
, sizeof (uint8_t), "adv_5000fdx_cap"},
264 { MAC_PROP_EN_5000FDX_CAP
, sizeof (uint8_t), "en_5000fdx_cap"},
266 { MAC_PROP_ADV_2500FDX_CAP
, sizeof (uint8_t), "adv_2500fdx_cap"},
268 { MAC_PROP_EN_2500FDX_CAP
, sizeof (uint8_t), "en_2500fdx_cap"},
270 { MAC_PROP_ADV_100GFDX_CAP
, sizeof (uint8_t), "adv_100gfdx_cap"},
272 { MAC_PROP_EN_100GFDX_CAP
, sizeof (uint8_t), "en_100gfdx_cap"},
274 { MAC_PROP_ADV_50GFDX_CAP
, sizeof (uint8_t), "adv_50gfdx_cap"},
276 { MAC_PROP_EN_50GFDX_CAP
, sizeof (uint8_t), "en_50gfdx_cap"},
278 { MAC_PROP_ADV_40GFDX_CAP
, sizeof (uint8_t), "adv_40gfdx_cap"},
280 { MAC_PROP_EN_40GFDX_CAP
, sizeof (uint8_t), "en_40gfdx_cap"},
282 { MAC_PROP_ADV_25GFDX_CAP
, sizeof (uint8_t), "adv_25gfdx_cap"},
284 { MAC_PROP_EN_25GFDX_CAP
, sizeof (uint8_t), "en_25gfdx_cap"},
286 { MAC_PROP_ADV_10GFDX_CAP
, sizeof (uint8_t), "adv_10gfdx_cap"},
288 { MAC_PROP_EN_10GFDX_CAP
, sizeof (uint8_t), "en_10gfdx_cap"},
290 { MAC_PROP_ADV_1000FDX_CAP
, sizeof (uint8_t), "adv_1000fdx_cap"},
292 { MAC_PROP_EN_1000FDX_CAP
, sizeof (uint8_t), "en_1000fdx_cap"},
294 { MAC_PROP_ADV_1000HDX_CAP
, sizeof (uint8_t), "adv_1000hdx_cap"},
296 { MAC_PROP_EN_1000HDX_CAP
, sizeof (uint8_t), "en_1000hdx_cap"},
298 { MAC_PROP_ADV_100FDX_CAP
, sizeof (uint8_t), "adv_100fdx_cap"},
300 { MAC_PROP_EN_100FDX_CAP
, sizeof (uint8_t), "en_100fdx_cap"},
302 { MAC_PROP_ADV_100HDX_CAP
, sizeof (uint8_t), "adv_100hdx_cap"},
304 { MAC_PROP_EN_100HDX_CAP
, sizeof (uint8_t), "en_100hdx_cap"},
306 { MAC_PROP_ADV_10FDX_CAP
, sizeof (uint8_t), "adv_10fdx_cap"},
308 { MAC_PROP_EN_10FDX_CAP
, sizeof (uint8_t), "en_10fdx_cap"},
310 { MAC_PROP_ADV_10HDX_CAP
, sizeof (uint8_t), "adv_10hdx_cap"},
312 { MAC_PROP_EN_10HDX_CAP
, sizeof (uint8_t), "en_10hdx_cap"},
314 { MAC_PROP_WL_ESSID
, sizeof (wl_linkstatus_t
), "essid"},
316 { MAC_PROP_WL_BSSID
, sizeof (wl_bssid_t
), "bssid"},
318 { MAC_PROP_WL_BSSTYPE
, sizeof (wl_bss_type_t
), "bsstype"},
320 { MAC_PROP_WL_LINKSTATUS
, sizeof (wl_linkstatus_t
), "wl_linkstatus"},
322 /* wl_rates_t has variable length */
323 { MAC_PROP_WL_DESIRED_RATES
, sizeof (wl_rates_t
), "desired_rates"},
325 /* wl_rates_t has variable length */
326 { MAC_PROP_WL_SUPPORTED_RATES
, sizeof (wl_rates_t
), "supported_rates"},
328 { MAC_PROP_WL_AUTH_MODE
, sizeof (wl_authmode_t
), "authmode"},
330 { MAC_PROP_WL_ENCRYPTION
, sizeof (wl_encryption_t
), "encryption"},
332 { MAC_PROP_WL_RSSI
, sizeof (wl_rssi_t
), "signal"},
334 { MAC_PROP_WL_PHY_CONFIG
, sizeof (wl_phy_conf_t
), "phy_conf"},
336 { MAC_PROP_WL_CAPABILITY
, sizeof (wl_capability_t
), "capability"},
338 { MAC_PROP_WL_WPA
, sizeof (wl_wpa_t
), "wpa"},
340 /* wl_wpa_ess_t has variable length */
341 { MAC_PROP_WL_SCANRESULTS
, sizeof (wl_wpa_ess_t
), "scan_results"},
343 { MAC_PROP_WL_POWER_MODE
, sizeof (wl_ps_mode_t
), "powermode"},
345 { MAC_PROP_WL_RADIO
, sizeof (dladm_wlan_radio_t
), "wl_radio"},
347 { MAC_PROP_WL_ESS_LIST
, sizeof (wl_ess_list_t
), "wl_ess_list"},
349 { MAC_PROP_WL_KEY_TAB
, sizeof (wl_wep_key_tab_t
), "wl_wep_key"},
351 { MAC_PROP_WL_CREATE_IBSS
, sizeof (wl_create_ibss_t
), "createibss"},
353 /* wl_wpa_ie_t has variable length */
354 { MAC_PROP_WL_SETOPTIE
, sizeof (wl_wpa_ie_t
), "set_ie"},
356 { MAC_PROP_WL_DELKEY
, sizeof (wl_del_key_t
), "wpa_del_key"},
358 { MAC_PROP_WL_KEY
, sizeof (wl_key_t
), "wl_key"},
360 { MAC_PROP_WL_MLME
, sizeof (wl_mlme_t
), "mlme"},
362 { MAC_PROP_TAGMODE
, sizeof (link_tagmode_t
), "tagmode"},
364 { MAC_PROP_IPTUN_HOPLIMIT
, sizeof (uint32_t), "hoplimit"},
366 { MAC_PROP_IPTUN_ENCAPLIMIT
, sizeof (uint32_t), "encaplimit"},
368 { MAC_PROP_PVID
, sizeof (uint16_t), "default_tag"},
370 { MAC_PROP_LLIMIT
, sizeof (uint32_t), "learn_limit"},
372 { MAC_PROP_LDECAY
, sizeof (uint32_t), "learn_decay"},
374 { MAC_PROP_RESOURCE
, sizeof (mac_resource_props_t
), "resource"},
376 { MAC_PROP_RESOURCE_EFF
, sizeof (mac_resource_props_t
),
377 "resource-effective"},
379 { MAC_PROP_RXRINGSRANGE
, sizeof (mac_propval_range_t
), "rxrings"},
381 { MAC_PROP_TXRINGSRANGE
, sizeof (mac_propval_range_t
), "txrings"},
383 { MAC_PROP_MAX_TX_RINGS_AVAIL
, sizeof (uint_t
),
384 "txrings-available"},
386 { MAC_PROP_MAX_RX_RINGS_AVAIL
, sizeof (uint_t
),
387 "rxrings-available"},
389 { MAC_PROP_MAX_RXHWCLNT_AVAIL
, sizeof (uint_t
), "rxhwclnt-available"},
391 { MAC_PROP_MAX_TXHWCLNT_AVAIL
, sizeof (uint_t
), "txhwclnt-available"},
393 { MAC_PROP_IB_LINKMODE
, sizeof (uint32_t), "linkmode"},
395 { MAC_PROP_VN_PROMISC_FILTERED
, sizeof (boolean_t
), "promisc-filtered"},
397 { MAC_PROP_SECONDARY_ADDRS
, sizeof (mac_secondary_addr_t
),
400 { MAC_PROP_PRIVATE
, 0, "driver-private"}
403 typedef struct bridge_public_prop_s
{
404 const char *bpp_name
;
406 } bridge_public_prop_t
;
408 static const bridge_public_prop_t bridge_prop
[] = {
409 { "stp", PT_CFG_NON_STP
},
410 { "stp_priority", PT_CFG_PRIO
},
411 { "stp_cost", PT_CFG_COST
},
412 { "stp_edge", PT_CFG_EDGE
},
413 { "stp_p2p", PT_CFG_P2P
},
414 { "stp_mcheck", PT_CFG_MCHECK
},
418 static val_desc_t link_duplex_vals
[] = {
419 { "half", LINK_DUPLEX_HALF
},
420 { "full", LINK_DUPLEX_HALF
}
422 static val_desc_t link_status_vals
[] = {
423 { "up", LINK_STATE_UP
},
424 { "down", LINK_STATE_DOWN
}
426 static val_desc_t link_01_vals
[] = {
430 static val_desc_t link_flow_vals
[] = {
431 { "no", LINK_FLOWCTRL_NONE
},
432 { "tx", LINK_FLOWCTRL_TX
},
433 { "rx", LINK_FLOWCTRL_RX
},
434 { "bi", LINK_FLOWCTRL_BI
}
436 static val_desc_t link_priority_vals
[] = {
438 { "medium", MPL_MEDIUM
},
442 static val_desc_t link_tagmode_vals
[] = {
443 { "normal", LINK_TAGMODE_NORMAL
},
444 { "vlanonly", LINK_TAGMODE_VLANONLY
}
447 static val_desc_t link_protect_vals
[] = {
448 { "mac-nospoof", MPT_MACNOSPOOF
},
449 { "restricted", MPT_RESTRICTED
},
450 { "ip-nospoof", MPT_IPNOSPOOF
},
451 { "dhcp-nospoof", MPT_DHCPNOSPOOF
},
454 static val_desc_t link_promisc_filtered_vals
[] = {
459 static val_desc_t dladm_wlan_radio_vals
[] = {
460 { "on", DLADM_WLAN_RADIO_ON
},
461 { "off", DLADM_WLAN_RADIO_OFF
}
464 static val_desc_t dladm_wlan_powermode_vals
[] = {
465 { "off", DLADM_WLAN_PM_OFF
},
466 { "fast", DLADM_WLAN_PM_FAST
},
467 { "max", DLADM_WLAN_PM_MAX
}
470 static val_desc_t stp_p2p_vals
[] = {
471 { "true", P2P_FORCE_TRUE
},
472 { "false", P2P_FORCE_FALSE
},
476 static val_desc_t dladm_part_linkmode_vals
[] = {
477 { "cm", DLADM_PART_CM_MODE
},
478 { "ud", DLADM_PART_UD_MODE
},
481 #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
482 #define RESET_VAL ((uintptr_t)-1)
483 #define UNSPEC_VAL ((uintptr_t)-2)
486 * For the default, if defaults are not defined for the property,
487 * pd_defval.vd_name should be null. If the driver has to be contacted for the
488 * value, vd_name should be the empty string (""). Otherwise, dladm will
489 * just print whatever is in the table.
491 static prop_desc_t prop_table
[] = {
492 { "channel", { NULL
, 0 },
494 get_channel
, NULL
, 0,
495 DATALINK_CLASS_PHYS
, DL_WIFI
},
497 { "powermode", { "off", DLADM_WLAN_PM_OFF
},
498 dladm_wlan_powermode_vals
, VALCNT(dladm_wlan_powermode_vals
),
500 get_powermode
, NULL
, 0,
501 DATALINK_CLASS_PHYS
, DL_WIFI
},
503 { "radio", { "on", DLADM_WLAN_RADIO_ON
},
504 dladm_wlan_radio_vals
, VALCNT(dladm_wlan_radio_vals
),
507 DATALINK_CLASS_PHYS
, DL_WIFI
},
509 { "linkmode", { "cm", DLADM_PART_CM_MODE
},
510 dladm_part_linkmode_vals
, VALCNT(dladm_part_linkmode_vals
),
511 set_public_prop
, NULL
, get_linkmode_prop
, NULL
, 0,
512 DATALINK_CLASS_PART
, DL_IB
},
514 { "speed", { "", 0 }, NULL
, 0,
515 set_rate
, get_rate_mod
,
516 get_rate
, check_rate
, 0,
517 DATALINK_CLASS_PHYS
, DATALINK_ANY_MEDIATYPE
},
519 { "autopush", { "", 0 }, NULL
, 0,
520 set_public_prop
, NULL
,
521 get_autopush
, check_autopush
, PD_CHECK_ALLOC
,
522 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
524 { "zone", { "", 0 }, NULL
, 0,
526 get_zone
, check_zone
, PD_TEMPONLY
|PD_CHECK_ALLOC
,
527 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
529 { "duplex", { "", 0 },
530 link_duplex_vals
, VALCNT(link_duplex_vals
),
531 NULL
, NULL
, get_duplex
, NULL
,
532 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
534 { "state", { "up", LINK_STATE_UP
},
535 link_status_vals
, VALCNT(link_status_vals
),
536 NULL
, NULL
, get_link_state
, NULL
,
537 0, DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
539 { "adv_autoneg_cap", { "", 0 },
540 link_01_vals
, VALCNT(link_01_vals
),
541 set_public_prop
, NULL
, get_binary
, NULL
,
542 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
544 { "mtu", { "", 0 }, NULL
, 0,
545 set_public_prop
, get_range
,
546 get_uint32
, check_uint32
, 0, DATALINK_CLASS_ALL
,
547 DATALINK_ANY_MEDIATYPE
},
549 { "flowctrl", { "", 0 },
550 link_flow_vals
, VALCNT(link_flow_vals
),
551 set_public_prop
, NULL
, get_flowctl
, NULL
,
552 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
554 { "secondary-macs", { "--", 0 }, NULL
, 0,
555 set_secondary_macs
, NULL
,
556 get_secondary_macs
, check_secondary_macs
, PD_CHECK_ALLOC
,
557 DATALINK_CLASS_VNIC
, DL_ETHER
},
559 { "adv_100gfdx_cap", { "", 0 },
560 link_01_vals
, VALCNT(link_01_vals
),
561 NULL
, NULL
, get_binary
, NULL
,
562 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
564 { "en_100gfdx_cap", { "", 0 },
565 link_01_vals
, VALCNT(link_01_vals
),
566 set_public_prop
, NULL
, get_binary
, NULL
,
567 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
569 { "adv_50gfdx_cap", { "", 0 },
570 link_01_vals
, VALCNT(link_01_vals
),
571 NULL
, NULL
, get_binary
, NULL
,
572 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
574 { "en_50gfdx_cap", { "", 0 },
575 link_01_vals
, VALCNT(link_01_vals
),
576 set_public_prop
, NULL
, get_binary
, NULL
,
577 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
579 { "adv_40gfdx_cap", { "", 0 },
580 link_01_vals
, VALCNT(link_01_vals
),
581 NULL
, NULL
, get_binary
, NULL
,
582 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
584 { "en_40gfdx_cap", { "", 0 },
585 link_01_vals
, VALCNT(link_01_vals
),
586 set_public_prop
, NULL
, get_binary
, NULL
,
587 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
589 { "adv_25gfdx_cap", { "", 0 },
590 link_01_vals
, VALCNT(link_01_vals
),
591 NULL
, NULL
, get_binary
, NULL
,
592 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
594 { "en_25gfdx_cap", { "", 0 },
595 link_01_vals
, VALCNT(link_01_vals
),
596 set_public_prop
, NULL
, get_binary
, NULL
,
597 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
599 { "adv_10gfdx_cap", { "", 0 },
600 link_01_vals
, VALCNT(link_01_vals
),
601 NULL
, NULL
, get_binary
, NULL
,
602 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
604 { "en_10gfdx_cap", { "", 0 },
605 link_01_vals
, VALCNT(link_01_vals
),
606 set_public_prop
, NULL
, get_binary
, NULL
,
607 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
609 { "adv_5000fdx_cap", { "", 0 },
610 link_01_vals
, VALCNT(link_01_vals
),
611 NULL
, NULL
, get_binary
, NULL
,
612 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
614 { "en_5000fdx_cap", { "", 0 },
615 link_01_vals
, VALCNT(link_01_vals
),
616 set_public_prop
, NULL
, get_binary
, NULL
,
617 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
619 { "adv_2500fdx_cap", { "", 0 },
620 link_01_vals
, VALCNT(link_01_vals
),
621 NULL
, NULL
, get_binary
, NULL
,
622 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
624 { "en_2500fdx_cap", { "", 0 },
625 link_01_vals
, VALCNT(link_01_vals
),
626 set_public_prop
, NULL
, get_binary
, NULL
,
627 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
629 { "adv_1000fdx_cap", { "", 0 },
630 link_01_vals
, VALCNT(link_01_vals
),
631 NULL
, NULL
, get_binary
, NULL
,
632 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
634 { "en_1000fdx_cap", { "", 0 },
635 link_01_vals
, VALCNT(link_01_vals
),
636 set_public_prop
, NULL
, get_binary
, NULL
,
637 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
639 { "adv_1000hdx_cap", { "", 0 },
640 link_01_vals
, VALCNT(link_01_vals
),
641 NULL
, NULL
, get_binary
, NULL
,
642 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
644 { "en_1000hdx_cap", { "", 0 },
645 link_01_vals
, VALCNT(link_01_vals
),
646 set_public_prop
, NULL
, get_binary
, NULL
,
647 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
649 { "adv_100fdx_cap", { "", 0 },
650 link_01_vals
, VALCNT(link_01_vals
),
651 NULL
, NULL
, get_binary
, NULL
,
652 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
654 { "en_100fdx_cap", { "", 0 },
655 link_01_vals
, VALCNT(link_01_vals
),
656 set_public_prop
, NULL
, get_binary
, NULL
,
657 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
659 { "adv_100hdx_cap", { "", 0 },
660 link_01_vals
, VALCNT(link_01_vals
),
661 NULL
, NULL
, get_binary
, NULL
,
662 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
664 { "en_100hdx_cap", { "", 0 },
665 link_01_vals
, VALCNT(link_01_vals
),
666 set_public_prop
, NULL
, get_binary
, NULL
,
667 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
669 { "adv_10fdx_cap", { "", 0 },
670 link_01_vals
, VALCNT(link_01_vals
),
671 NULL
, NULL
, get_binary
, NULL
,
672 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
674 { "en_10fdx_cap", { "", 0 },
675 link_01_vals
, VALCNT(link_01_vals
),
676 set_public_prop
, NULL
, get_binary
, NULL
,
677 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
679 { "adv_10hdx_cap", { "", 0 },
680 link_01_vals
, VALCNT(link_01_vals
),
681 NULL
, NULL
, get_binary
, NULL
,
682 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
684 { "en_10hdx_cap", { "", 0 },
685 link_01_vals
, VALCNT(link_01_vals
),
686 set_public_prop
, NULL
, get_binary
, NULL
,
687 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
689 { "maxbw", { "--", RESET_VAL
}, NULL
, 0,
691 get_maxbw
, check_maxbw
, PD_CHECK_ALLOC
,
692 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
694 { "cpus", { "--", RESET_VAL
}, NULL
, 0,
696 get_cpus
, check_cpus
, 0,
697 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
699 { "cpus-effective", { "--", 0 },
702 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
704 { "pool", { "--", RESET_VAL
}, NULL
, 0,
706 get_pool
, check_pool
, 0,
707 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
709 { "pool-effective", { "--", 0 },
712 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
714 { "priority", { "high", MPL_RESET
},
715 link_priority_vals
, VALCNT(link_priority_vals
), set_resource
,
716 NULL
, get_priority
, check_prop
, 0,
717 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
719 { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY
},
720 link_tagmode_vals
, VALCNT(link_tagmode_vals
),
721 set_public_prop
, NULL
, get_tagmode
,
723 DATALINK_CLASS_PHYS
| DATALINK_CLASS_AGGR
| DATALINK_CLASS_VNIC
,
726 { "hoplimit", { "", 0 }, NULL
, 0,
727 set_public_prop
, get_range
, get_uint32
,
728 check_hoplimit
, 0, DATALINK_CLASS_IPTUN
, DATALINK_ANY_MEDIATYPE
},
730 { "encaplimit", { "", 0 }, NULL
, 0,
731 set_public_prop
, get_range
, get_uint32
,
732 check_encaplim
, 0, DATALINK_CLASS_IPTUN
, DL_IPV6
},
734 { "forward", { "1", 1 },
735 link_01_vals
, VALCNT(link_01_vals
),
736 set_bridge_forward
, NULL
, get_bridge_forward
, NULL
, PD_AFTER_PERM
,
737 DATALINK_CLASS_ALL
& ~DATALINK_CLASS_VNIC
, DL_ETHER
},
739 { "default_tag", { "1", 1 }, NULL
, 0,
740 set_bridge_pvid
, NULL
, get_bridge_pvid
, check_bridge_pvid
,
741 0, DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
742 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
744 { "learn_limit", { "1000", 1000 }, NULL
, 0,
745 set_public_prop
, NULL
, get_uint32
,
747 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
748 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
750 { "learn_decay", { "200", 200 }, NULL
, 0,
751 set_public_prop
, NULL
, get_uint32
,
753 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
754 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
757 link_01_vals
, VALCNT(link_01_vals
),
758 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
759 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
760 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
762 { "stp_priority", { "128", 128 }, NULL
, 0,
763 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
764 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
765 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
767 { "stp_cost", { "auto", 0 }, NULL
, 0,
768 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
769 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
770 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
772 { "stp_edge", { "1", 1 },
773 link_01_vals
, VALCNT(link_01_vals
),
774 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
775 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
776 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
778 { "stp_p2p", { "auto", P2P_AUTO
},
779 stp_p2p_vals
, VALCNT(stp_p2p_vals
),
780 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
781 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
782 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
784 { "stp_mcheck", { "0", 0 },
785 link_01_vals
, VALCNT(link_01_vals
),
786 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
787 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
788 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
790 { "protection", { "--", RESET_VAL
},
791 link_protect_vals
, VALCNT(link_protect_vals
),
792 set_resource
, NULL
, get_protection
, check_prop
, 0,
793 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
795 { "promisc-filtered", { "on", 1 },
796 link_promisc_filtered_vals
, VALCNT(link_promisc_filtered_vals
),
797 set_promisc_filtered
, NULL
, get_promisc_filtered
, check_prop
, 0,
798 DATALINK_CLASS_VNIC
, DATALINK_ANY_MEDIATYPE
},
801 { "allowed-ips", { "--", 0 },
802 NULL
, 0, set_resource
, NULL
,
803 get_allowedips
, check_allowedips
, PD_CHECK_ALLOC
,
804 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
806 { "allowed-dhcp-cids", { "--", 0 },
807 NULL
, 0, set_resource
, NULL
,
808 get_allowedcids
, check_allowedcids
, PD_CHECK_ALLOC
,
809 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
811 { "rxrings", { "--", RESET_VAL
}, NULL
, 0,
812 set_resource
, get_rings_range
, get_rxrings
, check_rings
, 0,
813 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
815 { "rxrings-effective", { "--", 0 },
817 get_rxrings
, NULL
, 0,
818 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
820 { "txrings", { "--", RESET_VAL
}, NULL
, 0,
821 set_resource
, get_rings_range
, get_txrings
, check_rings
, 0,
822 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
824 { "txrings-effective", { "--", 0 },
826 get_txrings
, NULL
, 0,
827 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
829 { "txrings-available", { "", 0 }, NULL
, 0,
830 NULL
, NULL
, get_cntavail
, NULL
, 0,
831 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
833 { "rxrings-available", { "", 0 }, NULL
, 0,
834 NULL
, NULL
, get_cntavail
, NULL
, 0,
835 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
837 { "rxhwclnt-available", { "", 0 }, NULL
, 0,
838 NULL
, NULL
, get_cntavail
, NULL
, 0,
839 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
841 { "txhwclnt-available", { "", 0 }, NULL
, 0,
842 NULL
, NULL
, get_cntavail
, NULL
, 0,
843 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
847 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
849 static resource_prop_t rsrc_prop_table
[] = {
850 {"maxbw", extract_maxbw
},
851 {"priority", extract_priority
},
852 {"cpus", extract_cpus
},
853 {"cpus-effective", extract_cpus
},
854 {"pool", extract_pool
},
855 {"pool-effective", extract_pool
},
856 {"protection", extract_protection
},
857 {"allowed-ips", extract_allowedips
},
858 {"allowed-dhcp-cids", extract_allowedcids
},
859 {"rxrings", extract_rxrings
},
860 {"rxrings-effective", extract_rxrings
},
861 {"txrings", extract_txrings
},
862 {"txrings-effective", extract_txrings
}
864 #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
865 sizeof (resource_prop_t))
868 * when retrieving private properties, we pass down a buffer with
869 * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
871 #define DLADM_PROP_BUF_CHUNK 1024
873 static dladm_status_t
i_dladm_set_linkprop_db(dladm_handle_t
, datalink_id_t
,
874 const char *, char **, uint_t
);
875 static dladm_status_t
i_dladm_get_linkprop_db(dladm_handle_t
, datalink_id_t
,
876 const char *, char **, uint_t
*);
877 static dladm_status_t
i_dladm_walk_linkprop_priv_db(dladm_handle_t
,
878 datalink_id_t
, void *, int (*)(dladm_handle_t
,
879 datalink_id_t
, const char *, void *));
880 static dladm_status_t
i_dladm_set_single_prop(dladm_handle_t
, datalink_id_t
,
881 datalink_class_t
, uint32_t, prop_desc_t
*, char **,
883 static dladm_status_t
i_dladm_set_linkprop(dladm_handle_t
, datalink_id_t
,
884 const char *, char **, uint_t
, uint_t
);
885 static dladm_status_t
i_dladm_getset_defval(dladm_handle_t
, prop_desc_t
*,
886 datalink_id_t
, datalink_media_t
, uint_t
);
889 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
890 * rates to be retrieved. However, we cannot increase it at this
891 * time because it will break binary compatibility with unbundled
892 * WiFi drivers and utilities. So for now we define an additional
893 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
895 #define MAX_SUPPORT_RATES 64
897 #define AP_ANCHOR "[anchor]"
898 #define AP_DELIMITER '.'
901 static dladm_status_t
902 check_prop(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
903 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
904 datalink_media_t media
)
907 uint_t val_cnt
= *val_cntp
;
908 val_desc_t
*vdp
= *vdpp
;
910 for (j
= 0; j
< val_cnt
; j
++) {
911 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
912 if (strcasecmp(prop_val
[j
],
913 pdp
->pd_optval
[i
].vd_name
) == 0) {
917 if (i
== pdp
->pd_noptval
)
918 return (DLADM_STATUS_BADVAL
);
920 (void) memcpy(&vdp
[j
], &pdp
->pd_optval
[i
], sizeof (val_desc_t
));
922 return (DLADM_STATUS_OK
);
925 static dladm_status_t
926 i_dladm_set_single_prop(dladm_handle_t handle
, datalink_id_t linkid
,
927 datalink_class_t
class, uint32_t media
, prop_desc_t
*pdp
, char **prop_val
,
928 uint_t val_cnt
, uint_t flags
)
930 dladm_status_t status
= DLADM_STATUS_OK
;
931 val_desc_t
*vdp
= NULL
;
932 boolean_t needfree
= B_FALSE
;
935 if (!(pdp
->pd_class
& class))
936 return (DLADM_STATUS_BADARG
);
938 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
939 return (DLADM_STATUS_BADARG
);
941 if ((flags
& DLADM_OPT_PERSIST
) && (pdp
->pd_flags
& PD_TEMPONLY
))
942 return (DLADM_STATUS_TEMPONLY
);
944 if (!(flags
& DLADM_OPT_ACTIVE
))
945 return (DLADM_STATUS_OK
);
947 if (pdp
->pd_set
== NULL
)
948 return (DLADM_STATUS_PROPRDONLY
);
950 if (prop_val
!= NULL
) {
951 vdp
= calloc(val_cnt
, sizeof (val_desc_t
));
953 return (DLADM_STATUS_NOMEM
);
955 if (pdp
->pd_check
!= NULL
) {
956 needfree
= ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0);
957 status
= pdp
->pd_check(handle
, pdp
, linkid
, prop_val
,
958 &val_cnt
, flags
, &vdp
, media
);
959 } else if (pdp
->pd_optval
!= NULL
) {
960 status
= check_prop(handle
, pdp
, linkid
, prop_val
,
961 &val_cnt
, flags
, &vdp
, media
);
963 status
= DLADM_STATUS_BADARG
;
966 if (status
!= DLADM_STATUS_OK
)
973 if (pdp
->pd_defval
.vd_name
== NULL
)
974 return (DLADM_STATUS_NOTSUP
);
977 defval
= (strlen(pdp
->pd_defval
.vd_name
) > 0);
978 if ((pdp
->pd_flags
& PD_CHECK_ALLOC
) == 0 && !defval
) {
979 status
= i_dladm_getset_defval(handle
, pdp
, linkid
,
984 vdp
= calloc(1, sizeof (val_desc_t
));
986 return (DLADM_STATUS_NOMEM
);
989 (void) memcpy(vdp
, &pdp
->pd_defval
,
990 sizeof (val_desc_t
));
991 } else if (pdp
->pd_check
!= NULL
) {
992 needfree
= ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0);
993 status
= pdp
->pd_check(handle
, pdp
, linkid
, prop_val
,
994 &cnt
, flags
, &vdp
, media
);
995 if (status
!= DLADM_STATUS_OK
)
999 if (pdp
->pd_flags
& PD_AFTER_PERM
)
1000 status
= (flags
& DLADM_OPT_PERSIST
) ? DLADM_STATUS_OK
:
1001 DLADM_STATUS_PERMONLY
;
1003 status
= pdp
->pd_set(handle
, pdp
, linkid
, vdp
, cnt
, flags
,
1006 for (i
= 0; i
< cnt
; i
++)
1007 free((void *)((val_desc_t
*)vdp
+ i
)->vd_val
);
1014 static dladm_status_t
1015 i_dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1016 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
1019 boolean_t found
= B_FALSE
;
1020 datalink_class_t
class;
1022 dladm_status_t status
= DLADM_STATUS_OK
;
1024 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1026 if (status
!= DLADM_STATUS_OK
)
1029 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1030 prop_desc_t
*pdp
= &prop_table
[i
];
1033 if (prop_name
!= NULL
&&
1034 (strcasecmp(prop_name
, pdp
->pd_name
) != 0))
1037 s
= i_dladm_set_single_prop(handle
, linkid
, class, media
, pdp
,
1038 prop_val
, val_cnt
, flags
);
1040 if (prop_name
!= NULL
) {
1044 if (s
!= DLADM_STATUS_OK
&&
1045 s
!= DLADM_STATUS_NOTSUP
)
1050 if (prop_name
[0] == '_') {
1051 /* other private properties */
1052 status
= i_dladm_set_private_prop(handle
, linkid
,
1053 prop_name
, prop_val
, val_cnt
, flags
);
1055 status
= DLADM_STATUS_NOTFOUND
;
1062 * Set/reset link property for specific link
1065 dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1066 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
1068 dladm_status_t status
= DLADM_STATUS_OK
;
1070 if ((linkid
== DATALINK_INVALID_LINKID
) || (flags
== 0) ||
1071 (prop_val
== NULL
&& val_cnt
> 0) ||
1072 (prop_val
!= NULL
&& val_cnt
== 0) ||
1073 (prop_name
== NULL
&& prop_val
!= NULL
)) {
1074 return (DLADM_STATUS_BADARG
);
1078 * Check for valid link property against the flags passed
1079 * and set the link property when active flag is passed.
1081 status
= i_dladm_set_linkprop(handle
, linkid
, prop_name
, prop_val
,
1083 if (status
!= DLADM_STATUS_OK
)
1086 if (flags
& DLADM_OPT_PERSIST
) {
1087 status
= i_dladm_set_linkprop_db(handle
, linkid
, prop_name
,
1090 if (status
== DLADM_STATUS_OK
&& (flags
& DLADM_OPT_ACTIVE
)) {
1091 prop_desc_t
*pdp
= prop_table
;
1094 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++, pdp
++) {
1095 if (!(pdp
->pd_flags
& PD_AFTER_PERM
))
1097 if (prop_name
!= NULL
&&
1098 strcasecmp(prop_name
, pdp
->pd_name
) != 0)
1100 status
= pdp
->pd_set(handle
, pdp
, linkid
, NULL
,
1109 * Walk all link properties of the given specific link.
1111 * Note: this function currently lacks the ability to walk _all_ private
1112 * properties if the link, because there is no kernel interface to
1113 * retrieve all known private property names. Once such an interface
1114 * is added, this function should be fixed accordingly.
1117 dladm_walk_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
,
1118 int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
1120 dladm_status_t status
;
1121 datalink_class_t
class;
1125 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
1126 return (DLADM_STATUS_BADARG
);
1128 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1130 if (status
!= DLADM_STATUS_OK
)
1134 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1135 if (!(prop_table
[i
].pd_class
& class))
1138 if (!DATALINK_MEDIA_ACCEPTED(prop_table
[i
].pd_dmedia
, media
))
1141 if (func(handle
, linkid
, prop_table
[i
].pd_name
, arg
) ==
1142 DLADM_WALK_TERMINATE
) {
1148 status
= i_dladm_walk_linkprop_priv_db(handle
, linkid
, arg
, func
);
1154 * Get linkprop of the given specific link.
1157 dladm_get_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1158 dladm_prop_type_t type
, const char *prop_name
, char **prop_val
,
1161 dladm_status_t status
= DLADM_STATUS_OK
;
1162 datalink_class_t
class;
1165 uint_t cnt
, dld_flags
= 0;
1169 if (type
== DLADM_PROP_VAL_DEFAULT
)
1170 dld_flags
|= DLD_PROP_DEFAULT
;
1171 else if (type
== DLADM_PROP_VAL_MODIFIABLE
)
1172 dld_flags
|= DLD_PROP_POSSIBLE
;
1174 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1175 prop_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1176 return (DLADM_STATUS_BADARG
);
1178 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++)
1179 if (strcasecmp(prop_name
, prop_table
[i
].pd_name
) == 0)
1182 if (i
== DLADM_MAX_PROPS
) {
1183 if (prop_name
[0] == '_') {
1187 if (type
== DLADM_PROP_VAL_PERSISTENT
)
1188 return (i_dladm_get_linkprop_db(handle
, linkid
,
1189 prop_name
, prop_val
, val_cntp
));
1191 return (i_dladm_get_priv_prop(handle
, linkid
,
1192 prop_name
, prop_val
, val_cntp
, type
,
1195 return (DLADM_STATUS_NOTFOUND
);
1199 pdp
= &prop_table
[i
];
1201 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1203 if (status
!= DLADM_STATUS_OK
)
1206 if (!(pdp
->pd_class
& class))
1207 return (DLADM_STATUS_BADARG
);
1209 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1210 return (DLADM_STATUS_BADARG
);
1213 case DLADM_PROP_VAL_CURRENT
:
1214 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1215 media
, dld_flags
, &perm_flags
);
1218 case DLADM_PROP_VAL_PERM
:
1219 if (pdp
->pd_set
== NULL
) {
1220 perm_flags
= MAC_PROP_PERM_READ
;
1222 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1223 val_cntp
, media
, dld_flags
, &perm_flags
);
1226 *prop_val
[0] = '\0';
1228 if (status
== DLADM_STATUS_OK
)
1229 (void) dladm_perm2str(perm_flags
, *prop_val
);
1232 case DLADM_PROP_VAL_DEFAULT
:
1234 * If defaults are not defined for the property,
1235 * pd_defval.vd_name should be null. If the driver
1236 * has to be contacted for the value, vd_name should
1237 * be the empty string (""). Otherwise, dladm will
1238 * just print whatever is in the table.
1240 if (pdp
->pd_defval
.vd_name
== NULL
) {
1241 status
= DLADM_STATUS_NOTSUP
;
1245 if (strlen(pdp
->pd_defval
.vd_name
) == 0) {
1246 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1247 val_cntp
, media
, dld_flags
, &perm_flags
);
1249 (void) strcpy(*prop_val
, pdp
->pd_defval
.vd_name
);
1254 case DLADM_PROP_VAL_MODIFIABLE
:
1255 if (pdp
->pd_getmod
!= NULL
) {
1256 status
= pdp
->pd_getmod(handle
, pdp
, linkid
, prop_val
,
1257 val_cntp
, media
, dld_flags
, &perm_flags
);
1260 cnt
= pdp
->pd_noptval
;
1262 status
= DLADM_STATUS_NOTSUP
;
1263 } else if (cnt
> *val_cntp
) {
1264 status
= DLADM_STATUS_TOOSMALL
;
1266 for (i
= 0; i
< cnt
; i
++) {
1267 (void) strcpy(prop_val
[i
],
1268 pdp
->pd_optval
[i
].vd_name
);
1273 case DLADM_PROP_VAL_PERSISTENT
:
1274 if (pdp
->pd_flags
& PD_TEMPONLY
)
1275 return (DLADM_STATUS_TEMPONLY
);
1276 status
= i_dladm_get_linkprop_db(handle
, linkid
, prop_name
,
1277 prop_val
, val_cntp
);
1280 status
= DLADM_STATUS_BADARG
;
1288 * Get linkprop of the given specific link and run any possible conversion
1289 * of the values using the check function for the property. Fails if the
1290 * check function doesn't succeed for the property value.
1293 dladm_get_linkprop_values(dladm_handle_t handle
, datalink_id_t linkid
,
1294 dladm_prop_type_t type
, const char *prop_name
, uint_t
*ret_val
,
1297 dladm_status_t status
;
1298 datalink_class_t
class;
1306 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1307 ret_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1308 return (DLADM_STATUS_BADARG
);
1310 for (pdp
= prop_table
; pdp
< prop_table
+ DLADM_MAX_PROPS
; pdp
++)
1311 if (strcasecmp(prop_name
, pdp
->pd_name
) == 0)
1314 if (pdp
== prop_table
+ DLADM_MAX_PROPS
)
1315 return (DLADM_STATUS_NOTFOUND
);
1317 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
1318 return (DLADM_STATUS_BADARG
);
1320 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1322 if (status
!= DLADM_STATUS_OK
)
1325 if (!(pdp
->pd_class
& class))
1326 return (DLADM_STATUS_BADARG
);
1328 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1329 return (DLADM_STATUS_BADARG
);
1331 prop_val
= malloc(*val_cntp
* sizeof (*prop_val
) +
1332 *val_cntp
* DLADM_PROP_VAL_MAX
);
1333 if (prop_val
== NULL
)
1334 return (DLADM_STATUS_NOMEM
);
1335 for (valc
= 0; valc
< *val_cntp
; valc
++)
1336 prop_val
[valc
] = (char *)(prop_val
+ *val_cntp
) +
1337 valc
* DLADM_PROP_VAL_MAX
;
1339 dld_flags
= (type
== DLADM_PROP_VAL_DEFAULT
) ? DLD_PROP_DEFAULT
: 0;
1342 case DLADM_PROP_VAL_CURRENT
:
1343 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1344 media
, dld_flags
, &perm_flags
);
1347 case DLADM_PROP_VAL_DEFAULT
:
1349 * If defaults are not defined for the property,
1350 * pd_defval.vd_name should be null. If the driver
1351 * has to be contacted for the value, vd_name should
1352 * be the empty string (""). Otherwise, dladm will
1353 * just print whatever is in the table.
1355 if (pdp
->pd_defval
.vd_name
== NULL
) {
1356 status
= DLADM_STATUS_NOTSUP
;
1360 if (pdp
->pd_defval
.vd_name
[0] != '\0') {
1362 *ret_val
= pdp
->pd_defval
.vd_val
;
1364 return (DLADM_STATUS_OK
);
1366 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1367 media
, dld_flags
, &perm_flags
);
1370 case DLADM_PROP_VAL_PERSISTENT
:
1371 if (pdp
->pd_flags
& PD_TEMPONLY
)
1372 status
= DLADM_STATUS_TEMPONLY
;
1374 status
= i_dladm_get_linkprop_db(handle
, linkid
,
1375 prop_name
, prop_val
, val_cntp
);
1379 status
= DLADM_STATUS_BADARG
;
1383 if (status
== DLADM_STATUS_OK
) {
1384 if (pdp
->pd_check
!= NULL
) {
1387 vdp
= malloc(sizeof (val_desc_t
) * *val_cntp
);
1389 status
= DLADM_STATUS_NOMEM
;
1391 status
= pdp
->pd_check(handle
, pdp
, linkid
,
1392 prop_val
, val_cntp
, 0, &vdp
, media
);
1393 if (status
== DLADM_STATUS_OK
) {
1394 for (valc
= 0; valc
< *val_cntp
; valc
++)
1395 ret_val
[valc
] = vdp
[valc
].vd_val
;
1399 for (valc
= 0; valc
< *val_cntp
; valc
++) {
1400 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
1401 if (strcmp(pdp
->pd_optval
[i
].vd_name
,
1402 prop_val
[valc
]) == 0) {
1404 pdp
->pd_optval
[i
].vd_val
;
1408 if (i
== pdp
->pd_noptval
) {
1409 status
= DLADM_STATUS_FAILED
;
1423 i_dladm_init_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
1424 const char *prop_name
, void *arg
)
1426 char *buf
, **propvals
;
1427 uint_t i
, valcnt
= DLADM_MAX_PROP_VALCNT
;
1428 dladm_status_t status
;
1429 dladm_linkprop_args_t
*dla
= arg
;
1431 if ((buf
= malloc((sizeof (char *) + DLADM_PROP_VAL_MAX
) *
1432 DLADM_MAX_PROP_VALCNT
)) == NULL
) {
1433 return (DLADM_WALK_CONTINUE
);
1436 propvals
= (char **)(void *)buf
;
1437 for (i
= 0; i
< valcnt
; i
++) {
1439 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
1440 i
* DLADM_PROP_VAL_MAX
;
1443 if (dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
1444 prop_name
, propvals
, &valcnt
) != DLADM_STATUS_OK
) {
1448 status
= dladm_set_linkprop(handle
, linkid
, prop_name
, propvals
,
1449 valcnt
, dla
->dla_flags
| DLADM_OPT_ACTIVE
);
1451 if (status
!= DLADM_STATUS_OK
)
1452 dla
->dla_status
= status
;
1457 return (DLADM_WALK_CONTINUE
);
1462 i_dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
)
1464 datalink_class_t
class;
1465 dladm_status_t status
;
1467 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, NULL
,
1469 if (status
!= DLADM_STATUS_OK
)
1470 return (DLADM_WALK_TERMINATE
);
1472 if ((class & (DATALINK_CLASS_VNIC
| DATALINK_CLASS_VLAN
)) == 0)
1473 (void) dladm_init_linkprop(handle
, linkid
, B_TRUE
);
1475 return (DLADM_WALK_CONTINUE
);
1479 dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1480 boolean_t any_media
)
1482 dladm_status_t status
= DLADM_STATUS_OK
;
1483 datalink_media_t dmedia
;
1485 dladm_linkprop_args_t
*dla
;
1487 dmedia
= any_media
? DATALINK_ANY_MEDIATYPE
: DL_WIFI
;
1489 dla
= malloc(sizeof (dladm_linkprop_args_t
));
1491 return (DLADM_STATUS_NOMEM
);
1492 dla
->dla_flags
= DLADM_OPT_BOOT
;
1493 dla
->dla_status
= DLADM_STATUS_OK
;
1495 if (linkid
== DATALINK_ALL_LINKID
) {
1496 (void) dladm_walk_datalink_id(i_dladm_init_linkprop
, handle
,
1497 NULL
, DATALINK_CLASS_ALL
, dmedia
, DLADM_OPT_PERSIST
);
1498 } else if (any_media
||
1499 ((dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, &media
, NULL
,
1500 0) == DLADM_STATUS_OK
) &&
1501 DATALINK_MEDIA_ACCEPTED(dmedia
, media
))) {
1502 (void) dladm_walk_linkprop(handle
, linkid
, (void *)dla
,
1503 i_dladm_init_one_prop
);
1504 status
= dla
->dla_status
;
1511 static dladm_status_t
1512 get_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1513 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1514 uint_t flags
, uint_t
*perm_flags
)
1516 char zone_name
[ZONENAME_MAX
];
1518 dladm_status_t status
;
1521 return (DLADM_STATUS_NOTSUP
);
1523 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1524 perm_flags
, &zid
, sizeof (zid
));
1525 if (status
!= DLADM_STATUS_OK
)
1529 if (zid
!= GLOBAL_ZONEID
) {
1530 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0) {
1531 return (dladm_errno2status(errno
));
1534 (void) strncpy(*prop_val
, zone_name
, DLADM_PROP_VAL_MAX
);
1536 *prop_val
[0] = '\0';
1539 return (DLADM_STATUS_OK
);
1542 typedef int (*zone_get_devroot_t
)(char *, char *, size_t);
1545 i_dladm_get_zone_dev(char *zone_name
, char *dev
, size_t devlen
)
1547 char root
[MAXPATHLEN
];
1548 zone_get_devroot_t real_zone_get_devroot
;
1553 if ((dlhandle
= dlopen("libzonecfg.so.1", RTLD_LAZY
)) == NULL
)
1556 if ((sym
= dlsym(dlhandle
, "zone_get_devroot")) == NULL
) {
1557 (void) dlclose(dlhandle
);
1561 real_zone_get_devroot
= (zone_get_devroot_t
)sym
;
1563 if ((ret
= real_zone_get_devroot(zone_name
, root
, sizeof (root
))) == 0)
1564 (void) snprintf(dev
, devlen
, "%s%s", root
, "/dev");
1565 (void) dlclose(dlhandle
);
1569 static dladm_status_t
1570 i_dladm_update_deventry(dladm_handle_t handle
, zoneid_t zid
,
1571 datalink_id_t linkid
, boolean_t add
)
1573 char path
[MAXPATHLEN
];
1574 char name
[MAXLINKNAMELEN
];
1575 di_prof_t prof
= NULL
;
1576 char zone_name
[ZONENAME_MAX
];
1577 dladm_status_t status
;
1580 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0)
1581 return (dladm_errno2status(errno
));
1582 if (i_dladm_get_zone_dev(zone_name
, path
, sizeof (path
)) != 0)
1583 return (dladm_errno2status(errno
));
1584 if (di_prof_init(path
, &prof
) != 0)
1585 return (dladm_errno2status(errno
));
1587 status
= dladm_linkid2legacyname(handle
, linkid
, name
, MAXLINKNAMELEN
);
1588 if (status
!= DLADM_STATUS_OK
)
1592 ret
= di_prof_add_dev(prof
, name
);
1594 ret
= di_prof_add_exclude(prof
, name
);
1597 status
= dladm_errno2status(errno
);
1601 if (di_prof_commit(prof
) != 0)
1602 status
= dladm_errno2status(errno
);
1611 static dladm_status_t
1612 set_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1613 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
1615 dladm_status_t status
= DLADM_STATUS_OK
;
1616 zoneid_t zid_old
, zid_new
;
1620 return (DLADM_STATUS_BADVALCNT
);
1622 dzp
= (dld_ioc_zid_t
*)vdp
->vd_val
;
1624 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1625 NULL
, &zid_old
, sizeof (zid_old
));
1626 if (status
!= DLADM_STATUS_OK
)
1629 zid_new
= dzp
->diz_zid
;
1630 if (zid_new
== zid_old
)
1631 return (DLADM_STATUS_OK
);
1633 if ((status
= set_public_prop(handle
, pdp
, linkid
, vdp
, val_cnt
,
1634 flags
, media
)) != DLADM_STATUS_OK
)
1638 * It is okay to fail to update the /dev entry (some vanity-named
1639 * links do not have a /dev entry).
1641 if (zid_old
!= GLOBAL_ZONEID
) {
1642 (void) i_dladm_update_deventry(handle
, zid_old
, linkid
,
1645 if (zid_new
!= GLOBAL_ZONEID
)
1646 (void) i_dladm_update_deventry(handle
, zid_new
, linkid
, B_TRUE
);
1648 return (DLADM_STATUS_OK
);
1652 static dladm_status_t
1653 check_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1654 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1655 datalink_media_t media
)
1659 dladm_status_t status
= DLADM_STATUS_OK
;
1661 uint_t val_cnt
= *val_cntp
;
1662 val_desc_t
*vdp
= *vdpp
;
1665 return (DLADM_STATUS_BADVALCNT
);
1667 dzp
= malloc(sizeof (dld_ioc_zid_t
));
1669 return (DLADM_STATUS_NOMEM
);
1671 zone_name
= (prop_val
!= NULL
) ? *prop_val
: GLOBAL_ZONENAME
;
1672 if ((zoneid
= getzoneidbyname(zone_name
)) == -1) {
1673 status
= DLADM_STATUS_BADVAL
;
1677 if (zoneid
!= GLOBAL_ZONEID
) {
1680 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &flags
,
1681 sizeof (flags
)) < 0) {
1682 status
= dladm_errno2status(errno
);
1686 if (!(flags
& ZF_NET_EXCL
)) {
1687 status
= DLADM_STATUS_BADVAL
;
1692 (void) memset(dzp
, 0, sizeof (dld_ioc_zid_t
));
1694 dzp
->diz_zid
= zoneid
;
1695 dzp
->diz_linkid
= linkid
;
1697 vdp
->vd_val
= (uintptr_t)dzp
;
1698 return (DLADM_STATUS_OK
);
1705 static dladm_status_t
1706 get_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1707 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1708 uint_t flags
, uint_t
*perm_flags
)
1710 mac_resource_props_t mrp
;
1711 dladm_status_t status
;
1713 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
1714 perm_flags
, &mrp
, sizeof (mrp
));
1715 if (status
!= DLADM_STATUS_OK
)
1718 if ((mrp
.mrp_mask
& MRP_MAXBW
) == 0) {
1720 return (DLADM_STATUS_OK
);
1723 (void) dladm_bw2str(mrp
.mrp_maxbw
, prop_val
[0]);
1725 return (DLADM_STATUS_OK
);
1729 static dladm_status_t
1730 check_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1731 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1732 datalink_media_t media
)
1735 dladm_status_t status
= DLADM_STATUS_OK
;
1736 uint_t val_cnt
= *val_cntp
;
1737 val_desc_t
*vdp
= *vdpp
;
1740 return (DLADM_STATUS_BADVALCNT
);
1742 maxbw
= malloc(sizeof (uint64_t));
1744 return (DLADM_STATUS_NOMEM
);
1746 status
= dladm_str2bw(*prop_val
, maxbw
);
1747 if (status
!= DLADM_STATUS_OK
) {
1752 if ((*maxbw
< MRP_MAXBW_MINVAL
) && (*maxbw
!= 0)) {
1754 return (DLADM_STATUS_MINMAXBW
);
1757 vdp
->vd_val
= (uintptr_t)maxbw
;
1758 return (DLADM_STATUS_OK
);
1763 extract_maxbw(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1765 mac_resource_props_t
*mrp
= arg
;
1767 if (vdp
->vd_val
== RESET_VAL
) {
1768 mrp
->mrp_maxbw
= MRP_MAXBW_RESETVAL
;
1770 bcopy((char *)vdp
->vd_val
, &mrp
->mrp_maxbw
, sizeof (uint64_t));
1772 mrp
->mrp_mask
|= MRP_MAXBW
;
1774 return (DLADM_STATUS_OK
);
1778 static dladm_status_t
1779 get_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1780 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1781 uint_t flags
, uint_t
*perm_flags
)
1783 dladm_status_t status
;
1784 mac_resource_props_t mrp
;
1785 mac_propval_range_t
*pv_range
;
1788 if (strcmp(pdp
->pd_name
, "cpus-effective") == 0) {
1789 status
= i_dladm_get_public_prop(handle
, linkid
,
1790 "resource-effective", flags
, perm_flags
, &mrp
,
1793 status
= i_dladm_get_public_prop(handle
, linkid
,
1794 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1797 if (status
!= DLADM_STATUS_OK
)
1800 if (mrp
.mrp_ncpus
> *val_cnt
)
1801 return (DLADM_STATUS_TOOSMALL
);
1803 if (mrp
.mrp_ncpus
== 0) {
1805 return (DLADM_STATUS_OK
);
1808 /* Sort CPU list and convert it to a mac_propval_range */
1809 status
= dladm_list2range(mrp
.mrp_cpu
, mrp
.mrp_ncpus
,
1810 MAC_PROPVAL_UINT32
, &pv_range
);
1811 if (status
!= DLADM_STATUS_OK
)
1814 /* Write CPU ranges and individual CPUs */
1815 err
= dladm_range2strs(pv_range
, prop_val
);
1818 return (dladm_errno2status(err
));
1821 *val_cnt
= pv_range
->mpr_count
;
1824 return (DLADM_STATUS_OK
);
1828 static dladm_status_t
1829 check_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1830 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1831 datalink_media_t media
)
1834 long nproc
= sysconf(_SC_NPROCESSORS_CONF
);
1835 mac_resource_props_t mrp
;
1836 mac_propval_range_t
*pv_range
;
1839 uint32_t *cpus
= mrp
.mrp_cpu
;
1840 val_desc_t
*vdp
= *vdpp
;
1842 uint_t val_cnt
= *val_cntp
;
1843 dladm_status_t status
= DLADM_STATUS_OK
;
1845 /* Get the current pool property */
1846 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
1847 &perm_flags
, &mrp
, sizeof (mrp
));
1849 if (status
== DLADM_STATUS_OK
) {
1850 /* Can't set cpus if a pool is set */
1851 if (strlen(mrp
.mrp_pool
) != 0)
1852 return (DLADM_STATUS_POOLCPU
);
1855 /* Read ranges and convert to mac_propval_range */
1856 status
= dladm_strs2range(prop_val
, val_cnt
, MAC_PROPVAL_UINT32
,
1858 if (status
!= DLADM_STATUS_OK
)
1861 /* Convert mac_propval_range to a single CPU list */
1863 status
= dladm_range2list(pv_range
, cpus
, &ncpus
);
1864 if (status
!= DLADM_STATUS_OK
)
1868 * If a range of CPUs was entered, update value count and reallocate
1869 * the array of val_desc_t's. The array allocated was sized for
1870 * indvidual elements, but needs to be reallocated to accomodate the
1871 * expanded list of CPUs.
1873 if (val_cnt
< ncpus
) {
1874 newvdp
= calloc(*val_cntp
, sizeof (val_desc_t
));
1875 if (newvdp
== NULL
) {
1876 status
= DLADM_STATUS_NOMEM
;
1882 /* Check if all CPUs in the list are online */
1883 for (i
= 0; i
< ncpus
; i
++) {
1884 if (cpus
[i
] >= nproc
) {
1885 status
= DLADM_STATUS_BADCPUID
;
1889 rc
= p_online(cpus
[i
], P_STATUS
);
1891 status
= DLADM_STATUS_CPUERR
;
1895 if (rc
!= P_ONLINE
) {
1896 status
= DLADM_STATUS_CPUNOTONLINE
;
1900 vdp
[i
].vd_val
= (uintptr_t)cpus
[i
];
1903 /* Check for duplicate CPUs */
1904 for (i
= 0; i
< *val_cntp
; i
++) {
1905 for (j
= 0; j
< *val_cntp
; j
++) {
1906 if (i
!= j
&& vdp
[i
].vd_val
== vdp
[j
].vd_val
) {
1907 status
= DLADM_STATUS_BADVAL
;
1913 /* Update *val_cntp and *vdpp if everything was OK */
1914 if (val_cnt
< ncpus
) {
1920 status
= DLADM_STATUS_OK
;
1932 extract_cpus(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1934 mac_resource_props_t
*mrp
= arg
;
1937 if (vdp
[0].vd_val
== RESET_VAL
) {
1938 bzero(&mrp
->mrp_cpus
, sizeof (mac_cpus_t
));
1939 mrp
->mrp_mask
|= MRP_CPUS
;
1940 return (DLADM_STATUS_OK
);
1943 for (i
= 0; i
< cnt
; i
++)
1944 mrp
->mrp_cpu
[i
] = (uint32_t)vdp
[i
].vd_val
;
1946 mrp
->mrp_ncpus
= cnt
;
1947 mrp
->mrp_mask
|= (MRP_CPUS
|MRP_CPUS_USERSPEC
);
1948 mrp
->mrp_fanout_mode
= MCM_CPUS
;
1949 mrp
->mrp_rx_intr_cpu
= -1;
1951 return (DLADM_STATUS_OK
);
1955 * Get the pool datalink property from the kernel. This is used
1956 * for both the user specified pool and effective pool properties.
1959 static dladm_status_t
1960 get_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1961 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1962 uint_t flags
, uint_t
*perm_flags
)
1964 mac_resource_props_t mrp
;
1965 dladm_status_t status
;
1967 if (strcmp(pdp
->pd_name
, "pool-effective") == 0) {
1968 status
= i_dladm_get_public_prop(handle
, linkid
,
1969 "resource-effective", flags
, perm_flags
, &mrp
,
1972 status
= i_dladm_get_public_prop(handle
, linkid
,
1973 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1976 if (status
!= DLADM_STATUS_OK
)
1979 if (strlen(mrp
.mrp_pool
) == 0) {
1980 (*prop_val
)[0] = '\0';
1982 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
1983 "%s", mrp
.mrp_pool
);
1987 return (DLADM_STATUS_OK
);
1991 static dladm_status_t
1992 check_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1993 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1994 datalink_media_t media
)
1996 pool_conf_t
*poolconf
;
1998 mac_resource_props_t mrp
;
1999 dladm_status_t status
;
2002 val_desc_t
*vdp
= *vdpp
;
2004 /* Get the current cpus property */
2005 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
2006 &perm_flags
, &mrp
, sizeof (mrp
));
2008 if (status
== DLADM_STATUS_OK
) {
2009 /* Can't set pool if cpus are set */
2010 if (mrp
.mrp_ncpus
!= 0)
2011 return (DLADM_STATUS_POOLCPU
);
2014 poolname
= malloc(sizeof (mrp
.mrp_pool
));
2015 if (poolname
== NULL
)
2016 return (DLADM_STATUS_NOMEM
);
2018 /* Check for pool's availability if not booting */
2019 if ((flags
& DLADM_OPT_BOOT
) == 0) {
2021 /* Allocate and open pool configuration */
2022 if ((poolconf
= pool_conf_alloc()) == NULL
)
2023 return (DLADM_STATUS_BADVAL
);
2025 if (pool_conf_open(poolconf
, pool_dynamic_location(), PO_RDONLY
)
2027 pool_conf_free(poolconf
);
2028 return (DLADM_STATUS_BADVAL
);
2031 /* Look for pool name */
2032 if ((pool
= pool_get_pool(poolconf
, *prop_val
)) == NULL
) {
2033 pool_conf_free(poolconf
);
2034 return (DLADM_STATUS_BADVAL
);
2037 pool_conf_free(poolconf
);
2041 (void) strlcpy(poolname
, *prop_val
, sizeof (mrp
.mrp_pool
));
2042 vdp
->vd_val
= (uintptr_t)poolname
;
2044 return (DLADM_STATUS_OK
);
2049 extract_pool(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2051 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2053 if (vdp
->vd_val
== RESET_VAL
) {
2054 bzero(&mrp
->mrp_pool
, sizeof (mrp
->mrp_pool
));
2055 mrp
->mrp_mask
|= MRP_POOL
;
2056 return (DLADM_STATUS_OK
);
2059 (void) strlcpy(mrp
->mrp_pool
, (char *)vdp
->vd_val
,
2060 sizeof (mrp
->mrp_pool
));
2061 mrp
->mrp_mask
|= MRP_POOL
;
2063 * Use MCM_CPUS since the fanout count is not user specified
2064 * and will be determined by the cpu list generated from the
2067 mrp
->mrp_fanout_mode
= MCM_CPUS
;
2069 return (DLADM_STATUS_OK
);
2073 static dladm_status_t
2074 get_priority(dladm_handle_t handle
, prop_desc_t
*pdp
,
2075 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2076 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2078 mac_resource_props_t mrp
;
2079 mac_priority_level_t pri
;
2080 dladm_status_t status
;
2082 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2083 perm_flags
, &mrp
, sizeof (mrp
));
2084 if (status
!= DLADM_STATUS_OK
)
2087 pri
= ((mrp
.mrp_mask
& MRP_PRIORITY
) == 0) ? MPL_HIGH
:
2090 (void) dladm_pri2str(pri
, prop_val
[0]);
2092 return (DLADM_STATUS_OK
);
2097 extract_priority(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2099 mac_resource_props_t
*mrp
= arg
;
2102 return (DLADM_STATUS_BADVAL
);
2104 mrp
->mrp_priority
= (mac_priority_level_t
)vdp
->vd_val
;
2105 mrp
->mrp_mask
|= MRP_PRIORITY
;
2107 return (DLADM_STATUS_OK
);
2111 * Determines the size of the structure that needs to be sent to drivers
2112 * for retrieving the property range values.
2115 i_dladm_range_size(mac_propval_range_t
*r
, size_t *sz
, uint_t
*rcount
)
2117 uint_t count
= r
->mpr_count
;
2119 *sz
= sizeof (mac_propval_range_t
);
2123 switch (r
->mpr_type
) {
2124 case MAC_PROPVAL_UINT32
:
2125 *sz
+= (count
* sizeof (mac_propval_uint32_range_t
));
2137 static dladm_status_t
2138 check_rings(dladm_handle_t handle
, prop_desc_t
*pdp
,
2139 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2140 val_desc_t
**vp
, datalink_media_t media
)
2142 uint_t val_cnt
= *val_cntp
;
2143 val_desc_t
*v
= *vp
;
2146 return (DLADM_STATUS_BADVAL
);
2147 if (strncasecmp(prop_val
[0], "hw", strlen("hw")) == 0) {
2148 v
->vd_val
= UNSPEC_VAL
;
2149 } else if (strncasecmp(prop_val
[0], "sw", strlen("sw")) == 0) {
2152 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
2154 return (DLADM_STATUS_BADVAL
);
2156 return (DLADM_STATUS_OK
);
2160 static dladm_status_t
2161 get_rings_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
2162 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2163 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2165 dld_ioc_macprop_t
*dip
;
2166 dladm_status_t status
= DLADM_STATUS_OK
;
2167 mac_propval_range_t
*rangep
;
2169 mac_propval_uint32_range_t
*ur
;
2171 sz
= sizeof (mac_propval_range_t
);
2173 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
2177 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
2178 if (status
!= DLADM_STATUS_OK
)
2181 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
2183 ur
= &rangep
->mpr_range_uint32
[0];
2184 /* This is the case where the dev doesn't have any rings/groups */
2185 if (rangep
->mpr_count
== 0) {
2186 (*prop_val
)[0] = '\0';
2188 * This is the case where the dev supports rings, but static
2191 } else if (ur
->mpur_min
== ur
->mpur_max
&&
2192 ur
->mpur_max
== 0) {
2193 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw");
2195 * This is the case where the dev supports rings and dynamic
2196 * grouping, but has only one value (say 2 rings and 2 groups).
2198 } else if (ur
->mpur_min
== ur
->mpur_max
) {
2199 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw,%d",
2202 * This is the case where the dev supports rings and dynamic
2203 * grouping and has a range of rings.
2206 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
,
2207 "sw,hw,<%ld-%ld>", ur
->mpur_min
, ur
->mpur_max
);
2215 static dladm_status_t
2216 get_rxrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2217 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2218 uint_t flags
, uint_t
*perm_flags
)
2220 mac_resource_props_t mrp
;
2221 dladm_status_t status
;
2222 uint32_t nrings
= 0;
2225 * Get the number of (effective-)rings from the resource property.
2227 if (strcmp(pdp
->pd_name
, "rxrings-effective") == 0) {
2228 status
= i_dladm_get_public_prop(handle
, linkid
,
2229 "resource-effective", flags
, perm_flags
, &mrp
,
2233 * Get the permissions from the "rxrings" property.
2235 status
= i_dladm_get_public_prop(handle
, linkid
, "rxrings",
2236 flags
, perm_flags
, NULL
, 0);
2237 if (status
!= DLADM_STATUS_OK
)
2240 status
= i_dladm_get_public_prop(handle
, linkid
,
2241 "resource", flags
, NULL
, &mrp
, sizeof (mrp
));
2244 if (status
!= DLADM_STATUS_OK
)
2247 if ((mrp
.mrp_mask
& MRP_RX_RINGS
) == 0) {
2249 return (DLADM_STATUS_OK
);
2251 nrings
= mrp
.mrp_nrxrings
;
2253 if (mrp
.mrp_mask
& MRP_RXRINGS_UNSPEC
)
2254 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2255 else if (nrings
== 0)
2256 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2258 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2259 return (DLADM_STATUS_OK
);
2264 extract_rxrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2266 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2268 mrp
->mrp_nrxrings
= 0;
2269 if (vdp
->vd_val
== RESET_VAL
)
2270 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2271 else if (vdp
->vd_val
== UNSPEC_VAL
)
2272 mrp
->mrp_mask
= MRP_RXRINGS_UNSPEC
;
2274 mrp
->mrp_nrxrings
= vdp
->vd_val
;
2275 mrp
->mrp_mask
|= MRP_RX_RINGS
;
2277 return (DLADM_STATUS_OK
);
2281 static dladm_status_t
2282 get_txrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2283 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2284 uint_t flags
, uint_t
*perm_flags
)
2286 mac_resource_props_t mrp
;
2287 dladm_status_t status
;
2288 uint32_t nrings
= 0;
2292 * Get the number of (effective-)rings from the resource property.
2294 if (strcmp(pdp
->pd_name
, "txrings-effective") == 0) {
2295 status
= i_dladm_get_public_prop(handle
, linkid
,
2296 "resource-effective", flags
, perm_flags
, &mrp
,
2300 * Get the permissions from the "txrings" property.
2302 status
= i_dladm_get_public_prop(handle
, linkid
, "txrings",
2303 flags
, perm_flags
, NULL
, 0);
2304 if (status
!= DLADM_STATUS_OK
)
2308 * Get the number of rings from the "resource" property.
2310 status
= i_dladm_get_public_prop(handle
, linkid
, "resource",
2311 flags
, NULL
, &mrp
, sizeof (mrp
));
2314 if (status
!= DLADM_STATUS_OK
)
2317 if ((mrp
.mrp_mask
& MRP_TX_RINGS
) == 0) {
2319 return (DLADM_STATUS_OK
);
2321 nrings
= mrp
.mrp_ntxrings
;
2323 if (mrp
.mrp_mask
& MRP_TXRINGS_UNSPEC
)
2324 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2325 else if (nrings
== 0)
2326 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2328 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2329 return (DLADM_STATUS_OK
);
2334 extract_txrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2336 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2338 mrp
->mrp_ntxrings
= 0;
2339 if (vdp
->vd_val
== RESET_VAL
)
2340 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2341 else if (vdp
->vd_val
== UNSPEC_VAL
)
2342 mrp
->mrp_mask
= MRP_TXRINGS_UNSPEC
;
2344 mrp
->mrp_ntxrings
= vdp
->vd_val
;
2345 mrp
->mrp_mask
|= MRP_TX_RINGS
;
2347 return (DLADM_STATUS_OK
);
2351 static dladm_status_t
2352 get_cntavail(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2353 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
2356 if (flags
& DLD_PROP_DEFAULT
)
2357 return (DLADM_STATUS_NOTDEFINED
);
2359 return (get_uint32(handle
, pdp
, linkid
, prop_val
, val_cnt
, media
,
2360 flags
, perm_flags
));
2364 static dladm_status_t
2365 set_resource(dladm_handle_t handle
, prop_desc_t
*pdp
,
2366 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
2367 uint_t flags
, datalink_media_t media
)
2369 mac_resource_props_t mrp
;
2370 dladm_status_t status
= DLADM_STATUS_OK
;
2371 dld_ioc_macprop_t
*dip
;
2374 bzero(&mrp
, sizeof (mac_resource_props_t
));
2375 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "resource",
2381 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
2382 resource_prop_t
*rp
= &rsrc_prop_table
[i
];
2384 if (strcmp(pdp
->pd_name
, rp
->rp_name
) != 0)
2387 status
= rp
->rp_extract(vdp
, val_cnt
, &mrp
);
2388 if (status
!= DLADM_STATUS_OK
)
2394 (void) memcpy(dip
->pr_val
, &mrp
, dip
->pr_valsize
);
2395 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
2403 static dladm_status_t
2404 get_protection(dladm_handle_t handle
, prop_desc_t
*pdp
,
2405 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2406 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2408 mac_resource_props_t mrp
;
2410 dladm_status_t status
;
2411 uint32_t i
, cnt
= 0, setbits
[32];
2413 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2414 perm_flags
, &mrp
, sizeof (mrp
));
2415 if (status
!= DLADM_STATUS_OK
)
2418 p
= &mrp
.mrp_protect
;
2419 if ((mrp
.mrp_mask
& MRP_PROTECT
) == 0) {
2421 return (DLADM_STATUS_OK
);
2423 dladm_find_setbits32(p
->mp_types
, setbits
, &cnt
);
2425 return (DLADM_STATUS_BADVALCNT
);
2427 for (i
= 0; i
< cnt
; i
++)
2428 (void) dladm_protect2str(setbits
[i
], prop_val
[i
]);
2431 return (DLADM_STATUS_OK
);
2435 static dladm_status_t
2436 get_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2437 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2438 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2440 mac_resource_props_t mrp
;
2442 dladm_status_t status
;
2445 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2446 perm_flags
, &mrp
, sizeof (mrp
));
2447 if (status
!= DLADM_STATUS_OK
)
2450 p
= &mrp
.mrp_protect
;
2451 if (p
->mp_ipaddrcnt
== 0) {
2453 return (DLADM_STATUS_OK
);
2455 if (p
->mp_ipaddrcnt
> *val_cnt
)
2456 return (DLADM_STATUS_BADVALCNT
);
2458 for (i
= 0; i
< p
->mp_ipaddrcnt
; i
++) {
2460 if (p
->mp_ipaddrs
[i
].ip_version
== IPV4_VERSION
) {
2463 v4addr
= V4_PART_OF_V6(p
->mp_ipaddrs
[i
].ip_addr
);
2464 (void) dladm_ipv4addr2str(&v4addr
, prop_val
[i
]);
2466 (void) dladm_ipv6addr2str(&p
->mp_ipaddrs
[i
].ip_addr
,
2469 len
= strlen(prop_val
[i
]);
2470 (void) sprintf(prop_val
[i
] + len
, "/%d",
2471 p
->mp_ipaddrs
[i
].ip_netmask
);
2473 *val_cnt
= p
->mp_ipaddrcnt
;
2474 return (DLADM_STATUS_OK
);
2478 extract_protection(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2480 mac_resource_props_t
*mrp
= arg
;
2484 for (i
= 0; i
< cnt
; i
++)
2485 types
|= (uint32_t)vdp
[i
].vd_val
;
2487 mrp
->mrp_protect
.mp_types
= types
;
2488 mrp
->mrp_mask
|= MRP_PROTECT
;
2489 return (DLADM_STATUS_OK
);
2493 extract_allowedips(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2495 mac_resource_props_t
*mrp
= arg
;
2496 mac_protect_t
*p
= &mrp
->mrp_protect
;
2499 if (vdp
->vd_val
== 0) {
2502 for (i
= 0; i
< cnt
; i
++) {
2503 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_ipaddrs
[i
],
2504 sizeof (mac_ipaddr_t
));
2507 p
->mp_ipaddrcnt
= cnt
;
2508 mrp
->mrp_mask
|= MRP_PROTECT
;
2509 return (DLADM_STATUS_OK
);
2512 static dladm_status_t
2513 check_single_ip(char *buf
, mac_ipaddr_t
*addr
)
2515 dladm_status_t status
;
2518 boolean_t isv4
= B_TRUE
;
2523 * If the IP address is in CIDR format, parse the bits component
2524 * seperately. An address in this style will be used to indicate an
2525 * entire subnet, so it must be a network number with no host address.
2527 if ((p
= strchr(buf
, '/')) != NULL
) {
2532 return (DLADM_STATUS_INVALID_IP
);
2533 mask
= strtol(p
, &end
, 10);
2534 if (end
!= NULL
&& *end
!= '\0')
2535 return (DLADM_STATUS_INVALID_IP
);
2536 if (mask
> 128|| mask
< 1)
2537 return (DLADM_STATUS_INVALID_IP
);
2540 status
= dladm_str2ipv4addr(buf
, &v4addr
);
2541 if (status
== DLADM_STATUS_INVALID_IP
) {
2542 status
= dladm_str2ipv6addr(buf
, &v6addr
);
2543 if (status
== DLADM_STATUS_OK
)
2546 if (status
!= DLADM_STATUS_OK
)
2550 if (v4addr
== INADDR_ANY
)
2551 return (DLADM_STATUS_INVALID_IP
);
2553 IN6_IPADDR_TO_V4MAPPED(v4addr
, &addr
->ip_addr
);
2554 addr
->ip_version
= IPV4_VERSION
;
2559 * Validate the netmask is in the proper range for v4
2561 if (mask
> 32 || mask
< 1)
2562 return (DLADM_STATUS_INVALID_IP
);
2565 * We have a CIDR style address, confirm that only the
2566 * network number is set.
2568 smask
= 0xFFFFFFFFu
<< (32 - mask
);
2569 if (htonl(v4addr
) & ~smask
)
2570 return (DLADM_STATUS_INVALID_IP
);
2574 addr
->ip_netmask
= mask
;
2576 if (IN6_IS_ADDR_UNSPECIFIED(&v6addr
))
2577 return (DLADM_STATUS_INVALID_IP
);
2579 if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr
))
2580 return (DLADM_STATUS_INVALID_IP
);
2586 * Note that the address in our buffer is stored in
2587 * network byte order.
2590 for (i
= 3; i
>= 0; i
--) {
2591 high
= ffsl(ntohl(v6addr
._S6_un
._S6_u32
[i
]));
2597 if (128 - off
>= mask
)
2598 return (DLADM_STATUS_INVALID_IP
);
2603 addr
->ip_addr
= v6addr
;
2604 addr
->ip_version
= IPV6_VERSION
;
2605 addr
->ip_netmask
= mask
;
2607 return (DLADM_STATUS_OK
);
2611 static dladm_status_t
2612 check_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2613 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2614 val_desc_t
**vdpp
, datalink_media_t media
)
2616 dladm_status_t status
;
2619 uint_t val_cnt
= *val_cntp
;
2620 val_desc_t
*vdp
= *vdpp
;
2622 if (val_cnt
> MPT_MAXIPADDR
)
2623 return (DLADM_STATUS_BADVALCNT
);
2625 for (i
= 0; i
< val_cnt
; i
++) {
2626 if ((addr
= calloc(1, sizeof (mac_ipaddr_t
))) == NULL
) {
2627 status
= DLADM_STATUS_NOMEM
;
2630 vdp
[i
].vd_val
= (uintptr_t)addr
;
2632 status
= check_single_ip(prop_val
[i
], addr
);
2633 if (status
!= DLADM_STATUS_OK
)
2636 return (DLADM_STATUS_OK
);
2639 for (i
= 0; i
< val_cnt
; i
++) {
2640 free((void *)vdp
[i
].vd_val
);
2641 vdp
[i
].vd_val
= (uintptr_t)NULL
;
2647 dladm_cid2str(mac_dhcpcid_t
*cid
, char *buf
)
2649 char tmp_buf
[DLADM_STRSIZE
];
2652 switch (cid
->dc_form
) {
2653 case CIDFORM_TYPED
: {
2654 uint16_t duidtype
, hwtype
;
2655 uint32_t timestamp
, ennum
;
2658 if (cid
->dc_len
< sizeof (duidtype
))
2661 bcopy(cid
->dc_id
, &duidtype
, sizeof (duidtype
));
2662 duidtype
= ntohs(duidtype
);
2664 case DHCPV6_DUID_LLT
: {
2667 if (cid
->dc_len
< sizeof (llt
))
2670 bcopy(cid
->dc_id
, &llt
, sizeof (llt
));
2671 hwtype
= ntohs(llt
.dllt_hwtype
);
2672 timestamp
= ntohl(llt
.dllt_time
);
2673 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (llt
),
2674 NULL
, cid
->dc_len
- sizeof (llt
), IFT_OTHER
);
2678 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%d.%s",
2679 duidtype
, hwtype
, timestamp
, lladdr
);
2683 case DHCPV6_DUID_EN
: {
2686 if (cid
->dc_len
< sizeof (en
))
2689 bcopy(cid
->dc_id
, &en
, sizeof (en
));
2690 ennum
= DHCPV6_GET_ENTNUM(&en
);
2691 hexlen
= sizeof (tmp_buf
);
2692 if (octet_to_hexascii(cid
->dc_id
+ sizeof (en
),
2693 cid
->dc_len
- sizeof (en
), tmp_buf
, &hexlen
) != 0)
2696 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2697 duidtype
, ennum
, tmp_buf
);
2700 case DHCPV6_DUID_LL
: {
2703 if (cid
->dc_len
< sizeof (ll
))
2706 bcopy(cid
->dc_id
, &ll
, sizeof (ll
));
2707 hwtype
= ntohs(ll
.dll_hwtype
);
2708 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (ll
),
2709 NULL
, cid
->dc_len
- sizeof (ll
), IFT_OTHER
);
2713 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2714 duidtype
, hwtype
, lladdr
);
2719 hexlen
= sizeof (tmp_buf
);
2720 if (octet_to_hexascii(cid
->dc_id
+ sizeof (duidtype
),
2721 cid
->dc_len
- sizeof (duidtype
),
2722 tmp_buf
, &hexlen
) != 0)
2725 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%s",
2732 hexlen
= sizeof (tmp_buf
);
2733 if (octet_to_hexascii(cid
->dc_id
, cid
->dc_len
,
2734 tmp_buf
, &hexlen
) != 0)
2737 (void) snprintf(buf
, DLADM_STRSIZE
, "0x%s", tmp_buf
);
2743 for (i
= 0; i
< cid
->dc_len
; i
++) {
2744 if (!isprint(cid
->dc_id
[i
]))
2747 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", cid
->dc_id
);
2756 (void) snprintf(buf
, DLADM_STRSIZE
, "<unknown>");
2759 static dladm_status_t
2760 dladm_str2cid(char *buf
, mac_dhcpcid_t
*cid
)
2763 char tmp_buf
[DLADM_STRSIZE
];
2764 uint_t hexlen
, cidlen
;
2766 bzero(cid
, sizeof (*cid
));
2767 if (isdigit(*ptr
) &&
2768 ptr
[strspn(ptr
, "0123456789")] == '.') {
2777 duidtype
= strtoul(ptr
, &cp
, 0);
2778 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.' ||
2779 duidtype
> USHRT_MAX
)
2780 return (DLADM_STATUS_BADARG
);
2783 if (duidtype
!= 0 && duidtype
<= DHCPV6_DUID_LL
) {
2785 subtype
= strtoul(ptr
, &cp
, 0);
2786 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2787 return (DLADM_STATUS_BADARG
);
2791 case DHCPV6_DUID_LLT
: {
2795 timestamp
= strtoul(ptr
, &cp
, 0);
2796 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2797 return (DLADM_STATUS_BADARG
);
2800 lladdr
= _link_aton(ptr
, &addrlen
);
2802 return (DLADM_STATUS_BADARG
);
2804 cidlen
= sizeof (llt
) + addrlen
;
2805 if (cidlen
> sizeof (cid
->dc_id
)) {
2807 return (DLADM_STATUS_TOOSMALL
);
2809 llt
.dllt_dutype
= htons(duidtype
);
2810 llt
.dllt_hwtype
= htons(subtype
);
2811 llt
.dllt_time
= htonl(timestamp
);
2812 bcopy(&llt
, cid
->dc_id
, sizeof (llt
));
2813 bcopy(lladdr
, cid
->dc_id
+ sizeof (llt
), addrlen
);
2817 case DHCPV6_DUID_LL
: {
2820 lladdr
= _link_aton(ptr
, &addrlen
);
2822 return (DLADM_STATUS_BADARG
);
2824 cidlen
= sizeof (ll
) + addrlen
;
2825 if (cidlen
> sizeof (cid
->dc_id
)) {
2827 return (DLADM_STATUS_TOOSMALL
);
2829 ll
.dll_dutype
= htons(duidtype
);
2830 ll
.dll_hwtype
= htons(subtype
);
2831 bcopy(&ll
, cid
->dc_id
, sizeof (ll
));
2832 bcopy(lladdr
, cid
->dc_id
+ sizeof (ll
), addrlen
);
2837 hexlen
= sizeof (tmp_buf
);
2838 if (hexascii_to_octet(ptr
, strlen(ptr
),
2839 tmp_buf
, &hexlen
) != 0)
2840 return (DLADM_STATUS_BADARG
);
2842 if (duidtype
== DHCPV6_DUID_EN
) {
2845 en
.den_dutype
= htons(duidtype
);
2846 DHCPV6_SET_ENTNUM(&en
, subtype
);
2848 cidlen
= sizeof (en
) + hexlen
;
2849 if (cidlen
> sizeof (cid
->dc_id
))
2850 return (DLADM_STATUS_TOOSMALL
);
2852 bcopy(&en
, cid
->dc_id
, sizeof (en
));
2853 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (en
),
2856 uint16_t dutype
= htons(duidtype
);
2858 cidlen
= sizeof (dutype
) + hexlen
;
2859 if (cidlen
> sizeof (cid
->dc_id
))
2860 return (DLADM_STATUS_TOOSMALL
);
2862 bcopy(&dutype
, cid
->dc_id
, sizeof (dutype
));
2863 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (dutype
),
2869 cid
->dc_form
= CIDFORM_TYPED
;
2870 } else if (strncasecmp("0x", ptr
, 2) == 0 && ptr
[2] != '\0') {
2872 hexlen
= sizeof (tmp_buf
);
2873 if (hexascii_to_octet(ptr
, strlen(ptr
), tmp_buf
,
2875 return (DLADM_STATUS_BADARG
);
2878 if (cidlen
> sizeof (cid
->dc_id
))
2879 return (DLADM_STATUS_TOOSMALL
);
2881 bcopy(tmp_buf
, cid
->dc_id
, cidlen
);
2882 cid
->dc_form
= CIDFORM_HEX
;
2884 cidlen
= strlen(ptr
);
2885 if (cidlen
> sizeof (cid
->dc_id
))
2886 return (DLADM_STATUS_TOOSMALL
);
2888 bcopy(ptr
, cid
->dc_id
, cidlen
);
2889 cid
->dc_form
= CIDFORM_STR
;
2891 cid
->dc_len
= cidlen
;
2892 return (DLADM_STATUS_OK
);
2896 static dladm_status_t
2897 get_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2898 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2899 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2901 mac_resource_props_t mrp
;
2903 dladm_status_t status
;
2906 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2907 perm_flags
, &mrp
, sizeof (mrp
));
2908 if (status
!= DLADM_STATUS_OK
)
2911 p
= &mrp
.mrp_protect
;
2912 if (p
->mp_cidcnt
== 0) {
2914 return (DLADM_STATUS_OK
);
2916 if (p
->mp_cidcnt
> *val_cnt
)
2917 return (DLADM_STATUS_BADVALCNT
);
2919 for (i
= 0; i
< p
->mp_cidcnt
; i
++) {
2920 mac_dhcpcid_t
*cid
= &p
->mp_cids
[i
];
2922 dladm_cid2str(cid
, prop_val
[i
]);
2924 *val_cnt
= p
->mp_cidcnt
;
2925 return (DLADM_STATUS_OK
);
2929 extract_allowedcids(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2931 mac_resource_props_t
*mrp
= arg
;
2932 mac_protect_t
*p
= &mrp
->mrp_protect
;
2935 if (vdp
->vd_val
== 0) {
2938 for (i
= 0; i
< cnt
; i
++) {
2939 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_cids
[i
],
2940 sizeof (mac_dhcpcid_t
));
2944 mrp
->mrp_mask
|= MRP_PROTECT
;
2945 return (DLADM_STATUS_OK
);
2949 static dladm_status_t
2950 check_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2951 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
2952 uint_t flags
, val_desc_t
**vdpp
, datalink_media_t media
)
2954 dladm_status_t status
;
2957 uint_t val_cnt
= *val_cntp
;
2958 val_desc_t
*vdp
= *vdpp
;
2960 if (val_cnt
> MPT_MAXCID
)
2961 return (DLADM_STATUS_BADVALCNT
);
2963 for (i
= 0; i
< val_cnt
; i
++) {
2964 if ((cid
= calloc(1, sizeof (mac_dhcpcid_t
))) == NULL
) {
2965 status
= DLADM_STATUS_NOMEM
;
2968 vdp
[i
].vd_val
= (uintptr_t)cid
;
2970 status
= dladm_str2cid(prop_val
[i
], cid
);
2971 if (status
!= DLADM_STATUS_OK
)
2974 return (DLADM_STATUS_OK
);
2977 for (i
= 0; i
< val_cnt
; i
++) {
2978 free((void *)vdp
[i
].vd_val
);
2979 vdp
[i
].vd_val
= (uintptr_t)NULL
;
2985 static dladm_status_t
2986 get_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
2987 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2988 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2990 mac_secondary_addr_t sa
;
2991 dladm_status_t status
;
2994 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
2995 perm_flags
, &sa
, sizeof (sa
));
2996 if (status
!= DLADM_STATUS_OK
)
2999 if (sa
.ms_addrcnt
> *val_cnt
)
3000 return (DLADM_STATUS_BADVALCNT
);
3002 for (i
= 0; i
< sa
.ms_addrcnt
; i
++) {
3003 if (dladm_aggr_macaddr2str(
3004 (const unsigned char *)&sa
.ms_addrs
[i
], prop_val
[i
]) ==
3007 return (DLADM_STATUS_NOMEM
);
3010 *val_cnt
= sa
.ms_addrcnt
;
3011 return (DLADM_STATUS_OK
);
3015 static dladm_status_t
3016 check_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
3017 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3018 val_desc_t
**vdpp
, datalink_media_t media
)
3020 dladm_status_t status
;
3024 uint_t val_cnt
= *val_cntp
;
3025 val_desc_t
*vdp
= *vdpp
;
3027 if (val_cnt
>= MPT_MAXMACADDR
)
3028 return (DLADM_STATUS_BADVALCNT
);
3030 for (i
= 0; i
< val_cnt
; i
++) {
3031 addr
= _link_aton(prop_val
[i
], (int *)&len
);
3033 if (len
== (uint_t
)-1)
3034 status
= DLADM_STATUS_MACADDRINVAL
;
3036 status
= DLADM_STATUS_NOMEM
;
3040 vdp
[i
].vd_val
= (uintptr_t)addr
;
3042 return (DLADM_STATUS_OK
);
3045 for (i
= 0; i
< val_cnt
; i
++) {
3046 free((void *)vdp
[i
].vd_val
);
3047 vdp
[i
].vd_val
= (uintptr_t)NULL
;
3053 static dladm_status_t
3054 set_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
3055 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3057 dladm_status_t status
;
3058 dld_ioc_macprop_t
*dip
;
3060 mac_secondary_addr_t msa
;
3062 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "secondary-macs", 0,
3067 if (vdp
->vd_val
== 0) {
3068 val_cnt
= (uint_t
)-1;
3070 for (i
= 0; i
< val_cnt
; i
++) {
3071 bcopy((void *)vdp
[i
].vd_val
, msa
.ms_addrs
[i
],
3075 msa
.ms_addrcnt
= val_cnt
;
3076 bcopy(&msa
, dip
->pr_val
, dip
->pr_valsize
);
3078 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3085 static dladm_status_t
3086 get_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3087 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3088 uint_t flags
, uint_t
*perm_flags
)
3090 struct dlautopush dlap
;
3092 dladm_status_t status
;
3094 if (flags
& DLD_PROP_DEFAULT
)
3095 return (DLADM_STATUS_NOTDEFINED
);
3097 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3098 perm_flags
, &dlap
, sizeof (dlap
));
3099 if (status
!= DLADM_STATUS_OK
)
3102 if (dlap
.dap_npush
== 0) {
3104 return (DLADM_STATUS_OK
);
3106 for (i
= 0, len
= 0; i
< dlap
.dap_npush
; i
++) {
3108 (void) snprintf(*prop_val
+ len
,
3109 DLADM_PROP_VAL_MAX
- len
, "%c", AP_DELIMITER
);
3112 (void) snprintf(*prop_val
+ len
, DLADM_PROP_VAL_MAX
- len
,
3113 "%s", dlap
.dap_aplist
[i
]);
3114 len
+= strlen(dlap
.dap_aplist
[i
]);
3115 if (dlap
.dap_anchor
- 1 == i
) {
3116 (void) snprintf(*prop_val
+ len
,
3117 DLADM_PROP_VAL_MAX
- len
, "%c%s", AP_DELIMITER
,
3119 len
+= (strlen(AP_ANCHOR
) + 1);
3123 return (DLADM_STATUS_OK
);
3127 * Add the specified module to the dlautopush structure; returns a
3128 * DLADM_STATUS_* code.
3131 i_dladm_add_ap_module(const char *module
, struct dlautopush
*dlap
)
3133 if ((strlen(module
) == 0) || (strlen(module
) > FMNAMESZ
))
3134 return (DLADM_STATUS_BADVAL
);
3136 if (strncasecmp(module
, AP_ANCHOR
, strlen(AP_ANCHOR
)) == 0) {
3138 * We don't allow multiple anchors, and the anchor must
3139 * be after at least one module.
3141 if (dlap
->dap_anchor
!= 0)
3142 return (DLADM_STATUS_BADVAL
);
3143 if (dlap
->dap_npush
== 0)
3144 return (DLADM_STATUS_BADVAL
);
3146 dlap
->dap_anchor
= dlap
->dap_npush
;
3147 return (DLADM_STATUS_OK
);
3149 if (dlap
->dap_npush
>= MAXAPUSH
)
3150 return (DLADM_STATUS_BADVALCNT
);
3152 (void) strlcpy(dlap
->dap_aplist
[dlap
->dap_npush
++], module
,
3155 return (DLADM_STATUS_OK
);
3159 * Currently, both '.' and ' '(space) can be used as the delimiters between
3160 * autopush modules. The former is used in dladm set-linkprop, and the
3161 * latter is used in the autopush(1M) file.
3164 static dladm_status_t
3165 check_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3166 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3167 datalink_media_t media
)
3170 struct dlautopush
*dlap
;
3171 dladm_status_t status
;
3172 char val
[DLADM_PROP_VAL_MAX
];
3174 uint_t val_cnt
= *val_cntp
;
3175 val_desc_t
*vdp
= *vdpp
;
3178 return (DLADM_STATUS_BADVALCNT
);
3180 if (prop_val
!= NULL
) {
3181 dlap
= malloc(sizeof (struct dlautopush
));
3183 return (DLADM_STATUS_NOMEM
);
3185 (void) memset(dlap
, 0, sizeof (struct dlautopush
));
3186 (void) snprintf(delimiters
, 4, " %c\n", AP_DELIMITER
);
3187 bcopy(*prop_val
, val
, DLADM_PROP_VAL_MAX
);
3188 module
= strtok(val
, delimiters
);
3189 while (module
!= NULL
) {
3190 status
= i_dladm_add_ap_module(module
, dlap
);
3191 if (status
!= DLADM_STATUS_OK
)
3193 module
= strtok(NULL
, delimiters
);
3196 vdp
->vd_val
= (uintptr_t)dlap
;
3200 return (DLADM_STATUS_OK
);
3203 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3206 static dladm_status_t
3207 get_rate_common(dladm_handle_t handle
, prop_desc_t
*pdp
,
3208 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
, uint_t id
,
3213 dladm_status_t status
= DLADM_STATUS_OK
;
3215 wrp
= malloc(WLDP_BUFSIZE
);
3217 return (DLADM_STATUS_NOMEM
);
3219 status
= i_dladm_wlan_param(handle
, linkid
, wrp
, id
, WLDP_BUFSIZE
,
3221 if (status
!= DLADM_STATUS_OK
)
3224 if (wrp
->wl_rates_num
> *val_cnt
) {
3225 status
= DLADM_STATUS_TOOSMALL
;
3229 if (wrp
->wl_rates_rates
[0] == 0) {
3230 prop_val
[0][0] = '\0';
3235 for (i
= 0; i
< wrp
->wl_rates_num
; i
++) {
3236 (void) snprintf(prop_val
[i
], DLADM_STRSIZE
, "%.*f",
3237 wrp
->wl_rates_rates
[i
] % 2,
3238 (float)wrp
->wl_rates_rates
[i
] / 2);
3240 *val_cnt
= wrp
->wl_rates_num
;
3241 *perm_flags
= MAC_PROP_PERM_RW
;
3248 static dladm_status_t
3249 get_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3250 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3251 uint_t flags
, uint_t
*perm_flags
)
3253 if (media
!= DL_WIFI
) {
3254 return (get_speed(handle
, pdp
, linkid
, prop_val
,
3255 val_cnt
, media
, flags
, perm_flags
));
3258 return (get_rate_common(handle
, pdp
, linkid
, prop_val
, val_cnt
,
3259 MAC_PROP_WL_DESIRED_RATES
, perm_flags
));
3263 static dladm_status_t
3264 get_rate_mod(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3265 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3266 uint_t flags
, uint_t
*perm_flags
)
3271 * Speed for ethernet links is unbounded. E.g., 802.11b
3272 * links can have a speed of 5.5 Gbps.
3274 return (DLADM_STATUS_NOTSUP
);
3277 return (get_rate_common(handle
, pdp
, linkid
, prop_val
,
3278 val_cnt
, MAC_PROP_WL_SUPPORTED_RATES
, perm_flags
));
3280 return (DLADM_STATUS_BADARG
);
3284 static dladm_status_t
3285 set_wlan_rate(dladm_handle_t handle
, datalink_id_t linkid
,
3286 dladm_wlan_rates_t
*rates
)
3291 dladm_status_t status
= DLADM_STATUS_OK
;
3293 wrp
= malloc(WLDP_BUFSIZE
);
3295 return (DLADM_STATUS_NOMEM
);
3297 bzero(wrp
, WLDP_BUFSIZE
);
3298 for (i
= 0; i
< rates
->wr_cnt
; i
++)
3299 wrp
->wl_rates_rates
[i
] = rates
->wr_rates
[i
];
3300 wrp
->wl_rates_num
= rates
->wr_cnt
;
3302 len
= offsetof(wl_rates_t
, wl_rates_rates
) +
3303 (rates
->wr_cnt
* sizeof (char)) + WIFI_BUF_OFFSET
;
3304 status
= i_dladm_wlan_param(handle
, linkid
, wrp
,
3305 MAC_PROP_WL_DESIRED_RATES
, len
, B_TRUE
);
3312 static dladm_status_t
3313 set_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3314 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3316 dladm_wlan_rates_t rates
;
3317 dladm_status_t status
;
3320 * can currently set rate on WIFI links only.
3322 if (media
!= DL_WIFI
)
3323 return (DLADM_STATUS_PROPRDONLY
);
3326 return (DLADM_STATUS_BADVALCNT
);
3329 rates
.wr_rates
[0] = vdp
[0].vd_val
;
3331 status
= set_wlan_rate(handle
, linkid
, &rates
);
3337 static dladm_status_t
3338 check_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3339 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3340 datalink_media_t media
)
3343 uint_t modval_cnt
= MAX_SUPPORT_RATES
;
3344 char *buf
, **modval
;
3345 dladm_status_t status
;
3347 uint_t val_cnt
= *val_cntp
;
3348 val_desc_t
*vdp
= *vdpp
;
3351 return (DLADM_STATUS_BADVALCNT
);
3353 buf
= malloc((sizeof (char *) + DLADM_STRSIZE
) *
3356 status
= DLADM_STATUS_NOMEM
;
3360 modval
= (char **)(void *)buf
;
3361 for (i
= 0; i
< MAX_SUPPORT_RATES
; i
++) {
3362 modval
[i
] = buf
+ sizeof (char *) * MAX_SUPPORT_RATES
+
3366 status
= get_rate_mod(handle
, NULL
, linkid
, modval
, &modval_cnt
,
3367 media
, 0, &perm_flags
);
3368 if (status
!= DLADM_STATUS_OK
)
3371 for (i
= 0; i
< modval_cnt
; i
++) {
3372 if (strcasecmp(*prop_val
, modval
[i
]) == 0) {
3373 vdp
->vd_val
= (uintptr_t)(uint_t
)
3374 (atof(*prop_val
) * 2);
3375 status
= DLADM_STATUS_OK
;
3379 if (i
== modval_cnt
)
3380 status
= DLADM_STATUS_BADVAL
;
3386 static dladm_status_t
3387 get_phyconf(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
3390 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_PHY_CONFIG
,
3395 static dladm_status_t
3396 get_channel(dladm_handle_t handle
, prop_desc_t
*pdp
,
3397 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3398 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3401 char buf
[WLDP_BUFSIZE
];
3402 dladm_status_t status
;
3403 wl_phy_conf_t wl_phy_conf
;
3405 if ((status
= get_phyconf(handle
, linkid
, buf
, sizeof (buf
)))
3409 (void) memcpy(&wl_phy_conf
, buf
, sizeof (wl_phy_conf
));
3410 if (!i_dladm_wlan_convert_chan(&wl_phy_conf
, &channel
))
3411 return (DLADM_STATUS_NOTFOUND
);
3413 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%u", channel
);
3415 *perm_flags
= MAC_PROP_PERM_READ
;
3416 return (DLADM_STATUS_OK
);
3420 static dladm_status_t
3421 get_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3422 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3423 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3427 char buf
[WLDP_BUFSIZE
];
3428 dladm_status_t status
;
3430 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3431 MAC_PROP_WL_POWER_MODE
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3434 (void) memcpy(&mode
, buf
, sizeof (mode
));
3435 switch (mode
.wl_ps_mode
) {
3446 return (DLADM_STATUS_NOTFOUND
);
3448 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3450 *perm_flags
= MAC_PROP_PERM_RW
;
3451 return (DLADM_STATUS_OK
);
3455 static dladm_status_t
3456 set_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3457 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3458 datalink_media_t media
)
3460 dladm_wlan_powermode_t powermode
= vdp
->vd_val
;
3461 wl_ps_mode_t ps_mode
;
3464 return (DLADM_STATUS_BADVALCNT
);
3466 (void) memset(&ps_mode
, 0xff, sizeof (ps_mode
));
3468 switch (powermode
) {
3469 case DLADM_WLAN_PM_OFF
:
3470 ps_mode
.wl_ps_mode
= WL_PM_AM
;
3472 case DLADM_WLAN_PM_MAX
:
3473 ps_mode
.wl_ps_mode
= WL_PM_MPS
;
3475 case DLADM_WLAN_PM_FAST
:
3476 ps_mode
.wl_ps_mode
= WL_PM_FAST
;
3479 return (DLADM_STATUS_NOTSUP
);
3481 return (i_dladm_wlan_param(handle
, linkid
, &ps_mode
,
3482 MAC_PROP_WL_POWER_MODE
, sizeof (ps_mode
), B_TRUE
));
3486 static dladm_status_t
3487 get_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3488 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3489 uint_t flags
, uint_t
*perm_flags
)
3493 char buf
[WLDP_BUFSIZE
];
3494 dladm_status_t status
;
3496 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3497 MAC_PROP_WL_RADIO
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3500 (void) memcpy(&radio
, buf
, sizeof (radio
));
3509 return (DLADM_STATUS_NOTFOUND
);
3511 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3513 *perm_flags
= MAC_PROP_PERM_RW
;
3514 return (DLADM_STATUS_OK
);
3518 static dladm_status_t
3519 set_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3520 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3522 dladm_wlan_radio_t radio
= vdp
->vd_val
;
3526 return (DLADM_STATUS_BADVALCNT
);
3529 case DLADM_WLAN_RADIO_ON
:
3532 case DLADM_WLAN_RADIO_OFF
:
3536 return (DLADM_STATUS_NOTSUP
);
3538 return (i_dladm_wlan_param(handle
, linkid
, &r
, MAC_PROP_WL_RADIO
,
3539 sizeof (r
), B_TRUE
));
3543 static dladm_status_t
3544 check_hoplimit(dladm_handle_t handle
, prop_desc_t
*pdp
,
3545 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3546 val_desc_t
**vdpp
, datalink_media_t media
)
3550 uint_t val_cnt
= *val_cntp
;
3551 val_desc_t
*vdp
= *vdpp
;
3554 return (DLADM_STATUS_BADVALCNT
);
3557 hlim
= strtol(*prop_val
, &ep
, 10);
3558 if (errno
!= 0 || ep
== *prop_val
|| hlim
< 1 ||
3559 hlim
> (int32_t)UINT8_MAX
)
3560 return (DLADM_STATUS_BADVAL
);
3562 return (DLADM_STATUS_OK
);
3566 static dladm_status_t
3567 check_encaplim(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3568 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3569 datalink_media_t media
)
3573 uint_t val_cnt
= *val_cntp
;
3574 val_desc_t
*vdp
= *vdpp
;
3576 if (media
!= DL_IPV6
)
3577 return (DLADM_STATUS_BADARG
);
3580 return (DLADM_STATUS_BADVALCNT
);
3583 elim
= strtol(*prop_val
, &ep
, 10);
3584 if (errno
!= 0 || ep
== *prop_val
|| elim
< 0 ||
3585 elim
> (int32_t)UINT8_MAX
)
3586 return (DLADM_STATUS_BADVAL
);
3588 return (DLADM_STATUS_OK
);
3591 static dladm_status_t
3592 i_dladm_set_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3593 const char *prop_name
, char **prop_val
, uint_t val_cnt
)
3595 char buf
[MAXLINELEN
];
3598 dladm_status_t status
;
3600 status
= dladm_open_conf(handle
, linkid
, &conf
);
3601 if (status
!= DLADM_STATUS_OK
)
3608 status
= dladm_unset_conf_field(handle
, conf
, prop_name
);
3609 if (status
== DLADM_STATUS_OK
)
3610 status
= dladm_write_conf(handle
, conf
);
3615 for (i
= 0; i
< val_cnt
; i
++) {
3616 (void) strlcat(buf
, prop_val
[i
], MAXLINELEN
);
3617 if (i
!= val_cnt
- 1)
3618 (void) strlcat(buf
, ",", MAXLINELEN
);
3621 status
= dladm_set_conf_field(handle
, conf
, prop_name
, DLADM_TYPE_STR
,
3623 if (status
== DLADM_STATUS_OK
)
3624 status
= dladm_write_conf(handle
, conf
);
3627 dladm_destroy_conf(handle
, conf
);
3631 static dladm_status_t
3632 i_dladm_get_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3633 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
3635 char buf
[MAXLINELEN
], *str
;
3638 dladm_status_t status
;
3640 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3641 if (status
!= DLADM_STATUS_OK
)
3644 status
= dladm_get_conf_field(handle
, conf
, prop_name
, buf
, MAXLINELEN
);
3645 if (status
!= DLADM_STATUS_OK
)
3648 str
= strtok(buf
, ",");
3649 while (str
!= NULL
) {
3650 if (cnt
== *val_cntp
) {
3651 status
= DLADM_STATUS_TOOSMALL
;
3654 (void) strlcpy(prop_val
[cnt
++], str
, DLADM_PROP_VAL_MAX
);
3655 str
= strtok(NULL
, ",");
3661 dladm_destroy_conf(handle
, conf
);
3666 * Walk persistent private link properties of a link.
3668 static dladm_status_t
3669 i_dladm_walk_linkprop_priv_db(dladm_handle_t handle
, datalink_id_t linkid
,
3670 void *arg
, int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
3672 dladm_status_t status
;
3674 char last_attr
[MAXLINKATTRLEN
];
3675 char attr
[MAXLINKATTRLEN
];
3676 char attrval
[MAXLINKATTRVALLEN
];
3679 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
3680 return (DLADM_STATUS_BADARG
);
3682 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3683 if (status
!= DLADM_STATUS_OK
)
3686 last_attr
[0] = '\0';
3687 while ((status
= dladm_getnext_conf_linkprop(handle
, conf
, last_attr
,
3688 attr
, attrval
, MAXLINKATTRVALLEN
, &attrsz
)) == DLADM_STATUS_OK
) {
3689 if (attr
[0] == '_') {
3690 if (func(handle
, linkid
, attr
, arg
) ==
3691 DLADM_WALK_TERMINATE
)
3694 (void) strlcpy(last_attr
, attr
, MAXLINKATTRLEN
);
3697 dladm_destroy_conf(handle
, conf
);
3698 return (DLADM_STATUS_OK
);
3701 static link_attr_t
*
3702 dladm_name2prop(const char *prop_name
)
3706 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3707 if (strcmp(p
->pp_name
, prop_name
) == 0)
3713 static link_attr_t
*
3714 dladm_id2prop(mac_prop_id_t propid
)
3718 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3719 if (p
->pp_id
== propid
)
3725 static dld_ioc_macprop_t
*
3726 i_dladm_buf_alloc_impl(size_t valsize
, datalink_id_t linkid
,
3727 const char *prop_name
, mac_prop_id_t propid
, uint_t flags
,
3728 dladm_status_t
*status
)
3731 dld_ioc_macprop_t
*dip
;
3733 *status
= DLADM_STATUS_OK
;
3734 dsize
= MAC_PROP_BUFSIZE(valsize
);
3735 dip
= malloc(dsize
);
3737 *status
= DLADM_STATUS_NOMEM
;
3741 dip
->pr_valsize
= valsize
;
3742 (void) strlcpy(dip
->pr_name
, prop_name
, sizeof (dip
->pr_name
));
3743 dip
->pr_linkid
= linkid
;
3744 dip
->pr_num
= propid
;
3745 dip
->pr_flags
= flags
;
3749 static dld_ioc_macprop_t
*
3750 i_dladm_buf_alloc_by_name(size_t valsize
, datalink_id_t linkid
,
3751 const char *prop_name
, uint_t flags
, dladm_status_t
*status
)
3755 p
= dladm_name2prop(prop_name
);
3756 valsize
= MAX(p
->pp_valsize
, valsize
);
3757 return (i_dladm_buf_alloc_impl(valsize
, linkid
, prop_name
, p
->pp_id
,
3761 static dld_ioc_macprop_t
*
3762 i_dladm_buf_alloc_by_id(size_t valsize
, datalink_id_t linkid
,
3763 mac_prop_id_t propid
, uint_t flags
, dladm_status_t
*status
)
3767 p
= dladm_id2prop(propid
);
3768 valsize
= MAX(p
->pp_valsize
, valsize
);
3769 return (i_dladm_buf_alloc_impl(valsize
, linkid
, p
->pp_name
, propid
,
3774 static dladm_status_t
3775 set_public_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
3776 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3777 datalink_media_t media
)
3779 dld_ioc_macprop_t
*dip
;
3780 dladm_status_t status
= DLADM_STATUS_OK
;
3786 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
, 0, &status
);
3790 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
3791 val
= (void *)vdp
->vd_val
;
3794 * Currently all 1/2/4-byte size properties are byte/word/int.
3795 * No need (yet) to distinguish these from arrays of same size.
3797 switch (dip
->pr_valsize
) {
3817 (void) memcpy(dip
->pr_val
, val
, dip
->pr_valsize
);
3819 dip
->pr_valsize
= 0;
3821 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3829 i_dladm_macprop(dladm_handle_t handle
, void *dip
, boolean_t set
)
3831 dladm_status_t status
= DLADM_STATUS_OK
;
3833 if (ioctl(dladm_dld_fd(handle
),
3834 (set
? DLDIOC_SETMACPROP
: DLDIOC_GETMACPROP
), dip
))
3835 status
= dladm_errno2status(errno
);
3840 static dladm_status_t
3841 i_dladm_get_public_prop(dladm_handle_t handle
, datalink_id_t linkid
,
3842 char *prop_name
, uint_t flags
, uint_t
*perm_flags
, void *arg
, size_t size
)
3844 dld_ioc_macprop_t
*dip
;
3845 dladm_status_t status
;
3847 dip
= i_dladm_buf_alloc_by_name(0, linkid
, prop_name
, flags
, &status
);
3849 return (DLADM_STATUS_NOMEM
);
3851 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
3852 if (status
!= DLADM_STATUS_OK
) {
3857 if (perm_flags
!= NULL
)
3858 *perm_flags
= dip
->pr_perm_flags
;
3861 (void) memcpy(arg
, dip
->pr_val
, size
);
3863 return (DLADM_STATUS_OK
);
3867 static dladm_status_t
3868 check_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3869 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3870 val_desc_t
**vp
, datalink_media_t media
)
3872 uint_t val_cnt
= *val_cntp
;
3873 val_desc_t
*v
= *vp
;
3876 return (DLADM_STATUS_BADVAL
);
3877 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
3878 return (DLADM_STATUS_OK
);
3882 static dladm_status_t
3883 get_duplex(dladm_handle_t handle
, prop_desc_t
*pdp
,
3884 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3885 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3887 link_duplex_t link_duplex
;
3888 dladm_status_t status
;
3890 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "link_duplex",
3891 KSTAT_DATA_UINT32
, &link_duplex
)) != 0)
3894 switch (link_duplex
) {
3895 case LINK_DUPLEX_FULL
:
3896 (void) strcpy(*prop_val
, "full");
3898 case LINK_DUPLEX_HALF
:
3899 (void) strcpy(*prop_val
, "half");
3902 (void) strcpy(*prop_val
, "unknown");
3906 return (DLADM_STATUS_OK
);
3910 static dladm_status_t
3911 get_speed(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3912 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
3915 uint64_t ifspeed
= 0;
3916 dladm_status_t status
;
3918 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "ifspeed",
3919 KSTAT_DATA_UINT64
, &ifspeed
)) != 0)
3922 if ((ifspeed
% 1000000) != 0) {
3923 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3924 "%llf", ifspeed
/ (float)1000000); /* Mbps */
3926 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3927 "%llu", ifspeed
/ 1000000); /* Mbps */
3930 *perm_flags
= MAC_PROP_PERM_READ
;
3931 return (DLADM_STATUS_OK
);
3935 static dladm_status_t
3936 get_link_state(dladm_handle_t handle
, prop_desc_t
*pdp
,
3937 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3938 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3940 link_state_t link_state
;
3941 dladm_status_t status
;
3943 status
= dladm_get_state(handle
, linkid
, &link_state
);
3944 if (status
!= DLADM_STATUS_OK
)
3947 switch (link_state
) {
3949 (void) strcpy(*prop_val
, "up");
3951 case LINK_STATE_DOWN
:
3952 (void) strcpy(*prop_val
, "down");
3955 (void) strcpy(*prop_val
, "unknown");
3959 *perm_flags
= MAC_PROP_PERM_READ
;
3960 return (DLADM_STATUS_OK
);
3964 static dladm_status_t
3965 get_binary(dladm_handle_t handle
, prop_desc_t
*pdp
,
3966 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3967 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3969 dladm_status_t status
;
3972 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3973 perm_flags
, &v
, sizeof (v
));
3974 if (status
!= DLADM_STATUS_OK
)
3977 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%d", (uint_t
)(v
> 0));
3979 return (DLADM_STATUS_OK
);
3983 static dladm_status_t
3984 get_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3985 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3986 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3988 dladm_status_t status
;
3991 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3992 perm_flags
, &v
, sizeof (v
));
3993 if (status
!= DLADM_STATUS_OK
)
3996 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", v
);
3998 return (DLADM_STATUS_OK
);
4002 static dladm_status_t
4003 get_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
4004 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4005 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4007 dld_ioc_macprop_t
*dip
;
4008 dladm_status_t status
= DLADM_STATUS_OK
;
4011 mac_propval_range_t
*rangep
;
4014 * As caller we don't know number of value ranges, the driver
4015 * supports. To begin with we assume that number to be 1. If the
4016 * buffer size is insufficient, driver returns back with the
4017 * actual count of value ranges. See mac.h for more details.
4019 sz
= sizeof (mac_propval_range_t
);
4022 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
4026 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
4027 rangep
->mpr_count
= rcount
;
4029 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4030 if (status
!= DLADM_STATUS_OK
) {
4031 if (status
== DLADM_STATUS_TOOSMALL
) {
4034 if ((err
= i_dladm_range_size(rangep
, &sz
, &rcount
))
4039 status
= dladm_errno2status(err
);
4046 if (rangep
->mpr_count
== 0) {
4048 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "--");
4052 switch (rangep
->mpr_type
) {
4053 case MAC_PROPVAL_UINT32
: {
4054 mac_propval_uint32_range_t
*ur
;
4055 uint_t count
= rangep
->mpr_count
, i
;
4057 ur
= &rangep
->mpr_range_uint32
[0];
4059 for (i
= 0; i
< count
; i
++, ur
++) {
4060 if (ur
->mpur_min
== ur
->mpur_max
) {
4061 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4062 "%ld", ur
->mpur_min
);
4064 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4065 "%ld-%ld", ur
->mpur_min
, ur
->mpur_max
);
4072 status
= DLADM_STATUS_BADARG
;
4081 static dladm_status_t
4082 get_tagmode(dladm_handle_t handle
, prop_desc_t
*pdp
,
4083 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4084 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4086 link_tagmode_t mode
;
4087 dladm_status_t status
;
4089 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4090 perm_flags
, &mode
, sizeof (mode
));
4091 if (status
!= DLADM_STATUS_OK
)
4095 case LINK_TAGMODE_NORMAL
:
4096 (void) strlcpy(*prop_val
, "normal", DLADM_PROP_VAL_MAX
);
4098 case LINK_TAGMODE_VLANONLY
:
4099 (void) strlcpy(*prop_val
, "vlanonly", DLADM_PROP_VAL_MAX
);
4102 (void) strlcpy(*prop_val
, "unknown", DLADM_PROP_VAL_MAX
);
4105 return (DLADM_STATUS_OK
);
4109 static dladm_status_t
4110 get_flowctl(dladm_handle_t handle
, prop_desc_t
*pdp
,
4111 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4112 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4115 dladm_status_t status
;
4117 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4118 perm_flags
, &v
, sizeof (v
));
4119 if (status
!= DLADM_STATUS_OK
)
4123 case LINK_FLOWCTRL_NONE
:
4124 (void) sprintf(*prop_val
, "no");
4126 case LINK_FLOWCTRL_RX
:
4127 (void) sprintf(*prop_val
, "rx");
4129 case LINK_FLOWCTRL_TX
:
4130 (void) sprintf(*prop_val
, "tx");
4132 case LINK_FLOWCTRL_BI
:
4133 (void) sprintf(*prop_val
, "bi");
4137 return (DLADM_STATUS_OK
);
4142 static dladm_status_t
4143 i_dladm_set_private_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4144 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
4148 dld_ioc_macprop_t
*dip
= NULL
;
4151 dladm_status_t status
= DLADM_STATUS_OK
;
4153 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4154 (prop_val
!= NULL
&& val_cnt
== 0))
4155 return (DLADM_STATUS_BADARG
);
4156 p
= dladm_name2prop(prop_name
);
4157 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4158 return (DLADM_STATUS_BADARG
);
4160 if (!(flags
& DLADM_OPT_ACTIVE
))
4161 return (DLADM_STATUS_OK
);
4164 * private properties: all parsing is done in the kernel.
4165 * allocate a enough space for each property + its separator (',').
4167 for (i
= 0; i
< val_cnt
; i
++) {
4168 bufsize
+= strlen(prop_val
[i
]) + 1;
4171 if (prop_val
== NULL
) {
4173 * getting default value. so use more buffer space.
4175 bufsize
+= DLADM_PROP_BUF_CHUNK
;
4178 dip
= i_dladm_buf_alloc_by_name(bufsize
+ 1, linkid
, prop_name
,
4179 (prop_val
!= NULL
? 0 : DLD_PROP_DEFAULT
), &status
);
4183 dp
= (uchar_t
*)dip
->pr_val
;
4186 if (prop_val
== NULL
) {
4187 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4190 for (i
= 0; i
< val_cnt
; i
++) {
4193 plen
= strlen(prop_val
[i
]);
4194 bcopy(prop_val
[i
], dp
, plen
);
4197 * add a "," separator and update dp.
4199 if (i
!= (val_cnt
-1))
4204 if (status
== DLADM_STATUS_OK
)
4205 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4211 static dladm_status_t
4212 i_dladm_get_priv_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4213 const char *prop_name
, char **prop_val
, uint_t
*val_cnt
,
4214 dladm_prop_type_t type
, uint_t dld_flags
)
4216 dladm_status_t status
= DLADM_STATUS_OK
;
4217 dld_ioc_macprop_t
*dip
= NULL
;
4220 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4221 (prop_val
!= NULL
&& val_cnt
== 0))
4222 return (DLADM_STATUS_BADARG
);
4224 p
= dladm_name2prop(prop_name
);
4225 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4226 return (DLADM_STATUS_BADARG
);
4229 * private properties: all parsing is done in the kernel.
4231 dip
= i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK
, linkid
, prop_name
,
4232 dld_flags
, &status
);
4236 if ((status
= i_dladm_macprop(handle
, dip
, B_FALSE
)) ==
4238 if (type
== DLADM_PROP_VAL_PERM
) {
4239 (void) dladm_perm2str(dip
->pr_perm_flags
, *prop_val
);
4240 } else if (type
== DLADM_PROP_VAL_MODIFIABLE
) {
4241 *prop_val
[0] = '\0';
4243 (void) strncpy(*prop_val
, dip
->pr_val
,
4244 DLADM_PROP_VAL_MAX
);
4247 } else if ((status
== DLADM_STATUS_NOTSUP
) &&
4248 (type
== DLADM_PROP_VAL_CURRENT
)) {
4249 status
= DLADM_STATUS_NOTFOUND
;
4256 static dladm_status_t
4257 i_dladm_getset_defval(dladm_handle_t handle
, prop_desc_t
*pdp
,
4258 datalink_id_t linkid
, datalink_media_t media
, uint_t flags
)
4260 dladm_status_t status
;
4261 char **prop_vals
= NULL
, *buf
;
4268 * Allocate buffer needed for prop_vals array. We can have at most
4269 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4270 * each entry has max size DLADM_PROP_VAL_MAX
4273 (sizeof (char *) + DLADM_PROP_VAL_MAX
) * DLADM_MAX_PROP_VALCNT
;
4274 buf
= malloc(bufsize
);
4275 prop_vals
= (char **)(void *)buf
;
4276 for (i
= 0; i
< DLADM_MAX_PROP_VALCNT
; i
++) {
4277 prop_vals
[i
] = buf
+
4278 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4279 i
* DLADM_PROP_VAL_MAX
;
4283 * For properties which have pdp->pd_defval.vd_name as a non-empty
4284 * string, the "" itself is used to reset the property (exceptions
4285 * are zone and autopush, which populate vdp->vd_val). So
4286 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4287 * down on the setprop using the global values in the table. For
4288 * other cases (vd_name is ""), doing reset-linkprop will cause
4289 * libdladm to do a getprop to find the default value and then do
4290 * a setprop to reset the value to default.
4292 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_vals
, &cnt
, media
,
4293 DLD_PROP_DEFAULT
, &perm_flags
);
4294 if (status
== DLADM_STATUS_OK
) {
4295 if (perm_flags
== MAC_PROP_PERM_RW
) {
4296 status
= i_dladm_set_single_prop(handle
, linkid
,
4297 pdp
->pd_class
, media
, pdp
, prop_vals
, cnt
, flags
);
4300 status
= DLADM_STATUS_NOTSUP
;
4307 static dladm_status_t
4308 get_stp(dladm_handle_t handle
, struct prop_desc
*pd
, datalink_id_t linkid
,
4309 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
4312 const bridge_public_prop_t
*bpp
;
4313 dladm_status_t retv
;
4317 return (DLADM_STATUS_NOTSUP
);
4318 *perm_flags
= MAC_PROP_PERM_RW
;
4320 for (bpp
= bridge_prop
; bpp
->bpp_name
!= NULL
; bpp
++)
4321 if (strcmp(bpp
->bpp_name
, pd
->pd_name
) == 0)
4323 retv
= dladm_bridge_get_port_cfg(handle
, linkid
, bpp
->bpp_code
, &val
);
4324 /* If the daemon isn't running, then return the persistent value */
4325 if (retv
== DLADM_STATUS_NOTFOUND
) {
4326 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4327 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4328 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4329 DLADM_PROP_VAL_MAX
);
4330 return (DLADM_STATUS_OK
);
4332 if (retv
!= DLADM_STATUS_OK
) {
4333 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4336 if (val
== pd
->pd_defval
.vd_val
&& pd
->pd_defval
.vd_name
[0] != '\0') {
4337 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4338 DLADM_PROP_VAL_MAX
);
4339 return (DLADM_STATUS_OK
);
4341 for (i
= 0; i
< pd
->pd_noptval
; i
++) {
4342 if (val
== pd
->pd_optval
[i
].vd_val
) {
4343 (void) strlcpy(*prop_val
, pd
->pd_optval
[i
].vd_name
,
4344 DLADM_PROP_VAL_MAX
);
4345 return (DLADM_STATUS_OK
);
4348 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", (unsigned)val
);
4349 return (DLADM_STATUS_OK
);
4353 static dladm_status_t
4354 set_stp_prop(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4355 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4358 * Special case for mcheck: the daemon resets the value to zero, and we
4359 * don't want the daemon to refresh itself; it leads to deadlock.
4361 if (flags
& DLADM_OPT_NOREFRESH
)
4362 return (DLADM_STATUS_OK
);
4364 /* Tell the running daemon, if any */
4365 return (dladm_bridge_refresh(handle
, linkid
));
4369 * This is used only for stp_priority, stp_cost, and stp_mcheck.
4372 static dladm_status_t
4373 check_stp_prop(dladm_handle_t handle
, struct prop_desc
*pd
,
4374 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4375 val_desc_t
**vdpp
, datalink_media_t media
)
4379 uint_t val_cnt
= *val_cntp
;
4380 val_desc_t
*vdp
= *vdpp
;
4383 return (DLADM_STATUS_BADVALCNT
);
4385 if (prop_val
== NULL
) {
4388 /* Only stp_priority and stp_cost use this function */
4389 iscost
= strcmp(pd
->pd_name
, "stp_cost") == 0;
4391 if (iscost
&& strcmp(prop_val
[0], "auto") == 0) {
4392 /* Illegal value 0 is allowed to mean "automatic" */
4396 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4397 if (errno
!= 0 || *cp
!= '\0')
4398 return (DLADM_STATUS_BADVAL
);
4403 return (vdp
->vd_val
> 65535 ? DLADM_STATUS_BADVAL
:
4406 if (vdp
->vd_val
> 255)
4407 return (DLADM_STATUS_BADVAL
);
4409 * If the user is setting stp_mcheck non-zero, then (per the
4410 * IEEE management standards and UNH testing) we need to check
4411 * whether this link is part of a bridge that is running RSTP.
4412 * If it's not, then setting the flag is an error. Note that
4413 * errors are intentionally discarded here; it's the value
4414 * that's the problem -- it's not a bad value, merely one that
4415 * can't be used now.
4417 if (strcmp(pd
->pd_name
, "stp_mcheck") == 0 &&
4419 char bridge
[MAXLINKNAMELEN
];
4421 dladm_bridge_prot_t brprot
;
4423 if (dladm_bridge_getlink(handle
, linkid
, bridge
,
4424 sizeof (bridge
)) != DLADM_STATUS_OK
||
4425 dladm_bridge_get_properties(bridge
, &cfg
,
4426 &brprot
) != DLADM_STATUS_OK
)
4427 return (DLADM_STATUS_FAILED
);
4428 if (cfg
.force_version
<= 1)
4429 return (DLADM_STATUS_FAILED
);
4431 return (DLADM_STATUS_OK
);
4436 static dladm_status_t
4437 get_bridge_forward(dladm_handle_t handle
, struct prop_desc
*pd
,
4438 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4439 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4441 dladm_status_t retv
;
4445 return (DLADM_STATUS_NOTSUP
);
4446 *perm_flags
= MAC_PROP_PERM_RW
;
4448 retv
= dladm_bridge_get_forwarding(handle
, linkid
, &val
);
4449 if (retv
== DLADM_STATUS_NOTFOUND
) {
4450 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4451 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4452 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4453 DLADM_PROP_VAL_MAX
);
4454 return (DLADM_STATUS_OK
);
4456 if (retv
== DLADM_STATUS_OK
)
4457 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", val
);
4459 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4464 static dladm_status_t
4465 set_bridge_forward(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4466 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4468 /* Tell the running daemon, if any */
4469 return (dladm_bridge_refresh(handle
, linkid
));
4473 static dladm_status_t
4474 get_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4475 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4476 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4478 dladm_status_t status
;
4479 dld_ioc_macprop_t
*dip
;
4483 return (DLADM_STATUS_NOTSUP
);
4484 *perm_flags
= MAC_PROP_PERM_RW
;
4486 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4490 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4491 if (status
== DLADM_STATUS_OK
) {
4492 (void) memcpy(&pvid
, dip
->pr_val
, sizeof (pvid
));
4493 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", pvid
);
4495 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4502 static dladm_status_t
4503 set_bridge_pvid(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4504 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4506 dladm_status_t status
;
4507 dld_ioc_macprop_t
*dip
;
4510 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4515 (void) memcpy(dip
->pr_val
, &pvid
, sizeof (pvid
));
4516 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4518 if (status
!= DLADM_STATUS_OK
)
4521 /* Tell the running daemon, if any */
4522 return (dladm_bridge_refresh(handle
, linkid
));
4526 static dladm_status_t
4527 check_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4528 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4529 val_desc_t
**vdpp
, datalink_media_t media
)
4532 uint_t val_cnt
= *val_cntp
;
4533 val_desc_t
*vdp
= *vdpp
;
4536 return (DLADM_STATUS_BADVALCNT
);
4538 if (prop_val
== NULL
) {
4542 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4543 if (errno
!= 0 || *cp
!= '\0')
4544 return (DLADM_STATUS_BADVAL
);
4547 return (vdp
->vd_val
> VLAN_ID_MAX
? DLADM_STATUS_BADVAL
:
4552 i_dladm_wlan_param(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
4553 mac_prop_id_t cmd
, size_t len
, boolean_t set
)
4556 dladm_status_t status
;
4558 dld_ioc_macprop_t
*dip
;
4561 if ((status
= dladm_datalink_id2info(handle
, linkid
, &flags
, NULL
,
4562 &media
, NULL
, 0)) != DLADM_STATUS_OK
) {
4566 if (media
!= DL_WIFI
)
4567 return (DLADM_STATUS_BADARG
);
4569 if (!(flags
& DLADM_OPT_ACTIVE
))
4570 return (DLADM_STATUS_TEMPONLY
);
4572 if (len
== (MAX_BUF_LEN
- WIFI_BUF_OFFSET
))
4573 len
= MAX_BUF_LEN
- sizeof (dld_ioc_macprop_t
) - 1;
4575 dip
= i_dladm_buf_alloc_by_id(len
, linkid
, cmd
, 0, &status
);
4577 return (DLADM_STATUS_NOMEM
);
4579 dp
= (uchar_t
*)dip
->pr_val
;
4581 (void) memcpy(dp
, buf
, len
);
4583 status
= i_dladm_macprop(handle
, dip
, set
);
4584 if (status
== DLADM_STATUS_OK
) {
4586 (void) memcpy(buf
, dp
, len
);
4594 dladm_parse_link_props(char *str
, dladm_arg_list_t
**listp
, boolean_t novalues
)
4596 return (dladm_parse_args(str
, listp
, novalues
));
4600 * Retrieve the one link property from the database
4604 i_dladm_get_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4605 const char *prop_name
, void *arg
)
4607 dladm_arg_list_t
*proplist
= arg
;
4608 dladm_arg_info_t
*aip
= NULL
;
4610 aip
= &proplist
->al_info
[proplist
->al_count
];
4612 * it is fine to point to prop_name since prop_name points to the
4613 * prop_table[n].pd_name.
4615 aip
->ai_name
= prop_name
;
4617 (void) dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
4618 prop_name
, aip
->ai_val
, &aip
->ai_count
);
4620 if (aip
->ai_count
!= 0)
4621 proplist
->al_count
++;
4623 return (DLADM_WALK_CONTINUE
);
4628 * Retrieve all link properties for a link from the database and
4629 * return a property list.
4632 dladm_link_get_proplist(dladm_handle_t handle
, datalink_id_t linkid
,
4633 dladm_arg_list_t
**listp
)
4635 dladm_arg_list_t
*list
;
4636 dladm_status_t status
= DLADM_STATUS_OK
;
4638 list
= calloc(1, sizeof (dladm_arg_list_t
));
4640 return (dladm_errno2status(errno
));
4642 status
= dladm_walk_linkprop(handle
, linkid
, list
,
4643 i_dladm_get_one_prop
);
4650 * Retrieve the named property from a proplist, check the value and
4651 * convert to a kernel structure.
4653 static dladm_status_t
4654 i_dladm_link_proplist_extract_one(dladm_handle_t handle
,
4655 dladm_arg_list_t
*proplist
, const char *name
, uint_t flags
, void *arg
)
4657 dladm_status_t status
;
4658 dladm_arg_info_t
*aip
= NULL
;
4661 /* Find named property in proplist */
4662 for (i
= 0; i
< proplist
->al_count
; i
++) {
4663 aip
= &proplist
->al_info
[i
];
4664 if (strcasecmp(aip
->ai_name
, name
) == 0)
4668 /* Property not in list */
4669 if (i
== proplist
->al_count
)
4670 return (DLADM_STATUS_OK
);
4672 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
4673 prop_desc_t
*pdp
= &prop_table
[i
];
4676 vdp
= malloc(sizeof (val_desc_t
) * aip
->ai_count
);
4678 return (DLADM_STATUS_NOMEM
);
4680 if (strcasecmp(aip
->ai_name
, pdp
->pd_name
) != 0)
4683 if (aip
->ai_val
== NULL
)
4684 return (DLADM_STATUS_BADARG
);
4686 /* Check property value */
4687 if (pdp
->pd_check
!= NULL
) {
4688 status
= pdp
->pd_check(handle
, pdp
, 0, aip
->ai_val
,
4689 &(aip
->ai_count
), flags
, &vdp
, 0);
4691 status
= DLADM_STATUS_BADARG
;
4694 if (status
!= DLADM_STATUS_OK
)
4697 for (j
= 0; j
< DLADM_MAX_RSRC_PROP
; j
++) {
4698 resource_prop_t
*rpp
= &rsrc_prop_table
[j
];
4700 if (strcasecmp(aip
->ai_name
, rpp
->rp_name
) != 0)
4703 /* Extract kernel structure */
4704 if (rpp
->rp_extract
!= NULL
) {
4705 status
= rpp
->rp_extract(vdp
,
4706 aip
->ai_count
, arg
);
4708 status
= DLADM_STATUS_BADARG
;
4713 if (status
!= DLADM_STATUS_OK
)
4722 * Extract properties from a proplist and convert to mac_resource_props_t.
4725 dladm_link_proplist_extract(dladm_handle_t handle
, dladm_arg_list_t
*proplist
,
4726 mac_resource_props_t
*mrp
, uint_t flags
)
4728 dladm_status_t status
;
4731 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
4732 status
= i_dladm_link_proplist_extract_one(handle
,
4733 proplist
, rsrc_prop_table
[i
].rp_name
, flags
, mrp
);
4734 if (status
!= DLADM_STATUS_OK
)
4741 dladm_perm2str(uint_t perm
, char *buf
)
4743 (void) snprintf(buf
, DLADM_STRSIZE
, "%c%c",
4744 ((perm
& MAC_PROP_PERM_READ
) != 0) ? 'r' : '-',
4745 ((perm
& MAC_PROP_PERM_WRITE
) != 0) ? 'w' : '-');
4750 dladm_get_state(dladm_handle_t handle
, datalink_id_t linkid
,
4751 link_state_t
*state
)
4755 return (i_dladm_get_public_prop(handle
, linkid
, "state", 0,
4756 &perms
, state
, sizeof (*state
)));
4760 dladm_attr_is_linkprop(const char *name
)
4762 /* non-property attribute names */
4763 const char *nonprop
[] = {
4764 /* dlmgmtd core attributes */
4772 /* other attributes for vlan, aggr, etc */
4775 boolean_t is_nonprop
= B_FALSE
;
4778 for (i
= 0; i
< sizeof (nonprop
) / sizeof (nonprop
[0]); i
++) {
4779 if (strcmp(name
, nonprop
[i
]) == 0) {
4780 is_nonprop
= B_TRUE
;
4785 return (!is_nonprop
);
4789 dladm_linkprop_is_set(dladm_handle_t handle
, datalink_id_t linkid
,
4790 dladm_prop_type_t type
, const char *prop_name
, boolean_t
*is_set
)
4792 char *buf
, **propvals
;
4793 uint_t valcnt
= DLADM_MAX_PROP_VALCNT
;
4795 dladm_status_t status
= DLADM_STATUS_OK
;
4800 bufsize
= (sizeof (char *) + DLADM_PROP_VAL_MAX
) *
4801 DLADM_MAX_PROP_VALCNT
;
4802 if ((buf
= calloc(1, bufsize
)) == NULL
)
4803 return (DLADM_STATUS_NOMEM
);
4805 propvals
= (char **)(void *)buf
;
4806 for (i
= 0; i
< valcnt
; i
++) {
4808 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4809 i
* DLADM_PROP_VAL_MAX
;
4812 if (dladm_get_linkprop(handle
, linkid
, type
, prop_name
, propvals
,
4813 &valcnt
) != DLADM_STATUS_OK
) {
4818 * valcnt is always set to 1 by get_pool(), hence we need to check
4819 * for a non-null string to see if it is set. For protection,
4820 * secondary-macs and allowed-ips, we can check either the *propval
4823 if ((strcmp(prop_name
, "pool") == 0 ||
4824 strcmp(prop_name
, "protection") == 0 ||
4825 strcmp(prop_name
, "secondary-macs") == 0 ||
4826 strcmp(prop_name
, "allowed-ips") == 0) &&
4827 (strlen(*propvals
) != 0)) {
4829 } else if ((strcmp(prop_name
, "cpus") == 0) && (valcnt
!= 0)) {
4831 } else if ((strcmp(prop_name
, "_softmac") == 0) && (valcnt
!= 0) &&
4832 (strcmp(propvals
[0], "true") == 0)) {
4842 static dladm_status_t
4843 get_linkmode_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
4844 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4845 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4849 dladm_status_t status
;
4851 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4852 perm_flags
, &v
, sizeof (v
));
4853 if (status
!= DLADM_STATUS_OK
)
4857 case DLADM_PART_CM_MODE
:
4860 case DLADM_PART_UD_MODE
:
4867 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
4870 return (DLADM_STATUS_OK
);
4874 static dladm_status_t
4875 get_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
4876 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4877 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4880 dladm_status_t status
;
4883 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4884 perm_flags
, &filt
, sizeof (filt
));
4885 if (status
!= DLADM_STATUS_OK
)
4889 s
= link_promisc_filtered_vals
[1].vd_name
;
4891 s
= link_promisc_filtered_vals
[0].vd_name
;
4892 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
4895 return (DLADM_STATUS_OK
);
4899 static dladm_status_t
4900 set_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
4901 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
4902 datalink_media_t media
)
4904 dld_ioc_macprop_t
*dip
;
4905 dladm_status_t status
= DLADM_STATUS_OK
;
4907 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
,
4913 (void) memcpy(dip
->pr_val
, &vdp
->vd_val
, dip
->pr_valsize
);
4914 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);