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