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