2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Stefan Metzmacher 2016
5 * Copyright (C) Ralph Boehme 2016
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 by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "system/network.h"
25 #include "lib/util/tevent_ntstatus.h"
26 #include "lib/util/tevent_unix.h"
27 #include "lib/util/tevent_ntstatus.h"
28 #include "lib/util/blocking.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "lib/util/debug.h"
31 #include "lib/util/data_blob.h"
32 #include "librpc/gen_ndr/smb_direct_daemon.h"
33 #include "librpc/gen_ndr/ndr_smb_direct_daemon.h"
34 #include "librpc/ndr/libndr.h"
35 #include "libcli/util/tstream.h"
36 #include "lib/util/byteorder.h"
37 #include "lib/util/samba_util.h"
38 #include "lib/util/blocking.h"
40 #ifdef SMB_TRANSPORT_ENABLE_RDMA
41 #include <rdma/rdma_cma_abi.h>
42 #include <rdma/rdma_cma.h>
43 #include "smb_direct.h"
44 #include "smb_direct_util.h"
46 struct smb_direct_daemon_state {
48 * Global state of the daemon
51 /* Our tevent context */
52 struct tevent_context *ev;
58 * Path, fd and fde for the listening UNIX domain socket
62 struct tevent_fd *listen_fde;
64 struct sdd_listen_params params;
67 * Pointer to the connection in listening state. There can be
68 * only one and it will receive all new SMB-D connections.
70 struct smb_direct_daemon_conn *listening_conn;
73 struct rdma_cm_id *cm_id;
74 struct rdma_event_channel *cm_channel;
75 struct tevent_fd *cm_channel_fde;
79 struct smb_direct_daemon_conn {
81 * Connection object, one for each peer.
84 /* Backpointer to the global daemon state */
85 struct smb_direct_daemon_state *daemon_state;
87 /* Our tevent context */
88 struct tevent_context *ev;
91 * We use the tstream_context for general protocol data
92 * exchange and use the fd for fd-passing with
93 * sendmsg()/recvmsg().
96 struct tstream_context *stream;
98 /* true if our peer is root */
102 * A connection in the listening state can only be used with
103 * smb_direct_accept() to accept a connection fd and can't be
104 * used for messaging.
109 static struct tevent_req *smb_direct_daemon_conn_send(
111 struct tevent_context *ev,
112 struct smb_direct_daemon_state *daemon_state,
115 struct tstream_context **stream);
117 static int smb_direct_daemon_conn_recv(struct tevent_req *req);
119 struct smbd_direct_daemon_write_state {
120 struct smb_direct_daemon_conn *conn;
125 static void smbd_direct_daemon_write_done(struct tevent_req *subreq);
127 static struct tevent_req *smbd_direct_daemon_write_send(
128 struct smb_direct_daemon_conn *conn,
131 struct tevent_req *req = NULL;
132 struct smbd_direct_daemon_write_state *write_state = NULL;
133 struct tevent_req *subreq = NULL;
135 req = tevent_req_create(conn, &write_state,
136 struct smbd_direct_daemon_write_state);
141 *write_state = (struct smbd_direct_daemon_write_state) {
143 .out_data = out_data,
145 talloc_steal(write_state, write_state->out_data.data);
147 write_state->iov = (struct iovec) {
148 .iov_base = write_state->out_data.data,
149 .iov_len = write_state->out_data.length
152 subreq = tstream_writev_send(write_state, conn->ev, conn->stream,
153 &write_state->iov, 1);
154 if (tevent_req_nomem(subreq, req)) {
155 return tevent_req_post(req, conn->ev);
157 tevent_req_set_callback(subreq, smbd_direct_daemon_write_done, req);
162 static void smbd_direct_daemon_write_done(struct tevent_req *subreq)
164 struct tevent_req *req = tevent_req_callback_data(
165 subreq, struct tevent_req);
169 result = tstream_writev_recv(subreq, &err);
171 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
175 tevent_req_done(req);
178 static NTSTATUS smbd_direct_daemon_write_recv(struct tevent_req *req)
182 if (tevent_req_is_nterror(req, &status)) {
183 tevent_req_received(req);
187 tevent_req_received(req);
191 struct smbd_direct_daemon_read_state {
192 struct smb_direct_daemon_conn *conn;
196 static void smbd_direct_daemon_read_done(struct tevent_req *subreq);
198 static NTSTATUS smbd_direct_daemon_packet_full(void *private_data,
204 if (blob.length < 4) {
205 return STATUS_MORE_ENTRIES;
208 packet_len = IVAL(&blob.data[0], 0);
209 if (packet_len < 5 || packet_len > 0x1000) {
210 return NT_STATUS_DATA_ERROR;
215 if (*size > blob.length) {
216 return STATUS_MORE_ENTRIES;
222 static struct tevent_req *smbd_direct_daemon_read_send(
223 struct smb_direct_daemon_conn *conn)
225 struct tevent_req *req = NULL;
226 struct smbd_direct_daemon_read_state *read_state = NULL;
227 struct tevent_req *subreq = NULL;
229 req = tevent_req_create(conn, &read_state,
230 struct smbd_direct_daemon_read_state);
235 *read_state = (struct smbd_direct_daemon_read_state) {
239 subreq = tstream_read_pdu_blob_send(read_state,
242 4, /* initial_read_size */
243 smbd_direct_daemon_packet_full,
245 if (tevent_req_nomem(subreq, req)) {
246 return tevent_req_post(req, conn->ev);
248 tevent_req_set_callback(subreq, smbd_direct_daemon_read_done, req);
253 static void smbd_direct_daemon_read_done(struct tevent_req *subreq)
255 struct tevent_req *req = tevent_req_callback_data(
256 subreq, struct tevent_req);
257 struct smbd_direct_daemon_read_state *read_state = tevent_req_data(
258 req, struct smbd_direct_daemon_read_state);
261 status = tstream_read_pdu_blob_recv(subreq, read_state,
262 &read_state->in_data);
264 if (tevent_req_nterror(req, status)) {
265 DBG_ERR("tstream_read_pdu_blob_recv [%s]",
270 tevent_req_done(req);
273 static NTSTATUS smbd_direct_daemon_read_recv(struct tevent_req *req,
277 struct smbd_direct_daemon_read_state *read_state = tevent_req_data(
278 req, struct smbd_direct_daemon_read_state);
281 if (tevent_req_is_nterror(req, &status)) {
282 DBG_ERR("tstream_read_pdu_blob_recv [%s]",
284 tevent_req_received(req);
288 *in_data = read_state->in_data;
289 talloc_steal(mem_ctx, in_data->data);
291 tevent_req_received(req);
295 static void smb_direct_daemon_req_cleanup(struct tevent_req *req,
296 enum tevent_req_state req_state)
298 struct smb_direct_daemon_state *state = tevent_req_data(
299 req, struct smb_direct_daemon_state);
301 TALLOC_FREE(state->listen_fde);
303 if (state->listen_path != NULL) {
304 unlink(state->listen_path);
305 TALLOC_FREE(state->listen_path);
308 if (state->listen_fd != -1) {
309 close(state->listen_fd);
310 state->listen_fd = -1;
313 if (state->socket_lock_fd != -1) {
314 close(state->socket_lock_fd);
315 state->socket_lock_fd = -1;
319 static void smb_direct_daemon_listen_handler(struct tevent_context *ev,
320 struct tevent_fd *fde,
324 struct tevent_req *smb_direct_daemon_send(TALLOC_CTX *mem_ctx,
325 struct tevent_context *ev)
327 struct tevent_req *req = NULL;
328 struct smb_direct_daemon_state *state = NULL;
329 char *lock_path = NULL;
330 char *listen_path = NULL;
332 struct sockaddr_un su;
338 req = tevent_req_create(mem_ctx, &state, struct smb_direct_daemon_state);
342 *state = (struct smb_direct_daemon_state) {
345 .socket_lock_fd = -1,
348 tevent_req_set_cleanup_fn(req, smb_direct_daemon_req_cleanup);
350 lock_path = smb_direct_lock_path(state);
351 if (tevent_req_nomem(lock_path, req)) {
352 return tevent_req_post(req, ev);
355 state->socket_lock_fd = open(lock_path, O_CREAT|O_RDWR, 0700);
356 if (state->socket_lock_fd == -1) {
357 DBG_ERR("Can't open socket lockfile %s [%s]\n",
358 lock_path, strerror(errno));
359 tevent_req_error(req, errno);
360 return tevent_req_post(req, ev);
363 ok = fcntl_lock(state->socket_lock_fd, F_SETLK, 0, 0, F_WRLCK);
365 DBG_ERR("Can't lock socket lockfile %s [%s]\n",
366 lock_path, strerror(errno));
367 tevent_req_error(req, errno);
368 return tevent_req_post(req, ev);
371 listen_path = smb_direct_socket_path(state);
372 if (tevent_req_nomem(listen_path, req)) {
373 DBG_ERR("smb_direct_socket_path failed\n");
374 return tevent_req_post(req, ev);
377 if (strlen(listen_path) > sizeof(addr.su.sun_path) - 1) {
378 DBG_ERR("listen_path too long [%s]\n", listen_path);
379 tevent_req_error(req, ENAMETOOLONG);
380 return tevent_req_post(req, ev);
386 addr.su.sun_family = AF_UNIX;
387 strncpy(addr.su.sun_path, listen_path,
388 sizeof(addr.su.sun_path) - 1);
390 state->listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
391 if (state->listen_fd == -1) {
392 DBG_ERR("socket failed [%s]\n", strerror(errno));
393 tevent_req_error(req, errno);
394 return tevent_req_post(req, ev);
397 set_close_on_exec(state->listen_fd);
399 ret = bind(state->listen_fd, &addr.sa, sizeof(addr.su));
401 DBG_ERR("bind failed [%s]\n", strerror(errno));
402 tevent_req_error(req, errno);
403 return tevent_req_post(req, ev);
407 * Once the bind has created the socket file set the path in
408 * the state for the cleanup function.
410 state->listen_path = listen_path;
412 ret = listen(state->listen_fd, SMB_DIRECT_LISTEN_BACKLOG);
414 DBG_ERR("listen failed [%s]\n", strerror(errno));
415 tevent_req_error(req, errno);
416 return tevent_req_post(req, ev);
419 set_blocking(state->listen_fd, false);
421 state->listen_fde = tevent_add_fd(ev, state,
424 smb_direct_daemon_listen_handler,
426 if (tevent_req_nomem(state->listen_fde, req)) {
427 return tevent_req_post(req, ev);
430 DBG_NOTICE("smb_direct_daemon started\n");
435 static void smb_direct_daemon_conn_disconnect(struct tevent_req *subreq);
437 static void smb_direct_daemon_listen_handler(struct tevent_context *ev,
438 struct tevent_fd *fde,
442 struct tevent_req *req = talloc_get_type_abort(
443 private_data, struct tevent_req);
444 struct smb_direct_daemon_state *daemon_state = tevent_req_data(
445 req, struct smb_direct_daemon_state);
450 bool privileged = false;
451 struct tstream_context *stream = NULL;
452 struct tevent_req *subreq = NULL;
454 conn_fd = accept(daemon_state->listen_fd, NULL, NULL);
456 if (errno != EINTR && errno != EAGAIN) {
457 DBG_WARNING("accept failed [%s]\n", strerror(errno));
462 set_close_on_exec(conn_fd);
464 ret = getpeereid(conn_fd, &peer_uid, &peer_gid);
466 DBG_WARNING("getpeereid failed [%s]\n", strerror(errno));
471 if (peer_uid == geteuid()) {
475 set_blocking(conn_fd, false);
477 ret = tstream_bsd_existing_socket(daemon_state, conn_fd, &stream);
479 DBG_WARNING("tstream_bsd_existing_socket failed [%s]\n",
485 subreq = smb_direct_daemon_conn_send(daemon_state,
490 if (subreq == NULL) {
491 DBG_WARNING("smb_direct_daemon_conn_send failed [%s]\n",
496 tevent_req_set_callback(subreq, smb_direct_daemon_conn_disconnect, req);
499 static void smb_direct_daemon_conn_disconnect(struct tevent_req *subreq)
503 ret = smb_direct_daemon_conn_recv(subreq);
506 DBG_DEBUG("smb_direct_daemon_conn_send failed\n");
510 int smb_direct_daemon_recv(struct tevent_req *req)
512 return tevent_req_simple_recv_unix(req);
515 static NTSTATUS smbd_direct_daemon_ping(
516 struct sdd_packet_ping_request *ping_request,
517 struct sdd_packet_ping_response *ping_response)
519 ping_response->data = ping_request->data;
523 static void rdma_cm_handler(struct tevent_context *ev,
524 struct tevent_fd *fde,
528 static NTSTATUS smbd_direct_daemon_listen(
529 struct smb_direct_daemon_conn *conn,
530 struct sdd_packet_listen_request *listen_request,
531 struct sdd_packet_listen_response *listen_response)
533 struct smb_direct_daemon_state *daemon_state = conn->daemon_state;
534 struct sockaddr_in inaddr;
537 DBG_ERR("got listen request...\n");
539 if (daemon_state->listening_conn != NULL) {
540 /* There can be only one... */
541 return NT_STATUS_INVALID_PARAMETER;
544 daemon_state->rdma.cm_channel = rdma_create_event_channel();
545 if (daemon_state->rdma.cm_channel == NULL) {
546 DBG_ERR("rdma_create_event_channel failed [%s]\n",
548 return NT_STATUS_INTERNAL_ERROR;
551 set_close_on_exec(daemon_state->rdma.cm_channel->fd);
552 set_blocking(daemon_state->rdma.cm_channel->fd, false);
554 #if RDMA_USER_CM_MAX_ABI_VERSION >= 2
555 result = rdma_create_id(daemon_state->rdma.cm_channel,
556 &daemon_state->rdma.cm_id,
560 result = rdma_create_id(daemon_state->rdma.cm_channel,
561 &daemon_state->rdma.cm_id,
565 DBG_ERR("rdma_create_id failed [%s]\n",
570 daemon_state->rdma.cm_channel_fde = tevent_add_fd(
573 daemon_state->rdma.cm_channel->fd,
577 if (daemon_state->rdma.cm_channel_fde == NULL) {
578 DBG_ERR("tevent_add_fd failed\n");
583 inaddr.sin_family = AF_INET;
584 inaddr.sin_port = htons(5445);
585 inaddr.sin_addr.s_addr = INADDR_ANY;
587 result = rdma_bind_addr(daemon_state->rdma.cm_id,
588 (struct sockaddr *)&inaddr);
590 DBG_ERR("rdma_bind_addr failed\n");
594 result = rdma_listen(daemon_state->rdma.cm_id,
595 SMB_DIRECT_LISTEN_BACKLOG);
597 DBG_ERR("rdma_bind_addr failed\n");
601 conn->listening = true;
603 daemon_state->params = listen_request->params;
604 daemon_state->listening_conn = conn;
605 listen_response->status = 0;
607 DBG_ERR("SMB-D daemon started accepting SMB-D connections\n");
612 rdma_destroy_id(daemon_state->rdma.cm_id);
613 daemon_state->rdma.cm_id = NULL;
614 rdma_destroy_event_channel(daemon_state->rdma.cm_channel);
615 daemon_state->rdma.cm_channel = NULL;
616 return NT_STATUS_INTERNAL_ERROR;
619 static NTSTATUS smbd_direct_daemon_dispatch(struct smb_direct_daemon_conn *conn,
623 struct sdd_packetB *request_packet = NULL;
624 struct sdd_packetB *response_packet = NULL;
625 enum ndr_err_code ndr_err;
628 if (conn->listening) {
629 return NT_STATUS_INVALID_MESSAGE;
632 request_packet = talloc_zero(conn, struct sdd_packetB);
633 if (request_packet == NULL) {
634 return NT_STATUS_NO_MEMORY;
637 response_packet = talloc_zero(conn, struct sdd_packetB);
638 if (response_packet == NULL) {
639 return NT_STATUS_NO_MEMORY;
642 ndr_err = ndr_pull_struct_blob_all(
643 &in_data, request_packet, request_packet,
644 (ndr_pull_flags_fn_t)ndr_pull_sdd_packetB);
645 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
646 return NT_STATUS_DATA_ERROR;
649 switch (request_packet->command) {
651 case SDD_PING_REQUEST: {
652 struct sdd_packet_ping_response ping_response;
654 ZERO_STRUCT(ping_response);
656 status = smbd_direct_daemon_ping(
657 &request_packet->packet.ping_request,
659 if (!NT_STATUS_IS_OK(status)) {
663 response_packet->command = SDD_PING_RESPONSE;
664 response_packet->packet.ping_response = ping_response;
668 case SDD_LISTEN_REQUEST: {
669 struct sdd_packet_listen_response listen_response;
671 ZERO_STRUCT(listen_response);
673 status = smbd_direct_daemon_listen(
675 &request_packet->packet.listen_request,
677 if (!NT_STATUS_IS_OK(status)) {
681 response_packet->command = SDD_LISTEN_RESPONSE;
682 response_packet->packet.listen_response = listen_response;
687 status = NT_STATUS_DATA_ERROR;
691 ndr_err = ndr_push_struct_blob(
692 out_data, conn, response_packet,
693 (ndr_push_flags_fn_t)ndr_push_sdd_packetB);
694 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
695 status = NT_STATUS_DATA_ERROR;
699 SIVAL(&out_data->data[0], 0, out_data->length);
702 TALLOC_FREE(request_packet);
703 TALLOC_FREE(response_packet);
707 static void smbd_direct_daemon_conn_handler(struct tevent_req *read_req);
708 static void smbd_direct_daemon_conn_handler_next(struct tevent_req *write_req);
710 static void smb_direct_daemon_conn_cleanup(struct tevent_req *req,
711 enum tevent_req_state req_state)
713 struct smb_direct_daemon_conn *conn = tevent_req_data(
714 req, struct smb_direct_daemon_conn);
715 struct smb_direct_daemon_state *daemon_state = NULL;
718 if (conn->conn_fd != -1) {
719 close(conn->conn_fd);
723 if (conn->daemon_state->listening_conn != conn) {
727 daemon_state = conn->daemon_state;
728 daemon_state->listening_conn = NULL;
730 rdma_destroy_event_channel(daemon_state->rdma.cm_channel);
731 daemon_state->rdma.cm_channel = NULL;
733 result = rdma_destroy_id(daemon_state->rdma.cm_id);
735 DBG_ERR("rdma_destroy_id failed [%s]\n",
738 daemon_state->rdma.cm_id = NULL;
742 * @brief Handle an already accepted connection
744 * Connection handler, called just after the connection was accepted.
746 static struct tevent_req *smb_direct_daemon_conn_send(
748 struct tevent_context *ev,
749 struct smb_direct_daemon_state *daemon_state,
752 struct tstream_context **stream)
754 struct tevent_req *req = NULL;
755 struct smb_direct_daemon_conn *conn = NULL;
756 struct tevent_req *subreq = NULL;
758 req = tevent_req_create(mem_ctx, &conn, struct smb_direct_daemon_conn);
763 *conn = (struct smb_direct_daemon_conn) {
765 .daemon_state = daemon_state,
767 .stream = talloc_move(conn, stream),
768 .privileged = privileged,
771 tevent_req_set_cleanup_fn(req, smb_direct_daemon_conn_cleanup);
773 subreq = smbd_direct_daemon_read_send(conn);
774 if (tevent_req_nomem(subreq, req)) {
775 tevent_req_post(req, ev);
777 tevent_req_set_callback(subreq, smbd_direct_daemon_conn_handler, req);
781 static void smbd_direct_daemon_conn_handler(struct tevent_req *read_req)
783 struct tevent_req *conn_req = tevent_req_callback_data(
784 read_req, struct tevent_req);
785 struct smb_direct_daemon_conn *conn = tevent_req_data(
786 conn_req, struct smb_direct_daemon_conn);
787 struct tevent_req *write_req = NULL;
792 status = smbd_direct_daemon_read_recv(read_req, conn, &in_data);
793 TALLOC_FREE(read_req);
794 if (tevent_req_nterror(conn_req, status)) {
795 DBG_ERR("smbd_direct_daemon_read_recv [%s]",
800 status = smbd_direct_daemon_dispatch(conn, in_data, &out_data);
801 if (tevent_req_nterror(conn_req, status)) {
802 DBG_ERR("smbd_direct_daemon_read_recv [%s]",
807 write_req = smbd_direct_daemon_write_send(conn, out_data);
808 if (tevent_req_nomem(write_req, conn_req)) {
811 tevent_req_set_callback(write_req,
812 smbd_direct_daemon_conn_handler_next,
816 static void smbd_direct_daemon_conn_handler_next(struct tevent_req *write_req)
819 struct tevent_req *conn_req = tevent_req_callback_data(
820 write_req, struct tevent_req);
821 struct smb_direct_daemon_conn *conn = tevent_req_data(
822 conn_req, struct smb_direct_daemon_conn);
823 struct tevent_req *read_req = NULL;
825 status = smbd_direct_daemon_write_recv(write_req);
826 TALLOC_FREE(write_req);
827 if (tevent_req_nterror(conn_req, status)) {
828 DBG_ERR("smbd_direct_daemon_write_recv [%s]",
833 read_req = smbd_direct_daemon_read_send(conn);
834 if (tevent_req_nomem(read_req, conn_req)) {
837 tevent_req_set_callback(read_req,
838 smbd_direct_daemon_conn_handler,
842 static int smb_direct_daemon_conn_recv(struct tevent_req *req)
844 return tevent_req_simple_recv_unix(req);
847 static void rdma_cm_handler(struct tevent_context *ev,
848 struct tevent_fd *fde,
852 struct smb_direct_daemon_state *daemon_state = talloc_get_type_abort(
853 private_data, struct smb_direct_daemon_state);
854 struct smb_direct_connection *sconn = NULL;
855 struct rdma_cm_event *cm_ev = NULL;
859 DBG_ERR("SMB-D got connection event\n");
861 result = rdma_get_cm_event(daemon_state->rdma.cm_channel, &cm_ev);
863 DBG_ERR("rdma_get_cm_event failed [%s]\n", strerror(errno));
867 DBG_ERR("cm_event type [%d] cm_id [%p]\n",
868 cm_ev->event, cm_ev->id);
870 switch (cm_ev->event) {
871 case RDMA_CM_EVENT_CONNECT_REQUEST: {
872 struct rdma_conn_param conn_param;
873 uint8_t ird_ord_hdr[8];
875 RSIVAL(ird_ord_hdr, 0, 0);
876 RSIVAL(ird_ord_hdr, 4, 16);
878 DBG_DEBUG("RDMA_CM_EVENT_CONNECT_REQUEST\n");
880 ZERO_STRUCT(conn_param);
881 // conn_param.private_data = ird_ord_hdr;
882 // conn_param.private_data_len = sizeof(ird_ord_hdr);
883 conn_param.responder_resources = 1;
884 conn_param.initiator_depth = 1;
885 // conn_param.retry_count = 10;
889 result = rdma_accept(cm_ev->id, NULL);
891 DBG_ERR("rdma_accept failed [%s] result [%d]\n", strerror(errno), result);
895 sconn = smb_direct_connection_listener(daemon_state,
898 DBG_ERR("smb_direct_connection_create failed\n");
902 cm_ev->id->context = sconn;
906 case RDMA_CM_EVENT_ESTABLISHED:
907 DBG_DEBUG("RDMA_CM_EVENT_ESTABLISHED\n");
909 sconn = talloc_get_type_abort(cm_ev->id->context,
910 struct smb_direct_connection);
911 status = smb_direct_connection_complete_alloc(sconn);
912 if (!NT_STATUS_IS_OK(status)) {
913 DBG_ERR("smb_direct_connection_complete_alloc failed\n");
917 * TODO: get things going...
921 case RDMA_CM_EVENT_DISCONNECTED:
922 DBG_DEBUG("RDMA_CM_EVENT_DISCONNECTED\n");
924 sconn = talloc_get_type(cm_ev->id->context,
925 struct smb_direct_connection);
929 case RDMA_CM_EVENT_DEVICE_REMOVAL:
930 DBG_ERR("RDMA device removal\n");
934 DBG_ERR("event %d\n", cm_ev->event);
938 result = rdma_ack_cm_event(cm_ev);
940 DBG_ERR("rdma_ack_cm_event failed [%s]\n", strerror(errno));
947 rdma_ack_cm_event(cm_ev);
949 if (cm_ev->id == daemon_state->rdma.cm_id) {
950 /* Listening conn is erroring out, shut it down and die */
951 TALLOC_FREE(daemon_state->listening_conn);
952 // tevent_req_error(daemon_state->req, EPANIC);
959 #endif /* SMB_TRANSPORT_ENABLE_RDMA */