1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 #include <sys/sdt.h>
17
18 #include <krrp_params.h>
19
20 #include "krrp_svc.h"
21 #include "krrp_session.h"
22 #include "krrp_ioctl.h"
23
24 static boolean_t krrp_is_input_data_required(krrp_ioctl_cmd_t cmd);
25
26 static int krrp_ioctl_sess_set_private_data(nvlist_t *params,
27 krrp_error_t *error);
28 static int krrp_ioctl_sess_get_private_data(nvlist_t *params,
29 nvlist_t *result, krrp_error_t *error);
30
31 static int krrp_ioctl_sess_status(nvlist_t *params, nvlist_t *result,
32 krrp_error_t *error);
33 static int krrp_ioctl_sess_create(nvlist_t *params, krrp_error_t *error);
34 static int krrp_ioctl_sess_destroy(nvlist_t *params, krrp_error_t *error);
35 static int krrp_ioctl_sess_run(nvlist_t *params, krrp_error_t *error);
36 static int krrp_ioctl_sess_send_stop(nvlist_t *params, krrp_error_t *error);
37 static int krrp_ioctl_sess_create_conn(nvlist_t *params, krrp_error_t *error);
38 static int krrp_ioctl_sess_create_pdu_engine(nvlist_t *params,
39 krrp_error_t *error);
40
41 static int krrp_ioctl_sess_create_stream(nvlist_t *params,
42 boolean_t read_stream, krrp_error_t *error);
43 static int krrp_ioctl_sess_create_fake_stream(krrp_stream_t **result_stream,
44 boolean_t sender, nvlist_t *params, krrp_error_t *error);
45 static int krrp_ioctl_sess_create_read_stream(krrp_stream_t **result_stream,
46 nvlist_t *params, krrp_error_t *error);
47 static int krrp_ioctl_sess_create_write_stream(krrp_stream_t **result_stream,
48 nvlist_t *params, krrp_error_t *error);
49
50 static int krrp_ioctl_sess_conn_throttle(nvlist_t *params, krrp_error_t *error);
51 static int krrp_ioctl_sess_conn_get_info(nvlist_t *params, nvlist_t *result,
52 krrp_error_t *error);
53
54 static krrp_sess_t *krrp_ioctl_sess_action_common(nvlist_t *params,
55 krrp_error_t *error);
56
57 static krrp_stream_read_flag_t krrp_fill_read_stream_flags(nvlist_t *params);
58 static krrp_stream_write_flag_t krrp_fill_write_stream_flags(nvlist_t *params);
59
60 int
61 krrp_ioctl_validate_cmd(krrp_ioctl_cmd_t cmd)
62 {
63 if (cmd <= KRRP_IOCTL_FIRST || cmd >= KRRP_IOCTL_LAST)
64 return (-1);
65
66 return (0);
67 }
68
69 int krrp_ioctl_process(krrp_ioctl_cmd_t cmd, nvlist_t *input,
70 nvlist_t *output, krrp_error_t *error)
71 {
72 int rc = 0;
73
74 if (input == NULL && krrp_is_input_data_required(cmd)) {
75 krrp_error_set(error, KRRP_ERRNO_INVAL, ENODATA);
76 rc = -1;
77 goto out;
78 }
79
80 switch (cmd) {
81 case KRRP_IOCTL_SVC_ENABLE:
82 rc = krrp_svc_enable(error);
83 break;
84 case KRRP_IOCTL_SVC_DISABLE:
85 rc = krrp_svc_disable(error);
86 break;
87 case KRRP_IOCTL_SVC_STATE:
88 krrp_svc_state(output);
89 break;
90 case KRRP_IOCTL_SVC_SET_CONFIG:
91 rc = krrp_svc_config(input, NULL, error);
92 break;
93 case KRRP_IOCTL_SVC_GET_CONFIG:
94 rc = krrp_svc_config(input, output, error);
95 break;
96 case KRRP_IOCTL_SESS_SET_PRIVATE_DATA:
97 rc = krrp_ioctl_sess_set_private_data(input, error);
98 break;
99 case KRRP_IOCTL_SESS_GET_PRIVATE_DATA:
100 rc = krrp_ioctl_sess_get_private_data(input, output, error);
101 break;
102 case KRRP_IOCTL_SESS_LIST:
103 krrp_svc_list_sessions(output);
104 break;
105 case KRRP_IOCTL_SESS_STATUS:
106 rc = krrp_ioctl_sess_status(input, output, error);
107 break;
108 case KRRP_IOCTL_SESS_CREATE:
109 rc = krrp_ioctl_sess_create(input, error);
110 break;
111 case KRRP_IOCTL_SESS_DESTROY:
112 rc = krrp_ioctl_sess_destroy(input, error);
113 break;
114 case KRRP_IOCTL_SESS_RUN:
115 rc = krrp_ioctl_sess_run(input, error);
116 break;
117 case KRRP_IOCTL_SESS_SEND_STOP:
118 rc = krrp_ioctl_sess_send_stop(input, error);
119 break;
120 case KRRP_IOCTL_SESS_CREATE_CONN:
121 rc = krrp_ioctl_sess_create_conn(input, error);
122 break;
123 case KRRP_IOCTL_SESS_CREATE_PDU_ENGINE:
124 rc = krrp_ioctl_sess_create_pdu_engine(input, error);
125 break;
126 case KRRP_IOCTL_SESS_CREATE_READ_STREAM:
127 rc = krrp_ioctl_sess_create_stream(input, B_TRUE, error);
128 break;
129 case KRRP_IOCTL_SESS_CREATE_WRITE_STREAM:
130 rc = krrp_ioctl_sess_create_stream(input, B_FALSE, error);
131 break;
132 case KRRP_IOCTL_SESS_CONN_THROTTLE:
133 rc = krrp_ioctl_sess_conn_throttle(input, error);
134 break;
135 case KRRP_IOCTL_SESS_GET_CONN_INFO:
136 rc = krrp_ioctl_sess_conn_get_info(input, output, error);
137 break;
138 default:
139 cmn_err(CE_WARN, "Unknown ioctl cmd [%d]", cmd);
140 krrp_error_set(error, KRRP_ERRNO_INVAL, ENOTSUP);
141 rc = -1;
142 #ifdef DEBUG
143 panic("Unknown ioctl cmd");
144 #endif
145 }
146
147 out:
148 return (rc);
149 }
150
151 static boolean_t
152 krrp_is_input_data_required(krrp_ioctl_cmd_t cmd)
153 {
154 boolean_t result;
155
156 /*
157 * If an ioctl requires input data do not forget
158 * to add it to this switch
159 */
160 switch (cmd) {
161 case KRRP_IOCTL_SVC_SET_CONFIG:
162 case KRRP_IOCTL_SVC_GET_CONFIG:
163 case KRRP_IOCTL_SESS_SET_PRIVATE_DATA:
164 case KRRP_IOCTL_SESS_GET_PRIVATE_DATA:
165 case KRRP_IOCTL_SESS_STATUS:
166 case KRRP_IOCTL_SESS_CREATE:
167 case KRRP_IOCTL_SESS_DESTROY:
168 case KRRP_IOCTL_SESS_RUN:
169 case KRRP_IOCTL_SESS_SEND_STOP:
170 case KRRP_IOCTL_SESS_CREATE_CONN:
171 case KRRP_IOCTL_SESS_CREATE_PDU_ENGINE:
172 case KRRP_IOCTL_SESS_CREATE_READ_STREAM:
173 case KRRP_IOCTL_SESS_CREATE_WRITE_STREAM:
174 result = B_TRUE;
175 break;
176 default:
177 result = B_FALSE;
178 }
179
180 return (result);
181 }
182
183 static int
184 krrp_ioctl_sess_set_private_data(nvlist_t *params,
185 krrp_error_t *error)
186 {
187 krrp_sess_t *sess = NULL;
188 int rc;
189 nvlist_t *private_data = NULL;
190
191 sess = krrp_ioctl_sess_action_common(params, error);
192 if (sess == NULL)
193 return (-1);
194
195 rc = krrp_param_get(KRRP_PARAM_SESS_PRIVATE_DATA,
196 params, &private_data);
197 if (rc != 0) {
198 krrp_error_set(error, KRRP_ERRNO_SESS, ENODATA);
199 goto out;
200 }
201
202 if (sess->private_data != NULL)
203 fnvlist_free(sess->private_data);
204
205 sess->private_data = fnvlist_dup(private_data);
206
207 out:
208 krrp_sess_rele(sess);
209 return (rc);
210 }
211
212 static int
213 krrp_ioctl_sess_get_private_data(nvlist_t *params, nvlist_t *result,
214 krrp_error_t *error)
215 {
216 krrp_sess_t *sess = NULL;
217 int rc = -1;
218
219 sess = krrp_ioctl_sess_action_common(params, error);
220 if (sess == NULL)
221 return (-1);
222
223 if (sess->private_data == NULL) {
224 krrp_error_set(error, KRRP_ERRNO_SESS, ENODATA);
225 goto out;
226 }
227
228 (void) krrp_param_put(KRRP_PARAM_SESS_PRIVATE_DATA,
229 result, sess->private_data);
230 rc = 0;
231
232 out:
233 krrp_sess_rele(sess);
234 return (rc);
235 }
236
237 static int
238 krrp_ioctl_sess_status(nvlist_t *params, nvlist_t *result,
239 krrp_error_t *error)
240 {
241 krrp_sess_t *sess = NULL;
242
243 sess = krrp_ioctl_sess_action_common(params, error);
244 if (sess == NULL)
245 return (-1);
246
247 krrp_sess_get_status(sess, result);
248
249 krrp_sess_rele(sess);
250 return (0);
251 }
252
253 static int
254 krrp_ioctl_sess_create(nvlist_t *params, krrp_error_t *error)
255 {
256 int rc;
257 const char *sess_id = NULL, *sess_kstat_id = NULL,
258 *auth_digest = NULL;
259 krrp_sess_t *sess = NULL;
260 boolean_t sender = B_FALSE;
261 boolean_t fake_mode = B_FALSE;
262 boolean_t compound = B_FALSE;
263
264 rc = krrp_param_get(KRRP_PARAM_SESS_ID, params,
265 (void *) &sess_id);
266 if (rc != 0) {
267 krrp_error_set(error, KRRP_ERRNO_SESSID, ENOENT);
268 return (-1);
269 }
270
271 rc = krrp_param_get(KRRP_PARAM_SESS_KSTAT_ID, params,
272 (void *) &sess_kstat_id);
273 if (rc != 0) {
274 krrp_error_set(error, KRRP_ERRNO_KSTATID, ENOENT);
275 return (-1);
276 }
277
278 (void) krrp_param_get(KRRP_PARAM_AUTH_DATA,
279 params, (void *)&auth_digest);
280 (void) krrp_param_get(KRRP_PARAM_FAKE_MODE,
281 params, (void *)&fake_mode);
282 (void) krrp_param_get(KRRP_PARAM_SESS_SENDER,
283 params, (void *)&sender);
284 (void) krrp_param_get(KRRP_PARAM_SESS_COMPOUND,
285 params, (void *)&compound);
286
287 if (krrp_sess_create(&sess, sess_id, sess_kstat_id,
288 auth_digest, sender, fake_mode, compound, error) != 0)
289 return (-1);
290
291 if (krrp_svc_register_session(sess, error) != 0) {
292 krrp_sess_destroy(sess);
293 return (-1);
294 }
295
296 return (0);
297 }
298
299 static int
300 krrp_ioctl_sess_destroy(nvlist_t *params, krrp_error_t *error)
301 {
302 krrp_sess_t *sess = NULL;
303
304 sess = krrp_ioctl_sess_action_common(params, error);
305 if (sess == NULL)
306 return (-1);
307
308 if (krrp_svc_unregister_session(sess, error) != 0)
309 return (-1);
310
311 krrp_sess_destroy(sess);
312
313 return (0);
314 }
315
316 static int
317 krrp_ioctl_sess_create_conn(nvlist_t *params, krrp_error_t *error)
318 {
319 int rc, remote_port = 0, timeout = 10;
320 const char *remote_addr = NULL;
321 krrp_sess_t *sess = NULL;
322 krrp_conn_t *conn = NULL;
323
324 sess = krrp_ioctl_sess_action_common(params, error);
325 if (sess == NULL)
326 return (-1);
327
328 rc = krrp_param_get(KRRP_PARAM_CONN_TIMEOUT,
329 params, (void *) &timeout);
330 if (rc == 0 && (timeout < KRRP_MIN_CONN_TIMEOUT ||
331 timeout > KRRP_MAX_CONN_TIMEOUT)) {
332 rc = -1;
333 krrp_error_set(error, KRRP_ERRNO_CONNTIMEOUT, EINVAL);
334 goto out;
335 }
336
337 rc = krrp_param_get(KRRP_PARAM_REMOTE_HOST,
338 params, (void *) &remote_addr);
339 if (rc != 0) {
340 krrp_error_set(error, KRRP_ERRNO_ADDR, ENOENT);
341 goto out;
342 }
343
344 /* Remote address will be valiated by inet_pton() */
345
346 rc = krrp_param_get(KRRP_PARAM_PORT,
347 params, (void *) &remote_port);
348 if (rc != 0) {
349 krrp_error_set(error, KRRP_ERRNO_PORT, ENOENT);
350 goto out;
351 }
352
353 if (remote_port < KRRP_MIN_PORT || remote_port > KRRP_MAX_PORT) {
354 rc = -1;
355 krrp_error_set(error, KRRP_ERRNO_PORT, EINVAL);
356 goto out;
357 }
358
359 rc = krrp_conn_create_from_scratch(&conn,
360 remote_addr, remote_port, timeout, error);
361 if (rc != 0)
362 goto out;
363
364 rc = krrp_sess_initiator_attach_conn(sess, conn, error);
365 if (rc != 0)
366 krrp_conn_destroy(conn);
367
368 out:
369 krrp_sess_rele(sess);
370 return (rc);
371 }
372
373 static int
374 krrp_ioctl_sess_create_pdu_engine(nvlist_t *params, krrp_error_t *error)
375 {
376 int rc = -1;
377 krrp_sess_t *sess = NULL;
378 krrp_pdu_engine_t *pdu_engine = NULL;
379 boolean_t use_prealloc = B_FALSE;
380 size_t dblk_data_sz = 0, dblk_head_sz = 0, max_memory = 0;
381
382 sess = krrp_ioctl_sess_action_common(params, error);
383 if (sess == NULL)
384 return (-1);
385
386 /*
387 * dblk at sender side (since the sender uses ksocket_sendmblk)
388 * must have some space before data space, because the space is used
389 * by TCP/IP stack. The size of the space is equal to mblk_wroff,
390 * that is extracted from sonode_t.
391 * So to create pdu_engine in this case we need to be sure that
392 * a connection already established.
393 */
394 if (sess->type == KRRP_SESS_SENDER) {
395 if (sess->conn == NULL) {
396 krrp_error_set(error, KRRP_ERRNO_CONN, ENOENT);
397 goto out;
398 }
399
400 dblk_head_sz = sess->conn->mblk_wroff;
401 }
402
403 rc = krrp_param_get(KRRP_PARAM_DBLK_DATA_SIZE, params,
404 (void *) &dblk_data_sz);
405 if (rc != 0) {
406 krrp_error_set(error, KRRP_ERRNO_DBLKSZ, ENOENT);
407 goto out;
408 }
409
410 /*
411 * kmem-allocator works very slowly for mem-blocks >128 KB,
412 * so the upper limit is 128 KB
413 *
414 * the lower limit is just an optimal value
415 */
416 if (dblk_data_sz < KRRP_MIN_SESS_PDU_DBLK_DATA_SZ ||
417 dblk_data_sz > KRRP_MAX_SESS_PDU_DBLK_DATA_SZ) {
418 rc = -1;
419 krrp_error_set(error, KRRP_ERRNO_DBLKSZ, EINVAL);
420 goto out;
421 }
422
423 rc = krrp_param_get(KRRP_PARAM_MAX_MEMORY, params,
424 (void *) &max_memory);
425 if (rc != 0) {
426 krrp_error_set(error, KRRP_ERRNO_MAXMEMSZ, ENOENT);
427 goto out;
428 }
429
430 if (max_memory < KRRP_MIN_MAXMEM) {
431 rc = -1;
432 krrp_error_set(error, KRRP_ERRNO_MAXMEMSZ, EINVAL);
433 goto out;
434 }
435
436 (void) krrp_param_get(KRRP_PARAM_USE_PREALLOCATION, params,
437 (void *) &use_prealloc);
438
439 rc = krrp_pdu_engine_create(&pdu_engine, B_FALSE,
440 use_prealloc, max_memory, 0, dblk_head_sz,
441 dblk_data_sz, error);
442 if (rc != 0)
443 goto out;
444
445 rc = krrp_sess_attach_pdu_engine(sess, pdu_engine, error);
446 if (rc != 0)
447 krrp_pdu_engine_destroy(pdu_engine);
448
449 out:
450 krrp_sess_rele(sess);
451 return (rc);
452 }
453
454 static int
455 krrp_ioctl_sess_create_stream(nvlist_t *params, boolean_t read_stream,
456 krrp_error_t *error)
457 {
458 int rc = -1;
459 krrp_sess_t *sess = NULL;
460 krrp_stream_t *stream = NULL;
461
462 sess = krrp_ioctl_sess_action_common(params, error);
463 if (sess == NULL)
464 return (-1);
465
466 switch (sess->type) {
467 case KRRP_SESS_SENDER:
468 if (!read_stream) {
469 krrp_error_set(error, KRRP_ERRNO_SESS, EINVAL);
470 goto out;
471 }
472
473 if (sess->fake_mode)
474 rc = krrp_ioctl_sess_create_fake_stream(&stream,
475 B_TRUE, params, error);
476 else
477 rc = krrp_ioctl_sess_create_read_stream(&stream,
478 params, error);
479
480 break;
481 case KRRP_SESS_RECEIVER:
482 if (read_stream) {
483 krrp_error_set(error, KRRP_ERRNO_SESS, EINVAL);
484 goto out;
485 }
486
487 if (sess->fake_mode)
488 rc = krrp_ioctl_sess_create_fake_stream(&stream,
489 B_FALSE, params, error);
490 else
491 rc = krrp_ioctl_sess_create_write_stream(&stream,
492 params, error);
493
494 break;
495 case KRRP_SESS_COMPOUND:
496 if (sess->fake_mode && read_stream) {
497 krrp_error_set(error, KRRP_ERRNO_SESS, EINVAL);
498 goto out;
499 }
500
501 if (read_stream)
502 rc = krrp_ioctl_sess_create_read_stream(&stream,
503 params, error);
504 else if (sess->fake_mode)
505 rc = krrp_ioctl_sess_create_fake_stream(&stream,
506 B_FALSE, params, error);
507 else
508 rc = krrp_ioctl_sess_create_write_stream(&stream,
509 params, error);
510
511 break;
512 }
513
514 if (rc != 0)
515 goto out;
516
517 if (read_stream)
518 rc = krrp_sess_attach_read_stream(sess, stream, error);
519 else
520 rc = krrp_sess_attach_write_stream(sess, stream, error);
521
522 if (rc != 0)
523 krrp_stream_destroy(stream);
524
525 out:
526 krrp_sess_rele(sess);
527 return (rc);
528 }
529
530 static int
531 krrp_ioctl_sess_create_fake_stream(krrp_stream_t **result_stream,
532 boolean_t sender, nvlist_t *params, krrp_error_t *error)
533 {
534 if (sender) {
535 int rc;
536 uint64_t fake_data_ds = 0;
537
538 rc = krrp_param_get(KRRP_PARAM_FAKE_DATA_SIZE,
539 params, (void *) &fake_data_ds);
540 if (rc != 0) {
541 krrp_error_set(error, KRRP_ERRNO_FAKEDSZ, ENOENT);
542 return (-1);
543 }
544
545 return (krrp_stream_fake_read_create(result_stream,
546 fake_data_ds, error));
547 } else
548 return (krrp_stream_fake_write_create(result_stream, error));
549
550 }
551
552 static int
553 krrp_ioctl_sess_create_read_stream(krrp_stream_t **result_stream,
554 nvlist_t *params, krrp_error_t *error)
555 {
556 int rc;
557 const char *dataset = NULL, *base_snap_name = NULL,
558 *common_snap_name = NULL, *resume_token = NULL,
559 *skip_snaps_mask = NULL;
560 uint32_t keep_snaps;
561 krrp_stream_read_flag_t flags;
562
563 rc = krrp_param_get(KRRP_PARAM_SRC_DATASET,
564 params, (void *) &dataset);
565 if (rc != 0) {
566 krrp_error_set(error, KRRP_ERRNO_SRCDS, ENOENT);
567 return (-1);
568 }
569
570 (void) krrp_param_get(KRRP_PARAM_RESUME_TOKEN,
571 params, (void *) &resume_token);
572
573 (void) krrp_param_get(KRRP_PARAM_COMMON_SNAPSHOT,
574 params, (void *) &common_snap_name);
575 (void) krrp_param_get(KRRP_PARAM_SRC_SNAPSHOT,
576 params, (void *) &base_snap_name);
577
578 (void) krrp_param_get(KRRP_PARAM_SKIP_SNAPS_MASK,
579 params, (void *) &skip_snaps_mask);
580
581 rc = krrp_param_get(KRRP_PARAM_STREAM_KEEP_SNAPS,
582 params, (void *) &keep_snaps);
583 if (rc != 0) {
584 /* KRRP_PARAM_STREAM_KEEP_SNAPS not defined, so use the MIN */
585 keep_snaps = KRRP_MIN_KEEP_SNAPS;
586 } else if (keep_snaps < KRRP_MIN_KEEP_SNAPS ||
587 keep_snaps > KRRP_MAX_KEEP_SNAPS) {
588 krrp_error_set(error, KRRP_ERRNO_KEEPSNAPS, EINVAL);
589 return (-1);
590 }
591
592 flags = krrp_fill_read_stream_flags(params);
593
594 return (krrp_stream_read_create(result_stream, keep_snaps, dataset,
595 base_snap_name, common_snap_name, resume_token, flags,
596 skip_snaps_mask, error));
597 }
598
599 static int
600 krrp_ioctl_sess_create_write_stream(krrp_stream_t **result_stream,
601 nvlist_t *params, krrp_error_t *error)
602 {
603 int rc;
604 const char *dataset = NULL, *common_snap_name = NULL,
605 *resume_token = NULL;
606 nvlist_t *ignore_props_list = NULL, *replace_props_list = NULL;
607 uint32_t keep_snaps;
608 krrp_stream_write_flag_t flags;
609
610 rc = krrp_param_get(KRRP_PARAM_DST_DATASET,
611 params, (void *) &dataset);
612 if (rc != 0) {
613 krrp_error_set(error, KRRP_ERRNO_DSTDS, ENOENT);
614 return (-1);
615 }
616
617 (void) krrp_param_get(KRRP_PARAM_RESUME_TOKEN,
618 params, (void *) &resume_token);
619
620 (void) krrp_param_get(KRRP_PARAM_IGNORE_PROPS_LIST,
621 params, (void *) &ignore_props_list);
622 (void) krrp_param_get(KRRP_PARAM_REPLACE_PROPS_LIST,
623 params, (void *) &replace_props_list);
624
625 (void) krrp_param_get(KRRP_PARAM_COMMON_SNAPSHOT,
626 params, (void *) &common_snap_name);
627
628 rc = krrp_param_get(KRRP_PARAM_STREAM_KEEP_SNAPS,
629 params, (void *) &keep_snaps);
630 if (rc != 0) {
631 /* KRRP_PARAM_STREAM_KEEP_SNAPS not defined, so use the MIN */
632 keep_snaps = KRRP_MIN_KEEP_SNAPS;
633 } else if (keep_snaps < KRRP_MIN_KEEP_SNAPS ||
634 keep_snaps > KRRP_MAX_KEEP_SNAPS) {
635 krrp_error_set(error, KRRP_ERRNO_KEEPSNAPS, EINVAL);
636 return (-1);
637 }
638
639 flags = krrp_fill_write_stream_flags(params);
640
641 return (krrp_stream_write_create(result_stream, keep_snaps,
642 dataset, common_snap_name, resume_token, flags,
643 ignore_props_list, replace_props_list, error));
644 }
645
646 static int
647 krrp_ioctl_sess_run(nvlist_t *params, krrp_error_t *error)
648 {
649 krrp_sess_t *sess = NULL;
650 boolean_t only_once = B_FALSE;
651 int rc;
652
653 sess = krrp_ioctl_sess_action_common(params, error);
654 if (sess == NULL)
655 return (-1);
656
657 (void) krrp_param_get(KRRP_PARAM_ONLY_ONCE, params,
658 (void *) &only_once);
659
660 rc = krrp_sess_run(sess, only_once, error);
661
662 krrp_sess_rele(sess);
663 return (rc);
664 }
665
666 static int
667 krrp_ioctl_sess_send_stop(nvlist_t *params, krrp_error_t *error)
668 {
669 int rc;
670 krrp_sess_t *sess = NULL;
671
672 sess = krrp_ioctl_sess_action_common(params, error);
673 if (sess == NULL)
674 return (-1);
675
676 rc = krrp_sess_send_stop(sess, error);
677
678 krrp_sess_rele(sess);
679 return (rc);
680 }
681
682 static int
683 krrp_ioctl_sess_conn_throttle(nvlist_t *params, krrp_error_t *error)
684 {
685 int rc;
686 krrp_sess_t *sess = NULL;
687 size_t limit = 0;
688
689 sess = krrp_ioctl_sess_action_common(params, error);
690 if (sess == NULL)
691 return (-1);
692
693 rc = krrp_param_get(KRRP_PARAM_THROTTLE,
694 params, (void *) &limit);
695 if (rc != 0) {
696 krrp_error_set(error, KRRP_ERRNO_THROTTLE, ENOENT);
697 goto out;
698 }
699
700 if (limit < KRRP_MIN_CONN_THROTTLE && limit != 0) {
701 krrp_error_set(error, KRRP_ERRNO_THROTTLE, EINVAL);
702 rc = -1;
703 goto out;
704 }
705
706 rc = krrp_sess_throttle_conn(sess, limit, error);
707
708 out:
709 krrp_sess_rele(sess);
710 return (rc);
711 }
712
713 static int
714 krrp_ioctl_sess_conn_get_info(nvlist_t *params, nvlist_t *result,
715 krrp_error_t *error)
716 {
717 int rc;
718 krrp_sess_t *sess = NULL;
719
720 sess = krrp_ioctl_sess_action_common(params, error);
721 if (sess == NULL)
722 return (-1);
723
724 rc = krrp_sess_get_conn_info(sess, result, error);
725
726 krrp_sess_rele(sess);
727 return (rc);
728 }
729
730 static krrp_sess_t *
731 krrp_ioctl_sess_action_common(nvlist_t *params, krrp_error_t *error)
732 {
733 int rc;
734 krrp_sess_t *sess = NULL;
735 const char *sess_id = NULL;
736
737 rc = krrp_param_get(KRRP_PARAM_SESS_ID, params,
738 (void *) &sess_id);
739 if (rc != 0) {
740 krrp_error_set(error, KRRP_ERRNO_SESSID, ENOENT);
741 goto out;
742 }
743
744 sess = krrp_svc_lookup_session(sess_id);
745 if (sess == NULL) {
746 krrp_error_set(error, KRRP_ERRNO_SESS, ENOENT);
747 goto out;
748 }
749
750 if (krrp_sess_try_hold(sess) != 0) {
751 krrp_error_set(error, KRRP_ERRNO_SESS, EBUSY);
752 sess = NULL;
753 }
754
755 out:
756 return (sess);
757 }
758
759 static krrp_stream_read_flag_t
760 krrp_fill_read_stream_flags(nvlist_t *params)
761 {
762 boolean_t value = B_FALSE;
763 krrp_stream_read_flag_t flags = 0;
764
765 if (krrp_param_get(KRRP_PARAM_SEND_RECURSIVE,
766 params, (void *) &value) == 0 && value)
767 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_RECURSIVE);
768
769 if (krrp_param_get(KRRP_PARAM_SEND_PROPERTIES,
770 params, (void *) &value) == 0 && value)
771 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_SEND_PROPS);
772
773 if (krrp_param_get(KRRP_PARAM_INCLUDE_ALL_SNAPSHOTS,
774 params, (void *) &value) == 0 && value)
775 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_SEND_ALL_SNAPS);
776
777 if (krrp_param_get(KRRP_PARAM_ENABLE_STREAM_CHKSUM,
778 params, (void *) &value) == 0 && value)
779 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_ENABLE_CHKSUM);
780
781 if (krrp_param_get(KRRP_PARAM_STREAM_EMBEDDED_BLOCKS,
782 params, (void *) &value) == 0 && value)
783 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_EMBEDDED);
784
785 if (krrp_param_get(KRRP_PARAM_STREAM_COMPRESSED_BLOCKS,
786 params, (void *) &value) == 0 && value)
787 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_COMPRESSED);
788
789 if (krrp_param_get(KRRP_PARAM_STREAM_LARGE_BLOCKS,
790 params, (void *) &value) == 0 && value)
791 krrp_stream_set_read_flag(&flags, KRRP_STRMRF_LARGE_BLOCKS);
792
793 return (flags);
794 }
795
796 static krrp_stream_write_flag_t
797 krrp_fill_write_stream_flags(nvlist_t *params)
798 {
799 boolean_t value = B_FALSE;
800 krrp_stream_write_flag_t flags = 0;
801
802 if (krrp_param_get(KRRP_PARAM_FORCE_RECEIVE,
803 params, (void *) &value) == 0 && value)
804 krrp_stream_set_write_flag(&flags, KRRP_STRMWF_FORCE_RECV);
805
806 if (krrp_param_get(KRRP_PARAM_ENABLE_STREAM_CHKSUM,
807 params, (void *) &value) == 0 && value)
808 krrp_stream_set_write_flag(&flags, KRRP_STRMWF_ENABLE_CHKSUM);
809
810 if (krrp_param_get(KRRP_PARAM_STREAM_DISCARD_HEAD,
811 params, (void *) &value) == 0 && value)
812 krrp_stream_set_write_flag(&flags, KRRP_STRMWF_DISCARD_HEAD);
813
814 if (krrp_param_get(KRRP_PARAM_STREAM_LEAVE_TAIL,
815 params, (void *) &value) == 0 && value)
816 krrp_stream_set_write_flag(&flags, KRRP_STRMWF_LEAVE_TAIL);
817
818 return (flags);
819 }