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