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
;
1458 return (DLADM_WALK_CONTINUE
);
1463 i_dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
)
1465 datalink_class_t
class;
1466 dladm_status_t status
;
1468 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, NULL
,
1470 if (status
!= DLADM_STATUS_OK
)
1471 return (DLADM_WALK_TERMINATE
);
1473 if ((class & (DATALINK_CLASS_VNIC
| DATALINK_CLASS_VLAN
)) == 0)
1474 (void) dladm_init_linkprop(handle
, linkid
, B_TRUE
);
1476 return (DLADM_WALK_CONTINUE
);
1480 dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1481 boolean_t any_media
)
1483 dladm_status_t status
= DLADM_STATUS_OK
;
1484 datalink_media_t dmedia
;
1486 dladm_linkprop_args_t
*dla
;
1488 dmedia
= any_media
? DATALINK_ANY_MEDIATYPE
: DL_WIFI
;
1490 dla
= malloc(sizeof (dladm_linkprop_args_t
));
1492 return (DLADM_STATUS_NOMEM
);
1493 dla
->dla_flags
= DLADM_OPT_BOOT
;
1494 dla
->dla_status
= DLADM_STATUS_OK
;
1496 if (linkid
== DATALINK_ALL_LINKID
) {
1497 (void) dladm_walk_datalink_id(i_dladm_init_linkprop
, handle
,
1498 NULL
, DATALINK_CLASS_ALL
, dmedia
, DLADM_OPT_PERSIST
);
1499 } else if (any_media
||
1500 ((dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, &media
, NULL
,
1501 0) == DLADM_STATUS_OK
) &&
1502 DATALINK_MEDIA_ACCEPTED(dmedia
, media
))) {
1503 (void) dladm_walk_linkprop(handle
, linkid
, (void *)dla
,
1504 i_dladm_init_one_prop
);
1505 status
= dla
->dla_status
;
1512 static dladm_status_t
1513 get_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1514 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1515 uint_t flags
, uint_t
*perm_flags
)
1517 char zone_name
[ZONENAME_MAX
];
1519 dladm_status_t status
;
1522 return (DLADM_STATUS_NOTSUP
);
1524 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1525 perm_flags
, &zid
, sizeof (zid
));
1526 if (status
!= DLADM_STATUS_OK
)
1530 if (zid
!= GLOBAL_ZONEID
) {
1531 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0) {
1532 return (dladm_errno2status(errno
));
1535 (void) strncpy(*prop_val
, zone_name
, DLADM_PROP_VAL_MAX
);
1537 *prop_val
[0] = '\0';
1540 return (DLADM_STATUS_OK
);
1543 typedef int (*zone_get_devroot_t
)(char *, char *, size_t);
1546 i_dladm_get_zone_dev(char *zone_name
, char *dev
, size_t devlen
)
1548 char root
[MAXPATHLEN
];
1549 zone_get_devroot_t real_zone_get_devroot
;
1554 if ((dlhandle
= dlopen("libzonecfg.so.1", RTLD_LAZY
)) == NULL
)
1557 if ((sym
= dlsym(dlhandle
, "zone_get_devroot")) == NULL
) {
1558 (void) dlclose(dlhandle
);
1562 real_zone_get_devroot
= (zone_get_devroot_t
)sym
;
1564 if ((ret
= real_zone_get_devroot(zone_name
, root
, sizeof (root
))) == 0)
1565 (void) snprintf(dev
, devlen
, "%s%s", root
, "/dev");
1566 (void) dlclose(dlhandle
);
1570 static dladm_status_t
1571 i_dladm_update_deventry(dladm_handle_t handle
, zoneid_t zid
,
1572 datalink_id_t linkid
, boolean_t add
)
1574 char path
[MAXPATHLEN
];
1575 char name
[MAXLINKNAMELEN
];
1576 di_prof_t prof
= NULL
;
1577 char zone_name
[ZONENAME_MAX
];
1578 dladm_status_t status
;
1581 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0)
1582 return (dladm_errno2status(errno
));
1583 if (i_dladm_get_zone_dev(zone_name
, path
, sizeof (path
)) != 0)
1584 return (dladm_errno2status(errno
));
1585 if (di_prof_init(path
, &prof
) != 0)
1586 return (dladm_errno2status(errno
));
1588 status
= dladm_linkid2legacyname(handle
, linkid
, name
, MAXLINKNAMELEN
);
1589 if (status
!= DLADM_STATUS_OK
)
1593 ret
= di_prof_add_dev(prof
, name
);
1595 ret
= di_prof_add_exclude(prof
, name
);
1598 status
= dladm_errno2status(errno
);
1602 if (di_prof_commit(prof
) != 0)
1603 status
= dladm_errno2status(errno
);
1612 static dladm_status_t
1613 set_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1614 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
1616 dladm_status_t status
= DLADM_STATUS_OK
;
1617 zoneid_t zid_old
, zid_new
;
1621 return (DLADM_STATUS_BADVALCNT
);
1623 dzp
= (dld_ioc_zid_t
*)vdp
->vd_val
;
1625 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1626 NULL
, &zid_old
, sizeof (zid_old
));
1627 if (status
!= DLADM_STATUS_OK
)
1630 zid_new
= dzp
->diz_zid
;
1631 if (zid_new
== zid_old
)
1632 return (DLADM_STATUS_OK
);
1634 if ((status
= set_public_prop(handle
, pdp
, linkid
, vdp
, val_cnt
,
1635 flags
, media
)) != DLADM_STATUS_OK
)
1639 * It is okay to fail to update the /dev entry (some vanity-named
1640 * links do not have a /dev entry).
1642 if (zid_old
!= GLOBAL_ZONEID
) {
1643 (void) i_dladm_update_deventry(handle
, zid_old
, linkid
,
1646 if (zid_new
!= GLOBAL_ZONEID
)
1647 (void) i_dladm_update_deventry(handle
, zid_new
, linkid
, B_TRUE
);
1649 return (DLADM_STATUS_OK
);
1653 static dladm_status_t
1654 check_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1655 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1656 datalink_media_t media
)
1660 dladm_status_t status
= DLADM_STATUS_OK
;
1662 uint_t val_cnt
= *val_cntp
;
1663 val_desc_t
*vdp
= *vdpp
;
1666 return (DLADM_STATUS_BADVALCNT
);
1668 dzp
= malloc(sizeof (dld_ioc_zid_t
));
1670 return (DLADM_STATUS_NOMEM
);
1672 zone_name
= (prop_val
!= NULL
) ? *prop_val
: GLOBAL_ZONENAME
;
1673 if ((zoneid
= getzoneidbyname(zone_name
)) == -1) {
1674 status
= DLADM_STATUS_BADVAL
;
1678 if (zoneid
!= GLOBAL_ZONEID
) {
1681 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &flags
,
1682 sizeof (flags
)) < 0) {
1683 status
= dladm_errno2status(errno
);
1687 if (!(flags
& ZF_NET_EXCL
)) {
1688 status
= DLADM_STATUS_BADVAL
;
1693 (void) memset(dzp
, 0, sizeof (dld_ioc_zid_t
));
1695 dzp
->diz_zid
= zoneid
;
1696 dzp
->diz_linkid
= linkid
;
1698 vdp
->vd_val
= (uintptr_t)dzp
;
1699 return (DLADM_STATUS_OK
);
1706 static dladm_status_t
1707 get_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1708 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1709 uint_t flags
, uint_t
*perm_flags
)
1711 mac_resource_props_t mrp
;
1712 dladm_status_t status
;
1714 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
1715 perm_flags
, &mrp
, sizeof (mrp
));
1716 if (status
!= DLADM_STATUS_OK
)
1719 if ((mrp
.mrp_mask
& MRP_MAXBW
) == 0) {
1721 return (DLADM_STATUS_OK
);
1724 (void) dladm_bw2str(mrp
.mrp_maxbw
, prop_val
[0]);
1726 return (DLADM_STATUS_OK
);
1730 static dladm_status_t
1731 check_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1732 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1733 datalink_media_t media
)
1736 dladm_status_t status
= DLADM_STATUS_OK
;
1737 uint_t val_cnt
= *val_cntp
;
1738 val_desc_t
*vdp
= *vdpp
;
1741 return (DLADM_STATUS_BADVALCNT
);
1743 maxbw
= malloc(sizeof (uint64_t));
1745 return (DLADM_STATUS_NOMEM
);
1747 status
= dladm_str2bw(*prop_val
, maxbw
);
1748 if (status
!= DLADM_STATUS_OK
) {
1753 if ((*maxbw
< MRP_MAXBW_MINVAL
) && (*maxbw
!= 0)) {
1755 return (DLADM_STATUS_MINMAXBW
);
1758 vdp
->vd_val
= (uintptr_t)maxbw
;
1759 return (DLADM_STATUS_OK
);
1764 extract_maxbw(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1766 mac_resource_props_t
*mrp
= arg
;
1768 if (vdp
->vd_val
== RESET_VAL
) {
1769 mrp
->mrp_maxbw
= MRP_MAXBW_RESETVAL
;
1771 bcopy((char *)vdp
->vd_val
, &mrp
->mrp_maxbw
, sizeof (uint64_t));
1773 mrp
->mrp_mask
|= MRP_MAXBW
;
1775 return (DLADM_STATUS_OK
);
1779 static dladm_status_t
1780 get_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1781 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1782 uint_t flags
, uint_t
*perm_flags
)
1784 dladm_status_t status
;
1785 mac_resource_props_t mrp
;
1786 mac_propval_range_t
*pv_range
;
1789 if (strcmp(pdp
->pd_name
, "cpus-effective") == 0) {
1790 status
= i_dladm_get_public_prop(handle
, linkid
,
1791 "resource-effective", flags
, perm_flags
, &mrp
,
1794 status
= i_dladm_get_public_prop(handle
, linkid
,
1795 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1798 if (status
!= DLADM_STATUS_OK
)
1801 if (mrp
.mrp_ncpus
> *val_cnt
)
1802 return (DLADM_STATUS_TOOSMALL
);
1804 if (mrp
.mrp_ncpus
== 0) {
1806 return (DLADM_STATUS_OK
);
1809 /* Sort CPU list and convert it to a mac_propval_range */
1810 status
= dladm_list2range(mrp
.mrp_cpu
, mrp
.mrp_ncpus
,
1811 MAC_PROPVAL_UINT32
, &pv_range
);
1812 if (status
!= DLADM_STATUS_OK
)
1815 /* Write CPU ranges and individual CPUs */
1816 err
= dladm_range2strs(pv_range
, prop_val
);
1819 return (dladm_errno2status(err
));
1822 *val_cnt
= pv_range
->mpr_count
;
1825 return (DLADM_STATUS_OK
);
1829 static dladm_status_t
1830 check_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1831 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1832 datalink_media_t media
)
1835 long nproc
= sysconf(_SC_NPROCESSORS_CONF
);
1836 mac_resource_props_t mrp
;
1837 mac_propval_range_t
*pv_range
;
1840 uint32_t *cpus
= mrp
.mrp_cpu
;
1841 val_desc_t
*vdp
= *vdpp
;
1843 uint_t val_cnt
= *val_cntp
;
1844 dladm_status_t status
= DLADM_STATUS_OK
;
1846 /* Get the current pool property */
1847 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
1848 &perm_flags
, &mrp
, sizeof (mrp
));
1850 if (status
== DLADM_STATUS_OK
) {
1851 /* Can't set cpus if a pool is set */
1852 if (strlen(mrp
.mrp_pool
) != 0)
1853 return (DLADM_STATUS_POOLCPU
);
1856 /* Read ranges and convert to mac_propval_range */
1857 status
= dladm_strs2range(prop_val
, val_cnt
, MAC_PROPVAL_UINT32
,
1859 if (status
!= DLADM_STATUS_OK
)
1862 /* Convert mac_propval_range to a single CPU list */
1864 status
= dladm_range2list(pv_range
, cpus
, &ncpus
);
1865 if (status
!= DLADM_STATUS_OK
)
1869 * If a range of CPUs was entered, update value count and reallocate
1870 * the array of val_desc_t's. The array allocated was sized for
1871 * indvidual elements, but needs to be reallocated to accomodate the
1872 * expanded list of CPUs.
1874 if (val_cnt
< ncpus
) {
1875 newvdp
= calloc(*val_cntp
, sizeof (val_desc_t
));
1876 if (newvdp
== NULL
) {
1877 status
= DLADM_STATUS_NOMEM
;
1883 /* Check if all CPUs in the list are online */
1884 for (i
= 0; i
< ncpus
; i
++) {
1885 if (cpus
[i
] >= nproc
) {
1886 status
= DLADM_STATUS_BADCPUID
;
1890 rc
= p_online(cpus
[i
], P_STATUS
);
1892 status
= DLADM_STATUS_CPUERR
;
1896 if (rc
!= P_ONLINE
) {
1897 status
= DLADM_STATUS_CPUNOTONLINE
;
1901 vdp
[i
].vd_val
= (uintptr_t)cpus
[i
];
1904 /* Check for duplicate CPUs */
1905 for (i
= 0; i
< *val_cntp
; i
++) {
1906 for (j
= 0; j
< *val_cntp
; j
++) {
1907 if (i
!= j
&& vdp
[i
].vd_val
== vdp
[j
].vd_val
) {
1908 status
= DLADM_STATUS_BADVAL
;
1914 /* Update *val_cntp and *vdpp if everything was OK */
1915 if (val_cnt
< ncpus
) {
1921 status
= DLADM_STATUS_OK
;
1933 extract_cpus(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1935 mac_resource_props_t
*mrp
= arg
;
1938 if (vdp
[0].vd_val
== RESET_VAL
) {
1939 bzero(&mrp
->mrp_cpus
, sizeof (mac_cpus_t
));
1940 mrp
->mrp_mask
|= MRP_CPUS
;
1941 return (DLADM_STATUS_OK
);
1944 for (i
= 0; i
< cnt
; i
++)
1945 mrp
->mrp_cpu
[i
] = (uint32_t)vdp
[i
].vd_val
;
1947 mrp
->mrp_ncpus
= cnt
;
1948 mrp
->mrp_mask
|= (MRP_CPUS
|MRP_CPUS_USERSPEC
);
1949 mrp
->mrp_fanout_mode
= MCM_CPUS
;
1950 mrp
->mrp_rx_intr_cpu
= -1;
1952 return (DLADM_STATUS_OK
);
1956 * Get the pool datalink property from the kernel. This is used
1957 * for both the user specified pool and effective pool properties.
1960 static dladm_status_t
1961 get_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1962 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1963 uint_t flags
, uint_t
*perm_flags
)
1965 mac_resource_props_t mrp
;
1966 dladm_status_t status
;
1968 if (strcmp(pdp
->pd_name
, "pool-effective") == 0) {
1969 status
= i_dladm_get_public_prop(handle
, linkid
,
1970 "resource-effective", flags
, perm_flags
, &mrp
,
1973 status
= i_dladm_get_public_prop(handle
, linkid
,
1974 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1977 if (status
!= DLADM_STATUS_OK
)
1980 if (strlen(mrp
.mrp_pool
) == 0) {
1981 (*prop_val
)[0] = '\0';
1983 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
1984 "%s", mrp
.mrp_pool
);
1988 return (DLADM_STATUS_OK
);
1992 static dladm_status_t
1993 check_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1994 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1995 datalink_media_t media
)
1997 pool_conf_t
*poolconf
;
1999 mac_resource_props_t mrp
;
2000 dladm_status_t status
;
2003 val_desc_t
*vdp
= *vdpp
;
2005 /* Get the current cpus property */
2006 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
2007 &perm_flags
, &mrp
, sizeof (mrp
));
2009 if (status
== DLADM_STATUS_OK
) {
2010 /* Can't set pool if cpus are set */
2011 if (mrp
.mrp_ncpus
!= 0)
2012 return (DLADM_STATUS_POOLCPU
);
2015 poolname
= malloc(sizeof (mrp
.mrp_pool
));
2016 if (poolname
== NULL
)
2017 return (DLADM_STATUS_NOMEM
);
2019 /* Check for pool's availability if not booting */
2020 if ((flags
& DLADM_OPT_BOOT
) == 0) {
2022 /* Allocate and open pool configuration */
2023 if ((poolconf
= pool_conf_alloc()) == NULL
)
2024 return (DLADM_STATUS_BADVAL
);
2026 if (pool_conf_open(poolconf
, pool_dynamic_location(), PO_RDONLY
)
2028 pool_conf_free(poolconf
);
2029 return (DLADM_STATUS_BADVAL
);
2032 /* Look for pool name */
2033 if ((pool
= pool_get_pool(poolconf
, *prop_val
)) == NULL
) {
2034 pool_conf_free(poolconf
);
2035 return (DLADM_STATUS_BADVAL
);
2038 pool_conf_free(poolconf
);
2042 (void) strlcpy(poolname
, *prop_val
, sizeof (mrp
.mrp_pool
));
2043 vdp
->vd_val
= (uintptr_t)poolname
;
2045 return (DLADM_STATUS_OK
);
2050 extract_pool(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2052 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2054 if (vdp
->vd_val
== RESET_VAL
) {
2055 bzero(&mrp
->mrp_pool
, sizeof (mrp
->mrp_pool
));
2056 mrp
->mrp_mask
|= MRP_POOL
;
2057 return (DLADM_STATUS_OK
);
2060 (void) strlcpy(mrp
->mrp_pool
, (char *)vdp
->vd_val
,
2061 sizeof (mrp
->mrp_pool
));
2062 mrp
->mrp_mask
|= MRP_POOL
;
2064 * Use MCM_CPUS since the fanout count is not user specified
2065 * and will be determined by the cpu list generated from the
2068 mrp
->mrp_fanout_mode
= MCM_CPUS
;
2070 return (DLADM_STATUS_OK
);
2074 static dladm_status_t
2075 get_priority(dladm_handle_t handle
, prop_desc_t
*pdp
,
2076 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2077 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2079 mac_resource_props_t mrp
;
2080 mac_priority_level_t pri
;
2081 dladm_status_t status
;
2083 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2084 perm_flags
, &mrp
, sizeof (mrp
));
2085 if (status
!= DLADM_STATUS_OK
)
2088 pri
= ((mrp
.mrp_mask
& MRP_PRIORITY
) == 0) ? MPL_HIGH
:
2091 (void) dladm_pri2str(pri
, prop_val
[0]);
2093 return (DLADM_STATUS_OK
);
2098 extract_priority(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2100 mac_resource_props_t
*mrp
= arg
;
2103 return (DLADM_STATUS_BADVAL
);
2105 mrp
->mrp_priority
= (mac_priority_level_t
)vdp
->vd_val
;
2106 mrp
->mrp_mask
|= MRP_PRIORITY
;
2108 return (DLADM_STATUS_OK
);
2112 * Determines the size of the structure that needs to be sent to drivers
2113 * for retrieving the property range values.
2116 i_dladm_range_size(mac_propval_range_t
*r
, size_t *sz
, uint_t
*rcount
)
2118 uint_t count
= r
->mpr_count
;
2120 *sz
= sizeof (mac_propval_range_t
);
2124 switch (r
->mpr_type
) {
2125 case MAC_PROPVAL_UINT32
:
2126 *sz
+= (count
* sizeof (mac_propval_uint32_range_t
));
2138 static dladm_status_t
2139 check_rings(dladm_handle_t handle
, prop_desc_t
*pdp
,
2140 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2141 val_desc_t
**vp
, datalink_media_t media
)
2143 uint_t val_cnt
= *val_cntp
;
2144 val_desc_t
*v
= *vp
;
2147 return (DLADM_STATUS_BADVAL
);
2148 if (strncasecmp(prop_val
[0], "hw", strlen("hw")) == 0) {
2149 v
->vd_val
= UNSPEC_VAL
;
2150 } else if (strncasecmp(prop_val
[0], "sw", strlen("sw")) == 0) {
2153 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
2155 return (DLADM_STATUS_BADVAL
);
2157 return (DLADM_STATUS_OK
);
2161 static dladm_status_t
2162 get_rings_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
2163 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2164 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2166 dld_ioc_macprop_t
*dip
;
2167 dladm_status_t status
= DLADM_STATUS_OK
;
2168 mac_propval_range_t
*rangep
;
2170 mac_propval_uint32_range_t
*ur
;
2172 sz
= sizeof (mac_propval_range_t
);
2174 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
2178 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
2179 if (status
!= DLADM_STATUS_OK
)
2182 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
2184 ur
= &rangep
->mpr_range_uint32
[0];
2185 /* This is the case where the dev doesn't have any rings/groups */
2186 if (rangep
->mpr_count
== 0) {
2187 (*prop_val
)[0] = '\0';
2189 * This is the case where the dev supports rings, but static
2192 } else if (ur
->mpur_min
== ur
->mpur_max
&&
2193 ur
->mpur_max
== 0) {
2194 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw");
2196 * This is the case where the dev supports rings and dynamic
2197 * grouping, but has only one value (say 2 rings and 2 groups).
2199 } else if (ur
->mpur_min
== ur
->mpur_max
) {
2200 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw,%d",
2203 * This is the case where the dev supports rings and dynamic
2204 * grouping and has a range of rings.
2207 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
,
2208 "sw,hw,<%ld-%ld>", ur
->mpur_min
, ur
->mpur_max
);
2216 static dladm_status_t
2217 get_rxrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2218 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2219 uint_t flags
, uint_t
*perm_flags
)
2221 mac_resource_props_t mrp
;
2222 dladm_status_t status
;
2223 uint32_t nrings
= 0;
2226 * Get the number of (effective-)rings from the resource property.
2228 if (strcmp(pdp
->pd_name
, "rxrings-effective") == 0) {
2229 status
= i_dladm_get_public_prop(handle
, linkid
,
2230 "resource-effective", flags
, perm_flags
, &mrp
,
2234 * Get the permissions from the "rxrings" property.
2236 status
= i_dladm_get_public_prop(handle
, linkid
, "rxrings",
2237 flags
, perm_flags
, NULL
, 0);
2238 if (status
!= DLADM_STATUS_OK
)
2241 status
= i_dladm_get_public_prop(handle
, linkid
,
2242 "resource", flags
, NULL
, &mrp
, sizeof (mrp
));
2245 if (status
!= DLADM_STATUS_OK
)
2248 if ((mrp
.mrp_mask
& MRP_RX_RINGS
) == 0) {
2250 return (DLADM_STATUS_OK
);
2252 nrings
= mrp
.mrp_nrxrings
;
2254 if (mrp
.mrp_mask
& MRP_RXRINGS_UNSPEC
)
2255 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2256 else if (nrings
== 0)
2257 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2259 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2260 return (DLADM_STATUS_OK
);
2265 extract_rxrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2267 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2269 mrp
->mrp_nrxrings
= 0;
2270 if (vdp
->vd_val
== RESET_VAL
)
2271 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2272 else if (vdp
->vd_val
== UNSPEC_VAL
)
2273 mrp
->mrp_mask
= MRP_RXRINGS_UNSPEC
;
2275 mrp
->mrp_nrxrings
= vdp
->vd_val
;
2276 mrp
->mrp_mask
|= MRP_RX_RINGS
;
2278 return (DLADM_STATUS_OK
);
2282 static dladm_status_t
2283 get_txrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2284 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2285 uint_t flags
, uint_t
*perm_flags
)
2287 mac_resource_props_t mrp
;
2288 dladm_status_t status
;
2289 uint32_t nrings
= 0;
2293 * Get the number of (effective-)rings from the resource property.
2295 if (strcmp(pdp
->pd_name
, "txrings-effective") == 0) {
2296 status
= i_dladm_get_public_prop(handle
, linkid
,
2297 "resource-effective", flags
, perm_flags
, &mrp
,
2301 * Get the permissions from the "txrings" property.
2303 status
= i_dladm_get_public_prop(handle
, linkid
, "txrings",
2304 flags
, perm_flags
, NULL
, 0);
2305 if (status
!= DLADM_STATUS_OK
)
2309 * Get the number of rings from the "resource" property.
2311 status
= i_dladm_get_public_prop(handle
, linkid
, "resource",
2312 flags
, NULL
, &mrp
, sizeof (mrp
));
2315 if (status
!= DLADM_STATUS_OK
)
2318 if ((mrp
.mrp_mask
& MRP_TX_RINGS
) == 0) {
2320 return (DLADM_STATUS_OK
);
2322 nrings
= mrp
.mrp_ntxrings
;
2324 if (mrp
.mrp_mask
& MRP_TXRINGS_UNSPEC
)
2325 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2326 else if (nrings
== 0)
2327 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2329 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2330 return (DLADM_STATUS_OK
);
2335 extract_txrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2337 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2339 mrp
->mrp_ntxrings
= 0;
2340 if (vdp
->vd_val
== RESET_VAL
)
2341 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2342 else if (vdp
->vd_val
== UNSPEC_VAL
)
2343 mrp
->mrp_mask
= MRP_TXRINGS_UNSPEC
;
2345 mrp
->mrp_ntxrings
= vdp
->vd_val
;
2346 mrp
->mrp_mask
|= MRP_TX_RINGS
;
2348 return (DLADM_STATUS_OK
);
2352 static dladm_status_t
2353 get_cntavail(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2354 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
2357 if (flags
& DLD_PROP_DEFAULT
)
2358 return (DLADM_STATUS_NOTDEFINED
);
2360 return (get_uint32(handle
, pdp
, linkid
, prop_val
, val_cnt
, media
,
2361 flags
, perm_flags
));
2365 static dladm_status_t
2366 set_resource(dladm_handle_t handle
, prop_desc_t
*pdp
,
2367 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
2368 uint_t flags
, datalink_media_t media
)
2370 mac_resource_props_t mrp
;
2371 dladm_status_t status
= DLADM_STATUS_OK
;
2372 dld_ioc_macprop_t
*dip
;
2375 bzero(&mrp
, sizeof (mac_resource_props_t
));
2376 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "resource",
2382 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
2383 resource_prop_t
*rp
= &rsrc_prop_table
[i
];
2385 if (strcmp(pdp
->pd_name
, rp
->rp_name
) != 0)
2388 status
= rp
->rp_extract(vdp
, val_cnt
, &mrp
);
2389 if (status
!= DLADM_STATUS_OK
)
2395 (void) memcpy(dip
->pr_val
, &mrp
, dip
->pr_valsize
);
2396 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
2404 static dladm_status_t
2405 get_protection(dladm_handle_t handle
, prop_desc_t
*pdp
,
2406 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2407 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2409 mac_resource_props_t mrp
;
2411 dladm_status_t status
;
2412 uint32_t i
, cnt
= 0, setbits
[32];
2414 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2415 perm_flags
, &mrp
, sizeof (mrp
));
2416 if (status
!= DLADM_STATUS_OK
)
2419 p
= &mrp
.mrp_protect
;
2420 if ((mrp
.mrp_mask
& MRP_PROTECT
) == 0) {
2422 return (DLADM_STATUS_OK
);
2424 dladm_find_setbits32(p
->mp_types
, setbits
, &cnt
);
2426 return (DLADM_STATUS_BADVALCNT
);
2428 for (i
= 0; i
< cnt
; i
++)
2429 (void) dladm_protect2str(setbits
[i
], prop_val
[i
]);
2432 return (DLADM_STATUS_OK
);
2436 static dladm_status_t
2437 get_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2438 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2439 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2441 mac_resource_props_t mrp
;
2443 dladm_status_t status
;
2446 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2447 perm_flags
, &mrp
, sizeof (mrp
));
2448 if (status
!= DLADM_STATUS_OK
)
2451 p
= &mrp
.mrp_protect
;
2452 if (p
->mp_ipaddrcnt
== 0) {
2454 return (DLADM_STATUS_OK
);
2456 if (p
->mp_ipaddrcnt
> *val_cnt
)
2457 return (DLADM_STATUS_BADVALCNT
);
2459 for (i
= 0; i
< p
->mp_ipaddrcnt
; i
++) {
2461 if (p
->mp_ipaddrs
[i
].ip_version
== IPV4_VERSION
) {
2464 v4addr
= V4_PART_OF_V6(p
->mp_ipaddrs
[i
].ip_addr
);
2465 (void) dladm_ipv4addr2str(&v4addr
, prop_val
[i
]);
2467 (void) dladm_ipv6addr2str(&p
->mp_ipaddrs
[i
].ip_addr
,
2470 len
= strlen(prop_val
[i
]);
2471 (void) sprintf(prop_val
[i
] + len
, "/%d",
2472 p
->mp_ipaddrs
[i
].ip_netmask
);
2474 *val_cnt
= p
->mp_ipaddrcnt
;
2475 return (DLADM_STATUS_OK
);
2479 extract_protection(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2481 mac_resource_props_t
*mrp
= arg
;
2485 for (i
= 0; i
< cnt
; i
++)
2486 types
|= (uint32_t)vdp
[i
].vd_val
;
2488 mrp
->mrp_protect
.mp_types
= types
;
2489 mrp
->mrp_mask
|= MRP_PROTECT
;
2490 return (DLADM_STATUS_OK
);
2494 extract_allowedips(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2496 mac_resource_props_t
*mrp
= arg
;
2497 mac_protect_t
*p
= &mrp
->mrp_protect
;
2500 if (vdp
->vd_val
== 0) {
2503 for (i
= 0; i
< cnt
; i
++) {
2504 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_ipaddrs
[i
],
2505 sizeof (mac_ipaddr_t
));
2508 p
->mp_ipaddrcnt
= cnt
;
2509 mrp
->mrp_mask
|= MRP_PROTECT
;
2510 return (DLADM_STATUS_OK
);
2513 static dladm_status_t
2514 check_single_ip(char *buf
, mac_ipaddr_t
*addr
)
2516 dladm_status_t status
;
2519 boolean_t isv4
= B_TRUE
;
2524 * If the IP address is in CIDR format, parse the bits component
2525 * seperately. An address in this style will be used to indicate an
2526 * entire subnet, so it must be a network number with no host address.
2528 if ((p
= strchr(buf
, '/')) != NULL
) {
2533 return (DLADM_STATUS_INVALID_IP
);
2534 mask
= strtol(p
, &end
, 10);
2535 if (end
!= NULL
&& *end
!= '\0')
2536 return (DLADM_STATUS_INVALID_IP
);
2537 if (mask
> 128|| mask
< 1)
2538 return (DLADM_STATUS_INVALID_IP
);
2541 status
= dladm_str2ipv4addr(buf
, &v4addr
);
2542 if (status
== DLADM_STATUS_INVALID_IP
) {
2543 status
= dladm_str2ipv6addr(buf
, &v6addr
);
2544 if (status
== DLADM_STATUS_OK
)
2547 if (status
!= DLADM_STATUS_OK
)
2551 if (v4addr
== INADDR_ANY
)
2552 return (DLADM_STATUS_INVALID_IP
);
2554 IN6_IPADDR_TO_V4MAPPED(v4addr
, &addr
->ip_addr
);
2555 addr
->ip_version
= IPV4_VERSION
;
2560 * Validate the netmask is in the proper range for v4
2562 if (mask
> 32 || mask
< 1)
2563 return (DLADM_STATUS_INVALID_IP
);
2566 * We have a CIDR style address, confirm that only the
2567 * network number is set.
2569 smask
= 0xFFFFFFFFu
<< (32 - mask
);
2570 if (htonl(v4addr
) & ~smask
)
2571 return (DLADM_STATUS_INVALID_IP
);
2575 addr
->ip_netmask
= mask
;
2577 if (IN6_IS_ADDR_UNSPECIFIED(&v6addr
))
2578 return (DLADM_STATUS_INVALID_IP
);
2580 if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr
))
2581 return (DLADM_STATUS_INVALID_IP
);
2587 * Note that the address in our buffer is stored in
2588 * network byte order.
2591 for (i
= 3; i
>= 0; i
--) {
2592 high
= ffsl(ntohl(v6addr
._S6_un
._S6_u32
[i
]));
2598 if (128 - off
>= mask
)
2599 return (DLADM_STATUS_INVALID_IP
);
2604 addr
->ip_addr
= v6addr
;
2605 addr
->ip_version
= IPV6_VERSION
;
2606 addr
->ip_netmask
= mask
;
2608 return (DLADM_STATUS_OK
);
2612 static dladm_status_t
2613 check_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2614 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2615 val_desc_t
**vdpp
, datalink_media_t media
)
2617 dladm_status_t status
;
2620 uint_t val_cnt
= *val_cntp
;
2621 val_desc_t
*vdp
= *vdpp
;
2623 if (val_cnt
> MPT_MAXIPADDR
)
2624 return (DLADM_STATUS_BADVALCNT
);
2626 for (i
= 0; i
< val_cnt
; i
++) {
2627 if ((addr
= calloc(1, sizeof (mac_ipaddr_t
))) == NULL
) {
2628 status
= DLADM_STATUS_NOMEM
;
2631 vdp
[i
].vd_val
= (uintptr_t)addr
;
2633 status
= check_single_ip(prop_val
[i
], addr
);
2634 if (status
!= DLADM_STATUS_OK
)
2637 return (DLADM_STATUS_OK
);
2640 for (i
= 0; i
< val_cnt
; i
++) {
2641 free((void *)vdp
[i
].vd_val
);
2642 vdp
[i
].vd_val
= NULL
;
2648 dladm_cid2str(mac_dhcpcid_t
*cid
, char *buf
)
2650 char tmp_buf
[DLADM_STRSIZE
];
2653 switch (cid
->dc_form
) {
2654 case CIDFORM_TYPED
: {
2655 uint16_t duidtype
, hwtype
;
2656 uint32_t timestamp
, ennum
;
2659 if (cid
->dc_len
< sizeof (duidtype
))
2662 bcopy(cid
->dc_id
, &duidtype
, sizeof (duidtype
));
2663 duidtype
= ntohs(duidtype
);
2665 case DHCPV6_DUID_LLT
: {
2668 if (cid
->dc_len
< sizeof (llt
))
2671 bcopy(cid
->dc_id
, &llt
, sizeof (llt
));
2672 hwtype
= ntohs(llt
.dllt_hwtype
);
2673 timestamp
= ntohl(llt
.dllt_time
);
2674 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (llt
),
2675 NULL
, cid
->dc_len
- sizeof (llt
), IFT_OTHER
);
2679 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%d.%s",
2680 duidtype
, hwtype
, timestamp
, lladdr
);
2684 case DHCPV6_DUID_EN
: {
2687 if (cid
->dc_len
< sizeof (en
))
2690 bcopy(cid
->dc_id
, &en
, sizeof (en
));
2691 ennum
= DHCPV6_GET_ENTNUM(&en
);
2692 hexlen
= sizeof (tmp_buf
);
2693 if (octet_to_hexascii(cid
->dc_id
+ sizeof (en
),
2694 cid
->dc_len
- sizeof (en
), tmp_buf
, &hexlen
) != 0)
2697 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2698 duidtype
, ennum
, tmp_buf
);
2701 case DHCPV6_DUID_LL
: {
2704 if (cid
->dc_len
< sizeof (ll
))
2707 bcopy(cid
->dc_id
, &ll
, sizeof (ll
));
2708 hwtype
= ntohs(ll
.dll_hwtype
);
2709 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (ll
),
2710 NULL
, cid
->dc_len
- sizeof (ll
), IFT_OTHER
);
2714 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2715 duidtype
, hwtype
, lladdr
);
2720 hexlen
= sizeof (tmp_buf
);
2721 if (octet_to_hexascii(cid
->dc_id
+ sizeof (duidtype
),
2722 cid
->dc_len
- sizeof (duidtype
),
2723 tmp_buf
, &hexlen
) != 0)
2726 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%s",
2733 hexlen
= sizeof (tmp_buf
);
2734 if (octet_to_hexascii(cid
->dc_id
, cid
->dc_len
,
2735 tmp_buf
, &hexlen
) != 0)
2738 (void) snprintf(buf
, DLADM_STRSIZE
, "0x%s", tmp_buf
);
2744 for (i
= 0; i
< cid
->dc_len
; i
++) {
2745 if (!isprint(cid
->dc_id
[i
]))
2748 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", cid
->dc_id
);
2757 (void) snprintf(buf
, DLADM_STRSIZE
, "<unknown>");
2760 static dladm_status_t
2761 dladm_str2cid(char *buf
, mac_dhcpcid_t
*cid
)
2764 char tmp_buf
[DLADM_STRSIZE
];
2765 uint_t hexlen
, cidlen
;
2767 bzero(cid
, sizeof (*cid
));
2768 if (isdigit(*ptr
) &&
2769 ptr
[strspn(ptr
, "0123456789")] == '.') {
2778 duidtype
= strtoul(ptr
, &cp
, 0);
2779 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.' ||
2780 duidtype
> USHRT_MAX
)
2781 return (DLADM_STATUS_BADARG
);
2784 if (duidtype
!= 0 && duidtype
<= DHCPV6_DUID_LL
) {
2786 subtype
= strtoul(ptr
, &cp
, 0);
2787 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2788 return (DLADM_STATUS_BADARG
);
2792 case DHCPV6_DUID_LLT
: {
2796 timestamp
= strtoul(ptr
, &cp
, 0);
2797 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2798 return (DLADM_STATUS_BADARG
);
2801 lladdr
= _link_aton(ptr
, &addrlen
);
2803 return (DLADM_STATUS_BADARG
);
2805 cidlen
= sizeof (llt
) + addrlen
;
2806 if (cidlen
> sizeof (cid
->dc_id
)) {
2808 return (DLADM_STATUS_TOOSMALL
);
2810 llt
.dllt_dutype
= htons(duidtype
);
2811 llt
.dllt_hwtype
= htons(subtype
);
2812 llt
.dllt_time
= htonl(timestamp
);
2813 bcopy(&llt
, cid
->dc_id
, sizeof (llt
));
2814 bcopy(lladdr
, cid
->dc_id
+ sizeof (llt
), addrlen
);
2818 case DHCPV6_DUID_LL
: {
2821 lladdr
= _link_aton(ptr
, &addrlen
);
2823 return (DLADM_STATUS_BADARG
);
2825 cidlen
= sizeof (ll
) + addrlen
;
2826 if (cidlen
> sizeof (cid
->dc_id
)) {
2828 return (DLADM_STATUS_TOOSMALL
);
2830 ll
.dll_dutype
= htons(duidtype
);
2831 ll
.dll_hwtype
= htons(subtype
);
2832 bcopy(&ll
, cid
->dc_id
, sizeof (ll
));
2833 bcopy(lladdr
, cid
->dc_id
+ sizeof (ll
), addrlen
);
2838 hexlen
= sizeof (tmp_buf
);
2839 if (hexascii_to_octet(ptr
, strlen(ptr
),
2840 tmp_buf
, &hexlen
) != 0)
2841 return (DLADM_STATUS_BADARG
);
2843 if (duidtype
== DHCPV6_DUID_EN
) {
2846 en
.den_dutype
= htons(duidtype
);
2847 DHCPV6_SET_ENTNUM(&en
, subtype
);
2849 cidlen
= sizeof (en
) + hexlen
;
2850 if (cidlen
> sizeof (cid
->dc_id
))
2851 return (DLADM_STATUS_TOOSMALL
);
2853 bcopy(&en
, cid
->dc_id
, sizeof (en
));
2854 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (en
),
2857 uint16_t dutype
= htons(duidtype
);
2859 cidlen
= sizeof (dutype
) + hexlen
;
2860 if (cidlen
> sizeof (cid
->dc_id
))
2861 return (DLADM_STATUS_TOOSMALL
);
2863 bcopy(&dutype
, cid
->dc_id
, sizeof (dutype
));
2864 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (dutype
),
2870 cid
->dc_form
= CIDFORM_TYPED
;
2871 } else if (strncasecmp("0x", ptr
, 2) == 0 && ptr
[2] != '\0') {
2873 hexlen
= sizeof (tmp_buf
);
2874 if (hexascii_to_octet(ptr
, strlen(ptr
), tmp_buf
,
2876 return (DLADM_STATUS_BADARG
);
2879 if (cidlen
> sizeof (cid
->dc_id
))
2880 return (DLADM_STATUS_TOOSMALL
);
2882 bcopy(tmp_buf
, cid
->dc_id
, cidlen
);
2883 cid
->dc_form
= CIDFORM_HEX
;
2885 cidlen
= strlen(ptr
);
2886 if (cidlen
> sizeof (cid
->dc_id
))
2887 return (DLADM_STATUS_TOOSMALL
);
2889 bcopy(ptr
, cid
->dc_id
, cidlen
);
2890 cid
->dc_form
= CIDFORM_STR
;
2892 cid
->dc_len
= cidlen
;
2893 return (DLADM_STATUS_OK
);
2897 static dladm_status_t
2898 get_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2899 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2900 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2902 mac_resource_props_t mrp
;
2904 dladm_status_t status
;
2907 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2908 perm_flags
, &mrp
, sizeof (mrp
));
2909 if (status
!= DLADM_STATUS_OK
)
2912 p
= &mrp
.mrp_protect
;
2913 if (p
->mp_cidcnt
== 0) {
2915 return (DLADM_STATUS_OK
);
2917 if (p
->mp_cidcnt
> *val_cnt
)
2918 return (DLADM_STATUS_BADVALCNT
);
2920 for (i
= 0; i
< p
->mp_cidcnt
; i
++) {
2921 mac_dhcpcid_t
*cid
= &p
->mp_cids
[i
];
2923 dladm_cid2str(cid
, prop_val
[i
]);
2925 *val_cnt
= p
->mp_cidcnt
;
2926 return (DLADM_STATUS_OK
);
2930 extract_allowedcids(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2932 mac_resource_props_t
*mrp
= arg
;
2933 mac_protect_t
*p
= &mrp
->mrp_protect
;
2936 if (vdp
->vd_val
== 0) {
2939 for (i
= 0; i
< cnt
; i
++) {
2940 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_cids
[i
],
2941 sizeof (mac_dhcpcid_t
));
2945 mrp
->mrp_mask
|= MRP_PROTECT
;
2946 return (DLADM_STATUS_OK
);
2950 static dladm_status_t
2951 check_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2952 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
2953 uint_t flags
, val_desc_t
**vdpp
, datalink_media_t media
)
2955 dladm_status_t status
;
2958 uint_t val_cnt
= *val_cntp
;
2959 val_desc_t
*vdp
= *vdpp
;
2961 if (val_cnt
> MPT_MAXCID
)
2962 return (DLADM_STATUS_BADVALCNT
);
2964 for (i
= 0; i
< val_cnt
; i
++) {
2965 if ((cid
= calloc(1, sizeof (mac_dhcpcid_t
))) == NULL
) {
2966 status
= DLADM_STATUS_NOMEM
;
2969 vdp
[i
].vd_val
= (uintptr_t)cid
;
2971 status
= dladm_str2cid(prop_val
[i
], cid
);
2972 if (status
!= DLADM_STATUS_OK
)
2975 return (DLADM_STATUS_OK
);
2978 for (i
= 0; i
< val_cnt
; i
++) {
2979 free((void *)vdp
[i
].vd_val
);
2980 vdp
[i
].vd_val
= NULL
;
2986 static dladm_status_t
2987 get_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
2988 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2989 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2991 mac_secondary_addr_t sa
;
2992 dladm_status_t status
;
2995 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
2996 perm_flags
, &sa
, sizeof (sa
));
2997 if (status
!= DLADM_STATUS_OK
)
3000 if (sa
.ms_addrcnt
> *val_cnt
)
3001 return (DLADM_STATUS_BADVALCNT
);
3003 for (i
= 0; i
< sa
.ms_addrcnt
; i
++) {
3004 if (dladm_aggr_macaddr2str(
3005 (const unsigned char *)&sa
.ms_addrs
[i
], prop_val
[i
]) ==
3008 return (DLADM_STATUS_NOMEM
);
3011 *val_cnt
= sa
.ms_addrcnt
;
3012 return (DLADM_STATUS_OK
);
3016 static dladm_status_t
3017 check_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
3018 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3019 val_desc_t
**vdpp
, datalink_media_t media
)
3021 dladm_status_t status
;
3025 uint_t val_cnt
= *val_cntp
;
3026 val_desc_t
*vdp
= *vdpp
;
3028 if (val_cnt
>= MPT_MAXMACADDR
)
3029 return (DLADM_STATUS_BADVALCNT
);
3031 for (i
= 0; i
< val_cnt
; i
++) {
3032 addr
= _link_aton(prop_val
[i
], (int *)&len
);
3034 if (len
== (uint_t
)-1)
3035 status
= DLADM_STATUS_MACADDRINVAL
;
3037 status
= DLADM_STATUS_NOMEM
;
3041 vdp
[i
].vd_val
= (uintptr_t)addr
;
3043 return (DLADM_STATUS_OK
);
3046 for (i
= 0; i
< val_cnt
; i
++) {
3047 free((void *)vdp
[i
].vd_val
);
3048 vdp
[i
].vd_val
= NULL
;
3054 static dladm_status_t
3055 set_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
3056 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3058 dladm_status_t status
;
3059 dld_ioc_macprop_t
*dip
;
3061 mac_secondary_addr_t msa
;
3063 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "secondary-macs", 0,
3068 if (vdp
->vd_val
== 0) {
3069 val_cnt
= (uint_t
)-1;
3071 for (i
= 0; i
< val_cnt
; i
++) {
3072 bcopy((void *)vdp
[i
].vd_val
, msa
.ms_addrs
[i
],
3076 msa
.ms_addrcnt
= val_cnt
;
3077 bcopy(&msa
, dip
->pr_val
, dip
->pr_valsize
);
3079 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3086 static dladm_status_t
3087 get_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3088 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3089 uint_t flags
, uint_t
*perm_flags
)
3091 struct dlautopush dlap
;
3093 dladm_status_t status
;
3095 if (flags
& DLD_PROP_DEFAULT
)
3096 return (DLADM_STATUS_NOTDEFINED
);
3098 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3099 perm_flags
, &dlap
, sizeof (dlap
));
3100 if (status
!= DLADM_STATUS_OK
)
3103 if (dlap
.dap_npush
== 0) {
3105 return (DLADM_STATUS_OK
);
3107 for (i
= 0, len
= 0; i
< dlap
.dap_npush
; i
++) {
3109 (void) snprintf(*prop_val
+ len
,
3110 DLADM_PROP_VAL_MAX
- len
, "%c", AP_DELIMITER
);
3113 (void) snprintf(*prop_val
+ len
, DLADM_PROP_VAL_MAX
- len
,
3114 "%s", dlap
.dap_aplist
[i
]);
3115 len
+= strlen(dlap
.dap_aplist
[i
]);
3116 if (dlap
.dap_anchor
- 1 == i
) {
3117 (void) snprintf(*prop_val
+ len
,
3118 DLADM_PROP_VAL_MAX
- len
, "%c%s", AP_DELIMITER
,
3120 len
+= (strlen(AP_ANCHOR
) + 1);
3124 return (DLADM_STATUS_OK
);
3128 * Add the specified module to the dlautopush structure; returns a
3129 * DLADM_STATUS_* code.
3132 i_dladm_add_ap_module(const char *module
, struct dlautopush
*dlap
)
3134 if ((strlen(module
) == 0) || (strlen(module
) > FMNAMESZ
))
3135 return (DLADM_STATUS_BADVAL
);
3137 if (strncasecmp(module
, AP_ANCHOR
, strlen(AP_ANCHOR
)) == 0) {
3139 * We don't allow multiple anchors, and the anchor must
3140 * be after at least one module.
3142 if (dlap
->dap_anchor
!= 0)
3143 return (DLADM_STATUS_BADVAL
);
3144 if (dlap
->dap_npush
== 0)
3145 return (DLADM_STATUS_BADVAL
);
3147 dlap
->dap_anchor
= dlap
->dap_npush
;
3148 return (DLADM_STATUS_OK
);
3150 if (dlap
->dap_npush
>= MAXAPUSH
)
3151 return (DLADM_STATUS_BADVALCNT
);
3153 (void) strlcpy(dlap
->dap_aplist
[dlap
->dap_npush
++], module
,
3156 return (DLADM_STATUS_OK
);
3160 * Currently, both '.' and ' '(space) can be used as the delimiters between
3161 * autopush modules. The former is used in dladm set-linkprop, and the
3162 * latter is used in the autopush(1M) file.
3165 static dladm_status_t
3166 check_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3167 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3168 datalink_media_t media
)
3171 struct dlautopush
*dlap
;
3172 dladm_status_t status
;
3173 char val
[DLADM_PROP_VAL_MAX
];
3175 uint_t val_cnt
= *val_cntp
;
3176 val_desc_t
*vdp
= *vdpp
;
3179 return (DLADM_STATUS_BADVALCNT
);
3181 if (prop_val
!= NULL
) {
3182 dlap
= malloc(sizeof (struct dlautopush
));
3184 return (DLADM_STATUS_NOMEM
);
3186 (void) memset(dlap
, 0, sizeof (struct dlautopush
));
3187 (void) snprintf(delimiters
, 4, " %c\n", AP_DELIMITER
);
3188 bcopy(*prop_val
, val
, DLADM_PROP_VAL_MAX
);
3189 module
= strtok(val
, delimiters
);
3190 while (module
!= NULL
) {
3191 status
= i_dladm_add_ap_module(module
, dlap
);
3192 if (status
!= DLADM_STATUS_OK
)
3194 module
= strtok(NULL
, delimiters
);
3197 vdp
->vd_val
= (uintptr_t)dlap
;
3201 return (DLADM_STATUS_OK
);
3204 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3207 static dladm_status_t
3208 get_rate_common(dladm_handle_t handle
, prop_desc_t
*pdp
,
3209 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
, uint_t id
,
3214 dladm_status_t status
= DLADM_STATUS_OK
;
3216 wrp
= malloc(WLDP_BUFSIZE
);
3218 return (DLADM_STATUS_NOMEM
);
3220 status
= i_dladm_wlan_param(handle
, linkid
, wrp
, id
, WLDP_BUFSIZE
,
3222 if (status
!= DLADM_STATUS_OK
)
3225 if (wrp
->wl_rates_num
> *val_cnt
) {
3226 status
= DLADM_STATUS_TOOSMALL
;
3230 if (wrp
->wl_rates_rates
[0] == 0) {
3231 prop_val
[0][0] = '\0';
3236 for (i
= 0; i
< wrp
->wl_rates_num
; i
++) {
3237 (void) snprintf(prop_val
[i
], DLADM_STRSIZE
, "%.*f",
3238 wrp
->wl_rates_rates
[i
] % 2,
3239 (float)wrp
->wl_rates_rates
[i
] / 2);
3241 *val_cnt
= wrp
->wl_rates_num
;
3242 *perm_flags
= MAC_PROP_PERM_RW
;
3249 static dladm_status_t
3250 get_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3251 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3252 uint_t flags
, uint_t
*perm_flags
)
3254 if (media
!= DL_WIFI
) {
3255 return (get_speed(handle
, pdp
, linkid
, prop_val
,
3256 val_cnt
, media
, flags
, perm_flags
));
3259 return (get_rate_common(handle
, pdp
, linkid
, prop_val
, val_cnt
,
3260 MAC_PROP_WL_DESIRED_RATES
, perm_flags
));
3264 static dladm_status_t
3265 get_rate_mod(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3266 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3267 uint_t flags
, uint_t
*perm_flags
)
3272 * Speed for ethernet links is unbounded. E.g., 802.11b
3273 * links can have a speed of 5.5 Gbps.
3275 return (DLADM_STATUS_NOTSUP
);
3278 return (get_rate_common(handle
, pdp
, linkid
, prop_val
,
3279 val_cnt
, MAC_PROP_WL_SUPPORTED_RATES
, perm_flags
));
3281 return (DLADM_STATUS_BADARG
);
3285 static dladm_status_t
3286 set_wlan_rate(dladm_handle_t handle
, datalink_id_t linkid
,
3287 dladm_wlan_rates_t
*rates
)
3292 dladm_status_t status
= DLADM_STATUS_OK
;
3294 wrp
= malloc(WLDP_BUFSIZE
);
3296 return (DLADM_STATUS_NOMEM
);
3298 bzero(wrp
, WLDP_BUFSIZE
);
3299 for (i
= 0; i
< rates
->wr_cnt
; i
++)
3300 wrp
->wl_rates_rates
[i
] = rates
->wr_rates
[i
];
3301 wrp
->wl_rates_num
= rates
->wr_cnt
;
3303 len
= offsetof(wl_rates_t
, wl_rates_rates
) +
3304 (rates
->wr_cnt
* sizeof (char)) + WIFI_BUF_OFFSET
;
3305 status
= i_dladm_wlan_param(handle
, linkid
, wrp
,
3306 MAC_PROP_WL_DESIRED_RATES
, len
, B_TRUE
);
3313 static dladm_status_t
3314 set_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3315 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3317 dladm_wlan_rates_t rates
;
3318 dladm_status_t status
;
3321 * can currently set rate on WIFI links only.
3323 if (media
!= DL_WIFI
)
3324 return (DLADM_STATUS_PROPRDONLY
);
3327 return (DLADM_STATUS_BADVALCNT
);
3330 rates
.wr_rates
[0] = vdp
[0].vd_val
;
3332 status
= set_wlan_rate(handle
, linkid
, &rates
);
3338 static dladm_status_t
3339 check_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3340 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3341 datalink_media_t media
)
3344 uint_t modval_cnt
= MAX_SUPPORT_RATES
;
3345 char *buf
, **modval
;
3346 dladm_status_t status
;
3348 uint_t val_cnt
= *val_cntp
;
3349 val_desc_t
*vdp
= *vdpp
;
3352 return (DLADM_STATUS_BADVALCNT
);
3354 buf
= malloc((sizeof (char *) + DLADM_STRSIZE
) *
3357 status
= DLADM_STATUS_NOMEM
;
3361 modval
= (char **)(void *)buf
;
3362 for (i
= 0; i
< MAX_SUPPORT_RATES
; i
++) {
3363 modval
[i
] = buf
+ sizeof (char *) * MAX_SUPPORT_RATES
+
3367 status
= get_rate_mod(handle
, NULL
, linkid
, modval
, &modval_cnt
,
3368 media
, 0, &perm_flags
);
3369 if (status
!= DLADM_STATUS_OK
)
3372 for (i
= 0; i
< modval_cnt
; i
++) {
3373 if (strcasecmp(*prop_val
, modval
[i
]) == 0) {
3374 vdp
->vd_val
= (uintptr_t)(uint_t
)
3375 (atof(*prop_val
) * 2);
3376 status
= DLADM_STATUS_OK
;
3380 if (i
== modval_cnt
)
3381 status
= DLADM_STATUS_BADVAL
;
3387 static dladm_status_t
3388 get_phyconf(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
3391 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_PHY_CONFIG
,
3396 static dladm_status_t
3397 get_channel(dladm_handle_t handle
, prop_desc_t
*pdp
,
3398 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3399 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3402 char buf
[WLDP_BUFSIZE
];
3403 dladm_status_t status
;
3404 wl_phy_conf_t wl_phy_conf
;
3406 if ((status
= get_phyconf(handle
, linkid
, buf
, sizeof (buf
)))
3410 (void) memcpy(&wl_phy_conf
, buf
, sizeof (wl_phy_conf
));
3411 if (!i_dladm_wlan_convert_chan(&wl_phy_conf
, &channel
))
3412 return (DLADM_STATUS_NOTFOUND
);
3414 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%u", channel
);
3416 *perm_flags
= MAC_PROP_PERM_READ
;
3417 return (DLADM_STATUS_OK
);
3421 static dladm_status_t
3422 get_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3423 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3424 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3428 char buf
[WLDP_BUFSIZE
];
3429 dladm_status_t status
;
3431 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3432 MAC_PROP_WL_POWER_MODE
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3435 (void) memcpy(&mode
, buf
, sizeof (mode
));
3436 switch (mode
.wl_ps_mode
) {
3447 return (DLADM_STATUS_NOTFOUND
);
3449 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3451 *perm_flags
= MAC_PROP_PERM_RW
;
3452 return (DLADM_STATUS_OK
);
3456 static dladm_status_t
3457 set_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3458 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3459 datalink_media_t media
)
3461 dladm_wlan_powermode_t powermode
= vdp
->vd_val
;
3462 wl_ps_mode_t ps_mode
;
3465 return (DLADM_STATUS_BADVALCNT
);
3467 (void) memset(&ps_mode
, 0xff, sizeof (ps_mode
));
3469 switch (powermode
) {
3470 case DLADM_WLAN_PM_OFF
:
3471 ps_mode
.wl_ps_mode
= WL_PM_AM
;
3473 case DLADM_WLAN_PM_MAX
:
3474 ps_mode
.wl_ps_mode
= WL_PM_MPS
;
3476 case DLADM_WLAN_PM_FAST
:
3477 ps_mode
.wl_ps_mode
= WL_PM_FAST
;
3480 return (DLADM_STATUS_NOTSUP
);
3482 return (i_dladm_wlan_param(handle
, linkid
, &ps_mode
,
3483 MAC_PROP_WL_POWER_MODE
, sizeof (ps_mode
), B_TRUE
));
3487 static dladm_status_t
3488 get_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3489 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3490 uint_t flags
, uint_t
*perm_flags
)
3494 char buf
[WLDP_BUFSIZE
];
3495 dladm_status_t status
;
3497 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3498 MAC_PROP_WL_RADIO
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3501 (void) memcpy(&radio
, buf
, sizeof (radio
));
3510 return (DLADM_STATUS_NOTFOUND
);
3512 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3514 *perm_flags
= MAC_PROP_PERM_RW
;
3515 return (DLADM_STATUS_OK
);
3519 static dladm_status_t
3520 set_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3521 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3523 dladm_wlan_radio_t radio
= vdp
->vd_val
;
3527 return (DLADM_STATUS_BADVALCNT
);
3530 case DLADM_WLAN_RADIO_ON
:
3533 case DLADM_WLAN_RADIO_OFF
:
3537 return (DLADM_STATUS_NOTSUP
);
3539 return (i_dladm_wlan_param(handle
, linkid
, &r
, MAC_PROP_WL_RADIO
,
3540 sizeof (r
), B_TRUE
));
3544 static dladm_status_t
3545 check_hoplimit(dladm_handle_t handle
, prop_desc_t
*pdp
,
3546 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3547 val_desc_t
**vdpp
, datalink_media_t media
)
3551 uint_t val_cnt
= *val_cntp
;
3552 val_desc_t
*vdp
= *vdpp
;
3555 return (DLADM_STATUS_BADVALCNT
);
3558 hlim
= strtol(*prop_val
, &ep
, 10);
3559 if (errno
!= 0 || ep
== *prop_val
|| hlim
< 1 ||
3560 hlim
> (int32_t)UINT8_MAX
)
3561 return (DLADM_STATUS_BADVAL
);
3563 return (DLADM_STATUS_OK
);
3567 static dladm_status_t
3568 check_encaplim(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3569 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3570 datalink_media_t media
)
3574 uint_t val_cnt
= *val_cntp
;
3575 val_desc_t
*vdp
= *vdpp
;
3577 if (media
!= DL_IPV6
)
3578 return (DLADM_STATUS_BADARG
);
3581 return (DLADM_STATUS_BADVALCNT
);
3584 elim
= strtol(*prop_val
, &ep
, 10);
3585 if (errno
!= 0 || ep
== *prop_val
|| elim
< 0 ||
3586 elim
> (int32_t)UINT8_MAX
)
3587 return (DLADM_STATUS_BADVAL
);
3589 return (DLADM_STATUS_OK
);
3592 static dladm_status_t
3593 i_dladm_set_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3594 const char *prop_name
, char **prop_val
, uint_t val_cnt
)
3596 char buf
[MAXLINELEN
];
3599 dladm_status_t status
;
3601 status
= dladm_open_conf(handle
, linkid
, &conf
);
3602 if (status
!= DLADM_STATUS_OK
)
3609 status
= dladm_unset_conf_field(handle
, conf
, prop_name
);
3610 if (status
== DLADM_STATUS_OK
)
3611 status
= dladm_write_conf(handle
, conf
);
3616 for (i
= 0; i
< val_cnt
; i
++) {
3617 (void) strlcat(buf
, prop_val
[i
], MAXLINELEN
);
3618 if (i
!= val_cnt
- 1)
3619 (void) strlcat(buf
, ",", MAXLINELEN
);
3622 status
= dladm_set_conf_field(handle
, conf
, prop_name
, DLADM_TYPE_STR
,
3624 if (status
== DLADM_STATUS_OK
)
3625 status
= dladm_write_conf(handle
, conf
);
3628 dladm_destroy_conf(handle
, conf
);
3632 static dladm_status_t
3633 i_dladm_get_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3634 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
3636 char buf
[MAXLINELEN
], *str
;
3639 dladm_status_t status
;
3641 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3642 if (status
!= DLADM_STATUS_OK
)
3645 status
= dladm_get_conf_field(handle
, conf
, prop_name
, buf
, MAXLINELEN
);
3646 if (status
!= DLADM_STATUS_OK
)
3649 str
= strtok(buf
, ",");
3650 while (str
!= NULL
) {
3651 if (cnt
== *val_cntp
) {
3652 status
= DLADM_STATUS_TOOSMALL
;
3655 (void) strlcpy(prop_val
[cnt
++], str
, DLADM_PROP_VAL_MAX
);
3656 str
= strtok(NULL
, ",");
3662 dladm_destroy_conf(handle
, conf
);
3667 * Walk persistent private link properties of a link.
3669 static dladm_status_t
3670 i_dladm_walk_linkprop_priv_db(dladm_handle_t handle
, datalink_id_t linkid
,
3671 void *arg
, int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
3673 dladm_status_t status
;
3675 char last_attr
[MAXLINKATTRLEN
];
3676 char attr
[MAXLINKATTRLEN
];
3677 char attrval
[MAXLINKATTRVALLEN
];
3680 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
3681 return (DLADM_STATUS_BADARG
);
3683 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3684 if (status
!= DLADM_STATUS_OK
)
3687 last_attr
[0] = '\0';
3688 while ((status
= dladm_getnext_conf_linkprop(handle
, conf
, last_attr
,
3689 attr
, attrval
, MAXLINKATTRVALLEN
, &attrsz
)) == DLADM_STATUS_OK
) {
3690 if (attr
[0] == '_') {
3691 if (func(handle
, linkid
, attr
, arg
) ==
3692 DLADM_WALK_TERMINATE
)
3695 (void) strlcpy(last_attr
, attr
, MAXLINKATTRLEN
);
3698 dladm_destroy_conf(handle
, conf
);
3699 return (DLADM_STATUS_OK
);
3702 static link_attr_t
*
3703 dladm_name2prop(const char *prop_name
)
3707 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3708 if (strcmp(p
->pp_name
, prop_name
) == 0)
3714 static link_attr_t
*
3715 dladm_id2prop(mac_prop_id_t propid
)
3719 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3720 if (p
->pp_id
== propid
)
3726 static dld_ioc_macprop_t
*
3727 i_dladm_buf_alloc_impl(size_t valsize
, datalink_id_t linkid
,
3728 const char *prop_name
, mac_prop_id_t propid
, uint_t flags
,
3729 dladm_status_t
*status
)
3732 dld_ioc_macprop_t
*dip
;
3734 *status
= DLADM_STATUS_OK
;
3735 dsize
= MAC_PROP_BUFSIZE(valsize
);
3736 dip
= malloc(dsize
);
3738 *status
= DLADM_STATUS_NOMEM
;
3742 dip
->pr_valsize
= valsize
;
3743 (void) strlcpy(dip
->pr_name
, prop_name
, sizeof (dip
->pr_name
));
3744 dip
->pr_linkid
= linkid
;
3745 dip
->pr_num
= propid
;
3746 dip
->pr_flags
= flags
;
3750 static dld_ioc_macprop_t
*
3751 i_dladm_buf_alloc_by_name(size_t valsize
, datalink_id_t linkid
,
3752 const char *prop_name
, uint_t flags
, dladm_status_t
*status
)
3756 p
= dladm_name2prop(prop_name
);
3757 valsize
= MAX(p
->pp_valsize
, valsize
);
3758 return (i_dladm_buf_alloc_impl(valsize
, linkid
, prop_name
, p
->pp_id
,
3762 static dld_ioc_macprop_t
*
3763 i_dladm_buf_alloc_by_id(size_t valsize
, datalink_id_t linkid
,
3764 mac_prop_id_t propid
, uint_t flags
, dladm_status_t
*status
)
3768 p
= dladm_id2prop(propid
);
3769 valsize
= MAX(p
->pp_valsize
, valsize
);
3770 return (i_dladm_buf_alloc_impl(valsize
, linkid
, p
->pp_name
, propid
,
3775 static dladm_status_t
3776 set_public_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
3777 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3778 datalink_media_t media
)
3780 dld_ioc_macprop_t
*dip
;
3781 dladm_status_t status
= DLADM_STATUS_OK
;
3787 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
, 0, &status
);
3791 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
3792 val
= (void *)vdp
->vd_val
;
3795 * Currently all 1/2/4-byte size properties are byte/word/int.
3796 * No need (yet) to distinguish these from arrays of same size.
3798 switch (dip
->pr_valsize
) {
3818 (void) memcpy(dip
->pr_val
, val
, dip
->pr_valsize
);
3820 dip
->pr_valsize
= 0;
3822 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3830 i_dladm_macprop(dladm_handle_t handle
, void *dip
, boolean_t set
)
3832 dladm_status_t status
= DLADM_STATUS_OK
;
3834 if (ioctl(dladm_dld_fd(handle
),
3835 (set
? DLDIOC_SETMACPROP
: DLDIOC_GETMACPROP
), dip
))
3836 status
= dladm_errno2status(errno
);
3841 static dladm_status_t
3842 i_dladm_get_public_prop(dladm_handle_t handle
, datalink_id_t linkid
,
3843 char *prop_name
, uint_t flags
, uint_t
*perm_flags
, void *arg
, size_t size
)
3845 dld_ioc_macprop_t
*dip
;
3846 dladm_status_t status
;
3848 dip
= i_dladm_buf_alloc_by_name(0, linkid
, prop_name
, flags
, &status
);
3850 return (DLADM_STATUS_NOMEM
);
3852 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
3853 if (status
!= DLADM_STATUS_OK
) {
3858 if (perm_flags
!= NULL
)
3859 *perm_flags
= dip
->pr_perm_flags
;
3862 (void) memcpy(arg
, dip
->pr_val
, size
);
3864 return (DLADM_STATUS_OK
);
3868 static dladm_status_t
3869 check_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3870 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3871 val_desc_t
**vp
, datalink_media_t media
)
3873 uint_t val_cnt
= *val_cntp
;
3874 val_desc_t
*v
= *vp
;
3877 return (DLADM_STATUS_BADVAL
);
3878 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
3879 return (DLADM_STATUS_OK
);
3883 static dladm_status_t
3884 get_duplex(dladm_handle_t handle
, prop_desc_t
*pdp
,
3885 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3886 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3888 link_duplex_t link_duplex
;
3889 dladm_status_t status
;
3891 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "link_duplex",
3892 KSTAT_DATA_UINT32
, &link_duplex
)) != 0)
3895 switch (link_duplex
) {
3896 case LINK_DUPLEX_FULL
:
3897 (void) strcpy(*prop_val
, "full");
3899 case LINK_DUPLEX_HALF
:
3900 (void) strcpy(*prop_val
, "half");
3903 (void) strcpy(*prop_val
, "unknown");
3907 return (DLADM_STATUS_OK
);
3911 static dladm_status_t
3912 get_speed(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3913 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
3916 uint64_t ifspeed
= 0;
3917 dladm_status_t status
;
3919 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "ifspeed",
3920 KSTAT_DATA_UINT64
, &ifspeed
)) != 0)
3923 if ((ifspeed
% 1000000) != 0) {
3924 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3925 "%llf", ifspeed
/ (float)1000000); /* Mbps */
3927 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3928 "%llu", ifspeed
/ 1000000); /* Mbps */
3931 *perm_flags
= MAC_PROP_PERM_READ
;
3932 return (DLADM_STATUS_OK
);
3936 static dladm_status_t
3937 get_link_state(dladm_handle_t handle
, prop_desc_t
*pdp
,
3938 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3939 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3941 link_state_t link_state
;
3942 dladm_status_t status
;
3944 status
= dladm_get_state(handle
, linkid
, &link_state
);
3945 if (status
!= DLADM_STATUS_OK
)
3948 switch (link_state
) {
3950 (void) strcpy(*prop_val
, "up");
3952 case LINK_STATE_DOWN
:
3953 (void) strcpy(*prop_val
, "down");
3956 (void) strcpy(*prop_val
, "unknown");
3960 *perm_flags
= MAC_PROP_PERM_READ
;
3961 return (DLADM_STATUS_OK
);
3965 static dladm_status_t
3966 get_binary(dladm_handle_t handle
, prop_desc_t
*pdp
,
3967 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3968 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3970 dladm_status_t status
;
3973 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3974 perm_flags
, &v
, sizeof (v
));
3975 if (status
!= DLADM_STATUS_OK
)
3978 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%d", (uint_t
)(v
> 0));
3980 return (DLADM_STATUS_OK
);
3984 static dladm_status_t
3985 get_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3986 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3987 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3989 dladm_status_t status
;
3992 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3993 perm_flags
, &v
, sizeof (v
));
3994 if (status
!= DLADM_STATUS_OK
)
3997 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", v
);
3999 return (DLADM_STATUS_OK
);
4003 static dladm_status_t
4004 get_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
4005 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4006 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4008 dld_ioc_macprop_t
*dip
;
4009 dladm_status_t status
= DLADM_STATUS_OK
;
4012 mac_propval_range_t
*rangep
;
4015 * As caller we don't know number of value ranges, the driver
4016 * supports. To begin with we assume that number to be 1. If the
4017 * buffer size is insufficient, driver returns back with the
4018 * actual count of value ranges. See mac.h for more details.
4020 sz
= sizeof (mac_propval_range_t
);
4023 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
4027 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
4028 rangep
->mpr_count
= rcount
;
4030 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4031 if (status
!= DLADM_STATUS_OK
) {
4032 if (status
== DLADM_STATUS_TOOSMALL
) {
4035 if ((err
= i_dladm_range_size(rangep
, &sz
, &rcount
))
4040 status
= dladm_errno2status(err
);
4047 if (rangep
->mpr_count
== 0) {
4049 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "--");
4053 switch (rangep
->mpr_type
) {
4054 case MAC_PROPVAL_UINT32
: {
4055 mac_propval_uint32_range_t
*ur
;
4056 uint_t count
= rangep
->mpr_count
, i
;
4058 ur
= &rangep
->mpr_range_uint32
[0];
4060 for (i
= 0; i
< count
; i
++, ur
++) {
4061 if (ur
->mpur_min
== ur
->mpur_max
) {
4062 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4063 "%ld", ur
->mpur_min
);
4065 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4066 "%ld-%ld", ur
->mpur_min
, ur
->mpur_max
);
4073 status
= DLADM_STATUS_BADARG
;
4082 static dladm_status_t
4083 get_tagmode(dladm_handle_t handle
, prop_desc_t
*pdp
,
4084 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4085 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4087 link_tagmode_t mode
;
4088 dladm_status_t status
;
4090 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4091 perm_flags
, &mode
, sizeof (mode
));
4092 if (status
!= DLADM_STATUS_OK
)
4096 case LINK_TAGMODE_NORMAL
:
4097 (void) strlcpy(*prop_val
, "normal", DLADM_PROP_VAL_MAX
);
4099 case LINK_TAGMODE_VLANONLY
:
4100 (void) strlcpy(*prop_val
, "vlanonly", DLADM_PROP_VAL_MAX
);
4103 (void) strlcpy(*prop_val
, "unknown", DLADM_PROP_VAL_MAX
);
4106 return (DLADM_STATUS_OK
);
4110 static dladm_status_t
4111 get_flowctl(dladm_handle_t handle
, prop_desc_t
*pdp
,
4112 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4113 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4116 dladm_status_t status
;
4118 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4119 perm_flags
, &v
, sizeof (v
));
4120 if (status
!= DLADM_STATUS_OK
)
4124 case LINK_FLOWCTRL_NONE
:
4125 (void) sprintf(*prop_val
, "no");
4127 case LINK_FLOWCTRL_RX
:
4128 (void) sprintf(*prop_val
, "rx");
4130 case LINK_FLOWCTRL_TX
:
4131 (void) sprintf(*prop_val
, "tx");
4133 case LINK_FLOWCTRL_BI
:
4134 (void) sprintf(*prop_val
, "bi");
4138 return (DLADM_STATUS_OK
);
4143 static dladm_status_t
4144 i_dladm_set_private_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4145 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
4149 dld_ioc_macprop_t
*dip
= NULL
;
4152 dladm_status_t status
= DLADM_STATUS_OK
;
4154 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4155 (prop_val
!= NULL
&& val_cnt
== 0))
4156 return (DLADM_STATUS_BADARG
);
4157 p
= dladm_name2prop(prop_name
);
4158 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4159 return (DLADM_STATUS_BADARG
);
4161 if (!(flags
& DLADM_OPT_ACTIVE
))
4162 return (DLADM_STATUS_OK
);
4165 * private properties: all parsing is done in the kernel.
4166 * allocate a enough space for each property + its separator (',').
4168 for (i
= 0; i
< val_cnt
; i
++) {
4169 bufsize
+= strlen(prop_val
[i
]) + 1;
4172 if (prop_val
== NULL
) {
4174 * getting default value. so use more buffer space.
4176 bufsize
+= DLADM_PROP_BUF_CHUNK
;
4179 dip
= i_dladm_buf_alloc_by_name(bufsize
+ 1, linkid
, prop_name
,
4180 (prop_val
!= NULL
? 0 : DLD_PROP_DEFAULT
), &status
);
4184 dp
= (uchar_t
*)dip
->pr_val
;
4187 if (prop_val
== NULL
) {
4188 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4191 for (i
= 0; i
< val_cnt
; i
++) {
4194 plen
= strlen(prop_val
[i
]);
4195 bcopy(prop_val
[i
], dp
, plen
);
4198 * add a "," separator and update dp.
4200 if (i
!= (val_cnt
-1))
4205 if (status
== DLADM_STATUS_OK
)
4206 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4212 static dladm_status_t
4213 i_dladm_get_priv_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4214 const char *prop_name
, char **prop_val
, uint_t
*val_cnt
,
4215 dladm_prop_type_t type
, uint_t dld_flags
)
4217 dladm_status_t status
= DLADM_STATUS_OK
;
4218 dld_ioc_macprop_t
*dip
= NULL
;
4221 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4222 (prop_val
!= NULL
&& val_cnt
== 0))
4223 return (DLADM_STATUS_BADARG
);
4225 p
= dladm_name2prop(prop_name
);
4226 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4227 return (DLADM_STATUS_BADARG
);
4230 * private properties: all parsing is done in the kernel.
4232 dip
= i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK
, linkid
, prop_name
,
4233 dld_flags
, &status
);
4237 if ((status
= i_dladm_macprop(handle
, dip
, B_FALSE
)) ==
4239 if (type
== DLADM_PROP_VAL_PERM
) {
4240 (void) dladm_perm2str(dip
->pr_perm_flags
, *prop_val
);
4241 } else if (type
== DLADM_PROP_VAL_MODIFIABLE
) {
4242 *prop_val
[0] = '\0';
4244 (void) strncpy(*prop_val
, dip
->pr_val
,
4245 DLADM_PROP_VAL_MAX
);
4248 } else if ((status
== DLADM_STATUS_NOTSUP
) &&
4249 (type
== DLADM_PROP_VAL_CURRENT
)) {
4250 status
= DLADM_STATUS_NOTFOUND
;
4257 static dladm_status_t
4258 i_dladm_getset_defval(dladm_handle_t handle
, prop_desc_t
*pdp
,
4259 datalink_id_t linkid
, datalink_media_t media
, uint_t flags
)
4261 dladm_status_t status
;
4262 char **prop_vals
= NULL
, *buf
;
4269 * Allocate buffer needed for prop_vals array. We can have at most
4270 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4271 * each entry has max size DLADM_PROP_VAL_MAX
4274 (sizeof (char *) + DLADM_PROP_VAL_MAX
) * DLADM_MAX_PROP_VALCNT
;
4275 buf
= malloc(bufsize
);
4276 prop_vals
= (char **)(void *)buf
;
4277 for (i
= 0; i
< DLADM_MAX_PROP_VALCNT
; i
++) {
4278 prop_vals
[i
] = buf
+
4279 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4280 i
* DLADM_PROP_VAL_MAX
;
4284 * For properties which have pdp->pd_defval.vd_name as a non-empty
4285 * string, the "" itself is used to reset the property (exceptions
4286 * are zone and autopush, which populate vdp->vd_val). So
4287 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4288 * down on the setprop using the global values in the table. For
4289 * other cases (vd_name is ""), doing reset-linkprop will cause
4290 * libdladm to do a getprop to find the default value and then do
4291 * a setprop to reset the value to default.
4293 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_vals
, &cnt
, media
,
4294 DLD_PROP_DEFAULT
, &perm_flags
);
4295 if (status
== DLADM_STATUS_OK
) {
4296 if (perm_flags
== MAC_PROP_PERM_RW
) {
4297 status
= i_dladm_set_single_prop(handle
, linkid
,
4298 pdp
->pd_class
, media
, pdp
, prop_vals
, cnt
, flags
);
4301 status
= DLADM_STATUS_NOTSUP
;
4308 static dladm_status_t
4309 get_stp(dladm_handle_t handle
, struct prop_desc
*pd
, datalink_id_t linkid
,
4310 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
4313 const bridge_public_prop_t
*bpp
;
4314 dladm_status_t retv
;
4318 return (DLADM_STATUS_NOTSUP
);
4319 *perm_flags
= MAC_PROP_PERM_RW
;
4321 for (bpp
= bridge_prop
; bpp
->bpp_name
!= NULL
; bpp
++)
4322 if (strcmp(bpp
->bpp_name
, pd
->pd_name
) == 0)
4324 retv
= dladm_bridge_get_port_cfg(handle
, linkid
, bpp
->bpp_code
, &val
);
4325 /* If the daemon isn't running, then return the persistent value */
4326 if (retv
== DLADM_STATUS_NOTFOUND
) {
4327 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4328 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4329 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4330 DLADM_PROP_VAL_MAX
);
4331 return (DLADM_STATUS_OK
);
4333 if (retv
!= DLADM_STATUS_OK
) {
4334 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4337 if (val
== pd
->pd_defval
.vd_val
&& pd
->pd_defval
.vd_name
[0] != '\0') {
4338 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4339 DLADM_PROP_VAL_MAX
);
4340 return (DLADM_STATUS_OK
);
4342 for (i
= 0; i
< pd
->pd_noptval
; i
++) {
4343 if (val
== pd
->pd_optval
[i
].vd_val
) {
4344 (void) strlcpy(*prop_val
, pd
->pd_optval
[i
].vd_name
,
4345 DLADM_PROP_VAL_MAX
);
4346 return (DLADM_STATUS_OK
);
4349 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", (unsigned)val
);
4350 return (DLADM_STATUS_OK
);
4354 static dladm_status_t
4355 set_stp_prop(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4356 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4359 * Special case for mcheck: the daemon resets the value to zero, and we
4360 * don't want the daemon to refresh itself; it leads to deadlock.
4362 if (flags
& DLADM_OPT_NOREFRESH
)
4363 return (DLADM_STATUS_OK
);
4365 /* Tell the running daemon, if any */
4366 return (dladm_bridge_refresh(handle
, linkid
));
4370 * This is used only for stp_priority, stp_cost, and stp_mcheck.
4373 static dladm_status_t
4374 check_stp_prop(dladm_handle_t handle
, struct prop_desc
*pd
,
4375 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4376 val_desc_t
**vdpp
, datalink_media_t media
)
4380 uint_t val_cnt
= *val_cntp
;
4381 val_desc_t
*vdp
= *vdpp
;
4384 return (DLADM_STATUS_BADVALCNT
);
4386 if (prop_val
== NULL
) {
4389 /* Only stp_priority and stp_cost use this function */
4390 iscost
= strcmp(pd
->pd_name
, "stp_cost") == 0;
4392 if (iscost
&& strcmp(prop_val
[0], "auto") == 0) {
4393 /* Illegal value 0 is allowed to mean "automatic" */
4397 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4398 if (errno
!= 0 || *cp
!= '\0')
4399 return (DLADM_STATUS_BADVAL
);
4404 return (vdp
->vd_val
> 65535 ? DLADM_STATUS_BADVAL
:
4407 if (vdp
->vd_val
> 255)
4408 return (DLADM_STATUS_BADVAL
);
4410 * If the user is setting stp_mcheck non-zero, then (per the
4411 * IEEE management standards and UNH testing) we need to check
4412 * whether this link is part of a bridge that is running RSTP.
4413 * If it's not, then setting the flag is an error. Note that
4414 * errors are intentionally discarded here; it's the value
4415 * that's the problem -- it's not a bad value, merely one that
4416 * can't be used now.
4418 if (strcmp(pd
->pd_name
, "stp_mcheck") == 0 &&
4420 char bridge
[MAXLINKNAMELEN
];
4422 dladm_bridge_prot_t brprot
;
4424 if (dladm_bridge_getlink(handle
, linkid
, bridge
,
4425 sizeof (bridge
)) != DLADM_STATUS_OK
||
4426 dladm_bridge_get_properties(bridge
, &cfg
,
4427 &brprot
) != DLADM_STATUS_OK
)
4428 return (DLADM_STATUS_FAILED
);
4429 if (cfg
.force_version
<= 1)
4430 return (DLADM_STATUS_FAILED
);
4432 return (DLADM_STATUS_OK
);
4437 static dladm_status_t
4438 get_bridge_forward(dladm_handle_t handle
, struct prop_desc
*pd
,
4439 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4440 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4442 dladm_status_t retv
;
4446 return (DLADM_STATUS_NOTSUP
);
4447 *perm_flags
= MAC_PROP_PERM_RW
;
4449 retv
= dladm_bridge_get_forwarding(handle
, linkid
, &val
);
4450 if (retv
== DLADM_STATUS_NOTFOUND
) {
4451 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4452 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4453 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4454 DLADM_PROP_VAL_MAX
);
4455 return (DLADM_STATUS_OK
);
4457 if (retv
== DLADM_STATUS_OK
)
4458 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", val
);
4460 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4465 static dladm_status_t
4466 set_bridge_forward(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4467 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4469 /* Tell the running daemon, if any */
4470 return (dladm_bridge_refresh(handle
, linkid
));
4474 static dladm_status_t
4475 get_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4476 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4477 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4479 dladm_status_t status
;
4480 dld_ioc_macprop_t
*dip
;
4484 return (DLADM_STATUS_NOTSUP
);
4485 *perm_flags
= MAC_PROP_PERM_RW
;
4487 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4491 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4492 if (status
== DLADM_STATUS_OK
) {
4493 (void) memcpy(&pvid
, dip
->pr_val
, sizeof (pvid
));
4494 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", pvid
);
4496 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4503 static dladm_status_t
4504 set_bridge_pvid(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4505 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4507 dladm_status_t status
;
4508 dld_ioc_macprop_t
*dip
;
4511 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4516 (void) memcpy(dip
->pr_val
, &pvid
, sizeof (pvid
));
4517 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4519 if (status
!= DLADM_STATUS_OK
)
4522 /* Tell the running daemon, if any */
4523 return (dladm_bridge_refresh(handle
, linkid
));
4527 static dladm_status_t
4528 check_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4529 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4530 val_desc_t
**vdpp
, datalink_media_t media
)
4533 uint_t val_cnt
= *val_cntp
;
4534 val_desc_t
*vdp
= *vdpp
;
4537 return (DLADM_STATUS_BADVALCNT
);
4539 if (prop_val
== NULL
) {
4543 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4544 if (errno
!= 0 || *cp
!= '\0')
4545 return (DLADM_STATUS_BADVAL
);
4548 return (vdp
->vd_val
> VLAN_ID_MAX
? DLADM_STATUS_BADVAL
:
4553 i_dladm_wlan_param(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
4554 mac_prop_id_t cmd
, size_t len
, boolean_t set
)
4557 dladm_status_t status
;
4559 dld_ioc_macprop_t
*dip
;
4562 if ((status
= dladm_datalink_id2info(handle
, linkid
, &flags
, NULL
,
4563 &media
, NULL
, 0)) != DLADM_STATUS_OK
) {
4567 if (media
!= DL_WIFI
)
4568 return (DLADM_STATUS_BADARG
);
4570 if (!(flags
& DLADM_OPT_ACTIVE
))
4571 return (DLADM_STATUS_TEMPONLY
);
4573 if (len
== (MAX_BUF_LEN
- WIFI_BUF_OFFSET
))
4574 len
= MAX_BUF_LEN
- sizeof (dld_ioc_macprop_t
) - 1;
4576 dip
= i_dladm_buf_alloc_by_id(len
, linkid
, cmd
, 0, &status
);
4578 return (DLADM_STATUS_NOMEM
);
4580 dp
= (uchar_t
*)dip
->pr_val
;
4582 (void) memcpy(dp
, buf
, len
);
4584 status
= i_dladm_macprop(handle
, dip
, set
);
4585 if (status
== DLADM_STATUS_OK
) {
4587 (void) memcpy(buf
, dp
, len
);
4595 dladm_parse_link_props(char *str
, dladm_arg_list_t
**listp
, boolean_t novalues
)
4597 return (dladm_parse_args(str
, listp
, novalues
));
4601 * Retrieve the one link property from the database
4605 i_dladm_get_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4606 const char *prop_name
, void *arg
)
4608 dladm_arg_list_t
*proplist
= arg
;
4609 dladm_arg_info_t
*aip
= NULL
;
4611 aip
= &proplist
->al_info
[proplist
->al_count
];
4613 * it is fine to point to prop_name since prop_name points to the
4614 * prop_table[n].pd_name.
4616 aip
->ai_name
= prop_name
;
4618 (void) dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
4619 prop_name
, aip
->ai_val
, &aip
->ai_count
);
4621 if (aip
->ai_count
!= 0)
4622 proplist
->al_count
++;
4624 return (DLADM_WALK_CONTINUE
);
4629 * Retrieve all link properties for a link from the database and
4630 * return a property list.
4633 dladm_link_get_proplist(dladm_handle_t handle
, datalink_id_t linkid
,
4634 dladm_arg_list_t
**listp
)
4636 dladm_arg_list_t
*list
;
4637 dladm_status_t status
= DLADM_STATUS_OK
;
4639 list
= calloc(1, sizeof (dladm_arg_list_t
));
4641 return (dladm_errno2status(errno
));
4643 status
= dladm_walk_linkprop(handle
, linkid
, list
,
4644 i_dladm_get_one_prop
);
4651 * Retrieve the named property from a proplist, check the value and
4652 * convert to a kernel structure.
4654 static dladm_status_t
4655 i_dladm_link_proplist_extract_one(dladm_handle_t handle
,
4656 dladm_arg_list_t
*proplist
, const char *name
, uint_t flags
, void *arg
)
4658 dladm_status_t status
;
4659 dladm_arg_info_t
*aip
= NULL
;
4662 /* Find named property in proplist */
4663 for (i
= 0; i
< proplist
->al_count
; i
++) {
4664 aip
= &proplist
->al_info
[i
];
4665 if (strcasecmp(aip
->ai_name
, name
) == 0)
4669 /* Property not in list */
4670 if (i
== proplist
->al_count
)
4671 return (DLADM_STATUS_OK
);
4673 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
4674 prop_desc_t
*pdp
= &prop_table
[i
];
4677 vdp
= malloc(sizeof (val_desc_t
) * aip
->ai_count
);
4679 return (DLADM_STATUS_NOMEM
);
4681 if (strcasecmp(aip
->ai_name
, pdp
->pd_name
) != 0)
4684 if (aip
->ai_val
== NULL
)
4685 return (DLADM_STATUS_BADARG
);
4687 /* Check property value */
4688 if (pdp
->pd_check
!= NULL
) {
4689 status
= pdp
->pd_check(handle
, pdp
, 0, aip
->ai_val
,
4690 &(aip
->ai_count
), flags
, &vdp
, 0);
4692 status
= DLADM_STATUS_BADARG
;
4695 if (status
!= DLADM_STATUS_OK
)
4698 for (j
= 0; j
< DLADM_MAX_RSRC_PROP
; j
++) {
4699 resource_prop_t
*rpp
= &rsrc_prop_table
[j
];
4701 if (strcasecmp(aip
->ai_name
, rpp
->rp_name
) != 0)
4704 /* Extract kernel structure */
4705 if (rpp
->rp_extract
!= NULL
) {
4706 status
= rpp
->rp_extract(vdp
,
4707 aip
->ai_count
, arg
);
4709 status
= DLADM_STATUS_BADARG
;
4714 if (status
!= DLADM_STATUS_OK
)
4723 * Extract properties from a proplist and convert to mac_resource_props_t.
4726 dladm_link_proplist_extract(dladm_handle_t handle
, dladm_arg_list_t
*proplist
,
4727 mac_resource_props_t
*mrp
, uint_t flags
)
4729 dladm_status_t status
;
4732 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
4733 status
= i_dladm_link_proplist_extract_one(handle
,
4734 proplist
, rsrc_prop_table
[i
].rp_name
, flags
, mrp
);
4735 if (status
!= DLADM_STATUS_OK
)
4742 dladm_perm2str(uint_t perm
, char *buf
)
4744 (void) snprintf(buf
, DLADM_STRSIZE
, "%c%c",
4745 ((perm
& MAC_PROP_PERM_READ
) != 0) ? 'r' : '-',
4746 ((perm
& MAC_PROP_PERM_WRITE
) != 0) ? 'w' : '-');
4751 dladm_get_state(dladm_handle_t handle
, datalink_id_t linkid
,
4752 link_state_t
*state
)
4756 return (i_dladm_get_public_prop(handle
, linkid
, "state", 0,
4757 &perms
, state
, sizeof (*state
)));
4761 dladm_attr_is_linkprop(const char *name
)
4763 /* non-property attribute names */
4764 const char *nonprop
[] = {
4765 /* dlmgmtd core attributes */
4773 /* other attributes for vlan, aggr, etc */
4776 boolean_t is_nonprop
= B_FALSE
;
4779 for (i
= 0; i
< sizeof (nonprop
) / sizeof (nonprop
[0]); i
++) {
4780 if (strcmp(name
, nonprop
[i
]) == 0) {
4781 is_nonprop
= B_TRUE
;
4786 return (!is_nonprop
);
4790 dladm_linkprop_is_set(dladm_handle_t handle
, datalink_id_t linkid
,
4791 dladm_prop_type_t type
, const char *prop_name
, boolean_t
*is_set
)
4793 char *buf
, **propvals
;
4794 uint_t valcnt
= DLADM_MAX_PROP_VALCNT
;
4796 dladm_status_t status
= DLADM_STATUS_OK
;
4801 bufsize
= (sizeof (char *) + DLADM_PROP_VAL_MAX
) *
4802 DLADM_MAX_PROP_VALCNT
;
4803 if ((buf
= calloc(1, bufsize
)) == NULL
)
4804 return (DLADM_STATUS_NOMEM
);
4806 propvals
= (char **)(void *)buf
;
4807 for (i
= 0; i
< valcnt
; i
++) {
4809 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4810 i
* DLADM_PROP_VAL_MAX
;
4813 if (dladm_get_linkprop(handle
, linkid
, type
, prop_name
, propvals
,
4814 &valcnt
) != DLADM_STATUS_OK
) {
4819 * valcnt is always set to 1 by get_pool(), hence we need to check
4820 * for a non-null string to see if it is set. For protection,
4821 * secondary-macs and allowed-ips, we can check either the *propval
4824 if ((strcmp(prop_name
, "pool") == 0 ||
4825 strcmp(prop_name
, "protection") == 0 ||
4826 strcmp(prop_name
, "secondary-macs") == 0 ||
4827 strcmp(prop_name
, "allowed-ips") == 0) &&
4828 (strlen(*propvals
) != 0)) {
4830 } else if ((strcmp(prop_name
, "cpus") == 0) && (valcnt
!= 0)) {
4832 } else if ((strcmp(prop_name
, "_softmac") == 0) && (valcnt
!= 0) &&
4833 (strcmp(propvals
[0], "true") == 0)) {
4844 static dladm_status_t
4845 get_linkmode_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
4846 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4847 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4851 dladm_status_t status
;
4853 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4854 perm_flags
, &v
, sizeof (v
));
4855 if (status
!= DLADM_STATUS_OK
)
4859 case DLADM_PART_CM_MODE
:
4862 case DLADM_PART_UD_MODE
:
4869 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
4872 return (DLADM_STATUS_OK
);
4876 static dladm_status_t
4877 get_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
4878 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4879 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4882 dladm_status_t status
;
4885 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4886 perm_flags
, &filt
, sizeof (filt
));
4887 if (status
!= DLADM_STATUS_OK
)
4891 s
= link_promisc_filtered_vals
[1].vd_name
;
4893 s
= link_promisc_filtered_vals
[0].vd_name
;
4894 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
4897 return (DLADM_STATUS_OK
);
4901 static dladm_status_t
4902 set_promisc_filtered(dladm_handle_t handle
, prop_desc_t
*pdp
,
4903 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
4904 datalink_media_t media
)
4906 dld_ioc_macprop_t
*dip
;
4907 dladm_status_t status
= DLADM_STATUS_OK
;
4909 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
,
4915 (void) memcpy(dip
->pr_val
, &vdp
->vd_val
, dip
->pr_valsize
);
4916 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);