usr/config.h: fix comment for struct iscsi_session_timeout_config
[open-iscsi.git] / usr / netlink.c
blob801ee6f8fcf3b0cad958ade5e67dc5a2d5286c56
1 /*
2 * iSCSI Netlink/Linux Interface
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * Copyright (C) 2006 Mike Christie
6 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
7 * maintained by open-iscsi@googlegroups.com
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * See the file COPYING included with this distribution for more details.
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdint.h>
27 #include <errno.h>
28 #include <inttypes.h>
29 #include <asm/types.h>
30 #include <sys/socket.h>
31 #include <sys/types.h>
32 #include <linux/netlink.h>
34 #include "types.h"
35 #include "iscsi_if.h"
36 #include "log.h"
37 #include "iscsi_ipc.h"
38 #include "initiator.h"
39 #include "iscsi_sysfs.h"
40 #include "transport.h"
42 static int ctrl_fd;
43 static struct sockaddr_nl src_addr, dest_addr;
44 static void *xmitbuf = NULL;
45 static int xmitlen = 0;
46 static void *recvbuf = NULL;
47 static int recvlen = 0;
48 static void *nlm_sendbuf;
49 static void *nlm_recvbuf;
50 static void *pdu_sendbuf;
51 static void *setparam_buf;
52 static struct iscsi_ipc_ev_clbk *ipc_ev_clbk;
54 static int ctldev_handle(void);
56 #define NLM_BUF_DEFAULT_MAX (NLMSG_SPACE(ISCSI_DEF_MAX_RECV_SEG_LEN + \
57 sizeof(struct iscsi_uevent) + \
58 sizeof(struct iscsi_hdr)))
60 #define PDU_SENDBUF_DEFAULT_MAX (ISCSI_DEF_MAX_RECV_SEG_LEN + \
61 sizeof(struct iscsi_uevent) + \
62 sizeof(struct iscsi_hdr))
64 #define NLM_SETPARAM_DEFAULT_MAX (NI_MAXHOST + 1 + sizeof(struct iscsi_uevent))
66 static int
67 kread(char *data, int count)
69 log_debug(7, "in %s %u %u %p %p", __FUNCTION__, recvlen, count,
70 data, recvbuf);
72 memcpy(data, recvbuf + recvlen, count);
73 recvlen += count;
74 return count;
77 static int
78 nl_read(int ctrl_fd, char *data, int size, int flags)
80 int rc;
81 struct iovec iov;
82 struct msghdr msg;
84 log_debug(7, "in %s", __FUNCTION__);
86 iov.iov_base = data;
87 iov.iov_len = size;
89 memset(&msg, 0, sizeof(msg));
90 msg.msg_name= (void*)&src_addr;
91 msg.msg_namelen = sizeof(src_addr);
92 msg.msg_iov = &iov;
93 msg.msg_iovlen = 1;
95 rc = recvmsg(ctrl_fd, &msg, flags);
97 return rc;
100 static int
101 nlpayload_read(int ctrl_fd, char *data, int count, int flags)
103 int rc;
104 struct iovec iov;
105 struct msghdr msg;
107 log_debug(7, "in %s", __FUNCTION__);
109 iov.iov_base = nlm_recvbuf;
110 iov.iov_len = NLMSG_SPACE(count);
112 if (iov.iov_len > NLM_BUF_DEFAULT_MAX) {
113 log_error("Cannot read %lu bytes. nlm_recvbuf too small.",
114 iov.iov_len);
115 return -1;
117 memset(iov.iov_base, 0, iov.iov_len);
119 memset(&msg, 0, sizeof(msg));
120 msg.msg_name= (void*)&src_addr;
121 msg.msg_namelen = sizeof(src_addr);
122 msg.msg_iov = &iov;
123 msg.msg_iovlen = 1;
126 * Netlink recvmsg call path:
128 * - transport api callback
129 * - iscsi_control_conn_error (should succeed)
130 * - iscsi_unicast_skb (must succeed)
131 * - netlink_unicast (must succeed)
132 * - netlink_data_ready (must succeed)
133 * - netlink_sendskb (must succeed)
134 * - netlink_recvmsg (must succeed)
135 * - sock_recvmsg (must succeed)
136 * - sys_recvmsg (must succeed)
137 * - sys_socketcall (must succeed)
138 * - syscall_call (must succeed)
140 * Note1: "must succeed" means succeed unless bug in daemon.
141 * It also means - no sleep and memory allocation on
142 * the path.
144 * Note2: "should succeed" means will succeed in most of cases
145 * because of mempool preallocation.
147 * FIXME: if "Note2" than interface should generate iSCSI error
148 * level 0 on its own. Interface must always succeed on this.
150 rc = recvmsg(ctrl_fd, &msg, flags);
152 if (data)
153 memcpy(data, NLMSG_DATA(iov.iov_base), count);
155 return rc;
158 static int
159 kwritev(enum iscsi_uevent_e type, struct iovec *iovp, int count)
161 int i, rc;
162 struct nlmsghdr *nlh;
163 struct msghdr msg;
164 int datalen = 0;
166 log_debug(7, "in %s", __FUNCTION__);
168 for (i = 0; i < count; i++) {
169 datalen += iovp[i].iov_len;
172 if (xmitbuf && type != ISCSI_UEVENT_SEND_PDU) {
173 for (i = 0; i < count; i++) {
174 memcpy(xmitbuf + xmitlen,
175 iovp[i].iov_base, iovp[i].iov_len);
176 xmitlen += iovp[i].iov_len;
178 return datalen;
181 nlh = nlm_sendbuf;
182 memset(nlh, 0, NLMSG_SPACE(0));
184 datalen = 0;
185 for (i = 1; i < count; i++)
186 datalen += iovp[i].iov_len;
188 nlh->nlmsg_len = NLMSG_ALIGN(datalen);
189 nlh->nlmsg_pid = getpid();
190 nlh->nlmsg_flags = 0;
191 nlh->nlmsg_type = type;
193 iovp[0].iov_base = (void *)nlh;
194 iovp[0].iov_len = sizeof(*nlh);
196 memset(&msg, 0, sizeof(msg));
197 msg.msg_name= (void*)&dest_addr;
198 msg.msg_namelen = sizeof(dest_addr);
199 msg.msg_iov = iovp;
200 msg.msg_iovlen = count;
202 do {
204 * Netlink down call path:
206 * - transport api call
207 * - iscsi_if_recv_msg (must succeed)
208 * - iscsi_if_rx (must succeed)
209 * - netlink_data_ready (must succeed)
210 * - netlink_sendskb (must succeed)
211 * - netlink_sendmsg (alloc_skb() might fail)
212 * - sock_sendmsg (must succeed)
213 * - sys_sendmsg (must succeed)
214 * - sys_socketcall (must succeed)
215 * - syscall_call (must succeed)
217 * Note1: "must succeed" means succeed unless bug in daemon.
218 * It also means - no sleep and memory allocation on
219 * the path.
221 * Note2: netlink_sendmsg() might fail because of OOM. Since
222 * we are in user-space, we will sleep until we succeed.
225 rc = sendmsg(ctrl_fd, &msg, 0);
226 if (rc == -ENOMEM) {
227 log_debug(1, "sendmsg: alloc_skb() failed");
228 sleep(1);
229 } else if (rc < 0) {
230 log_error("sendmsg: bug? ctrl_fd %d", ctrl_fd);
231 exit(rc);
233 } while (rc < 0);
235 return rc;
239 * __kipc_call() should never block. Therefore
240 * Netlink's xmit logic is serialized. This means we do not allocate on
241 * xmit path. Instead we reuse nlm_sendbuf buffer.
243 * Transport must assure non-blocking operations for:
245 * - session_create()
246 * - conn_create()
247 * - conn_bind()
248 * _ set_param()
249 * - conn_start()
250 * - conn_stop()
252 * Its OK to block for cleanup for short period of time in operatations for:
254 * - conn_destroy()
255 * - session_destroy()
257 * FIXME: interface needs to be extended to allow longer blocking on
258 * cleanup. (Dima)
260 static int
261 __kipc_call(struct iovec *iovp, int count)
263 int rc, iferr;
264 struct iscsi_uevent *ev = iovp[1].iov_base;
265 enum iscsi_uevent_e type = ev->type;
267 log_debug(7, "in %s", __FUNCTION__);
269 rc = kwritev(type, iovp, count);
271 do {
272 if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
273 sizeof(*ev), MSG_PEEK)) < 0) {
274 return rc;
276 if (ev->type != type) {
277 log_debug(1, "expecting event %d, got %d, handling...",
278 type, ev->type);
279 if (ev->type == ISCSI_KEVENT_IF_ERROR) {
280 if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
281 sizeof(*ev), 0)) < 0) {
282 return rc;
285 * iferror is u32, but the kernel returns
286 * negative errno values for errors.
288 iferr = ev->iferror;
290 if (iferr == -ENOSYS)
291 /* not fatal so let caller handle log */
292 log_debug(1, "Received iferror %d: %s.",
293 iferr, strerror(-iferr));
294 else if (iferr < 0)
295 log_error("Received iferror %d: %s.",
296 iferr, strerror(-iferr));
297 else
298 log_error("Received iferror %d.",
299 iferr);
300 return ev->iferror;
303 * receive and queue async. event which as of
304 * today could be:
305 * - CONN_ERROR
306 * - RECV_PDU
308 ctldev_handle();
309 } else if (ev->type == ISCSI_UEVENT_GET_STATS) {
310 /* kget_stats() will read */
311 return 0;
312 } else {
313 if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
314 sizeof(*ev), 0)) < 0) {
315 return rc;
317 break;
319 } while (ev->type != type);
321 return rc;
324 static int
325 ksendtargets(uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr)
327 int rc, addrlen;
328 struct iscsi_uevent *ev;
329 struct iovec iov[2];
331 log_debug(7, "in %s", __FUNCTION__);
333 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
334 ev = (struct iscsi_uevent *)setparam_buf;
335 ev->type = ISCSI_UEVENT_TGT_DSCVR;
336 ev->transport_handle = transport_handle;
337 ev->u.tgt_dscvr.type = ISCSI_TGT_DSCVR_SEND_TARGETS;
338 ev->u.tgt_dscvr.host_no = host_no;
340 if (addr->sa_family == PF_INET)
341 addrlen = sizeof(struct sockaddr_in);
342 else if (addr->sa_family == PF_INET6)
343 addrlen = sizeof(struct sockaddr_in6);
344 else {
345 log_error("%s unknown addr family %d\n",
346 __FUNCTION__, addr->sa_family);
347 return -EINVAL;
349 memcpy(setparam_buf + sizeof(*ev), addr, addrlen);
351 iov[1].iov_base = ev;
352 iov[1].iov_len = sizeof(*ev) + addrlen;
353 rc = __kipc_call(iov, 2);
354 if (rc < 0) {
355 log_error("sendtargets failed rc%d\n", rc);
356 return rc;
358 return 0;
361 static int
362 kcreate_session(uint64_t transport_handle, uint64_t ep_handle,
363 uint32_t initial_cmdsn, uint16_t cmds_max, uint16_t qdepth,
364 uint32_t *out_sid, uint32_t *hostno)
366 int rc;
367 struct iscsi_uevent ev;
368 struct iovec iov[2];
370 log_debug(7, "in %s", __FUNCTION__);
372 memset(&ev, 0, sizeof(struct iscsi_uevent));
374 if (ep_handle == 0) {
375 ev.type = ISCSI_UEVENT_CREATE_SESSION;
376 ev.transport_handle = transport_handle;
377 ev.u.c_session.initial_cmdsn = initial_cmdsn;
378 ev.u.c_session.cmds_max = cmds_max;
379 ev.u.c_session.queue_depth = qdepth;
380 } else {
381 ev.type = ISCSI_UEVENT_CREATE_BOUND_SESSION;
382 ev.transport_handle = transport_handle;
383 ev.u.c_bound_session.initial_cmdsn = initial_cmdsn;
384 ev.u.c_bound_session.cmds_max = cmds_max;
385 ev.u.c_bound_session.queue_depth = qdepth;
386 ev.u.c_bound_session.ep_handle = ep_handle;
389 iov[1].iov_base = &ev;
390 iov[1].iov_len = sizeof(ev);
391 rc = __kipc_call(iov, 2);
392 if (rc < 0)
393 return rc;
395 *hostno = ev.r.c_session_ret.host_no;
396 *out_sid = ev.r.c_session_ret.sid;
398 return 0;
401 static int
402 kdestroy_session(uint64_t transport_handle, uint32_t sid)
404 int rc;
405 struct iscsi_uevent ev;
406 struct iovec iov[2];
408 log_debug(7, "in %s", __FUNCTION__);
410 memset(&ev, 0, sizeof(struct iscsi_uevent));
412 ev.type = ISCSI_UEVENT_DESTROY_SESSION;
413 ev.transport_handle = transport_handle;
414 ev.u.d_session.sid = sid;
416 iov[1].iov_base = &ev;
417 iov[1].iov_len = sizeof(ev);
418 rc = __kipc_call(iov, 2);
419 if (rc < 0)
420 return rc;
422 return 0;
425 static int
426 kunbind_session(uint64_t transport_handle, uint32_t sid)
428 int rc;
429 struct iscsi_uevent ev;
430 struct iovec iov[2];
432 log_debug(7, "in %s", __FUNCTION__);
434 memset(&ev, 0, sizeof(struct iscsi_uevent));
436 ev.type = ISCSI_UEVENT_UNBIND_SESSION;
437 ev.transport_handle = transport_handle;
438 ev.u.d_session.sid = sid;
440 iov[1].iov_base = &ev;
441 iov[1].iov_len = sizeof(ev);
442 rc = __kipc_call(iov, 2);
443 if (rc < 0)
444 return rc;
446 return 0;
449 static int
450 kcreate_conn(uint64_t transport_handle, uint32_t sid,
451 uint32_t cid, uint32_t *out_cid)
453 int rc;
454 struct iscsi_uevent ev;
455 struct iovec iov[2];
457 log_debug(7, "in %s", __FUNCTION__);
459 memset(&ev, 0, sizeof(struct iscsi_uevent));
461 ev.type = ISCSI_UEVENT_CREATE_CONN;
462 ev.transport_handle = transport_handle;
463 ev.u.c_conn.cid = cid;
464 ev.u.c_conn.sid = sid;
466 iov[1].iov_base = &ev;
467 iov[1].iov_len = sizeof(ev);
468 rc = __kipc_call(iov, 2);
469 if (rc < 0) {
470 log_debug(7, "returned %d", rc);
471 return rc;
474 if ((int)ev.r.c_conn_ret.cid == -1)
475 return -EIO;
477 *out_cid = ev.r.c_conn_ret.cid;
478 return 0;
481 static int
482 kdestroy_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid)
484 int rc;
485 struct iscsi_uevent ev;
486 struct iovec iov[2];
488 log_debug(7, "in %s", __FUNCTION__);
490 memset(&ev, 0, sizeof(struct iscsi_uevent));
492 ev.type = ISCSI_UEVENT_DESTROY_CONN;
493 ev.transport_handle = transport_handle;
494 ev.u.d_conn.sid = sid;
495 ev.u.d_conn.cid = cid;
497 iov[1].iov_base = &ev;
498 iov[1].iov_len = sizeof(ev);
499 rc = __kipc_call(iov, 2);
500 if (rc < 0)
501 return rc;
503 return 0;
506 static int
507 kbind_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
508 uint64_t transport_eph, int is_leading, int *retcode)
510 int rc;
511 struct iscsi_uevent ev;
512 struct iovec iov[2];
514 log_debug(7, "in %s", __FUNCTION__);
516 memset(&ev, 0, sizeof(struct iscsi_uevent));
518 ev.type = ISCSI_UEVENT_BIND_CONN;
519 ev.transport_handle = transport_handle;
520 ev.u.b_conn.sid = sid;
521 ev.u.b_conn.cid = cid;
522 ev.u.b_conn.transport_eph = transport_eph;
523 ev.u.b_conn.is_leading = is_leading;
525 iov[1].iov_base = &ev;
526 iov[1].iov_len = sizeof(ev);
527 rc = __kipc_call(iov, 2);
528 if (rc < 0)
529 return rc;
531 *retcode = ev.r.retcode;
533 return 0;
536 static void
537 ksend_pdu_begin(uint64_t transport_handle, uint32_t sid, uint32_t cid,
538 int hdr_size, int data_size)
540 struct iscsi_uevent *ev;
541 int total_xmitlen = sizeof(*ev) + hdr_size + data_size;
543 log_debug(7, "in %s", __FUNCTION__);
545 if (xmitbuf) {
546 log_error("send's begin state machine bug?");
547 exit(-EIO);
550 if (total_xmitlen > PDU_SENDBUF_DEFAULT_MAX) {
551 log_error("BUG: Cannot send %d bytes.", total_xmitlen);
552 exit(-EINVAL);
555 xmitbuf = pdu_sendbuf;
556 memset(xmitbuf, 0, total_xmitlen);
557 xmitlen = sizeof(*ev);
558 ev = xmitbuf;
559 memset(ev, 0, sizeof(*ev));
560 ev->type = ISCSI_UEVENT_SEND_PDU;
561 ev->transport_handle = transport_handle;
562 ev->u.send_pdu.sid = sid;
563 ev->u.send_pdu.cid = cid;
564 ev->u.send_pdu.hdr_size = hdr_size;
565 ev->u.send_pdu.data_size = data_size;
567 log_debug(3, "send PDU began for hdr %d bytes and data %d bytes",
568 hdr_size, data_size);
571 static int
572 ksend_pdu_end(uint64_t transport_handle, uint32_t sid, uint32_t cid,
573 int *retcode)
575 int rc;
576 struct iscsi_uevent *ev;
577 struct iovec iov[2];
579 log_debug(7, "in %s", __FUNCTION__);
581 if (!xmitbuf) {
582 log_error("send's end state machine bug?");
583 exit(-EIO);
585 ev = xmitbuf;
586 if (ev->u.send_pdu.sid != sid || ev->u.send_pdu.cid != cid) {
587 log_error("send's end state machine corruption?");
588 exit(-EIO);
591 iov[1].iov_base = xmitbuf;
592 iov[1].iov_len = xmitlen;
594 rc = __kipc_call(iov, 2);
595 if (rc < 0)
596 goto err;
597 if (ev->r.retcode) {
598 *retcode = ev->r.retcode;
599 goto err;
601 if (ev->type != ISCSI_UEVENT_SEND_PDU) {
602 log_error("bad event: bug on send_pdu_end?");
603 exit(-EIO);
606 log_debug(3, "send PDU finished for conn %d:%d",
607 sid, cid);
609 xmitbuf = NULL;
610 return 0;
612 err:
613 xmitbuf = NULL;
614 xmitlen = 0;
615 return rc;
618 static int
619 kset_host_param(uint64_t transport_handle, uint32_t host_no,
620 enum iscsi_host_param param, void *value, int type)
622 struct iscsi_uevent *ev;
623 char *param_str;
624 int rc, len;
625 struct iovec iov[2];
627 log_debug(7, "in %s", __FUNCTION__);
629 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
630 ev = (struct iscsi_uevent *)setparam_buf;
631 ev->type = ISCSI_UEVENT_SET_HOST_PARAM;
632 ev->transport_handle = transport_handle;
633 ev->u.set_host_param.host_no = host_no;
634 ev->u.set_host_param.param = param;
636 param_str = setparam_buf + sizeof(*ev);
637 switch (type) {
638 case ISCSI_INT:
639 sprintf(param_str, "%d", *((int *)value));
640 break;
641 case ISCSI_STRING:
642 if (!strlen(value))
643 return 0;
644 sprintf(param_str, "%s", (char *)value);
645 break;
646 default:
647 log_error("invalid type %d\n", type);
648 return -EINVAL;
650 ev->u.set_host_param.len = len = strlen(param_str) + 1;
652 iov[1].iov_base = ev;
653 iov[1].iov_len = sizeof(*ev) + len;
654 rc = __kipc_call(iov, 2);
655 if (rc < 0)
656 return rc;
658 return 0;
661 static int
662 kset_param(uint64_t transport_handle, uint32_t sid, uint32_t cid,
663 enum iscsi_param param, void *value, int type)
665 struct iscsi_uevent *ev;
666 char *param_str;
667 int rc, len;
668 struct iovec iov[2];
670 log_debug(7, "in %s", __FUNCTION__);
672 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
673 ev = (struct iscsi_uevent *)setparam_buf;
674 ev->type = ISCSI_UEVENT_SET_PARAM;
675 ev->transport_handle = transport_handle;
676 ev->u.set_param.sid = sid;
677 ev->u.set_param.cid = cid;
678 ev->u.set_param.param = param;
680 param_str = setparam_buf + sizeof(*ev);
681 switch (type) {
682 case ISCSI_INT:
683 sprintf(param_str, "%d", *((int *)value));
684 break;
685 case ISCSI_STRING:
686 if (!strlen(value))
687 return 0;
688 sprintf(param_str, "%s", (char *)value);
689 break;
690 default:
691 log_error("invalid type %d\n", type);
692 return -EINVAL;
694 ev->u.set_param.len = len = strlen(param_str) + 1;
696 iov[1].iov_base = ev;
697 iov[1].iov_len = sizeof(*ev) + len;
698 rc = __kipc_call(iov, 2);
699 if (rc < 0)
700 return rc;
702 return 0;
705 static int
706 kstop_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid, int flag)
708 int rc;
709 struct iscsi_uevent ev;
710 struct iovec iov[2];
712 log_debug(7, "in %s", __FUNCTION__);
714 memset(&ev, 0, sizeof(struct iscsi_uevent));
716 ev.type = ISCSI_UEVENT_STOP_CONN;
717 ev.transport_handle = transport_handle;
718 ev.u.stop_conn.sid = sid;
719 ev.u.stop_conn.cid = cid;
720 ev.u.stop_conn.flag = flag;
722 iov[1].iov_base = &ev;
723 iov[1].iov_len = sizeof(ev);
724 rc = __kipc_call(iov, 2);
725 if (rc < 0)
726 return rc;
728 return 0;
731 static int
732 kstart_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
733 int *retcode)
735 int rc;
736 struct iscsi_uevent ev;
737 struct iovec iov[2];
739 log_debug(7, "in %s", __FUNCTION__);
741 memset(&ev, 0, sizeof(struct iscsi_uevent));
743 ev.type = ISCSI_UEVENT_START_CONN;
744 ev.transport_handle = transport_handle;
745 ev.u.start_conn.sid = sid;
746 ev.u.start_conn.cid = cid;
748 iov[1].iov_base = &ev;
749 iov[1].iov_len = sizeof(ev);
750 rc = __kipc_call(iov, 2);
751 if (rc < 0)
752 return rc;
754 *retcode = ev.r.retcode;
755 return 0;
758 static int
759 krecv_pdu_begin(struct iscsi_conn *conn)
761 int rc;
763 log_debug(7, "in %s", __FUNCTION__);
765 if (recvbuf) {
766 log_error("recv's begin state machine bug?");
767 return -EIO;
770 if (!conn->recv_context) {
771 rc = ipc->ctldev_handle();
772 if (rc == -ENXIO)
773 /* event for some other conn */
774 return -EAGAIN;
775 else if (rc < 0)
776 /* fatal handling error or conn error */
777 return rc;
779 * Session create/destroy event for another conn
781 if (!conn->recv_context)
782 return -EAGAIN;
785 recvbuf = conn->recv_context->data + sizeof(struct iscsi_uevent);
786 recvlen = 0;
788 log_debug(3, "recv PDU began, pdu handle %p", recvbuf);
789 return 0;
792 static int
793 krecv_pdu_end(struct iscsi_conn *conn)
795 log_debug(7, "in %s", __FUNCTION__);
797 if (!recvbuf) {
798 log_error("recv's end state machine bug?");
799 return -EIO;
802 log_debug(3, "recv PDU finished for pdu handle 0x%p",
803 recvbuf);
805 ipc_ev_clbk->put_ev_context(conn->recv_context);
806 conn->recv_context = NULL;
807 recvbuf = NULL;
808 return 0;
812 ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
814 int rc, addrlen;
815 struct iscsi_uevent *ev;
816 struct sockaddr *dst_addr = (struct sockaddr *)&conn->saddr;
817 struct iovec iov[2];
819 log_debug(7, "in %s", __FUNCTION__);
821 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
822 ev = (struct iscsi_uevent *)setparam_buf;
823 ev->transport_handle = conn->session->t->handle;
825 if (conn->bind_ep) {
826 ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST;
827 ev->u.ep_connect_through_host.non_blocking = non_blocking;
828 ev->u.ep_connect_through_host.host_no = conn->session->hostno;
829 } else {
830 ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
831 ev->u.ep_connect.non_blocking = non_blocking;
834 if (dst_addr->sa_family == PF_INET)
835 addrlen = sizeof(struct sockaddr_in);
836 else if (dst_addr->sa_family == PF_INET6)
837 addrlen = sizeof(struct sockaddr_in6);
838 else {
839 log_error("%s unknown addr family %d\n",
840 __FUNCTION__, dst_addr->sa_family);
841 return -EINVAL;
843 memcpy(setparam_buf + sizeof(*ev), dst_addr, addrlen);
845 iov[1].iov_base = ev;
846 iov[1].iov_len = sizeof(*ev) + addrlen;
847 rc = __kipc_call(iov, 2);
848 if (rc < 0)
849 return rc;
851 if (!ev->r.ep_connect_ret.handle)
852 return -EIO;
854 conn->transport_ep_handle = ev->r.ep_connect_ret.handle;
856 log_debug(6, "%s got handle %llx",
857 __FUNCTION__, (unsigned long long)conn->transport_ep_handle);
858 return 0;
862 ktransport_ep_poll(iscsi_conn_t *conn, int timeout_ms)
864 int rc;
865 struct iscsi_uevent ev;
866 struct iovec iov[2];
868 log_debug(7, "in %s", __FUNCTION__);
870 memset(&ev, 0, sizeof(struct iscsi_uevent));
872 ev.type = ISCSI_UEVENT_TRANSPORT_EP_POLL;
873 ev.transport_handle = conn->session->t->handle;
874 ev.u.ep_poll.ep_handle = conn->transport_ep_handle;
875 ev.u.ep_poll.timeout_ms = timeout_ms;
877 iov[1].iov_base = &ev;
878 iov[1].iov_len = sizeof(ev);
879 rc = __kipc_call(iov, 2);
880 if (rc < 0)
881 return rc;
883 return ev.r.retcode;
886 void
887 ktransport_ep_disconnect(iscsi_conn_t *conn)
889 int rc;
890 struct iscsi_uevent ev;
891 struct iovec iov[2];
893 log_debug(7, "in %s", __FUNCTION__);
895 if (conn->transport_ep_handle == -1)
896 return;
898 memset(&ev, 0, sizeof(struct iscsi_uevent));
900 ev.type = ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT;
901 ev.transport_handle = conn->session->t->handle;
902 ev.u.ep_disconnect.ep_handle = conn->transport_ep_handle;
904 iov[1].iov_base = &ev;
905 iov[1].iov_len = sizeof(ev);
906 rc = __kipc_call(iov, 2);
907 if (rc < 0) {
908 log_error("connnection %d:%d transport disconnect failed for "
909 "ep %" PRIu64 " with error %d.", conn->session->id,
910 conn->id, conn->transport_ep_handle, rc);
911 } else
912 conn->transport_ep_handle = -1;
915 static int
916 kget_stats(uint64_t transport_handle, uint32_t sid, uint32_t cid,
917 char *statsbuf, int statsbuf_max)
919 int rc;
920 int ev_size;
921 struct iscsi_uevent ev;
922 char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
923 struct nlmsghdr *nlh;
924 struct iovec iov[2];
926 log_debug(7, "in %s", __FUNCTION__);
928 memset(&ev, 0, sizeof(struct iscsi_uevent));
930 ev.type = ISCSI_UEVENT_GET_STATS;
931 ev.transport_handle = transport_handle;
932 ev.u.get_stats.sid = sid;
933 ev.u.get_stats.cid = cid;
935 iov[1].iov_base = &ev;
936 iov[1].iov_len = sizeof(ev);
937 rc = __kipc_call(iov, 2);
938 if (rc < 0)
939 return rc;
941 if ((rc = nl_read(ctrl_fd, nlm_ev,
942 NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
943 log_error("can not read nlm_ev, error %d", rc);
944 return rc;
946 nlh = (struct nlmsghdr *)nlm_ev;
947 ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
949 log_debug(6, "message real length is %d bytes", nlh->nlmsg_len);
951 if (ev_size > statsbuf_max) {
952 log_error("destanation buffer for statistics is "
953 "not big enough to fit %d bytes", statsbuf_max);
954 ev_size = statsbuf_max;
957 if ((rc = nlpayload_read(ctrl_fd, (void*)statsbuf, ev_size, 0)) < 0) {
958 log_error("can not read from NL socket, error %d", rc);
959 return rc;
962 return 0;
965 static int
966 kset_net_config(uint64_t transport_handle, uint32_t host_no,
967 struct iovec *iovs, uint32_t param_count)
969 struct iscsi_uevent ev;
970 int rc, ev_len;
971 struct iovec *iov = iovs + 1;
973 log_debug(8, "in %s", __FUNCTION__);
975 ev_len = sizeof(ev);
976 ev.type = ISCSI_UEVENT_SET_IFACE_PARAMS;
977 ev.transport_handle = transport_handle;
978 ev.u.set_iface_params.host_no = host_no;
979 /* first two iovs for nlmsg hdr and ev */
980 ev.u.set_iface_params.count = param_count - 2;
982 iov->iov_base = &ev;
983 iov->iov_len = ev_len;
984 rc = __kipc_call(iovs, param_count);
985 if (rc < 0)
986 return rc;
988 return 0;
991 static int krecv_conn_state(struct iscsi_conn *conn, int *state)
993 int rc;
995 rc = ipc->ctldev_handle();
996 if (rc == -ENXIO) {
997 /* event for some other conn */
998 rc = -EAGAIN;
999 goto exit;
1000 } else if (rc < 0)
1001 /* fatal handling error or conn error */
1002 goto exit;
1004 *state = *(enum iscsi_conn_state *)conn->recv_context->data;
1006 ipc_ev_clbk->put_ev_context(conn->recv_context);
1007 conn->recv_context = NULL;
1009 exit:
1010 return rc;
1013 static void drop_data(struct nlmsghdr *nlh)
1015 int ev_size;
1017 ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
1018 nlpayload_read(ctrl_fd, NULL, ev_size, 0);
1021 static int ctldev_handle(void)
1023 int rc, ev_size;
1024 struct iscsi_uevent *ev;
1025 iscsi_session_t *session = NULL;
1026 iscsi_conn_t *conn = NULL;
1027 char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
1028 struct nlmsghdr *nlh;
1029 struct iscsi_ev_context *ev_context;
1030 uint32_t sid = 0, cid = 0, state = 0;
1032 log_debug(7, "in %s", __FUNCTION__);
1034 if ((rc = nl_read(ctrl_fd, nlm_ev,
1035 NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
1036 log_error("can not read nlm_ev, error %d", rc);
1037 return rc;
1039 nlh = (struct nlmsghdr *)nlm_ev;
1040 ev = (struct iscsi_uevent *)NLMSG_DATA(nlm_ev);
1042 log_debug(7, "%s got event type %u\n", __FUNCTION__, ev->type);
1043 /* drivers like qla4xxx can be inserted after iscsid is started */
1044 switch (ev->type) {
1045 case ISCSI_KEVENT_CREATE_SESSION:
1046 /* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
1047 case ISCSI_UEVENT_CREATE_SESSION:
1048 drop_data(nlh);
1049 if (ipc_ev_clbk->create_session)
1050 ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
1051 ev->r.c_session_ret.sid);
1052 return 0;
1053 case ISCSI_KEVENT_DESTROY_SESSION:
1054 drop_data(nlh);
1055 if (ipc_ev_clbk->destroy_session)
1056 ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
1057 ev->r.d_session.sid);
1058 return 0;
1059 case ISCSI_KEVENT_RECV_PDU:
1060 sid = ev->r.recv_req.sid;
1061 cid = ev->r.recv_req.cid;
1062 break;
1063 case ISCSI_KEVENT_CONN_ERROR:
1064 sid = ev->r.connerror.sid;
1065 cid = ev->r.connerror.cid;
1066 break;
1067 case ISCSI_KEVENT_CONN_LOGIN_STATE:
1068 sid = ev->r.conn_login.sid;
1069 cid = ev->r.conn_login.cid;
1070 state = ev->r.conn_login.state;
1071 break;
1072 case ISCSI_KEVENT_UNBIND_SESSION:
1073 sid = ev->r.unbind_session.sid;
1074 /* session wide event so cid is 0 */
1075 cid = 0;
1076 break;
1077 default:
1078 if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
1079 (ev->type > ISCSI_KEVENT_MAX))
1080 log_error("Unknown kernel event %d. You may want to "
1081 " upgrade your iscsi tools.", ev->type);
1082 else
1084 * If another app is using the interface we might
1085 * see their
1086 * stuff. Just drop it.
1088 log_debug(7, "Got unknwon event %d. Dropping.",
1089 ev->type);
1090 drop_data(nlh);
1091 return 0;
1094 /* verify connection */
1095 session = session_find_by_sid(sid);
1096 if (!session) {
1098 * this can happen normally when other apps are using the
1099 * nl interface.
1101 log_debug(1, "Could not verify connection %d:%d. Dropping "
1102 "event.\n", sid, cid);
1103 drop_data(nlh);
1104 return -ENXIO;
1106 conn = &session->conn[0];
1108 ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
1110 ev_context = ipc_ev_clbk->get_ev_context(conn, ev_size);
1111 if (!ev_context) {
1112 /* retry later */
1113 log_error("Can not allocate memory for receive context.");
1114 return -ENOMEM;
1117 log_debug(6, "message real length is %d bytes, recv_handle %p",
1118 nlh->nlmsg_len, ev_context->data);
1120 if ((rc = nlpayload_read(ctrl_fd, ev_context->data,
1121 ev_size, 0)) < 0) {
1122 ipc_ev_clbk->put_ev_context(ev_context);
1123 log_error("can not read from NL socket, error %d", rc);
1124 /* retry later */
1125 return rc;
1129 * we sched these events because the handlers could call back
1130 * into ctldev_handle
1132 switch (ev->type) {
1133 case ISCSI_KEVENT_RECV_PDU:
1134 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1135 EV_CONN_RECV_PDU);
1136 break;
1137 case ISCSI_KEVENT_CONN_ERROR:
1138 memcpy(ev_context->data, &ev->r.connerror.error,
1139 sizeof(ev->r.connerror.error));
1140 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1141 EV_CONN_ERROR);
1142 break;
1143 case ISCSI_KEVENT_CONN_LOGIN_STATE:
1144 memcpy(ev_context->data, &ev->r.conn_login.state,
1145 sizeof(ev->r.conn_login.state));
1146 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1147 EV_CONN_LOGIN);
1148 break;
1149 case ISCSI_KEVENT_UNBIND_SESSION:
1150 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1151 EV_CONN_STOP);
1152 break;
1153 default:
1154 ipc_ev_clbk->put_ev_context(ev_context);
1155 log_error("unknown kernel event %d", ev->type);
1156 return -EEXIST;
1159 if (rc)
1160 ipc_ev_clbk->put_ev_context(ev_context);
1161 return rc;
1164 static int
1165 ctldev_open(void)
1167 log_debug(7, "in %s", __FUNCTION__);
1169 nlm_sendbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
1170 if (!nlm_sendbuf) {
1171 log_error("can not allocate nlm_sendbuf");
1172 return -1;
1175 nlm_recvbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
1176 if (!nlm_recvbuf) {
1177 log_error("can not allocate nlm_recvbuf");
1178 goto free_nlm_sendbuf;
1181 pdu_sendbuf = calloc(1, PDU_SENDBUF_DEFAULT_MAX);
1182 if (!pdu_sendbuf) {
1183 log_error("can not allocate nlm_sendbuf");
1184 goto free_nlm_recvbuf;
1187 setparam_buf = calloc(1, NLM_SETPARAM_DEFAULT_MAX);
1188 if (!setparam_buf) {
1189 log_error("can not allocate setparam_buf");
1190 goto free_pdu_sendbuf;
1193 ctrl_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
1194 if (ctrl_fd < 0) {
1195 log_error("can not create NETLINK_ISCSI socket");
1196 goto free_setparam_buf;
1199 memset(&src_addr, 0, sizeof(src_addr));
1200 src_addr.nl_family = AF_NETLINK;
1201 src_addr.nl_pid = getpid();
1202 src_addr.nl_groups = 1;
1203 if (bind(ctrl_fd, (struct sockaddr *)&src_addr, sizeof(src_addr))) {
1204 log_error("can not bind NETLINK_ISCSI socket");
1205 goto close_socket;
1208 memset(&dest_addr, 0, sizeof(dest_addr));
1209 dest_addr.nl_family = AF_NETLINK;
1210 dest_addr.nl_pid = 0; /* kernel */
1211 dest_addr.nl_groups = 0; /* unicast */
1213 log_debug(7, "created NETLINK_ISCSI socket...");
1215 return ctrl_fd;
1217 close_socket:
1218 close(ctrl_fd);
1219 free_setparam_buf:
1220 free(setparam_buf);
1221 free_pdu_sendbuf:
1222 free(pdu_sendbuf);
1223 free_nlm_recvbuf:
1224 free(nlm_recvbuf);
1225 free_nlm_sendbuf:
1226 free(nlm_sendbuf);
1227 return -1;
1230 static void
1231 ctldev_close(void)
1233 log_debug(7, "in %s", __FUNCTION__);
1235 if (ctrl_fd >= 0)
1236 close(ctrl_fd);
1237 free(setparam_buf);
1238 free(pdu_sendbuf);
1239 free(nlm_recvbuf);
1240 free(nlm_sendbuf);
1243 struct iscsi_ipc nl_ipc = {
1244 .name = "Open-iSCSI Kernel IPC/NETLINK v.1",
1245 .ctldev_bufmax = NLM_BUF_DEFAULT_MAX,
1246 .ctldev_open = ctldev_open,
1247 .ctldev_close = ctldev_close,
1248 .ctldev_handle = ctldev_handle,
1249 .sendtargets = ksendtargets,
1250 .create_session = kcreate_session,
1251 .destroy_session = kdestroy_session,
1252 .unbind_session = kunbind_session,
1253 .create_conn = kcreate_conn,
1254 .destroy_conn = kdestroy_conn,
1255 .bind_conn = kbind_conn,
1256 .set_param = kset_param,
1257 .set_host_param = kset_host_param,
1258 .get_param = NULL,
1259 .start_conn = kstart_conn,
1260 .stop_conn = kstop_conn,
1261 .get_stats = kget_stats,
1262 .writev = kwritev,
1263 .send_pdu_begin = ksend_pdu_begin,
1264 .send_pdu_end = ksend_pdu_end,
1265 .read = kread,
1266 .recv_pdu_begin = krecv_pdu_begin,
1267 .recv_pdu_end = krecv_pdu_end,
1268 .set_net_config = kset_net_config,
1269 .recv_conn_state = krecv_conn_state,
1271 struct iscsi_ipc *ipc = &nl_ipc;
1273 void ipc_register_ev_callback(struct iscsi_ipc_ev_clbk *ev_clbk)
1275 ipc_ev_clbk = ev_clbk;