4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 * functions to handle legacy ndd ioctls
28 #include <sys/types.h>
30 #include <sys/mac_impl.h>
31 #include <sys/mac_client_priv.h>
33 #include <sys/mac_ether.h>
34 #include <sys/policy.h>
35 #include <sys/strsun.h>
37 static int mac_ndd_set_ioctl(mac_impl_t
*, mblk_t
*, int, int *);
38 static int mac_ndd_get_ioctl(mac_impl_t
*, mblk_t
*, int, int *);
39 static int mac_ndd_get_names(mac_impl_t
*, mblk_t
*);
40 static boolean_t
mac_add_name(mblk_t
*, char *, int);
43 * add "<name> (<rwtag>) " into the mblk, allocating more memory if needed.
46 mac_add_name(mblk_t
*mp
, char *name
, int ndd_flags
)
51 flags
= (ndd_flags
& (MAC_PROP_PERM_WRITE
|MAC_PROP_PERM_READ
));
54 rwtag
= "no read or write";
56 case MAC_PROP_PERM_WRITE
:
59 case MAC_PROP_PERM_READ
:
63 rwtag
= "read and write";
67 while (mp
->b_cont
!= NULL
)
70 * allocate space for name, <space>, '(', rwtag, ')', and
71 * two terminating null chars.
73 len
= strlen(name
) + strlen(rwtag
) + 6;
74 if (mp
->b_wptr
+ len
>= mp
->b_datap
->db_lim
) {
75 mp
->b_cont
= allocb(len
, BPRI_HI
);
80 cp
= (char *)mp
->b_wptr
;
81 (void) snprintf(cp
, len
, "%s (%s)", name
, rwtag
);
82 mp
->b_wptr
+= strnlen(cp
, len
);
83 mp
->b_wptr
++; /* skip past the terminating \0 */
89 * handle a query for "ndd -get \?". The result is put into mp, and
90 * more memory is allocated if needed. The resulting size of the data
94 mac_ndd_get_names(mac_impl_t
*mip
, mblk_t
*mp
)
103 if (!mac_add_name(mp
, "?", MAC_PROP_PERM_READ
))
106 /* first the known ndd mappings */
107 for (i
= 0; i
< mip
->mi_type
->mt_mappingcount
; i
++) {
108 if ((mip
->mi_type
->mt_mapping
[i
].mp_flags
& MAC_PROP_MAP_KSTAT
)
110 permflags
= MAC_PROP_PERM_READ
;
112 status
= mip
->mi_callbacks
->mc_getprop(mip
->mi_driver
,
113 mip
->mi_type
->mt_mapping
[i
].mp_name
,
114 mip
->mi_type
->mt_mapping
[i
].mp_prop_id
,
115 mip
->mi_type
->mt_mapping
[i
].mp_valsize
, &value
);
118 status
= mac_prop_info((mac_handle_t
)mip
,
119 mip
->mi_type
->mt_mapping
[i
].mp_prop_id
,
120 mip
->mi_type
->mt_mapping
[i
].mp_name
, NULL
, 0,
125 if (!mac_add_name(mp
, mip
->mi_type
->mt_mapping
[i
].mp_name
,
130 /* now the driver's ndd variables */
131 for (i
= 0; i
< mip
->mi_priv_prop_count
; i
++) {
133 prop_name
= mip
->mi_priv_prop
[i
];
135 if (mac_prop_info((mac_handle_t
)mip
, MAC_PROP_PRIVATE
,
136 prop_name
, NULL
, 0, NULL
, &permflags
) != 0)
139 /* skip over the "_" */
140 if (!mac_add_name(mp
, &prop_name
[1], permflags
))
145 while (tmp
->b_cont
!= NULL
)
147 *tmp
->b_wptr
++ = '\0';
148 size_out
= msgdsize(mp
);
154 * Handle legacy ndd ioctls for ND_GET and ND_SET.
157 mac_ndd_ioctl(mac_impl_t
*mip
, queue_t
*wq
, mblk_t
*mp
)
162 iocp
= (IOCP
)mp
->b_rptr
;
163 if (iocp
->ioc_count
== 0 || mp
->b_cont
== NULL
) {
171 err
= mac_ndd_set_ioctl(mip
, mp
, iocp
->ioc_count
, &rval
);
172 } else if (cmd
== ND_GET
) {
173 err
= mac_ndd_get_ioctl(mip
, mp
, iocp
->ioc_count
, &rval
);
177 miocack(wq
, mp
, msgdsize(mp
->b_cont
), rval
);
179 miocnak(wq
, mp
, 0, err
);
183 mac_ndd_get_ioctl(mac_impl_t
*mip
, mblk_t
*mp
, int avail
, int *rval
)
191 char *name
, priv_name
[MAXLINKPROPNAME
];
197 if (mp
->b_cont
== NULL
|| avail
< 2)
199 valp
= (char *)mp
->b_cont
->b_rptr
;
200 mp1
= allocb(avail
, BPRI_HI
); /* the returned buffer */
204 if (strcmp(valp
, "?") == 0) {
206 * handle "ndd -get <..> \?" queries.
208 size_out
= mac_ndd_get_names(mip
, mp1
);
213 if (size_out
> avail
) {
217 * need more user buffer space. Return as many
218 * mblks as will fit and return the needed
219 * buffer size in ioc_rval.
221 excess
= size_out
- avail
;
222 *rval
= size_out
; /* what's needed */
224 (void) adjmsg(mp1
, -(excess
+ 1));
225 cp
= (char *)mp1
->b_wptr
;
232 ASSERT(mip
->mi_callbacks
->mc_callbacks
& MC_GETPROP
);
234 valp
= (char *)mp1
->b_rptr
;
235 mp1
->b_wptr
= mp1
->b_rptr
;
237 /* first lookup ndd <-> public property mapping */
238 for (i
= 0; i
< mip
->mi_type
->mt_mappingcount
; i
++) {
239 if (strcmp(name
, mip
->mi_type
->mt_mapping
[i
].mp_name
) != 0)
242 switch (mip
->mi_type
->mt_mapping
[i
].mp_valsize
) {
244 value
= (uchar_t
*)&u8
;
247 value
= (uchar_t
*)&u16
;
250 value
= (uchar_t
*)&u32
;
253 value
= (uchar_t
*)&u64
;
257 if ((mip
->mi_type
->mt_mapping
[i
].mp_flags
& MAC_PROP_MAP_KSTAT
)
259 u64
= mac_stat_get((mac_handle_t
)mip
,
260 mip
->mi_type
->mt_mapping
[i
].mp_kstat
);
263 * ether_stats are all always KSTAT_DATA_UINT32
265 new_value
= u32
= (long)u64
;
267 status
= mip
->mi_callbacks
->mc_getprop(mip
->mi_driver
,
268 name
, mip
->mi_type
->mt_mapping
[i
].mp_prop_id
,
269 mip
->mi_type
->mt_mapping
[i
].mp_valsize
, value
);
270 switch (mip
->mi_type
->mt_mapping
[i
].mp_valsize
) {
282 * The only uint64_t is for speed, which is
283 * converted to Mbps in ndd reports.
285 new_value
= (u64
/1000000);
293 (void) snprintf(valp
, avail
, "%d", new_value
);
298 * could not find a public property. try the private prop route
299 * where all string processing will be done by the driver.
301 (void) snprintf(priv_name
, sizeof (priv_name
), "_%s", name
);
302 status
= mip
->mi_callbacks
->mc_getprop(mip
->mi_driver
, priv_name
,
303 MAC_PROP_PRIVATE
, avail
- 2, mp1
->b_rptr
);
308 size_out
+= strnlen((const char *)mp1
->b_rptr
, avail
);
310 *valp
++ = '\0'; /* need \0\0 */
312 mp1
->b_wptr
= (uchar_t
*)valp
;
327 mac_ndd_set_ioctl(mac_impl_t
*mip
, mblk_t
*mp
, int avail
, int *rval
)
330 char *valp
, *name
, *new_valuep
;
338 char priv_name
[MAXLINKPROPNAME
];
340 if (avail
== 0 || !(mp1
= mp
->b_cont
))
344 freemsg(mp1
->b_cont
);
347 mp1
->b_datap
->db_lim
[-1] = '\0';
348 valp
= (char *)mp1
->b_rptr
;
353 if (valp
>= (char *)mp1
->b_wptr
)
357 if (ddi_strtol(valp
, NULL
, 0, &new_value
) != 0)
360 iocp
= (IOCP
)mp
->b_rptr
;
362 ((iocp
->ioc_cr
== NULL
) ||
363 ((status
= secpolicy_net_config(iocp
->ioc_cr
, B_FALSE
)) != 0)))
368 /* first lookup ndd <-> public property mapping */
369 for (i
= 0; i
< mip
->mi_type
->mt_mappingcount
; i
++) {
370 if (strcmp(name
, mip
->mi_type
->mt_mapping
[i
].mp_name
) != 0)
373 if (mip
->mi_type
->mt_mapping
[i
].mp_flags
& MAC_PROP_MAP_KSTAT
)
376 if (new_value
> mip
->mi_type
->mt_mapping
[i
].mp_maxval
||
377 new_value
< mip
->mi_type
->mt_mapping
[i
].mp_minval
||
378 (mip
->mi_type
->mt_mapping
[i
].mp_flags
& MAC_PROP_PERM_WRITE
)
381 switch (mip
->mi_type
->mt_mapping
[i
].mp_valsize
) {
383 u8
= (uint8_t)new_value
;
387 u16
= (uint16_t)new_value
;
388 vp
= (uchar_t
*)&u16
;
391 u32
= (uint32_t)new_value
;
392 vp
= (uchar_t
*)&u32
;
395 vp
= (uchar_t
*)&new_value
;
401 status
= mip
->mi_callbacks
->mc_setprop(mip
->mi_driver
,
402 name
, mip
->mi_type
->mt_mapping
[i
].mp_prop_id
,
403 mip
->mi_type
->mt_mapping
[i
].mp_valsize
, (const void *)vp
);
408 (void) snprintf(priv_name
, sizeof (priv_name
), "_%s", name
);
409 status
= mip
->mi_callbacks
->mc_setprop(mip
->mi_driver
, priv_name
,
410 MAC_PROP_PRIVATE
, strlen(new_valuep
), new_valuep
);