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 (c) 2014, Joyent, Inc. All rights reserved.
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
;
159 static pd_setf_t set_zone
, set_rate
, set_powermode
, set_radio
,
160 set_public_prop
, set_resource
, set_stp_prop
,
161 set_bridge_forward
, set_bridge_pvid
, set_secondary_macs
;
163 static pd_checkf_t check_zone
, check_autopush
, check_rate
, check_hoplimit
,
164 check_encaplim
, check_uint32
, check_maxbw
, check_cpus
,
165 check_stp_prop
, check_bridge_pvid
, check_allowedips
,
166 check_allowedcids
, check_secondary_macs
, check_rings
,
167 check_pool
, check_prop
;
176 * default property value, can be set to { "", NULL }
178 val_desc_t pd_defval
;
181 * list of optional property values, can be NULL.
183 * This is set to non-NULL if there is a list of possible property
184 * values. pd_optval would point to the array of possible values.
186 val_desc_t
*pd_optval
;
189 * count of the above optional property values. 0 if pd_optval is NULL.
194 * callback to set link property; set to NULL if this property is
195 * read-only and may be called before or after permanent update; see
201 * callback to get modifiable link property
203 pd_getf_t
*pd_getmod
;
206 * callback to get current link property
211 * callback to validate link property value, set to NULL if pd_optval
212 * is not NULL. In that case, validate the value by comparing it with
213 * the pd_optval. Return a val_desc_t array pointer if the value is
216 pd_checkf_t
*pd_check
;
219 #define PD_TEMPONLY 0x1 /* property is temporary only */
220 #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */
221 #define PD_AFTER_PERM 0x4 /* pd_set after db update; no temporary */
223 * indicate link classes this property applies to.
225 datalink_class_t pd_class
;
228 * indicate link media type this property applies to.
230 datalink_media_t pd_dmedia
;
233 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1
236 * Supported link properties enumerated in the prop_table[] array are
237 * computed using the callback functions in that array. To compute the
238 * property value, multiple distinct system calls may be needed (e.g.,
239 * for wifi speed, we need to issue system calls to get desired/supported
240 * rates). The link_attr[] table enumerates the interfaces to the kernel,
241 * and the type/size of the data passed in the user-kernel interface.
243 static link_attr_t link_attr
[] = {
244 { MAC_PROP_DUPLEX
, sizeof (link_duplex_t
), "duplex"},
246 { MAC_PROP_SPEED
, sizeof (uint64_t), "speed"},
248 { MAC_PROP_STATUS
, sizeof (link_state_t
), "state"},
250 { MAC_PROP_AUTONEG
, sizeof (uint8_t), "adv_autoneg_cap"},
252 { MAC_PROP_MTU
, sizeof (uint32_t), "mtu"},
254 { MAC_PROP_FLOWCTRL
, sizeof (link_flowctrl_t
), "flowctrl"},
256 { MAC_PROP_ZONE
, sizeof (dld_ioc_zid_t
), "zone"},
258 { MAC_PROP_AUTOPUSH
, sizeof (struct dlautopush
), "autopush"},
260 { MAC_PROP_ADV_5000FDX_CAP
, sizeof (uint8_t), "adv_5000fdx_cap"},
262 { MAC_PROP_EN_5000FDX_CAP
, sizeof (uint8_t), "en_5000fdx_cap"},
264 { MAC_PROP_ADV_2500FDX_CAP
, sizeof (uint8_t), "adv_2500fdx_cap"},
266 { MAC_PROP_EN_2500FDX_CAP
, sizeof (uint8_t), "en_2500fdx_cap"},
268 { MAC_PROP_ADV_100GFDX_CAP
, sizeof (uint8_t), "adv_100gfdx_cap"},
270 { MAC_PROP_EN_100GFDX_CAP
, sizeof (uint8_t), "en_100gfdx_cap"},
272 { MAC_PROP_ADV_40GFDX_CAP
, sizeof (uint8_t), "adv_40gfdx_cap"},
274 { MAC_PROP_EN_40GFDX_CAP
, sizeof (uint8_t), "en_40gfdx_cap"},
276 { MAC_PROP_ADV_10GFDX_CAP
, sizeof (uint8_t), "adv_10gfdx_cap"},
278 { MAC_PROP_EN_10GFDX_CAP
, sizeof (uint8_t), "en_10gfdx_cap"},
280 { MAC_PROP_ADV_1000FDX_CAP
, sizeof (uint8_t), "adv_1000fdx_cap"},
282 { MAC_PROP_EN_1000FDX_CAP
, sizeof (uint8_t), "en_1000fdx_cap"},
284 { MAC_PROP_ADV_1000HDX_CAP
, sizeof (uint8_t), "adv_1000hdx_cap"},
286 { MAC_PROP_EN_1000HDX_CAP
, sizeof (uint8_t), "en_1000hdx_cap"},
288 { MAC_PROP_ADV_100FDX_CAP
, sizeof (uint8_t), "adv_100fdx_cap"},
290 { MAC_PROP_EN_100FDX_CAP
, sizeof (uint8_t), "en_100fdx_cap"},
292 { MAC_PROP_ADV_100HDX_CAP
, sizeof (uint8_t), "adv_100hdx_cap"},
294 { MAC_PROP_EN_100HDX_CAP
, sizeof (uint8_t), "en_100hdx_cap"},
296 { MAC_PROP_ADV_10FDX_CAP
, sizeof (uint8_t), "adv_10fdx_cap"},
298 { MAC_PROP_EN_10FDX_CAP
, sizeof (uint8_t), "en_10fdx_cap"},
300 { MAC_PROP_ADV_10HDX_CAP
, sizeof (uint8_t), "adv_10hdx_cap"},
302 { MAC_PROP_EN_10HDX_CAP
, sizeof (uint8_t), "en_10hdx_cap"},
304 { MAC_PROP_WL_ESSID
, sizeof (wl_linkstatus_t
), "essid"},
306 { MAC_PROP_WL_BSSID
, sizeof (wl_bssid_t
), "bssid"},
308 { MAC_PROP_WL_BSSTYPE
, sizeof (wl_bss_type_t
), "bsstype"},
310 { MAC_PROP_WL_LINKSTATUS
, sizeof (wl_linkstatus_t
), "wl_linkstatus"},
312 /* wl_rates_t has variable length */
313 { MAC_PROP_WL_DESIRED_RATES
, sizeof (wl_rates_t
), "desired_rates"},
315 /* wl_rates_t has variable length */
316 { MAC_PROP_WL_SUPPORTED_RATES
, sizeof (wl_rates_t
), "supported_rates"},
318 { MAC_PROP_WL_AUTH_MODE
, sizeof (wl_authmode_t
), "authmode"},
320 { MAC_PROP_WL_ENCRYPTION
, sizeof (wl_encryption_t
), "encryption"},
322 { MAC_PROP_WL_RSSI
, sizeof (wl_rssi_t
), "signal"},
324 { MAC_PROP_WL_PHY_CONFIG
, sizeof (wl_phy_conf_t
), "phy_conf"},
326 { MAC_PROP_WL_CAPABILITY
, sizeof (wl_capability_t
), "capability"},
328 { MAC_PROP_WL_WPA
, sizeof (wl_wpa_t
), "wpa"},
330 /* wl_wpa_ess_t has variable length */
331 { MAC_PROP_WL_SCANRESULTS
, sizeof (wl_wpa_ess_t
), "scan_results"},
333 { MAC_PROP_WL_POWER_MODE
, sizeof (wl_ps_mode_t
), "powermode"},
335 { MAC_PROP_WL_RADIO
, sizeof (dladm_wlan_radio_t
), "wl_radio"},
337 { MAC_PROP_WL_ESS_LIST
, sizeof (wl_ess_list_t
), "wl_ess_list"},
339 { MAC_PROP_WL_KEY_TAB
, sizeof (wl_wep_key_tab_t
), "wl_wep_key"},
341 { MAC_PROP_WL_CREATE_IBSS
, sizeof (wl_create_ibss_t
), "createibss"},
343 /* wl_wpa_ie_t has variable length */
344 { MAC_PROP_WL_SETOPTIE
, sizeof (wl_wpa_ie_t
), "set_ie"},
346 { MAC_PROP_WL_DELKEY
, sizeof (wl_del_key_t
), "wpa_del_key"},
348 { MAC_PROP_WL_KEY
, sizeof (wl_key_t
), "wl_key"},
350 { MAC_PROP_WL_MLME
, sizeof (wl_mlme_t
), "mlme"},
352 { MAC_PROP_TAGMODE
, sizeof (link_tagmode_t
), "tagmode"},
354 { MAC_PROP_IPTUN_HOPLIMIT
, sizeof (uint32_t), "hoplimit"},
356 { MAC_PROP_IPTUN_ENCAPLIMIT
, sizeof (uint32_t), "encaplimit"},
358 { MAC_PROP_PVID
, sizeof (uint16_t), "default_tag"},
360 { MAC_PROP_LLIMIT
, sizeof (uint32_t), "learn_limit"},
362 { MAC_PROP_LDECAY
, sizeof (uint32_t), "learn_decay"},
364 { MAC_PROP_RESOURCE
, sizeof (mac_resource_props_t
), "resource"},
366 { MAC_PROP_RESOURCE_EFF
, sizeof (mac_resource_props_t
),
367 "resource-effective"},
369 { MAC_PROP_RXRINGSRANGE
, sizeof (mac_propval_range_t
), "rxrings"},
371 { MAC_PROP_TXRINGSRANGE
, sizeof (mac_propval_range_t
), "txrings"},
373 { MAC_PROP_MAX_TX_RINGS_AVAIL
, sizeof (uint_t
),
374 "txrings-available"},
376 { MAC_PROP_MAX_RX_RINGS_AVAIL
, sizeof (uint_t
),
377 "rxrings-available"},
379 { MAC_PROP_MAX_RXHWCLNT_AVAIL
, sizeof (uint_t
), "rxhwclnt-available"},
381 { MAC_PROP_MAX_TXHWCLNT_AVAIL
, sizeof (uint_t
), "txhwclnt-available"},
383 { MAC_PROP_IB_LINKMODE
, sizeof (uint32_t), "linkmode"},
385 { MAC_PROP_SECONDARY_ADDRS
, sizeof (mac_secondary_addr_t
),
388 { MAC_PROP_PRIVATE
, 0, "driver-private"}
391 typedef struct bridge_public_prop_s
{
392 const char *bpp_name
;
394 } bridge_public_prop_t
;
396 static const bridge_public_prop_t bridge_prop
[] = {
397 { "stp", PT_CFG_NON_STP
},
398 { "stp_priority", PT_CFG_PRIO
},
399 { "stp_cost", PT_CFG_COST
},
400 { "stp_edge", PT_CFG_EDGE
},
401 { "stp_p2p", PT_CFG_P2P
},
402 { "stp_mcheck", PT_CFG_MCHECK
},
406 static val_desc_t link_duplex_vals
[] = {
407 { "half", LINK_DUPLEX_HALF
},
408 { "full", LINK_DUPLEX_HALF
}
410 static val_desc_t link_status_vals
[] = {
411 { "up", LINK_STATE_UP
},
412 { "down", LINK_STATE_DOWN
}
414 static val_desc_t link_01_vals
[] = {
418 static val_desc_t link_flow_vals
[] = {
419 { "no", LINK_FLOWCTRL_NONE
},
420 { "tx", LINK_FLOWCTRL_TX
},
421 { "rx", LINK_FLOWCTRL_RX
},
422 { "bi", LINK_FLOWCTRL_BI
}
424 static val_desc_t link_priority_vals
[] = {
426 { "medium", MPL_MEDIUM
},
430 static val_desc_t link_tagmode_vals
[] = {
431 { "normal", LINK_TAGMODE_NORMAL
},
432 { "vlanonly", LINK_TAGMODE_VLANONLY
}
435 static val_desc_t link_protect_vals
[] = {
436 { "mac-nospoof", MPT_MACNOSPOOF
},
437 { "restricted", MPT_RESTRICTED
},
438 { "ip-nospoof", MPT_IPNOSPOOF
},
439 { "dhcp-nospoof", MPT_DHCPNOSPOOF
},
442 static val_desc_t dladm_wlan_radio_vals
[] = {
443 { "on", DLADM_WLAN_RADIO_ON
},
444 { "off", DLADM_WLAN_RADIO_OFF
}
447 static val_desc_t dladm_wlan_powermode_vals
[] = {
448 { "off", DLADM_WLAN_PM_OFF
},
449 { "fast", DLADM_WLAN_PM_FAST
},
450 { "max", DLADM_WLAN_PM_MAX
}
453 static val_desc_t stp_p2p_vals
[] = {
454 { "true", P2P_FORCE_TRUE
},
455 { "false", P2P_FORCE_FALSE
},
459 static val_desc_t dladm_part_linkmode_vals
[] = {
460 { "cm", DLADM_PART_CM_MODE
},
461 { "ud", DLADM_PART_UD_MODE
},
464 #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
465 #define RESET_VAL ((uintptr_t)-1)
466 #define UNSPEC_VAL ((uintptr_t)-2)
469 * For the default, if defaults are not defined for the property,
470 * pd_defval.vd_name should be null. If the driver has to be contacted for the
471 * value, vd_name should be the empty string (""). Otherwise, dladm will
472 * just print whatever is in the table.
474 static prop_desc_t prop_table
[] = {
475 { "channel", { NULL
, 0 },
477 get_channel
, NULL
, 0,
478 DATALINK_CLASS_PHYS
, DL_WIFI
},
480 { "powermode", { "off", DLADM_WLAN_PM_OFF
},
481 dladm_wlan_powermode_vals
, VALCNT(dladm_wlan_powermode_vals
),
483 get_powermode
, NULL
, 0,
484 DATALINK_CLASS_PHYS
, DL_WIFI
},
486 { "radio", { "on", DLADM_WLAN_RADIO_ON
},
487 dladm_wlan_radio_vals
, VALCNT(dladm_wlan_radio_vals
),
490 DATALINK_CLASS_PHYS
, DL_WIFI
},
492 { "linkmode", { "cm", DLADM_PART_CM_MODE
},
493 dladm_part_linkmode_vals
, VALCNT(dladm_part_linkmode_vals
),
494 set_public_prop
, NULL
, get_linkmode_prop
, NULL
, 0,
495 DATALINK_CLASS_PART
, DL_IB
},
497 { "speed", { "", 0 }, NULL
, 0,
498 set_rate
, get_rate_mod
,
499 get_rate
, check_rate
, 0,
500 DATALINK_CLASS_PHYS
, DATALINK_ANY_MEDIATYPE
},
502 { "autopush", { "", 0 }, NULL
, 0,
503 set_public_prop
, NULL
,
504 get_autopush
, check_autopush
, PD_CHECK_ALLOC
,
505 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
507 { "zone", { "", 0 }, NULL
, 0,
509 get_zone
, check_zone
, PD_TEMPONLY
|PD_CHECK_ALLOC
,
510 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
512 { "duplex", { "", 0 },
513 link_duplex_vals
, VALCNT(link_duplex_vals
),
514 NULL
, NULL
, get_duplex
, NULL
,
515 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
517 { "state", { "up", LINK_STATE_UP
},
518 link_status_vals
, VALCNT(link_status_vals
),
519 NULL
, NULL
, get_link_state
, NULL
,
520 0, DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
522 { "adv_autoneg_cap", { "", 0 },
523 link_01_vals
, VALCNT(link_01_vals
),
524 set_public_prop
, NULL
, get_binary
, NULL
,
525 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
527 { "mtu", { "", 0 }, NULL
, 0,
528 set_public_prop
, get_range
,
529 get_uint32
, check_uint32
, 0, DATALINK_CLASS_ALL
,
530 DATALINK_ANY_MEDIATYPE
},
532 { "flowctrl", { "", 0 },
533 link_flow_vals
, VALCNT(link_flow_vals
),
534 set_public_prop
, NULL
, get_flowctl
, NULL
,
535 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
537 { "secondary-macs", { "--", 0 }, NULL
, 0,
538 set_secondary_macs
, NULL
,
539 get_secondary_macs
, check_secondary_macs
, PD_CHECK_ALLOC
,
540 DATALINK_CLASS_VNIC
, DL_ETHER
},
542 { "adv_100gfdx_cap", { "", 0 },
543 link_01_vals
, VALCNT(link_01_vals
),
544 NULL
, NULL
, get_binary
, NULL
,
545 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
547 { "en_100gfdx_cap", { "", 0 },
548 link_01_vals
, VALCNT(link_01_vals
),
549 set_public_prop
, NULL
, get_binary
, NULL
,
550 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
552 { "adv_40gfdx_cap", { "", 0 },
553 link_01_vals
, VALCNT(link_01_vals
),
554 NULL
, NULL
, get_binary
, NULL
,
555 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
557 { "en_40gfdx_cap", { "", 0 },
558 link_01_vals
, VALCNT(link_01_vals
),
559 set_public_prop
, NULL
, get_binary
, NULL
,
560 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
562 { "adv_10gfdx_cap", { "", 0 },
563 link_01_vals
, VALCNT(link_01_vals
),
564 NULL
, NULL
, get_binary
, NULL
,
565 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
567 { "en_10gfdx_cap", { "", 0 },
568 link_01_vals
, VALCNT(link_01_vals
),
569 set_public_prop
, NULL
, get_binary
, NULL
,
570 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
572 { "adv_5000fdx_cap", { "", 0 },
573 link_01_vals
, VALCNT(link_01_vals
),
574 NULL
, NULL
, get_binary
, NULL
,
575 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
577 { "en_5000fdx_cap", { "", 0 },
578 link_01_vals
, VALCNT(link_01_vals
),
579 set_public_prop
, NULL
, get_binary
, NULL
,
580 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
582 { "adv_2500fdx_cap", { "", 0 },
583 link_01_vals
, VALCNT(link_01_vals
),
584 NULL
, NULL
, get_binary
, NULL
,
585 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
587 { "en_2500fdx_cap", { "", 0 },
588 link_01_vals
, VALCNT(link_01_vals
),
589 set_public_prop
, NULL
, get_binary
, NULL
,
590 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
592 { "adv_1000fdx_cap", { "", 0 },
593 link_01_vals
, VALCNT(link_01_vals
),
594 NULL
, NULL
, get_binary
, NULL
,
595 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
597 { "en_1000fdx_cap", { "", 0 },
598 link_01_vals
, VALCNT(link_01_vals
),
599 set_public_prop
, NULL
, get_binary
, NULL
,
600 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
602 { "adv_1000hdx_cap", { "", 0 },
603 link_01_vals
, VALCNT(link_01_vals
),
604 NULL
, NULL
, get_binary
, NULL
,
605 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
607 { "en_1000hdx_cap", { "", 0 },
608 link_01_vals
, VALCNT(link_01_vals
),
609 set_public_prop
, NULL
, get_binary
, NULL
,
610 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
612 { "adv_100fdx_cap", { "", 0 },
613 link_01_vals
, VALCNT(link_01_vals
),
614 NULL
, NULL
, get_binary
, NULL
,
615 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
617 { "en_100fdx_cap", { "", 0 },
618 link_01_vals
, VALCNT(link_01_vals
),
619 set_public_prop
, NULL
, get_binary
, NULL
,
620 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
622 { "adv_100hdx_cap", { "", 0 },
623 link_01_vals
, VALCNT(link_01_vals
),
624 NULL
, NULL
, get_binary
, NULL
,
625 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
627 { "en_100hdx_cap", { "", 0 },
628 link_01_vals
, VALCNT(link_01_vals
),
629 set_public_prop
, NULL
, get_binary
, NULL
,
630 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
632 { "adv_10fdx_cap", { "", 0 },
633 link_01_vals
, VALCNT(link_01_vals
),
634 NULL
, NULL
, get_binary
, NULL
,
635 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
637 { "en_10fdx_cap", { "", 0 },
638 link_01_vals
, VALCNT(link_01_vals
),
639 set_public_prop
, NULL
, get_binary
, NULL
,
640 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
642 { "adv_10hdx_cap", { "", 0 },
643 link_01_vals
, VALCNT(link_01_vals
),
644 NULL
, NULL
, get_binary
, NULL
,
645 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
647 { "en_10hdx_cap", { "", 0 },
648 link_01_vals
, VALCNT(link_01_vals
),
649 set_public_prop
, NULL
, get_binary
, NULL
,
650 0, DATALINK_CLASS_PHYS
, DL_ETHER
},
652 { "maxbw", { "--", RESET_VAL
}, NULL
, 0,
654 get_maxbw
, check_maxbw
, PD_CHECK_ALLOC
,
655 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
657 { "cpus", { "--", RESET_VAL
}, NULL
, 0,
659 get_cpus
, check_cpus
, 0,
660 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
662 { "cpus-effective", { "--", 0 },
665 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
667 { "pool", { "--", RESET_VAL
}, NULL
, 0,
669 get_pool
, check_pool
, 0,
670 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
672 { "pool-effective", { "--", 0 },
675 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
677 { "priority", { "high", MPL_RESET
},
678 link_priority_vals
, VALCNT(link_priority_vals
), set_resource
,
679 NULL
, get_priority
, check_prop
, 0,
680 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
682 { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY
},
683 link_tagmode_vals
, VALCNT(link_tagmode_vals
),
684 set_public_prop
, NULL
, get_tagmode
,
686 DATALINK_CLASS_PHYS
| DATALINK_CLASS_AGGR
| DATALINK_CLASS_VNIC
,
689 { "hoplimit", { "", 0 }, NULL
, 0,
690 set_public_prop
, get_range
, get_uint32
,
691 check_hoplimit
, 0, DATALINK_CLASS_IPTUN
, DATALINK_ANY_MEDIATYPE
},
693 { "encaplimit", { "", 0 }, NULL
, 0,
694 set_public_prop
, get_range
, get_uint32
,
695 check_encaplim
, 0, DATALINK_CLASS_IPTUN
, DL_IPV6
},
697 { "forward", { "1", 1 },
698 link_01_vals
, VALCNT(link_01_vals
),
699 set_bridge_forward
, NULL
, get_bridge_forward
, NULL
, PD_AFTER_PERM
,
700 DATALINK_CLASS_ALL
& ~DATALINK_CLASS_VNIC
, DL_ETHER
},
702 { "default_tag", { "1", 1 }, NULL
, 0,
703 set_bridge_pvid
, NULL
, get_bridge_pvid
, check_bridge_pvid
,
704 0, DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
705 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
707 { "learn_limit", { "1000", 1000 }, NULL
, 0,
708 set_public_prop
, NULL
, get_uint32
,
710 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
711 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
713 { "learn_decay", { "200", 200 }, NULL
, 0,
714 set_public_prop
, NULL
, get_uint32
,
716 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
717 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
720 link_01_vals
, VALCNT(link_01_vals
),
721 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
722 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
723 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
725 { "stp_priority", { "128", 128 }, NULL
, 0,
726 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
727 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
728 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
730 { "stp_cost", { "auto", 0 }, NULL
, 0,
731 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
732 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
733 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
735 { "stp_edge", { "1", 1 },
736 link_01_vals
, VALCNT(link_01_vals
),
737 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
738 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
739 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
741 { "stp_p2p", { "auto", P2P_AUTO
},
742 stp_p2p_vals
, VALCNT(stp_p2p_vals
),
743 set_stp_prop
, NULL
, get_stp
, NULL
, PD_AFTER_PERM
,
744 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
745 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
747 { "stp_mcheck", { "0", 0 },
748 link_01_vals
, VALCNT(link_01_vals
),
749 set_stp_prop
, NULL
, get_stp
, check_stp_prop
, PD_AFTER_PERM
,
750 DATALINK_CLASS_PHYS
|DATALINK_CLASS_AGGR
|
751 DATALINK_CLASS_ETHERSTUB
|DATALINK_CLASS_SIMNET
, DL_ETHER
},
753 { "protection", { "--", RESET_VAL
},
754 link_protect_vals
, VALCNT(link_protect_vals
),
755 set_resource
, NULL
, get_protection
, check_prop
, 0,
756 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
758 { "allowed-ips", { "--", 0 },
759 NULL
, 0, set_resource
, NULL
,
760 get_allowedips
, check_allowedips
, PD_CHECK_ALLOC
,
761 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
763 { "allowed-dhcp-cids", { "--", 0 },
764 NULL
, 0, set_resource
, NULL
,
765 get_allowedcids
, check_allowedcids
, PD_CHECK_ALLOC
,
766 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
768 { "rxrings", { "--", RESET_VAL
}, NULL
, 0,
769 set_resource
, get_rings_range
, get_rxrings
, check_rings
, 0,
770 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
772 { "rxrings-effective", { "--", 0 },
774 get_rxrings
, NULL
, 0,
775 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
777 { "txrings", { "--", RESET_VAL
}, NULL
, 0,
778 set_resource
, get_rings_range
, get_txrings
, check_rings
, 0,
779 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
781 { "txrings-effective", { "--", 0 },
783 get_txrings
, NULL
, 0,
784 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
786 { "txrings-available", { "", 0 }, NULL
, 0,
787 NULL
, NULL
, get_cntavail
, NULL
, 0,
788 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
790 { "rxrings-available", { "", 0 }, NULL
, 0,
791 NULL
, NULL
, get_cntavail
, NULL
, 0,
792 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
794 { "rxhwclnt-available", { "", 0 }, NULL
, 0,
795 NULL
, NULL
, get_cntavail
, NULL
, 0,
796 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
798 { "txhwclnt-available", { "", 0 }, NULL
, 0,
799 NULL
, NULL
, get_cntavail
, NULL
, 0,
800 DATALINK_CLASS_ALL
, DATALINK_ANY_MEDIATYPE
},
804 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
806 static resource_prop_t rsrc_prop_table
[] = {
807 {"maxbw", extract_maxbw
},
808 {"priority", extract_priority
},
809 {"cpus", extract_cpus
},
810 {"cpus-effective", extract_cpus
},
811 {"pool", extract_pool
},
812 {"pool-effective", extract_pool
},
813 {"protection", extract_protection
},
814 {"allowed-ips", extract_allowedips
},
815 {"allowed-dhcp-cids", extract_allowedcids
},
816 {"rxrings", extract_rxrings
},
817 {"rxrings-effective", extract_rxrings
},
818 {"txrings", extract_txrings
},
819 {"txrings-effective", extract_txrings
}
821 #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
822 sizeof (resource_prop_t))
825 * when retrieving private properties, we pass down a buffer with
826 * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
828 #define DLADM_PROP_BUF_CHUNK 1024
830 static dladm_status_t
i_dladm_set_linkprop_db(dladm_handle_t
, datalink_id_t
,
831 const char *, char **, uint_t
);
832 static dladm_status_t
i_dladm_get_linkprop_db(dladm_handle_t
, datalink_id_t
,
833 const char *, char **, uint_t
*);
834 static dladm_status_t
i_dladm_walk_linkprop_priv_db(dladm_handle_t
,
835 datalink_id_t
, void *, int (*)(dladm_handle_t
,
836 datalink_id_t
, const char *, void *));
837 static dladm_status_t
i_dladm_set_single_prop(dladm_handle_t
, datalink_id_t
,
838 datalink_class_t
, uint32_t, prop_desc_t
*, char **,
840 static dladm_status_t
i_dladm_set_linkprop(dladm_handle_t
, datalink_id_t
,
841 const char *, char **, uint_t
, uint_t
);
842 static dladm_status_t
i_dladm_getset_defval(dladm_handle_t
, prop_desc_t
*,
843 datalink_id_t
, datalink_media_t
, uint_t
);
846 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
847 * rates to be retrieved. However, we cannot increase it at this
848 * time because it will break binary compatibility with unbundled
849 * WiFi drivers and utilities. So for now we define an additional
850 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
852 #define MAX_SUPPORT_RATES 64
854 #define AP_ANCHOR "[anchor]"
855 #define AP_DELIMITER '.'
858 static dladm_status_t
859 check_prop(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
860 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
861 datalink_media_t media
)
864 uint_t val_cnt
= *val_cntp
;
865 val_desc_t
*vdp
= *vdpp
;
867 for (j
= 0; j
< val_cnt
; j
++) {
868 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
869 if (strcasecmp(prop_val
[j
],
870 pdp
->pd_optval
[i
].vd_name
) == 0) {
874 if (i
== pdp
->pd_noptval
)
875 return (DLADM_STATUS_BADVAL
);
877 (void) memcpy(&vdp
[j
], &pdp
->pd_optval
[i
], sizeof (val_desc_t
));
879 return (DLADM_STATUS_OK
);
882 static dladm_status_t
883 i_dladm_set_single_prop(dladm_handle_t handle
, datalink_id_t linkid
,
884 datalink_class_t
class, uint32_t media
, prop_desc_t
*pdp
, char **prop_val
,
885 uint_t val_cnt
, uint_t flags
)
887 dladm_status_t status
= DLADM_STATUS_OK
;
888 val_desc_t
*vdp
= NULL
;
889 boolean_t needfree
= B_FALSE
;
892 if (!(pdp
->pd_class
& class))
893 return (DLADM_STATUS_BADARG
);
895 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
896 return (DLADM_STATUS_BADARG
);
898 if ((flags
& DLADM_OPT_PERSIST
) && (pdp
->pd_flags
& PD_TEMPONLY
))
899 return (DLADM_STATUS_TEMPONLY
);
901 if (!(flags
& DLADM_OPT_ACTIVE
))
902 return (DLADM_STATUS_OK
);
904 if (pdp
->pd_set
== NULL
)
905 return (DLADM_STATUS_PROPRDONLY
);
907 if (prop_val
!= NULL
) {
908 vdp
= calloc(val_cnt
, sizeof (val_desc_t
));
910 return (DLADM_STATUS_NOMEM
);
912 if (pdp
->pd_check
!= NULL
) {
913 needfree
= ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0);
914 status
= pdp
->pd_check(handle
, pdp
, linkid
, prop_val
,
915 &val_cnt
, flags
, &vdp
, media
);
916 } else if (pdp
->pd_optval
!= NULL
) {
917 status
= check_prop(handle
, pdp
, linkid
, prop_val
,
918 &val_cnt
, flags
, &vdp
, media
);
920 status
= DLADM_STATUS_BADARG
;
923 if (status
!= DLADM_STATUS_OK
)
928 boolean_t defval
= B_FALSE
;
930 if (pdp
->pd_defval
.vd_name
== NULL
)
931 return (DLADM_STATUS_NOTSUP
);
934 defval
= (strlen(pdp
->pd_defval
.vd_name
) > 0);
935 if ((pdp
->pd_flags
& PD_CHECK_ALLOC
) != 0 || defval
) {
936 if ((vdp
= calloc(1, sizeof (val_desc_t
))) == NULL
)
937 return (DLADM_STATUS_NOMEM
);
940 (void) memcpy(vdp
, &pdp
->pd_defval
,
941 sizeof (val_desc_t
));
942 } else if (pdp
->pd_check
!= NULL
) {
943 status
= pdp
->pd_check(handle
, pdp
, linkid
,
944 prop_val
, &cnt
, flags
, &vdp
, media
);
945 if (status
!= DLADM_STATUS_OK
)
949 status
= i_dladm_getset_defval(handle
, pdp
, linkid
,
954 if (pdp
->pd_flags
& PD_AFTER_PERM
)
955 status
= (flags
& DLADM_OPT_PERSIST
) ? DLADM_STATUS_OK
:
956 DLADM_STATUS_PERMONLY
;
958 status
= pdp
->pd_set(handle
, pdp
, linkid
, vdp
, cnt
, flags
,
961 for (i
= 0; i
< cnt
; i
++)
962 free((void *)((val_desc_t
*)vdp
+ i
)->vd_val
);
969 static dladm_status_t
970 i_dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
971 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
974 boolean_t found
= B_FALSE
;
975 datalink_class_t
class;
977 dladm_status_t status
= DLADM_STATUS_OK
;
979 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
981 if (status
!= DLADM_STATUS_OK
)
984 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
985 prop_desc_t
*pdp
= &prop_table
[i
];
988 if (prop_name
!= NULL
&&
989 (strcasecmp(prop_name
, pdp
->pd_name
) != 0))
992 s
= i_dladm_set_single_prop(handle
, linkid
, class, media
, pdp
,
993 prop_val
, val_cnt
, flags
);
995 if (prop_name
!= NULL
) {
999 if (s
!= DLADM_STATUS_OK
&&
1000 s
!= DLADM_STATUS_NOTSUP
)
1005 if (prop_name
[0] == '_') {
1006 /* other private properties */
1007 status
= i_dladm_set_private_prop(handle
, linkid
,
1008 prop_name
, prop_val
, val_cnt
, flags
);
1010 status
= DLADM_STATUS_NOTFOUND
;
1017 * Set/reset link property for specific link
1020 dladm_set_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1021 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
1023 dladm_status_t status
= DLADM_STATUS_OK
;
1025 if ((linkid
== DATALINK_INVALID_LINKID
) || (flags
== 0) ||
1026 (prop_val
== NULL
&& val_cnt
> 0) ||
1027 (prop_val
!= NULL
&& val_cnt
== 0) ||
1028 (prop_name
== NULL
&& prop_val
!= NULL
)) {
1029 return (DLADM_STATUS_BADARG
);
1033 * Check for valid link property against the flags passed
1034 * and set the link property when active flag is passed.
1036 status
= i_dladm_set_linkprop(handle
, linkid
, prop_name
, prop_val
,
1038 if (status
!= DLADM_STATUS_OK
)
1041 if (flags
& DLADM_OPT_PERSIST
) {
1042 status
= i_dladm_set_linkprop_db(handle
, linkid
, prop_name
,
1045 if (status
== DLADM_STATUS_OK
&& (flags
& DLADM_OPT_ACTIVE
)) {
1046 prop_desc_t
*pdp
= prop_table
;
1049 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++, pdp
++) {
1050 if (!(pdp
->pd_flags
& PD_AFTER_PERM
))
1052 if (prop_name
!= NULL
&&
1053 strcasecmp(prop_name
, pdp
->pd_name
) != 0)
1055 status
= pdp
->pd_set(handle
, pdp
, linkid
, NULL
,
1064 * Walk all link properties of the given specific link.
1066 * Note: this function currently lacks the ability to walk _all_ private
1067 * properties if the link, because there is no kernel interface to
1068 * retrieve all known private property names. Once such an interface
1069 * is added, this function should be fixed accordingly.
1072 dladm_walk_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
,
1073 int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
1075 dladm_status_t status
;
1076 datalink_class_t
class;
1080 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
1081 return (DLADM_STATUS_BADARG
);
1083 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1085 if (status
!= DLADM_STATUS_OK
)
1089 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
1090 if (!(prop_table
[i
].pd_class
& class))
1093 if (!DATALINK_MEDIA_ACCEPTED(prop_table
[i
].pd_dmedia
, media
))
1096 if (func(handle
, linkid
, prop_table
[i
].pd_name
, arg
) ==
1097 DLADM_WALK_TERMINATE
) {
1103 status
= i_dladm_walk_linkprop_priv_db(handle
, linkid
, arg
, func
);
1109 * Get linkprop of the given specific link.
1112 dladm_get_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1113 dladm_prop_type_t type
, const char *prop_name
, char **prop_val
,
1116 dladm_status_t status
= DLADM_STATUS_OK
;
1117 datalink_class_t
class;
1120 uint_t cnt
, dld_flags
= 0;
1124 if (type
== DLADM_PROP_VAL_DEFAULT
)
1125 dld_flags
|= DLD_PROP_DEFAULT
;
1126 else if (type
== DLADM_PROP_VAL_MODIFIABLE
)
1127 dld_flags
|= DLD_PROP_POSSIBLE
;
1129 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1130 prop_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1131 return (DLADM_STATUS_BADARG
);
1133 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++)
1134 if (strcasecmp(prop_name
, prop_table
[i
].pd_name
) == 0)
1137 if (i
== DLADM_MAX_PROPS
) {
1138 if (prop_name
[0] == '_') {
1142 if (type
== DLADM_PROP_VAL_PERSISTENT
)
1143 return (i_dladm_get_linkprop_db(handle
, linkid
,
1144 prop_name
, prop_val
, val_cntp
));
1146 return (i_dladm_get_priv_prop(handle
, linkid
,
1147 prop_name
, prop_val
, val_cntp
, type
,
1150 return (DLADM_STATUS_NOTFOUND
);
1154 pdp
= &prop_table
[i
];
1156 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1158 if (status
!= DLADM_STATUS_OK
)
1161 if (!(pdp
->pd_class
& class))
1162 return (DLADM_STATUS_BADARG
);
1164 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1165 return (DLADM_STATUS_BADARG
);
1168 case DLADM_PROP_VAL_CURRENT
:
1169 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1170 media
, dld_flags
, &perm_flags
);
1173 case DLADM_PROP_VAL_PERM
:
1174 if (pdp
->pd_set
== NULL
) {
1175 perm_flags
= MAC_PROP_PERM_READ
;
1177 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1178 val_cntp
, media
, dld_flags
, &perm_flags
);
1181 *prop_val
[0] = '\0';
1183 if (status
== DLADM_STATUS_OK
)
1184 (void) dladm_perm2str(perm_flags
, *prop_val
);
1187 case DLADM_PROP_VAL_DEFAULT
:
1189 * If defaults are not defined for the property,
1190 * pd_defval.vd_name should be null. If the driver
1191 * has to be contacted for the value, vd_name should
1192 * be the empty string (""). Otherwise, dladm will
1193 * just print whatever is in the table.
1195 if (pdp
->pd_defval
.vd_name
== NULL
) {
1196 status
= DLADM_STATUS_NOTSUP
;
1200 if (strlen(pdp
->pd_defval
.vd_name
) == 0) {
1201 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
,
1202 val_cntp
, media
, dld_flags
, &perm_flags
);
1204 (void) strcpy(*prop_val
, pdp
->pd_defval
.vd_name
);
1209 case DLADM_PROP_VAL_MODIFIABLE
:
1210 if (pdp
->pd_getmod
!= NULL
) {
1211 status
= pdp
->pd_getmod(handle
, pdp
, linkid
, prop_val
,
1212 val_cntp
, media
, dld_flags
, &perm_flags
);
1215 cnt
= pdp
->pd_noptval
;
1217 status
= DLADM_STATUS_NOTSUP
;
1218 } else if (cnt
> *val_cntp
) {
1219 status
= DLADM_STATUS_TOOSMALL
;
1221 for (i
= 0; i
< cnt
; i
++) {
1222 (void) strcpy(prop_val
[i
],
1223 pdp
->pd_optval
[i
].vd_name
);
1228 case DLADM_PROP_VAL_PERSISTENT
:
1229 if (pdp
->pd_flags
& PD_TEMPONLY
)
1230 return (DLADM_STATUS_TEMPONLY
);
1231 status
= i_dladm_get_linkprop_db(handle
, linkid
, prop_name
,
1232 prop_val
, val_cntp
);
1235 status
= DLADM_STATUS_BADARG
;
1243 * Get linkprop of the given specific link and run any possible conversion
1244 * of the values using the check function for the property. Fails if the
1245 * check function doesn't succeed for the property value.
1248 dladm_get_linkprop_values(dladm_handle_t handle
, datalink_id_t linkid
,
1249 dladm_prop_type_t type
, const char *prop_name
, uint_t
*ret_val
,
1252 dladm_status_t status
;
1253 datalink_class_t
class;
1261 if (linkid
== DATALINK_INVALID_LINKID
|| prop_name
== NULL
||
1262 ret_val
== NULL
|| val_cntp
== NULL
|| *val_cntp
== 0)
1263 return (DLADM_STATUS_BADARG
);
1265 for (pdp
= prop_table
; pdp
< prop_table
+ DLADM_MAX_PROPS
; pdp
++)
1266 if (strcasecmp(prop_name
, pdp
->pd_name
) == 0)
1269 if (pdp
== prop_table
+ DLADM_MAX_PROPS
)
1270 return (DLADM_STATUS_NOTFOUND
);
1272 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
1273 return (DLADM_STATUS_BADARG
);
1275 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, &media
,
1277 if (status
!= DLADM_STATUS_OK
)
1280 if (!(pdp
->pd_class
& class))
1281 return (DLADM_STATUS_BADARG
);
1283 if (!DATALINK_MEDIA_ACCEPTED(pdp
->pd_dmedia
, media
))
1284 return (DLADM_STATUS_BADARG
);
1286 prop_val
= malloc(*val_cntp
* sizeof (*prop_val
) +
1287 *val_cntp
* DLADM_PROP_VAL_MAX
);
1288 if (prop_val
== NULL
)
1289 return (DLADM_STATUS_NOMEM
);
1290 for (valc
= 0; valc
< *val_cntp
; valc
++)
1291 prop_val
[valc
] = (char *)(prop_val
+ *val_cntp
) +
1292 valc
* DLADM_PROP_VAL_MAX
;
1294 dld_flags
= (type
== DLADM_PROP_VAL_DEFAULT
) ? DLD_PROP_DEFAULT
: 0;
1297 case DLADM_PROP_VAL_CURRENT
:
1298 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1299 media
, dld_flags
, &perm_flags
);
1302 case DLADM_PROP_VAL_DEFAULT
:
1304 * If defaults are not defined for the property,
1305 * pd_defval.vd_name should be null. If the driver
1306 * has to be contacted for the value, vd_name should
1307 * be the empty string (""). Otherwise, dladm will
1308 * just print whatever is in the table.
1310 if (pdp
->pd_defval
.vd_name
== NULL
) {
1311 status
= DLADM_STATUS_NOTSUP
;
1315 if (pdp
->pd_defval
.vd_name
[0] != '\0') {
1317 *ret_val
= pdp
->pd_defval
.vd_val
;
1319 return (DLADM_STATUS_OK
);
1321 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_val
, val_cntp
,
1322 media
, dld_flags
, &perm_flags
);
1325 case DLADM_PROP_VAL_PERSISTENT
:
1326 if (pdp
->pd_flags
& PD_TEMPONLY
)
1327 status
= DLADM_STATUS_TEMPONLY
;
1329 status
= i_dladm_get_linkprop_db(handle
, linkid
,
1330 prop_name
, prop_val
, val_cntp
);
1334 status
= DLADM_STATUS_BADARG
;
1338 if (status
== DLADM_STATUS_OK
) {
1339 if (pdp
->pd_check
!= NULL
) {
1342 vdp
= malloc(sizeof (val_desc_t
) * *val_cntp
);
1344 status
= DLADM_STATUS_NOMEM
;
1346 status
= pdp
->pd_check(handle
, pdp
, linkid
,
1347 prop_val
, val_cntp
, 0, &vdp
, media
);
1348 if (status
== DLADM_STATUS_OK
) {
1349 for (valc
= 0; valc
< *val_cntp
; valc
++)
1350 ret_val
[valc
] = vdp
[valc
].vd_val
;
1354 for (valc
= 0; valc
< *val_cntp
; valc
++) {
1355 for (i
= 0; i
< pdp
->pd_noptval
; i
++) {
1356 if (strcmp(pdp
->pd_optval
[i
].vd_name
,
1357 prop_val
[valc
]) == 0) {
1359 pdp
->pd_optval
[i
].vd_val
;
1363 if (i
== pdp
->pd_noptval
) {
1364 status
= DLADM_STATUS_FAILED
;
1378 i_dladm_init_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
1379 const char *prop_name
, void *arg
)
1381 char *buf
, **propvals
;
1382 uint_t i
, valcnt
= DLADM_MAX_PROP_VALCNT
;
1383 dladm_status_t status
;
1384 dladm_linkprop_args_t
*dla
= arg
;
1386 if ((buf
= malloc((sizeof (char *) + DLADM_PROP_VAL_MAX
) *
1387 DLADM_MAX_PROP_VALCNT
)) == NULL
) {
1388 return (DLADM_WALK_CONTINUE
);
1391 propvals
= (char **)(void *)buf
;
1392 for (i
= 0; i
< valcnt
; i
++) {
1394 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
1395 i
* DLADM_PROP_VAL_MAX
;
1398 if (dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
1399 prop_name
, propvals
, &valcnt
) != DLADM_STATUS_OK
) {
1403 status
= dladm_set_linkprop(handle
, linkid
, prop_name
, propvals
,
1404 valcnt
, dla
->dla_flags
| DLADM_OPT_ACTIVE
);
1406 if (status
!= DLADM_STATUS_OK
)
1407 dla
->dla_status
= status
;
1413 return (DLADM_WALK_CONTINUE
);
1418 i_dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
)
1420 datalink_class_t
class;
1421 dladm_status_t status
;
1423 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, &class, NULL
,
1425 if (status
!= DLADM_STATUS_OK
)
1426 return (DLADM_WALK_TERMINATE
);
1428 if ((class & (DATALINK_CLASS_VNIC
| DATALINK_CLASS_VLAN
)) == 0)
1429 (void) dladm_init_linkprop(handle
, linkid
, B_TRUE
);
1431 return (DLADM_WALK_CONTINUE
);
1435 dladm_init_linkprop(dladm_handle_t handle
, datalink_id_t linkid
,
1436 boolean_t any_media
)
1438 dladm_status_t status
= DLADM_STATUS_OK
;
1439 datalink_media_t dmedia
;
1441 dladm_linkprop_args_t
*dla
;
1443 dmedia
= any_media
? DATALINK_ANY_MEDIATYPE
: DL_WIFI
;
1445 dla
= malloc(sizeof (dladm_linkprop_args_t
));
1447 return (DLADM_STATUS_NOMEM
);
1448 dla
->dla_flags
= DLADM_OPT_BOOT
;
1449 dla
->dla_status
= DLADM_STATUS_OK
;
1451 if (linkid
== DATALINK_ALL_LINKID
) {
1452 (void) dladm_walk_datalink_id(i_dladm_init_linkprop
, handle
,
1453 NULL
, DATALINK_CLASS_ALL
, dmedia
, DLADM_OPT_PERSIST
);
1454 } else if (any_media
||
1455 ((dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, &media
, NULL
,
1456 0) == DLADM_STATUS_OK
) &&
1457 DATALINK_MEDIA_ACCEPTED(dmedia
, media
))) {
1458 (void) dladm_walk_linkprop(handle
, linkid
, (void *)dla
,
1459 i_dladm_init_one_prop
);
1460 status
= dla
->dla_status
;
1467 static dladm_status_t
1468 get_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1469 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1470 uint_t flags
, uint_t
*perm_flags
)
1472 char zone_name
[ZONENAME_MAX
];
1474 dladm_status_t status
;
1477 return (DLADM_STATUS_NOTSUP
);
1479 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1480 perm_flags
, &zid
, sizeof (zid
));
1481 if (status
!= DLADM_STATUS_OK
)
1485 if (zid
!= GLOBAL_ZONEID
) {
1486 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0) {
1487 return (dladm_errno2status(errno
));
1490 (void) strncpy(*prop_val
, zone_name
, DLADM_PROP_VAL_MAX
);
1492 *prop_val
[0] = '\0';
1495 return (DLADM_STATUS_OK
);
1498 typedef int (*zone_get_devroot_t
)(char *, char *, size_t);
1501 i_dladm_get_zone_dev(char *zone_name
, char *dev
, size_t devlen
)
1503 char root
[MAXPATHLEN
];
1504 zone_get_devroot_t real_zone_get_devroot
;
1509 if ((dlhandle
= dlopen("libzonecfg.so.1", RTLD_LAZY
)) == NULL
)
1512 if ((sym
= dlsym(dlhandle
, "zone_get_devroot")) == NULL
) {
1513 (void) dlclose(dlhandle
);
1517 real_zone_get_devroot
= (zone_get_devroot_t
)sym
;
1519 if ((ret
= real_zone_get_devroot(zone_name
, root
, sizeof (root
))) == 0)
1520 (void) snprintf(dev
, devlen
, "%s%s", root
, "/dev");
1521 (void) dlclose(dlhandle
);
1525 static dladm_status_t
1526 i_dladm_update_deventry(dladm_handle_t handle
, zoneid_t zid
,
1527 datalink_id_t linkid
, boolean_t add
)
1529 char path
[MAXPATHLEN
];
1530 char name
[MAXLINKNAMELEN
];
1531 di_prof_t prof
= NULL
;
1532 char zone_name
[ZONENAME_MAX
];
1533 dladm_status_t status
;
1536 if (getzonenamebyid(zid
, zone_name
, sizeof (zone_name
)) < 0)
1537 return (dladm_errno2status(errno
));
1538 if (i_dladm_get_zone_dev(zone_name
, path
, sizeof (path
)) != 0)
1539 return (dladm_errno2status(errno
));
1540 if (di_prof_init(path
, &prof
) != 0)
1541 return (dladm_errno2status(errno
));
1543 status
= dladm_linkid2legacyname(handle
, linkid
, name
, MAXLINKNAMELEN
);
1544 if (status
!= DLADM_STATUS_OK
)
1548 ret
= di_prof_add_dev(prof
, name
);
1550 ret
= di_prof_add_exclude(prof
, name
);
1553 status
= dladm_errno2status(errno
);
1557 if (di_prof_commit(prof
) != 0)
1558 status
= dladm_errno2status(errno
);
1567 static dladm_status_t
1568 set_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1569 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
1571 dladm_status_t status
= DLADM_STATUS_OK
;
1572 zoneid_t zid_old
, zid_new
;
1576 return (DLADM_STATUS_BADVALCNT
);
1578 dzp
= (dld_ioc_zid_t
*)vdp
->vd_val
;
1580 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
1581 NULL
, &zid_old
, sizeof (zid_old
));
1582 if (status
!= DLADM_STATUS_OK
)
1585 zid_new
= dzp
->diz_zid
;
1586 if (zid_new
== zid_old
)
1587 return (DLADM_STATUS_OK
);
1589 if ((status
= set_public_prop(handle
, pdp
, linkid
, vdp
, val_cnt
,
1590 flags
, media
)) != DLADM_STATUS_OK
)
1594 * It is okay to fail to update the /dev entry (some vanity-named
1595 * links do not have a /dev entry).
1597 if (zid_old
!= GLOBAL_ZONEID
) {
1598 (void) i_dladm_update_deventry(handle
, zid_old
, linkid
,
1601 if (zid_new
!= GLOBAL_ZONEID
)
1602 (void) i_dladm_update_deventry(handle
, zid_new
, linkid
, B_TRUE
);
1604 return (DLADM_STATUS_OK
);
1608 static dladm_status_t
1609 check_zone(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1610 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1611 datalink_media_t media
)
1615 dladm_status_t status
= DLADM_STATUS_OK
;
1617 uint_t val_cnt
= *val_cntp
;
1618 val_desc_t
*vdp
= *vdpp
;
1621 return (DLADM_STATUS_BADVALCNT
);
1623 dzp
= malloc(sizeof (dld_ioc_zid_t
));
1625 return (DLADM_STATUS_NOMEM
);
1627 zone_name
= (prop_val
!= NULL
) ? *prop_val
: GLOBAL_ZONENAME
;
1628 if ((zoneid
= getzoneidbyname(zone_name
)) == -1) {
1629 status
= DLADM_STATUS_BADVAL
;
1633 if (zoneid
!= GLOBAL_ZONEID
) {
1636 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &flags
,
1637 sizeof (flags
)) < 0) {
1638 status
= dladm_errno2status(errno
);
1642 if (!(flags
& ZF_NET_EXCL
)) {
1643 status
= DLADM_STATUS_BADVAL
;
1648 (void) memset(dzp
, 0, sizeof (dld_ioc_zid_t
));
1650 dzp
->diz_zid
= zoneid
;
1651 dzp
->diz_linkid
= linkid
;
1653 vdp
->vd_val
= (uintptr_t)dzp
;
1654 return (DLADM_STATUS_OK
);
1661 static dladm_status_t
1662 get_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1663 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1664 uint_t flags
, uint_t
*perm_flags
)
1666 mac_resource_props_t mrp
;
1667 dladm_status_t status
;
1669 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
1670 perm_flags
, &mrp
, sizeof (mrp
));
1671 if (status
!= DLADM_STATUS_OK
)
1674 if ((mrp
.mrp_mask
& MRP_MAXBW
) == 0) {
1676 return (DLADM_STATUS_OK
);
1679 (void) dladm_bw2str(mrp
.mrp_maxbw
, prop_val
[0]);
1681 return (DLADM_STATUS_OK
);
1685 static dladm_status_t
1686 check_maxbw(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1687 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1688 datalink_media_t media
)
1691 dladm_status_t status
= DLADM_STATUS_OK
;
1692 uint_t val_cnt
= *val_cntp
;
1693 val_desc_t
*vdp
= *vdpp
;
1696 return (DLADM_STATUS_BADVALCNT
);
1698 maxbw
= malloc(sizeof (uint64_t));
1700 return (DLADM_STATUS_NOMEM
);
1702 status
= dladm_str2bw(*prop_val
, maxbw
);
1703 if (status
!= DLADM_STATUS_OK
) {
1708 if ((*maxbw
< MRP_MAXBW_MINVAL
) && (*maxbw
!= 0)) {
1710 return (DLADM_STATUS_MINMAXBW
);
1713 vdp
->vd_val
= (uintptr_t)maxbw
;
1714 return (DLADM_STATUS_OK
);
1719 extract_maxbw(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1721 mac_resource_props_t
*mrp
= arg
;
1723 if (vdp
->vd_val
== RESET_VAL
) {
1724 mrp
->mrp_maxbw
= MRP_MAXBW_RESETVAL
;
1726 bcopy((char *)vdp
->vd_val
, &mrp
->mrp_maxbw
, sizeof (uint64_t));
1728 mrp
->mrp_mask
|= MRP_MAXBW
;
1730 return (DLADM_STATUS_OK
);
1734 static dladm_status_t
1735 get_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1736 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1737 uint_t flags
, uint_t
*perm_flags
)
1739 dladm_status_t status
;
1740 mac_resource_props_t mrp
;
1741 mac_propval_range_t
*pv_range
;
1744 if (strcmp(pdp
->pd_name
, "cpus-effective") == 0) {
1745 status
= i_dladm_get_public_prop(handle
, linkid
,
1746 "resource-effective", flags
, perm_flags
, &mrp
,
1749 status
= i_dladm_get_public_prop(handle
, linkid
,
1750 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1753 if (status
!= DLADM_STATUS_OK
)
1756 if (mrp
.mrp_ncpus
> *val_cnt
)
1757 return (DLADM_STATUS_TOOSMALL
);
1759 if (mrp
.mrp_ncpus
== 0) {
1761 return (DLADM_STATUS_OK
);
1764 /* Sort CPU list and convert it to a mac_propval_range */
1765 status
= dladm_list2range(mrp
.mrp_cpu
, mrp
.mrp_ncpus
,
1766 MAC_PROPVAL_UINT32
, &pv_range
);
1767 if (status
!= DLADM_STATUS_OK
)
1770 /* Write CPU ranges and individual CPUs */
1771 err
= dladm_range2strs(pv_range
, prop_val
);
1774 return (dladm_errno2status(err
));
1777 *val_cnt
= pv_range
->mpr_count
;
1780 return (DLADM_STATUS_OK
);
1784 static dladm_status_t
1785 check_cpus(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1786 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1787 datalink_media_t media
)
1790 long nproc
= sysconf(_SC_NPROCESSORS_CONF
);
1791 mac_resource_props_t mrp
;
1792 mac_propval_range_t
*pv_range
;
1795 uint32_t *cpus
= mrp
.mrp_cpu
;
1796 val_desc_t
*vdp
= *vdpp
;
1798 uint_t val_cnt
= *val_cntp
;
1799 dladm_status_t status
= DLADM_STATUS_OK
;
1801 /* Get the current pool property */
1802 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
1803 &perm_flags
, &mrp
, sizeof (mrp
));
1805 if (status
== DLADM_STATUS_OK
) {
1806 /* Can't set cpus if a pool is set */
1807 if (strlen(mrp
.mrp_pool
) != 0)
1808 return (DLADM_STATUS_POOLCPU
);
1811 /* Read ranges and convert to mac_propval_range */
1812 status
= dladm_strs2range(prop_val
, val_cnt
, MAC_PROPVAL_UINT32
,
1814 if (status
!= DLADM_STATUS_OK
)
1817 /* Convert mac_propval_range to a single CPU list */
1819 status
= dladm_range2list(pv_range
, cpus
, &ncpus
);
1820 if (status
!= DLADM_STATUS_OK
)
1824 * If a range of CPUs was entered, update value count and reallocate
1825 * the array of val_desc_t's. The array allocated was sized for
1826 * indvidual elements, but needs to be reallocated to accomodate the
1827 * expanded list of CPUs.
1829 if (val_cnt
< ncpus
) {
1830 newvdp
= calloc(*val_cntp
, sizeof (val_desc_t
));
1831 if (newvdp
== NULL
) {
1832 status
= DLADM_STATUS_NOMEM
;
1838 /* Check if all CPUs in the list are online */
1839 for (i
= 0; i
< ncpus
; i
++) {
1840 if (cpus
[i
] >= nproc
) {
1841 status
= DLADM_STATUS_BADCPUID
;
1845 rc
= p_online(cpus
[i
], P_STATUS
);
1847 status
= DLADM_STATUS_CPUERR
;
1851 if (rc
!= P_ONLINE
) {
1852 status
= DLADM_STATUS_CPUNOTONLINE
;
1856 vdp
[i
].vd_val
= (uintptr_t)cpus
[i
];
1859 /* Check for duplicate CPUs */
1860 for (i
= 0; i
< *val_cntp
; i
++) {
1861 for (j
= 0; j
< *val_cntp
; j
++) {
1862 if (i
!= j
&& vdp
[i
].vd_val
== vdp
[j
].vd_val
) {
1863 status
= DLADM_STATUS_BADVAL
;
1869 /* Update *val_cntp and *vdpp if everything was OK */
1870 if (val_cnt
< ncpus
) {
1876 status
= DLADM_STATUS_OK
;
1888 extract_cpus(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
1890 mac_resource_props_t
*mrp
= arg
;
1893 if (vdp
[0].vd_val
== RESET_VAL
) {
1894 bzero(&mrp
->mrp_cpus
, sizeof (mac_cpus_t
));
1895 mrp
->mrp_mask
|= MRP_CPUS
;
1896 return (DLADM_STATUS_OK
);
1899 for (i
= 0; i
< cnt
; i
++)
1900 mrp
->mrp_cpu
[i
] = (uint32_t)vdp
[i
].vd_val
;
1902 mrp
->mrp_ncpus
= cnt
;
1903 mrp
->mrp_mask
|= (MRP_CPUS
|MRP_CPUS_USERSPEC
);
1904 mrp
->mrp_fanout_mode
= MCM_CPUS
;
1905 mrp
->mrp_rx_intr_cpu
= -1;
1907 return (DLADM_STATUS_OK
);
1911 * Get the pool datalink property from the kernel. This is used
1912 * for both the user specified pool and effective pool properties.
1915 static dladm_status_t
1916 get_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1917 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
1918 uint_t flags
, uint_t
*perm_flags
)
1920 mac_resource_props_t mrp
;
1921 dladm_status_t status
;
1923 if (strcmp(pdp
->pd_name
, "pool-effective") == 0) {
1924 status
= i_dladm_get_public_prop(handle
, linkid
,
1925 "resource-effective", flags
, perm_flags
, &mrp
,
1928 status
= i_dladm_get_public_prop(handle
, linkid
,
1929 "resource", flags
, perm_flags
, &mrp
, sizeof (mrp
));
1932 if (status
!= DLADM_STATUS_OK
)
1935 if (strlen(mrp
.mrp_pool
) == 0) {
1936 (*prop_val
)[0] = '\0';
1938 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
1939 "%s", mrp
.mrp_pool
);
1943 return (DLADM_STATUS_OK
);
1947 static dladm_status_t
1948 check_pool(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
1949 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
1950 datalink_media_t media
)
1952 pool_conf_t
*poolconf
;
1954 mac_resource_props_t mrp
;
1955 dladm_status_t status
;
1958 val_desc_t
*vdp
= *vdpp
;
1960 /* Get the current cpus property */
1961 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", 0,
1962 &perm_flags
, &mrp
, sizeof (mrp
));
1964 if (status
== DLADM_STATUS_OK
) {
1965 /* Can't set pool if cpus are set */
1966 if (mrp
.mrp_ncpus
!= 0)
1967 return (DLADM_STATUS_POOLCPU
);
1970 poolname
= malloc(sizeof (mrp
.mrp_pool
));
1971 if (poolname
== NULL
)
1972 return (DLADM_STATUS_NOMEM
);
1974 /* Check for pool's availability if not booting */
1975 if ((flags
& DLADM_OPT_BOOT
) == 0) {
1977 /* Allocate and open pool configuration */
1978 if ((poolconf
= pool_conf_alloc()) == NULL
)
1979 return (DLADM_STATUS_BADVAL
);
1981 if (pool_conf_open(poolconf
, pool_dynamic_location(), PO_RDONLY
)
1983 pool_conf_free(poolconf
);
1984 return (DLADM_STATUS_BADVAL
);
1987 /* Look for pool name */
1988 if ((pool
= pool_get_pool(poolconf
, *prop_val
)) == NULL
) {
1989 pool_conf_free(poolconf
);
1990 return (DLADM_STATUS_BADVAL
);
1993 pool_conf_free(poolconf
);
1997 (void) strlcpy(poolname
, *prop_val
, sizeof (mrp
.mrp_pool
));
1998 vdp
->vd_val
= (uintptr_t)poolname
;
2000 return (DLADM_STATUS_OK
);
2005 extract_pool(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2007 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2009 if (vdp
->vd_val
== RESET_VAL
) {
2010 bzero(&mrp
->mrp_pool
, sizeof (mrp
->mrp_pool
));
2011 mrp
->mrp_mask
|= MRP_POOL
;
2012 return (DLADM_STATUS_OK
);
2015 (void) strlcpy(mrp
->mrp_pool
, (char *)vdp
->vd_val
,
2016 sizeof (mrp
->mrp_pool
));
2017 mrp
->mrp_mask
|= MRP_POOL
;
2019 * Use MCM_CPUS since the fanout count is not user specified
2020 * and will be determined by the cpu list generated from the
2023 mrp
->mrp_fanout_mode
= MCM_CPUS
;
2025 return (DLADM_STATUS_OK
);
2029 static dladm_status_t
2030 get_priority(dladm_handle_t handle
, prop_desc_t
*pdp
,
2031 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2032 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2034 mac_resource_props_t mrp
;
2035 mac_priority_level_t pri
;
2036 dladm_status_t status
;
2038 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2039 perm_flags
, &mrp
, sizeof (mrp
));
2040 if (status
!= DLADM_STATUS_OK
)
2043 pri
= ((mrp
.mrp_mask
& MRP_PRIORITY
) == 0) ? MPL_HIGH
:
2046 (void) dladm_pri2str(pri
, prop_val
[0]);
2048 return (DLADM_STATUS_OK
);
2053 extract_priority(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2055 mac_resource_props_t
*mrp
= arg
;
2058 return (DLADM_STATUS_BADVAL
);
2060 mrp
->mrp_priority
= (mac_priority_level_t
)vdp
->vd_val
;
2061 mrp
->mrp_mask
|= MRP_PRIORITY
;
2063 return (DLADM_STATUS_OK
);
2067 * Determines the size of the structure that needs to be sent to drivers
2068 * for retrieving the property range values.
2071 i_dladm_range_size(mac_propval_range_t
*r
, size_t *sz
, uint_t
*rcount
)
2073 uint_t count
= r
->mpr_count
;
2075 *sz
= sizeof (mac_propval_range_t
);
2079 switch (r
->mpr_type
) {
2080 case MAC_PROPVAL_UINT32
:
2081 *sz
+= (count
* sizeof (mac_propval_uint32_range_t
));
2093 static dladm_status_t
2094 check_rings(dladm_handle_t handle
, prop_desc_t
*pdp
,
2095 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2096 val_desc_t
**vp
, datalink_media_t media
)
2098 uint_t val_cnt
= *val_cntp
;
2099 val_desc_t
*v
= *vp
;
2102 return (DLADM_STATUS_BADVAL
);
2103 if (strncasecmp(prop_val
[0], "hw", strlen("hw")) == 0) {
2104 v
->vd_val
= UNSPEC_VAL
;
2105 } else if (strncasecmp(prop_val
[0], "sw", strlen("sw")) == 0) {
2108 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
2110 return (DLADM_STATUS_BADVAL
);
2112 return (DLADM_STATUS_OK
);
2116 static dladm_status_t
2117 get_rings_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
2118 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2119 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2121 dld_ioc_macprop_t
*dip
;
2122 dladm_status_t status
= DLADM_STATUS_OK
;
2123 mac_propval_range_t
*rangep
;
2125 mac_propval_uint32_range_t
*ur
;
2127 sz
= sizeof (mac_propval_range_t
);
2129 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
2133 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
2134 if (status
!= DLADM_STATUS_OK
)
2137 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
2139 ur
= &rangep
->mpr_range_uint32
[0];
2140 /* This is the case where the dev doesn't have any rings/groups */
2141 if (rangep
->mpr_count
== 0) {
2142 (*prop_val
)[0] = '\0';
2144 * This is the case where the dev supports rings, but static
2147 } else if (ur
->mpur_min
== ur
->mpur_max
&&
2148 ur
->mpur_max
== 0) {
2149 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw");
2151 * This is the case where the dev supports rings and dynamic
2152 * grouping, but has only one value (say 2 rings and 2 groups).
2154 } else if (ur
->mpur_min
== ur
->mpur_max
) {
2155 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "sw,hw,%d",
2158 * This is the case where the dev supports rings and dynamic
2159 * grouping and has a range of rings.
2162 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
,
2163 "sw,hw,<%ld-%ld>", ur
->mpur_min
, ur
->mpur_max
);
2171 static dladm_status_t
2172 get_rxrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2173 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2174 uint_t flags
, uint_t
*perm_flags
)
2176 mac_resource_props_t mrp
;
2177 dladm_status_t status
;
2178 uint32_t nrings
= 0;
2181 * Get the number of (effective-)rings from the resource property.
2183 if (strcmp(pdp
->pd_name
, "rxrings-effective") == 0) {
2184 status
= i_dladm_get_public_prop(handle
, linkid
,
2185 "resource-effective", flags
, perm_flags
, &mrp
,
2189 * Get the permissions from the "rxrings" property.
2191 status
= i_dladm_get_public_prop(handle
, linkid
, "rxrings",
2192 flags
, perm_flags
, NULL
, 0);
2193 if (status
!= DLADM_STATUS_OK
)
2196 status
= i_dladm_get_public_prop(handle
, linkid
,
2197 "resource", flags
, NULL
, &mrp
, sizeof (mrp
));
2200 if (status
!= DLADM_STATUS_OK
)
2203 if ((mrp
.mrp_mask
& MRP_RX_RINGS
) == 0) {
2205 return (DLADM_STATUS_OK
);
2207 nrings
= mrp
.mrp_nrxrings
;
2209 if (mrp
.mrp_mask
& MRP_RXRINGS_UNSPEC
)
2210 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2211 else if (nrings
== 0)
2212 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2214 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2215 return (DLADM_STATUS_OK
);
2220 extract_rxrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2222 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2224 mrp
->mrp_nrxrings
= 0;
2225 if (vdp
->vd_val
== RESET_VAL
)
2226 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2227 else if (vdp
->vd_val
== UNSPEC_VAL
)
2228 mrp
->mrp_mask
= MRP_RXRINGS_UNSPEC
;
2230 mrp
->mrp_nrxrings
= vdp
->vd_val
;
2231 mrp
->mrp_mask
|= MRP_RX_RINGS
;
2233 return (DLADM_STATUS_OK
);
2237 static dladm_status_t
2238 get_txrings(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2239 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
2240 uint_t flags
, uint_t
*perm_flags
)
2242 mac_resource_props_t mrp
;
2243 dladm_status_t status
;
2244 uint32_t nrings
= 0;
2248 * Get the number of (effective-)rings from the resource property.
2250 if (strcmp(pdp
->pd_name
, "txrings-effective") == 0) {
2251 status
= i_dladm_get_public_prop(handle
, linkid
,
2252 "resource-effective", flags
, perm_flags
, &mrp
,
2256 * Get the permissions from the "txrings" property.
2258 status
= i_dladm_get_public_prop(handle
, linkid
, "txrings",
2259 flags
, perm_flags
, NULL
, 0);
2260 if (status
!= DLADM_STATUS_OK
)
2264 * Get the number of rings from the "resource" property.
2266 status
= i_dladm_get_public_prop(handle
, linkid
, "resource",
2267 flags
, NULL
, &mrp
, sizeof (mrp
));
2270 if (status
!= DLADM_STATUS_OK
)
2273 if ((mrp
.mrp_mask
& MRP_TX_RINGS
) == 0) {
2275 return (DLADM_STATUS_OK
);
2277 nrings
= mrp
.mrp_ntxrings
;
2279 if (mrp
.mrp_mask
& MRP_TXRINGS_UNSPEC
)
2280 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "hw");
2281 else if (nrings
== 0)
2282 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "sw");
2284 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", nrings
);
2285 return (DLADM_STATUS_OK
);
2290 extract_txrings(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2292 mac_resource_props_t
*mrp
= (mac_resource_props_t
*)arg
;
2294 mrp
->mrp_ntxrings
= 0;
2295 if (vdp
->vd_val
== RESET_VAL
)
2296 mrp
->mrp_mask
= MRP_RINGS_RESET
;
2297 else if (vdp
->vd_val
== UNSPEC_VAL
)
2298 mrp
->mrp_mask
= MRP_TXRINGS_UNSPEC
;
2300 mrp
->mrp_ntxrings
= vdp
->vd_val
;
2301 mrp
->mrp_mask
|= MRP_TX_RINGS
;
2303 return (DLADM_STATUS_OK
);
2307 static dladm_status_t
2308 get_cntavail(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
2309 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
2312 if (flags
& DLD_PROP_DEFAULT
)
2313 return (DLADM_STATUS_NOTDEFINED
);
2315 return (get_uint32(handle
, pdp
, linkid
, prop_val
, val_cnt
, media
,
2316 flags
, perm_flags
));
2320 static dladm_status_t
2321 set_resource(dladm_handle_t handle
, prop_desc_t
*pdp
,
2322 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
,
2323 uint_t flags
, datalink_media_t media
)
2325 mac_resource_props_t mrp
;
2326 dladm_status_t status
= DLADM_STATUS_OK
;
2327 dld_ioc_macprop_t
*dip
;
2330 bzero(&mrp
, sizeof (mac_resource_props_t
));
2331 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "resource",
2337 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
2338 resource_prop_t
*rp
= &rsrc_prop_table
[i
];
2340 if (strcmp(pdp
->pd_name
, rp
->rp_name
) != 0)
2343 status
= rp
->rp_extract(vdp
, val_cnt
, &mrp
);
2344 if (status
!= DLADM_STATUS_OK
)
2350 (void) memcpy(dip
->pr_val
, &mrp
, dip
->pr_valsize
);
2351 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
2359 static dladm_status_t
2360 get_protection(dladm_handle_t handle
, prop_desc_t
*pdp
,
2361 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2362 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2364 mac_resource_props_t mrp
;
2366 dladm_status_t status
;
2367 uint32_t i
, cnt
= 0, setbits
[32];
2369 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2370 perm_flags
, &mrp
, sizeof (mrp
));
2371 if (status
!= DLADM_STATUS_OK
)
2374 p
= &mrp
.mrp_protect
;
2375 if ((mrp
.mrp_mask
& MRP_PROTECT
) == 0) {
2377 return (DLADM_STATUS_OK
);
2379 dladm_find_setbits32(p
->mp_types
, setbits
, &cnt
);
2381 return (DLADM_STATUS_BADVALCNT
);
2383 for (i
= 0; i
< cnt
; i
++)
2384 (void) dladm_protect2str(setbits
[i
], prop_val
[i
]);
2387 return (DLADM_STATUS_OK
);
2391 static dladm_status_t
2392 get_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2393 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2394 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2396 mac_resource_props_t mrp
;
2398 dladm_status_t status
;
2401 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2402 perm_flags
, &mrp
, sizeof (mrp
));
2403 if (status
!= DLADM_STATUS_OK
)
2406 p
= &mrp
.mrp_protect
;
2407 if (p
->mp_ipaddrcnt
== 0) {
2409 return (DLADM_STATUS_OK
);
2411 if (p
->mp_ipaddrcnt
> *val_cnt
)
2412 return (DLADM_STATUS_BADVALCNT
);
2414 for (i
= 0; i
< p
->mp_ipaddrcnt
; i
++) {
2416 if (p
->mp_ipaddrs
[i
].ip_version
== IPV4_VERSION
) {
2419 v4addr
= V4_PART_OF_V6(p
->mp_ipaddrs
[i
].ip_addr
);
2420 (void) dladm_ipv4addr2str(&v4addr
, prop_val
[i
]);
2422 (void) dladm_ipv6addr2str(&p
->mp_ipaddrs
[i
].ip_addr
,
2425 len
= strlen(prop_val
[i
]);
2426 (void) sprintf(prop_val
[i
] + len
, "/%d",
2427 p
->mp_ipaddrs
[i
].ip_netmask
);
2429 *val_cnt
= p
->mp_ipaddrcnt
;
2430 return (DLADM_STATUS_OK
);
2434 extract_protection(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2436 mac_resource_props_t
*mrp
= arg
;
2440 for (i
= 0; i
< cnt
; i
++)
2441 types
|= (uint32_t)vdp
[i
].vd_val
;
2443 mrp
->mrp_protect
.mp_types
= types
;
2444 mrp
->mrp_mask
|= MRP_PROTECT
;
2445 return (DLADM_STATUS_OK
);
2449 extract_allowedips(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2451 mac_resource_props_t
*mrp
= arg
;
2452 mac_protect_t
*p
= &mrp
->mrp_protect
;
2455 if (vdp
->vd_val
== 0) {
2458 for (i
= 0; i
< cnt
; i
++) {
2459 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_ipaddrs
[i
],
2460 sizeof (mac_ipaddr_t
));
2463 p
->mp_ipaddrcnt
= cnt
;
2464 mrp
->mrp_mask
|= MRP_PROTECT
;
2465 return (DLADM_STATUS_OK
);
2468 static dladm_status_t
2469 check_single_ip(char *buf
, mac_ipaddr_t
*addr
)
2471 dladm_status_t status
;
2474 boolean_t isv4
= B_TRUE
;
2479 * If the IP address is in CIDR format, parse the bits component
2480 * seperately. An address in this style will be used to indicate an
2481 * entire subnet, so it must be a network number with no host address.
2483 if ((p
= strchr(buf
, '/')) != NULL
) {
2488 return (DLADM_STATUS_INVALID_IP
);
2489 mask
= strtol(p
, &end
, 10);
2490 if (end
!= NULL
&& *end
!= '\0')
2491 return (DLADM_STATUS_INVALID_IP
);
2492 if (mask
> 128|| mask
< 1)
2493 return (DLADM_STATUS_INVALID_IP
);
2496 status
= dladm_str2ipv4addr(buf
, &v4addr
);
2497 if (status
== DLADM_STATUS_INVALID_IP
) {
2498 status
= dladm_str2ipv6addr(buf
, &v6addr
);
2499 if (status
== DLADM_STATUS_OK
)
2502 if (status
!= DLADM_STATUS_OK
)
2506 if (v4addr
== INADDR_ANY
)
2507 return (DLADM_STATUS_INVALID_IP
);
2509 IN6_IPADDR_TO_V4MAPPED(v4addr
, &addr
->ip_addr
);
2510 addr
->ip_version
= IPV4_VERSION
;
2515 * Validate the netmask is in the proper range for v4
2517 if (mask
> 32 || mask
< 1)
2518 return (DLADM_STATUS_INVALID_IP
);
2521 * We have a CIDR style address, confirm that only the
2522 * network number is set.
2524 smask
= 0xFFFFFFFFu
<< (32 - mask
);
2525 if (htonl(v4addr
) & ~smask
)
2526 return (DLADM_STATUS_INVALID_IP
);
2530 addr
->ip_netmask
= mask
;
2532 if (IN6_IS_ADDR_UNSPECIFIED(&v6addr
))
2533 return (DLADM_STATUS_INVALID_IP
);
2535 if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr
))
2536 return (DLADM_STATUS_INVALID_IP
);
2542 * Note that the address in our buffer is stored in
2543 * network byte order.
2546 for (i
= 3; i
>= 0; i
--) {
2547 high
= ffsl(ntohl(v6addr
._S6_un
._S6_u32
[i
]));
2553 if (128 - off
>= mask
)
2554 return (DLADM_STATUS_INVALID_IP
);
2559 addr
->ip_addr
= v6addr
;
2560 addr
->ip_version
= IPV6_VERSION
;
2561 addr
->ip_netmask
= mask
;
2563 return (DLADM_STATUS_OK
);
2567 static dladm_status_t
2568 check_allowedips(dladm_handle_t handle
, prop_desc_t
*pdp
,
2569 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2570 val_desc_t
**vdpp
, datalink_media_t media
)
2572 dladm_status_t status
;
2575 uint_t val_cnt
= *val_cntp
;
2576 val_desc_t
*vdp
= *vdpp
;
2578 if (val_cnt
> MPT_MAXIPADDR
)
2579 return (DLADM_STATUS_BADVALCNT
);
2581 for (i
= 0; i
< val_cnt
; i
++) {
2582 if ((addr
= calloc(1, sizeof (mac_ipaddr_t
))) == NULL
) {
2583 status
= DLADM_STATUS_NOMEM
;
2586 vdp
[i
].vd_val
= (uintptr_t)addr
;
2588 status
= check_single_ip(prop_val
[i
], addr
);
2589 if (status
!= DLADM_STATUS_OK
)
2592 return (DLADM_STATUS_OK
);
2595 for (i
= 0; i
< val_cnt
; i
++) {
2596 free((void *)vdp
[i
].vd_val
);
2597 vdp
[i
].vd_val
= NULL
;
2603 dladm_cid2str(mac_dhcpcid_t
*cid
, char *buf
)
2605 char tmp_buf
[DLADM_STRSIZE
];
2608 switch (cid
->dc_form
) {
2609 case CIDFORM_TYPED
: {
2610 uint16_t duidtype
, hwtype
;
2611 uint32_t timestamp
, ennum
;
2614 if (cid
->dc_len
< sizeof (duidtype
))
2617 bcopy(cid
->dc_id
, &duidtype
, sizeof (duidtype
));
2618 duidtype
= ntohs(duidtype
);
2620 case DHCPV6_DUID_LLT
: {
2623 if (cid
->dc_len
< sizeof (llt
))
2626 bcopy(cid
->dc_id
, &llt
, sizeof (llt
));
2627 hwtype
= ntohs(llt
.dllt_hwtype
);
2628 timestamp
= ntohl(llt
.dllt_time
);
2629 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (llt
),
2630 NULL
, cid
->dc_len
- sizeof (llt
), IFT_OTHER
);
2634 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%d.%s",
2635 duidtype
, hwtype
, timestamp
, lladdr
);
2639 case DHCPV6_DUID_EN
: {
2642 if (cid
->dc_len
< sizeof (en
))
2645 bcopy(cid
->dc_id
, &en
, sizeof (en
));
2646 ennum
= DHCPV6_GET_ENTNUM(&en
);
2647 hexlen
= sizeof (tmp_buf
);
2648 if (octet_to_hexascii(cid
->dc_id
+ sizeof (en
),
2649 cid
->dc_len
- sizeof (en
), tmp_buf
, &hexlen
) != 0)
2652 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2653 duidtype
, ennum
, tmp_buf
);
2656 case DHCPV6_DUID_LL
: {
2659 if (cid
->dc_len
< sizeof (ll
))
2662 bcopy(cid
->dc_id
, &ll
, sizeof (ll
));
2663 hwtype
= ntohs(ll
.dll_hwtype
);
2664 lladdr
= _link_ntoa(cid
->dc_id
+ sizeof (ll
),
2665 NULL
, cid
->dc_len
- sizeof (ll
), IFT_OTHER
);
2669 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%d.%s",
2670 duidtype
, hwtype
, lladdr
);
2675 hexlen
= sizeof (tmp_buf
);
2676 if (octet_to_hexascii(cid
->dc_id
+ sizeof (duidtype
),
2677 cid
->dc_len
- sizeof (duidtype
),
2678 tmp_buf
, &hexlen
) != 0)
2681 (void) snprintf(buf
, DLADM_STRSIZE
, "%d.%s",
2688 hexlen
= sizeof (tmp_buf
);
2689 if (octet_to_hexascii(cid
->dc_id
, cid
->dc_len
,
2690 tmp_buf
, &hexlen
) != 0)
2693 (void) snprintf(buf
, DLADM_STRSIZE
, "0x%s", tmp_buf
);
2699 for (i
= 0; i
< cid
->dc_len
; i
++) {
2700 if (!isprint(cid
->dc_id
[i
]))
2703 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", cid
->dc_id
);
2712 (void) snprintf(buf
, DLADM_STRSIZE
, "<unknown>");
2715 static dladm_status_t
2716 dladm_str2cid(char *buf
, mac_dhcpcid_t
*cid
)
2719 char tmp_buf
[DLADM_STRSIZE
];
2720 uint_t hexlen
, cidlen
;
2722 bzero(cid
, sizeof (*cid
));
2723 if (isdigit(*ptr
) &&
2724 ptr
[strspn(ptr
, "0123456789")] == '.') {
2733 duidtype
= strtoul(ptr
, &cp
, 0);
2734 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.' ||
2735 duidtype
> USHRT_MAX
)
2736 return (DLADM_STATUS_BADARG
);
2739 if (duidtype
!= 0 && duidtype
<= DHCPV6_DUID_LL
) {
2741 subtype
= strtoul(ptr
, &cp
, 0);
2742 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2743 return (DLADM_STATUS_BADARG
);
2747 case DHCPV6_DUID_LLT
: {
2751 timestamp
= strtoul(ptr
, &cp
, 0);
2752 if (ptr
== cp
|| errno
!= 0 || *cp
!= '.')
2753 return (DLADM_STATUS_BADARG
);
2756 lladdr
= _link_aton(ptr
, &addrlen
);
2758 return (DLADM_STATUS_BADARG
);
2760 cidlen
= sizeof (llt
) + addrlen
;
2761 if (cidlen
> sizeof (cid
->dc_id
)) {
2763 return (DLADM_STATUS_TOOSMALL
);
2765 llt
.dllt_dutype
= htons(duidtype
);
2766 llt
.dllt_hwtype
= htons(subtype
);
2767 llt
.dllt_time
= htonl(timestamp
);
2768 bcopy(&llt
, cid
->dc_id
, sizeof (llt
));
2769 bcopy(lladdr
, cid
->dc_id
+ sizeof (llt
), addrlen
);
2773 case DHCPV6_DUID_LL
: {
2776 lladdr
= _link_aton(ptr
, &addrlen
);
2778 return (DLADM_STATUS_BADARG
);
2780 cidlen
= sizeof (ll
) + addrlen
;
2781 if (cidlen
> sizeof (cid
->dc_id
)) {
2783 return (DLADM_STATUS_TOOSMALL
);
2785 ll
.dll_dutype
= htons(duidtype
);
2786 ll
.dll_hwtype
= htons(subtype
);
2787 bcopy(&ll
, cid
->dc_id
, sizeof (ll
));
2788 bcopy(lladdr
, cid
->dc_id
+ sizeof (ll
), addrlen
);
2793 hexlen
= sizeof (tmp_buf
);
2794 if (hexascii_to_octet(ptr
, strlen(ptr
),
2795 tmp_buf
, &hexlen
) != 0)
2796 return (DLADM_STATUS_BADARG
);
2798 if (duidtype
== DHCPV6_DUID_EN
) {
2801 en
.den_dutype
= htons(duidtype
);
2802 DHCPV6_SET_ENTNUM(&en
, subtype
);
2804 cidlen
= sizeof (en
) + hexlen
;
2805 if (cidlen
> sizeof (cid
->dc_id
))
2806 return (DLADM_STATUS_TOOSMALL
);
2808 bcopy(&en
, cid
->dc_id
, sizeof (en
));
2809 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (en
),
2812 uint16_t dutype
= htons(duidtype
);
2814 cidlen
= sizeof (dutype
) + hexlen
;
2815 if (cidlen
> sizeof (cid
->dc_id
))
2816 return (DLADM_STATUS_TOOSMALL
);
2818 bcopy(&dutype
, cid
->dc_id
, sizeof (dutype
));
2819 bcopy(tmp_buf
, cid
->dc_id
+ sizeof (dutype
),
2825 cid
->dc_form
= CIDFORM_TYPED
;
2826 } else if (strncasecmp("0x", ptr
, 2) == 0 && ptr
[2] != '\0') {
2828 hexlen
= sizeof (tmp_buf
);
2829 if (hexascii_to_octet(ptr
, strlen(ptr
), tmp_buf
,
2831 return (DLADM_STATUS_BADARG
);
2834 if (cidlen
> sizeof (cid
->dc_id
))
2835 return (DLADM_STATUS_TOOSMALL
);
2837 bcopy(tmp_buf
, cid
->dc_id
, cidlen
);
2838 cid
->dc_form
= CIDFORM_HEX
;
2840 cidlen
= strlen(ptr
);
2841 if (cidlen
> sizeof (cid
->dc_id
))
2842 return (DLADM_STATUS_TOOSMALL
);
2844 bcopy(ptr
, cid
->dc_id
, cidlen
);
2845 cid
->dc_form
= CIDFORM_STR
;
2847 cid
->dc_len
= cidlen
;
2848 return (DLADM_STATUS_OK
);
2852 static dladm_status_t
2853 get_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2854 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2855 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2857 mac_resource_props_t mrp
;
2859 dladm_status_t status
;
2862 status
= i_dladm_get_public_prop(handle
, linkid
, "resource", flags
,
2863 perm_flags
, &mrp
, sizeof (mrp
));
2864 if (status
!= DLADM_STATUS_OK
)
2867 p
= &mrp
.mrp_protect
;
2868 if (p
->mp_cidcnt
== 0) {
2870 return (DLADM_STATUS_OK
);
2872 if (p
->mp_cidcnt
> *val_cnt
)
2873 return (DLADM_STATUS_BADVALCNT
);
2875 for (i
= 0; i
< p
->mp_cidcnt
; i
++) {
2876 mac_dhcpcid_t
*cid
= &p
->mp_cids
[i
];
2878 dladm_cid2str(cid
, prop_val
[i
]);
2880 *val_cnt
= p
->mp_cidcnt
;
2881 return (DLADM_STATUS_OK
);
2885 extract_allowedcids(val_desc_t
*vdp
, uint_t cnt
, void *arg
)
2887 mac_resource_props_t
*mrp
= arg
;
2888 mac_protect_t
*p
= &mrp
->mrp_protect
;
2891 if (vdp
->vd_val
== 0) {
2894 for (i
= 0; i
< cnt
; i
++) {
2895 bcopy((void *)vdp
[i
].vd_val
, &p
->mp_cids
[i
],
2896 sizeof (mac_dhcpcid_t
));
2900 mrp
->mrp_mask
|= MRP_PROTECT
;
2901 return (DLADM_STATUS_OK
);
2905 static dladm_status_t
2906 check_allowedcids(dladm_handle_t handle
, prop_desc_t
*pdp
,
2907 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
,
2908 uint_t flags
, val_desc_t
**vdpp
, datalink_media_t media
)
2910 dladm_status_t status
;
2913 uint_t val_cnt
= *val_cntp
;
2914 val_desc_t
*vdp
= *vdpp
;
2916 if (val_cnt
> MPT_MAXCID
)
2917 return (DLADM_STATUS_BADVALCNT
);
2919 for (i
= 0; i
< val_cnt
; i
++) {
2920 if ((cid
= calloc(1, sizeof (mac_dhcpcid_t
))) == NULL
) {
2921 status
= DLADM_STATUS_NOMEM
;
2924 vdp
[i
].vd_val
= (uintptr_t)cid
;
2926 status
= dladm_str2cid(prop_val
[i
], cid
);
2927 if (status
!= DLADM_STATUS_OK
)
2930 return (DLADM_STATUS_OK
);
2933 for (i
= 0; i
< val_cnt
; i
++) {
2934 free((void *)vdp
[i
].vd_val
);
2935 vdp
[i
].vd_val
= NULL
;
2941 static dladm_status_t
2942 get_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
2943 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
2944 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
2946 mac_secondary_addr_t sa
;
2947 dladm_status_t status
;
2950 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
2951 perm_flags
, &sa
, sizeof (sa
));
2952 if (status
!= DLADM_STATUS_OK
)
2955 if (sa
.ms_addrcnt
> *val_cnt
)
2956 return (DLADM_STATUS_BADVALCNT
);
2958 for (i
= 0; i
< sa
.ms_addrcnt
; i
++) {
2959 if (dladm_aggr_macaddr2str(
2960 (const unsigned char *)&sa
.ms_addrs
[i
], prop_val
[i
]) ==
2963 return (DLADM_STATUS_NOMEM
);
2966 *val_cnt
= sa
.ms_addrcnt
;
2967 return (DLADM_STATUS_OK
);
2971 static dladm_status_t
2972 check_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pdp
,
2973 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
2974 val_desc_t
**vdpp
, datalink_media_t media
)
2976 dladm_status_t status
;
2980 uint_t val_cnt
= *val_cntp
;
2981 val_desc_t
*vdp
= *vdpp
;
2983 if (val_cnt
>= MPT_MAXMACADDR
)
2984 return (DLADM_STATUS_BADVALCNT
);
2986 for (i
= 0; i
< val_cnt
; i
++) {
2987 addr
= _link_aton(prop_val
[i
], (int *)&len
);
2989 if (len
== (uint_t
)-1)
2990 status
= DLADM_STATUS_MACADDRINVAL
;
2992 status
= DLADM_STATUS_NOMEM
;
2996 vdp
[i
].vd_val
= (uintptr_t)addr
;
2998 return (DLADM_STATUS_OK
);
3001 for (i
= 0; i
< val_cnt
; i
++) {
3002 free((void *)vdp
[i
].vd_val
);
3003 vdp
[i
].vd_val
= NULL
;
3009 static dladm_status_t
3010 set_secondary_macs(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
3011 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3013 dladm_status_t status
;
3014 dld_ioc_macprop_t
*dip
;
3016 mac_secondary_addr_t msa
;
3018 dip
= i_dladm_buf_alloc_by_name(0, linkid
, "secondary-macs", 0,
3023 if (vdp
->vd_val
== 0) {
3024 val_cnt
= (uint_t
)-1;
3026 for (i
= 0; i
< val_cnt
; i
++) {
3027 bcopy((void *)vdp
[i
].vd_val
, msa
.ms_addrs
[i
],
3031 msa
.ms_addrcnt
= val_cnt
;
3032 bcopy(&msa
, dip
->pr_val
, dip
->pr_valsize
);
3034 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3041 static dladm_status_t
3042 get_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3043 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3044 uint_t flags
, uint_t
*perm_flags
)
3046 struct dlautopush dlap
;
3048 dladm_status_t status
;
3050 if (flags
& DLD_PROP_DEFAULT
)
3051 return (DLADM_STATUS_NOTDEFINED
);
3053 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3054 perm_flags
, &dlap
, sizeof (dlap
));
3055 if (status
!= DLADM_STATUS_OK
)
3058 if (dlap
.dap_npush
== 0) {
3060 return (DLADM_STATUS_OK
);
3062 for (i
= 0, len
= 0; i
< dlap
.dap_npush
; i
++) {
3064 (void) snprintf(*prop_val
+ len
,
3065 DLADM_PROP_VAL_MAX
- len
, "%c", AP_DELIMITER
);
3068 (void) snprintf(*prop_val
+ len
, DLADM_PROP_VAL_MAX
- len
,
3069 "%s", dlap
.dap_aplist
[i
]);
3070 len
+= strlen(dlap
.dap_aplist
[i
]);
3071 if (dlap
.dap_anchor
- 1 == i
) {
3072 (void) snprintf(*prop_val
+ len
,
3073 DLADM_PROP_VAL_MAX
- len
, "%c%s", AP_DELIMITER
,
3075 len
+= (strlen(AP_ANCHOR
) + 1);
3079 return (DLADM_STATUS_OK
);
3083 * Add the specified module to the dlautopush structure; returns a
3084 * DLADM_STATUS_* code.
3087 i_dladm_add_ap_module(const char *module
, struct dlautopush
*dlap
)
3089 if ((strlen(module
) == 0) || (strlen(module
) > FMNAMESZ
))
3090 return (DLADM_STATUS_BADVAL
);
3092 if (strncasecmp(module
, AP_ANCHOR
, strlen(AP_ANCHOR
)) == 0) {
3094 * We don't allow multiple anchors, and the anchor must
3095 * be after at least one module.
3097 if (dlap
->dap_anchor
!= 0)
3098 return (DLADM_STATUS_BADVAL
);
3099 if (dlap
->dap_npush
== 0)
3100 return (DLADM_STATUS_BADVAL
);
3102 dlap
->dap_anchor
= dlap
->dap_npush
;
3103 return (DLADM_STATUS_OK
);
3105 if (dlap
->dap_npush
>= MAXAPUSH
)
3106 return (DLADM_STATUS_BADVALCNT
);
3108 (void) strlcpy(dlap
->dap_aplist
[dlap
->dap_npush
++], module
,
3111 return (DLADM_STATUS_OK
);
3115 * Currently, both '.' and ' '(space) can be used as the delimiters between
3116 * autopush modules. The former is used in dladm set-linkprop, and the
3117 * latter is used in the autopush(1M) file.
3120 static dladm_status_t
3121 check_autopush(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3122 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3123 datalink_media_t media
)
3126 struct dlautopush
*dlap
;
3127 dladm_status_t status
;
3128 char val
[DLADM_PROP_VAL_MAX
];
3130 uint_t val_cnt
= *val_cntp
;
3131 val_desc_t
*vdp
= *vdpp
;
3134 return (DLADM_STATUS_BADVALCNT
);
3136 if (prop_val
!= NULL
) {
3137 dlap
= malloc(sizeof (struct dlautopush
));
3139 return (DLADM_STATUS_NOMEM
);
3141 (void) memset(dlap
, 0, sizeof (struct dlautopush
));
3142 (void) snprintf(delimiters
, 4, " %c\n", AP_DELIMITER
);
3143 bcopy(*prop_val
, val
, DLADM_PROP_VAL_MAX
);
3144 module
= strtok(val
, delimiters
);
3145 while (module
!= NULL
) {
3146 status
= i_dladm_add_ap_module(module
, dlap
);
3147 if (status
!= DLADM_STATUS_OK
)
3149 module
= strtok(NULL
, delimiters
);
3152 vdp
->vd_val
= (uintptr_t)dlap
;
3156 return (DLADM_STATUS_OK
);
3159 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3162 static dladm_status_t
3163 get_rate_common(dladm_handle_t handle
, prop_desc_t
*pdp
,
3164 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
, uint_t id
,
3169 dladm_status_t status
= DLADM_STATUS_OK
;
3171 wrp
= malloc(WLDP_BUFSIZE
);
3173 return (DLADM_STATUS_NOMEM
);
3175 status
= i_dladm_wlan_param(handle
, linkid
, wrp
, id
, WLDP_BUFSIZE
,
3177 if (status
!= DLADM_STATUS_OK
)
3180 if (wrp
->wl_rates_num
> *val_cnt
) {
3181 status
= DLADM_STATUS_TOOSMALL
;
3185 if (wrp
->wl_rates_rates
[0] == 0) {
3186 prop_val
[0][0] = '\0';
3191 for (i
= 0; i
< wrp
->wl_rates_num
; i
++) {
3192 (void) snprintf(prop_val
[i
], DLADM_STRSIZE
, "%.*f",
3193 wrp
->wl_rates_rates
[i
] % 2,
3194 (float)wrp
->wl_rates_rates
[i
] / 2);
3196 *val_cnt
= wrp
->wl_rates_num
;
3197 *perm_flags
= MAC_PROP_PERM_RW
;
3204 static dladm_status_t
3205 get_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3206 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3207 uint_t flags
, uint_t
*perm_flags
)
3209 if (media
!= DL_WIFI
) {
3210 return (get_speed(handle
, pdp
, linkid
, prop_val
,
3211 val_cnt
, media
, flags
, perm_flags
));
3214 return (get_rate_common(handle
, pdp
, linkid
, prop_val
, val_cnt
,
3215 MAC_PROP_WL_DESIRED_RATES
, perm_flags
));
3219 static dladm_status_t
3220 get_rate_mod(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3221 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3222 uint_t flags
, uint_t
*perm_flags
)
3227 * Speed for ethernet links is unbounded. E.g., 802.11b
3228 * links can have a speed of 5.5 Gbps.
3230 return (DLADM_STATUS_NOTSUP
);
3233 return (get_rate_common(handle
, pdp
, linkid
, prop_val
,
3234 val_cnt
, MAC_PROP_WL_SUPPORTED_RATES
, perm_flags
));
3236 return (DLADM_STATUS_BADARG
);
3240 static dladm_status_t
3241 set_wlan_rate(dladm_handle_t handle
, datalink_id_t linkid
,
3242 dladm_wlan_rates_t
*rates
)
3247 dladm_status_t status
= DLADM_STATUS_OK
;
3249 wrp
= malloc(WLDP_BUFSIZE
);
3251 return (DLADM_STATUS_NOMEM
);
3253 bzero(wrp
, WLDP_BUFSIZE
);
3254 for (i
= 0; i
< rates
->wr_cnt
; i
++)
3255 wrp
->wl_rates_rates
[i
] = rates
->wr_rates
[i
];
3256 wrp
->wl_rates_num
= rates
->wr_cnt
;
3258 len
= offsetof(wl_rates_t
, wl_rates_rates
) +
3259 (rates
->wr_cnt
* sizeof (char)) + WIFI_BUF_OFFSET
;
3260 status
= i_dladm_wlan_param(handle
, linkid
, wrp
,
3261 MAC_PROP_WL_DESIRED_RATES
, len
, B_TRUE
);
3268 static dladm_status_t
3269 set_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3270 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3272 dladm_wlan_rates_t rates
;
3273 dladm_status_t status
;
3276 * can currently set rate on WIFI links only.
3278 if (media
!= DL_WIFI
)
3279 return (DLADM_STATUS_PROPRDONLY
);
3282 return (DLADM_STATUS_BADVALCNT
);
3285 rates
.wr_rates
[0] = vdp
[0].vd_val
;
3287 status
= set_wlan_rate(handle
, linkid
, &rates
);
3293 static dladm_status_t
3294 check_rate(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3295 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3296 datalink_media_t media
)
3299 uint_t modval_cnt
= MAX_SUPPORT_RATES
;
3300 char *buf
, **modval
;
3301 dladm_status_t status
;
3303 uint_t val_cnt
= *val_cntp
;
3304 val_desc_t
*vdp
= *vdpp
;
3307 return (DLADM_STATUS_BADVALCNT
);
3309 buf
= malloc((sizeof (char *) + DLADM_STRSIZE
) *
3312 status
= DLADM_STATUS_NOMEM
;
3316 modval
= (char **)(void *)buf
;
3317 for (i
= 0; i
< MAX_SUPPORT_RATES
; i
++) {
3318 modval
[i
] = buf
+ sizeof (char *) * MAX_SUPPORT_RATES
+
3322 status
= get_rate_mod(handle
, NULL
, linkid
, modval
, &modval_cnt
,
3323 media
, 0, &perm_flags
);
3324 if (status
!= DLADM_STATUS_OK
)
3327 for (i
= 0; i
< modval_cnt
; i
++) {
3328 if (strcasecmp(*prop_val
, modval
[i
]) == 0) {
3329 vdp
->vd_val
= (uintptr_t)(uint_t
)
3330 (atof(*prop_val
) * 2);
3331 status
= DLADM_STATUS_OK
;
3335 if (i
== modval_cnt
)
3336 status
= DLADM_STATUS_BADVAL
;
3342 static dladm_status_t
3343 get_phyconf(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
3346 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_PHY_CONFIG
,
3351 static dladm_status_t
3352 get_channel(dladm_handle_t handle
, prop_desc_t
*pdp
,
3353 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3354 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3357 char buf
[WLDP_BUFSIZE
];
3358 dladm_status_t status
;
3359 wl_phy_conf_t wl_phy_conf
;
3361 if ((status
= get_phyconf(handle
, linkid
, buf
, sizeof (buf
)))
3365 (void) memcpy(&wl_phy_conf
, buf
, sizeof (wl_phy_conf
));
3366 if (!i_dladm_wlan_convert_chan(&wl_phy_conf
, &channel
))
3367 return (DLADM_STATUS_NOTFOUND
);
3369 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%u", channel
);
3371 *perm_flags
= MAC_PROP_PERM_READ
;
3372 return (DLADM_STATUS_OK
);
3376 static dladm_status_t
3377 get_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3378 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3379 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3383 char buf
[WLDP_BUFSIZE
];
3384 dladm_status_t status
;
3386 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3387 MAC_PROP_WL_POWER_MODE
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3390 (void) memcpy(&mode
, buf
, sizeof (mode
));
3391 switch (mode
.wl_ps_mode
) {
3402 return (DLADM_STATUS_NOTFOUND
);
3404 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3406 *perm_flags
= MAC_PROP_PERM_RW
;
3407 return (DLADM_STATUS_OK
);
3411 static dladm_status_t
3412 set_powermode(dladm_handle_t handle
, prop_desc_t
*pdp
,
3413 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3414 datalink_media_t media
)
3416 dladm_wlan_powermode_t powermode
= vdp
->vd_val
;
3417 wl_ps_mode_t ps_mode
;
3420 return (DLADM_STATUS_BADVALCNT
);
3422 (void) memset(&ps_mode
, 0xff, sizeof (ps_mode
));
3424 switch (powermode
) {
3425 case DLADM_WLAN_PM_OFF
:
3426 ps_mode
.wl_ps_mode
= WL_PM_AM
;
3428 case DLADM_WLAN_PM_MAX
:
3429 ps_mode
.wl_ps_mode
= WL_PM_MPS
;
3431 case DLADM_WLAN_PM_FAST
:
3432 ps_mode
.wl_ps_mode
= WL_PM_FAST
;
3435 return (DLADM_STATUS_NOTSUP
);
3437 return (i_dladm_wlan_param(handle
, linkid
, &ps_mode
,
3438 MAC_PROP_WL_POWER_MODE
, sizeof (ps_mode
), B_TRUE
));
3442 static dladm_status_t
3443 get_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3444 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
,
3445 uint_t flags
, uint_t
*perm_flags
)
3449 char buf
[WLDP_BUFSIZE
];
3450 dladm_status_t status
;
3452 if ((status
= i_dladm_wlan_param(handle
, linkid
, buf
,
3453 MAC_PROP_WL_RADIO
, sizeof (buf
), B_FALSE
)) != DLADM_STATUS_OK
)
3456 (void) memcpy(&radio
, buf
, sizeof (radio
));
3465 return (DLADM_STATUS_NOTFOUND
);
3467 (void) snprintf(*prop_val
, DLADM_STRSIZE
, "%s", s
);
3469 *perm_flags
= MAC_PROP_PERM_RW
;
3470 return (DLADM_STATUS_OK
);
3474 static dladm_status_t
3475 set_radio(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3476 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
3478 dladm_wlan_radio_t radio
= vdp
->vd_val
;
3482 return (DLADM_STATUS_BADVALCNT
);
3485 case DLADM_WLAN_RADIO_ON
:
3488 case DLADM_WLAN_RADIO_OFF
:
3492 return (DLADM_STATUS_NOTSUP
);
3494 return (i_dladm_wlan_param(handle
, linkid
, &r
, MAC_PROP_WL_RADIO
,
3495 sizeof (r
), B_TRUE
));
3499 static dladm_status_t
3500 check_hoplimit(dladm_handle_t handle
, prop_desc_t
*pdp
,
3501 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3502 val_desc_t
**vdpp
, datalink_media_t media
)
3506 uint_t val_cnt
= *val_cntp
;
3507 val_desc_t
*vdp
= *vdpp
;
3510 return (DLADM_STATUS_BADVALCNT
);
3513 hlim
= strtol(*prop_val
, &ep
, 10);
3514 if (errno
!= 0 || ep
== *prop_val
|| hlim
< 1 ||
3515 hlim
> (int32_t)UINT8_MAX
)
3516 return (DLADM_STATUS_BADVAL
);
3518 return (DLADM_STATUS_OK
);
3522 static dladm_status_t
3523 check_encaplim(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3524 char **prop_val
, uint_t
*val_cntp
, uint_t flags
, val_desc_t
**vdpp
,
3525 datalink_media_t media
)
3529 uint_t val_cnt
= *val_cntp
;
3530 val_desc_t
*vdp
= *vdpp
;
3532 if (media
!= DL_IPV6
)
3533 return (DLADM_STATUS_BADARG
);
3536 return (DLADM_STATUS_BADVALCNT
);
3539 elim
= strtol(*prop_val
, &ep
, 10);
3540 if (errno
!= 0 || ep
== *prop_val
|| elim
< 0 ||
3541 elim
> (int32_t)UINT8_MAX
)
3542 return (DLADM_STATUS_BADVAL
);
3544 return (DLADM_STATUS_OK
);
3547 static dladm_status_t
3548 i_dladm_set_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3549 const char *prop_name
, char **prop_val
, uint_t val_cnt
)
3551 char buf
[MAXLINELEN
];
3554 dladm_status_t status
;
3556 status
= dladm_open_conf(handle
, linkid
, &conf
);
3557 if (status
!= DLADM_STATUS_OK
)
3564 status
= dladm_unset_conf_field(handle
, conf
, prop_name
);
3565 if (status
== DLADM_STATUS_OK
)
3566 status
= dladm_write_conf(handle
, conf
);
3571 for (i
= 0; i
< val_cnt
; i
++) {
3572 (void) strlcat(buf
, prop_val
[i
], MAXLINELEN
);
3573 if (i
!= val_cnt
- 1)
3574 (void) strlcat(buf
, ",", MAXLINELEN
);
3577 status
= dladm_set_conf_field(handle
, conf
, prop_name
, DLADM_TYPE_STR
,
3579 if (status
== DLADM_STATUS_OK
)
3580 status
= dladm_write_conf(handle
, conf
);
3583 dladm_destroy_conf(handle
, conf
);
3587 static dladm_status_t
3588 i_dladm_get_linkprop_db(dladm_handle_t handle
, datalink_id_t linkid
,
3589 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
3591 char buf
[MAXLINELEN
], *str
;
3594 dladm_status_t status
;
3596 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3597 if (status
!= DLADM_STATUS_OK
)
3600 status
= dladm_get_conf_field(handle
, conf
, prop_name
, buf
, MAXLINELEN
);
3601 if (status
!= DLADM_STATUS_OK
)
3604 str
= strtok(buf
, ",");
3605 while (str
!= NULL
) {
3606 if (cnt
== *val_cntp
) {
3607 status
= DLADM_STATUS_TOOSMALL
;
3610 (void) strlcpy(prop_val
[cnt
++], str
, DLADM_PROP_VAL_MAX
);
3611 str
= strtok(NULL
, ",");
3617 dladm_destroy_conf(handle
, conf
);
3622 * Walk persistent private link properties of a link.
3624 static dladm_status_t
3625 i_dladm_walk_linkprop_priv_db(dladm_handle_t handle
, datalink_id_t linkid
,
3626 void *arg
, int (*func
)(dladm_handle_t
, datalink_id_t
, const char *, void *))
3628 dladm_status_t status
;
3630 char last_attr
[MAXLINKATTRLEN
];
3631 char attr
[MAXLINKATTRLEN
];
3632 char attrval
[MAXLINKATTRVALLEN
];
3635 if (linkid
== DATALINK_INVALID_LINKID
|| func
== NULL
)
3636 return (DLADM_STATUS_BADARG
);
3638 status
= dladm_getsnap_conf(handle
, linkid
, &conf
);
3639 if (status
!= DLADM_STATUS_OK
)
3642 last_attr
[0] = '\0';
3643 while ((status
= dladm_getnext_conf_linkprop(handle
, conf
, last_attr
,
3644 attr
, attrval
, MAXLINKATTRVALLEN
, &attrsz
)) == DLADM_STATUS_OK
) {
3645 if (attr
[0] == '_') {
3646 if (func(handle
, linkid
, attr
, arg
) ==
3647 DLADM_WALK_TERMINATE
)
3650 (void) strlcpy(last_attr
, attr
, MAXLINKATTRLEN
);
3653 dladm_destroy_conf(handle
, conf
);
3654 return (DLADM_STATUS_OK
);
3657 static link_attr_t
*
3658 dladm_name2prop(const char *prop_name
)
3662 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3663 if (strcmp(p
->pp_name
, prop_name
) == 0)
3669 static link_attr_t
*
3670 dladm_id2prop(mac_prop_id_t propid
)
3674 for (p
= link_attr
; p
->pp_id
!= MAC_PROP_PRIVATE
; p
++) {
3675 if (p
->pp_id
== propid
)
3681 static dld_ioc_macprop_t
*
3682 i_dladm_buf_alloc_impl(size_t valsize
, datalink_id_t linkid
,
3683 const char *prop_name
, mac_prop_id_t propid
, uint_t flags
,
3684 dladm_status_t
*status
)
3687 dld_ioc_macprop_t
*dip
;
3689 *status
= DLADM_STATUS_OK
;
3690 dsize
= MAC_PROP_BUFSIZE(valsize
);
3691 dip
= malloc(dsize
);
3693 *status
= DLADM_STATUS_NOMEM
;
3697 dip
->pr_valsize
= valsize
;
3698 (void) strlcpy(dip
->pr_name
, prop_name
, sizeof (dip
->pr_name
));
3699 dip
->pr_linkid
= linkid
;
3700 dip
->pr_num
= propid
;
3701 dip
->pr_flags
= flags
;
3705 static dld_ioc_macprop_t
*
3706 i_dladm_buf_alloc_by_name(size_t valsize
, datalink_id_t linkid
,
3707 const char *prop_name
, uint_t flags
, dladm_status_t
*status
)
3711 p
= dladm_name2prop(prop_name
);
3712 valsize
= MAX(p
->pp_valsize
, valsize
);
3713 return (i_dladm_buf_alloc_impl(valsize
, linkid
, prop_name
, p
->pp_id
,
3717 static dld_ioc_macprop_t
*
3718 i_dladm_buf_alloc_by_id(size_t valsize
, datalink_id_t linkid
,
3719 mac_prop_id_t propid
, uint_t flags
, dladm_status_t
*status
)
3723 p
= dladm_id2prop(propid
);
3724 valsize
= MAX(p
->pp_valsize
, valsize
);
3725 return (i_dladm_buf_alloc_impl(valsize
, linkid
, p
->pp_name
, propid
,
3730 static dladm_status_t
3731 set_public_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
3732 datalink_id_t linkid
, val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
,
3733 datalink_media_t media
)
3735 dld_ioc_macprop_t
*dip
;
3736 dladm_status_t status
= DLADM_STATUS_OK
;
3742 dip
= i_dladm_buf_alloc_by_name(0, linkid
, pdp
->pd_name
, 0, &status
);
3746 if (pdp
->pd_flags
& PD_CHECK_ALLOC
)
3747 val
= (void *)vdp
->vd_val
;
3750 * Currently all 1/2/4-byte size properties are byte/word/int.
3751 * No need (yet) to distinguish these from arrays of same size.
3753 switch (dip
->pr_valsize
) {
3773 (void) memcpy(dip
->pr_val
, val
, dip
->pr_valsize
);
3775 dip
->pr_valsize
= 0;
3777 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
3785 i_dladm_macprop(dladm_handle_t handle
, void *dip
, boolean_t set
)
3787 dladm_status_t status
= DLADM_STATUS_OK
;
3789 if (ioctl(dladm_dld_fd(handle
),
3790 (set
? DLDIOC_SETMACPROP
: DLDIOC_GETMACPROP
), dip
))
3791 status
= dladm_errno2status(errno
);
3796 static dladm_status_t
3797 i_dladm_get_public_prop(dladm_handle_t handle
, datalink_id_t linkid
,
3798 char *prop_name
, uint_t flags
, uint_t
*perm_flags
, void *arg
, size_t size
)
3800 dld_ioc_macprop_t
*dip
;
3801 dladm_status_t status
;
3803 dip
= i_dladm_buf_alloc_by_name(0, linkid
, prop_name
, flags
, &status
);
3805 return (DLADM_STATUS_NOMEM
);
3807 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
3808 if (status
!= DLADM_STATUS_OK
) {
3813 if (perm_flags
!= NULL
)
3814 *perm_flags
= dip
->pr_perm_flags
;
3817 (void) memcpy(arg
, dip
->pr_val
, size
);
3819 return (DLADM_STATUS_OK
);
3823 static dladm_status_t
3824 check_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3825 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
3826 val_desc_t
**vp
, datalink_media_t media
)
3828 uint_t val_cnt
= *val_cntp
;
3829 val_desc_t
*v
= *vp
;
3832 return (DLADM_STATUS_BADVAL
);
3833 v
->vd_val
= strtoul(prop_val
[0], NULL
, 0);
3834 return (DLADM_STATUS_OK
);
3838 static dladm_status_t
3839 get_duplex(dladm_handle_t handle
, prop_desc_t
*pdp
,
3840 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3841 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3843 link_duplex_t link_duplex
;
3844 dladm_status_t status
;
3846 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "link_duplex",
3847 KSTAT_DATA_UINT32
, &link_duplex
)) != 0)
3850 switch (link_duplex
) {
3851 case LINK_DUPLEX_FULL
:
3852 (void) strcpy(*prop_val
, "full");
3854 case LINK_DUPLEX_HALF
:
3855 (void) strcpy(*prop_val
, "half");
3858 (void) strcpy(*prop_val
, "unknown");
3862 return (DLADM_STATUS_OK
);
3866 static dladm_status_t
3867 get_speed(dladm_handle_t handle
, prop_desc_t
*pdp
, datalink_id_t linkid
,
3868 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
3871 uint64_t ifspeed
= 0;
3872 dladm_status_t status
;
3874 if ((status
= dladm_get_single_mac_stat(handle
, linkid
, "ifspeed",
3875 KSTAT_DATA_UINT64
, &ifspeed
)) != 0)
3878 if ((ifspeed
% 1000000) != 0) {
3879 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3880 "%llf", ifspeed
/ (float)1000000); /* Mbps */
3882 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
,
3883 "%llu", ifspeed
/ 1000000); /* Mbps */
3886 *perm_flags
= MAC_PROP_PERM_READ
;
3887 return (DLADM_STATUS_OK
);
3891 static dladm_status_t
3892 get_link_state(dladm_handle_t handle
, prop_desc_t
*pdp
,
3893 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3894 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3896 link_state_t link_state
;
3897 dladm_status_t status
;
3899 status
= dladm_get_state(handle
, linkid
, &link_state
);
3900 if (status
!= DLADM_STATUS_OK
)
3903 switch (link_state
) {
3905 (void) strcpy(*prop_val
, "up");
3907 case LINK_STATE_DOWN
:
3908 (void) strcpy(*prop_val
, "down");
3911 (void) strcpy(*prop_val
, "unknown");
3915 *perm_flags
= MAC_PROP_PERM_READ
;
3916 return (DLADM_STATUS_OK
);
3920 static dladm_status_t
3921 get_binary(dladm_handle_t handle
, prop_desc_t
*pdp
,
3922 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3923 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3925 dladm_status_t status
;
3928 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3929 perm_flags
, &v
, sizeof (v
));
3930 if (status
!= DLADM_STATUS_OK
)
3933 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%d", (uint_t
)(v
> 0));
3935 return (DLADM_STATUS_OK
);
3939 static dladm_status_t
3940 get_uint32(dladm_handle_t handle
, prop_desc_t
*pdp
,
3941 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3942 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3944 dladm_status_t status
;
3947 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
3948 perm_flags
, &v
, sizeof (v
));
3949 if (status
!= DLADM_STATUS_OK
)
3952 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%ld", v
);
3954 return (DLADM_STATUS_OK
);
3958 static dladm_status_t
3959 get_range(dladm_handle_t handle
, prop_desc_t
*pdp
,
3960 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
3961 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
3963 dld_ioc_macprop_t
*dip
;
3964 dladm_status_t status
= DLADM_STATUS_OK
;
3967 mac_propval_range_t
*rangep
;
3970 * As caller we don't know number of value ranges, the driver
3971 * supports. To begin with we assume that number to be 1. If the
3972 * buffer size is insufficient, driver returns back with the
3973 * actual count of value ranges. See mac.h for more details.
3975 sz
= sizeof (mac_propval_range_t
);
3978 if ((dip
= i_dladm_buf_alloc_by_name(sz
, linkid
, pdp
->pd_name
, flags
,
3982 rangep
= (mac_propval_range_t
*)(void *)&dip
->pr_val
;
3983 rangep
->mpr_count
= rcount
;
3985 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
3986 if (status
!= DLADM_STATUS_OK
) {
3987 if (status
== DLADM_STATUS_TOOSMALL
) {
3990 if ((err
= i_dladm_range_size(rangep
, &sz
, &rcount
))
3995 status
= dladm_errno2status(err
);
4002 if (rangep
->mpr_count
== 0) {
4004 (void) snprintf(prop_val
[0], DLADM_PROP_VAL_MAX
, "--");
4008 switch (rangep
->mpr_type
) {
4009 case MAC_PROPVAL_UINT32
: {
4010 mac_propval_uint32_range_t
*ur
;
4011 uint_t count
= rangep
->mpr_count
, i
;
4013 ur
= &rangep
->mpr_range_uint32
[0];
4015 for (i
= 0; i
< count
; i
++, ur
++) {
4016 if (ur
->mpur_min
== ur
->mpur_max
) {
4017 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4018 "%ld", ur
->mpur_min
);
4020 (void) snprintf(prop_val
[i
], DLADM_PROP_VAL_MAX
,
4021 "%ld-%ld", ur
->mpur_min
, ur
->mpur_max
);
4028 status
= DLADM_STATUS_BADARG
;
4037 static dladm_status_t
4038 get_tagmode(dladm_handle_t handle
, prop_desc_t
*pdp
,
4039 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4040 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4042 link_tagmode_t mode
;
4043 dladm_status_t status
;
4045 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4046 perm_flags
, &mode
, sizeof (mode
));
4047 if (status
!= DLADM_STATUS_OK
)
4051 case LINK_TAGMODE_NORMAL
:
4052 (void) strlcpy(*prop_val
, "normal", DLADM_PROP_VAL_MAX
);
4054 case LINK_TAGMODE_VLANONLY
:
4055 (void) strlcpy(*prop_val
, "vlanonly", DLADM_PROP_VAL_MAX
);
4058 (void) strlcpy(*prop_val
, "unknown", DLADM_PROP_VAL_MAX
);
4061 return (DLADM_STATUS_OK
);
4065 static dladm_status_t
4066 get_flowctl(dladm_handle_t handle
, prop_desc_t
*pdp
,
4067 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4068 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4071 dladm_status_t status
;
4073 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4074 perm_flags
, &v
, sizeof (v
));
4075 if (status
!= DLADM_STATUS_OK
)
4079 case LINK_FLOWCTRL_NONE
:
4080 (void) sprintf(*prop_val
, "no");
4082 case LINK_FLOWCTRL_RX
:
4083 (void) sprintf(*prop_val
, "rx");
4085 case LINK_FLOWCTRL_TX
:
4086 (void) sprintf(*prop_val
, "tx");
4088 case LINK_FLOWCTRL_BI
:
4089 (void) sprintf(*prop_val
, "bi");
4093 return (DLADM_STATUS_OK
);
4098 static dladm_status_t
4099 i_dladm_set_private_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4100 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
)
4105 dld_ioc_macprop_t
*dip
= NULL
;
4108 dladm_status_t status
= DLADM_STATUS_OK
;
4110 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4111 (prop_val
!= NULL
&& val_cnt
== 0))
4112 return (DLADM_STATUS_BADARG
);
4113 p
= dladm_name2prop(prop_name
);
4114 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4115 return (DLADM_STATUS_BADARG
);
4117 if (!(flags
& DLADM_OPT_ACTIVE
))
4118 return (DLADM_STATUS_OK
);
4121 * private properties: all parsing is done in the kernel.
4122 * allocate a enough space for each property + its separator (',').
4124 for (i
= 0; i
< val_cnt
; i
++) {
4125 bufsize
+= strlen(prop_val
[i
]) + 1;
4128 if (prop_val
== NULL
) {
4130 * getting default value. so use more buffer space.
4132 bufsize
+= DLADM_PROP_BUF_CHUNK
;
4135 dip
= i_dladm_buf_alloc_by_name(bufsize
+ 1, linkid
, prop_name
,
4136 (prop_val
!= NULL
? 0 : DLD_PROP_DEFAULT
), &status
);
4140 dp
= (uchar_t
*)dip
->pr_val
;
4143 if (prop_val
== NULL
) {
4144 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4147 for (i
= 0; i
< val_cnt
; i
++) {
4150 plen
= strlen(prop_val
[i
]);
4151 bcopy(prop_val
[i
], dp
, plen
);
4154 * add a "," separator and update dp.
4156 if (i
!= (val_cnt
-1))
4161 if (status
== DLADM_STATUS_OK
)
4162 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4168 static dladm_status_t
4169 i_dladm_get_priv_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4170 const char *prop_name
, char **prop_val
, uint_t
*val_cnt
,
4171 dladm_prop_type_t type
, uint_t dld_flags
)
4173 dladm_status_t status
= DLADM_STATUS_OK
;
4174 dld_ioc_macprop_t
*dip
= NULL
;
4177 if ((prop_name
== NULL
&& prop_val
!= NULL
) ||
4178 (prop_val
!= NULL
&& val_cnt
== 0))
4179 return (DLADM_STATUS_BADARG
);
4181 p
= dladm_name2prop(prop_name
);
4182 if (p
->pp_id
!= MAC_PROP_PRIVATE
)
4183 return (DLADM_STATUS_BADARG
);
4186 * private properties: all parsing is done in the kernel.
4188 dip
= i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK
, linkid
, prop_name
,
4189 dld_flags
, &status
);
4193 if ((status
= i_dladm_macprop(handle
, dip
, B_FALSE
)) ==
4195 if (type
== DLADM_PROP_VAL_PERM
) {
4196 (void) dladm_perm2str(dip
->pr_perm_flags
, *prop_val
);
4197 } else if (type
== DLADM_PROP_VAL_MODIFIABLE
) {
4198 *prop_val
[0] = '\0';
4200 (void) strncpy(*prop_val
, dip
->pr_val
,
4201 DLADM_PROP_VAL_MAX
);
4204 } else if ((status
== DLADM_STATUS_NOTSUP
) &&
4205 (type
== DLADM_PROP_VAL_CURRENT
)) {
4206 status
= DLADM_STATUS_NOTFOUND
;
4213 static dladm_status_t
4214 i_dladm_getset_defval(dladm_handle_t handle
, prop_desc_t
*pdp
,
4215 datalink_id_t linkid
, datalink_media_t media
, uint_t flags
)
4217 dladm_status_t status
;
4218 char **prop_vals
= NULL
, *buf
;
4225 * Allocate buffer needed for prop_vals array. We can have at most
4226 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4227 * each entry has max size DLADM_PROP_VAL_MAX
4230 (sizeof (char *) + DLADM_PROP_VAL_MAX
) * DLADM_MAX_PROP_VALCNT
;
4231 buf
= malloc(bufsize
);
4232 prop_vals
= (char **)(void *)buf
;
4233 for (i
= 0; i
< DLADM_MAX_PROP_VALCNT
; i
++) {
4234 prop_vals
[i
] = buf
+
4235 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4236 i
* DLADM_PROP_VAL_MAX
;
4240 * For properties which have pdp->pd_defval.vd_name as a non-empty
4241 * string, the "" itself is used to reset the property (exceptions
4242 * are zone and autopush, which populate vdp->vd_val). So
4243 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4244 * down on the setprop using the global values in the table. For
4245 * other cases (vd_name is ""), doing reset-linkprop will cause
4246 * libdladm to do a getprop to find the default value and then do
4247 * a setprop to reset the value to default.
4249 status
= pdp
->pd_get(handle
, pdp
, linkid
, prop_vals
, &cnt
, media
,
4250 DLD_PROP_DEFAULT
, &perm_flags
);
4251 if (status
== DLADM_STATUS_OK
) {
4252 if (perm_flags
== MAC_PROP_PERM_RW
) {
4253 status
= i_dladm_set_single_prop(handle
, linkid
,
4254 pdp
->pd_class
, media
, pdp
, prop_vals
, cnt
, flags
);
4257 status
= DLADM_STATUS_NOTSUP
;
4264 static dladm_status_t
4265 get_stp(dladm_handle_t handle
, struct prop_desc
*pd
, datalink_id_t linkid
,
4266 char **prop_val
, uint_t
*val_cnt
, datalink_media_t media
, uint_t flags
,
4269 const bridge_public_prop_t
*bpp
;
4270 dladm_status_t retv
;
4274 return (DLADM_STATUS_NOTSUP
);
4275 *perm_flags
= MAC_PROP_PERM_RW
;
4277 for (bpp
= bridge_prop
; bpp
->bpp_name
!= NULL
; bpp
++)
4278 if (strcmp(bpp
->bpp_name
, pd
->pd_name
) == 0)
4280 retv
= dladm_bridge_get_port_cfg(handle
, linkid
, bpp
->bpp_code
, &val
);
4281 /* If the daemon isn't running, then return the persistent value */
4282 if (retv
== DLADM_STATUS_NOTFOUND
) {
4283 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4284 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4285 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4286 DLADM_PROP_VAL_MAX
);
4287 return (DLADM_STATUS_OK
);
4289 if (retv
!= DLADM_STATUS_OK
) {
4290 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4293 if (val
== pd
->pd_defval
.vd_val
&& pd
->pd_defval
.vd_name
[0] != '\0') {
4294 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4295 DLADM_PROP_VAL_MAX
);
4296 return (DLADM_STATUS_OK
);
4298 for (i
= 0; i
< pd
->pd_noptval
; i
++) {
4299 if (val
== pd
->pd_optval
[i
].vd_val
) {
4300 (void) strlcpy(*prop_val
, pd
->pd_optval
[i
].vd_name
,
4301 DLADM_PROP_VAL_MAX
);
4302 return (DLADM_STATUS_OK
);
4305 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", (unsigned)val
);
4306 return (DLADM_STATUS_OK
);
4310 static dladm_status_t
4311 set_stp_prop(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4312 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4315 * Special case for mcheck: the daemon resets the value to zero, and we
4316 * don't want the daemon to refresh itself; it leads to deadlock.
4318 if (flags
& DLADM_OPT_NOREFRESH
)
4319 return (DLADM_STATUS_OK
);
4321 /* Tell the running daemon, if any */
4322 return (dladm_bridge_refresh(handle
, linkid
));
4326 * This is used only for stp_priority, stp_cost, and stp_mcheck.
4329 static dladm_status_t
4330 check_stp_prop(dladm_handle_t handle
, struct prop_desc
*pd
,
4331 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4332 val_desc_t
**vdpp
, datalink_media_t media
)
4336 uint_t val_cnt
= *val_cntp
;
4337 val_desc_t
*vdp
= *vdpp
;
4340 return (DLADM_STATUS_BADVALCNT
);
4342 if (prop_val
== NULL
) {
4345 /* Only stp_priority and stp_cost use this function */
4346 iscost
= strcmp(pd
->pd_name
, "stp_cost") == 0;
4348 if (iscost
&& strcmp(prop_val
[0], "auto") == 0) {
4349 /* Illegal value 0 is allowed to mean "automatic" */
4353 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4354 if (errno
!= 0 || *cp
!= '\0')
4355 return (DLADM_STATUS_BADVAL
);
4360 return (vdp
->vd_val
> 65535 ? DLADM_STATUS_BADVAL
:
4363 if (vdp
->vd_val
> 255)
4364 return (DLADM_STATUS_BADVAL
);
4366 * If the user is setting stp_mcheck non-zero, then (per the
4367 * IEEE management standards and UNH testing) we need to check
4368 * whether this link is part of a bridge that is running RSTP.
4369 * If it's not, then setting the flag is an error. Note that
4370 * errors are intentionally discarded here; it's the value
4371 * that's the problem -- it's not a bad value, merely one that
4372 * can't be used now.
4374 if (strcmp(pd
->pd_name
, "stp_mcheck") == 0 &&
4376 char bridge
[MAXLINKNAMELEN
];
4378 dladm_bridge_prot_t brprot
;
4380 if (dladm_bridge_getlink(handle
, linkid
, bridge
,
4381 sizeof (bridge
)) != DLADM_STATUS_OK
||
4382 dladm_bridge_get_properties(bridge
, &cfg
,
4383 &brprot
) != DLADM_STATUS_OK
)
4384 return (DLADM_STATUS_FAILED
);
4385 if (cfg
.force_version
<= 1)
4386 return (DLADM_STATUS_FAILED
);
4388 return (DLADM_STATUS_OK
);
4393 static dladm_status_t
4394 get_bridge_forward(dladm_handle_t handle
, struct prop_desc
*pd
,
4395 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4396 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4398 dladm_status_t retv
;
4402 return (DLADM_STATUS_NOTSUP
);
4403 *perm_flags
= MAC_PROP_PERM_RW
;
4405 retv
= dladm_bridge_get_forwarding(handle
, linkid
, &val
);
4406 if (retv
== DLADM_STATUS_NOTFOUND
) {
4407 if (i_dladm_get_linkprop_db(handle
, linkid
, pd
->pd_name
,
4408 prop_val
, val_cnt
) != DLADM_STATUS_OK
)
4409 (void) strlcpy(*prop_val
, pd
->pd_defval
.vd_name
,
4410 DLADM_PROP_VAL_MAX
);
4411 return (DLADM_STATUS_OK
);
4413 if (retv
== DLADM_STATUS_OK
)
4414 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", val
);
4416 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4421 static dladm_status_t
4422 set_bridge_forward(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4423 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4425 /* Tell the running daemon, if any */
4426 return (dladm_bridge_refresh(handle
, linkid
));
4430 static dladm_status_t
4431 get_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4432 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4433 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4435 dladm_status_t status
;
4436 dld_ioc_macprop_t
*dip
;
4440 return (DLADM_STATUS_NOTSUP
);
4441 *perm_flags
= MAC_PROP_PERM_RW
;
4443 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4447 status
= i_dladm_macprop(handle
, dip
, B_FALSE
);
4448 if (status
== DLADM_STATUS_OK
) {
4449 (void) memcpy(&pvid
, dip
->pr_val
, sizeof (pvid
));
4450 (void) snprintf(*prop_val
, DLADM_PROP_VAL_MAX
, "%u", pvid
);
4452 (void) strlcpy(*prop_val
, "?", DLADM_PROP_VAL_MAX
);
4459 static dladm_status_t
4460 set_bridge_pvid(dladm_handle_t handle
, prop_desc_t
*pd
, datalink_id_t linkid
,
4461 val_desc_t
*vdp
, uint_t val_cnt
, uint_t flags
, datalink_media_t media
)
4463 dladm_status_t status
;
4464 dld_ioc_macprop_t
*dip
;
4467 dip
= i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid
, MAC_PROP_PVID
,
4472 (void) memcpy(dip
->pr_val
, &pvid
, sizeof (pvid
));
4473 status
= i_dladm_macprop(handle
, dip
, B_TRUE
);
4475 if (status
!= DLADM_STATUS_OK
)
4478 /* Tell the running daemon, if any */
4479 return (dladm_bridge_refresh(handle
, linkid
));
4483 static dladm_status_t
4484 check_bridge_pvid(dladm_handle_t handle
, struct prop_desc
*pd
,
4485 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cntp
, uint_t flags
,
4486 val_desc_t
**vdpp
, datalink_media_t media
)
4489 uint_t val_cnt
= *val_cntp
;
4490 val_desc_t
*vdp
= *vdpp
;
4493 return (DLADM_STATUS_BADVALCNT
);
4495 if (prop_val
== NULL
) {
4499 vdp
->vd_val
= strtoul(prop_val
[0], &cp
, 0);
4500 if (errno
!= 0 || *cp
!= '\0')
4501 return (DLADM_STATUS_BADVAL
);
4504 return (vdp
->vd_val
> VLAN_ID_MAX
? DLADM_STATUS_BADVAL
:
4509 i_dladm_wlan_param(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
4510 mac_prop_id_t cmd
, size_t len
, boolean_t set
)
4513 dladm_status_t status
;
4515 dld_ioc_macprop_t
*dip
;
4518 if ((status
= dladm_datalink_id2info(handle
, linkid
, &flags
, NULL
,
4519 &media
, NULL
, 0)) != DLADM_STATUS_OK
) {
4523 if (media
!= DL_WIFI
)
4524 return (DLADM_STATUS_BADARG
);
4526 if (!(flags
& DLADM_OPT_ACTIVE
))
4527 return (DLADM_STATUS_TEMPONLY
);
4529 if (len
== (MAX_BUF_LEN
- WIFI_BUF_OFFSET
))
4530 len
= MAX_BUF_LEN
- sizeof (dld_ioc_macprop_t
) - 1;
4532 dip
= i_dladm_buf_alloc_by_id(len
, linkid
, cmd
, 0, &status
);
4534 return (DLADM_STATUS_NOMEM
);
4536 dp
= (uchar_t
*)dip
->pr_val
;
4538 (void) memcpy(dp
, buf
, len
);
4540 status
= i_dladm_macprop(handle
, dip
, set
);
4541 if (status
== DLADM_STATUS_OK
) {
4543 (void) memcpy(buf
, dp
, len
);
4551 dladm_parse_link_props(char *str
, dladm_arg_list_t
**listp
, boolean_t novalues
)
4553 return (dladm_parse_args(str
, listp
, novalues
));
4557 * Retrieve the one link property from the database
4561 i_dladm_get_one_prop(dladm_handle_t handle
, datalink_id_t linkid
,
4562 const char *prop_name
, void *arg
)
4564 dladm_arg_list_t
*proplist
= arg
;
4565 dladm_arg_info_t
*aip
= NULL
;
4567 aip
= &proplist
->al_info
[proplist
->al_count
];
4569 * it is fine to point to prop_name since prop_name points to the
4570 * prop_table[n].pd_name.
4572 aip
->ai_name
= prop_name
;
4574 (void) dladm_get_linkprop(handle
, linkid
, DLADM_PROP_VAL_PERSISTENT
,
4575 prop_name
, aip
->ai_val
, &aip
->ai_count
);
4577 if (aip
->ai_count
!= 0)
4578 proplist
->al_count
++;
4580 return (DLADM_WALK_CONTINUE
);
4585 * Retrieve all link properties for a link from the database and
4586 * return a property list.
4589 dladm_link_get_proplist(dladm_handle_t handle
, datalink_id_t linkid
,
4590 dladm_arg_list_t
**listp
)
4592 dladm_arg_list_t
*list
;
4593 dladm_status_t status
= DLADM_STATUS_OK
;
4595 list
= calloc(1, sizeof (dladm_arg_list_t
));
4597 return (dladm_errno2status(errno
));
4599 status
= dladm_walk_linkprop(handle
, linkid
, list
,
4600 i_dladm_get_one_prop
);
4607 * Retrieve the named property from a proplist, check the value and
4608 * convert to a kernel structure.
4610 static dladm_status_t
4611 i_dladm_link_proplist_extract_one(dladm_handle_t handle
,
4612 dladm_arg_list_t
*proplist
, const char *name
, uint_t flags
, void *arg
)
4614 dladm_status_t status
;
4615 dladm_arg_info_t
*aip
= NULL
;
4618 /* Find named property in proplist */
4619 for (i
= 0; i
< proplist
->al_count
; i
++) {
4620 aip
= &proplist
->al_info
[i
];
4621 if (strcasecmp(aip
->ai_name
, name
) == 0)
4625 /* Property not in list */
4626 if (i
== proplist
->al_count
)
4627 return (DLADM_STATUS_OK
);
4629 for (i
= 0; i
< DLADM_MAX_PROPS
; i
++) {
4630 prop_desc_t
*pdp
= &prop_table
[i
];
4633 vdp
= malloc(sizeof (val_desc_t
) * aip
->ai_count
);
4635 return (DLADM_STATUS_NOMEM
);
4637 if (strcasecmp(aip
->ai_name
, pdp
->pd_name
) != 0)
4640 if (aip
->ai_val
== NULL
)
4641 return (DLADM_STATUS_BADARG
);
4643 /* Check property value */
4644 if (pdp
->pd_check
!= NULL
) {
4645 status
= pdp
->pd_check(handle
, pdp
, 0, aip
->ai_val
,
4646 &(aip
->ai_count
), flags
, &vdp
, 0);
4648 status
= DLADM_STATUS_BADARG
;
4651 if (status
!= DLADM_STATUS_OK
)
4654 for (j
= 0; j
< DLADM_MAX_RSRC_PROP
; j
++) {
4655 resource_prop_t
*rpp
= &rsrc_prop_table
[j
];
4657 if (strcasecmp(aip
->ai_name
, rpp
->rp_name
) != 0)
4660 /* Extract kernel structure */
4661 if (rpp
->rp_extract
!= NULL
) {
4662 status
= rpp
->rp_extract(vdp
,
4663 aip
->ai_count
, arg
);
4665 status
= DLADM_STATUS_BADARG
;
4670 if (status
!= DLADM_STATUS_OK
)
4679 * Extract properties from a proplist and convert to mac_resource_props_t.
4682 dladm_link_proplist_extract(dladm_handle_t handle
, dladm_arg_list_t
*proplist
,
4683 mac_resource_props_t
*mrp
, uint_t flags
)
4685 dladm_status_t status
;
4688 for (i
= 0; i
< DLADM_MAX_RSRC_PROP
; i
++) {
4689 status
= i_dladm_link_proplist_extract_one(handle
,
4690 proplist
, rsrc_prop_table
[i
].rp_name
, flags
, mrp
);
4691 if (status
!= DLADM_STATUS_OK
)
4698 dladm_perm2str(uint_t perm
, char *buf
)
4700 (void) snprintf(buf
, DLADM_STRSIZE
, "%c%c",
4701 ((perm
& MAC_PROP_PERM_READ
) != 0) ? 'r' : '-',
4702 ((perm
& MAC_PROP_PERM_WRITE
) != 0) ? 'w' : '-');
4707 dladm_get_state(dladm_handle_t handle
, datalink_id_t linkid
,
4708 link_state_t
*state
)
4712 return (i_dladm_get_public_prop(handle
, linkid
, "state", 0,
4713 &perms
, state
, sizeof (*state
)));
4717 dladm_attr_is_linkprop(const char *name
)
4719 /* non-property attribute names */
4720 const char *nonprop
[] = {
4721 /* dlmgmtd core attributes */
4729 /* other attributes for vlan, aggr, etc */
4732 boolean_t is_nonprop
= B_FALSE
;
4735 for (i
= 0; i
< sizeof (nonprop
) / sizeof (nonprop
[0]); i
++) {
4736 if (strcmp(name
, nonprop
[i
]) == 0) {
4737 is_nonprop
= B_TRUE
;
4742 return (!is_nonprop
);
4746 dladm_linkprop_is_set(dladm_handle_t handle
, datalink_id_t linkid
,
4747 dladm_prop_type_t type
, const char *prop_name
, boolean_t
*is_set
)
4749 char *buf
, **propvals
;
4750 uint_t valcnt
= DLADM_MAX_PROP_VALCNT
;
4752 dladm_status_t status
= DLADM_STATUS_OK
;
4757 bufsize
= (sizeof (char *) + DLADM_PROP_VAL_MAX
) *
4758 DLADM_MAX_PROP_VALCNT
;
4759 if ((buf
= calloc(1, bufsize
)) == NULL
)
4760 return (DLADM_STATUS_NOMEM
);
4762 propvals
= (char **)(void *)buf
;
4763 for (i
= 0; i
< valcnt
; i
++) {
4765 sizeof (char *) * DLADM_MAX_PROP_VALCNT
+
4766 i
* DLADM_PROP_VAL_MAX
;
4769 if (dladm_get_linkprop(handle
, linkid
, type
, prop_name
, propvals
,
4770 &valcnt
) != DLADM_STATUS_OK
) {
4775 * valcnt is always set to 1 by get_pool(), hence we need to check
4776 * for a non-null string to see if it is set. For protection,
4777 * secondary-macs and allowed-ips, we can check either the *propval
4780 if ((strcmp(prop_name
, "pool") == 0 ||
4781 strcmp(prop_name
, "protection") == 0 ||
4782 strcmp(prop_name
, "secondary-macs") == 0 ||
4783 strcmp(prop_name
, "allowed-ips") == 0) &&
4784 (strlen(*propvals
) != 0)) {
4786 } else if ((strcmp(prop_name
, "cpus") == 0) && (valcnt
!= 0)) {
4788 } else if ((strcmp(prop_name
, "_softmac") == 0) && (valcnt
!= 0) &&
4789 (strcmp(propvals
[0], "true") == 0)) {
4800 static dladm_status_t
4801 get_linkmode_prop(dladm_handle_t handle
, prop_desc_t
*pdp
,
4802 datalink_id_t linkid
, char **prop_val
, uint_t
*val_cnt
,
4803 datalink_media_t media
, uint_t flags
, uint_t
*perm_flags
)
4807 dladm_status_t status
;
4809 status
= i_dladm_get_public_prop(handle
, linkid
, pdp
->pd_name
, flags
,
4810 perm_flags
, &v
, sizeof (v
));
4811 if (status
!= DLADM_STATUS_OK
)
4815 case DLADM_PART_CM_MODE
:
4818 case DLADM_PART_UD_MODE
:
4825 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s", s
);
4828 return (DLADM_STATUS_OK
);