Print this page
OS-406
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libdladm/common/linkprop.c
+++ new/usr/src/lib/libdladm/common/linkprop.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <stdlib.h>
27 27 #include <string.h>
28 28 #include <strings.h>
29 29 #include <errno.h>
30 30 #include <ctype.h>
31 31 #include <stddef.h>
32 32 #include <sys/types.h>
33 33 #include <sys/stat.h>
34 34 #include <sys/dld.h>
35 35 #include <sys/zone.h>
36 36 #include <fcntl.h>
37 37 #include <unistd.h>
38 38 #include <libdevinfo.h>
39 39 #include <zone.h>
40 40 #include <libdllink.h>
41 41 #include <libdladm_impl.h>
42 42 #include <libdlwlan_impl.h>
43 43 #include <libdlwlan.h>
44 44 #include <libdlvlan.h>
45 45 #include <libdlvnic.h>
46 46 #include <libdlib.h>
47 47 #include <libintl.h>
48 48 #include <dlfcn.h>
49 49 #include <link.h>
50 50 #include <inet/wifi_ioctl.h>
51 51 #include <libdladm.h>
52 52 #include <libdlstat.h>
53 53 #include <sys/param.h>
54 54 #include <sys/debug.h>
55 55 #include <sys/dld.h>
56 56 #include <inttypes.h>
57 57 #include <sys/ethernet.h>
58 58 #include <inet/iptun.h>
59 59 #include <net/wpa.h>
60 60 #include <sys/sysmacros.h>
61 61 #include <sys/vlan.h>
62 62 #include <libdlbridge.h>
63 63 #include <stp_in.h>
64 64 #include <netinet/dhcp.h>
65 65 #include <netinet/dhcp6.h>
66 66 #include <net/if_types.h>
67 67 #include <libinetutil.h>
68 68 #include <pool.h>
69 69 #include <libdlaggr.h>
70 70
71 71 /*
72 72 * The linkprop get() callback.
73 73 * - pd: pointer to the prop_desc_t
74 74 * - propstrp: a property string array to keep the returned property.
75 75 * Caller allocated.
76 76 * - cntp: number of returned properties.
77 77 * Caller also uses it to indicate how many it expects.
78 78 */
79 79 struct prop_desc;
80 80 typedef struct prop_desc prop_desc_t;
81 81
82 82 typedef dladm_status_t pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
83 83 datalink_id_t, char **propstp, uint_t *cntp,
84 84 datalink_media_t, uint_t, uint_t *);
85 85
86 86 /*
87 87 * The linkprop set() callback.
88 88 * - propval: a val_desc_t array which keeps the property values to be set.
89 89 * - cnt: number of properties to be set.
90 90 * - flags: additional flags passed down the system call.
91 91 *
92 92 * pd_set takes val_desc_t given by pd_check(), translates it into
93 93 * a format suitable for kernel consumption. This may require allocation
94 94 * of ioctl buffers etc. pd_set() may call another common routine (used
95 95 * by all other pd_sets) which invokes the ioctl.
96 96 */
97 97 typedef dladm_status_t pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
98 98 val_desc_t *propval, uint_t cnt, uint_t flags,
99 99 datalink_media_t);
100 100
101 101 /*
102 102 * The linkprop check() callback.
103 103 * - propstrp: property string array which keeps the property to be checked.
104 104 * - cnt: number of properties.
105 105 * - propval: return value; the property values of the given property strings.
106 106 *
107 107 * pd_check checks that the input values are valid. It does so by
108 108 * iteraring through the pd_modval list for the property. If
109 109 * the modifiable values cannot be expressed as a list, a pd_check
110 110 * specific to this property can be used. If the input values are
111 111 * verified to be valid, pd_check allocates a val_desc_t and fills it
112 112 * with either a val_desc_t found on the pd_modval list or something
113 113 * generated on the fly.
114 114 */
115 115 typedef dladm_status_t pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
116 116 datalink_id_t, char **propstrp, uint_t *cnt,
117 117 uint_t flags, val_desc_t **propval,
118 118 datalink_media_t);
119 119
120 120 typedef struct link_attr_s {
121 121 mac_prop_id_t pp_id;
122 122 size_t pp_valsize;
123 123 char *pp_name;
124 124 } link_attr_t;
125 125
126 126 typedef struct dladm_linkprop_args_s {
127 127 dladm_status_t dla_status;
128 128 uint_t dla_flags;
129 129 } dladm_linkprop_args_t;
130 130
131 131 static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
132 132 const char *, uint_t, dladm_status_t *);
133 133 static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
134 134 mac_prop_id_t, uint_t, dladm_status_t *);
135 135 static dladm_status_t i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
136 136 char *, uint_t, uint_t *, void *, size_t);
137 137
138 138 static dladm_status_t i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
139 139 const char *, char **, uint_t, uint_t);
140 140 static dladm_status_t i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
141 141 const char *, char **, uint_t *, dladm_prop_type_t,
142 142 uint_t);
143 143 static dladm_status_t i_dladm_macprop(dladm_handle_t, void *, boolean_t);
144 144 static const char *dladm_perm2str(uint_t, char *);
145 145 static link_attr_t *dladm_name2prop(const char *);
146 146 static link_attr_t *dladm_id2prop(mac_prop_id_t);
147 147
148 148 static pd_getf_t get_zone, get_autopush, get_rate_mod, get_rate,
149 149 get_speed, get_channel, get_powermode, get_radio,
150 150 get_duplex, get_link_state, get_binary, get_uint32,
151 151 get_flowctl, get_maxbw, get_cpus, get_priority,
152 152 get_tagmode, get_range, get_stp, get_bridge_forward,
153 153 get_bridge_pvid, get_protection, get_rxrings,
154 154 get_txrings, get_cntavail, get_secondary_macs,
155 155 get_allowedips, get_allowedcids, get_pool,
156 156 get_rings_range, get_linkmode_prop;
157 157
158 158 static pd_setf_t set_zone, set_rate, set_powermode, set_radio,
159 159 set_public_prop, set_resource, set_stp_prop,
160 160 set_bridge_forward, set_bridge_pvid, set_secondary_macs;
161 161
162 162 static pd_checkf_t check_zone, check_autopush, check_rate, check_hoplimit,
163 163 check_encaplim, check_uint32, check_maxbw, check_cpus,
164 164 check_stp_prop, check_bridge_pvid, check_allowedips,
165 165 check_allowedcids, check_secondary_macs, check_rings,
166 166 check_pool, check_prop;
167 167
168 168 struct prop_desc {
169 169 /*
170 170 * link property name
171 171 */
172 172 char *pd_name;
173 173
174 174 /*
175 175 * default property value, can be set to { "", NULL }
176 176 */
177 177 val_desc_t pd_defval;
178 178
179 179 /*
180 180 * list of optional property values, can be NULL.
181 181 *
182 182 * This is set to non-NULL if there is a list of possible property
183 183 * values. pd_optval would point to the array of possible values.
184 184 */
185 185 val_desc_t *pd_optval;
186 186
187 187 /*
188 188 * count of the above optional property values. 0 if pd_optval is NULL.
189 189 */
190 190 uint_t pd_noptval;
191 191
192 192 /*
193 193 * callback to set link property; set to NULL if this property is
194 194 * read-only and may be called before or after permanent update; see
195 195 * flags.
196 196 */
197 197 pd_setf_t *pd_set;
198 198
199 199 /*
200 200 * callback to get modifiable link property
201 201 */
202 202 pd_getf_t *pd_getmod;
203 203
204 204 /*
205 205 * callback to get current link property
206 206 */
207 207 pd_getf_t *pd_get;
208 208
209 209 /*
210 210 * callback to validate link property value, set to NULL if pd_optval
211 211 * is not NULL. In that case, validate the value by comparing it with
212 212 * the pd_optval. Return a val_desc_t array pointer if the value is
213 213 * valid.
214 214 */
215 215 pd_checkf_t *pd_check;
216 216
217 217 uint_t pd_flags;
218 218 #define PD_TEMPONLY 0x1 /* property is temporary only */
219 219 #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */
220 220 #define PD_AFTER_PERM 0x4 /* pd_set after db update; no temporary */
221 221 /*
222 222 * indicate link classes this property applies to.
223 223 */
224 224 datalink_class_t pd_class;
225 225
226 226 /*
227 227 * indicate link media type this property applies to.
228 228 */
229 229 datalink_media_t pd_dmedia;
230 230 };
231 231
232 232 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1
233 233
234 234 /*
235 235 * Supported link properties enumerated in the prop_table[] array are
236 236 * computed using the callback functions in that array. To compute the
237 237 * property value, multiple distinct system calls may be needed (e.g.,
238 238 * for wifi speed, we need to issue system calls to get desired/supported
239 239 * rates). The link_attr[] table enumerates the interfaces to the kernel,
240 240 * and the type/size of the data passed in the user-kernel interface.
241 241 */
242 242 static link_attr_t link_attr[] = {
243 243 { MAC_PROP_DUPLEX, sizeof (link_duplex_t), "duplex"},
244 244
245 245 { MAC_PROP_SPEED, sizeof (uint64_t), "speed"},
246 246
247 247 { MAC_PROP_STATUS, sizeof (link_state_t), "state"},
248 248
249 249 { MAC_PROP_AUTONEG, sizeof (uint8_t), "adv_autoneg_cap"},
250 250
251 251 { MAC_PROP_MTU, sizeof (uint32_t), "mtu"},
252 252
253 253 { MAC_PROP_FLOWCTRL, sizeof (link_flowctrl_t), "flowctrl"},
254 254
255 255 { MAC_PROP_ZONE, sizeof (dld_ioc_zid_t), "zone"},
256 256
257 257 { MAC_PROP_AUTOPUSH, sizeof (struct dlautopush), "autopush"},
258 258
259 259 { MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t), "adv_10gfdx_cap"},
260 260
261 261 { MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t), "en_10gfdx_cap"},
262 262
263 263 { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), "adv_1000fdx_cap"},
264 264
265 265 { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), "en_1000fdx_cap"},
266 266
267 267 { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), "adv_1000hdx_cap"},
268 268
269 269 { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), "en_1000hdx_cap"},
270 270
271 271 { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), "adv_100fdx_cap"},
272 272
273 273 { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), "en_100fdx_cap"},
274 274
275 275 { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), "adv_100hdx_cap"},
276 276
277 277 { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), "en_100hdx_cap"},
278 278
279 279 { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), "adv_10fdx_cap"},
280 280
281 281 { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), "en_10fdx_cap"},
282 282
283 283 { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), "adv_10hdx_cap"},
284 284
285 285 { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), "en_10hdx_cap"},
286 286
287 287 { MAC_PROP_WL_ESSID, sizeof (wl_linkstatus_t), "essid"},
288 288
289 289 { MAC_PROP_WL_BSSID, sizeof (wl_bssid_t), "bssid"},
290 290
291 291 { MAC_PROP_WL_BSSTYPE, sizeof (wl_bss_type_t), "bsstype"},
292 292
293 293 { MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
294 294
295 295 /* wl_rates_t has variable length */
296 296 { MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
297 297
298 298 /* wl_rates_t has variable length */
299 299 { MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
300 300
301 301 { MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
302 302
303 303 { MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
304 304
305 305 { MAC_PROP_WL_RSSI, sizeof (wl_rssi_t), "signal"},
306 306
307 307 { MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
308 308
309 309 { MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
310 310
311 311 { MAC_PROP_WL_WPA, sizeof (wl_wpa_t), "wpa"},
312 312
313 313 /* wl_wpa_ess_t has variable length */
314 314 { MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
315 315
316 316 { MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
317 317
318 318 { MAC_PROP_WL_RADIO, sizeof (dladm_wlan_radio_t), "wl_radio"},
319 319
320 320 { MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t), "wl_ess_list"},
321 321
322 322 { MAC_PROP_WL_KEY_TAB, sizeof (wl_wep_key_tab_t), "wl_wep_key"},
323 323
324 324 { MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
325 325
326 326 /* wl_wpa_ie_t has variable length */
327 327 { MAC_PROP_WL_SETOPTIE, sizeof (wl_wpa_ie_t), "set_ie"},
328 328
329 329 { MAC_PROP_WL_DELKEY, sizeof (wl_del_key_t), "wpa_del_key"},
330 330
331 331 { MAC_PROP_WL_KEY, sizeof (wl_key_t), "wl_key"},
332 332
333 333 { MAC_PROP_WL_MLME, sizeof (wl_mlme_t), "mlme"},
334 334
335 335 { MAC_PROP_TAGMODE, sizeof (link_tagmode_t), "tagmode"},
336 336
337 337 { MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t), "hoplimit"},
338 338
339 339 { MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t), "encaplimit"},
340 340
341 341 { MAC_PROP_PVID, sizeof (uint16_t), "default_tag"},
342 342
343 343 { MAC_PROP_LLIMIT, sizeof (uint32_t), "learn_limit"},
344 344
345 345 { MAC_PROP_LDECAY, sizeof (uint32_t), "learn_decay"},
346 346
347 347 { MAC_PROP_RESOURCE, sizeof (mac_resource_props_t), "resource"},
348 348
349 349 { MAC_PROP_RESOURCE_EFF, sizeof (mac_resource_props_t),
350 350 "resource-effective"},
351 351
352 352 { MAC_PROP_RXRINGSRANGE, sizeof (mac_propval_range_t), "rxrings"},
353 353
354 354 { MAC_PROP_TXRINGSRANGE, sizeof (mac_propval_range_t), "txrings"},
355 355
356 356 { MAC_PROP_MAX_TX_RINGS_AVAIL, sizeof (uint_t),
357 357 "txrings-available"},
358 358
359 359 { MAC_PROP_MAX_RX_RINGS_AVAIL, sizeof (uint_t),
360 360 "rxrings-available"},
361 361
362 362 { MAC_PROP_MAX_RXHWCLNT_AVAIL, sizeof (uint_t), "rxhwclnt-available"},
363 363
364 364 { MAC_PROP_MAX_TXHWCLNT_AVAIL, sizeof (uint_t), "txhwclnt-available"},
365 365
366 366 { MAC_PROP_IB_LINKMODE, sizeof (uint32_t), "linkmode"},
367 367
368 368 { MAC_PROP_SECONDARY_ADDRS, sizeof (mac_secondary_addr_t),
369 369 "secondary-macs"},
370 370
371 371 { MAC_PROP_PRIVATE, 0, "driver-private"}
372 372 };
373 373
374 374 typedef struct bridge_public_prop_s {
375 375 const char *bpp_name;
376 376 int bpp_code;
377 377 } bridge_public_prop_t;
378 378
379 379 static const bridge_public_prop_t bridge_prop[] = {
380 380 { "stp", PT_CFG_NON_STP },
381 381 { "stp_priority", PT_CFG_PRIO },
382 382 { "stp_cost", PT_CFG_COST },
383 383 { "stp_edge", PT_CFG_EDGE },
384 384 { "stp_p2p", PT_CFG_P2P },
385 385 { "stp_mcheck", PT_CFG_MCHECK },
386 386 { NULL, 0 }
387 387 };
388 388
389 389 static val_desc_t link_duplex_vals[] = {
390 390 { "half", LINK_DUPLEX_HALF },
391 391 { "full", LINK_DUPLEX_HALF }
392 392 };
393 393 static val_desc_t link_status_vals[] = {
394 394 { "up", LINK_STATE_UP },
395 395 { "down", LINK_STATE_DOWN }
396 396 };
397 397 static val_desc_t link_01_vals[] = {
398 398 { "1", 1 },
399 399 { "0", 0 }
400 400 };
401 401 static val_desc_t link_flow_vals[] = {
402 402 { "no", LINK_FLOWCTRL_NONE },
403 403 { "tx", LINK_FLOWCTRL_TX },
404 404 { "rx", LINK_FLOWCTRL_RX },
405 405 { "bi", LINK_FLOWCTRL_BI }
406 406 };
407 407 static val_desc_t link_priority_vals[] = {
408 408 { "low", MPL_LOW },
409 409 { "medium", MPL_MEDIUM },
410 410 { "high", MPL_HIGH }
411 411 };
412 412
413 413 static val_desc_t link_tagmode_vals[] = {
414 414 { "normal", LINK_TAGMODE_NORMAL },
415 415 { "vlanonly", LINK_TAGMODE_VLANONLY }
416 416 };
417 417
418 418 static val_desc_t link_protect_vals[] = {
419 419 { "mac-nospoof", MPT_MACNOSPOOF },
420 420 { "restricted", MPT_RESTRICTED },
421 421 { "ip-nospoof", MPT_IPNOSPOOF },
422 422 { "dhcp-nospoof", MPT_DHCPNOSPOOF },
423 423 };
424 424
425 425 static val_desc_t dladm_wlan_radio_vals[] = {
426 426 { "on", DLADM_WLAN_RADIO_ON },
427 427 { "off", DLADM_WLAN_RADIO_OFF }
428 428 };
429 429
430 430 static val_desc_t dladm_wlan_powermode_vals[] = {
431 431 { "off", DLADM_WLAN_PM_OFF },
432 432 { "fast", DLADM_WLAN_PM_FAST },
433 433 { "max", DLADM_WLAN_PM_MAX }
434 434 };
435 435
436 436 static val_desc_t stp_p2p_vals[] = {
437 437 { "true", P2P_FORCE_TRUE },
438 438 { "false", P2P_FORCE_FALSE },
439 439 { "auto", P2P_AUTO }
440 440 };
441 441
442 442 static val_desc_t dladm_part_linkmode_vals[] = {
443 443 { "cm", DLADM_PART_CM_MODE },
444 444 { "ud", DLADM_PART_UD_MODE },
445 445 };
446 446
447 447 #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
448 448 #define RESET_VAL ((uintptr_t)-1)
449 449 #define UNSPEC_VAL ((uintptr_t)-2)
450 450
451 451 /*
452 452 * For the default, if defaults are not defined for the property,
453 453 * pd_defval.vd_name should be null. If the driver has to be contacted for the
454 454 * value, vd_name should be the empty string (""). Otherwise, dladm will
455 455 * just print whatever is in the table.
456 456 */
457 457 static prop_desc_t prop_table[] = {
458 458 { "channel", { NULL, 0 },
459 459 NULL, 0, NULL, NULL,
460 460 get_channel, NULL, 0,
461 461 DATALINK_CLASS_PHYS, DL_WIFI },
462 462
463 463 { "powermode", { "off", DLADM_WLAN_PM_OFF },
464 464 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
465 465 set_powermode, NULL,
466 466 get_powermode, NULL, 0,
467 467 DATALINK_CLASS_PHYS, DL_WIFI },
468 468
469 469 { "radio", { "on", DLADM_WLAN_RADIO_ON },
470 470 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
471 471 set_radio, NULL,
472 472 get_radio, NULL, 0,
473 473 DATALINK_CLASS_PHYS, DL_WIFI },
474 474
475 475 { "linkmode", { "cm", DLADM_PART_CM_MODE },
476 476 dladm_part_linkmode_vals, VALCNT(dladm_part_linkmode_vals),
477 477 set_public_prop, NULL, get_linkmode_prop, NULL, 0,
478 478 DATALINK_CLASS_PART, DL_IB },
479 479
480 480 { "speed", { "", 0 }, NULL, 0,
481 481 set_rate, get_rate_mod,
482 482 get_rate, check_rate, 0,
483 483 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
484 484
485 485 { "autopush", { "", 0 }, NULL, 0,
486 486 set_public_prop, NULL,
487 487 get_autopush, check_autopush, PD_CHECK_ALLOC,
488 488 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
489 489
490 490 { "zone", { "", 0 }, NULL, 0,
491 491 set_zone, NULL,
492 492 get_zone, check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
493 493 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
494 494
495 495 { "duplex", { "", 0 },
496 496 link_duplex_vals, VALCNT(link_duplex_vals),
497 497 NULL, NULL, get_duplex, NULL,
498 498 0, DATALINK_CLASS_PHYS, DL_ETHER },
499 499
500 500 { "state", { "up", LINK_STATE_UP },
501 501 link_status_vals, VALCNT(link_status_vals),
502 502 NULL, NULL, get_link_state, NULL,
503 503 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
504 504
505 505 { "adv_autoneg_cap", { "", 0 },
506 506 link_01_vals, VALCNT(link_01_vals),
507 507 set_public_prop, NULL, get_binary, NULL,
508 508 0, DATALINK_CLASS_PHYS, DL_ETHER },
509 509
510 510 { "mtu", { "", 0 }, NULL, 0,
511 511 set_public_prop, get_range,
512 512 get_uint32, check_uint32, 0, DATALINK_CLASS_ALL,
513 513 DATALINK_ANY_MEDIATYPE },
514 514
515 515 { "flowctrl", { "", 0 },
516 516 link_flow_vals, VALCNT(link_flow_vals),
517 517 set_public_prop, NULL, get_flowctl, NULL,
518 518 0, DATALINK_CLASS_PHYS, DL_ETHER },
519 519
520 520 { "secondary-macs", { "--", 0 }, NULL, 0,
521 521 set_secondary_macs, NULL,
522 522 get_secondary_macs, check_secondary_macs, PD_CHECK_ALLOC,
523 523 DATALINK_CLASS_VNIC, DL_ETHER },
524 524
525 525 { "adv_10gfdx_cap", { "", 0 },
526 526 link_01_vals, VALCNT(link_01_vals),
527 527 NULL, NULL, get_binary, NULL,
528 528 0, DATALINK_CLASS_PHYS, DL_ETHER },
529 529
530 530 { "en_10gfdx_cap", { "", 0 },
531 531 link_01_vals, VALCNT(link_01_vals),
532 532 set_public_prop, NULL, get_binary, NULL,
533 533 0, DATALINK_CLASS_PHYS, DL_ETHER },
534 534
535 535 { "adv_1000fdx_cap", { "", 0 },
536 536 link_01_vals, VALCNT(link_01_vals),
537 537 NULL, NULL, get_binary, NULL,
538 538 0, DATALINK_CLASS_PHYS, DL_ETHER },
539 539
540 540 { "en_1000fdx_cap", { "", 0 },
541 541 link_01_vals, VALCNT(link_01_vals),
542 542 set_public_prop, NULL, get_binary, NULL,
543 543 0, DATALINK_CLASS_PHYS, DL_ETHER },
544 544
545 545 { "adv_1000hdx_cap", { "", 0 },
546 546 link_01_vals, VALCNT(link_01_vals),
547 547 NULL, NULL, get_binary, NULL,
548 548 0, DATALINK_CLASS_PHYS, DL_ETHER },
549 549
550 550 { "en_1000hdx_cap", { "", 0 },
551 551 link_01_vals, VALCNT(link_01_vals),
552 552 set_public_prop, NULL, get_binary, NULL,
553 553 0, DATALINK_CLASS_PHYS, DL_ETHER },
554 554
555 555 { "adv_100fdx_cap", { "", 0 },
556 556 link_01_vals, VALCNT(link_01_vals),
557 557 NULL, NULL, get_binary, NULL,
558 558 0, DATALINK_CLASS_PHYS, DL_ETHER },
559 559
560 560 { "en_100fdx_cap", { "", 0 },
561 561 link_01_vals, VALCNT(link_01_vals),
562 562 set_public_prop, NULL, get_binary, NULL,
563 563 0, DATALINK_CLASS_PHYS, DL_ETHER },
564 564
565 565 { "adv_100hdx_cap", { "", 0 },
566 566 link_01_vals, VALCNT(link_01_vals),
567 567 NULL, NULL, get_binary, NULL,
568 568 0, DATALINK_CLASS_PHYS, DL_ETHER },
569 569
570 570 { "en_100hdx_cap", { "", 0 },
571 571 link_01_vals, VALCNT(link_01_vals),
572 572 set_public_prop, NULL, get_binary, NULL,
573 573 0, DATALINK_CLASS_PHYS, DL_ETHER },
574 574
575 575 { "adv_10fdx_cap", { "", 0 },
576 576 link_01_vals, VALCNT(link_01_vals),
577 577 NULL, NULL, get_binary, NULL,
578 578 0, DATALINK_CLASS_PHYS, DL_ETHER },
579 579
580 580 { "en_10fdx_cap", { "", 0 },
581 581 link_01_vals, VALCNT(link_01_vals),
582 582 set_public_prop, NULL, get_binary, NULL,
583 583 0, DATALINK_CLASS_PHYS, DL_ETHER },
584 584
585 585 { "adv_10hdx_cap", { "", 0 },
586 586 link_01_vals, VALCNT(link_01_vals),
587 587 NULL, NULL, get_binary, NULL,
588 588 0, DATALINK_CLASS_PHYS, DL_ETHER },
589 589
590 590 { "en_10hdx_cap", { "", 0 },
591 591 link_01_vals, VALCNT(link_01_vals),
592 592 set_public_prop, NULL, get_binary, NULL,
593 593 0, DATALINK_CLASS_PHYS, DL_ETHER },
594 594
595 595 { "maxbw", { "--", RESET_VAL }, NULL, 0,
596 596 set_resource, NULL,
597 597 get_maxbw, check_maxbw, PD_CHECK_ALLOC,
598 598 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
599 599
600 600 { "cpus", { "--", RESET_VAL }, NULL, 0,
601 601 set_resource, NULL,
602 602 get_cpus, check_cpus, 0,
603 603 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
604 604
605 605 { "cpus-effective", { "--", 0 },
606 606 NULL, 0, NULL, NULL,
607 607 get_cpus, 0, 0,
608 608 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
609 609
610 610 { "pool", { "--", RESET_VAL }, NULL, 0,
611 611 set_resource, NULL,
612 612 get_pool, check_pool, 0,
613 613 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
614 614
615 615 { "pool-effective", { "--", 0 },
616 616 NULL, 0, NULL, NULL,
617 617 get_pool, 0, 0,
618 618 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
619 619
620 620 { "priority", { "high", MPL_RESET },
621 621 link_priority_vals, VALCNT(link_priority_vals), set_resource,
622 622 NULL, get_priority, check_prop, 0,
623 623 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
624 624
625 625 { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
626 626 link_tagmode_vals, VALCNT(link_tagmode_vals),
627 627 set_public_prop, NULL, get_tagmode,
628 628 NULL, 0,
629 629 DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
630 630 DL_ETHER },
631 631
632 632 { "hoplimit", { "", 0 }, NULL, 0,
633 633 set_public_prop, get_range, get_uint32,
634 634 check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
635 635
636 636 { "encaplimit", { "", 0 }, NULL, 0,
637 637 set_public_prop, get_range, get_uint32,
638 638 check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
639 639
640 640 { "forward", { "1", 1 },
641 641 link_01_vals, VALCNT(link_01_vals),
642 642 set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
643 643 DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
644 644
645 645 { "default_tag", { "1", 1 }, NULL, 0,
646 646 set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
647 647 0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
648 648 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
649 649
650 650 { "learn_limit", { "1000", 1000 }, NULL, 0,
651 651 set_public_prop, NULL, get_uint32,
652 652 check_uint32, 0,
653 653 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
654 654 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
655 655
656 656 { "learn_decay", { "200", 200 }, NULL, 0,
657 657 set_public_prop, NULL, get_uint32,
658 658 check_uint32, 0,
659 659 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
660 660 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
661 661
662 662 { "stp", { "1", 1 },
663 663 link_01_vals, VALCNT(link_01_vals),
664 664 set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
665 665 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
666 666 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
667 667
668 668 { "stp_priority", { "128", 128 }, NULL, 0,
669 669 set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
670 670 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
671 671 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
672 672
673 673 { "stp_cost", { "auto", 0 }, NULL, 0,
674 674 set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
675 675 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
676 676 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
677 677
678 678 { "stp_edge", { "1", 1 },
679 679 link_01_vals, VALCNT(link_01_vals),
680 680 set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
681 681 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
682 682 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
683 683
684 684 { "stp_p2p", { "auto", P2P_AUTO },
685 685 stp_p2p_vals, VALCNT(stp_p2p_vals),
686 686 set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
687 687 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
688 688 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
689 689
690 690 { "stp_mcheck", { "0", 0 },
691 691 link_01_vals, VALCNT(link_01_vals),
692 692 set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
693 693 DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
694 694 DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
695 695
696 696 { "protection", { "--", RESET_VAL },
697 697 link_protect_vals, VALCNT(link_protect_vals),
698 698 set_resource, NULL, get_protection, check_prop, 0,
699 699 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
700 700
701 701 { "allowed-ips", { "--", 0 },
702 702 NULL, 0, set_resource, NULL,
703 703 get_allowedips, check_allowedips, PD_CHECK_ALLOC,
704 704 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
705 705
706 706 { "allowed-dhcp-cids", { "--", 0 },
707 707 NULL, 0, set_resource, NULL,
708 708 get_allowedcids, check_allowedcids, PD_CHECK_ALLOC,
709 709 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
710 710
711 711 { "rxrings", { "--", RESET_VAL }, NULL, 0,
712 712 set_resource, get_rings_range, get_rxrings, check_rings, 0,
713 713 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
714 714
715 715 { "rxrings-effective", { "--", 0 },
716 716 NULL, 0, NULL, NULL,
717 717 get_rxrings, NULL, 0,
718 718 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
719 719
720 720 { "txrings", { "--", RESET_VAL }, NULL, 0,
721 721 set_resource, get_rings_range, get_txrings, check_rings, 0,
722 722 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
723 723
724 724 { "txrings-effective", { "--", 0 },
725 725 NULL, 0, NULL, NULL,
726 726 get_txrings, NULL, 0,
727 727 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
728 728
729 729 { "txrings-available", { "", 0 }, NULL, 0,
730 730 NULL, NULL, get_cntavail, NULL, 0,
731 731 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
732 732
733 733 { "rxrings-available", { "", 0 }, NULL, 0,
734 734 NULL, NULL, get_cntavail, NULL, 0,
735 735 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
736 736
737 737 { "rxhwclnt-available", { "", 0 }, NULL, 0,
738 738 NULL, NULL, get_cntavail, NULL, 0,
739 739 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
740 740
741 741 { "txhwclnt-available", { "", 0 }, NULL, 0,
742 742 NULL, NULL, get_cntavail, NULL, 0,
743 743 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
744 744
745 745 };
746 746
747 747 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
748 748
749 749 static resource_prop_t rsrc_prop_table[] = {
750 750 {"maxbw", extract_maxbw},
751 751 {"priority", extract_priority},
752 752 {"cpus", extract_cpus},
753 753 {"cpus-effective", extract_cpus},
754 754 {"pool", extract_pool},
755 755 {"pool-effective", extract_pool},
756 756 {"protection", extract_protection},
757 757 {"allowed-ips", extract_allowedips},
758 758 {"allowed-dhcp-cids", extract_allowedcids},
759 759 {"rxrings", extract_rxrings},
760 760 {"rxrings-effective", extract_rxrings},
761 761 {"txrings", extract_txrings},
762 762 {"txrings-effective", extract_txrings}
763 763 };
764 764 #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
765 765 sizeof (resource_prop_t))
766 766
767 767 /*
768 768 * when retrieving private properties, we pass down a buffer with
769 769 * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
770 770 */
771 771 #define DLADM_PROP_BUF_CHUNK 1024
772 772
773 773 static dladm_status_t i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
774 774 const char *, char **, uint_t);
775 775 static dladm_status_t i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
776 776 const char *, char **, uint_t *);
777 777 static dladm_status_t i_dladm_walk_linkprop_priv_db(dladm_handle_t,
778 778 datalink_id_t, void *, int (*)(dladm_handle_t,
779 779 datalink_id_t, const char *, void *));
780 780 static dladm_status_t i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
781 781 datalink_class_t, uint32_t, prop_desc_t *, char **,
782 782 uint_t, uint_t);
783 783 static dladm_status_t i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
784 784 const char *, char **, uint_t, uint_t);
785 785 static dladm_status_t i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
786 786 datalink_id_t, datalink_media_t, uint_t);
787 787
788 788 /*
789 789 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
790 790 * rates to be retrieved. However, we cannot increase it at this
791 791 * time because it will break binary compatibility with unbundled
792 792 * WiFi drivers and utilities. So for now we define an additional
793 793 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
794 794 */
795 795 #define MAX_SUPPORT_RATES 64
796 796
797 797 #define AP_ANCHOR "[anchor]"
798 798 #define AP_DELIMITER '.'
799 799
800 800 /* ARGSUSED */
801 801 static dladm_status_t
802 802 check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
803 803 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
804 804 datalink_media_t media)
805 805 {
806 806 int i, j;
807 807 uint_t val_cnt = *val_cntp;
808 808 val_desc_t *vdp = *vdpp;
809 809
810 810 for (j = 0; j < val_cnt; j++) {
811 811 for (i = 0; i < pdp->pd_noptval; i++) {
812 812 if (strcasecmp(prop_val[j],
813 813 pdp->pd_optval[i].vd_name) == 0) {
814 814 break;
815 815 }
816 816 }
817 817 if (i == pdp->pd_noptval)
818 818 return (DLADM_STATUS_BADVAL);
819 819
820 820 (void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
821 821 }
822 822 return (DLADM_STATUS_OK);
823 823 }
824 824
825 825 static dladm_status_t
826 826 i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
827 827 datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
828 828 uint_t val_cnt, uint_t flags)
829 829 {
830 830 dladm_status_t status = DLADM_STATUS_OK;
831 831 val_desc_t *vdp = NULL;
832 832 boolean_t needfree = B_FALSE;
833 833 uint_t cnt, i;
834 834
835 835 if (!(pdp->pd_class & class))
836 836 return (DLADM_STATUS_BADARG);
837 837
838 838 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
839 839 return (DLADM_STATUS_BADARG);
840 840
841 841 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
842 842 return (DLADM_STATUS_TEMPONLY);
843 843
844 844 if (!(flags & DLADM_OPT_ACTIVE))
845 845 return (DLADM_STATUS_OK);
846 846
847 847 if (pdp->pd_set == NULL)
848 848 return (DLADM_STATUS_PROPRDONLY);
849 849
850 850 if (prop_val != NULL) {
851 851 vdp = calloc(val_cnt, sizeof (val_desc_t));
852 852 if (vdp == NULL)
853 853 return (DLADM_STATUS_NOMEM);
854 854
855 855 if (pdp->pd_check != NULL) {
856 856 needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
857 857 status = pdp->pd_check(handle, pdp, linkid, prop_val,
858 858 &val_cnt, flags, &vdp, media);
859 859 } else if (pdp->pd_optval != NULL) {
860 860 status = check_prop(handle, pdp, linkid, prop_val,
861 861 &val_cnt, flags, &vdp, media);
862 862 } else {
863 863 status = DLADM_STATUS_BADARG;
864 864 }
865 865
866 866 if (status != DLADM_STATUS_OK)
867 867 goto done;
868 868
869 869 cnt = val_cnt;
870 870 } else {
871 871 boolean_t defval = B_FALSE;
872 872
873 873 if (pdp->pd_defval.vd_name == NULL)
874 874 return (DLADM_STATUS_NOTSUP);
875 875
876 876 cnt = 1;
877 877 defval = (strlen(pdp->pd_defval.vd_name) > 0);
878 878 if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
879 879 if ((vdp = calloc(1, sizeof (val_desc_t))) == NULL)
880 880 return (DLADM_STATUS_NOMEM);
881 881
882 882 if (defval) {
883 883 (void) memcpy(vdp, &pdp->pd_defval,
884 884 sizeof (val_desc_t));
885 885 } else if (pdp->pd_check != NULL) {
886 886 status = pdp->pd_check(handle, pdp, linkid,
887 887 prop_val, &cnt, flags, &vdp, media);
888 888 if (status != DLADM_STATUS_OK)
889 889 goto done;
890 890 }
891 891 } else {
892 892 status = i_dladm_getset_defval(handle, pdp, linkid,
893 893 media, flags);
894 894 return (status);
895 895 }
896 896 }
897 897 if (pdp->pd_flags & PD_AFTER_PERM)
898 898 status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
899 899 DLADM_STATUS_PERMONLY;
900 900 else
901 901 status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
902 902 media);
903 903 if (needfree) {
904 904 for (i = 0; i < cnt; i++)
905 905 free((void *)((val_desc_t *)vdp + i)->vd_val);
906 906 }
907 907 done:
908 908 free(vdp);
909 909 return (status);
910 910 }
911 911
912 912 static dladm_status_t
913 913 i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
914 914 const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
915 915 {
916 916 int i;
917 917 boolean_t found = B_FALSE;
918 918 datalink_class_t class;
919 919 uint32_t media;
920 920 dladm_status_t status = DLADM_STATUS_OK;
921 921
922 922 status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
923 923 NULL, 0);
924 924 if (status != DLADM_STATUS_OK)
925 925 return (status);
926 926
927 927 for (i = 0; i < DLADM_MAX_PROPS; i++) {
928 928 prop_desc_t *pdp = &prop_table[i];
929 929 dladm_status_t s;
930 930
931 931 if (prop_name != NULL &&
932 932 (strcasecmp(prop_name, pdp->pd_name) != 0))
933 933 continue;
934 934 found = B_TRUE;
935 935 s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
936 936 prop_val, val_cnt, flags);
937 937
938 938 if (prop_name != NULL) {
939 939 status = s;
940 940 break;
941 941 } else {
942 942 if (s != DLADM_STATUS_OK &&
943 943 s != DLADM_STATUS_NOTSUP)
944 944 status = s;
945 945 }
946 946 }
947 947 if (!found) {
948 948 if (prop_name[0] == '_') {
949 949 /* other private properties */
950 950 status = i_dladm_set_private_prop(handle, linkid,
951 951 prop_name, prop_val, val_cnt, flags);
952 952 } else {
953 953 status = DLADM_STATUS_NOTFOUND;
954 954 }
955 955 }
956 956 return (status);
957 957 }
958 958
959 959 /*
960 960 * Set/reset link property for specific link
961 961 */
962 962 dladm_status_t
963 963 dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
964 964 const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
965 965 {
966 966 dladm_status_t status = DLADM_STATUS_OK;
967 967
968 968 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
969 969 (prop_val == NULL && val_cnt > 0) ||
970 970 (prop_val != NULL && val_cnt == 0) ||
971 971 (prop_name == NULL && prop_val != NULL)) {
972 972 return (DLADM_STATUS_BADARG);
973 973 }
974 974
975 975 /*
976 976 * Check for valid link property against the flags passed
977 977 * and set the link property when active flag is passed.
978 978 */
979 979 status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
980 980 val_cnt, flags);
981 981 if (status != DLADM_STATUS_OK)
982 982 return (status);
983 983
984 984 if (flags & DLADM_OPT_PERSIST) {
985 985 status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
986 986 prop_val, val_cnt);
987 987
988 988 if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
989 989 prop_desc_t *pdp = prop_table;
990 990 int i;
991 991
992 992 for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
993 993 if (!(pdp->pd_flags & PD_AFTER_PERM))
994 994 continue;
995 995 if (prop_name != NULL &&
996 996 strcasecmp(prop_name, pdp->pd_name) != 0)
997 997 continue;
998 998 status = pdp->pd_set(handle, pdp, linkid, NULL,
999 999 0, flags, 0);
1000 1000 }
1001 1001 }
1002 1002 }
1003 1003 return (status);
1004 1004 }
1005 1005
1006 1006 /*
1007 1007 * Walk all link properties of the given specific link.
1008 1008 *
1009 1009 * Note: this function currently lacks the ability to walk _all_ private
1010 1010 * properties if the link, because there is no kernel interface to
1011 1011 * retrieve all known private property names. Once such an interface
1012 1012 * is added, this function should be fixed accordingly.
1013 1013 */
1014 1014 dladm_status_t
1015 1015 dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
1016 1016 int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
1017 1017 {
1018 1018 dladm_status_t status;
1019 1019 datalink_class_t class;
1020 1020 uint_t media;
1021 1021 int i;
1022 1022
1023 1023 if (linkid == DATALINK_INVALID_LINKID || func == NULL)
1024 1024 return (DLADM_STATUS_BADARG);
1025 1025
1026 1026 status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1027 1027 NULL, 0);
1028 1028 if (status != DLADM_STATUS_OK)
1029 1029 return (status);
1030 1030
1031 1031 /* public */
1032 1032 for (i = 0; i < DLADM_MAX_PROPS; i++) {
1033 1033 if (!(prop_table[i].pd_class & class))
1034 1034 continue;
1035 1035
1036 1036 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
1037 1037 continue;
1038 1038
1039 1039 if (func(handle, linkid, prop_table[i].pd_name, arg) ==
1040 1040 DLADM_WALK_TERMINATE) {
1041 1041 break;
1042 1042 }
1043 1043 }
1044 1044
1045 1045 /* private */
1046 1046 status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
1047 1047
1048 1048 return (status);
1049 1049 }
1050 1050
1051 1051 /*
1052 1052 * Get linkprop of the given specific link.
1053 1053 */
1054 1054 dladm_status_t
1055 1055 dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
1056 1056 dladm_prop_type_t type, const char *prop_name, char **prop_val,
1057 1057 uint_t *val_cntp)
1058 1058 {
1059 1059 dladm_status_t status = DLADM_STATUS_OK;
1060 1060 datalink_class_t class;
1061 1061 uint_t media;
1062 1062 prop_desc_t *pdp;
1063 1063 uint_t cnt, dld_flags = 0;
1064 1064 int i;
1065 1065 uint_t perm_flags;
1066 1066
1067 1067 if (type == DLADM_PROP_VAL_DEFAULT)
1068 1068 dld_flags |= DLD_PROP_DEFAULT;
1069 1069 else if (type == DLADM_PROP_VAL_MODIFIABLE)
1070 1070 dld_flags |= DLD_PROP_POSSIBLE;
1071 1071
1072 1072 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
1073 1073 prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
1074 1074 return (DLADM_STATUS_BADARG);
1075 1075
1076 1076 for (i = 0; i < DLADM_MAX_PROPS; i++)
1077 1077 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
1078 1078 break;
1079 1079
1080 1080 if (i == DLADM_MAX_PROPS) {
1081 1081 if (prop_name[0] == '_') {
1082 1082 /*
1083 1083 * private property.
1084 1084 */
1085 1085 if (type == DLADM_PROP_VAL_PERSISTENT)
1086 1086 return (i_dladm_get_linkprop_db(handle, linkid,
1087 1087 prop_name, prop_val, val_cntp));
1088 1088 else
1089 1089 return (i_dladm_get_priv_prop(handle, linkid,
1090 1090 prop_name, prop_val, val_cntp, type,
1091 1091 dld_flags));
1092 1092 } else {
1093 1093 return (DLADM_STATUS_NOTFOUND);
1094 1094 }
1095 1095 }
1096 1096
1097 1097 pdp = &prop_table[i];
1098 1098
1099 1099 status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1100 1100 NULL, 0);
1101 1101 if (status != DLADM_STATUS_OK)
1102 1102 return (status);
1103 1103
1104 1104 if (!(pdp->pd_class & class))
1105 1105 return (DLADM_STATUS_BADARG);
1106 1106
1107 1107 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
1108 1108 return (DLADM_STATUS_BADARG);
1109 1109
1110 1110 switch (type) {
1111 1111 case DLADM_PROP_VAL_CURRENT:
1112 1112 status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1113 1113 media, dld_flags, &perm_flags);
1114 1114 break;
1115 1115
1116 1116 case DLADM_PROP_VAL_PERM:
1117 1117 if (pdp->pd_set == NULL) {
1118 1118 perm_flags = MAC_PROP_PERM_READ;
1119 1119 } else {
1120 1120 status = pdp->pd_get(handle, pdp, linkid, prop_val,
1121 1121 val_cntp, media, dld_flags, &perm_flags);
1122 1122 }
1123 1123
1124 1124 *prop_val[0] = '\0';
1125 1125 *val_cntp = 1;
1126 1126 if (status == DLADM_STATUS_OK)
1127 1127 (void) dladm_perm2str(perm_flags, *prop_val);
1128 1128 break;
1129 1129
1130 1130 case DLADM_PROP_VAL_DEFAULT:
1131 1131 /*
1132 1132 * If defaults are not defined for the property,
1133 1133 * pd_defval.vd_name should be null. If the driver
1134 1134 * has to be contacted for the value, vd_name should
1135 1135 * be the empty string (""). Otherwise, dladm will
1136 1136 * just print whatever is in the table.
1137 1137 */
1138 1138 if (pdp->pd_defval.vd_name == NULL) {
1139 1139 status = DLADM_STATUS_NOTSUP;
1140 1140 break;
1141 1141 }
1142 1142
1143 1143 if (strlen(pdp->pd_defval.vd_name) == 0) {
1144 1144 status = pdp->pd_get(handle, pdp, linkid, prop_val,
1145 1145 val_cntp, media, dld_flags, &perm_flags);
1146 1146 } else {
1147 1147 (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
1148 1148 }
1149 1149 *val_cntp = 1;
1150 1150 break;
1151 1151
1152 1152 case DLADM_PROP_VAL_MODIFIABLE:
1153 1153 if (pdp->pd_getmod != NULL) {
1154 1154 status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
1155 1155 val_cntp, media, dld_flags, &perm_flags);
1156 1156 break;
1157 1157 }
1158 1158 cnt = pdp->pd_noptval;
1159 1159 if (cnt == 0) {
1160 1160 status = DLADM_STATUS_NOTSUP;
1161 1161 } else if (cnt > *val_cntp) {
1162 1162 status = DLADM_STATUS_TOOSMALL;
1163 1163 } else {
1164 1164 for (i = 0; i < cnt; i++) {
1165 1165 (void) strcpy(prop_val[i],
1166 1166 pdp->pd_optval[i].vd_name);
1167 1167 }
1168 1168 *val_cntp = cnt;
1169 1169 }
1170 1170 break;
1171 1171 case DLADM_PROP_VAL_PERSISTENT:
1172 1172 if (pdp->pd_flags & PD_TEMPONLY)
1173 1173 return (DLADM_STATUS_TEMPONLY);
1174 1174 status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
1175 1175 prop_val, val_cntp);
1176 1176 break;
1177 1177 default:
1178 1178 status = DLADM_STATUS_BADARG;
1179 1179 break;
1180 1180 }
1181 1181
1182 1182 return (status);
1183 1183 }
1184 1184
1185 1185 /*
1186 1186 * Get linkprop of the given specific link and run any possible conversion
1187 1187 * of the values using the check function for the property. Fails if the
1188 1188 * check function doesn't succeed for the property value.
1189 1189 */
1190 1190 dladm_status_t
1191 1191 dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
1192 1192 dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
1193 1193 uint_t *val_cntp)
1194 1194 {
1195 1195 dladm_status_t status;
1196 1196 datalink_class_t class;
1197 1197 uint_t media;
1198 1198 prop_desc_t *pdp;
1199 1199 uint_t dld_flags;
1200 1200 int valc, i;
1201 1201 char **prop_val;
1202 1202 uint_t perm_flags;
1203 1203
1204 1204 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
1205 1205 ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
1206 1206 return (DLADM_STATUS_BADARG);
1207 1207
1208 1208 for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
1209 1209 if (strcasecmp(prop_name, pdp->pd_name) == 0)
1210 1210 break;
1211 1211
1212 1212 if (pdp == prop_table + DLADM_MAX_PROPS)
1213 1213 return (DLADM_STATUS_NOTFOUND);
1214 1214
1215 1215 if (pdp->pd_flags & PD_CHECK_ALLOC)
1216 1216 return (DLADM_STATUS_BADARG);
1217 1217
1218 1218 status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1219 1219 NULL, 0);
1220 1220 if (status != DLADM_STATUS_OK)
1221 1221 return (status);
1222 1222
1223 1223 if (!(pdp->pd_class & class))
1224 1224 return (DLADM_STATUS_BADARG);
1225 1225
1226 1226 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
1227 1227 return (DLADM_STATUS_BADARG);
1228 1228
1229 1229 prop_val = malloc(*val_cntp * sizeof (*prop_val) +
1230 1230 *val_cntp * DLADM_PROP_VAL_MAX);
1231 1231 if (prop_val == NULL)
1232 1232 return (DLADM_STATUS_NOMEM);
1233 1233 for (valc = 0; valc < *val_cntp; valc++)
1234 1234 prop_val[valc] = (char *)(prop_val + *val_cntp) +
1235 1235 valc * DLADM_PROP_VAL_MAX;
1236 1236
1237 1237 dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? DLD_PROP_DEFAULT : 0;
1238 1238
1239 1239 switch (type) {
1240 1240 case DLADM_PROP_VAL_CURRENT:
1241 1241 status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1242 1242 media, dld_flags, &perm_flags);
1243 1243 break;
1244 1244
1245 1245 case DLADM_PROP_VAL_DEFAULT:
1246 1246 /*
1247 1247 * If defaults are not defined for the property,
1248 1248 * pd_defval.vd_name should be null. If the driver
1249 1249 * has to be contacted for the value, vd_name should
1250 1250 * be the empty string (""). Otherwise, dladm will
1251 1251 * just print whatever is in the table.
1252 1252 */
1253 1253 if (pdp->pd_defval.vd_name == NULL) {
1254 1254 status = DLADM_STATUS_NOTSUP;
1255 1255 break;
1256 1256 }
1257 1257
1258 1258 if (pdp->pd_defval.vd_name[0] != '\0') {
1259 1259 *val_cntp = 1;
1260 1260 *ret_val = pdp->pd_defval.vd_val;
1261 1261 free(prop_val);
1262 1262 return (DLADM_STATUS_OK);
1263 1263 }
1264 1264 status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1265 1265 media, dld_flags, &perm_flags);
1266 1266 break;
1267 1267
1268 1268 case DLADM_PROP_VAL_PERSISTENT:
1269 1269 if (pdp->pd_flags & PD_TEMPONLY)
1270 1270 status = DLADM_STATUS_TEMPONLY;
1271 1271 else
1272 1272 status = i_dladm_get_linkprop_db(handle, linkid,
1273 1273 prop_name, prop_val, val_cntp);
1274 1274 break;
1275 1275
1276 1276 default:
1277 1277 status = DLADM_STATUS_BADARG;
1278 1278 break;
1279 1279 }
1280 1280
1281 1281 if (status == DLADM_STATUS_OK) {
1282 1282 if (pdp->pd_check != NULL) {
1283 1283 val_desc_t *vdp;
1284 1284
1285 1285 vdp = malloc(sizeof (val_desc_t) * *val_cntp);
1286 1286 if (vdp == NULL)
1287 1287 status = DLADM_STATUS_NOMEM;
1288 1288 else
1289 1289 status = pdp->pd_check(handle, pdp, linkid,
1290 1290 prop_val, val_cntp, 0, &vdp, media);
1291 1291 if (status == DLADM_STATUS_OK) {
1292 1292 for (valc = 0; valc < *val_cntp; valc++)
1293 1293 ret_val[valc] = vdp[valc].vd_val;
1294 1294 }
1295 1295 free(vdp);
1296 1296 } else {
1297 1297 for (valc = 0; valc < *val_cntp; valc++) {
1298 1298 for (i = 0; i < pdp->pd_noptval; i++) {
1299 1299 if (strcmp(pdp->pd_optval[i].vd_name,
1300 1300 prop_val[valc]) == 0) {
1301 1301 ret_val[valc] =
1302 1302 pdp->pd_optval[i].vd_val;
1303 1303 break;
1304 1304 }
1305 1305 }
1306 1306 if (i == pdp->pd_noptval) {
1307 1307 status = DLADM_STATUS_FAILED;
1308 1308 break;
1309 1309 }
1310 1310 }
1311 1311 }
1312 1312 }
1313 1313
1314 1314 free(prop_val);
1315 1315
1316 1316 return (status);
1317 1317 }
1318 1318
1319 1319 /*ARGSUSED*/
1320 1320 static int
1321 1321 i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
1322 1322 const char *prop_name, void *arg)
1323 1323 {
1324 1324 char *buf, **propvals;
1325 1325 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT;
1326 1326 dladm_status_t status;
1327 1327 dladm_linkprop_args_t *dla = arg;
1328 1328
1329 1329 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
1330 1330 DLADM_MAX_PROP_VALCNT)) == NULL) {
1331 1331 return (DLADM_WALK_CONTINUE);
1332 1332 }
1333 1333
1334 1334 propvals = (char **)(void *)buf;
1335 1335 for (i = 0; i < valcnt; i++) {
1336 1336 propvals[i] = buf +
1337 1337 sizeof (char *) * DLADM_MAX_PROP_VALCNT +
1338 1338 i * DLADM_PROP_VAL_MAX;
1339 1339 }
1340 1340
1341 1341 if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
1342 1342 prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
1343 1343 goto done;
1344 1344 }
1345 1345
1346 1346 status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
1347 1347 valcnt, dla->dla_flags | DLADM_OPT_ACTIVE);
1348 1348
1349 1349 if (status != DLADM_STATUS_OK)
1350 1350 dla->dla_status = status;
1351 1351
1352 1352 done:
1353 1353 if (buf != NULL)
1354 1354 free(buf);
1355 1355
1356 1356 return (DLADM_WALK_CONTINUE);
1357 1357 }
1358 1358
1359 1359 /*ARGSUSED*/
1360 1360 static int
1361 1361 i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
1362 1362 {
1363 1363 datalink_class_t class;
1364 1364 dladm_status_t status;
1365 1365
1366 1366 status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
1367 1367 NULL, 0);
1368 1368 if (status != DLADM_STATUS_OK)
1369 1369 return (DLADM_WALK_TERMINATE);
1370 1370
1371 1371 if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
1372 1372 (void) dladm_init_linkprop(handle, linkid, B_TRUE);
1373 1373
1374 1374 return (DLADM_WALK_CONTINUE);
1375 1375 }
1376 1376
1377 1377 dladm_status_t
1378 1378 dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
1379 1379 boolean_t any_media)
1380 1380 {
1381 1381 dladm_status_t status = DLADM_STATUS_OK;
1382 1382 datalink_media_t dmedia;
1383 1383 uint32_t media;
1384 1384 dladm_linkprop_args_t *dla;
1385 1385
1386 1386 dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
1387 1387
1388 1388 dla = malloc(sizeof (dladm_linkprop_args_t));
1389 1389 if (dla == NULL)
1390 1390 return (DLADM_STATUS_NOMEM);
1391 1391 dla->dla_flags = DLADM_OPT_BOOT;
1392 1392 dla->dla_status = DLADM_STATUS_OK;
1393 1393
1394 1394 if (linkid == DATALINK_ALL_LINKID) {
1395 1395 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
1396 1396 NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
1397 1397 } else if (any_media ||
1398 1398 ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
1399 1399 0) == DLADM_STATUS_OK) &&
1400 1400 DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
1401 1401 (void) dladm_walk_linkprop(handle, linkid, (void *)dla,
1402 1402 i_dladm_init_one_prop);
1403 1403 status = dla->dla_status;
1404 1404 }
1405 1405 free(dla);
1406 1406 return (status);
1407 1407 }
1408 1408
1409 1409 /* ARGSUSED */
1410 1410 static dladm_status_t
1411 1411 get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1412 1412 char **prop_val, uint_t *val_cnt, datalink_media_t media,
1413 1413 uint_t flags, uint_t *perm_flags)
1414 1414 {
1415 1415 char zone_name[ZONENAME_MAX];
1416 1416 zoneid_t zid;
1417 1417 dladm_status_t status;
1418 1418
1419 1419 if (flags != 0)
1420 1420 return (DLADM_STATUS_NOTSUP);
1421 1421
1422 1422 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1423 1423 perm_flags, &zid, sizeof (zid));
1424 1424 if (status != DLADM_STATUS_OK)
1425 1425 return (status);
1426 1426
1427 1427 *val_cnt = 1;
1428 1428 if (zid != GLOBAL_ZONEID) {
1429 1429 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
1430 1430 return (dladm_errno2status(errno));
1431 1431 }
1432 1432
1433 1433 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
1434 1434 } else {
1435 1435 *prop_val[0] = '\0';
1436 1436 }
1437 1437
1438 1438 return (DLADM_STATUS_OK);
1439 1439 }
1440 1440
1441 1441 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
1442 1442
1443 1443 static int
1444 1444 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
1445 1445 {
1446 1446 char root[MAXPATHLEN];
1447 1447 zone_get_devroot_t real_zone_get_devroot;
1448 1448 void *dlhandle;
1449 1449 void *sym;
1450 1450 int ret;
1451 1451
1452 1452 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
1453 1453 return (-1);
1454 1454
1455 1455 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
1456 1456 (void) dlclose(dlhandle);
1457 1457 return (-1);
1458 1458 }
1459 1459
1460 1460 real_zone_get_devroot = (zone_get_devroot_t)sym;
1461 1461
1462 1462 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
1463 1463 (void) snprintf(dev, devlen, "%s%s", root, "/dev");
1464 1464 (void) dlclose(dlhandle);
1465 1465 return (ret);
1466 1466 }
1467 1467
1468 1468 static dladm_status_t
1469 1469 i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
1470 1470 datalink_id_t linkid, boolean_t add)
1471 1471 {
1472 1472 char path[MAXPATHLEN];
1473 1473 char name[MAXLINKNAMELEN];
1474 1474 di_prof_t prof = NULL;
1475 1475 char zone_name[ZONENAME_MAX];
1476 1476 dladm_status_t status;
1477 1477 int ret;
1478 1478
1479 1479 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
1480 1480 return (dladm_errno2status(errno));
1481 1481 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
1482 1482 return (dladm_errno2status(errno));
1483 1483 if (di_prof_init(path, &prof) != 0)
1484 1484 return (dladm_errno2status(errno));
1485 1485
1486 1486 status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
1487 1487 if (status != DLADM_STATUS_OK)
1488 1488 goto cleanup;
1489 1489
1490 1490 if (add)
1491 1491 ret = di_prof_add_dev(prof, name);
1492 1492 else
1493 1493 ret = di_prof_add_exclude(prof, name);
1494 1494
1495 1495 if (ret != 0) {
1496 1496 status = dladm_errno2status(errno);
1497 1497 goto cleanup;
1498 1498 }
1499 1499
1500 1500 if (di_prof_commit(prof) != 0)
1501 1501 status = dladm_errno2status(errno);
1502 1502 cleanup:
1503 1503 if (prof)
1504 1504 di_prof_fini(prof);
1505 1505
1506 1506 return (status);
1507 1507 }
1508 1508
1509 1509 /* ARGSUSED */
1510 1510 static dladm_status_t
1511 1511 set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1512 1512 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1513 1513 {
1514 1514 dladm_status_t status = DLADM_STATUS_OK;
1515 1515 zoneid_t zid_old, zid_new;
1516 1516 dld_ioc_zid_t *dzp;
1517 1517
1518 1518 if (val_cnt != 1)
1519 1519 return (DLADM_STATUS_BADVALCNT);
1520 1520
1521 1521 dzp = (dld_ioc_zid_t *)vdp->vd_val;
|
↓ open down ↓ |
1521 lines elided |
↑ open up ↑ |
1522 1522
1523 1523 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1524 1524 NULL, &zid_old, sizeof (zid_old));
1525 1525 if (status != DLADM_STATUS_OK)
1526 1526 return (status);
1527 1527
1528 1528 zid_new = dzp->diz_zid;
1529 1529 if (zid_new == zid_old)
1530 1530 return (DLADM_STATUS_OK);
1531 1531
1532 + if (flags & DLADM_OPT_TRANSIENT)
1533 + dzp->diz_transient = B_TRUE;
1534 +
1532 1535 if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt,
1533 1536 flags, media)) != DLADM_STATUS_OK)
1534 1537 return (status);
1535 1538
1536 1539 /*
1537 1540 * It is okay to fail to update the /dev entry (some vanity-named
1538 1541 * links do not have a /dev entry).
1539 1542 */
1540 1543 if (zid_old != GLOBAL_ZONEID) {
1541 1544 (void) i_dladm_update_deventry(handle, zid_old, linkid,
1542 1545 B_FALSE);
1543 1546 }
1544 1547 if (zid_new != GLOBAL_ZONEID)
1545 1548 (void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
1546 1549
1547 1550 return (DLADM_STATUS_OK);
1548 1551 }
1549 1552
1550 1553 /* ARGSUSED */
1551 1554 static dladm_status_t
1552 1555 check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1553 1556 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1554 1557 datalink_media_t media)
1555 1558 {
1556 1559 char *zone_name;
1557 1560 zoneid_t zoneid;
1558 1561 dladm_status_t status = DLADM_STATUS_OK;
1559 1562 dld_ioc_zid_t *dzp;
1560 1563 uint_t val_cnt = *val_cntp;
1561 1564 val_desc_t *vdp = *vdpp;
1562 1565
1563 1566 if (val_cnt != 1)
1564 1567 return (DLADM_STATUS_BADVALCNT);
1565 1568
1566 1569 dzp = malloc(sizeof (dld_ioc_zid_t));
1567 1570 if (dzp == NULL)
1568 1571 return (DLADM_STATUS_NOMEM);
1569 1572
1570 1573 zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
1571 1574 if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1572 1575 status = DLADM_STATUS_BADVAL;
1573 1576 goto done;
1574 1577 }
1575 1578
1576 1579 if (zoneid != GLOBAL_ZONEID) {
1577 1580 ushort_t flags;
1578 1581
1579 1582 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
1580 1583 sizeof (flags)) < 0) {
1581 1584 status = dladm_errno2status(errno);
1582 1585 goto done;
1583 1586 }
1584 1587
1585 1588 if (!(flags & ZF_NET_EXCL)) {
1586 1589 status = DLADM_STATUS_BADVAL;
1587 1590 goto done;
1588 1591 }
1589 1592 }
1590 1593
1591 1594 (void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
1592 1595
1593 1596 dzp->diz_zid = zoneid;
1594 1597 dzp->diz_linkid = linkid;
1595 1598
1596 1599 vdp->vd_val = (uintptr_t)dzp;
1597 1600 return (DLADM_STATUS_OK);
1598 1601 done:
1599 1602 free(dzp);
1600 1603 return (status);
1601 1604 }
1602 1605
1603 1606 /* ARGSUSED */
1604 1607 static dladm_status_t
1605 1608 get_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1606 1609 char **prop_val, uint_t *val_cnt, datalink_media_t media,
1607 1610 uint_t flags, uint_t *perm_flags)
1608 1611 {
1609 1612 mac_resource_props_t mrp;
1610 1613 dladm_status_t status;
1611 1614
1612 1615 status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
1613 1616 perm_flags, &mrp, sizeof (mrp));
1614 1617 if (status != DLADM_STATUS_OK)
1615 1618 return (status);
1616 1619
1617 1620 if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
1618 1621 *val_cnt = 0;
1619 1622 return (DLADM_STATUS_OK);
1620 1623 }
1621 1624
1622 1625 (void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
1623 1626 *val_cnt = 1;
1624 1627 return (DLADM_STATUS_OK);
1625 1628 }
1626 1629
1627 1630 /* ARGSUSED */
1628 1631 static dladm_status_t
1629 1632 check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1630 1633 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1631 1634 datalink_media_t media)
1632 1635 {
1633 1636 uint64_t *maxbw;
1634 1637 dladm_status_t status = DLADM_STATUS_OK;
1635 1638 uint_t val_cnt = *val_cntp;
1636 1639 val_desc_t *vdp = *vdpp;
1637 1640
1638 1641 if (val_cnt != 1)
1639 1642 return (DLADM_STATUS_BADVALCNT);
1640 1643
1641 1644 maxbw = malloc(sizeof (uint64_t));
1642 1645 if (maxbw == NULL)
1643 1646 return (DLADM_STATUS_NOMEM);
1644 1647
1645 1648 status = dladm_str2bw(*prop_val, maxbw);
1646 1649 if (status != DLADM_STATUS_OK) {
1647 1650 free(maxbw);
1648 1651 return (status);
1649 1652 }
1650 1653
1651 1654 if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
1652 1655 free(maxbw);
1653 1656 return (DLADM_STATUS_MINMAXBW);
1654 1657 }
1655 1658
1656 1659 vdp->vd_val = (uintptr_t)maxbw;
1657 1660 return (DLADM_STATUS_OK);
1658 1661 }
1659 1662
1660 1663 /* ARGSUSED */
1661 1664 dladm_status_t
1662 1665 extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
1663 1666 {
1664 1667 mac_resource_props_t *mrp = arg;
1665 1668
1666 1669 if (vdp->vd_val == RESET_VAL) {
1667 1670 mrp->mrp_maxbw = MRP_MAXBW_RESETVAL;
1668 1671 } else {
1669 1672 bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
1670 1673 }
1671 1674 mrp->mrp_mask |= MRP_MAXBW;
1672 1675
1673 1676 return (DLADM_STATUS_OK);
1674 1677 }
1675 1678
1676 1679 /* ARGSUSED */
1677 1680 static dladm_status_t
1678 1681 get_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1679 1682 char **prop_val, uint_t *val_cnt, datalink_media_t media,
1680 1683 uint_t flags, uint_t *perm_flags)
1681 1684 {
1682 1685 dladm_status_t status;
1683 1686 mac_resource_props_t mrp;
1684 1687 mac_propval_range_t *pv_range;
1685 1688 int err;
1686 1689
1687 1690 if (strcmp(pdp->pd_name, "cpus-effective") == 0) {
1688 1691 status = i_dladm_get_public_prop(handle, linkid,
1689 1692 "resource-effective", flags, perm_flags, &mrp,
1690 1693 sizeof (mrp));
1691 1694 } else {
1692 1695 status = i_dladm_get_public_prop(handle, linkid,
1693 1696 "resource", flags, perm_flags, &mrp, sizeof (mrp));
1694 1697 }
1695 1698
1696 1699 if (status != DLADM_STATUS_OK)
1697 1700 return (status);
1698 1701
1699 1702 if (mrp.mrp_ncpus > *val_cnt)
1700 1703 return (DLADM_STATUS_TOOSMALL);
1701 1704
1702 1705 if (mrp.mrp_ncpus == 0) {
1703 1706 *val_cnt = 0;
1704 1707 return (DLADM_STATUS_OK);
1705 1708 }
1706 1709
1707 1710 /* Sort CPU list and convert it to a mac_propval_range */
1708 1711 status = dladm_list2range(mrp.mrp_cpu, mrp.mrp_ncpus,
1709 1712 MAC_PROPVAL_UINT32, &pv_range);
1710 1713 if (status != DLADM_STATUS_OK)
1711 1714 return (status);
1712 1715
1713 1716 /* Write CPU ranges and individual CPUs */
1714 1717 err = dladm_range2strs(pv_range, prop_val);
1715 1718 if (err != 0) {
1716 1719 free(pv_range);
1717 1720 return (dladm_errno2status(err));
1718 1721 }
1719 1722
1720 1723 *val_cnt = pv_range->mpr_count;
1721 1724 free(pv_range);
1722 1725
1723 1726 return (DLADM_STATUS_OK);
1724 1727 }
1725 1728
1726 1729 /* ARGSUSED */
1727 1730 static dladm_status_t
1728 1731 check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1729 1732 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1730 1733 datalink_media_t media)
1731 1734 {
1732 1735 int i, j, rc;
1733 1736 long nproc = sysconf(_SC_NPROCESSORS_CONF);
1734 1737 mac_resource_props_t mrp;
1735 1738 mac_propval_range_t *pv_range;
1736 1739 uint_t perm_flags;
1737 1740 uint32_t ncpus;
1738 1741 uint32_t *cpus = mrp.mrp_cpu;
1739 1742 val_desc_t *vdp = *vdpp;
1740 1743 val_desc_t *newvdp;
1741 1744 uint_t val_cnt = *val_cntp;
1742 1745 dladm_status_t status = DLADM_STATUS_OK;
1743 1746
1744 1747 /* Get the current pool property */
1745 1748 status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1746 1749 &perm_flags, &mrp, sizeof (mrp));
1747 1750
1748 1751 if (status == DLADM_STATUS_OK) {
1749 1752 /* Can't set cpus if a pool is set */
1750 1753 if (strlen(mrp.mrp_pool) != 0)
1751 1754 return (DLADM_STATUS_POOLCPU);
1752 1755 }
1753 1756
1754 1757 /* Read ranges and convert to mac_propval_range */
1755 1758 status = dladm_strs2range(prop_val, val_cnt, MAC_PROPVAL_UINT32,
1756 1759 &pv_range);
1757 1760 if (status != DLADM_STATUS_OK)
1758 1761 goto done1;
1759 1762
1760 1763 /* Convert mac_propval_range to a single CPU list */
1761 1764 ncpus = MRP_NCPUS;
1762 1765 status = dladm_range2list(pv_range, cpus, &ncpus);
1763 1766 if (status != DLADM_STATUS_OK)
1764 1767 goto done1;
1765 1768
1766 1769 /*
1767 1770 * If a range of CPUs was entered, update value count and reallocate
1768 1771 * the array of val_desc_t's. The array allocated was sized for
1769 1772 * indvidual elements, but needs to be reallocated to accomodate the
1770 1773 * expanded list of CPUs.
1771 1774 */
1772 1775 if (val_cnt < ncpus) {
1773 1776 newvdp = calloc(*val_cntp, sizeof (val_desc_t));
1774 1777 if (newvdp == NULL) {
1775 1778 status = DLADM_STATUS_NOMEM;
1776 1779 goto done1;
1777 1780 }
1778 1781 vdp = newvdp;
1779 1782 }
1780 1783
1781 1784 /* Check if all CPUs in the list are online */
1782 1785 for (i = 0; i < ncpus; i++) {
1783 1786 if (cpus[i] >= nproc) {
1784 1787 status = DLADM_STATUS_BADCPUID;
1785 1788 goto done2;
1786 1789 }
1787 1790
1788 1791 rc = p_online(cpus[i], P_STATUS);
1789 1792 if (rc < 1) {
1790 1793 status = DLADM_STATUS_CPUERR;
1791 1794 goto done2;
1792 1795 }
1793 1796
1794 1797 if (rc != P_ONLINE) {
1795 1798 status = DLADM_STATUS_CPUNOTONLINE;
1796 1799 goto done2;
1797 1800 }
1798 1801
1799 1802 vdp[i].vd_val = (uintptr_t)cpus[i];
1800 1803 }
1801 1804
1802 1805 /* Check for duplicate CPUs */
1803 1806 for (i = 0; i < *val_cntp; i++) {
1804 1807 for (j = 0; j < *val_cntp; j++) {
1805 1808 if (i != j && vdp[i].vd_val == vdp[j].vd_val) {
1806 1809 status = DLADM_STATUS_BADVAL;
1807 1810 goto done2;
1808 1811 }
1809 1812 }
1810 1813 }
1811 1814
1812 1815 /* Update *val_cntp and *vdpp if everything was OK */
1813 1816 if (val_cnt < ncpus) {
1814 1817 *val_cntp = ncpus;
1815 1818 free(*vdpp);
1816 1819 *vdpp = newvdp;
1817 1820 }
1818 1821
1819 1822 status = DLADM_STATUS_OK;
1820 1823 goto done1;
1821 1824
1822 1825 done2:
1823 1826 free(newvdp);
1824 1827 done1:
1825 1828 free(pv_range);
1826 1829 return (status);
1827 1830 }
1828 1831
1829 1832 /* ARGSUSED */
1830 1833 dladm_status_t
1831 1834 extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
1832 1835 {
1833 1836 mac_resource_props_t *mrp = arg;
1834 1837 int i;
1835 1838
1836 1839 if (vdp[0].vd_val == RESET_VAL) {
1837 1840 bzero(&mrp->mrp_cpus, sizeof (mac_cpus_t));
1838 1841 mrp->mrp_mask |= MRP_CPUS;
1839 1842 return (DLADM_STATUS_OK);
1840 1843 }
1841 1844
1842 1845 for (i = 0; i < cnt; i++)
1843 1846 mrp->mrp_cpu[i] = (uint32_t)vdp[i].vd_val;
1844 1847
1845 1848 mrp->mrp_ncpus = cnt;
1846 1849 mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
1847 1850 mrp->mrp_fanout_mode = MCM_CPUS;
1848 1851 mrp->mrp_rx_intr_cpu = -1;
1849 1852
1850 1853 return (DLADM_STATUS_OK);
1851 1854 }
1852 1855
1853 1856 /*
1854 1857 * Get the pool datalink property from the kernel. This is used
1855 1858 * for both the user specified pool and effective pool properties.
1856 1859 */
1857 1860 /* ARGSUSED */
1858 1861 static dladm_status_t
1859 1862 get_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1860 1863 char **prop_val, uint_t *val_cnt, datalink_media_t media,
1861 1864 uint_t flags, uint_t *perm_flags)
1862 1865 {
1863 1866 mac_resource_props_t mrp;
1864 1867 dladm_status_t status;
1865 1868
1866 1869 if (strcmp(pdp->pd_name, "pool-effective") == 0) {
1867 1870 status = i_dladm_get_public_prop(handle, linkid,
1868 1871 "resource-effective", flags, perm_flags, &mrp,
1869 1872 sizeof (mrp));
1870 1873 } else {
1871 1874 status = i_dladm_get_public_prop(handle, linkid,
1872 1875 "resource", flags, perm_flags, &mrp, sizeof (mrp));
1873 1876 }
1874 1877
1875 1878 if (status != DLADM_STATUS_OK)
1876 1879 return (status);
1877 1880
1878 1881 if (strlen(mrp.mrp_pool) == 0) {
1879 1882 (*prop_val)[0] = '\0';
1880 1883 } else {
1881 1884 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
1882 1885 "%s", mrp.mrp_pool);
1883 1886 }
1884 1887 *val_cnt = 1;
1885 1888
1886 1889 return (DLADM_STATUS_OK);
1887 1890 }
1888 1891
1889 1892 /* ARGSUSED */
1890 1893 static dladm_status_t
1891 1894 check_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1892 1895 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1893 1896 datalink_media_t media)
1894 1897 {
1895 1898 pool_conf_t *poolconf;
1896 1899 pool_t *pool;
1897 1900 mac_resource_props_t mrp;
1898 1901 dladm_status_t status;
1899 1902 uint_t perm_flags;
1900 1903 char *poolname;
1901 1904 val_desc_t *vdp = *vdpp;
1902 1905
1903 1906 /* Get the current cpus property */
1904 1907 status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1905 1908 &perm_flags, &mrp, sizeof (mrp));
1906 1909
1907 1910 if (status == DLADM_STATUS_OK) {
1908 1911 /* Can't set pool if cpus are set */
1909 1912 if (mrp.mrp_ncpus != 0)
1910 1913 return (DLADM_STATUS_POOLCPU);
1911 1914 }
1912 1915
1913 1916 poolname = malloc(sizeof (mrp.mrp_pool));
1914 1917 if (poolname == NULL)
1915 1918 return (DLADM_STATUS_NOMEM);
1916 1919
1917 1920 /* Check for pool's availability if not booting */
1918 1921 if ((flags & DLADM_OPT_BOOT) == 0) {
1919 1922
1920 1923 /* Allocate and open pool configuration */
1921 1924 if ((poolconf = pool_conf_alloc()) == NULL)
1922 1925 return (DLADM_STATUS_BADVAL);
1923 1926
1924 1927 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY)
1925 1928 != PO_SUCCESS) {
1926 1929 pool_conf_free(poolconf);
1927 1930 return (DLADM_STATUS_BADVAL);
1928 1931 }
1929 1932
1930 1933 /* Look for pool name */
1931 1934 if ((pool = pool_get_pool(poolconf, *prop_val)) == NULL) {
1932 1935 pool_conf_free(poolconf);
1933 1936 return (DLADM_STATUS_BADVAL);
1934 1937 }
1935 1938
1936 1939 pool_conf_free(poolconf);
1937 1940 free(pool);
1938 1941 }
1939 1942
1940 1943 (void) strlcpy(poolname, *prop_val, sizeof (mrp.mrp_pool));
1941 1944 vdp->vd_val = (uintptr_t)poolname;
1942 1945
1943 1946 return (DLADM_STATUS_OK);
1944 1947 }
1945 1948
1946 1949 /* ARGSUSED */
1947 1950 dladm_status_t
1948 1951 extract_pool(val_desc_t *vdp, uint_t cnt, void *arg)
1949 1952 {
1950 1953 mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
1951 1954
1952 1955 if (vdp->vd_val == RESET_VAL) {
1953 1956 bzero(&mrp->mrp_pool, sizeof (mrp->mrp_pool));
1954 1957 mrp->mrp_mask |= MRP_POOL;
1955 1958 return (DLADM_STATUS_OK);
1956 1959 }
1957 1960
1958 1961 (void) strlcpy(mrp->mrp_pool, (char *)vdp->vd_val,
1959 1962 sizeof (mrp->mrp_pool));
1960 1963 mrp->mrp_mask |= MRP_POOL;
1961 1964 /*
1962 1965 * Use MCM_CPUS since the fanout count is not user specified
1963 1966 * and will be determined by the cpu list generated from the
1964 1967 * pool.
1965 1968 */
1966 1969 mrp->mrp_fanout_mode = MCM_CPUS;
1967 1970
1968 1971 return (DLADM_STATUS_OK);
1969 1972 }
1970 1973
1971 1974 /* ARGSUSED */
1972 1975 static dladm_status_t
1973 1976 get_priority(dladm_handle_t handle, prop_desc_t *pdp,
1974 1977 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
1975 1978 datalink_media_t media, uint_t flags, uint_t *perm_flags)
1976 1979 {
1977 1980 mac_resource_props_t mrp;
1978 1981 mac_priority_level_t pri;
1979 1982 dladm_status_t status;
1980 1983
1981 1984 status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
1982 1985 perm_flags, &mrp, sizeof (mrp));
1983 1986 if (status != DLADM_STATUS_OK)
1984 1987 return (status);
1985 1988
1986 1989 pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
1987 1990 mrp.mrp_priority;
1988 1991
1989 1992 (void) dladm_pri2str(pri, prop_val[0]);
1990 1993 *val_cnt = 1;
1991 1994 return (DLADM_STATUS_OK);
1992 1995 }
1993 1996
1994 1997 /* ARGSUSED */
1995 1998 dladm_status_t
1996 1999 extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
1997 2000 {
1998 2001 mac_resource_props_t *mrp = arg;
1999 2002
2000 2003 if (cnt != 1)
2001 2004 return (DLADM_STATUS_BADVAL);
2002 2005
2003 2006 mrp->mrp_priority = (mac_priority_level_t)vdp->vd_val;
2004 2007 mrp->mrp_mask |= MRP_PRIORITY;
2005 2008
2006 2009 return (DLADM_STATUS_OK);
2007 2010 }
2008 2011
2009 2012 /*
2010 2013 * Determines the size of the structure that needs to be sent to drivers
2011 2014 * for retrieving the property range values.
2012 2015 */
2013 2016 static int
2014 2017 i_dladm_range_size(mac_propval_range_t *r, size_t *sz, uint_t *rcount)
2015 2018 {
2016 2019 uint_t count = r->mpr_count;
2017 2020
2018 2021 *sz = sizeof (mac_propval_range_t);
2019 2022 *rcount = count;
2020 2023 --count;
2021 2024
2022 2025 switch (r->mpr_type) {
2023 2026 case MAC_PROPVAL_UINT32:
2024 2027 *sz += (count * sizeof (mac_propval_uint32_range_t));
2025 2028 return (0);
2026 2029 default:
2027 2030 break;
2028 2031 }
2029 2032 *sz = 0;
2030 2033 *rcount = 0;
2031 2034 return (EINVAL);
2032 2035 }
2033 2036
2034 2037
2035 2038 /* ARGSUSED */
2036 2039 static dladm_status_t
2037 2040 check_rings(dladm_handle_t handle, prop_desc_t *pdp,
2038 2041 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2039 2042 val_desc_t **vp, datalink_media_t media)
2040 2043 {
2041 2044 uint_t val_cnt = *val_cntp;
2042 2045 val_desc_t *v = *vp;
2043 2046
2044 2047 if (val_cnt != 1)
2045 2048 return (DLADM_STATUS_BADVAL);
2046 2049 if (strncasecmp(prop_val[0], "hw", strlen("hw")) == 0) {
2047 2050 v->vd_val = UNSPEC_VAL;
2048 2051 } else if (strncasecmp(prop_val[0], "sw", strlen("sw")) == 0) {
2049 2052 v->vd_val = 0;
2050 2053 } else {
2051 2054 v->vd_val = strtoul(prop_val[0], NULL, 0);
2052 2055 if (v->vd_val == 0)
2053 2056 return (DLADM_STATUS_BADVAL);
2054 2057 }
2055 2058 return (DLADM_STATUS_OK);
2056 2059 }
2057 2060
2058 2061 /* ARGSUSED */
2059 2062 static dladm_status_t
2060 2063 get_rings_range(dladm_handle_t handle, prop_desc_t *pdp,
2061 2064 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2062 2065 datalink_media_t media, uint_t flags, uint_t *perm_flags)
2063 2066 {
2064 2067 dld_ioc_macprop_t *dip;
2065 2068 dladm_status_t status = DLADM_STATUS_OK;
2066 2069 mac_propval_range_t *rangep;
2067 2070 size_t sz;
2068 2071 mac_propval_uint32_range_t *ur;
2069 2072
2070 2073 sz = sizeof (mac_propval_range_t);
2071 2074
2072 2075 if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
2073 2076 &status)) == NULL)
2074 2077 return (status);
2075 2078
2076 2079 status = i_dladm_macprop(handle, dip, B_FALSE);
2077 2080 if (status != DLADM_STATUS_OK)
2078 2081 return (status);
2079 2082
2080 2083 rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
2081 2084 *val_cnt = 1;
2082 2085 ur = &rangep->mpr_range_uint32[0];
2083 2086 /* This is the case where the dev doesn't have any rings/groups */
2084 2087 if (rangep->mpr_count == 0) {
2085 2088 (*prop_val)[0] = '\0';
2086 2089 /*
2087 2090 * This is the case where the dev supports rings, but static
2088 2091 * grouping.
2089 2092 */
2090 2093 } else if (ur->mpur_min == ur->mpur_max &&
2091 2094 ur->mpur_max == 0) {
2092 2095 (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw");
2093 2096 /*
2094 2097 * This is the case where the dev supports rings and dynamic
2095 2098 * grouping, but has only one value (say 2 rings and 2 groups).
2096 2099 */
2097 2100 } else if (ur->mpur_min == ur->mpur_max) {
2098 2101 (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw,%d",
2099 2102 ur->mpur_min);
2100 2103 /*
2101 2104 * This is the case where the dev supports rings and dynamic
2102 2105 * grouping and has a range of rings.
2103 2106 */
2104 2107 } else {
2105 2108 (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX,
2106 2109 "sw,hw,<%ld-%ld>", ur->mpur_min, ur->mpur_max);
2107 2110 }
2108 2111 free(dip);
2109 2112 return (status);
2110 2113 }
2111 2114
2112 2115
2113 2116 /* ARGSUSED */
2114 2117 static dladm_status_t
2115 2118 get_rxrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2116 2119 char **prop_val, uint_t *val_cnt, datalink_media_t media,
2117 2120 uint_t flags, uint_t *perm_flags)
2118 2121 {
2119 2122 mac_resource_props_t mrp;
2120 2123 dladm_status_t status;
2121 2124 uint32_t nrings = 0;
2122 2125
2123 2126 /*
2124 2127 * Get the number of (effective-)rings from the resource property.
2125 2128 */
2126 2129 if (strcmp(pdp->pd_name, "rxrings-effective") == 0) {
2127 2130 status = i_dladm_get_public_prop(handle, linkid,
2128 2131 "resource-effective", flags, perm_flags, &mrp,
2129 2132 sizeof (mrp));
2130 2133 } else {
2131 2134 /*
2132 2135 * Get the permissions from the "rxrings" property.
2133 2136 */
2134 2137 status = i_dladm_get_public_prop(handle, linkid, "rxrings",
2135 2138 flags, perm_flags, NULL, 0);
2136 2139 if (status != DLADM_STATUS_OK)
2137 2140 return (status);
2138 2141
2139 2142 status = i_dladm_get_public_prop(handle, linkid,
2140 2143 "resource", flags, NULL, &mrp, sizeof (mrp));
2141 2144 }
2142 2145
2143 2146 if (status != DLADM_STATUS_OK)
2144 2147 return (status);
2145 2148
2146 2149 if ((mrp.mrp_mask & MRP_RX_RINGS) == 0) {
2147 2150 *val_cnt = 0;
2148 2151 return (DLADM_STATUS_OK);
2149 2152 }
2150 2153 nrings = mrp.mrp_nrxrings;
2151 2154 *val_cnt = 1;
2152 2155 if (mrp.mrp_mask & MRP_RXRINGS_UNSPEC)
2153 2156 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2154 2157 else if (nrings == 0)
2155 2158 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2156 2159 else
2157 2160 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
2158 2161 return (DLADM_STATUS_OK);
2159 2162 }
2160 2163
2161 2164 /* ARGSUSED */
2162 2165 dladm_status_t
2163 2166 extract_rxrings(val_desc_t *vdp, uint_t cnt, void *arg)
2164 2167 {
2165 2168 mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
2166 2169
2167 2170 mrp->mrp_nrxrings = 0;
2168 2171 if (vdp->vd_val == RESET_VAL)
2169 2172 mrp->mrp_mask = MRP_RINGS_RESET;
2170 2173 else if (vdp->vd_val == UNSPEC_VAL)
2171 2174 mrp->mrp_mask = MRP_RXRINGS_UNSPEC;
2172 2175 else
2173 2176 mrp->mrp_nrxrings = vdp->vd_val;
2174 2177 mrp->mrp_mask |= MRP_RX_RINGS;
2175 2178
2176 2179 return (DLADM_STATUS_OK);
2177 2180 }
2178 2181
2179 2182 /* ARGSUSED */
2180 2183 static dladm_status_t
2181 2184 get_txrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2182 2185 char **prop_val, uint_t *val_cnt, datalink_media_t media,
2183 2186 uint_t flags, uint_t *perm_flags)
2184 2187 {
2185 2188 mac_resource_props_t mrp;
2186 2189 dladm_status_t status;
2187 2190 uint32_t nrings = 0;
2188 2191
2189 2192
2190 2193 /*
2191 2194 * Get the number of (effective-)rings from the resource property.
2192 2195 */
2193 2196 if (strcmp(pdp->pd_name, "txrings-effective") == 0) {
2194 2197 status = i_dladm_get_public_prop(handle, linkid,
2195 2198 "resource-effective", flags, perm_flags, &mrp,
2196 2199 sizeof (mrp));
2197 2200 } else {
2198 2201 /*
2199 2202 * Get the permissions from the "txrings" property.
2200 2203 */
2201 2204 status = i_dladm_get_public_prop(handle, linkid, "txrings",
2202 2205 flags, perm_flags, NULL, 0);
2203 2206 if (status != DLADM_STATUS_OK)
2204 2207 return (status);
2205 2208
2206 2209 /*
2207 2210 * Get the number of rings from the "resource" property.
2208 2211 */
2209 2212 status = i_dladm_get_public_prop(handle, linkid, "resource",
2210 2213 flags, NULL, &mrp, sizeof (mrp));
2211 2214 }
2212 2215
2213 2216 if (status != DLADM_STATUS_OK)
2214 2217 return (status);
2215 2218
2216 2219 if ((mrp.mrp_mask & MRP_TX_RINGS) == 0) {
2217 2220 *val_cnt = 0;
2218 2221 return (DLADM_STATUS_OK);
2219 2222 }
2220 2223 nrings = mrp.mrp_ntxrings;
2221 2224 *val_cnt = 1;
2222 2225 if (mrp.mrp_mask & MRP_TXRINGS_UNSPEC)
2223 2226 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2224 2227 else if (nrings == 0)
2225 2228 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2226 2229 else
2227 2230 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
2228 2231 return (DLADM_STATUS_OK);
2229 2232 }
2230 2233
2231 2234 /* ARGSUSED */
2232 2235 dladm_status_t
2233 2236 extract_txrings(val_desc_t *vdp, uint_t cnt, void *arg)
2234 2237 {
2235 2238 mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
2236 2239
2237 2240 mrp->mrp_ntxrings = 0;
2238 2241 if (vdp->vd_val == RESET_VAL)
2239 2242 mrp->mrp_mask = MRP_RINGS_RESET;
2240 2243 else if (vdp->vd_val == UNSPEC_VAL)
2241 2244 mrp->mrp_mask = MRP_TXRINGS_UNSPEC;
2242 2245 else
2243 2246 mrp->mrp_ntxrings = vdp->vd_val;
2244 2247 mrp->mrp_mask |= MRP_TX_RINGS;
2245 2248
2246 2249 return (DLADM_STATUS_OK);
2247 2250 }
2248 2251
2249 2252 /* ARGSUSED */
2250 2253 static dladm_status_t
2251 2254 get_cntavail(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2252 2255 char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
2253 2256 uint_t *perm_flags)
2254 2257 {
2255 2258 if (flags & DLD_PROP_DEFAULT)
2256 2259 return (DLADM_STATUS_NOTDEFINED);
2257 2260
2258 2261 return (get_uint32(handle, pdp, linkid, prop_val, val_cnt, media,
2259 2262 flags, perm_flags));
2260 2263 }
2261 2264
2262 2265 /* ARGSUSED */
2263 2266 static dladm_status_t
2264 2267 set_resource(dladm_handle_t handle, prop_desc_t *pdp,
2265 2268 datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
2266 2269 uint_t flags, datalink_media_t media)
2267 2270 {
2268 2271 mac_resource_props_t mrp;
2269 2272 dladm_status_t status = DLADM_STATUS_OK;
2270 2273 dld_ioc_macprop_t *dip;
2271 2274 int i;
2272 2275
2273 2276 bzero(&mrp, sizeof (mac_resource_props_t));
2274 2277 dip = i_dladm_buf_alloc_by_name(0, linkid, "resource",
2275 2278 flags, &status);
2276 2279
2277 2280 if (dip == NULL)
2278 2281 return (status);
2279 2282
2280 2283 for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
2281 2284 resource_prop_t *rp = &rsrc_prop_table[i];
2282 2285
2283 2286 if (strcmp(pdp->pd_name, rp->rp_name) != 0)
2284 2287 continue;
2285 2288
2286 2289 status = rp->rp_extract(vdp, val_cnt, &mrp);
2287 2290 if (status != DLADM_STATUS_OK)
2288 2291 goto done;
2289 2292
2290 2293 break;
2291 2294 }
2292 2295
2293 2296 (void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
2294 2297 status = i_dladm_macprop(handle, dip, B_TRUE);
2295 2298
2296 2299 done:
2297 2300 free(dip);
2298 2301 return (status);
2299 2302 }
2300 2303
2301 2304 /* ARGSUSED */
2302 2305 static dladm_status_t
2303 2306 get_protection(dladm_handle_t handle, prop_desc_t *pdp,
2304 2307 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2305 2308 datalink_media_t media, uint_t flags, uint_t *perm_flags)
2306 2309 {
2307 2310 mac_resource_props_t mrp;
2308 2311 mac_protect_t *p;
2309 2312 dladm_status_t status;
2310 2313 uint32_t i, cnt = 0, setbits[32];
2311 2314
2312 2315 status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2313 2316 perm_flags, &mrp, sizeof (mrp));
2314 2317 if (status != DLADM_STATUS_OK)
2315 2318 return (status);
2316 2319
2317 2320 p = &mrp.mrp_protect;
2318 2321 if ((mrp.mrp_mask & MRP_PROTECT) == 0) {
2319 2322 *val_cnt = 0;
2320 2323 return (DLADM_STATUS_OK);
2321 2324 }
2322 2325 dladm_find_setbits32(p->mp_types, setbits, &cnt);
2323 2326 if (cnt > *val_cnt)
2324 2327 return (DLADM_STATUS_BADVALCNT);
2325 2328
2326 2329 for (i = 0; i < cnt; i++)
2327 2330 (void) dladm_protect2str(setbits[i], prop_val[i]);
2328 2331
2329 2332 *val_cnt = cnt;
2330 2333 return (DLADM_STATUS_OK);
2331 2334 }
2332 2335
2333 2336 /* ARGSUSED */
2334 2337 static dladm_status_t
2335 2338 get_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2336 2339 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2337 2340 datalink_media_t media, uint_t flags, uint_t *perm_flags)
2338 2341 {
2339 2342 mac_resource_props_t mrp;
2340 2343 mac_protect_t *p;
2341 2344 dladm_status_t status;
2342 2345 int i;
2343 2346
2344 2347 status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2345 2348 perm_flags, &mrp, sizeof (mrp));
2346 2349 if (status != DLADM_STATUS_OK)
2347 2350 return (status);
2348 2351
2349 2352 p = &mrp.mrp_protect;
2350 2353 if (p->mp_ipaddrcnt == 0) {
2351 2354 *val_cnt = 0;
2352 2355 return (DLADM_STATUS_OK);
2353 2356 }
2354 2357 if (p->mp_ipaddrcnt > *val_cnt)
2355 2358 return (DLADM_STATUS_BADVALCNT);
2356 2359
2357 2360 for (i = 0; i < p->mp_ipaddrcnt; i++) {
2358 2361 int len;
2359 2362 if (p->mp_ipaddrs[i].ip_version == IPV4_VERSION) {
2360 2363 ipaddr_t v4addr;
2361 2364
2362 2365 v4addr = V4_PART_OF_V6(p->mp_ipaddrs[i].ip_addr);
2363 2366 (void) dladm_ipv4addr2str(&v4addr, prop_val[i]);
2364 2367 } else {
2365 2368 (void) dladm_ipv6addr2str(&p->mp_ipaddrs[i].ip_addr,
2366 2369 prop_val[i]);
2367 2370 }
2368 2371 len = strlen(prop_val[i]);
2369 2372 (void) sprintf(prop_val[i] + len, "/%d",
2370 2373 p->mp_ipaddrs[i].ip_netmask);
2371 2374 }
2372 2375 *val_cnt = p->mp_ipaddrcnt;
2373 2376 return (DLADM_STATUS_OK);
2374 2377 }
2375 2378
2376 2379 dladm_status_t
2377 2380 extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
2378 2381 {
2379 2382 mac_resource_props_t *mrp = arg;
2380 2383 uint32_t types = 0;
2381 2384 int i;
2382 2385
2383 2386 for (i = 0; i < cnt; i++)
2384 2387 types |= (uint32_t)vdp[i].vd_val;
2385 2388
2386 2389 mrp->mrp_protect.mp_types = types;
2387 2390 mrp->mrp_mask |= MRP_PROTECT;
2388 2391 return (DLADM_STATUS_OK);
2389 2392 }
2390 2393
2391 2394 dladm_status_t
2392 2395 extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
2393 2396 {
2394 2397 mac_resource_props_t *mrp = arg;
2395 2398 mac_protect_t *p = &mrp->mrp_protect;
2396 2399 int i;
2397 2400
2398 2401 if (vdp->vd_val == 0) {
2399 2402 cnt = (uint_t)-1;
2400 2403 } else {
2401 2404 for (i = 0; i < cnt; i++) {
2402 2405 bcopy((void *)vdp[i].vd_val, &p->mp_ipaddrs[i],
2403 2406 sizeof (mac_ipaddr_t));
2404 2407 }
2405 2408 }
2406 2409 p->mp_ipaddrcnt = cnt;
2407 2410 mrp->mrp_mask |= MRP_PROTECT;
2408 2411 return (DLADM_STATUS_OK);
2409 2412 }
2410 2413
2411 2414 static dladm_status_t
2412 2415 check_single_ip(char *buf, mac_ipaddr_t *addr)
2413 2416 {
2414 2417 dladm_status_t status;
2415 2418 ipaddr_t v4addr;
2416 2419 in6_addr_t v6addr;
2417 2420 boolean_t isv4 = B_TRUE;
2418 2421 char *p;
2419 2422 uint32_t mask = 0;
2420 2423
2421 2424 /*
2422 2425 * If the IP address is in CIDR format, parse the bits component
2423 2426 * seperately. An address in this style will be used to indicate an
2424 2427 * entire subnet, so it must be a network number with no host address.
2425 2428 */
2426 2429 if ((p = strchr(buf, '/')) != NULL) {
2427 2430 char *end = NULL;
2428 2431
2429 2432 *p++ = '\0';
2430 2433 if (!isdigit(*p))
2431 2434 return (DLADM_STATUS_INVALID_IP);
2432 2435 mask = strtol(p, &end, 10);
2433 2436 if (end != NULL && *end != '\0')
2434 2437 return (DLADM_STATUS_INVALID_IP);
2435 2438 if (mask > 128|| mask < 1)
2436 2439 return (DLADM_STATUS_INVALID_IP);
2437 2440 }
2438 2441
2439 2442 status = dladm_str2ipv4addr(buf, &v4addr);
2440 2443 if (status == DLADM_STATUS_INVALID_IP) {
2441 2444 status = dladm_str2ipv6addr(buf, &v6addr);
2442 2445 if (status == DLADM_STATUS_OK)
2443 2446 isv4 = B_FALSE;
2444 2447 }
2445 2448 if (status != DLADM_STATUS_OK)
2446 2449 return (status);
2447 2450
2448 2451 if (isv4) {
2449 2452 if (v4addr == INADDR_ANY)
2450 2453 return (DLADM_STATUS_INVALID_IP);
2451 2454
2452 2455 IN6_IPADDR_TO_V4MAPPED(v4addr, &addr->ip_addr);
2453 2456 addr->ip_version = IPV4_VERSION;
2454 2457 if (p != NULL) {
2455 2458 uint32_t smask;
2456 2459
2457 2460 /*
2458 2461 * Validate the netmask is in the proper range for v4
2459 2462 */
2460 2463 if (mask > 32 || mask < 1)
2461 2464 return (DLADM_STATUS_INVALID_IP);
2462 2465
2463 2466 /*
2464 2467 * We have a CIDR style address, confirm that only the
2465 2468 * network number is set.
2466 2469 */
2467 2470 smask = 0xFFFFFFFFu << (32 - mask);
2468 2471 if (htonl(v4addr) & ~smask)
2469 2472 return (DLADM_STATUS_INVALID_IP);
2470 2473 } else {
2471 2474 mask = 32;
2472 2475 }
2473 2476 addr->ip_netmask = mask;
2474 2477 } else {
2475 2478 if (IN6_IS_ADDR_UNSPECIFIED(&v6addr))
2476 2479 return (DLADM_STATUS_INVALID_IP);
2477 2480
2478 2481 if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr))
2479 2482 return (DLADM_STATUS_INVALID_IP);
2480 2483
2481 2484 if (p != NULL) {
2482 2485 int i, off, high;
2483 2486
2484 2487 /*
2485 2488 * Note that the address in our buffer is stored in
2486 2489 * network byte order.
2487 2490 */
2488 2491 off = 0;
2489 2492 for (i = 3; i >= 0; i--) {
2490 2493 high = ffsl(ntohl(v6addr._S6_un._S6_u32[i]));
2491 2494 if (high != 0)
2492 2495 break;
2493 2496 off += 32;
2494 2497 }
2495 2498 off += high;
2496 2499 if (128 - off >= mask)
2497 2500 return (DLADM_STATUS_INVALID_IP);
2498 2501 } else {
2499 2502 mask = 128;
2500 2503 }
2501 2504
2502 2505 addr->ip_addr = v6addr;
2503 2506 addr->ip_version = IPV6_VERSION;
2504 2507 addr->ip_netmask = mask;
2505 2508 }
2506 2509 return (DLADM_STATUS_OK);
2507 2510 }
2508 2511
2509 2512 /* ARGSUSED */
2510 2513 static dladm_status_t
2511 2514 check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2512 2515 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2513 2516 val_desc_t **vdpp, datalink_media_t media)
2514 2517 {
2515 2518 dladm_status_t status;
2516 2519 mac_ipaddr_t *addr;
2517 2520 int i;
2518 2521 uint_t val_cnt = *val_cntp;
2519 2522 val_desc_t *vdp = *vdpp;
2520 2523
2521 2524 if (val_cnt > MPT_MAXIPADDR)
2522 2525 return (DLADM_STATUS_BADVALCNT);
2523 2526
2524 2527 for (i = 0; i < val_cnt; i++) {
2525 2528 if ((addr = calloc(1, sizeof (mac_ipaddr_t))) == NULL) {
2526 2529 status = DLADM_STATUS_NOMEM;
2527 2530 goto fail;
2528 2531 }
2529 2532 vdp[i].vd_val = (uintptr_t)addr;
2530 2533
2531 2534 status = check_single_ip(prop_val[i], addr);
2532 2535 if (status != DLADM_STATUS_OK)
2533 2536 goto fail;
2534 2537 }
2535 2538 return (DLADM_STATUS_OK);
2536 2539
2537 2540 fail:
2538 2541 for (i = 0; i < val_cnt; i++) {
2539 2542 free((void *)vdp[i].vd_val);
2540 2543 vdp[i].vd_val = NULL;
2541 2544 }
2542 2545 return (status);
2543 2546 }
2544 2547
2545 2548 static void
2546 2549 dladm_cid2str(mac_dhcpcid_t *cid, char *buf)
2547 2550 {
2548 2551 char tmp_buf[DLADM_STRSIZE];
2549 2552 uint_t hexlen;
2550 2553
2551 2554 switch (cid->dc_form) {
2552 2555 case CIDFORM_TYPED: {
2553 2556 uint16_t duidtype, hwtype;
2554 2557 uint32_t timestamp, ennum;
2555 2558 char *lladdr;
2556 2559
2557 2560 if (cid->dc_len < sizeof (duidtype))
2558 2561 goto fail;
2559 2562
2560 2563 bcopy(cid->dc_id, &duidtype, sizeof (duidtype));
2561 2564 duidtype = ntohs(duidtype);
2562 2565 switch (duidtype) {
2563 2566 case DHCPV6_DUID_LLT: {
2564 2567 duid_llt_t llt;
2565 2568
2566 2569 if (cid->dc_len < sizeof (llt))
2567 2570 goto fail;
2568 2571
2569 2572 bcopy(cid->dc_id, &llt, sizeof (llt));
2570 2573 hwtype = ntohs(llt.dllt_hwtype);
2571 2574 timestamp = ntohl(llt.dllt_time);
2572 2575 lladdr = _link_ntoa(cid->dc_id + sizeof (llt),
2573 2576 NULL, cid->dc_len - sizeof (llt), IFT_OTHER);
2574 2577 if (lladdr == NULL)
2575 2578 goto fail;
2576 2579
2577 2580 (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%d.%s",
2578 2581 duidtype, hwtype, timestamp, lladdr);
2579 2582 free(lladdr);
2580 2583 break;
2581 2584 }
2582 2585 case DHCPV6_DUID_EN: {
2583 2586 duid_en_t en;
2584 2587
2585 2588 if (cid->dc_len < sizeof (en))
2586 2589 goto fail;
2587 2590
2588 2591 bcopy(cid->dc_id, &en, sizeof (en));
2589 2592 ennum = DHCPV6_GET_ENTNUM(&en);
2590 2593 hexlen = sizeof (tmp_buf);
2591 2594 if (octet_to_hexascii(cid->dc_id + sizeof (en),
2592 2595 cid->dc_len - sizeof (en), tmp_buf, &hexlen) != 0)
2593 2596 goto fail;
2594 2597
2595 2598 (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2596 2599 duidtype, ennum, tmp_buf);
2597 2600 break;
2598 2601 }
2599 2602 case DHCPV6_DUID_LL: {
2600 2603 duid_ll_t ll;
2601 2604
2602 2605 if (cid->dc_len < sizeof (ll))
2603 2606 goto fail;
2604 2607
2605 2608 bcopy(cid->dc_id, &ll, sizeof (ll));
2606 2609 hwtype = ntohs(ll.dll_hwtype);
2607 2610 lladdr = _link_ntoa(cid->dc_id + sizeof (ll),
2608 2611 NULL, cid->dc_len - sizeof (ll), IFT_OTHER);
2609 2612 if (lladdr == NULL)
2610 2613 goto fail;
2611 2614
2612 2615 (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2613 2616 duidtype, hwtype, lladdr);
2614 2617 free(lladdr);
2615 2618 break;
2616 2619 }
2617 2620 default: {
2618 2621 hexlen = sizeof (tmp_buf);
2619 2622 if (octet_to_hexascii(cid->dc_id + sizeof (duidtype),
2620 2623 cid->dc_len - sizeof (duidtype),
2621 2624 tmp_buf, &hexlen) != 0)
2622 2625 goto fail;
2623 2626
2624 2627 (void) snprintf(buf, DLADM_STRSIZE, "%d.%s",
2625 2628 duidtype, tmp_buf);
2626 2629 }
2627 2630 }
2628 2631 break;
2629 2632 }
2630 2633 case CIDFORM_HEX: {
2631 2634 hexlen = sizeof (tmp_buf);
2632 2635 if (octet_to_hexascii(cid->dc_id, cid->dc_len,
2633 2636 tmp_buf, &hexlen) != 0)
2634 2637 goto fail;
2635 2638
2636 2639 (void) snprintf(buf, DLADM_STRSIZE, "0x%s", tmp_buf);
2637 2640 break;
2638 2641 }
2639 2642 case CIDFORM_STR: {
2640 2643 int i;
2641 2644
2642 2645 for (i = 0; i < cid->dc_len; i++) {
2643 2646 if (!isprint(cid->dc_id[i]))
2644 2647 goto fail;
2645 2648 }
2646 2649 (void) snprintf(buf, DLADM_STRSIZE, "%s", cid->dc_id);
2647 2650 break;
2648 2651 }
2649 2652 default:
2650 2653 goto fail;
2651 2654 }
2652 2655 return;
2653 2656
2654 2657 fail:
2655 2658 (void) snprintf(buf, DLADM_STRSIZE, "<unknown>");
2656 2659 }
2657 2660
2658 2661 static dladm_status_t
2659 2662 dladm_str2cid(char *buf, mac_dhcpcid_t *cid)
2660 2663 {
2661 2664 char *ptr = buf;
2662 2665 char tmp_buf[DLADM_STRSIZE];
2663 2666 uint_t hexlen, cidlen;
2664 2667
2665 2668 bzero(cid, sizeof (*cid));
2666 2669 if (isdigit(*ptr) &&
2667 2670 ptr[strspn(ptr, "0123456789")] == '.') {
2668 2671 char *cp;
2669 2672 ulong_t duidtype;
2670 2673 ulong_t subtype;
2671 2674 ulong_t timestamp;
2672 2675 uchar_t *lladdr;
2673 2676 int addrlen;
2674 2677
2675 2678 errno = 0;
2676 2679 duidtype = strtoul(ptr, &cp, 0);
2677 2680 if (ptr == cp || errno != 0 || *cp != '.' ||
2678 2681 duidtype > USHRT_MAX)
2679 2682 return (DLADM_STATUS_BADARG);
2680 2683 ptr = cp + 1;
2681 2684
2682 2685 if (duidtype != 0 && duidtype <= DHCPV6_DUID_LL) {
2683 2686 errno = 0;
2684 2687 subtype = strtoul(ptr, &cp, 0);
2685 2688 if (ptr == cp || errno != 0 || *cp != '.')
2686 2689 return (DLADM_STATUS_BADARG);
2687 2690 ptr = cp + 1;
2688 2691 }
2689 2692 switch (duidtype) {
2690 2693 case DHCPV6_DUID_LLT: {
2691 2694 duid_llt_t llt;
2692 2695
2693 2696 errno = 0;
2694 2697 timestamp = strtoul(ptr, &cp, 0);
2695 2698 if (ptr == cp || errno != 0 || *cp != '.')
2696 2699 return (DLADM_STATUS_BADARG);
2697 2700
2698 2701 ptr = cp + 1;
2699 2702 lladdr = _link_aton(ptr, &addrlen);
2700 2703 if (lladdr == NULL)
2701 2704 return (DLADM_STATUS_BADARG);
2702 2705
2703 2706 cidlen = sizeof (llt) + addrlen;
2704 2707 if (cidlen > sizeof (cid->dc_id)) {
2705 2708 free(lladdr);
2706 2709 return (DLADM_STATUS_TOOSMALL);
2707 2710 }
2708 2711 llt.dllt_dutype = htons(duidtype);
2709 2712 llt.dllt_hwtype = htons(subtype);
2710 2713 llt.dllt_time = htonl(timestamp);
2711 2714 bcopy(&llt, cid->dc_id, sizeof (llt));
2712 2715 bcopy(lladdr, cid->dc_id + sizeof (llt), addrlen);
2713 2716 free(lladdr);
2714 2717 break;
2715 2718 }
2716 2719 case DHCPV6_DUID_LL: {
2717 2720 duid_ll_t ll;
2718 2721
2719 2722 lladdr = _link_aton(ptr, &addrlen);
2720 2723 if (lladdr == NULL)
2721 2724 return (DLADM_STATUS_BADARG);
2722 2725
2723 2726 cidlen = sizeof (ll) + addrlen;
2724 2727 if (cidlen > sizeof (cid->dc_id)) {
2725 2728 free(lladdr);
2726 2729 return (DLADM_STATUS_TOOSMALL);
2727 2730 }
2728 2731 ll.dll_dutype = htons(duidtype);
2729 2732 ll.dll_hwtype = htons(subtype);
2730 2733 bcopy(&ll, cid->dc_id, sizeof (ll));
2731 2734 bcopy(lladdr, cid->dc_id + sizeof (ll), addrlen);
2732 2735 free(lladdr);
2733 2736 break;
2734 2737 }
2735 2738 default: {
2736 2739 hexlen = sizeof (tmp_buf);
2737 2740 if (hexascii_to_octet(ptr, strlen(ptr),
2738 2741 tmp_buf, &hexlen) != 0)
2739 2742 return (DLADM_STATUS_BADARG);
2740 2743
2741 2744 if (duidtype == DHCPV6_DUID_EN) {
2742 2745 duid_en_t en;
2743 2746
2744 2747 en.den_dutype = htons(duidtype);
2745 2748 DHCPV6_SET_ENTNUM(&en, subtype);
2746 2749
2747 2750 cidlen = sizeof (en) + hexlen;
2748 2751 if (cidlen > sizeof (cid->dc_id))
2749 2752 return (DLADM_STATUS_TOOSMALL);
2750 2753
2751 2754 bcopy(&en, cid->dc_id, sizeof (en));
2752 2755 bcopy(tmp_buf, cid->dc_id + sizeof (en),
2753 2756 hexlen);
2754 2757 } else {
2755 2758 uint16_t dutype = htons(duidtype);
2756 2759
2757 2760 cidlen = sizeof (dutype) + hexlen;
2758 2761 if (cidlen > sizeof (cid->dc_id))
2759 2762 return (DLADM_STATUS_TOOSMALL);
2760 2763
2761 2764 bcopy(&dutype, cid->dc_id, sizeof (dutype));
2762 2765 bcopy(tmp_buf, cid->dc_id + sizeof (dutype),
2763 2766 hexlen);
2764 2767 }
2765 2768 break;
2766 2769 }
2767 2770 }
2768 2771 cid->dc_form = CIDFORM_TYPED;
2769 2772 } else if (strncasecmp("0x", ptr, 2) == 0 && ptr[2] != '\0') {
2770 2773 ptr += 2;
2771 2774 hexlen = sizeof (tmp_buf);
2772 2775 if (hexascii_to_octet(ptr, strlen(ptr), tmp_buf,
2773 2776 &hexlen) != 0) {
2774 2777 return (DLADM_STATUS_BADARG);
2775 2778 }
2776 2779 cidlen = hexlen;
2777 2780 if (cidlen > sizeof (cid->dc_id))
2778 2781 return (DLADM_STATUS_TOOSMALL);
2779 2782
2780 2783 bcopy(tmp_buf, cid->dc_id, cidlen);
2781 2784 cid->dc_form = CIDFORM_HEX;
2782 2785 } else {
2783 2786 cidlen = strlen(ptr);
2784 2787 if (cidlen > sizeof (cid->dc_id))
2785 2788 return (DLADM_STATUS_TOOSMALL);
2786 2789
2787 2790 bcopy(ptr, cid->dc_id, cidlen);
2788 2791 cid->dc_form = CIDFORM_STR;
2789 2792 }
2790 2793 cid->dc_len = cidlen;
2791 2794 return (DLADM_STATUS_OK);
2792 2795 }
2793 2796
2794 2797 /* ARGSUSED */
2795 2798 static dladm_status_t
2796 2799 get_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2797 2800 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2798 2801 datalink_media_t media, uint_t flags, uint_t *perm_flags)
2799 2802 {
2800 2803 mac_resource_props_t mrp;
2801 2804 mac_protect_t *p;
2802 2805 dladm_status_t status;
2803 2806 int i;
2804 2807
2805 2808 status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2806 2809 perm_flags, &mrp, sizeof (mrp));
2807 2810 if (status != DLADM_STATUS_OK)
2808 2811 return (status);
2809 2812
2810 2813 p = &mrp.mrp_protect;
2811 2814 if (p->mp_cidcnt == 0) {
2812 2815 *val_cnt = 0;
2813 2816 return (DLADM_STATUS_OK);
2814 2817 }
2815 2818 if (p->mp_cidcnt > *val_cnt)
2816 2819 return (DLADM_STATUS_BADVALCNT);
2817 2820
2818 2821 for (i = 0; i < p->mp_cidcnt; i++) {
2819 2822 mac_dhcpcid_t *cid = &p->mp_cids[i];
2820 2823
2821 2824 dladm_cid2str(cid, prop_val[i]);
2822 2825 }
2823 2826 *val_cnt = p->mp_cidcnt;
2824 2827 return (DLADM_STATUS_OK);
2825 2828 }
2826 2829
2827 2830 dladm_status_t
2828 2831 extract_allowedcids(val_desc_t *vdp, uint_t cnt, void *arg)
2829 2832 {
2830 2833 mac_resource_props_t *mrp = arg;
2831 2834 mac_protect_t *p = &mrp->mrp_protect;
2832 2835 int i;
2833 2836
2834 2837 if (vdp->vd_val == 0) {
2835 2838 cnt = (uint_t)-1;
2836 2839 } else {
2837 2840 for (i = 0; i < cnt; i++) {
2838 2841 bcopy((void *)vdp[i].vd_val, &p->mp_cids[i],
2839 2842 sizeof (mac_dhcpcid_t));
2840 2843 }
2841 2844 }
2842 2845 p->mp_cidcnt = cnt;
2843 2846 mrp->mrp_mask |= MRP_PROTECT;
2844 2847 return (DLADM_STATUS_OK);
2845 2848 }
2846 2849
2847 2850 /* ARGSUSED */
2848 2851 static dladm_status_t
2849 2852 check_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2850 2853 datalink_id_t linkid, char **prop_val, uint_t *val_cntp,
2851 2854 uint_t flags, val_desc_t **vdpp, datalink_media_t media)
2852 2855 {
2853 2856 dladm_status_t status;
2854 2857 mac_dhcpcid_t *cid;
2855 2858 int i;
2856 2859 uint_t val_cnt = *val_cntp;
2857 2860 val_desc_t *vdp = *vdpp;
2858 2861
2859 2862 if (val_cnt > MPT_MAXCID)
2860 2863 return (DLADM_STATUS_BADVALCNT);
2861 2864
2862 2865 for (i = 0; i < val_cnt; i++) {
2863 2866 if ((cid = calloc(1, sizeof (mac_dhcpcid_t))) == NULL) {
2864 2867 status = DLADM_STATUS_NOMEM;
2865 2868 goto fail;
2866 2869 }
2867 2870 vdp[i].vd_val = (uintptr_t)cid;
2868 2871
2869 2872 status = dladm_str2cid(prop_val[i], cid);
2870 2873 if (status != DLADM_STATUS_OK)
2871 2874 goto fail;
2872 2875 }
2873 2876 return (DLADM_STATUS_OK);
2874 2877
2875 2878 fail:
2876 2879 for (i = 0; i < val_cnt; i++) {
2877 2880 free((void *)vdp[i].vd_val);
2878 2881 vdp[i].vd_val = NULL;
2879 2882 }
2880 2883 return (status);
2881 2884 }
2882 2885
2883 2886 /* ARGSUSED */
2884 2887 static dladm_status_t
2885 2888 get_secondary_macs(dladm_handle_t handle, prop_desc_t *pdp,
2886 2889 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2887 2890 datalink_media_t media, uint_t flags, uint_t *perm_flags)
2888 2891 {
2889 2892 mac_secondary_addr_t sa;
2890 2893 dladm_status_t status;
2891 2894 int i;
2892 2895
2893 2896 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
2894 2897 perm_flags, &sa, sizeof (sa));
2895 2898 if (status != DLADM_STATUS_OK)
2896 2899 return (status);
2897 2900
2898 2901 if (sa.ms_addrcnt > *val_cnt)
2899 2902 return (DLADM_STATUS_BADVALCNT);
2900 2903
2901 2904 for (i = 0; i < sa.ms_addrcnt; i++) {
2902 2905 if (dladm_aggr_macaddr2str(
2903 2906 (const unsigned char *)&sa.ms_addrs[i], prop_val[i]) ==
2904 2907 NULL) {
2905 2908 *val_cnt = i;
2906 2909 return (DLADM_STATUS_NOMEM);
2907 2910 }
2908 2911 }
2909 2912 *val_cnt = sa.ms_addrcnt;
2910 2913 return (DLADM_STATUS_OK);
2911 2914 }
2912 2915
2913 2916 /* ARGSUSED */
2914 2917 static dladm_status_t
2915 2918 check_secondary_macs(dladm_handle_t handle, prop_desc_t *pdp,
2916 2919 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2917 2920 val_desc_t **vdpp, datalink_media_t media)
2918 2921 {
2919 2922 dladm_status_t status;
2920 2923 uchar_t *addr;
2921 2924 uint_t len = 0;
2922 2925 int i;
2923 2926 uint_t val_cnt = *val_cntp;
2924 2927 val_desc_t *vdp = *vdpp;
2925 2928
2926 2929 if (val_cnt >= MPT_MAXMACADDR)
2927 2930 return (DLADM_STATUS_BADVALCNT);
2928 2931
2929 2932 for (i = 0; i < val_cnt; i++) {
2930 2933 addr = _link_aton(prop_val[i], (int *)&len);
2931 2934 if (addr == NULL) {
2932 2935 if (len == (uint_t)-1)
2933 2936 status = DLADM_STATUS_MACADDRINVAL;
2934 2937 else
2935 2938 status = DLADM_STATUS_NOMEM;
2936 2939 goto fail;
2937 2940 }
2938 2941
2939 2942 vdp[i].vd_val = (uintptr_t)addr;
2940 2943 }
2941 2944 return (DLADM_STATUS_OK);
2942 2945
2943 2946 fail:
2944 2947 for (i = 0; i < val_cnt; i++) {
2945 2948 free((void *)vdp[i].vd_val);
2946 2949 vdp[i].vd_val = NULL;
2947 2950 }
2948 2951 return (status);
2949 2952 }
2950 2953
2951 2954 /* ARGSUSED */
2952 2955 static dladm_status_t
2953 2956 set_secondary_macs(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
2954 2957 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
2955 2958 {
2956 2959 dladm_status_t status;
2957 2960 dld_ioc_macprop_t *dip;
2958 2961 int i;
2959 2962 mac_secondary_addr_t msa;
2960 2963
2961 2964 dip = i_dladm_buf_alloc_by_name(0, linkid, "secondary-macs", 0,
2962 2965 &status);
2963 2966 if (dip == NULL)
2964 2967 return (status);
2965 2968
2966 2969 if (vdp->vd_val == 0) {
2967 2970 val_cnt = (uint_t)-1;
2968 2971 } else {
2969 2972 for (i = 0; i < val_cnt; i++) {
2970 2973 bcopy((void *)vdp[i].vd_val, msa.ms_addrs[i],
2971 2974 MAXMACADDRLEN);
2972 2975 }
2973 2976 }
2974 2977 msa.ms_addrcnt = val_cnt;
2975 2978 bcopy(&msa, dip->pr_val, dip->pr_valsize);
2976 2979
2977 2980 status = i_dladm_macprop(handle, dip, B_TRUE);
2978 2981
2979 2982 free(dip);
2980 2983 return (status);
2981 2984 }
2982 2985
2983 2986 /* ARGSUSED */
2984 2987 static dladm_status_t
2985 2988 get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2986 2989 char **prop_val, uint_t *val_cnt, datalink_media_t media,
2987 2990 uint_t flags, uint_t *perm_flags)
2988 2991 {
2989 2992 struct dlautopush dlap;
2990 2993 int i, len;
2991 2994 dladm_status_t status;
2992 2995
2993 2996 if (flags & DLD_PROP_DEFAULT)
2994 2997 return (DLADM_STATUS_NOTDEFINED);
2995 2998
2996 2999 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
2997 3000 perm_flags, &dlap, sizeof (dlap));
2998 3001 if (status != DLADM_STATUS_OK)
2999 3002 return (status);
3000 3003
3001 3004 if (dlap.dap_npush == 0) {
3002 3005 *val_cnt = 0;
3003 3006 return (DLADM_STATUS_OK);
3004 3007 }
3005 3008 for (i = 0, len = 0; i < dlap.dap_npush; i++) {
3006 3009 if (i != 0) {
3007 3010 (void) snprintf(*prop_val + len,
3008 3011 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
3009 3012 len += 1;
3010 3013 }
3011 3014 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
3012 3015 "%s", dlap.dap_aplist[i]);
3013 3016 len += strlen(dlap.dap_aplist[i]);
3014 3017 if (dlap.dap_anchor - 1 == i) {
3015 3018 (void) snprintf(*prop_val + len,
3016 3019 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
3017 3020 AP_ANCHOR);
3018 3021 len += (strlen(AP_ANCHOR) + 1);
3019 3022 }
3020 3023 }
3021 3024 *val_cnt = 1;
3022 3025 return (DLADM_STATUS_OK);
3023 3026 }
3024 3027
3025 3028 /*
3026 3029 * Add the specified module to the dlautopush structure; returns a
3027 3030 * DLADM_STATUS_* code.
3028 3031 */
3029 3032 dladm_status_t
3030 3033 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
3031 3034 {
3032 3035 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
3033 3036 return (DLADM_STATUS_BADVAL);
3034 3037
3035 3038 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
3036 3039 /*
3037 3040 * We don't allow multiple anchors, and the anchor must
3038 3041 * be after at least one module.
3039 3042 */
3040 3043 if (dlap->dap_anchor != 0)
3041 3044 return (DLADM_STATUS_BADVAL);
3042 3045 if (dlap->dap_npush == 0)
3043 3046 return (DLADM_STATUS_BADVAL);
3044 3047
3045 3048 dlap->dap_anchor = dlap->dap_npush;
3046 3049 return (DLADM_STATUS_OK);
3047 3050 }
3048 3051 if (dlap->dap_npush >= MAXAPUSH)
3049 3052 return (DLADM_STATUS_BADVALCNT);
3050 3053
3051 3054 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
3052 3055 FMNAMESZ + 1);
3053 3056
3054 3057 return (DLADM_STATUS_OK);
3055 3058 }
3056 3059
3057 3060 /*
3058 3061 * Currently, both '.' and ' '(space) can be used as the delimiters between
3059 3062 * autopush modules. The former is used in dladm set-linkprop, and the
3060 3063 * latter is used in the autopush(1M) file.
3061 3064 */
3062 3065 /* ARGSUSED */
3063 3066 static dladm_status_t
3064 3067 check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3065 3068 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3066 3069 datalink_media_t media)
3067 3070 {
3068 3071 char *module;
3069 3072 struct dlautopush *dlap;
3070 3073 dladm_status_t status;
3071 3074 char val[DLADM_PROP_VAL_MAX];
3072 3075 char delimiters[4];
3073 3076 uint_t val_cnt = *val_cntp;
3074 3077 val_desc_t *vdp = *vdpp;
3075 3078
3076 3079 if (val_cnt != 1)
3077 3080 return (DLADM_STATUS_BADVALCNT);
3078 3081
3079 3082 if (prop_val != NULL) {
3080 3083 dlap = malloc(sizeof (struct dlautopush));
3081 3084 if (dlap == NULL)
3082 3085 return (DLADM_STATUS_NOMEM);
3083 3086
3084 3087 (void) memset(dlap, 0, sizeof (struct dlautopush));
3085 3088 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
3086 3089 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
3087 3090 module = strtok(val, delimiters);
3088 3091 while (module != NULL) {
3089 3092 status = i_dladm_add_ap_module(module, dlap);
3090 3093 if (status != DLADM_STATUS_OK)
3091 3094 return (status);
3092 3095 module = strtok(NULL, delimiters);
3093 3096 }
3094 3097
3095 3098 vdp->vd_val = (uintptr_t)dlap;
3096 3099 } else {
3097 3100 vdp->vd_val = 0;
3098 3101 }
3099 3102 return (DLADM_STATUS_OK);
3100 3103 }
3101 3104
3102 3105 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3103 3106
3104 3107 /* ARGSUSED */
3105 3108 static dladm_status_t
3106 3109 get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
3107 3110 datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
3108 3111 uint_t *perm_flags)
3109 3112 {
3110 3113 wl_rates_t *wrp;
3111 3114 uint_t i;
3112 3115 dladm_status_t status = DLADM_STATUS_OK;
3113 3116
3114 3117 wrp = malloc(WLDP_BUFSIZE);
3115 3118 if (wrp == NULL)
3116 3119 return (DLADM_STATUS_NOMEM);
3117 3120
3118 3121 status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
3119 3122 B_FALSE);
3120 3123 if (status != DLADM_STATUS_OK)
3121 3124 goto done;
3122 3125
3123 3126 if (wrp->wl_rates_num > *val_cnt) {
3124 3127 status = DLADM_STATUS_TOOSMALL;
3125 3128 goto done;
3126 3129 }
3127 3130
3128 3131 if (wrp->wl_rates_rates[0] == 0) {
3129 3132 prop_val[0][0] = '\0';
3130 3133 *val_cnt = 1;
3131 3134 goto done;
3132 3135 }
3133 3136
3134 3137 for (i = 0; i < wrp->wl_rates_num; i++) {
3135 3138 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
3136 3139 wrp->wl_rates_rates[i] % 2,
3137 3140 (float)wrp->wl_rates_rates[i] / 2);
3138 3141 }
3139 3142 *val_cnt = wrp->wl_rates_num;
3140 3143 *perm_flags = MAC_PROP_PERM_RW;
3141 3144
3142 3145 done:
3143 3146 free(wrp);
3144 3147 return (status);
3145 3148 }
3146 3149
3147 3150 static dladm_status_t
3148 3151 get_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3149 3152 char **prop_val, uint_t *val_cnt, datalink_media_t media,
3150 3153 uint_t flags, uint_t *perm_flags)
3151 3154 {
3152 3155 if (media != DL_WIFI) {
3153 3156 return (get_speed(handle, pdp, linkid, prop_val,
3154 3157 val_cnt, media, flags, perm_flags));
3155 3158 }
3156 3159
3157 3160 return (get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
3158 3161 MAC_PROP_WL_DESIRED_RATES, perm_flags));
3159 3162 }
3160 3163
3161 3164 /* ARGSUSED */
3162 3165 static dladm_status_t
3163 3166 get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3164 3167 char **prop_val, uint_t *val_cnt, datalink_media_t media,
3165 3168 uint_t flags, uint_t *perm_flags)
3166 3169 {
3167 3170 switch (media) {
3168 3171 case DL_ETHER:
3169 3172 /*
3170 3173 * Speed for ethernet links is unbounded. E.g., 802.11b
3171 3174 * links can have a speed of 5.5 Gbps.
3172 3175 */
3173 3176 return (DLADM_STATUS_NOTSUP);
3174 3177
3175 3178 case DL_WIFI:
3176 3179 return (get_rate_common(handle, pdp, linkid, prop_val,
3177 3180 val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
3178 3181 default:
3179 3182 return (DLADM_STATUS_BADARG);
3180 3183 }
3181 3184 }
3182 3185
3183 3186 static dladm_status_t
3184 3187 set_wlan_rate(dladm_handle_t handle, datalink_id_t linkid,
3185 3188 dladm_wlan_rates_t *rates)
3186 3189 {
3187 3190 int i;
3188 3191 uint_t len;
3189 3192 wl_rates_t *wrp;
3190 3193 dladm_status_t status = DLADM_STATUS_OK;
3191 3194
3192 3195 wrp = malloc(WLDP_BUFSIZE);
3193 3196 if (wrp == NULL)
3194 3197 return (DLADM_STATUS_NOMEM);
3195 3198
3196 3199 bzero(wrp, WLDP_BUFSIZE);
3197 3200 for (i = 0; i < rates->wr_cnt; i++)
3198 3201 wrp->wl_rates_rates[i] = rates->wr_rates[i];
3199 3202 wrp->wl_rates_num = rates->wr_cnt;
3200 3203
3201 3204 len = offsetof(wl_rates_t, wl_rates_rates) +
3202 3205 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
3203 3206 status = i_dladm_wlan_param(handle, linkid, wrp,
3204 3207 MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
3205 3208
3206 3209 free(wrp);
3207 3210 return (status);
3208 3211 }
3209 3212
3210 3213 /* ARGSUSED */
3211 3214 static dladm_status_t
3212 3215 set_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3213 3216 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3214 3217 {
3215 3218 dladm_wlan_rates_t rates;
3216 3219 dladm_status_t status;
3217 3220
3218 3221 /*
3219 3222 * can currently set rate on WIFI links only.
3220 3223 */
3221 3224 if (media != DL_WIFI)
3222 3225 return (DLADM_STATUS_PROPRDONLY);
3223 3226
3224 3227 if (val_cnt != 1)
3225 3228 return (DLADM_STATUS_BADVALCNT);
3226 3229
3227 3230 rates.wr_cnt = 1;
3228 3231 rates.wr_rates[0] = vdp[0].vd_val;
3229 3232
3230 3233 status = set_wlan_rate(handle, linkid, &rates);
3231 3234
3232 3235 return (status);
3233 3236 }
3234 3237
3235 3238 /* ARGSUSED */
3236 3239 static dladm_status_t
3237 3240 check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3238 3241 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3239 3242 datalink_media_t media)
3240 3243 {
3241 3244 int i;
3242 3245 uint_t modval_cnt = MAX_SUPPORT_RATES;
3243 3246 char *buf, **modval;
3244 3247 dladm_status_t status;
3245 3248 uint_t perm_flags;
3246 3249 uint_t val_cnt = *val_cntp;
3247 3250 val_desc_t *vdp = *vdpp;
3248 3251
3249 3252 if (val_cnt != 1)
3250 3253 return (DLADM_STATUS_BADVALCNT);
3251 3254
3252 3255 buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
3253 3256 MAX_SUPPORT_RATES);
3254 3257 if (buf == NULL) {
3255 3258 status = DLADM_STATUS_NOMEM;
3256 3259 goto done;
3257 3260 }
3258 3261
3259 3262 modval = (char **)(void *)buf;
3260 3263 for (i = 0; i < MAX_SUPPORT_RATES; i++) {
3261 3264 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
3262 3265 i * DLADM_STRSIZE;
3263 3266 }
3264 3267
3265 3268 status = get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
3266 3269 media, 0, &perm_flags);
3267 3270 if (status != DLADM_STATUS_OK)
3268 3271 goto done;
3269 3272
3270 3273 for (i = 0; i < modval_cnt; i++) {
3271 3274 if (strcasecmp(*prop_val, modval[i]) == 0) {
3272 3275 vdp->vd_val = (uintptr_t)(uint_t)
3273 3276 (atof(*prop_val) * 2);
3274 3277 status = DLADM_STATUS_OK;
3275 3278 break;
3276 3279 }
3277 3280 }
3278 3281 if (i == modval_cnt)
3279 3282 status = DLADM_STATUS_BADVAL;
3280 3283 done:
3281 3284 free(buf);
3282 3285 return (status);
3283 3286 }
3284 3287
3285 3288 static dladm_status_t
3286 3289 get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
3287 3290 int buflen)
3288 3291 {
3289 3292 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
3290 3293 buflen, B_FALSE));
3291 3294 }
3292 3295
3293 3296 /* ARGSUSED */
3294 3297 static dladm_status_t
3295 3298 get_channel(dladm_handle_t handle, prop_desc_t *pdp,
3296 3299 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3297 3300 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3298 3301 {
3299 3302 uint32_t channel;
3300 3303 char buf[WLDP_BUFSIZE];
3301 3304 dladm_status_t status;
3302 3305 wl_phy_conf_t wl_phy_conf;
3303 3306
3304 3307 if ((status = get_phyconf(handle, linkid, buf, sizeof (buf)))
3305 3308 != DLADM_STATUS_OK)
3306 3309 return (status);
3307 3310
3308 3311 (void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
3309 3312 if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel))
3310 3313 return (DLADM_STATUS_NOTFOUND);
3311 3314
3312 3315 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
3313 3316 *val_cnt = 1;
3314 3317 *perm_flags = MAC_PROP_PERM_READ;
3315 3318 return (DLADM_STATUS_OK);
3316 3319 }
3317 3320
3318 3321 /* ARGSUSED */
3319 3322 static dladm_status_t
3320 3323 get_powermode(dladm_handle_t handle, prop_desc_t *pdp,
3321 3324 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3322 3325 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3323 3326 {
3324 3327 wl_ps_mode_t mode;
3325 3328 const char *s;
3326 3329 char buf[WLDP_BUFSIZE];
3327 3330 dladm_status_t status;
3328 3331
3329 3332 if ((status = i_dladm_wlan_param(handle, linkid, buf,
3330 3333 MAC_PROP_WL_POWER_MODE, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3331 3334 return (status);
3332 3335
3333 3336 (void) memcpy(&mode, buf, sizeof (mode));
3334 3337 switch (mode.wl_ps_mode) {
3335 3338 case WL_PM_AM:
3336 3339 s = "off";
3337 3340 break;
3338 3341 case WL_PM_MPS:
3339 3342 s = "max";
3340 3343 break;
3341 3344 case WL_PM_FAST:
3342 3345 s = "fast";
3343 3346 break;
3344 3347 default:
3345 3348 return (DLADM_STATUS_NOTFOUND);
3346 3349 }
3347 3350 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
3348 3351 *val_cnt = 1;
3349 3352 *perm_flags = MAC_PROP_PERM_RW;
3350 3353 return (DLADM_STATUS_OK);
3351 3354 }
3352 3355
3353 3356 /* ARGSUSED */
3354 3357 static dladm_status_t
3355 3358 set_powermode(dladm_handle_t handle, prop_desc_t *pdp,
3356 3359 datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
3357 3360 datalink_media_t media)
3358 3361 {
3359 3362 dladm_wlan_powermode_t powermode = vdp->vd_val;
3360 3363 wl_ps_mode_t ps_mode;
3361 3364
3362 3365 if (val_cnt != 1)
3363 3366 return (DLADM_STATUS_BADVALCNT);
3364 3367
3365 3368 (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
3366 3369
3367 3370 switch (powermode) {
3368 3371 case DLADM_WLAN_PM_OFF:
3369 3372 ps_mode.wl_ps_mode = WL_PM_AM;
3370 3373 break;
3371 3374 case DLADM_WLAN_PM_MAX:
3372 3375 ps_mode.wl_ps_mode = WL_PM_MPS;
3373 3376 break;
3374 3377 case DLADM_WLAN_PM_FAST:
3375 3378 ps_mode.wl_ps_mode = WL_PM_FAST;
3376 3379 break;
3377 3380 default:
3378 3381 return (DLADM_STATUS_NOTSUP);
3379 3382 }
3380 3383 return (i_dladm_wlan_param(handle, linkid, &ps_mode,
3381 3384 MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
3382 3385 }
3383 3386
3384 3387 /* ARGSUSED */
3385 3388 static dladm_status_t
3386 3389 get_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3387 3390 char **prop_val, uint_t *val_cnt, datalink_media_t media,
3388 3391 uint_t flags, uint_t *perm_flags)
3389 3392 {
3390 3393 wl_radio_t radio;
3391 3394 const char *s;
3392 3395 char buf[WLDP_BUFSIZE];
3393 3396 dladm_status_t status;
3394 3397
3395 3398 if ((status = i_dladm_wlan_param(handle, linkid, buf,
3396 3399 MAC_PROP_WL_RADIO, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3397 3400 return (status);
3398 3401
3399 3402 (void) memcpy(&radio, buf, sizeof (radio));
3400 3403 switch (radio) {
3401 3404 case B_TRUE:
3402 3405 s = "on";
3403 3406 break;
3404 3407 case B_FALSE:
3405 3408 s = "off";
3406 3409 break;
3407 3410 default:
3408 3411 return (DLADM_STATUS_NOTFOUND);
3409 3412 }
3410 3413 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
3411 3414 *val_cnt = 1;
3412 3415 *perm_flags = MAC_PROP_PERM_RW;
3413 3416 return (DLADM_STATUS_OK);
3414 3417 }
3415 3418
3416 3419 /* ARGSUSED */
3417 3420 static dladm_status_t
3418 3421 set_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3419 3422 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3420 3423 {
3421 3424 dladm_wlan_radio_t radio = vdp->vd_val;
3422 3425 wl_radio_t r;
3423 3426
3424 3427 if (val_cnt != 1)
3425 3428 return (DLADM_STATUS_BADVALCNT);
3426 3429
3427 3430 switch (radio) {
3428 3431 case DLADM_WLAN_RADIO_ON:
3429 3432 r = B_TRUE;
3430 3433 break;
3431 3434 case DLADM_WLAN_RADIO_OFF:
3432 3435 r = B_FALSE;
3433 3436 break;
3434 3437 default:
3435 3438 return (DLADM_STATUS_NOTSUP);
3436 3439 }
3437 3440 return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
3438 3441 sizeof (r), B_TRUE));
3439 3442 }
3440 3443
3441 3444 /* ARGSUSED */
3442 3445 static dladm_status_t
3443 3446 check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
3444 3447 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
3445 3448 val_desc_t **vdpp, datalink_media_t media)
3446 3449 {
3447 3450 int32_t hlim;
3448 3451 char *ep;
3449 3452 uint_t val_cnt = *val_cntp;
3450 3453 val_desc_t *vdp = *vdpp;
3451 3454
3452 3455 if (val_cnt != 1)
3453 3456 return (DLADM_STATUS_BADVALCNT);
3454 3457
3455 3458 errno = 0;
3456 3459 hlim = strtol(*prop_val, &ep, 10);
3457 3460 if (errno != 0 || ep == *prop_val || hlim < 1 ||
3458 3461 hlim > (int32_t)UINT8_MAX)
3459 3462 return (DLADM_STATUS_BADVAL);
3460 3463 vdp->vd_val = hlim;
3461 3464 return (DLADM_STATUS_OK);
3462 3465 }
3463 3466
3464 3467 /* ARGSUSED */
3465 3468 static dladm_status_t
3466 3469 check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3467 3470 char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3468 3471 datalink_media_t media)
3469 3472 {
3470 3473 int32_t elim;
3471 3474 char *ep;
3472 3475 uint_t val_cnt = *val_cntp;
3473 3476 val_desc_t *vdp = *vdpp;
3474 3477
3475 3478 if (media != DL_IPV6)
3476 3479 return (DLADM_STATUS_BADARG);
3477 3480
3478 3481 if (val_cnt != 1)
3479 3482 return (DLADM_STATUS_BADVALCNT);
3480 3483
3481 3484 errno = 0;
3482 3485 elim = strtol(*prop_val, &ep, 10);
3483 3486 if (errno != 0 || ep == *prop_val || elim < 0 ||
3484 3487 elim > (int32_t)UINT8_MAX)
3485 3488 return (DLADM_STATUS_BADVAL);
3486 3489 vdp->vd_val = elim;
3487 3490 return (DLADM_STATUS_OK);
3488 3491 }
3489 3492
3490 3493 static dladm_status_t
3491 3494 i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
3492 3495 const char *prop_name, char **prop_val, uint_t val_cnt)
3493 3496 {
3494 3497 char buf[MAXLINELEN];
3495 3498 int i;
3496 3499 dladm_conf_t conf;
3497 3500 dladm_status_t status;
3498 3501
3499 3502 status = dladm_open_conf(handle, linkid, &conf);
3500 3503 if (status != DLADM_STATUS_OK)
3501 3504 return (status);
3502 3505
3503 3506 /*
3504 3507 * reset case.
3505 3508 */
3506 3509 if (val_cnt == 0) {
3507 3510 status = dladm_unset_conf_field(handle, conf, prop_name);
3508 3511 if (status == DLADM_STATUS_OK)
3509 3512 status = dladm_write_conf(handle, conf);
3510 3513 goto done;
3511 3514 }
3512 3515
3513 3516 buf[0] = '\0';
3514 3517 for (i = 0; i < val_cnt; i++) {
3515 3518 (void) strlcat(buf, prop_val[i], MAXLINELEN);
3516 3519 if (i != val_cnt - 1)
3517 3520 (void) strlcat(buf, ",", MAXLINELEN);
3518 3521 }
3519 3522
3520 3523 status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
3521 3524 buf);
3522 3525 if (status == DLADM_STATUS_OK)
3523 3526 status = dladm_write_conf(handle, conf);
3524 3527
3525 3528 done:
3526 3529 dladm_destroy_conf(handle, conf);
3527 3530 return (status);
3528 3531 }
3529 3532
3530 3533 static dladm_status_t
3531 3534 i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
3532 3535 const char *prop_name, char **prop_val, uint_t *val_cntp)
3533 3536 {
3534 3537 char buf[MAXLINELEN], *str;
3535 3538 uint_t cnt = 0;
3536 3539 dladm_conf_t conf;
3537 3540 dladm_status_t status;
3538 3541
3539 3542 status = dladm_getsnap_conf(handle, linkid, &conf);
3540 3543 if (status != DLADM_STATUS_OK)
3541 3544 return (status);
3542 3545
3543 3546 status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
3544 3547 if (status != DLADM_STATUS_OK)
3545 3548 goto done;
3546 3549
3547 3550 str = strtok(buf, ",");
3548 3551 while (str != NULL) {
3549 3552 if (cnt == *val_cntp) {
3550 3553 status = DLADM_STATUS_TOOSMALL;
3551 3554 goto done;
3552 3555 }
3553 3556 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
3554 3557 str = strtok(NULL, ",");
3555 3558 }
3556 3559
3557 3560 *val_cntp = cnt;
3558 3561
3559 3562 done:
3560 3563 dladm_destroy_conf(handle, conf);
3561 3564 return (status);
3562 3565 }
3563 3566
3564 3567 /*
3565 3568 * Walk persistent private link properties of a link.
3566 3569 */
3567 3570 static dladm_status_t
3568 3571 i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
3569 3572 void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
3570 3573 {
3571 3574 dladm_status_t status;
3572 3575 dladm_conf_t conf;
3573 3576 char last_attr[MAXLINKATTRLEN];
3574 3577 char attr[MAXLINKATTRLEN];
3575 3578 char attrval[MAXLINKATTRVALLEN];
3576 3579 size_t attrsz;
3577 3580
3578 3581 if (linkid == DATALINK_INVALID_LINKID || func == NULL)
3579 3582 return (DLADM_STATUS_BADARG);
3580 3583
3581 3584 status = dladm_getsnap_conf(handle, linkid, &conf);
3582 3585 if (status != DLADM_STATUS_OK)
3583 3586 return (status);
3584 3587
3585 3588 last_attr[0] = '\0';
3586 3589 while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
3587 3590 attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
3588 3591 if (attr[0] == '_') {
3589 3592 if (func(handle, linkid, attr, arg) ==
3590 3593 DLADM_WALK_TERMINATE)
3591 3594 break;
3592 3595 }
3593 3596 (void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
3594 3597 }
3595 3598
3596 3599 dladm_destroy_conf(handle, conf);
3597 3600 return (DLADM_STATUS_OK);
3598 3601 }
3599 3602
3600 3603 static link_attr_t *
3601 3604 dladm_name2prop(const char *prop_name)
3602 3605 {
3603 3606 link_attr_t *p;
3604 3607
3605 3608 for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
3606 3609 if (strcmp(p->pp_name, prop_name) == 0)
3607 3610 break;
3608 3611 }
3609 3612 return (p);
3610 3613 }
3611 3614
3612 3615 static link_attr_t *
3613 3616 dladm_id2prop(mac_prop_id_t propid)
3614 3617 {
3615 3618 link_attr_t *p;
3616 3619
3617 3620 for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
3618 3621 if (p->pp_id == propid)
3619 3622 break;
3620 3623 }
3621 3624 return (p);
3622 3625 }
3623 3626
3624 3627 static dld_ioc_macprop_t *
3625 3628 i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
3626 3629 const char *prop_name, mac_prop_id_t propid, uint_t flags,
3627 3630 dladm_status_t *status)
3628 3631 {
3629 3632 int dsize;
3630 3633 dld_ioc_macprop_t *dip;
3631 3634
3632 3635 *status = DLADM_STATUS_OK;
3633 3636 dsize = MAC_PROP_BUFSIZE(valsize);
3634 3637 dip = malloc(dsize);
3635 3638 if (dip == NULL) {
3636 3639 *status = DLADM_STATUS_NOMEM;
3637 3640 return (NULL);
3638 3641 }
3639 3642 bzero(dip, dsize);
3640 3643 dip->pr_valsize = valsize;
3641 3644 (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
3642 3645 dip->pr_linkid = linkid;
3643 3646 dip->pr_num = propid;
3644 3647 dip->pr_flags = flags;
3645 3648 return (dip);
3646 3649 }
3647 3650
3648 3651 static dld_ioc_macprop_t *
3649 3652 i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
3650 3653 const char *prop_name, uint_t flags, dladm_status_t *status)
3651 3654 {
3652 3655 link_attr_t *p;
3653 3656
3654 3657 p = dladm_name2prop(prop_name);
3655 3658 valsize = MAX(p->pp_valsize, valsize);
3656 3659 return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
3657 3660 flags, status));
3658 3661 }
3659 3662
3660 3663 static dld_ioc_macprop_t *
3661 3664 i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
3662 3665 mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
3663 3666 {
3664 3667 link_attr_t *p;
3665 3668
3666 3669 p = dladm_id2prop(propid);
3667 3670 valsize = MAX(p->pp_valsize, valsize);
3668 3671 return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
3669 3672 flags, status));
3670 3673 }
3671 3674
3672 3675 /* ARGSUSED */
3673 3676 static dladm_status_t
3674 3677 set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
3675 3678 datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
3676 3679 datalink_media_t media)
3677 3680 {
3678 3681 dld_ioc_macprop_t *dip;
3679 3682 dladm_status_t status = DLADM_STATUS_OK;
3680 3683 uint8_t u8;
3681 3684 uint16_t u16;
3682 3685 uint32_t u32;
3683 3686 void *val;
3684 3687
3685 3688 dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
3686 3689 if (dip == NULL)
3687 3690 return (status);
3688 3691
3689 3692 if (pdp->pd_flags & PD_CHECK_ALLOC)
3690 3693 val = (void *)vdp->vd_val;
3691 3694 else {
3692 3695 /*
3693 3696 * Currently all 1/2/4-byte size properties are byte/word/int.
3694 3697 * No need (yet) to distinguish these from arrays of same size.
3695 3698 */
3696 3699 switch (dip->pr_valsize) {
3697 3700 case 1:
3698 3701 u8 = vdp->vd_val;
3699 3702 val = &u8;
3700 3703 break;
3701 3704 case 2:
3702 3705 u16 = vdp->vd_val;
3703 3706 val = &u16;
3704 3707 break;
3705 3708 case 4:
3706 3709 u32 = vdp->vd_val;
3707 3710 val = &u32;
3708 3711 break;
3709 3712 default:
3710 3713 val = &vdp->vd_val;
3711 3714 break;
3712 3715 }
3713 3716 }
3714 3717
3715 3718 if (val != NULL)
3716 3719 (void) memcpy(dip->pr_val, val, dip->pr_valsize);
3717 3720 else
3718 3721 dip->pr_valsize = 0;
3719 3722
3720 3723 status = i_dladm_macprop(handle, dip, B_TRUE);
3721 3724
3722 3725 done:
3723 3726 free(dip);
3724 3727 return (status);
3725 3728 }
3726 3729
3727 3730 dladm_status_t
3728 3731 i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
3729 3732 {
3730 3733 dladm_status_t status = DLADM_STATUS_OK;
3731 3734
3732 3735 if (ioctl(dladm_dld_fd(handle),
3733 3736 (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
3734 3737 status = dladm_errno2status(errno);
3735 3738
3736 3739 return (status);
3737 3740 }
3738 3741
3739 3742 static dladm_status_t
3740 3743 i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
3741 3744 char *prop_name, uint_t flags, uint_t *perm_flags, void *arg, size_t size)
3742 3745 {
3743 3746 dld_ioc_macprop_t *dip;
3744 3747 dladm_status_t status;
3745 3748
3746 3749 dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, &status);
3747 3750 if (dip == NULL)
3748 3751 return (DLADM_STATUS_NOMEM);
3749 3752
3750 3753 status = i_dladm_macprop(handle, dip, B_FALSE);
3751 3754 if (status != DLADM_STATUS_OK) {
3752 3755 free(dip);
3753 3756 return (status);
3754 3757 }
3755 3758
3756 3759 if (perm_flags != NULL)
3757 3760 *perm_flags = dip->pr_perm_flags;
3758 3761
3759 3762 if (arg != NULL)
3760 3763 (void) memcpy(arg, dip->pr_val, size);
3761 3764 free(dip);
3762 3765 return (DLADM_STATUS_OK);
3763 3766 }
3764 3767
3765 3768 /* ARGSUSED */
3766 3769 static dladm_status_t
3767 3770 check_uint32(dladm_handle_t handle, prop_desc_t *pdp,
3768 3771 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
3769 3772 val_desc_t **vp, datalink_media_t media)
3770 3773 {
3771 3774 uint_t val_cnt = *val_cntp;
3772 3775 val_desc_t *v = *vp;
3773 3776
3774 3777 if (val_cnt != 1)
3775 3778 return (DLADM_STATUS_BADVAL);
3776 3779 v->vd_val = strtoul(prop_val[0], NULL, 0);
3777 3780 return (DLADM_STATUS_OK);
3778 3781 }
3779 3782
3780 3783 /* ARGSUSED */
3781 3784 static dladm_status_t
3782 3785 get_duplex(dladm_handle_t handle, prop_desc_t *pdp,
3783 3786 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3784 3787 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3785 3788 {
3786 3789 link_duplex_t link_duplex;
3787 3790 dladm_status_t status;
3788 3791
3789 3792 if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
3790 3793 KSTAT_DATA_UINT32, &link_duplex)) != 0)
3791 3794 return (status);
3792 3795
3793 3796 switch (link_duplex) {
3794 3797 case LINK_DUPLEX_FULL:
3795 3798 (void) strcpy(*prop_val, "full");
3796 3799 break;
3797 3800 case LINK_DUPLEX_HALF:
3798 3801 (void) strcpy(*prop_val, "half");
3799 3802 break;
3800 3803 default:
3801 3804 (void) strcpy(*prop_val, "unknown");
3802 3805 break;
3803 3806 }
3804 3807 *val_cnt = 1;
3805 3808 return (DLADM_STATUS_OK);
3806 3809 }
3807 3810
3808 3811 /* ARGSUSED */
3809 3812 static dladm_status_t
3810 3813 get_speed(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3811 3814 char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
3812 3815 uint_t *perm_flags)
3813 3816 {
3814 3817 uint64_t ifspeed = 0;
3815 3818 dladm_status_t status;
3816 3819
3817 3820 if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
3818 3821 KSTAT_DATA_UINT64, &ifspeed)) != 0)
3819 3822 return (status);
3820 3823
3821 3824 if ((ifspeed % 1000000) != 0) {
3822 3825 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
3823 3826 "%llf", ifspeed / (float)1000000); /* Mbps */
3824 3827 } else {
3825 3828 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
3826 3829 "%llu", ifspeed / 1000000); /* Mbps */
3827 3830 }
3828 3831 *val_cnt = 1;
3829 3832 *perm_flags = MAC_PROP_PERM_READ;
3830 3833 return (DLADM_STATUS_OK);
3831 3834 }
3832 3835
3833 3836 /* ARGSUSED */
3834 3837 static dladm_status_t
3835 3838 get_link_state(dladm_handle_t handle, prop_desc_t *pdp,
3836 3839 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3837 3840 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3838 3841 {
3839 3842 link_state_t link_state;
3840 3843 dladm_status_t status;
3841 3844
3842 3845 status = dladm_get_state(handle, linkid, &link_state);
3843 3846 if (status != DLADM_STATUS_OK)
3844 3847 return (status);
3845 3848
3846 3849 switch (link_state) {
3847 3850 case LINK_STATE_UP:
3848 3851 (void) strcpy(*prop_val, "up");
3849 3852 break;
3850 3853 case LINK_STATE_DOWN:
3851 3854 (void) strcpy(*prop_val, "down");
3852 3855 break;
3853 3856 default:
3854 3857 (void) strcpy(*prop_val, "unknown");
3855 3858 break;
3856 3859 }
3857 3860 *val_cnt = 1;
3858 3861 *perm_flags = MAC_PROP_PERM_READ;
3859 3862 return (DLADM_STATUS_OK);
3860 3863 }
3861 3864
3862 3865 /* ARGSUSED */
3863 3866 static dladm_status_t
3864 3867 get_binary(dladm_handle_t handle, prop_desc_t *pdp,
3865 3868 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3866 3869 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3867 3870 {
3868 3871 dladm_status_t status;
3869 3872 uint_t v = 0;
3870 3873
3871 3874 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3872 3875 perm_flags, &v, sizeof (v));
3873 3876 if (status != DLADM_STATUS_OK)
3874 3877 return (status);
3875 3878
3876 3879 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%d", (uint_t)(v > 0));
3877 3880 *val_cnt = 1;
3878 3881 return (DLADM_STATUS_OK);
3879 3882 }
3880 3883
3881 3884 /* ARGSUSED */
3882 3885 static dladm_status_t
3883 3886 get_uint32(dladm_handle_t handle, prop_desc_t *pdp,
3884 3887 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3885 3888 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3886 3889 {
3887 3890 dladm_status_t status;
3888 3891 uint32_t v = 0;
3889 3892
3890 3893 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3891 3894 perm_flags, &v, sizeof (v));
3892 3895 if (status != DLADM_STATUS_OK)
3893 3896 return (status);
3894 3897
3895 3898 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
3896 3899 *val_cnt = 1;
3897 3900 return (DLADM_STATUS_OK);
3898 3901 }
3899 3902
3900 3903 /* ARGSUSED */
3901 3904 static dladm_status_t
3902 3905 get_range(dladm_handle_t handle, prop_desc_t *pdp,
3903 3906 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3904 3907 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3905 3908 {
3906 3909 dld_ioc_macprop_t *dip;
3907 3910 dladm_status_t status = DLADM_STATUS_OK;
3908 3911 size_t sz;
3909 3912 uint_t rcount;
3910 3913 mac_propval_range_t *rangep;
3911 3914
3912 3915 /*
3913 3916 * As caller we don't know number of value ranges, the driver
3914 3917 * supports. To begin with we assume that number to be 1. If the
3915 3918 * buffer size is insufficient, driver returns back with the
3916 3919 * actual count of value ranges. See mac.h for more details.
3917 3920 */
3918 3921 sz = sizeof (mac_propval_range_t);
3919 3922 rcount = 1;
3920 3923 retry:
3921 3924 if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
3922 3925 &status)) == NULL)
3923 3926 return (status);
3924 3927
3925 3928 rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
3926 3929 rangep->mpr_count = rcount;
3927 3930
3928 3931 status = i_dladm_macprop(handle, dip, B_FALSE);
3929 3932 if (status != DLADM_STATUS_OK) {
3930 3933 if (status == DLADM_STATUS_TOOSMALL) {
3931 3934 int err;
3932 3935
3933 3936 if ((err = i_dladm_range_size(rangep, &sz, &rcount))
3934 3937 == 0) {
3935 3938 free(dip);
3936 3939 goto retry;
3937 3940 } else {
3938 3941 status = dladm_errno2status(err);
3939 3942 }
3940 3943 }
3941 3944 free(dip);
3942 3945 return (status);
3943 3946 }
3944 3947
3945 3948 if (rangep->mpr_count == 0) {
3946 3949 *val_cnt = 1;
3947 3950 (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "--");
3948 3951 goto done;
3949 3952 }
3950 3953
3951 3954 switch (rangep->mpr_type) {
3952 3955 case MAC_PROPVAL_UINT32: {
3953 3956 mac_propval_uint32_range_t *ur;
3954 3957 uint_t count = rangep->mpr_count, i;
3955 3958
3956 3959 ur = &rangep->mpr_range_uint32[0];
3957 3960
3958 3961 for (i = 0; i < count; i++, ur++) {
3959 3962 if (ur->mpur_min == ur->mpur_max) {
3960 3963 (void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
3961 3964 "%ld", ur->mpur_min);
3962 3965 } else {
3963 3966 (void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
3964 3967 "%ld-%ld", ur->mpur_min, ur->mpur_max);
3965 3968 }
3966 3969 }
3967 3970 *val_cnt = count;
3968 3971 break;
3969 3972 }
3970 3973 default:
3971 3974 status = DLADM_STATUS_BADARG;
3972 3975 break;
3973 3976 }
3974 3977 done:
3975 3978 free(dip);
3976 3979 return (status);
3977 3980 }
3978 3981
3979 3982 /* ARGSUSED */
3980 3983 static dladm_status_t
3981 3984 get_tagmode(dladm_handle_t handle, prop_desc_t *pdp,
3982 3985 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3983 3986 datalink_media_t media, uint_t flags, uint_t *perm_flags)
3984 3987 {
3985 3988 link_tagmode_t mode;
3986 3989 dladm_status_t status;
3987 3990
3988 3991 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3989 3992 perm_flags, &mode, sizeof (mode));
3990 3993 if (status != DLADM_STATUS_OK)
3991 3994 return (status);
3992 3995
3993 3996 switch (mode) {
3994 3997 case LINK_TAGMODE_NORMAL:
3995 3998 (void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
3996 3999 break;
3997 4000 case LINK_TAGMODE_VLANONLY:
3998 4001 (void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
3999 4002 break;
4000 4003 default:
4001 4004 (void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
4002 4005 }
4003 4006 *val_cnt = 1;
4004 4007 return (DLADM_STATUS_OK);
4005 4008 }
4006 4009
4007 4010 /* ARGSUSED */
4008 4011 static dladm_status_t
4009 4012 get_flowctl(dladm_handle_t handle, prop_desc_t *pdp,
4010 4013 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4011 4014 datalink_media_t media, uint_t flags, uint_t *perm_flags)
4012 4015 {
4013 4016 link_flowctrl_t v;
4014 4017 dladm_status_t status;
4015 4018
4016 4019 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4017 4020 perm_flags, &v, sizeof (v));
4018 4021 if (status != DLADM_STATUS_OK)
4019 4022 return (status);
4020 4023
4021 4024 switch (v) {
4022 4025 case LINK_FLOWCTRL_NONE:
4023 4026 (void) sprintf(*prop_val, "no");
4024 4027 break;
4025 4028 case LINK_FLOWCTRL_RX:
4026 4029 (void) sprintf(*prop_val, "rx");
4027 4030 break;
4028 4031 case LINK_FLOWCTRL_TX:
4029 4032 (void) sprintf(*prop_val, "tx");
4030 4033 break;
4031 4034 case LINK_FLOWCTRL_BI:
4032 4035 (void) sprintf(*prop_val, "bi");
4033 4036 break;
4034 4037 }
4035 4038 *val_cnt = 1;
4036 4039 return (DLADM_STATUS_OK);
4037 4040 }
4038 4041
4039 4042
4040 4043 /* ARGSUSED */
4041 4044 static dladm_status_t
4042 4045 i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
4043 4046 const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
4044 4047
4045 4048 {
4046 4049 int i, slen;
4047 4050 int bufsize = 0;
4048 4051 dld_ioc_macprop_t *dip = NULL;
4049 4052 uchar_t *dp;
4050 4053 link_attr_t *p;
4051 4054 dladm_status_t status = DLADM_STATUS_OK;
4052 4055
4053 4056 if ((prop_name == NULL && prop_val != NULL) ||
4054 4057 (prop_val != NULL && val_cnt == 0))
4055 4058 return (DLADM_STATUS_BADARG);
4056 4059 p = dladm_name2prop(prop_name);
4057 4060 if (p->pp_id != MAC_PROP_PRIVATE)
4058 4061 return (DLADM_STATUS_BADARG);
4059 4062
4060 4063 if (!(flags & DLADM_OPT_ACTIVE))
4061 4064 return (DLADM_STATUS_OK);
4062 4065
4063 4066 /*
4064 4067 * private properties: all parsing is done in the kernel.
4065 4068 * allocate a enough space for each property + its separator (',').
4066 4069 */
4067 4070 for (i = 0; i < val_cnt; i++) {
4068 4071 bufsize += strlen(prop_val[i]) + 1;
4069 4072 }
4070 4073
4071 4074 if (prop_val == NULL) {
4072 4075 /*
4073 4076 * getting default value. so use more buffer space.
4074 4077 */
4075 4078 bufsize += DLADM_PROP_BUF_CHUNK;
4076 4079 }
4077 4080
4078 4081 dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
4079 4082 (prop_val != NULL ? 0 : DLD_PROP_DEFAULT), &status);
4080 4083 if (dip == NULL)
4081 4084 return (status);
4082 4085
4083 4086 dp = (uchar_t *)dip->pr_val;
4084 4087 slen = 0;
4085 4088
4086 4089 if (prop_val == NULL) {
4087 4090 status = i_dladm_macprop(handle, dip, B_FALSE);
4088 4091 dip->pr_flags = 0;
4089 4092 } else {
4090 4093 for (i = 0; i < val_cnt; i++) {
4091 4094 int plen = 0;
4092 4095
4093 4096 plen = strlen(prop_val[i]);
4094 4097 bcopy(prop_val[i], dp, plen);
4095 4098 slen += plen;
4096 4099 /*
4097 4100 * add a "," separator and update dp.
4098 4101 */
4099 4102 if (i != (val_cnt -1))
4100 4103 dp[slen++] = ',';
4101 4104 dp += (plen + 1);
4102 4105 }
4103 4106 }
4104 4107 if (status == DLADM_STATUS_OK)
4105 4108 status = i_dladm_macprop(handle, dip, B_TRUE);
4106 4109
4107 4110 free(dip);
4108 4111 return (status);
4109 4112 }
4110 4113
4111 4114 static dladm_status_t
4112 4115 i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
4113 4116 const char *prop_name, char **prop_val, uint_t *val_cnt,
4114 4117 dladm_prop_type_t type, uint_t dld_flags)
4115 4118 {
4116 4119 dladm_status_t status = DLADM_STATUS_OK;
4117 4120 dld_ioc_macprop_t *dip = NULL;
4118 4121 link_attr_t *p;
4119 4122
4120 4123 if ((prop_name == NULL && prop_val != NULL) ||
4121 4124 (prop_val != NULL && val_cnt == 0))
4122 4125 return (DLADM_STATUS_BADARG);
4123 4126
4124 4127 p = dladm_name2prop(prop_name);
4125 4128 if (p->pp_id != MAC_PROP_PRIVATE)
4126 4129 return (DLADM_STATUS_BADARG);
4127 4130
4128 4131 /*
4129 4132 * private properties: all parsing is done in the kernel.
4130 4133 */
4131 4134 dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
4132 4135 dld_flags, &status);
4133 4136 if (dip == NULL)
4134 4137 return (status);
4135 4138
4136 4139 if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
4137 4140 DLADM_STATUS_OK) {
4138 4141 if (type == DLADM_PROP_VAL_PERM) {
4139 4142 (void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
4140 4143 } else if (type == DLADM_PROP_VAL_MODIFIABLE) {
4141 4144 *prop_val[0] = '\0';
4142 4145 } else {
4143 4146 (void) strncpy(*prop_val, dip->pr_val,
4144 4147 DLADM_PROP_VAL_MAX);
4145 4148 }
4146 4149 *val_cnt = 1;
4147 4150 } else if ((status == DLADM_STATUS_NOTSUP) &&
4148 4151 (type == DLADM_PROP_VAL_CURRENT)) {
4149 4152 status = DLADM_STATUS_NOTFOUND;
4150 4153 }
4151 4154 free(dip);
4152 4155 return (status);
4153 4156 }
4154 4157
4155 4158
4156 4159 static dladm_status_t
4157 4160 i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
4158 4161 datalink_id_t linkid, datalink_media_t media, uint_t flags)
4159 4162 {
4160 4163 dladm_status_t status;
4161 4164 char **prop_vals = NULL, *buf;
4162 4165 size_t bufsize;
4163 4166 uint_t cnt;
4164 4167 int i;
4165 4168 uint_t perm_flags;
4166 4169
4167 4170 /*
4168 4171 * Allocate buffer needed for prop_vals array. We can have at most
4169 4172 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4170 4173 * each entry has max size DLADM_PROP_VAL_MAX
4171 4174 */
4172 4175 bufsize =
4173 4176 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
4174 4177 buf = malloc(bufsize);
4175 4178 prop_vals = (char **)(void *)buf;
4176 4179 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
4177 4180 prop_vals[i] = buf +
4178 4181 sizeof (char *) * DLADM_MAX_PROP_VALCNT +
4179 4182 i * DLADM_PROP_VAL_MAX;
4180 4183 }
4181 4184
4182 4185 /*
4183 4186 * For properties which have pdp->pd_defval.vd_name as a non-empty
4184 4187 * string, the "" itself is used to reset the property (exceptions
4185 4188 * are zone and autopush, which populate vdp->vd_val). So
4186 4189 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4187 4190 * down on the setprop using the global values in the table. For
4188 4191 * other cases (vd_name is ""), doing reset-linkprop will cause
4189 4192 * libdladm to do a getprop to find the default value and then do
4190 4193 * a setprop to reset the value to default.
4191 4194 */
4192 4195 status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
4193 4196 DLD_PROP_DEFAULT, &perm_flags);
4194 4197 if (status == DLADM_STATUS_OK) {
4195 4198 if (perm_flags == MAC_PROP_PERM_RW) {
4196 4199 status = i_dladm_set_single_prop(handle, linkid,
4197 4200 pdp->pd_class, media, pdp, prop_vals, cnt, flags);
4198 4201 }
4199 4202 else
4200 4203 status = DLADM_STATUS_NOTSUP;
4201 4204 }
4202 4205 free(buf);
4203 4206 return (status);
4204 4207 }
4205 4208
4206 4209 /* ARGSUSED */
4207 4210 static dladm_status_t
4208 4211 get_stp(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
4209 4212 char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
4210 4213 uint_t *perm_flags)
4211 4214 {
4212 4215 const bridge_public_prop_t *bpp;
4213 4216 dladm_status_t retv;
4214 4217 int val, i;
4215 4218
4216 4219 if (flags != 0)
4217 4220 return (DLADM_STATUS_NOTSUP);
4218 4221 *perm_flags = MAC_PROP_PERM_RW;
4219 4222 *val_cnt = 1;
4220 4223 for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
4221 4224 if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
4222 4225 break;
4223 4226 retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
4224 4227 /* If the daemon isn't running, then return the persistent value */
4225 4228 if (retv == DLADM_STATUS_NOTFOUND) {
4226 4229 if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
4227 4230 prop_val, val_cnt) != DLADM_STATUS_OK)
4228 4231 (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4229 4232 DLADM_PROP_VAL_MAX);
4230 4233 return (DLADM_STATUS_OK);
4231 4234 }
4232 4235 if (retv != DLADM_STATUS_OK) {
4233 4236 (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4234 4237 return (retv);
4235 4238 }
4236 4239 if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
4237 4240 (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4238 4241 DLADM_PROP_VAL_MAX);
4239 4242 return (DLADM_STATUS_OK);
4240 4243 }
4241 4244 for (i = 0; i < pd->pd_noptval; i++) {
4242 4245 if (val == pd->pd_optval[i].vd_val) {
4243 4246 (void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
4244 4247 DLADM_PROP_VAL_MAX);
4245 4248 return (DLADM_STATUS_OK);
4246 4249 }
4247 4250 }
4248 4251 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
4249 4252 return (DLADM_STATUS_OK);
4250 4253 }
4251 4254
4252 4255 /* ARGSUSED1 */
4253 4256 static dladm_status_t
4254 4257 set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4255 4258 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4256 4259 {
4257 4260 /*
4258 4261 * Special case for mcheck: the daemon resets the value to zero, and we
4259 4262 * don't want the daemon to refresh itself; it leads to deadlock.
4260 4263 */
4261 4264 if (flags & DLADM_OPT_NOREFRESH)
4262 4265 return (DLADM_STATUS_OK);
4263 4266
4264 4267 /* Tell the running daemon, if any */
4265 4268 return (dladm_bridge_refresh(handle, linkid));
4266 4269 }
4267 4270
4268 4271 /*
4269 4272 * This is used only for stp_priority, stp_cost, and stp_mcheck.
4270 4273 */
4271 4274 /* ARGSUSED */
4272 4275 static dladm_status_t
4273 4276 check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
4274 4277 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
4275 4278 val_desc_t **vdpp, datalink_media_t media)
4276 4279 {
4277 4280 char *cp;
4278 4281 boolean_t iscost;
4279 4282 uint_t val_cnt = *val_cntp;
4280 4283 val_desc_t *vdp = *vdpp;
4281 4284
4282 4285 if (val_cnt != 1)
4283 4286 return (DLADM_STATUS_BADVALCNT);
4284 4287
4285 4288 if (prop_val == NULL) {
4286 4289 vdp->vd_val = 0;
4287 4290 } else {
4288 4291 /* Only stp_priority and stp_cost use this function */
4289 4292 iscost = strcmp(pd->pd_name, "stp_cost") == 0;
4290 4293
4291 4294 if (iscost && strcmp(prop_val[0], "auto") == 0) {
4292 4295 /* Illegal value 0 is allowed to mean "automatic" */
4293 4296 vdp->vd_val = 0;
4294 4297 } else {
4295 4298 errno = 0;
4296 4299 vdp->vd_val = strtoul(prop_val[0], &cp, 0);
4297 4300 if (errno != 0 || *cp != '\0')
4298 4301 return (DLADM_STATUS_BADVAL);
4299 4302 }
4300 4303 }
4301 4304
4302 4305 if (iscost) {
4303 4306 return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
4304 4307 DLADM_STATUS_OK);
4305 4308 } else {
4306 4309 if (vdp->vd_val > 255)
4307 4310 return (DLADM_STATUS_BADVAL);
4308 4311 /*
4309 4312 * If the user is setting stp_mcheck non-zero, then (per the
4310 4313 * IEEE management standards and UNH testing) we need to check
4311 4314 * whether this link is part of a bridge that is running RSTP.
4312 4315 * If it's not, then setting the flag is an error. Note that
4313 4316 * errors are intentionally discarded here; it's the value
4314 4317 * that's the problem -- it's not a bad value, merely one that
4315 4318 * can't be used now.
4316 4319 */
4317 4320 if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
4318 4321 vdp->vd_val != 0) {
4319 4322 char bridge[MAXLINKNAMELEN];
4320 4323 UID_STP_CFG_T cfg;
4321 4324 dladm_bridge_prot_t brprot;
4322 4325
4323 4326 if (dladm_bridge_getlink(handle, linkid, bridge,
4324 4327 sizeof (bridge)) != DLADM_STATUS_OK ||
4325 4328 dladm_bridge_get_properties(bridge, &cfg,
4326 4329 &brprot) != DLADM_STATUS_OK)
4327 4330 return (DLADM_STATUS_FAILED);
4328 4331 if (cfg.force_version <= 1)
4329 4332 return (DLADM_STATUS_FAILED);
4330 4333 }
4331 4334 return (DLADM_STATUS_OK);
4332 4335 }
4333 4336 }
4334 4337
4335 4338 /* ARGSUSED */
4336 4339 static dladm_status_t
4337 4340 get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
4338 4341 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4339 4342 datalink_media_t media, uint_t flags, uint_t *perm_flags)
4340 4343 {
4341 4344 dladm_status_t retv;
4342 4345 uint_t val;
4343 4346
4344 4347 if (flags != 0)
4345 4348 return (DLADM_STATUS_NOTSUP);
4346 4349 *perm_flags = MAC_PROP_PERM_RW;
4347 4350 *val_cnt = 1;
4348 4351 retv = dladm_bridge_get_forwarding(handle, linkid, &val);
4349 4352 if (retv == DLADM_STATUS_NOTFOUND) {
4350 4353 if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
4351 4354 prop_val, val_cnt) != DLADM_STATUS_OK)
4352 4355 (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4353 4356 DLADM_PROP_VAL_MAX);
4354 4357 return (DLADM_STATUS_OK);
4355 4358 }
4356 4359 if (retv == DLADM_STATUS_OK)
4357 4360 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
4358 4361 else
4359 4362 (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4360 4363 return (retv);
4361 4364 }
4362 4365
4363 4366 /* ARGSUSED */
4364 4367 static dladm_status_t
4365 4368 set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4366 4369 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4367 4370 {
4368 4371 /* Tell the running daemon, if any */
4369 4372 return (dladm_bridge_refresh(handle, linkid));
4370 4373 }
4371 4374
4372 4375 /* ARGSUSED */
4373 4376 static dladm_status_t
4374 4377 get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
4375 4378 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4376 4379 datalink_media_t media, uint_t flags, uint_t *perm_flags)
4377 4380 {
4378 4381 dladm_status_t status;
4379 4382 dld_ioc_macprop_t *dip;
4380 4383 uint16_t pvid;
4381 4384
4382 4385 if (flags != 0)
4383 4386 return (DLADM_STATUS_NOTSUP);
4384 4387 *perm_flags = MAC_PROP_PERM_RW;
4385 4388 *val_cnt = 1;
4386 4389 dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
4387 4390 0, &status);
4388 4391 if (dip == NULL)
4389 4392 return (status);
4390 4393 status = i_dladm_macprop(handle, dip, B_FALSE);
4391 4394 if (status == DLADM_STATUS_OK) {
4392 4395 (void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
4393 4396 (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
4394 4397 } else {
4395 4398 (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4396 4399 }
4397 4400 free(dip);
4398 4401 return (status);
4399 4402 }
4400 4403
4401 4404 /* ARGSUSED */
4402 4405 static dladm_status_t
4403 4406 set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4404 4407 val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4405 4408 {
4406 4409 dladm_status_t status;
4407 4410 dld_ioc_macprop_t *dip;
4408 4411 uint16_t pvid;
4409 4412
4410 4413 dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
4411 4414 0, &status);
4412 4415 if (dip == NULL)
4413 4416 return (status);
4414 4417 pvid = vdp->vd_val;
4415 4418 (void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
4416 4419 status = i_dladm_macprop(handle, dip, B_TRUE);
4417 4420 free(dip);
4418 4421 if (status != DLADM_STATUS_OK)
4419 4422 return (status);
4420 4423
4421 4424 /* Tell the running daemon, if any */
4422 4425 return (dladm_bridge_refresh(handle, linkid));
4423 4426 }
4424 4427
4425 4428 /* ARGSUSED */
4426 4429 static dladm_status_t
4427 4430 check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
4428 4431 datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
4429 4432 val_desc_t **vdpp, datalink_media_t media)
4430 4433 {
4431 4434 char *cp;
4432 4435 uint_t val_cnt = *val_cntp;
4433 4436 val_desc_t *vdp = *vdpp;
4434 4437
4435 4438 if (val_cnt != 1)
4436 4439 return (DLADM_STATUS_BADVALCNT);
4437 4440
4438 4441 if (prop_val == NULL) {
4439 4442 vdp->vd_val = 1;
4440 4443 } else {
4441 4444 errno = 0;
4442 4445 vdp->vd_val = strtoul(prop_val[0], &cp, 0);
4443 4446 if (errno != 0 || *cp != '\0')
4444 4447 return (DLADM_STATUS_BADVAL);
4445 4448 }
4446 4449
4447 4450 return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
4448 4451 DLADM_STATUS_OK);
4449 4452 }
4450 4453
4451 4454 dladm_status_t
4452 4455 i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
4453 4456 mac_prop_id_t cmd, size_t len, boolean_t set)
4454 4457 {
4455 4458 uint32_t flags;
4456 4459 dladm_status_t status;
4457 4460 uint32_t media;
4458 4461 dld_ioc_macprop_t *dip;
4459 4462 void *dp;
4460 4463
4461 4464 if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
4462 4465 &media, NULL, 0)) != DLADM_STATUS_OK) {
4463 4466 return (status);
4464 4467 }
4465 4468
4466 4469 if (media != DL_WIFI)
4467 4470 return (DLADM_STATUS_BADARG);
4468 4471
4469 4472 if (!(flags & DLADM_OPT_ACTIVE))
4470 4473 return (DLADM_STATUS_TEMPONLY);
4471 4474
4472 4475 if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
4473 4476 len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
4474 4477
4475 4478 dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
4476 4479 if (dip == NULL)
4477 4480 return (DLADM_STATUS_NOMEM);
4478 4481
4479 4482 dp = (uchar_t *)dip->pr_val;
4480 4483 if (set)
4481 4484 (void) memcpy(dp, buf, len);
4482 4485
4483 4486 status = i_dladm_macprop(handle, dip, set);
4484 4487 if (status == DLADM_STATUS_OK) {
4485 4488 if (!set)
4486 4489 (void) memcpy(buf, dp, len);
4487 4490 }
4488 4491
4489 4492 free(dip);
4490 4493 return (status);
4491 4494 }
4492 4495
4493 4496 dladm_status_t
4494 4497 dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
4495 4498 {
4496 4499 return (dladm_parse_args(str, listp, novalues));
4497 4500 }
4498 4501
4499 4502 /*
4500 4503 * Retrieve the one link property from the database
4501 4504 */
4502 4505 /*ARGSUSED*/
4503 4506 static int
4504 4507 i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
4505 4508 const char *prop_name, void *arg)
4506 4509 {
4507 4510 dladm_arg_list_t *proplist = arg;
4508 4511 dladm_arg_info_t *aip = NULL;
4509 4512
4510 4513 aip = &proplist->al_info[proplist->al_count];
4511 4514 /*
4512 4515 * it is fine to point to prop_name since prop_name points to the
4513 4516 * prop_table[n].pd_name.
4514 4517 */
4515 4518 aip->ai_name = prop_name;
4516 4519
4517 4520 (void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
4518 4521 prop_name, aip->ai_val, &aip->ai_count);
4519 4522
4520 4523 if (aip->ai_count != 0)
4521 4524 proplist->al_count++;
4522 4525
4523 4526 return (DLADM_WALK_CONTINUE);
4524 4527 }
4525 4528
4526 4529
4527 4530 /*
4528 4531 * Retrieve all link properties for a link from the database and
4529 4532 * return a property list.
4530 4533 */
4531 4534 dladm_status_t
4532 4535 dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
4533 4536 dladm_arg_list_t **listp)
4534 4537 {
4535 4538 dladm_arg_list_t *list;
4536 4539 dladm_status_t status = DLADM_STATUS_OK;
4537 4540
4538 4541 list = calloc(1, sizeof (dladm_arg_list_t));
4539 4542 if (list == NULL)
4540 4543 return (dladm_errno2status(errno));
4541 4544
4542 4545 status = dladm_walk_linkprop(handle, linkid, list,
4543 4546 i_dladm_get_one_prop);
4544 4547
4545 4548 *listp = list;
4546 4549 return (status);
4547 4550 }
4548 4551
4549 4552 /*
4550 4553 * Retrieve the named property from a proplist, check the value and
4551 4554 * convert to a kernel structure.
4552 4555 */
4553 4556 static dladm_status_t
4554 4557 i_dladm_link_proplist_extract_one(dladm_handle_t handle,
4555 4558 dladm_arg_list_t *proplist, const char *name, uint_t flags, void *arg)
4556 4559 {
4557 4560 dladm_status_t status;
4558 4561 dladm_arg_info_t *aip = NULL;
4559 4562 int i, j;
4560 4563
4561 4564 /* Find named property in proplist */
4562 4565 for (i = 0; i < proplist->al_count; i++) {
4563 4566 aip = &proplist->al_info[i];
4564 4567 if (strcasecmp(aip->ai_name, name) == 0)
4565 4568 break;
4566 4569 }
4567 4570
4568 4571 /* Property not in list */
4569 4572 if (i == proplist->al_count)
4570 4573 return (DLADM_STATUS_OK);
4571 4574
4572 4575 for (i = 0; i < DLADM_MAX_PROPS; i++) {
4573 4576 prop_desc_t *pdp = &prop_table[i];
4574 4577 val_desc_t *vdp;
4575 4578
4576 4579 vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
4577 4580 if (vdp == NULL)
4578 4581 return (DLADM_STATUS_NOMEM);
4579 4582
4580 4583 if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
4581 4584 continue;
4582 4585
4583 4586 if (aip->ai_val == NULL)
4584 4587 return (DLADM_STATUS_BADARG);
4585 4588
4586 4589 /* Check property value */
4587 4590 if (pdp->pd_check != NULL) {
4588 4591 status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
4589 4592 &(aip->ai_count), flags, &vdp, 0);
4590 4593 } else {
4591 4594 status = DLADM_STATUS_BADARG;
4592 4595 }
4593 4596
4594 4597 if (status != DLADM_STATUS_OK)
4595 4598 return (status);
4596 4599
4597 4600 for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
4598 4601 resource_prop_t *rpp = &rsrc_prop_table[j];
4599 4602
4600 4603 if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
4601 4604 continue;
4602 4605
4603 4606 /* Extract kernel structure */
4604 4607 if (rpp->rp_extract != NULL) {
4605 4608 status = rpp->rp_extract(vdp,
4606 4609 aip->ai_count, arg);
4607 4610 } else {
4608 4611 status = DLADM_STATUS_BADARG;
4609 4612 }
4610 4613 break;
4611 4614 }
4612 4615
4613 4616 if (status != DLADM_STATUS_OK)
4614 4617 return (status);
4615 4618
4616 4619 break;
4617 4620 }
4618 4621 return (status);
4619 4622 }
4620 4623
4621 4624 /*
4622 4625 * Extract properties from a proplist and convert to mac_resource_props_t.
4623 4626 */
4624 4627 dladm_status_t
4625 4628 dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
4626 4629 mac_resource_props_t *mrp, uint_t flags)
4627 4630 {
4628 4631 dladm_status_t status;
4629 4632 int i;
4630 4633
4631 4634 for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
4632 4635 status = i_dladm_link_proplist_extract_one(handle,
4633 4636 proplist, rsrc_prop_table[i].rp_name, flags, mrp);
4634 4637 if (status != DLADM_STATUS_OK)
4635 4638 return (status);
4636 4639 }
4637 4640 return (status);
4638 4641 }
4639 4642
4640 4643 static const char *
4641 4644 dladm_perm2str(uint_t perm, char *buf)
4642 4645 {
4643 4646 (void) snprintf(buf, DLADM_STRSIZE, "%c%c",
4644 4647 ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
4645 4648 ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
4646 4649 return (buf);
4647 4650 }
4648 4651
4649 4652 dladm_status_t
4650 4653 dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
4651 4654 link_state_t *state)
4652 4655 {
4653 4656 uint_t perms;
4654 4657
4655 4658 return (i_dladm_get_public_prop(handle, linkid, "state", 0,
4656 4659 &perms, state, sizeof (*state)));
4657 4660 }
4658 4661
4659 4662 boolean_t
4660 4663 dladm_attr_is_linkprop(const char *name)
4661 4664 {
4662 4665 /* non-property attribute names */
4663 4666 const char *nonprop[] = {
4664 4667 /* dlmgmtd core attributes */
4665 4668 "name",
4666 4669 "class",
4667 4670 "media",
4668 4671 FPHYMAJ,
4669 4672 FPHYINST,
4670 4673 FDEVNAME,
4671 4674
4672 4675 /* other attributes for vlan, aggr, etc */
4673 4676 DLADM_ATTR_NAMES
4674 4677 };
4675 4678 boolean_t is_nonprop = B_FALSE;
4676 4679 int i;
4677 4680
4678 4681 for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
4679 4682 if (strcmp(name, nonprop[i]) == 0) {
4680 4683 is_nonprop = B_TRUE;
4681 4684 break;
4682 4685 }
4683 4686 }
4684 4687
4685 4688 return (!is_nonprop);
4686 4689 }
4687 4690
4688 4691 dladm_status_t
4689 4692 dladm_linkprop_is_set(dladm_handle_t handle, datalink_id_t linkid,
4690 4693 dladm_prop_type_t type, const char *prop_name, boolean_t *is_set)
4691 4694 {
4692 4695 char *buf, **propvals;
4693 4696 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
4694 4697 int i;
4695 4698 dladm_status_t status = DLADM_STATUS_OK;
4696 4699 size_t bufsize;
4697 4700
4698 4701 *is_set = B_FALSE;
4699 4702
4700 4703 bufsize = (sizeof (char *) + DLADM_PROP_VAL_MAX) *
4701 4704 DLADM_MAX_PROP_VALCNT;
4702 4705 if ((buf = calloc(1, bufsize)) == NULL)
4703 4706 return (DLADM_STATUS_NOMEM);
4704 4707
4705 4708 propvals = (char **)(void *)buf;
4706 4709 for (i = 0; i < valcnt; i++) {
4707 4710 propvals[i] = buf +
4708 4711 sizeof (char *) * DLADM_MAX_PROP_VALCNT +
4709 4712 i * DLADM_PROP_VAL_MAX;
4710 4713 }
4711 4714
4712 4715 if (dladm_get_linkprop(handle, linkid, type, prop_name, propvals,
4713 4716 &valcnt) != DLADM_STATUS_OK) {
4714 4717 goto done;
4715 4718 }
4716 4719
4717 4720 /*
4718 4721 * valcnt is always set to 1 by get_pool(), hence we need to check
4719 4722 * for a non-null string to see if it is set. For protection,
4720 4723 * secondary-macs and allowed-ips, we can check either the *propval
4721 4724 * or the valcnt.
4722 4725 */
4723 4726 if ((strcmp(prop_name, "pool") == 0 ||
4724 4727 strcmp(prop_name, "protection") == 0 ||
4725 4728 strcmp(prop_name, "secondary-macs") == 0 ||
4726 4729 strcmp(prop_name, "allowed-ips") == 0) &&
4727 4730 (strlen(*propvals) != 0)) {
4728 4731 *is_set = B_TRUE;
4729 4732 } else if ((strcmp(prop_name, "cpus") == 0) && (valcnt != 0)) {
4730 4733 *is_set = B_TRUE;
4731 4734 } else if ((strcmp(prop_name, "_softmac") == 0) && (valcnt != 0) &&
4732 4735 (strcmp(propvals[0], "true") == 0)) {
4733 4736 *is_set = B_TRUE;
4734 4737 }
4735 4738
4736 4739 done:
4737 4740 if (buf != NULL)
4738 4741 free(buf);
4739 4742 return (status);
4740 4743 }
4741 4744
4742 4745 /* ARGSUSED */
4743 4746 static dladm_status_t
4744 4747 get_linkmode_prop(dladm_handle_t handle, prop_desc_t *pdp,
4745 4748 datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4746 4749 datalink_media_t media, uint_t flags, uint_t *perm_flags)
4747 4750 {
4748 4751 char *s;
4749 4752 uint32_t v;
4750 4753 dladm_status_t status;
4751 4754
4752 4755 status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4753 4756 perm_flags, &v, sizeof (v));
4754 4757 if (status != DLADM_STATUS_OK)
4755 4758 return (status);
4756 4759
4757 4760 switch (v) {
4758 4761 case DLADM_PART_CM_MODE:
4759 4762 s = "cm";
4760 4763 break;
4761 4764 case DLADM_PART_UD_MODE:
4762 4765 s = "ud";
4763 4766 break;
4764 4767 default:
4765 4768 s = "";
4766 4769 break;
4767 4770 }
4768 4771 (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s);
4769 4772
4770 4773 *val_cnt = 1;
4771 4774 return (DLADM_STATUS_OK);
4772 4775 }
|
↓ open down ↓ |
3231 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX