open-isns: Fix warnings reported by gcc-4.5.2
[open-iscsi.git] / usr / ioctl.c
blob3d67accb512c07493b2fb2fb8af8a6f32738cb89
1 /*
2 * iSCSI Ioctl/Unix Interface
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * maintained by open-iscsi@googlegroups.com
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * See the file COPYING included with this distribution for more details.
20 #include <ctype.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
30 #include "iscsi_if.h"
31 #include "iscsid.h"
32 #include "log.h"
33 #include "iscsi_ipc.h"
35 #define CTL_DEVICE "/dev/iscsictl"
37 static int ctrl_fd;
38 static void *xmitbuf = NULL;
39 static int xmitlen = 0;
40 static void *recvbuf = NULL;
41 static int recvlen = 0;
42 static void *ioctl_sendbuf;
43 static void *ioctl_recvbuf;
44 static void *pdu_sendbuf;
46 #define IOCTL_BUF_DEFAULT_MAX \
47 (ISCSI_DEF_MAX_RECV_SEG_LEN + sizeof(struct iscsi_hdr))
49 #define PDU_SENDBUF_DEFAULT_MAX \
50 (ISCSI_DEF_MAX_RECV_SEG_LEN + sizeof(struct iscsi_hdr))
52 static int
53 kread(char *data, int count)
55 log_debug(7, "in %s", __FUNCTION__);
56 return count;
59 static int
60 kwritev(enum iscsi_uevent_e type, struct iovec *iovp, int count)
62 log_debug(7, "in %s", __FUNCTION__);
63 return 0;
67 * __kipc_call() should never block
69 static int
70 __kipc_call(void *iov_base, int iov_len)
72 log_debug(7, "in %s", __FUNCTION__);
73 return 0;
76 static int
77 kcreate_session(uint64_t transport_handle, uint32_t initial_cmdsn,
78 uint32_t *out_sid, uint32_t *out_hostno)
80 int rc;
81 struct iscsi_uevent ev;
83 log_debug(7, "in %s", __FUNCTION__);
85 memset(&ev, 0, sizeof(struct iscsi_uevent));
87 ev.type = ISCSI_UEVENT_CREATE_SESSION;
88 ev.transport_handle = transport_handle;
89 ev.u.c_session.initial_cmdsn = initial_cmdsn;
91 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
92 return rc;
94 if (!ev.r.c_session_ret.session_handle || ev.r.c_session_ret.sid < 0)
95 return -EIO;
97 *out_handle = ev.r.c_session_ret.session_handle;
98 *out_sid = ev.r.c_session_ret.sid;
100 return 0;
103 static int
104 kdestroy_session(uint64_t transport_handle, uint64_t sessionh, uint32_t sid)
106 int rc;
107 struct iscsi_uevent ev;
109 log_debug(7, "in %s", __FUNCTION__);
111 memset(&ev, 0, sizeof(struct iscsi_uevent));
113 ev.type = ISCSI_UEVENT_DESTROY_SESSION;
114 ev.transport_handle = transport_handle;
115 ev.u.d_session.session_handle = sessionh;
116 ev.u.d_session.sid = sid;
118 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
119 return rc;
122 return 0;
125 static int
126 kcreate_conn(uint64_t transport_handle, uint64_t sessionh, uint32_t sid,
127 uint32_t cid, uint64_t *out_handle)
129 int rc;
130 struct iscsi_uevent ev;
132 log_debug(7, "in %s", __FUNCTION__);
134 memset(&ev, 0, sizeof(struct iscsi_uevent));
136 ev.type = ISCSI_UEVENT_CREATE_CONN;
137 ev.transport_handle = transport_handle;
138 ev.u.c_conn.session_handle = sessionh;
139 ev.u.c_conn.cid = cid;
140 ev.u.c_conn.sid = sid;
142 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
143 return rc;
145 if (!ev.r.handle)
146 return -EIO;
148 *out_handle = ev.r.handle;
149 return 0;
152 static int
153 kdestroy_conn(uint64_t transport_handle, uint64_t connh, int cid)
155 int rc;
156 struct iscsi_uevent ev;
158 log_debug(7, "in %s", __FUNCTION__);
160 memset(&ev, 0, sizeof(struct iscsi_uevent));
162 ev.type = ISCSI_UEVENT_DESTROY_CONN;
163 ev.transport_handle = transport_handle;
164 ev.u.d_conn.conn_handle = connh;
165 ev.u.d_conn.cid = cid;
167 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
168 return rc;
171 return 0;
174 static int
175 kbind_conn(uint64_t transport_handle, uint64_t sessionh, uint64_t connh,
176 uint32_t transport_fd, int is_leading, int *retcode)
178 int rc;
179 struct iscsi_uevent ev;
181 log_debug(7, "in %s", __FUNCTION__);
183 memset(&ev, 0, sizeof(struct iscsi_uevent));
185 ev.type = ISCSI_UEVENT_BIND_CONN;
186 ev.transport_handle = transport_handle;
187 ev.u.b_conn.session_handle = sessionh;
188 ev.u.b_conn.conn_handle = connh;
189 ev.u.b_conn.transport_fd = transport_fd;
190 ev.u.b_conn.is_leading = is_leading;
192 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
193 return rc;
196 *retcode = ev.r.retcode;
198 return 0;
201 static void
202 ksend_pdu_begin(uint64_t transport_handle, uint64_t connh,
203 int hdr_size, int data_size)
205 struct iscsi_uevent *ev;
207 log_debug(7, "in %s", __FUNCTION__);
209 if (xmitbuf) {
210 log_error("send's begin state machine bug?");
211 exit(-EIO);
214 xmitbuf = pdu_sendbuf;
215 memset(xmitbuf, 0, sizeof(*ev) + hdr_size + data_size);
216 xmitlen = sizeof(*ev);
217 ev = xmitbuf;
218 memset(ev, 0, sizeof(*ev));
219 ev->type = ISCSI_UEVENT_SEND_PDU;
220 ev->transport_handle = transport_handle;
221 ev->u.send_pdu.conn_handle = connh;
222 ev->u.send_pdu.hdr_size = hdr_size;
223 ev->u.send_pdu.data_size = data_size;
225 log_debug(3, "send PDU began for hdr %d bytes and data %d bytes",
226 hdr_size, data_size);
229 static int
230 ksend_pdu_end(uint64_t transport_handle, uint64_t connh, int *retcode)
232 int rc;
233 struct iscsi_uevent *ev;
234 struct iovec iov;
236 log_debug(7, "in %s", __FUNCTION__);
238 if (!xmitbuf) {
239 log_error("send's end state machine bug?");
240 exit(-EIO);
242 ev = xmitbuf;
243 if (ev->u.send_pdu.conn_handle != connh) {
244 log_error("send's end state machine corruption?");
245 exit(-EIO);
248 iov.iov_base = xmitbuf;
249 iov.iov_len = xmitlen;
251 if ((rc = __kipc_call(xmitbuf, xmitlen)) < 0)
252 goto err;
253 if (ev->r.retcode) {
254 *retcode = ev->r.retcode;
255 goto err;
257 if (ev->type != ISCSI_UEVENT_SEND_PDU) {
258 log_error("bad event: bug on send_pdu_end?");
259 exit(-EIO);
262 log_debug(3, "send PDU finished for conn (handle %p)", iscsi_ptr(connh));
264 xmitbuf = NULL;
265 return 0;
267 err:
268 xmitbuf = NULL;
269 xmitlen = 0;
270 return rc;
273 static int
274 kset_param(uint64_t transport_handle, uint64_t connh,
275 enum iscsi_param param, uint32_t value, int *retcode)
277 int rc;
278 struct iscsi_uevent ev;
280 log_debug(7, "in %s", __FUNCTION__);
282 memset(&ev, 0, sizeof(struct iscsi_uevent));
284 ev.type = ISCSI_UEVENT_SET_PARAM;
285 ev.transport_handle = transport_handle;
286 ev.u.set_param.conn_handle = connh;
287 ev.u.set_param.param = param;
288 ev.u.set_param.value = value;
290 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
291 return rc;
294 *retcode = ev.r.retcode;
296 return 0;
299 static int
300 kstop_conn(uint64_t transport_handle, uint64_t connh, int flag)
302 int rc;
303 struct iscsi_uevent ev;
305 log_debug(7, "in %s", __FUNCTION__);
307 memset(&ev, 0, sizeof(struct iscsi_uevent));
309 ev.type = ISCSI_UEVENT_STOP_CONN;
310 ev.transport_handle = transport_handle;
311 ev.u.stop_conn.conn_handle = connh;
312 ev.u.stop_conn.flag = flag;
314 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
315 return rc;
318 return 0;
321 static int
322 kstart_conn(uint64_t transport_handle, uint64_t connh, int *retcode)
324 int rc;
325 struct iscsi_uevent ev;
327 log_debug(7, "in %s", __FUNCTION__);
329 memset(&ev, 0, sizeof(struct iscsi_uevent));
331 ev.type = ISCSI_UEVENT_START_CONN;
332 ev.transport_handle = transport_handle;
333 ev.u.start_conn.conn_handle = connh;
335 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
336 return rc;
339 *retcode = ev.r.retcode;
340 return 0;
343 static int
344 krecv_pdu_begin(uint64_t transport_handle, uint64_t connh,
345 uintptr_t recv_handle, uintptr_t *pdu_handle, int *pdu_size)
347 log_debug(7, "in %s", __FUNCTION__);
349 if (recvbuf) {
350 log_error("recv's begin state machine bug?");
351 return -EIO;
353 recvbuf = (void*)recv_handle + sizeof(struct iscsi_uevent);
354 recvlen = 0;
355 *pdu_handle = recv_handle;
357 log_debug(3, "recv PDU began, pdu handle 0x%p",
358 (void*)*pdu_handle);
360 return 0;
363 static int
364 krecv_pdu_end(uint64_t transport_handle, uintptr_t conn_handle,
365 uintptr_t pdu_handle)
367 log_debug(7, "in %s", __FUNCTION__);
369 if (!recvbuf) {
370 log_error("recv's end state machine bug?");
371 return -EIO;
374 log_debug(3, "recv PDU finished for pdu handle 0x%p",
375 (void*)pdu_handle);
377 recvpool_put((void*)conn_handle, (void*)pdu_handle);
378 recvbuf = NULL;
379 return 0;
382 static int
383 ktrans_list(void)
385 struct iscsi_uevent ev;
386 int rc;
388 log_debug(7, "in %s", __FUNCTION__);
390 memset(ev, 0, sizeof(struct iscsi_uevent));
392 * need to define this for bsd
394 ev->type = ISCSI_UEVENT_TRANS_LIST;
396 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
397 return rc;
400 for (i = 0; i < ISCSI_TRANSPORT_MAX; i++) {
401 if (ev.r.t_list.elements[i].trans_handle) {
402 provider[i].handle =
403 ev.r.t_list.elements[i].trans_handle;
404 strncpy(provider[i].name, ev.r.t_list.elements[i].name,
405 ISCSI_TRANSPORT_NAME_MAXLEN);
406 provider[i].caps = ev.r.t_list.elements[i].caps;
409 return 0;
412 static int
413 ctldev_handle(void)
415 log_debug(7, "in %s", __FUNCTION__);
416 return 0;
419 static int
420 ctldev_open(void)
422 log_debug(7, "in %s", __FUNCTION__);
424 ioctl_sendbuf = calloc(1, IOCTL_BUF_DEFAULT_MAX);
425 if (!ioctl_sendbuf) {
426 log_error("can not allocate ioctl_sendbuf");
427 return -1;
430 ioctl_recvbuf = calloc(1, IOCTL_BUF_DEFAULT_MAX);
431 if (!ioctl_recvbuf) {
432 free(ioctl_sendbuf);
433 log_error("can not allocate ioctl_recvbuf");
434 return -1;
437 pdu_sendbuf = calloc(1, PDU_SENDBUF_DEFAULT_MAX);
438 if (!pdu_sendbuf) {
439 free(ioctl_recvbuf);
440 free(ioctl_sendbuf);
441 log_error("can not allocate ioctl_sendbuf");
442 return -1;
445 return ctrl_fd;
448 static void
449 ctldev_close(void)
451 free(pdu_sendbuf);
452 free(ioctl_recvbuf);
453 free(ioctl_sendbuf);
454 //close(ctrl_fd);
457 struct iscsi_ipc ioctl_ipc = {
458 .name = "Open-iSCSI Kernel IPC/IOCTL v.1",
459 .ctldev_bufmax = IOCTL_BUF_DEFAULT_MAX,
460 .ctldev_open = ctldev_open,
461 .ctldev_close = ctldev_close,
462 .ctldev_handle = ctldev_handle,
463 .trans_list = ktrans_list,
464 .create_session = kcreate_session,
465 .destroy_session = kdestroy_session,
466 .create_conn = kcreate_conn,
467 .destroy_conn = kdestroy_conn,
468 .bind_conn = kbind_conn,
469 .set_param = kset_param,
470 .get_param = NULL,
471 .start_conn = kstart_conn,
472 .stop_conn = kstop_conn,
473 .writev = kwritev,
474 .send_pdu_begin = ksend_pdu_begin,
475 .send_pdu_end = ksend_pdu_end,
476 .read = kread,
477 .recv_pdu_begin = krecv_pdu_begin,
478 .recv_pdu_end = krecv_pdu_end,
480 struct iscsi_ipc *ipc = &ioctl_ipc;