1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
6 #include <linux/jhash.h>
7 #include <linux/slab.h>
8 #include <linux/rwsem.h>
9 #include <linux/mutex.h>
10 #include <linux/wait.h>
11 #include <linux/hashtable.h>
12 #include <net/net_namespace.h>
13 #include <net/genetlink.h>
14 #include <linux/socket.h>
15 #include <linux/workqueue.h>
17 #include "vfs_cache.h"
18 #include "transport_ipc.h"
20 #include "smb_common.h"
22 #include "mgmt/user_config.h"
23 #include "mgmt/share_config.h"
24 #include "mgmt/user_session.h"
25 #include "mgmt/tree_connect.h"
26 #include "mgmt/ksmbd_ida.h"
27 #include "connection.h"
28 #include "transport_tcp.h"
30 #define IPC_WAIT_TIMEOUT (2 * HZ)
32 #define IPC_MSG_HASH_BITS 3
33 static DEFINE_HASHTABLE(ipc_msg_table
, IPC_MSG_HASH_BITS
);
34 static DECLARE_RWSEM(ipc_msg_table_lock
);
35 static DEFINE_MUTEX(startup_lock
);
37 static DEFINE_IDA(ipc_ida
);
39 static unsigned int ksmbd_tools_pid
;
41 static bool ksmbd_ipc_validate_version(struct genl_info
*m
)
43 if (m
->genlhdr
->version
!= KSMBD_GENL_VERSION
) {
44 pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
45 "Daemon and kernel module version mismatch",
48 "User-space ksmbd should terminate");
54 struct ksmbd_ipc_msg
{
57 unsigned char payload
[];
60 struct ipc_msg_table_entry
{
63 wait_queue_head_t wait
;
64 struct hlist_node ipc_table_hlist
;
69 static struct delayed_work ipc_timer_work
;
71 static int handle_startup_event(struct sk_buff
*skb
, struct genl_info
*info
);
72 static int handle_unsupported_event(struct sk_buff
*skb
, struct genl_info
*info
);
73 static int handle_generic_event(struct sk_buff
*skb
, struct genl_info
*info
);
74 static int ksmbd_ipc_heartbeat_request(void);
76 static const struct nla_policy ksmbd_nl_policy
[KSMBD_EVENT_MAX
] = {
77 [KSMBD_EVENT_UNSPEC
] = {
80 [KSMBD_EVENT_HEARTBEAT_REQUEST
] = {
81 .len
= sizeof(struct ksmbd_heartbeat
),
83 [KSMBD_EVENT_STARTING_UP
] = {
84 .len
= sizeof(struct ksmbd_startup_request
),
86 [KSMBD_EVENT_SHUTTING_DOWN
] = {
87 .len
= sizeof(struct ksmbd_shutdown_request
),
89 [KSMBD_EVENT_LOGIN_REQUEST
] = {
90 .len
= sizeof(struct ksmbd_login_request
),
92 [KSMBD_EVENT_LOGIN_RESPONSE
] = {
93 .len
= sizeof(struct ksmbd_login_response
),
95 [KSMBD_EVENT_SHARE_CONFIG_REQUEST
] = {
96 .len
= sizeof(struct ksmbd_share_config_request
),
98 [KSMBD_EVENT_SHARE_CONFIG_RESPONSE
] = {
99 .len
= sizeof(struct ksmbd_share_config_response
),
101 [KSMBD_EVENT_TREE_CONNECT_REQUEST
] = {
102 .len
= sizeof(struct ksmbd_tree_connect_request
),
104 [KSMBD_EVENT_TREE_CONNECT_RESPONSE
] = {
105 .len
= sizeof(struct ksmbd_tree_connect_response
),
107 [KSMBD_EVENT_TREE_DISCONNECT_REQUEST
] = {
108 .len
= sizeof(struct ksmbd_tree_disconnect_request
),
110 [KSMBD_EVENT_LOGOUT_REQUEST
] = {
111 .len
= sizeof(struct ksmbd_logout_request
),
113 [KSMBD_EVENT_RPC_REQUEST
] = {
115 [KSMBD_EVENT_RPC_RESPONSE
] = {
117 [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST
] = {
119 [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE
] = {
123 static struct genl_ops ksmbd_genl_ops
[] = {
125 .cmd
= KSMBD_EVENT_UNSPEC
,
126 .doit
= handle_unsupported_event
,
129 .cmd
= KSMBD_EVENT_HEARTBEAT_REQUEST
,
130 .doit
= handle_unsupported_event
,
133 .cmd
= KSMBD_EVENT_STARTING_UP
,
134 .doit
= handle_startup_event
,
137 .cmd
= KSMBD_EVENT_SHUTTING_DOWN
,
138 .doit
= handle_unsupported_event
,
141 .cmd
= KSMBD_EVENT_LOGIN_REQUEST
,
142 .doit
= handle_unsupported_event
,
145 .cmd
= KSMBD_EVENT_LOGIN_RESPONSE
,
146 .doit
= handle_generic_event
,
149 .cmd
= KSMBD_EVENT_SHARE_CONFIG_REQUEST
,
150 .doit
= handle_unsupported_event
,
153 .cmd
= KSMBD_EVENT_SHARE_CONFIG_RESPONSE
,
154 .doit
= handle_generic_event
,
157 .cmd
= KSMBD_EVENT_TREE_CONNECT_REQUEST
,
158 .doit
= handle_unsupported_event
,
161 .cmd
= KSMBD_EVENT_TREE_CONNECT_RESPONSE
,
162 .doit
= handle_generic_event
,
165 .cmd
= KSMBD_EVENT_TREE_DISCONNECT_REQUEST
,
166 .doit
= handle_unsupported_event
,
169 .cmd
= KSMBD_EVENT_LOGOUT_REQUEST
,
170 .doit
= handle_unsupported_event
,
173 .cmd
= KSMBD_EVENT_RPC_REQUEST
,
174 .doit
= handle_unsupported_event
,
177 .cmd
= KSMBD_EVENT_RPC_RESPONSE
,
178 .doit
= handle_generic_event
,
181 .cmd
= KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST
,
182 .doit
= handle_unsupported_event
,
185 .cmd
= KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE
,
186 .doit
= handle_generic_event
,
190 static struct genl_family ksmbd_genl_family
= {
191 .name
= KSMBD_GENL_NAME
,
192 .version
= KSMBD_GENL_VERSION
,
194 .maxattr
= KSMBD_EVENT_MAX
,
196 .module
= THIS_MODULE
,
197 .ops
= ksmbd_genl_ops
,
198 .n_ops
= ARRAY_SIZE(ksmbd_genl_ops
),
201 static void ksmbd_nl_init_fixup(void)
205 for (i
= 0; i
< ARRAY_SIZE(ksmbd_genl_ops
); i
++)
206 ksmbd_genl_ops
[i
].validate
= GENL_DONT_VALIDATE_STRICT
|
207 GENL_DONT_VALIDATE_DUMP
;
209 ksmbd_genl_family
.policy
= ksmbd_nl_policy
;
212 static int rpc_context_flags(struct ksmbd_session
*sess
)
214 if (user_guest(sess
->user
))
215 return KSMBD_RPC_RESTRICTED_CONTEXT
;
219 static void ipc_update_last_active(void)
221 if (server_conf
.ipc_timeout
)
222 server_conf
.ipc_last_active
= jiffies
;
225 static struct ksmbd_ipc_msg
*ipc_msg_alloc(size_t sz
)
227 struct ksmbd_ipc_msg
*msg
;
228 size_t msg_sz
= sz
+ sizeof(struct ksmbd_ipc_msg
);
230 msg
= kvmalloc(msg_sz
, GFP_KERNEL
| __GFP_ZERO
);
236 static void ipc_msg_free(struct ksmbd_ipc_msg
*msg
)
241 static void ipc_msg_handle_free(int handle
)
244 ksmbd_release_id(&ipc_ida
, handle
);
247 static int handle_response(int type
, void *payload
, size_t sz
)
249 unsigned int handle
= *(unsigned int *)payload
;
250 struct ipc_msg_table_entry
*entry
;
253 ipc_update_last_active();
254 down_read(&ipc_msg_table_lock
);
255 hash_for_each_possible(ipc_msg_table
, entry
, ipc_table_hlist
, handle
) {
256 if (handle
!= entry
->handle
)
259 entry
->response
= NULL
;
261 * Response message type value should be equal to
262 * request message type + 1.
264 if (entry
->type
+ 1 != type
) {
265 pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
266 entry
->type
+ 1, type
);
269 entry
->response
= kvmalloc(sz
, GFP_KERNEL
| __GFP_ZERO
);
270 if (!entry
->response
) {
275 memcpy(entry
->response
, payload
, sz
);
276 wake_up_interruptible(&entry
->wait
);
280 up_read(&ipc_msg_table_lock
);
285 static int ipc_server_config_on_startup(struct ksmbd_startup_request
*req
)
289 ksmbd_set_fd_limit(req
->file_max
);
290 server_conf
.flags
= req
->flags
;
291 server_conf
.signing
= req
->signing
;
292 server_conf
.tcp_port
= req
->tcp_port
;
293 server_conf
.ipc_timeout
= req
->ipc_timeout
* HZ
;
294 server_conf
.deadtime
= req
->deadtime
* SMB_ECHO_INTERVAL
;
295 server_conf
.share_fake_fscaps
= req
->share_fake_fscaps
;
296 ksmbd_init_domain(req
->sub_auth
);
298 if (req
->smb2_max_read
)
299 init_smb2_max_read_size(req
->smb2_max_read
);
300 if (req
->smb2_max_write
)
301 init_smb2_max_write_size(req
->smb2_max_write
);
302 if (req
->smb2_max_trans
)
303 init_smb2_max_trans_size(req
->smb2_max_trans
);
305 ret
= ksmbd_set_netbios_name(req
->netbios_name
);
306 ret
|= ksmbd_set_server_string(req
->server_string
);
307 ret
|= ksmbd_set_work_group(req
->work_group
);
308 ret
|= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req
),
311 pr_err("Server configuration error: %s %s %s\n",
312 req
->netbios_name
, req
->server_string
,
317 if (req
->min_prot
[0]) {
318 ret
= ksmbd_lookup_protocol_idx(req
->min_prot
);
320 server_conf
.min_protocol
= ret
;
322 if (req
->max_prot
[0]) {
323 ret
= ksmbd_lookup_protocol_idx(req
->max_prot
);
325 server_conf
.max_protocol
= ret
;
328 if (server_conf
.ipc_timeout
)
329 schedule_delayed_work(&ipc_timer_work
, server_conf
.ipc_timeout
);
333 static int handle_startup_event(struct sk_buff
*skb
, struct genl_info
*info
)
337 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
338 if (!netlink_capable(skb
, CAP_NET_ADMIN
))
342 if (!ksmbd_ipc_validate_version(info
))
345 if (!info
->attrs
[KSMBD_EVENT_STARTING_UP
])
348 mutex_lock(&startup_lock
);
349 if (!ksmbd_server_configurable()) {
350 mutex_unlock(&startup_lock
);
351 pr_err("Server reset is in progress, can't start daemon\n");
355 if (ksmbd_tools_pid
) {
356 if (ksmbd_ipc_heartbeat_request() == 0) {
361 pr_err("Reconnect to a new user space daemon\n");
363 struct ksmbd_startup_request
*req
;
365 req
= nla_data(info
->attrs
[info
->genlhdr
->cmd
]);
366 ret
= ipc_server_config_on_startup(req
);
369 server_queue_ctrl_init_work();
372 ksmbd_tools_pid
= info
->snd_portid
;
373 ipc_update_last_active();
376 mutex_unlock(&startup_lock
);
380 static int handle_unsupported_event(struct sk_buff
*skb
, struct genl_info
*info
)
382 pr_err("Unknown IPC event: %d, ignore.\n", info
->genlhdr
->cmd
);
386 static int handle_generic_event(struct sk_buff
*skb
, struct genl_info
*info
)
390 int type
= info
->genlhdr
->cmd
;
392 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
393 if (!netlink_capable(skb
, CAP_NET_ADMIN
))
397 if (type
>= KSMBD_EVENT_MAX
) {
402 if (!ksmbd_ipc_validate_version(info
))
405 if (!info
->attrs
[type
])
408 payload
= nla_data(info
->attrs
[info
->genlhdr
->cmd
]);
409 sz
= nla_len(info
->attrs
[info
->genlhdr
->cmd
]);
410 return handle_response(type
, payload
, sz
);
413 static int ipc_msg_send(struct ksmbd_ipc_msg
*msg
)
415 struct genlmsghdr
*nlh
;
419 if (!ksmbd_tools_pid
)
422 skb
= genlmsg_new(msg
->sz
, GFP_KERNEL
);
426 nlh
= genlmsg_put(skb
, 0, 0, &ksmbd_genl_family
, 0, msg
->type
);
430 ret
= nla_put(skb
, msg
->type
, msg
->sz
, msg
->payload
);
432 genlmsg_cancel(skb
, nlh
);
436 genlmsg_end(skb
, nlh
);
437 ret
= genlmsg_unicast(&init_net
, skb
, ksmbd_tools_pid
);
439 ipc_update_last_active();
447 static void *ipc_msg_send_request(struct ksmbd_ipc_msg
*msg
, unsigned int handle
)
449 struct ipc_msg_table_entry entry
;
455 entry
.type
= msg
->type
;
456 entry
.response
= NULL
;
457 init_waitqueue_head(&entry
.wait
);
459 down_write(&ipc_msg_table_lock
);
460 entry
.handle
= handle
;
461 hash_add(ipc_msg_table
, &entry
.ipc_table_hlist
, entry
.handle
);
462 up_write(&ipc_msg_table_lock
);
464 ret
= ipc_msg_send(msg
);
468 ret
= wait_event_interruptible_timeout(entry
.wait
,
469 entry
.response
!= NULL
,
472 down_write(&ipc_msg_table_lock
);
473 hash_del(&entry
.ipc_table_hlist
);
474 up_write(&ipc_msg_table_lock
);
475 return entry
.response
;
478 static int ksmbd_ipc_heartbeat_request(void)
480 struct ksmbd_ipc_msg
*msg
;
483 msg
= ipc_msg_alloc(sizeof(struct ksmbd_heartbeat
));
487 msg
->type
= KSMBD_EVENT_HEARTBEAT_REQUEST
;
488 ret
= ipc_msg_send(msg
);
493 struct ksmbd_login_response
*ksmbd_ipc_login_request(const char *account
)
495 struct ksmbd_ipc_msg
*msg
;
496 struct ksmbd_login_request
*req
;
497 struct ksmbd_login_response
*resp
;
499 if (strlen(account
) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
)
502 msg
= ipc_msg_alloc(sizeof(struct ksmbd_login_request
));
506 msg
->type
= KSMBD_EVENT_LOGIN_REQUEST
;
507 req
= (struct ksmbd_login_request
*)msg
->payload
;
508 req
->handle
= ksmbd_acquire_id(&ipc_ida
);
509 strscpy(req
->account
, account
, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
);
511 resp
= ipc_msg_send_request(msg
, req
->handle
);
512 ipc_msg_handle_free(req
->handle
);
517 struct ksmbd_spnego_authen_response
*
518 ksmbd_ipc_spnego_authen_request(const char *spnego_blob
, int blob_len
)
520 struct ksmbd_ipc_msg
*msg
;
521 struct ksmbd_spnego_authen_request
*req
;
522 struct ksmbd_spnego_authen_response
*resp
;
524 msg
= ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request
) +
529 msg
->type
= KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST
;
530 req
= (struct ksmbd_spnego_authen_request
*)msg
->payload
;
531 req
->handle
= ksmbd_acquire_id(&ipc_ida
);
532 req
->spnego_blob_len
= blob_len
;
533 memcpy(req
->spnego_blob
, spnego_blob
, blob_len
);
535 resp
= ipc_msg_send_request(msg
, req
->handle
);
536 ipc_msg_handle_free(req
->handle
);
541 struct ksmbd_tree_connect_response
*
542 ksmbd_ipc_tree_connect_request(struct ksmbd_session
*sess
,
543 struct ksmbd_share_config
*share
,
544 struct ksmbd_tree_connect
*tree_conn
,
545 struct sockaddr
*peer_addr
)
547 struct ksmbd_ipc_msg
*msg
;
548 struct ksmbd_tree_connect_request
*req
;
549 struct ksmbd_tree_connect_response
*resp
;
551 if (strlen(user_name(sess
->user
)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
)
554 if (strlen(share
->name
) >= KSMBD_REQ_MAX_SHARE_NAME
)
557 msg
= ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request
));
561 msg
->type
= KSMBD_EVENT_TREE_CONNECT_REQUEST
;
562 req
= (struct ksmbd_tree_connect_request
*)msg
->payload
;
564 req
->handle
= ksmbd_acquire_id(&ipc_ida
);
565 req
->account_flags
= sess
->user
->flags
;
566 req
->session_id
= sess
->id
;
567 req
->connect_id
= tree_conn
->id
;
568 strscpy(req
->account
, user_name(sess
->user
), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
);
569 strscpy(req
->share
, share
->name
, KSMBD_REQ_MAX_SHARE_NAME
);
570 snprintf(req
->peer_addr
, sizeof(req
->peer_addr
), "%pIS", peer_addr
);
572 if (peer_addr
->sa_family
== AF_INET6
)
573 req
->flags
|= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6
;
574 if (test_session_flag(sess
, CIFDS_SESSION_FLAG_SMB2
))
575 req
->flags
|= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2
;
577 resp
= ipc_msg_send_request(msg
, req
->handle
);
578 ipc_msg_handle_free(req
->handle
);
583 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id
,
584 unsigned long long connect_id
)
586 struct ksmbd_ipc_msg
*msg
;
587 struct ksmbd_tree_disconnect_request
*req
;
590 msg
= ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request
));
594 msg
->type
= KSMBD_EVENT_TREE_DISCONNECT_REQUEST
;
595 req
= (struct ksmbd_tree_disconnect_request
*)msg
->payload
;
596 req
->session_id
= session_id
;
597 req
->connect_id
= connect_id
;
599 ret
= ipc_msg_send(msg
);
604 int ksmbd_ipc_logout_request(const char *account
, int flags
)
606 struct ksmbd_ipc_msg
*msg
;
607 struct ksmbd_logout_request
*req
;
610 if (strlen(account
) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
)
613 msg
= ipc_msg_alloc(sizeof(struct ksmbd_logout_request
));
617 msg
->type
= KSMBD_EVENT_LOGOUT_REQUEST
;
618 req
= (struct ksmbd_logout_request
*)msg
->payload
;
619 req
->account_flags
= flags
;
620 strscpy(req
->account
, account
, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ
);
622 ret
= ipc_msg_send(msg
);
627 struct ksmbd_share_config_response
*
628 ksmbd_ipc_share_config_request(const char *name
)
630 struct ksmbd_ipc_msg
*msg
;
631 struct ksmbd_share_config_request
*req
;
632 struct ksmbd_share_config_response
*resp
;
634 if (strlen(name
) >= KSMBD_REQ_MAX_SHARE_NAME
)
637 msg
= ipc_msg_alloc(sizeof(struct ksmbd_share_config_request
));
641 msg
->type
= KSMBD_EVENT_SHARE_CONFIG_REQUEST
;
642 req
= (struct ksmbd_share_config_request
*)msg
->payload
;
643 req
->handle
= ksmbd_acquire_id(&ipc_ida
);
644 strscpy(req
->share_name
, name
, KSMBD_REQ_MAX_SHARE_NAME
);
646 resp
= ipc_msg_send_request(msg
, req
->handle
);
647 ipc_msg_handle_free(req
->handle
);
652 struct ksmbd_rpc_command
*ksmbd_rpc_open(struct ksmbd_session
*sess
, int handle
)
654 struct ksmbd_ipc_msg
*msg
;
655 struct ksmbd_rpc_command
*req
;
656 struct ksmbd_rpc_command
*resp
;
658 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
));
662 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
663 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
664 req
->handle
= handle
;
665 req
->flags
= ksmbd_session_rpc_method(sess
, handle
);
666 req
->flags
|= KSMBD_RPC_OPEN_METHOD
;
669 resp
= ipc_msg_send_request(msg
, req
->handle
);
674 struct ksmbd_rpc_command
*ksmbd_rpc_close(struct ksmbd_session
*sess
, int handle
)
676 struct ksmbd_ipc_msg
*msg
;
677 struct ksmbd_rpc_command
*req
;
678 struct ksmbd_rpc_command
*resp
;
680 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
));
684 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
685 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
686 req
->handle
= handle
;
687 req
->flags
= ksmbd_session_rpc_method(sess
, handle
);
688 req
->flags
|= KSMBD_RPC_CLOSE_METHOD
;
691 resp
= ipc_msg_send_request(msg
, req
->handle
);
696 struct ksmbd_rpc_command
*ksmbd_rpc_write(struct ksmbd_session
*sess
, int handle
,
697 void *payload
, size_t payload_sz
)
699 struct ksmbd_ipc_msg
*msg
;
700 struct ksmbd_rpc_command
*req
;
701 struct ksmbd_rpc_command
*resp
;
703 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
) + payload_sz
+ 1);
707 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
708 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
709 req
->handle
= handle
;
710 req
->flags
= ksmbd_session_rpc_method(sess
, handle
);
711 req
->flags
|= rpc_context_flags(sess
);
712 req
->flags
|= KSMBD_RPC_WRITE_METHOD
;
713 req
->payload_sz
= payload_sz
;
714 memcpy(req
->payload
, payload
, payload_sz
);
716 resp
= ipc_msg_send_request(msg
, req
->handle
);
721 struct ksmbd_rpc_command
*ksmbd_rpc_read(struct ksmbd_session
*sess
, int handle
)
723 struct ksmbd_ipc_msg
*msg
;
724 struct ksmbd_rpc_command
*req
;
725 struct ksmbd_rpc_command
*resp
;
727 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
));
731 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
732 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
733 req
->handle
= handle
;
734 req
->flags
= ksmbd_session_rpc_method(sess
, handle
);
735 req
->flags
|= rpc_context_flags(sess
);
736 req
->flags
|= KSMBD_RPC_READ_METHOD
;
739 resp
= ipc_msg_send_request(msg
, req
->handle
);
744 struct ksmbd_rpc_command
*ksmbd_rpc_ioctl(struct ksmbd_session
*sess
, int handle
,
745 void *payload
, size_t payload_sz
)
747 struct ksmbd_ipc_msg
*msg
;
748 struct ksmbd_rpc_command
*req
;
749 struct ksmbd_rpc_command
*resp
;
751 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
) + payload_sz
+ 1);
755 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
756 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
757 req
->handle
= handle
;
758 req
->flags
= ksmbd_session_rpc_method(sess
, handle
);
759 req
->flags
|= rpc_context_flags(sess
);
760 req
->flags
|= KSMBD_RPC_IOCTL_METHOD
;
761 req
->payload_sz
= payload_sz
;
762 memcpy(req
->payload
, payload
, payload_sz
);
764 resp
= ipc_msg_send_request(msg
, req
->handle
);
769 struct ksmbd_rpc_command
*ksmbd_rpc_rap(struct ksmbd_session
*sess
, void *payload
,
772 struct ksmbd_ipc_msg
*msg
;
773 struct ksmbd_rpc_command
*req
;
774 struct ksmbd_rpc_command
*resp
;
776 msg
= ipc_msg_alloc(sizeof(struct ksmbd_rpc_command
) + payload_sz
+ 1);
780 msg
->type
= KSMBD_EVENT_RPC_REQUEST
;
781 req
= (struct ksmbd_rpc_command
*)msg
->payload
;
782 req
->handle
= ksmbd_acquire_id(&ipc_ida
);
783 req
->flags
= rpc_context_flags(sess
);
784 req
->flags
|= KSMBD_RPC_RAP_METHOD
;
785 req
->payload_sz
= payload_sz
;
786 memcpy(req
->payload
, payload
, payload_sz
);
788 resp
= ipc_msg_send_request(msg
, req
->handle
);
789 ipc_msg_handle_free(req
->handle
);
794 static int __ipc_heartbeat(void)
798 if (!ksmbd_server_running())
801 if (time_after(jiffies
, server_conf
.ipc_last_active
)) {
802 delta
= (jiffies
- server_conf
.ipc_last_active
);
804 ipc_update_last_active();
805 schedule_delayed_work(&ipc_timer_work
,
806 server_conf
.ipc_timeout
);
810 if (delta
< server_conf
.ipc_timeout
) {
811 schedule_delayed_work(&ipc_timer_work
,
812 server_conf
.ipc_timeout
- delta
);
816 if (ksmbd_ipc_heartbeat_request() == 0) {
817 schedule_delayed_work(&ipc_timer_work
,
818 server_conf
.ipc_timeout
);
822 mutex_lock(&startup_lock
);
823 WRITE_ONCE(server_conf
.state
, SERVER_STATE_RESETTING
);
824 server_conf
.ipc_last_active
= 0;
826 pr_err("No IPC daemon response for %lus\n", delta
/ HZ
);
827 mutex_unlock(&startup_lock
);
831 static void ipc_timer_heartbeat(struct work_struct
*w
)
833 if (__ipc_heartbeat())
834 server_queue_ctrl_reset_work();
837 int ksmbd_ipc_id_alloc(void)
839 return ksmbd_acquire_id(&ipc_ida
);
842 void ksmbd_rpc_id_free(int handle
)
844 ksmbd_release_id(&ipc_ida
, handle
);
847 void ksmbd_ipc_release(void)
849 cancel_delayed_work_sync(&ipc_timer_work
);
850 genl_unregister_family(&ksmbd_genl_family
);
853 void ksmbd_ipc_soft_reset(void)
855 mutex_lock(&startup_lock
);
857 cancel_delayed_work_sync(&ipc_timer_work
);
858 mutex_unlock(&startup_lock
);
861 int ksmbd_ipc_init(void)
865 ksmbd_nl_init_fixup();
866 INIT_DELAYED_WORK(&ipc_timer_work
, ipc_timer_heartbeat
);
868 ret
= genl_register_family(&ksmbd_genl_family
);
870 pr_err("Failed to register KSMBD netlink interface %d\n", ret
);
871 cancel_delayed_work_sync(&ipc_timer_work
);