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.
29 #include <asm/types.h>
30 #include <sys/socket.h>
31 #include <sys/types.h>
32 #include <linux/netlink.h>
37 #include "iscsi_ipc.h"
38 #include "initiator.h"
39 #include "iscsi_sysfs.h"
40 #include "transport.h"
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))
67 kread(char *data
, int count
)
69 log_debug(7, "in %s %u %u %p %p", __FUNCTION__
, recvlen
, count
,
72 memcpy(data
, recvbuf
+ recvlen
, count
);
78 nl_read(int ctrl_fd
, char *data
, int size
, int flags
)
84 log_debug(7, "in %s", __FUNCTION__
);
89 memset(&msg
, 0, sizeof(msg
));
90 msg
.msg_name
= (void*)&src_addr
;
91 msg
.msg_namelen
= sizeof(src_addr
);
95 rc
= recvmsg(ctrl_fd
, &msg
, flags
);
101 nlpayload_read(int ctrl_fd
, char *data
, int count
, int flags
)
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
);
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
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
);
152 kwritev(enum iscsi_uevent_e type
, struct iovec
*iovp
, int count
)
155 struct nlmsghdr
*nlh
;
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
;
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
;
184 for (i
= 0; i
< count
; i
++) {
185 memcpy(NLMSG_DATA(nlh
) + datalen
, iovp
[i
].iov_base
,
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
);
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
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);
223 log_debug(1, "sendmsg: alloc_skb() failed");
226 log_error("sendmsg: bug? ctrl_fd %d", ctrl_fd
);
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:
248 * Its OK to block for cleanup for short period of time in operatations for:
251 * - session_destroy()
253 * FIXME: interface needs to be extended to allow longer blocking on
257 __kipc_call(void *iov_base
, int iov_len
)
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);
272 if ((rc
= nlpayload_read(ctrl_fd
, (void*)ev
,
273 sizeof(*ev
), MSG_PEEK
)) < 0) {
276 if (ev
->type
!= type
) {
277 log_debug(1, "expecting event %d, got %d, handling...",
279 if (ev
->type
== ISCSI_KEVENT_IF_ERROR
) {
280 if ((rc
= nlpayload_read(ctrl_fd
, (void*)ev
,
281 sizeof(*ev
), 0)) < 0) {
285 * iferror is u32, but the kernel returns
286 * negative errno values for errors.
290 if (iferr
== -ENOSYS
)
291 /* not fatal so let caller handle log */
292 log_debug(1, "Received iferror %d: %s.",
293 iferr
, strerror(-iferr
));
295 log_error("Received iferror %d: %s.",
296 iferr
, strerror(-iferr
));
298 log_error("Received iferror %d.",
303 * receive and queue async. event which as of
309 } else if (ev
->type
== ISCSI_UEVENT_GET_STATS
) {
310 /* kget_stats() will read */
313 if ((rc
= nlpayload_read(ctrl_fd
, (void*)ev
,
314 sizeof(*ev
), 0)) < 0) {
319 } while (ev
->type
!= type
);
325 ksendtargets(uint64_t transport_handle
, uint32_t host_no
, struct sockaddr
*addr
)
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
);
344 log_error("%s unknown addr family %d\n",
345 __FUNCTION__
, addr
->sa_family
);
348 memcpy(setparam_buf
+ sizeof(*ev
), addr
, addrlen
);
350 rc
= __kipc_call(ev
, sizeof(*ev
) + addrlen
);
352 log_error("sendtargets failed rc%d\n", rc
);
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
)
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
;
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) {
389 *hostno
= ev
.r
.c_session_ret
.host_no
;
390 *out_sid
= ev
.r
.c_session_ret
.sid
;
396 kdestroy_session(uint64_t transport_handle
, uint32_t sid
)
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) {
417 kunbind_session(uint64_t transport_handle
, uint32_t sid
)
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) {
438 kcreate_conn(uint64_t transport_handle
, uint32_t sid
,
439 uint32_t cid
, uint32_t *out_cid
)
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
);
458 if ((int)ev
.r
.c_conn_ret
.cid
== -1)
461 *out_cid
= ev
.r
.c_conn_ret
.cid
;
466 kdestroy_conn(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
)
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) {
488 kbind_conn(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
,
489 uint64_t transport_eph
, int is_leading
, int *retcode
)
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) {
509 *retcode
= ev
.r
.retcode
;
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__
);
523 log_error("send's begin state machine bug?");
527 xmitbuf
= pdu_sendbuf
;
528 memset(xmitbuf
, 0, sizeof(*ev
) + hdr_size
+ data_size
);
529 xmitlen
= sizeof(*ev
);
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
);
544 ksend_pdu_end(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
,
548 struct iscsi_uevent
*ev
;
551 log_debug(7, "in %s", __FUNCTION__
);
554 log_error("send's end state machine bug?");
558 if (ev
->u
.send_pdu
.sid
!= sid
|| ev
->u
.send_pdu
.cid
!= cid
) {
559 log_error("send's end state machine corruption?");
563 iov
.iov_base
= xmitbuf
;
564 iov
.iov_len
= xmitlen
;
566 if ((rc
= __kipc_call(xmitbuf
, xmitlen
)) < 0)
569 *retcode
= ev
->r
.retcode
;
572 if (ev
->type
!= ISCSI_UEVENT_SEND_PDU
) {
573 log_error("bad event: bug on send_pdu_end?");
577 log_debug(3, "send PDU finished for conn %d:%d",
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
;
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
);
609 sprintf(param_str
, "%d", *((int *)value
));
614 sprintf(param_str
, "%s", (char *)value
);
617 log_error("invalid type %d\n", type
);
620 ev
->u
.set_host_param
.len
= len
= strlen(param_str
) + 1;
622 if ((rc
= __kipc_call(ev
, sizeof(*ev
) + len
)) < 0) {
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
;
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
);
650 sprintf(param_str
, "%d", *((int *)value
));
655 sprintf(param_str
, "%s", (char *)value
);
658 log_error("invalid type %d\n", type
);
661 ev
->u
.set_param
.len
= len
= strlen(param_str
) + 1;
663 if ((rc
= __kipc_call(ev
, sizeof(*ev
) + len
)) < 0) {
671 kstop_conn(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
, int flag
)
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) {
694 kstart_conn(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
,
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) {
713 *retcode
= ev
.r
.retcode
;
718 krecv_pdu_begin(struct iscsi_conn
*conn
)
722 log_debug(7, "in %s", __FUNCTION__
);
725 log_error("recv's begin state machine bug?");
729 if (!conn
->recv_context
) {
730 rc
= ipc
->ctldev_handle();
732 /* event for some other conn */
735 /* fatal handling error or conn error */
738 * Session create/destroy event for another conn
740 if (!conn
->recv_context
)
744 recvbuf
= conn
->recv_context
->data
+ sizeof(struct iscsi_uevent
);
747 log_debug(3, "recv PDU began, pdu handle %p", recvbuf
);
752 krecv_pdu_end(struct iscsi_conn
*conn
)
754 log_debug(7, "in %s", __FUNCTION__
);
757 log_error("recv's end state machine bug?");
761 log_debug(3, "recv PDU finished for pdu handle 0x%p",
764 ipc_ev_clbk
->put_ev_context(conn
->recv_context
);
765 conn
->recv_context
= NULL
;
771 ktransport_ep_connect(iscsi_conn_t
*conn
, int non_blocking
)
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
;
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
;
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
);
797 log_error("%s unknown addr family %d\n",
798 __FUNCTION__
, dst_addr
->sa_family
);
801 memcpy(setparam_buf
+ sizeof(*ev
), dst_addr
, addrlen
);
803 if ((rc
= __kipc_call(ev
, sizeof(*ev
) + addrlen
)) < 0)
806 if (!ev
->r
.ep_connect_ret
.handle
)
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
);
817 ktransport_ep_poll(iscsi_conn_t
*conn
, int timeout_ms
)
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)
838 ktransport_ep_disconnect(iscsi_conn_t
*conn
)
841 struct iscsi_uevent ev
;
843 log_debug(7, "in %s", __FUNCTION__
);
845 if (conn
->transport_ep_handle
== -1)
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
);
859 conn
->transport_ep_handle
= -1;
863 kget_stats(uint64_t transport_handle
, uint32_t sid
, uint32_t cid
,
864 char *statsbuf
, int statsbuf_max
)
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) {
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
);
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
);
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);
922 log_error("Could not drop %d bytes of data.\n",
930 static int ctldev_handle(void)
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
);
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 */
954 case ISCSI_KEVENT_CREATE_SESSION
:
955 /* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
956 case ISCSI_UEVENT_CREATE_SESSION
:
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
);
962 case ISCSI_KEVENT_DESTROY_SESSION
:
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
);
968 case ISCSI_KEVENT_RECV_PDU
:
969 sid
= ev
->r
.recv_req
.sid
;
970 cid
= ev
->r
.recv_req
.cid
;
972 case ISCSI_KEVENT_CONN_ERROR
:
973 sid
= ev
->r
.connerror
.sid
;
974 cid
= ev
->r
.connerror
.cid
;
976 case ISCSI_KEVENT_UNBIND_SESSION
:
977 sid
= ev
->r
.unbind_session
.sid
;
978 /* session wide event so cid is 0 */
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
);
988 * If another app is using the interface we might
990 * stuff. Just drop it.
992 log_debug(7, "Got unknwon event %d. Dropping.",
998 /* verify connection */
999 session
= session_find_by_sid(sid
);
1002 * this can happen normally when other apps are using the
1005 log_debug(1, "Could not verify connection %d:%d. Dropping "
1006 "event.\n", sid
, cid
);
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
);
1017 log_error("Can not allocate memory for receive context.");
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
,
1026 ipc_ev_clbk
->put_ev_context(ev_context
);
1027 log_error("can not read from NL socket, error %d", rc
);
1033 * we sched these events because the handlers could call back
1034 * into ctldev_handle
1037 case ISCSI_KEVENT_RECV_PDU
:
1038 rc
= ipc_ev_clbk
->sched_ev_context(ev_context
, conn
, 0,
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,
1047 case ISCSI_KEVENT_UNBIND_SESSION
:
1048 rc
= ipc_ev_clbk
->sched_ev_context(ev_context
, conn
, 0,
1052 ipc_ev_clbk
->put_ev_context(ev_context
);
1053 log_error("unknown kernel event %d", ev
->type
);
1058 ipc_ev_clbk
->put_ev_context(ev_context
);
1065 log_debug(7, "in %s", __FUNCTION__
);
1067 nlm_sendbuf
= calloc(1, NLM_BUF_DEFAULT_MAX
);
1069 log_error("can not allocate nlm_sendbuf");
1073 nlm_recvbuf
= calloc(1, NLM_BUF_DEFAULT_MAX
);
1075 log_error("can not allocate nlm_recvbuf");
1076 goto free_nlm_sendbuf
;
1079 pdu_sendbuf
= calloc(1, PDU_SENDBUF_DEFAULT_MAX
);
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
);
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");
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...");
1131 log_debug(7, "in %s", __FUNCTION__
);
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
,
1157 .start_conn
= kstart_conn
,
1158 .stop_conn
= kstop_conn
,
1159 .get_stats
= kget_stats
,
1161 .send_pdu_begin
= ksend_pdu_begin
,
1162 .send_pdu_end
= ksend_pdu_end
,
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
;