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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Logical Domains Device Agent
34 #include <libdllink.h>
40 #include <sys/param.h>
41 #include <sys/types.h>
46 #define LDMA_MODULE LDMA_NAME_DEVICE
48 #define LDMA_NVERSIONS (sizeof (ldma_versions) / sizeof (ds_ver_t))
49 #define LDMA_NHANDLERS (sizeof (ldma_handlers) / sizeof (ldma_msg_handler_t))
51 static ldm_msg_func_t ldma_dev_validate_path
;
52 static ldm_msg_func_t ldma_dev_validate_nic
;
54 static ds_ver_t ldma_versions
[] = { { 1, 0 } };
56 static ldma_msg_handler_t ldma_handlers
[] = {
57 { LDMA_MSGDEV_VALIDATE_PATH
, LDMA_MSGFLG_ACCESS_CONTROL
,
58 ldma_dev_validate_path
},
59 { LDMA_MSGDEV_VALIDATE_NIC
, LDMA_MSGFLG_ACCESS_CONTROL
,
60 ldma_dev_validate_nic
}
63 ldma_agent_info_t ldma_device_info
= {
65 ldma_versions
, LDMA_NVERSIONS
,
66 ldma_handlers
, LDMA_NHANDLERS
70 static ldma_request_status_t
71 ldma_dev_validate_path(ds_ver_t
*ver
, ldma_message_header_t
*request
,
72 size_t request_dlen
, ldma_message_header_t
**replyp
, size_t *reply_dlenp
)
74 ldma_message_header_t
*reply
= NULL
;
75 ldma_request_status_t status
;
78 uint32_t *path_type
, reply_dlen
;
82 plen
= request
->msg_info
;
83 if (plen
== 0 || plen
> MAXPATHLEN
|| plen
> request_dlen
) {
84 status
= LDMA_REQ_INVALID
;
88 path
= malloc(plen
+ 1);
90 status
= LDMA_REQ_FAILED
;
94 (void) strncpy(path
, LDMA_HDR2DATA(request
), plen
);
97 LDMA_DBG("VALIDATE_PATH(%s)", path
);
99 reply_dlen
= sizeof (uint32_t);
100 reply
= ldma_alloc_result_msg(request
, reply_dlen
);
102 status
= LDMA_REQ_FAILED
;
106 /* LINTED E_BAD_PTR_CAST_ALIGN */
107 path_type
= (uint32_t *)(LDMA_HDR2DATA(reply
));
109 reply
->msg_info
= 0x0;
111 /* check if path exists */
112 if (stat(path
, &st
) != 0) {
114 LDMA_DBG("VALIDATE_PATH(%s): stat failed with error %d",
124 /* path is inaccessible, the request is completed */
125 status
= LDMA_REQ_COMPLETED
;
129 status
= LDMA_REQ_INVALID
;
133 /* request has failed */
134 status
= LDMA_REQ_FAILED
;
141 status
= LDMA_REQ_COMPLETED
;
143 reply
->msg_info
|= LDMA_DEVPATH_EXIST
;
145 LDMA_DBG("VALIDATE_PATH(%s): file mode = 0x%lx", path
, st
.st_mode
);
147 switch (st
.st_mode
& S_IFMT
) {
150 *path_type
= LDMA_DEVPATH_TYPE_FILE
;
155 *path_type
= LDMA_DEVPATH_TYPE_DEVICE
;
159 /* we don't advertise other types (fifo, directory...) */
163 /* check if path can be opened read/write */
164 if ((fd
= open(path
, O_RDWR
)) != -1) {
165 reply
->msg_info
|= LDMA_DEVPATH_OPENRW
| LDMA_DEVPATH_OPENRO
;
168 LDMA_DBG("VALIDATE_PATH(%s): open RDWR failed with error %d",
171 /* check if path can be opened read only */
172 if ((fd
= open(path
, O_RDONLY
)) != -1) {
173 reply
->msg_info
|= LDMA_DEVPATH_OPENRO
;
176 LDMA_DBG("VALIDATE_PATH(%s): open RDONLY failed "
177 "with error %d", path
, errno
);
182 if (status
!= LDMA_REQ_COMPLETED
) {
184 * We don't provide a reply message if the request has not
185 * been completed. The LDoms agent daemon will send an
186 * appropriate reply based on the return code of this function.
192 LDMA_DBG("VALIDATE_PATH(%s): return error %d",
193 (path
)? path
: "<none>", status
);
195 LDMA_DBG("VALIDATE_PATH(%s): return status=0x%x type=0x%x",
196 path
, reply
->msg_info
, *path_type
);
201 *reply_dlenp
= reply_dlen
;
207 * We check that the device is a network interface (NIC) using libdladm.
210 static ldma_request_status_t
211 ldma_dev_validate_nic(ds_ver_t
*ver
, ldma_message_header_t
*request
,
212 size_t request_dlen
, ldma_message_header_t
**replyp
, size_t *reply_dlenp
)
214 dladm_handle_t dlhandle
;
215 datalink_id_t linkid
;
216 uint32_t flag
, media
;
217 datalink_class_t
class;
218 ldma_message_header_t
*reply
= NULL
;
219 ldma_request_status_t status
;
221 uint32_t nlen
, reply_dlen
;
223 nlen
= request
->msg_info
;
224 if (nlen
== 0 || nlen
> MAXPATHLEN
|| nlen
> request_dlen
) {
225 status
= LDMA_REQ_INVALID
;
229 nic
= malloc(nlen
+ 1);
231 status
= LDMA_REQ_FAILED
;
235 (void) strncpy(nic
, LDMA_HDR2DATA(request
), nlen
);
238 LDMA_DBG("VALIDATE_NIC(%s)", nic
);
241 reply
= ldma_alloc_result_msg(request
, reply_dlen
);
243 status
= LDMA_REQ_FAILED
;
247 reply
->msg_info
= 0x0;
249 if (dladm_open(&dlhandle
) != DLADM_STATUS_OK
) {
250 status
= LDMA_REQ_FAILED
;
254 if (dladm_name2info(dlhandle
, nic
, &linkid
, &flag
, &class,
255 &media
) != DLADM_STATUS_OK
) {
256 LDMA_DBG("VALIDATE_NIC(%s): name2info failed", nic
);
258 LDMA_DBG("VALIDATE_NIC(%s): media=0x%x", nic
, media
);
259 reply
->msg_info
= LDMA_DEVNIC_EXIST
;
262 dladm_close(dlhandle
);
264 status
= LDMA_REQ_COMPLETED
;
267 if (status
!= LDMA_REQ_COMPLETED
) {
269 * We don't provide a reply message if the request has not
270 * been completed. The LDoms agent daemon will send an
271 * appropriate reply based on the return code of this function.
277 LDMA_DBG("VALIDATE_NIC(%s): return error %d",
278 (nic
)? nic
: "<none>", status
);
280 LDMA_DBG("VALIDATE_NIC(%s): return status=0x%x",
281 nic
, reply
->msg_info
);
286 *reply_dlenp
= reply_dlen
;