Use pass through interface for sendtargets (take4) Currenly offload cards like bnx2i...
[open-iscsi.git] / usr / netlink.c
blobe70602d99d42f5bb1f65ff61f42abaf5cbb6c1ac
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 \
57 (NLMSG_SPACE(ISCSI_DEF_MAX_RECV_SEG_LEN + \
58 sizeof(struct iscsi_hdr)))
60 #define PDU_SENDBUF_DEFAULT_MAX \
61 (ISCSI_DEF_MAX_RECV_SEG_LEN + sizeof(struct iscsi_hdr))
63 #define NLM_SETPARAM_DEFAULT_MAX \
64 (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);
111 memset(iov.iov_base, 0, iov.iov_len);
113 memset(&msg, 0, sizeof(msg));
114 msg.msg_name= (void*)&src_addr;
115 msg.msg_namelen = sizeof(src_addr);
116 msg.msg_iov = &iov;
117 msg.msg_iovlen = 1;
120 * Netlink recvmsg call path:
122 * - transport api callback
123 * - iscsi_control_conn_error (should succeed)
124 * - iscsi_unicast_skb (must succeed)
125 * - netlink_unicast (must succeed)
126 * - netlink_data_ready (must succeed)
127 * - netlink_sendskb (must succeed)
128 * - netlink_recvmsg (must succeed)
129 * - sock_recvmsg (must succeed)
130 * - sys_recvmsg (must succeed)
131 * - sys_socketcall (must succeed)
132 * - syscall_call (must succeed)
134 * Note1: "must succeed" means succeed unless bug in daemon.
135 * It also means - no sleep and memory allocation on
136 * the path.
138 * Note2: "should succeed" means will succeed in most of cases
139 * because of mempool preallocation.
141 * FIXME: if "Note2" than interface should generate iSCSI error
142 * level 0 on its own. Interface must always succeed on this.
144 rc = recvmsg(ctrl_fd, &msg, flags);
146 memcpy(data, NLMSG_DATA(iov.iov_base), count);
148 return rc;
151 static int
152 kwritev(enum iscsi_uevent_e type, struct iovec *iovp, int count)
154 int i, rc;
155 struct nlmsghdr *nlh;
156 struct msghdr msg;
157 struct iovec iov;
158 int datalen = 0;
160 log_debug(7, "in %s", __FUNCTION__);
162 for (i = 0; i < count; i++) {
163 datalen += iovp[i].iov_len;
166 if (xmitbuf && type != ISCSI_UEVENT_SEND_PDU) {
167 for (i = 0; i < count; i++) {
168 memcpy(xmitbuf + xmitlen,
169 iovp[i].iov_base, iovp[i].iov_len);
170 xmitlen += iovp[i].iov_len;
172 return datalen;
175 nlh = nlm_sendbuf;
176 memset(nlh, 0, NLMSG_SPACE(datalen));
178 nlh->nlmsg_len = NLMSG_SPACE(datalen);
179 nlh->nlmsg_pid = getpid();
180 nlh->nlmsg_flags = 0;
181 nlh->nlmsg_type = type;
183 datalen = 0;
184 for (i = 0; i < count; i++) {
185 memcpy(NLMSG_DATA(nlh) + datalen, iovp[i].iov_base,
186 iovp[i].iov_len);
187 datalen += iovp[i].iov_len;
189 iov.iov_base = (void*)nlh;
190 iov.iov_len = nlh->nlmsg_len;
192 memset(&msg, 0, sizeof(msg));
193 msg.msg_name= (void*)&dest_addr;
194 msg.msg_namelen = sizeof(dest_addr);
195 msg.msg_iov = &iov;
196 msg.msg_iovlen = 1;
198 do {
200 * Netlink down call path:
202 * - transport api call
203 * - iscsi_if_recv_msg (must succeed)
204 * - iscsi_if_rx (must succeed)
205 * - netlink_data_ready (must succeed)
206 * - netlink_sendskb (must succeed)
207 * - netlink_sendmsg (alloc_skb() might fail)
208 * - sock_sendmsg (must succeed)
209 * - sys_sendmsg (must succeed)
210 * - sys_socketcall (must succeed)
211 * - syscall_call (must succeed)
213 * Note1: "must succeed" means succeed unless bug in daemon.
214 * It also means - no sleep and memory allocation on
215 * the path.
217 * Note2: netlink_sendmsg() might fail because of OOM. Since
218 * we are in user-space, we will sleep until we succeed.
221 rc = sendmsg(ctrl_fd, &msg, 0);
222 if (rc == -ENOMEM) {
223 log_debug(1, "sendmsg: alloc_skb() failed");
224 sleep(1);
225 } else if (rc < 0) {
226 log_error("sendmsg: bug? ctrl_fd %d", ctrl_fd);
227 exit(rc);
229 } while (rc < 0);
231 return rc;
235 * __kipc_call() should never block. Therefore
236 * Netlink's xmit logic is serialized. This means we do not allocate on
237 * xmit path. Instead we reuse nlm_sendbuf buffer.
239 * Transport must assure non-blocking operations for:
241 * - session_create()
242 * - conn_create()
243 * - conn_bind()
244 * _ set_param()
245 * - conn_start()
246 * - conn_stop()
248 * Its OK to block for cleanup for short period of time in operatations for:
250 * - conn_destroy()
251 * - session_destroy()
253 * FIXME: interface needs to be extended to allow longer blocking on
254 * cleanup. (Dima)
256 static int
257 __kipc_call(void *iov_base, int iov_len)
259 int rc, iferr;
260 struct iovec iov;
261 struct iscsi_uevent *ev = iov_base;
262 enum iscsi_uevent_e type = ev->type;
264 log_debug(7, "in %s", __FUNCTION__);
266 iov.iov_base = iov_base;
267 iov.iov_len = iov_len;
269 rc = kwritev(type, &iov, 1);
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;
330 log_debug(7, "in %s", __FUNCTION__);
332 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
333 ev = (struct iscsi_uevent *)setparam_buf;
334 ev->type = ISCSI_UEVENT_TGT_DSCVR;
335 ev->transport_handle = transport_handle;
336 ev->u.tgt_dscvr.type = ISCSI_TGT_DSCVR_SEND_TARGETS;
337 ev->u.tgt_dscvr.host_no = host_no;
339 if (addr->sa_family == PF_INET)
340 addrlen = sizeof(struct sockaddr_in);
341 else if (addr->sa_family == PF_INET6)
342 addrlen = sizeof(struct sockaddr_in6);
343 else {
344 log_error("%s unknown addr family %d\n",
345 __FUNCTION__, addr->sa_family);
346 return -EINVAL;
348 memcpy(setparam_buf + sizeof(*ev), addr, addrlen);
350 rc = __kipc_call(ev, sizeof(*ev) + addrlen);
351 if (rc < 0) {
352 log_error("sendtargets failed rc%d\n", rc);
353 return rc;
355 return 0;
358 static int
359 kcreate_session(uint64_t transport_handle, uint64_t ep_handle,
360 uint32_t initial_cmdsn, uint16_t cmds_max, uint16_t qdepth,
361 uint32_t *out_sid, uint32_t *hostno)
363 int rc;
364 struct iscsi_uevent ev;
366 log_debug(7, "in %s", __FUNCTION__);
368 memset(&ev, 0, sizeof(struct iscsi_uevent));
370 if (ep_handle == 0) {
371 ev.type = ISCSI_UEVENT_CREATE_SESSION;
372 ev.transport_handle = transport_handle;
373 ev.u.c_session.initial_cmdsn = initial_cmdsn;
374 ev.u.c_session.cmds_max = cmds_max;
375 ev.u.c_session.queue_depth = qdepth;
376 } else {
377 ev.type = ISCSI_UEVENT_CREATE_BOUND_SESSION;
378 ev.transport_handle = transport_handle;
379 ev.u.c_bound_session.initial_cmdsn = initial_cmdsn;
380 ev.u.c_bound_session.cmds_max = cmds_max;
381 ev.u.c_bound_session.queue_depth = qdepth;
382 ev.u.c_bound_session.ep_handle = ep_handle;
385 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
386 return rc;
389 *hostno = ev.r.c_session_ret.host_no;
390 *out_sid = ev.r.c_session_ret.sid;
392 return 0;
395 static int
396 kdestroy_session(uint64_t transport_handle, uint32_t sid)
398 int rc;
399 struct iscsi_uevent ev;
401 log_debug(7, "in %s", __FUNCTION__);
403 memset(&ev, 0, sizeof(struct iscsi_uevent));
405 ev.type = ISCSI_UEVENT_DESTROY_SESSION;
406 ev.transport_handle = transport_handle;
407 ev.u.d_session.sid = sid;
409 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
410 return rc;
413 return 0;
416 static int
417 kunbind_session(uint64_t transport_handle, uint32_t sid)
419 int rc;
420 struct iscsi_uevent ev;
422 log_debug(7, "in %s", __FUNCTION__);
424 memset(&ev, 0, sizeof(struct iscsi_uevent));
426 ev.type = ISCSI_UEVENT_UNBIND_SESSION;
427 ev.transport_handle = transport_handle;
428 ev.u.d_session.sid = sid;
430 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
431 return rc;
434 return 0;
437 static int
438 kcreate_conn(uint64_t transport_handle, uint32_t sid,
439 uint32_t cid, uint32_t *out_cid)
441 int rc;
442 struct iscsi_uevent ev;
444 log_debug(7, "in %s", __FUNCTION__);
446 memset(&ev, 0, sizeof(struct iscsi_uevent));
448 ev.type = ISCSI_UEVENT_CREATE_CONN;
449 ev.transport_handle = transport_handle;
450 ev.u.c_conn.cid = cid;
451 ev.u.c_conn.sid = sid;
453 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
454 log_debug(7, "returned %d", rc);
455 return rc;
458 if ((int)ev.r.c_conn_ret.cid == -1)
459 return -EIO;
461 *out_cid = ev.r.c_conn_ret.cid;
462 return 0;
465 static int
466 kdestroy_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid)
468 int rc;
469 struct iscsi_uevent ev;
471 log_debug(7, "in %s", __FUNCTION__);
473 memset(&ev, 0, sizeof(struct iscsi_uevent));
475 ev.type = ISCSI_UEVENT_DESTROY_CONN;
476 ev.transport_handle = transport_handle;
477 ev.u.d_conn.sid = sid;
478 ev.u.d_conn.cid = cid;
480 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
481 return rc;
484 return 0;
487 static int
488 kbind_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
489 uint64_t transport_eph, int is_leading, int *retcode)
491 int rc;
492 struct iscsi_uevent ev;
494 log_debug(7, "in %s", __FUNCTION__);
496 memset(&ev, 0, sizeof(struct iscsi_uevent));
498 ev.type = ISCSI_UEVENT_BIND_CONN;
499 ev.transport_handle = transport_handle;
500 ev.u.b_conn.sid = sid;
501 ev.u.b_conn.cid = cid;
502 ev.u.b_conn.transport_eph = transport_eph;
503 ev.u.b_conn.is_leading = is_leading;
505 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
506 return rc;
509 *retcode = ev.r.retcode;
511 return 0;
514 static void
515 ksend_pdu_begin(uint64_t transport_handle, uint32_t sid, uint32_t cid,
516 int hdr_size, int data_size)
518 struct iscsi_uevent *ev;
520 log_debug(7, "in %s", __FUNCTION__);
522 if (xmitbuf) {
523 log_error("send's begin state machine bug?");
524 exit(-EIO);
527 xmitbuf = pdu_sendbuf;
528 memset(xmitbuf, 0, sizeof(*ev) + hdr_size + data_size);
529 xmitlen = sizeof(*ev);
530 ev = xmitbuf;
531 memset(ev, 0, sizeof(*ev));
532 ev->type = ISCSI_UEVENT_SEND_PDU;
533 ev->transport_handle = transport_handle;
534 ev->u.send_pdu.sid = sid;
535 ev->u.send_pdu.cid = cid;
536 ev->u.send_pdu.hdr_size = hdr_size;
537 ev->u.send_pdu.data_size = data_size;
539 log_debug(3, "send PDU began for hdr %d bytes and data %d bytes",
540 hdr_size, data_size);
543 static int
544 ksend_pdu_end(uint64_t transport_handle, uint32_t sid, uint32_t cid,
545 int *retcode)
547 int rc;
548 struct iscsi_uevent *ev;
549 struct iovec iov;
551 log_debug(7, "in %s", __FUNCTION__);
553 if (!xmitbuf) {
554 log_error("send's end state machine bug?");
555 exit(-EIO);
557 ev = xmitbuf;
558 if (ev->u.send_pdu.sid != sid || ev->u.send_pdu.cid != cid) {
559 log_error("send's end state machine corruption?");
560 exit(-EIO);
563 iov.iov_base = xmitbuf;
564 iov.iov_len = xmitlen;
566 if ((rc = __kipc_call(xmitbuf, xmitlen)) < 0)
567 goto err;
568 if (ev->r.retcode) {
569 *retcode = ev->r.retcode;
570 goto err;
572 if (ev->type != ISCSI_UEVENT_SEND_PDU) {
573 log_error("bad event: bug on send_pdu_end?");
574 exit(-EIO);
577 log_debug(3, "send PDU finished for conn %d:%d",
578 sid, cid);
580 xmitbuf = NULL;
581 return 0;
583 err:
584 xmitbuf = NULL;
585 xmitlen = 0;
586 return rc;
589 static int
590 kset_host_param(uint64_t transport_handle, uint32_t host_no,
591 enum iscsi_host_param param, void *value, int type)
593 struct iscsi_uevent *ev;
594 char *param_str;
595 int rc, len;
597 log_debug(7, "in %s", __FUNCTION__);
599 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
600 ev = (struct iscsi_uevent *)setparam_buf;
601 ev->type = ISCSI_UEVENT_SET_HOST_PARAM;
602 ev->transport_handle = transport_handle;
603 ev->u.set_host_param.host_no = host_no;
604 ev->u.set_host_param.param = param;
606 param_str = setparam_buf + sizeof(*ev);
607 switch (type) {
608 case ISCSI_INT:
609 sprintf(param_str, "%d", *((int *)value));
610 break;
611 case ISCSI_STRING:
612 if (!strlen(value))
613 return 0;
614 sprintf(param_str, "%s", (char *)value);
615 break;
616 default:
617 log_error("invalid type %d\n", type);
618 return -EINVAL;
620 ev->u.set_host_param.len = len = strlen(param_str) + 1;
622 if ((rc = __kipc_call(ev, sizeof(*ev) + len)) < 0) {
623 return rc;
626 return 0;
629 static int
630 kset_param(uint64_t transport_handle, uint32_t sid, uint32_t cid,
631 enum iscsi_param param, void *value, int type)
633 struct iscsi_uevent *ev;
634 char *param_str;
635 int rc, len;
637 log_debug(7, "in %s", __FUNCTION__);
639 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
640 ev = (struct iscsi_uevent *)setparam_buf;
641 ev->type = ISCSI_UEVENT_SET_PARAM;
642 ev->transport_handle = transport_handle;
643 ev->u.set_param.sid = sid;
644 ev->u.set_param.cid = cid;
645 ev->u.set_param.param = param;
647 param_str = setparam_buf + sizeof(*ev);
648 switch (type) {
649 case ISCSI_INT:
650 sprintf(param_str, "%d", *((int *)value));
651 break;
652 case ISCSI_STRING:
653 if (!strlen(value))
654 return 0;
655 sprintf(param_str, "%s", (char *)value);
656 break;
657 default:
658 log_error("invalid type %d\n", type);
659 return -EINVAL;
661 ev->u.set_param.len = len = strlen(param_str) + 1;
663 if ((rc = __kipc_call(ev, sizeof(*ev) + len)) < 0) {
664 return rc;
667 return 0;
670 static int
671 kstop_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid, int flag)
673 int rc;
674 struct iscsi_uevent ev;
676 log_debug(7, "in %s", __FUNCTION__);
678 memset(&ev, 0, sizeof(struct iscsi_uevent));
680 ev.type = ISCSI_UEVENT_STOP_CONN;
681 ev.transport_handle = transport_handle;
682 ev.u.stop_conn.sid = sid;
683 ev.u.stop_conn.cid = cid;
684 ev.u.stop_conn.flag = flag;
686 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
687 return rc;
690 return 0;
693 static int
694 kstart_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
695 int *retcode)
697 int rc;
698 struct iscsi_uevent ev;
700 log_debug(7, "in %s", __FUNCTION__);
702 memset(&ev, 0, sizeof(struct iscsi_uevent));
704 ev.type = ISCSI_UEVENT_START_CONN;
705 ev.transport_handle = transport_handle;
706 ev.u.start_conn.sid = sid;
707 ev.u.start_conn.cid = cid;
709 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
710 return rc;
713 *retcode = ev.r.retcode;
714 return 0;
717 static int
718 krecv_pdu_begin(struct iscsi_conn *conn)
720 int rc;
722 log_debug(7, "in %s", __FUNCTION__);
724 if (recvbuf) {
725 log_error("recv's begin state machine bug?");
726 return -EIO;
729 if (!conn->recv_context) {
730 rc = ipc->ctldev_handle();
731 if (rc == -ENXIO)
732 /* event for some other conn */
733 return -EAGAIN;
734 else if (rc < 0)
735 /* fatal handling error or conn error */
736 return rc;
738 * Session create/destroy event for another conn
740 if (!conn->recv_context)
741 return -EAGAIN;
744 recvbuf = conn->recv_context->data + sizeof(struct iscsi_uevent);
745 recvlen = 0;
747 log_debug(3, "recv PDU began, pdu handle %p", recvbuf);
748 return 0;
751 static int
752 krecv_pdu_end(struct iscsi_conn *conn)
754 log_debug(7, "in %s", __FUNCTION__);
756 if (!recvbuf) {
757 log_error("recv's end state machine bug?");
758 return -EIO;
761 log_debug(3, "recv PDU finished for pdu handle 0x%p",
762 recvbuf);
764 ipc_ev_clbk->put_ev_context(conn->recv_context);
765 conn->recv_context = NULL;
766 recvbuf = NULL;
767 return 0;
771 ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
773 int rc, addrlen;
774 struct iscsi_uevent *ev;
775 struct sockaddr *dst_addr = (struct sockaddr *)&conn->saddr;
777 log_debug(7, "in %s", __FUNCTION__);
779 memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
780 ev = (struct iscsi_uevent *)setparam_buf;
781 ev->transport_handle = conn->session->t->handle;
783 if (conn->bind_ep) {
784 ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST;
785 ev->u.ep_connect_through_host.non_blocking = non_blocking;
786 ev->u.ep_connect_through_host.host_no = conn->session->hostno;
787 } else {
788 ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
789 ev->u.ep_connect.non_blocking = non_blocking;
792 if (dst_addr->sa_family == PF_INET)
793 addrlen = sizeof(struct sockaddr_in);
794 else if (dst_addr->sa_family == PF_INET6)
795 addrlen = sizeof(struct sockaddr_in6);
796 else {
797 log_error("%s unknown addr family %d\n",
798 __FUNCTION__, dst_addr->sa_family);
799 return -EINVAL;
801 memcpy(setparam_buf + sizeof(*ev), dst_addr, addrlen);
803 if ((rc = __kipc_call(ev, sizeof(*ev) + addrlen)) < 0)
804 return rc;
806 if (!ev->r.ep_connect_ret.handle)
807 return -EIO;
809 conn->transport_ep_handle = ev->r.ep_connect_ret.handle;
811 log_debug(6, "%s got handle %llx",
812 __FUNCTION__, (unsigned long long)conn->transport_ep_handle);
813 return 0;
817 ktransport_ep_poll(iscsi_conn_t *conn, int timeout_ms)
819 int rc;
820 struct iscsi_uevent ev;
822 log_debug(7, "in %s", __FUNCTION__);
824 memset(&ev, 0, sizeof(struct iscsi_uevent));
826 ev.type = ISCSI_UEVENT_TRANSPORT_EP_POLL;
827 ev.transport_handle = conn->session->t->handle;
828 ev.u.ep_poll.ep_handle = conn->transport_ep_handle;
829 ev.u.ep_poll.timeout_ms = timeout_ms;
831 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0)
832 return rc;
834 return ev.r.retcode;
837 void
838 ktransport_ep_disconnect(iscsi_conn_t *conn)
840 int rc;
841 struct iscsi_uevent ev;
843 log_debug(7, "in %s", __FUNCTION__);
845 if (conn->transport_ep_handle == -1)
846 return;
848 memset(&ev, 0, sizeof(struct iscsi_uevent));
850 ev.type = ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT;
851 ev.transport_handle = conn->session->t->handle;
852 ev.u.ep_disconnect.ep_handle = conn->transport_ep_handle;
854 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
855 log_error("connnection %d:%d transport disconnect failed for "
856 "ep %" PRIu64 " with error %d.", conn->session->id,
857 conn->id, conn->transport_ep_handle, rc);
858 } else
859 conn->transport_ep_handle = -1;
862 static int
863 kget_stats(uint64_t transport_handle, uint32_t sid, uint32_t cid,
864 char *statsbuf, int statsbuf_max)
866 int rc;
867 int ev_size;
868 struct iscsi_uevent ev;
869 char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
870 struct nlmsghdr *nlh;
872 log_debug(7, "in %s", __FUNCTION__);
874 memset(&ev, 0, sizeof(struct iscsi_uevent));
876 ev.type = ISCSI_UEVENT_GET_STATS;
877 ev.transport_handle = transport_handle;
878 ev.u.get_stats.sid = sid;
879 ev.u.get_stats.cid = cid;
881 if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) {
882 return rc;
885 if ((rc = nl_read(ctrl_fd, nlm_ev,
886 NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
887 log_error("can not read nlm_ev, error %d", rc);
888 return rc;
890 nlh = (struct nlmsghdr *)nlm_ev;
891 ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
893 log_debug(6, "message real length is %d bytes", nlh->nlmsg_len);
895 if (ev_size > statsbuf_max) {
896 log_error("destanation buffer for statistics is "
897 "not big enough to fit %d bytes", statsbuf_max);
898 ev_size = statsbuf_max;
901 if ((rc = nlpayload_read(ctrl_fd, (void*)statsbuf, ev_size, 0)) < 0) {
902 log_error("can not read from NL socket, error %d", rc);
903 return rc;
906 return 0;
909 static void drop_data(struct nlmsghdr *nlh)
911 int ev_size, read, curr_total;
913 curr_total = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
914 while (curr_total > 0) {
915 ev_size = curr_total;
916 if (ev_size > NLM_BUF_DEFAULT_MAX)
917 ev_size = NLM_BUF_DEFAULT_MAX;
919 /* sendbuf will not be used here, so dump data to it */
920 read = nlpayload_read(ctrl_fd, nlm_sendbuf, ev_size, 0);
921 if (read < 0) {
922 log_error("Could not drop %d bytes of data.\n",
923 read);
924 } else if (!read)
925 break;
926 curr_total -= read;
930 static int ctldev_handle(void)
932 int rc, ev_size;
933 struct iscsi_uevent *ev;
934 iscsi_session_t *session = NULL;
935 iscsi_conn_t *conn = NULL;
936 char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
937 struct nlmsghdr *nlh;
938 struct iscsi_ev_context *ev_context;
939 uint32_t sid = 0, cid = 0;
941 log_debug(7, "in %s", __FUNCTION__);
943 if ((rc = nl_read(ctrl_fd, nlm_ev,
944 NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
945 log_error("can not read nlm_ev, error %d", rc);
946 return rc;
948 nlh = (struct nlmsghdr *)nlm_ev;
949 ev = (struct iscsi_uevent *)NLMSG_DATA(nlm_ev);
951 log_debug(7, "%s got event type %u\n", __FUNCTION__, ev->type);
952 /* drivers like qla4xxx can be inserted after iscsid is started */
953 switch (ev->type) {
954 case ISCSI_KEVENT_CREATE_SESSION:
955 /* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
956 case ISCSI_UEVENT_CREATE_SESSION:
957 drop_data(nlh);
958 if (ipc_ev_clbk->create_session)
959 ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
960 ev->r.c_session_ret.sid);
961 return 0;
962 case ISCSI_KEVENT_DESTROY_SESSION:
963 drop_data(nlh);
964 if (ipc_ev_clbk->destroy_session)
965 ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
966 ev->r.d_session.sid);
967 return 0;
968 case ISCSI_KEVENT_RECV_PDU:
969 sid = ev->r.recv_req.sid;
970 cid = ev->r.recv_req.cid;
971 break;
972 case ISCSI_KEVENT_CONN_ERROR:
973 sid = ev->r.connerror.sid;
974 cid = ev->r.connerror.cid;
975 break;
976 case ISCSI_KEVENT_UNBIND_SESSION:
977 sid = ev->r.unbind_session.sid;
978 /* session wide event so cid is 0 */
979 cid = 0;
980 break;
981 default:
982 if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
983 (ev->type > ISCSI_KEVENT_MAX))
984 log_error("Unknown kernel event %d. You may want to "
985 " upgrade your iscsi tools.", ev->type);
986 else
988 * If another app is using the interface we might
989 * see their
990 * stuff. Just drop it.
992 log_debug(7, "Got unknwon event %d. Dropping.",
993 ev->type);
994 drop_data(nlh);
995 return 0;
998 /* verify connection */
999 session = session_find_by_sid(sid);
1000 if (!session) {
1002 * this can happen normally when other apps are using the
1003 * nl interface.
1005 log_debug(1, "Could not verify connection %d:%d. Dropping "
1006 "event.\n", sid, cid);
1007 drop_data(nlh);
1008 return -ENXIO;
1010 conn = &session->conn[0];
1012 ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
1014 ev_context = ipc_ev_clbk->get_ev_context(conn, ev_size);
1015 if (!ev_context) {
1016 /* retry later */
1017 log_error("Can not allocate memory for receive context.");
1018 return -ENOMEM;
1021 log_debug(6, "message real length is %d bytes, recv_handle %p",
1022 nlh->nlmsg_len, ev_context->data);
1024 if ((rc = nlpayload_read(ctrl_fd, ev_context->data,
1025 ev_size, 0)) < 0) {
1026 ipc_ev_clbk->put_ev_context(ev_context);
1027 log_error("can not read from NL socket, error %d", rc);
1028 /* retry later */
1029 return rc;
1033 * we sched these events because the handlers could call back
1034 * into ctldev_handle
1036 switch (ev->type) {
1037 case ISCSI_KEVENT_RECV_PDU:
1038 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1039 EV_CONN_RECV_PDU);
1040 break;
1041 case ISCSI_KEVENT_CONN_ERROR:
1042 memcpy(ev_context->data, &ev->r.connerror.error,
1043 sizeof(ev->r.connerror.error));
1044 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1045 EV_CONN_ERROR);
1046 break;
1047 case ISCSI_KEVENT_UNBIND_SESSION:
1048 rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
1049 EV_CONN_STOP);
1050 break;
1051 default:
1052 ipc_ev_clbk->put_ev_context(ev_context);
1053 log_error("unknown kernel event %d", ev->type);
1054 return -EEXIST;
1057 if (rc)
1058 ipc_ev_clbk->put_ev_context(ev_context);
1059 return rc;
1062 static int
1063 ctldev_open(void)
1065 log_debug(7, "in %s", __FUNCTION__);
1067 nlm_sendbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
1068 if (!nlm_sendbuf) {
1069 log_error("can not allocate nlm_sendbuf");
1070 return -1;
1073 nlm_recvbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
1074 if (!nlm_recvbuf) {
1075 log_error("can not allocate nlm_recvbuf");
1076 goto free_nlm_sendbuf;
1079 pdu_sendbuf = calloc(1, PDU_SENDBUF_DEFAULT_MAX);
1080 if (!pdu_sendbuf) {
1081 log_error("can not allocate nlm_sendbuf");
1082 goto free_nlm_recvbuf;
1085 setparam_buf = calloc(1, NLM_SETPARAM_DEFAULT_MAX);
1086 if (!setparam_buf) {
1087 log_error("can not allocate setparam_buf");
1088 goto free_pdu_sendbuf;
1091 ctrl_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
1092 if (ctrl_fd < 0) {
1093 log_error("can not create NETLINK_ISCSI socket");
1094 goto free_setparam_buf;
1097 memset(&src_addr, 0, sizeof(src_addr));
1098 src_addr.nl_family = AF_NETLINK;
1099 src_addr.nl_pid = getpid();
1100 src_addr.nl_groups = 1;
1101 if (bind(ctrl_fd, (struct sockaddr *)&src_addr, sizeof(src_addr))) {
1102 log_error("can not bind NETLINK_ISCSI socket");
1103 goto close_socket;
1106 memset(&dest_addr, 0, sizeof(dest_addr));
1107 dest_addr.nl_family = AF_NETLINK;
1108 dest_addr.nl_pid = 0; /* kernel */
1109 dest_addr.nl_groups = 0; /* unicast */
1111 log_debug(7, "created NETLINK_ISCSI socket...");
1113 return ctrl_fd;
1115 close_socket:
1116 close(ctrl_fd);
1117 free_setparam_buf:
1118 free(setparam_buf);
1119 free_pdu_sendbuf:
1120 free(pdu_sendbuf);
1121 free_nlm_recvbuf:
1122 free(nlm_recvbuf);
1123 free_nlm_sendbuf:
1124 free(nlm_sendbuf);
1125 return -1;
1128 static void
1129 ctldev_close(void)
1131 log_debug(7, "in %s", __FUNCTION__);
1133 if (ctrl_fd >= 0)
1134 close(ctrl_fd);
1135 free(setparam_buf);
1136 free(pdu_sendbuf);
1137 free(nlm_recvbuf);
1138 free(nlm_sendbuf);
1141 struct iscsi_ipc nl_ipc = {
1142 .name = "Open-iSCSI Kernel IPC/NETLINK v.1",
1143 .ctldev_bufmax = NLM_BUF_DEFAULT_MAX,
1144 .ctldev_open = ctldev_open,
1145 .ctldev_close = ctldev_close,
1146 .ctldev_handle = ctldev_handle,
1147 .sendtargets = ksendtargets,
1148 .create_session = kcreate_session,
1149 .destroy_session = kdestroy_session,
1150 .unbind_session = kunbind_session,
1151 .create_conn = kcreate_conn,
1152 .destroy_conn = kdestroy_conn,
1153 .bind_conn = kbind_conn,
1154 .set_param = kset_param,
1155 .set_host_param = kset_host_param,
1156 .get_param = NULL,
1157 .start_conn = kstart_conn,
1158 .stop_conn = kstop_conn,
1159 .get_stats = kget_stats,
1160 .writev = kwritev,
1161 .send_pdu_begin = ksend_pdu_begin,
1162 .send_pdu_end = ksend_pdu_end,
1163 .read = kread,
1164 .recv_pdu_begin = krecv_pdu_begin,
1165 .recv_pdu_end = krecv_pdu_end,
1167 struct iscsi_ipc *ipc = &nl_ipc;
1169 void ipc_register_ev_callback(struct iscsi_ipc_ev_clbk *ev_clbk)
1171 ipc_ev_clbk = ev_clbk;