4553 ndmp_config_get_ext_list failed
[illumos-gate.git] / usr / src / cmd / ndmpd / ndmp / ndmpd_config.c
blobd110dc0bcec591d68d037195ba9db78bf8733a90
1 /*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
5 /*
6 * BSD 3 Clause License
8 * Copyright (c) 2007, The Storage Networking Industry Association.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
21 * - Neither the name of The Storage Networking Industry Association (SNIA)
22 * nor the names of its contributors may be used to endorse or promote
23 * products derived from this software without specific prior written
24 * permission.
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40 /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
42 #include <dirent.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sys/stat.h>
48 #include <sys/mnttab.h>
49 #include <sys/mntent.h>
50 #include <sys/mntio.h>
51 #include <sys/statvfs.h>
52 #include <sys/utsname.h>
53 #include <sys/scsi/scsi.h>
54 #include <unistd.h>
55 #include <sys/systeminfo.h>
56 #include "ndmpd_common.h"
57 #include "ndmpd.h"
59 static void simple_get_attrs(ulong_t *attributes);
62 * Number of environment variable for the file system
63 * info in V3 net_fs_info.
65 #define V3_N_FS_ENVS 4
68 * Is the file system a valid one to be reported to the
69 * clients?
71 #define IS_VALID_FS(fs) (fs && ( \
72 strcasecmp(fs->mnt_fstype, MNTTYPE_UFS) == 0 || \
73 strcasecmp(fs->mnt_fstype, MNTTYPE_ZFS) == 0 || \
74 strcasecmp(fs->mnt_fstype, MNTTYPE_NFS) == 0 || \
75 strcasecmp(fs->mnt_fstype, MNTTYPE_NFS3) == 0 || \
76 strcasecmp(fs->mnt_fstype, MNTTYPE_NFS4) == 0))
78 #define MNTTYPE_LEN 10
80 extern struct fs_ops sfs2_ops;
81 extern struct fs_ops sfs2cpv_ops;
85 * ************************************************************************
86 * NDMP V2 HANDLERS
87 * ************************************************************************
91 * ndmpd_config_get_host_info_v2
93 * This handler handles the ndmp_config_get_host_info request.
94 * Host specific information is returned.
96 * Parameters:
97 * connection (input) - connection handle.
98 * body (input) - request message body.
100 * Returns:
101 * void
103 /*ARGSUSED*/
104 void
105 ndmpd_config_get_host_info_v2(ndmp_connection_t *connection, void *body)
107 ndmp_config_get_host_info_reply_v2 reply;
108 ndmp_auth_type auth_types[2];
109 char buf[HOSTNAMELEN + 1];
110 struct utsname uts;
111 char hostidstr[16];
112 ulong_t hostid;
114 (void) memset((void*)&reply, 0, sizeof (reply));
115 (void) memset(buf, 0, sizeof (buf));
116 (void) gethostname(buf, sizeof (buf));
118 reply.error = NDMP_NO_ERR;
119 reply.hostname = buf;
120 (void) uname(&uts);
121 reply.os_type = uts.sysname;
122 reply.os_vers = uts.release;
124 if (sysinfo(SI_HW_SERIAL, hostidstr, sizeof (hostidstr)) < 0) {
125 NDMP_LOG(LOG_DEBUG, "sysinfo error: %m.");
126 reply.error = NDMP_UNDEFINED_ERR;
130 * Convert the hostid to hex. The returned string must match
131 * the string returned by hostid(1).
133 hostid = strtoul(hostidstr, 0, 0);
134 (void) snprintf(hostidstr, sizeof (hostidstr), "%lx", hostid);
135 reply.hostid = hostidstr;
137 auth_types[0] = NDMP_AUTH_TEXT;
138 reply.auth_type.auth_type_len = 1;
139 reply.auth_type.auth_type_val = auth_types;
141 ndmp_send_reply(connection, (void *) &reply,
142 "sending ndmp_config_get_host_info reply");
147 * ndmpd_config_get_butype_attr_v2
149 * This handler handles the ndmp_config_get_butype_attr request.
150 * Information about the specified backup type is returned.
152 * Parameters:
153 * connection (input) - connection handle.
154 * body (input) - request message body.
156 * Returns:
157 * void
159 void
160 ndmpd_config_get_butype_attr_v2(ndmp_connection_t *connection, void *body)
162 ndmp_config_get_butype_attr_request *request;
163 ndmp_config_get_butype_attr_reply reply;
165 request = (ndmp_config_get_butype_attr_request *)body;
167 reply.error = NDMP_NO_ERR;
169 if (strcmp(request->name, "dump") == 0) {
170 (void) simple_get_attrs(&reply.attrs);
171 } else if (strcmp(request->name, "tar") == 0) {
172 reply.attrs = NDMP_NO_BACKUP_FILELIST;
173 } else {
174 NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", request->name);
175 NDMP_LOG(LOG_ERR,
176 "Supported backup types are 'dump' and 'tar' only.");
177 reply.error = NDMP_ILLEGAL_ARGS_ERR;
180 ndmp_send_reply(connection, (void *) &reply,
181 "sending ndmp_config_get_butype_attr reply");
186 * ndmpd_config_get_mover_type_v2
188 * This handler handles the ndmp_config_get_mover_type request.
189 * Information about the supported mover types is returned.
191 * Parameters:
192 * connection (input) - connection handle.
193 * body (input) - request message body.
195 * Returns:
196 * void
198 /*ARGSUSED*/
199 void
200 ndmpd_config_get_mover_type_v2(ndmp_connection_t *connection, void *body)
202 ndmp_config_get_mover_type_reply reply;
203 ndmp_addr_type types[2];
205 types[0] = NDMP_ADDR_LOCAL;
206 types[1] = NDMP_ADDR_TCP;
208 reply.error = NDMP_NO_ERR;
209 reply.methods.methods_len = 2;
210 reply.methods.methods_val = types;
212 ndmp_send_reply(connection, (void *) &reply,
213 "sending ndmp_config_get_mover_type reply");
219 * ndmpd_config_get_auth_attr_v2
221 * This handler handles the ndmp_config_get_auth_attr request.
222 * Authorization type specific information is returned.
224 * Parameters:
225 * connection (input) - connection handle.
226 * body (input) - request message body.
228 * Returns:
229 * void
231 void
232 ndmpd_config_get_auth_attr_v2(ndmp_connection_t *connection, void *body)
234 ndmp_config_get_auth_attr_request *request;
235 ndmp_config_get_auth_attr_reply reply;
236 ndmpd_session_t *session = ndmp_get_client_data(connection);
238 request = (ndmp_config_get_auth_attr_request *)body;
240 reply.error = NDMP_NO_ERR;
241 reply.server_attr.auth_type = request->auth_type;
243 switch (request->auth_type) {
244 case NDMP_AUTH_TEXT:
245 break;
246 case NDMP_AUTH_MD5:
247 /* Create a 64 byte random session challenge */
248 randomize(session->ns_challenge, MD5_CHALLENGE_SIZE);
249 (void) memcpy(reply.server_attr.ndmp_auth_attr_u.challenge,
250 session->ns_challenge, MD5_CHALLENGE_SIZE);
251 break;
252 case NDMP_AUTH_NONE:
253 /* FALL THROUGH */
254 default:
255 NDMP_LOG(LOG_ERR, "Invalid authentication type: %d.",
256 request->auth_type);
257 NDMP_LOG(LOG_ERR,
258 "Supported authentication types are md5 and cleartext.");
259 reply.error = NDMP_ILLEGAL_ARGS_ERR;
260 break;
263 ndmp_send_reply(connection, (void *) &reply,
264 "sending ndmp_config_get_auth_attr reply");
269 * ************************************************************************
270 * NDMP V3 HANDLERS
271 * ************************************************************************
275 * ndmpd_config_get_host_info_v3
277 * This handler handles the ndmp_config_get_host_info request.
278 * Host specific information is returned.
280 * Parameters:
281 * connection (input) - connection handle.
282 * body (input) - request message body.
284 * Returns:
285 * void
287 /*ARGSUSED*/
288 void
289 ndmpd_config_get_host_info_v3(ndmp_connection_t *connection, void *body)
291 ndmp_config_get_host_info_reply_v3 reply;
292 char buf[HOSTNAMELEN+1];
293 struct utsname uts;
294 char hostidstr[16];
295 ulong_t hostid;
297 (void) memset((void*)&reply, 0, sizeof (reply));
298 (void) memset(buf, 0, sizeof (buf));
299 (void) gethostname(buf, sizeof (buf));
302 reply.error = NDMP_NO_ERR;
303 reply.hostname = buf;
304 (void) uname(&uts);
305 reply.os_type = uts.sysname;
306 reply.os_vers = uts.release;
308 if (sysinfo(SI_HW_SERIAL, hostidstr, sizeof (hostidstr)) < 0) {
310 NDMP_LOG(LOG_DEBUG, "sysinfo error: %m.");
311 reply.error = NDMP_UNDEFINED_ERR;
315 * Convert the hostid to hex. The returned string must match
316 * the string returned by hostid(1).
318 hostid = strtoul(hostidstr, 0, 0);
319 (void) snprintf(hostidstr, sizeof (hostidstr), "%lx", hostid);
320 reply.hostid = hostidstr;
322 ndmp_send_reply(connection, (void *) &reply,
323 "sending ndmp_config_get_host_info reply");
328 * ndmpd_config_get_connection_type_v3
330 * This handler handles the ndmp_config_get_connection_type_request.
331 * A list of supported data connection types is returned.
333 * Parameters:
334 * connection (input) - connection handle.
335 * body (input) - request message body.
337 * Returns:
338 * void
340 /*ARGSUSED*/
341 void
342 ndmpd_config_get_connection_type_v3(ndmp_connection_t *connection,
343 void *body)
345 ndmp_config_get_connection_type_reply_v3 reply;
346 ndmp_addr_type addr_types[2];
348 (void) memset((void*)&reply, 0, sizeof (reply));
350 reply.error = NDMP_NO_ERR;
352 addr_types[0] = NDMP_ADDR_LOCAL;
353 addr_types[1] = NDMP_ADDR_TCP;
354 reply.addr_types.addr_types_len = 2;
355 reply.addr_types.addr_types_val = addr_types;
357 ndmp_send_reply(connection, (void *) &reply,
358 "sending config_get_connection_type_v3 reply");
364 * ndmpd_config_get_auth_attr_v3
366 * This handler handles the ndmp_config_get_auth_attr request.
367 * Authorization type specific information is returned.
369 * Parameters:
370 * connection (input) - connection handle.
371 * body (input) - request message body.
373 * Returns:
374 * void
376 void
377 ndmpd_config_get_auth_attr_v3(ndmp_connection_t *connection, void *body)
379 ndmp_config_get_auth_attr_request *request;
380 ndmp_config_get_auth_attr_reply reply;
381 ndmpd_session_t *session = ndmp_get_client_data(connection);
383 request = (ndmp_config_get_auth_attr_request *)body;
385 (void) memset((void*)&reply, 0, sizeof (reply));
386 reply.error = NDMP_NO_ERR;
387 reply.server_attr.auth_type = request->auth_type;
389 switch (request->auth_type) {
390 case NDMP_AUTH_TEXT:
391 break;
392 case NDMP_AUTH_MD5:
393 /* Create a 64 bytes random session challenge */
394 randomize(session->ns_challenge, MD5_CHALLENGE_SIZE);
395 (void) memcpy(reply.server_attr.ndmp_auth_attr_u.challenge,
396 session->ns_challenge, MD5_CHALLENGE_SIZE);
397 break;
398 case NDMP_AUTH_NONE:
399 /* FALL THROUGH */
400 default:
401 NDMP_LOG(LOG_ERR, "Invalid authentication type: %d.",
402 request->auth_type);
403 NDMP_LOG(LOG_ERR,
404 "Supported authentication types are md5 and cleartext.");
405 reply.error = NDMP_ILLEGAL_ARGS_ERR;
406 break;
409 ndmp_send_reply(connection, (void *) &reply,
410 "sending ndmp_config_get_auth_attr_v3 reply");
415 * ndmpd_config_get_butype_info_v3
417 * This handler handles the ndmp_config_get_butype_info_request.
418 * Information about all supported backup types are returned.
420 * Parameters:
421 * connection (input) - connection handle.
422 * body (input) - request message body.
424 * Returns:
425 * void
427 /*ARGSUSED*/
428 void
429 ndmpd_config_get_butype_info_v3(ndmp_connection_t *connection, void *body)
431 ndmp_config_get_butype_info_reply_v3 reply;
432 ndmp_butype_info info[3];
433 ndmp_pval envs[8];
434 ulong_t attrs;
435 ndmp_pval *envp = envs;
437 ndmp_pval zfs_envs[9];
438 ulong_t zfs_attrs;
439 ndmp_pval *zfs_envp = zfs_envs;
441 (void) memset((void*)&reply, 0, sizeof (reply));
444 * Supported environment variables and their default values
445 * for dump and tar.
447 * The environment variables for dump and tar format are the
448 * same, because we use the same backup engine for both.
450 NDMP_SETENV(envp, "PREFIX", "");
451 NDMP_SETENV(envp, "TYPE", "");
452 NDMP_SETENV(envp, "DIRECT", "n");
453 NDMP_SETENV(envp, "HIST", "n");
454 NDMP_SETENV(envp, "FILESYSTEM", "");
455 NDMP_SETENV(envp, "LEVEL", "0");
456 NDMP_SETENV(envp, "UPDATE", "TRUE");
457 NDMP_SETENV(envp, "BASE_DATE", "");
459 attrs = NDMP_BUTYPE_BACKUP_FILE_HISTORY |
460 NDMP_BUTYPE_RECOVER_FILELIST |
461 NDMP_BUTYPE_BACKUP_DIRECT |
462 NDMP_BUTYPE_BACKUP_INCREMENTAL |
463 NDMP_BUTYPE_BACKUP_UTF8 |
464 NDMP_BUTYPE_RECOVER_UTF8;
466 /* If DAR supported */
467 if (ndmp_dar_support)
468 attrs |= NDMP_BUTYPE_RECOVER_DIRECT;
470 /* tar backup type */
471 info[0].butype_name = "tar";
472 info[0].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval);
473 info[0].default_env.default_env_val = envs;
474 info[0].attrs = attrs;
476 /* dump backup type */
477 info[1].butype_name = "dump";
478 info[1].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval);
479 info[1].default_env.default_env_val = envs;
480 info[1].attrs = attrs;
483 * Supported environment variables and their default values
484 * for type "zfs."
487 NDMP_SETENV(zfs_envp, "PREFIX", "");
488 NDMP_SETENV(zfs_envp, "FILESYSTEM", "");
489 NDMP_SETENV(zfs_envp, "TYPE", "zfs");
490 NDMP_SETENV(zfs_envp, "HIST", "n");
491 NDMP_SETENV(zfs_envp, "LEVEL", "0");
492 NDMP_SETENV(zfs_envp, "ZFS_MODE", "recursive");
493 NDMP_SETENV(zfs_envp, "ZFS_FORCE", "FALSE");
494 NDMP_SETENV(zfs_envp, "UPDATE", "TRUE");
495 NDMP_SETENV(zfs_envp, "DMP_NAME", "level");
497 zfs_attrs = NDMP_BUTYPE_BACKUP_UTF8 |
498 NDMP_BUTYPE_RECOVER_UTF8 |
499 NDMP_BUTYPE_BACKUP_DIRECT |
500 NDMP_BUTYPE_BACKUP_INCREMENTAL;
502 /* zfs backup type */
503 info[2].butype_name = "zfs";
504 info[2].default_env.default_env_len = ARRAY_LEN(zfs_envs, ndmp_pval);
505 info[2].default_env.default_env_val = zfs_envs;
506 info[2].attrs = zfs_attrs;
508 reply.error = NDMP_NO_ERR;
509 reply.butype_info.butype_info_len = ARRAY_LEN(info, ndmp_butype_info);
510 reply.butype_info.butype_info_val = info;
512 ndmp_send_reply(connection, (void *)&reply,
513 "sending ndmp_config_get_butype_info reply");
517 * ndmpd_config_get_fs_info_v3
519 * This handler handles the ndmp_config_get_fs_info_request.
520 * Information about all mounted file systems is returned.
522 * Parameters:
523 * connection (input) - connection handle.
524 * body (input) - request message body.
526 * Returns:
527 * void
529 /*ARGSUSED*/
530 void
531 ndmpd_config_get_fs_info_v3(ndmp_connection_t *connection, void *body)
533 ndmp_config_get_fs_info_reply_v3 reply;
534 ndmp_fs_info_v3 *fsip = NULL, *fsip_save = NULL; /* FS info pointer */
535 int len = 0, nmnt, fd;
536 int log_dev_len;
537 FILE *fp = NULL;
538 struct mnttab mt, *fs;
539 struct statvfs64 stat_buf;
540 ndmp_pval *envp, *save;
542 (void) memset((void*)&reply, 0, sizeof (reply));
543 reply.error = NDMP_NO_ERR;
545 if ((fd = open(MNTTAB, O_RDONLY)) == -1) {
546 NDMP_LOG(LOG_ERR, "File mnttab open error: %m.");
547 reply.error = NDMP_UNDEFINED_ERR;
548 goto send_reply;
551 /* nothing was found, send an empty reply */
552 if (ioctl(fd, MNTIOC_NMNTS, &nmnt) != 0 || nmnt <= 0) {
553 (void) close(fd);
554 NDMP_LOG(LOG_ERR, "No file system found.");
555 goto send_reply;
558 fp = fdopen(fd, "r");
559 if (!fp) {
560 (void) close(fd);
561 NDMP_LOG(LOG_ERR, "File mnttab open error: %m.");
562 reply.error = NDMP_UNDEFINED_ERR;
563 goto send_reply;
566 fsip_save = fsip = ndmp_malloc(sizeof (ndmp_fs_info_v3) * nmnt);
567 if (!fsip) {
568 (void) fclose(fp);
569 reply.error = NDMP_NO_MEM_ERR;
570 goto send_reply;
574 * Re-read the directory and set up file system information.
576 rewind(fp);
577 while (len < nmnt && (getmntent(fp, &mt) == 0))
580 fs = &mt;
581 log_dev_len = strlen(mt.mnt_mountp)+2;
582 if (!IS_VALID_FS(fs))
583 continue;
585 fsip->fs_logical_device = ndmp_malloc(log_dev_len);
586 fsip->fs_type = ndmp_malloc(MNTTYPE_LEN);
587 if (!fsip->fs_logical_device || !fsip->fs_type) {
588 free(fsip->fs_logical_device);
589 free(fsip->fs_type);
590 reply.error = NDMP_NO_MEM_ERR;
591 break;
593 (void) snprintf(fsip->fs_type, MNTTYPE_LEN, "%s",
594 fs->mnt_fstype);
595 (void) snprintf(fsip->fs_logical_device, log_dev_len, "%s",
596 fs->mnt_mountp);
597 fsip->invalid = 0;
599 if (statvfs64(fs->mnt_mountp, &stat_buf) < 0) {
600 NDMP_LOG(LOG_DEBUG,
601 "statvfs(%s) error.", fs->mnt_mountp);
602 fsip->fs_status =
603 "statvfs error: unable to determine filesystem"
604 " attributes";
605 } else {
606 fsip->invalid = 0;
607 fsip->total_size =
608 long_long_to_quad((u_longlong_t)stat_buf.f_frsize *
609 (u_longlong_t)stat_buf.f_blocks);
610 fsip->used_size =
611 long_long_to_quad((u_longlong_t)stat_buf.f_frsize *
612 (u_longlong_t)(stat_buf.f_blocks-stat_buf.f_bfree));
614 fsip->avail_size =
615 long_long_to_quad((u_longlong_t)stat_buf.f_frsize *
616 (u_longlong_t)stat_buf.f_bfree);
617 fsip->total_inodes =
618 long_long_to_quad((u_longlong_t)stat_buf.f_files);
619 fsip->used_inodes =
620 long_long_to_quad((u_longlong_t)(stat_buf.f_files -
621 stat_buf.f_ffree));
622 fsip->fs_status = "";
624 save = envp = ndmp_malloc(sizeof (ndmp_pval) * V3_N_FS_ENVS);
625 if (!envp) {
626 free(fsip->fs_logical_device);
627 free(fsip->fs_type);
628 reply.error = NDMP_NO_MEM_ERR;
629 break;
631 (void) memset((void*)save, 0,
632 V3_N_FS_ENVS * sizeof (ndmp_pval));
634 fsip->fs_env.fs_env_val = envp;
635 NDMP_SETENV(envp, "LOCAL", "y");
636 NDMP_SETENV(envp, "TYPE", fsip->fs_type);
637 NDMP_SETENV(envp, "AVAILABLE_BACKUP", "tar,dump");
639 if (FS_READONLY(fs) == 0) {
640 NDMP_SETENV(envp, "AVAILABLE_RECOVERY", "tar,dump");
643 fsip->fs_env.fs_env_len = envp - save;
644 len++;
645 fsip++;
647 (void) fclose(fp);
649 send_reply:
650 if (reply.error == NDMP_NO_ERR) {
651 reply.fs_info.fs_info_len = len;
652 reply.fs_info.fs_info_val = fsip_save;
654 ndmp_send_reply(connection, (void *)&reply,
655 "error sending ndmp_config_get_fs_info reply");
657 while (fsip > fsip_save) {
658 fsip--;
659 free(fsip->fs_logical_device);
660 free(fsip->fs_env.fs_env_val);
661 free(fsip->fs_type);
664 free(fsip);
669 * ndmpd_config_get_tape_info_v3
671 * This handler handles the ndmp_config_get_tape_info_request.
672 * Information about all connected tape drives is returned.
674 * Parameters:
675 * connection (input) - connection handle.
676 * body (input) - request message body.
678 * Returns:
679 * void
681 /*ARGSUSED*/
682 void
683 ndmpd_config_get_tape_info_v3(ndmp_connection_t *connection, void *body)
685 ndmp_config_get_tape_info_reply_v3 reply;
686 ndmp_device_info_v3 *tip, *tip_save = NULL; /* tape info pointer */
687 ndmp_device_capability_v3 *dcp;
688 ndmp_device_capability_v3 *dcp_save = NULL; /* dev capability pointer */
689 int i, n, max;
690 sasd_drive_t *sd;
691 scsi_link_t *sl;
692 ndmp_pval *envp, *envp_save = NULL;
693 ndmp_pval *envp_head;
695 (void) memset((void*)&reply, 0, sizeof (reply));
696 max = sasd_dev_count();
698 tip_save = tip = ndmp_malloc(sizeof (ndmp_device_info_v3) * max);
699 dcp_save = dcp = ndmp_malloc(sizeof (ndmp_device_capability_v3) * max);
700 envp_save = envp = ndmp_malloc(sizeof (ndmp_pval) * max * 3);
701 if (!tip_save || !dcp_save || !envp_save) {
702 free(tip_save);
703 free(dcp_save);
704 free(envp_save);
705 reply.error = NDMP_NO_MEM_ERR;
706 ndmp_send_reply(connection, (void *)&reply,
707 "error sending ndmp_config_get_tape_info reply");
708 return;
711 reply.error = NDMP_NO_ERR;
713 for (i = n = 0; i < max; i++) {
714 if (!(sl = sasd_dev_slink(i)) || !(sd = sasd_drive(i)))
715 continue;
716 if (sl->sl_type != DTYPE_SEQUENTIAL)
717 continue;
719 * Don't report dead links.
721 if ((access(sd->sd_name, F_OK) == -1) && (errno == ENOENT))
722 continue;
724 NDMP_LOG(LOG_DEBUG,
725 "model \"%s\" dev \"%s\"", sd->sd_id, sd->sd_name);
727 envp_head = envp;
728 NDMP_SETENV(envp, "EXECUTE_CDB", "b");
729 NDMP_SETENV(envp, "SERIAL_NUMBER", sd->sd_serial);
730 NDMP_SETENV(envp, "WORLD_WIDE_NAME", sd->sd_wwn);
732 tip->model = sd->sd_id; /* like "DLT7000 " */
733 tip->caplist.caplist_len = 1;
734 tip->caplist.caplist_val = dcp;
735 dcp->device = sd->sd_name; /* like "isp1t060" */
736 dcp->attr = 0;
737 dcp->capability.capability_len = 3;
738 dcp->capability.capability_val = envp_head;
739 tip++;
740 dcp++;
741 n++;
744 NDMP_LOG(LOG_DEBUG, "n %d", n);
747 * We should not receive the get_tape_info when three-way backup is
748 * running and we are acting as just data, but some clients try
749 * to get the Tape information anyway.
751 if (n == 0 || max <= 0) {
752 reply.error = NDMP_NO_DEVICE_ERR;
753 ndmp_send_reply(connection, (void *)&reply,
754 "error sending ndmp_config_get_tape_info reply");
755 free(tip_save); free(dcp_save); free(envp_save);
756 return;
760 reply.tape_info.tape_info_len = n;
761 reply.tape_info.tape_info_val = tip_save;
763 ndmp_send_reply(connection, (void *)&reply,
764 "error sending ndmp_config_get_tape_info reply");
766 free(tip_save);
767 free(dcp_save);
768 free(envp_save);
773 * ndmpd_config_get_scsi_info_v3
775 * This handler handles the ndmp_config_get_tape_scsi_request.
776 * Information about all connected scsi tape stacker and jukeboxes
777 * is returned.
779 * Parameters:
780 * connection (input) - connection handle.
781 * body (input) - request message body.
783 * Returns:
784 * void
786 /*ARGSUSED*/
787 void
788 ndmpd_config_get_scsi_info_v3(ndmp_connection_t *connection, void *body)
790 ndmp_config_get_scsi_info_reply_v3 reply;
791 ndmp_device_info_v3 *sip, *sip_save;
792 ndmp_device_capability_v3 *dcp, *dcp_save;
793 int i, n, max;
794 sasd_drive_t *sd;
795 scsi_link_t *sl;
796 ndmp_pval *envp, *envp_save = NULL;
797 ndmp_pval *envp_head;
799 (void) memset((void*)&reply, 0, sizeof (reply));
800 max = sasd_dev_count();
801 sip_save = sip = ndmp_malloc(sizeof (ndmp_device_info_v3) * max);
802 dcp_save = dcp = ndmp_malloc(sizeof (ndmp_device_capability_v3) * max);
803 envp_save = envp = ndmp_malloc(sizeof (ndmp_pval) * max * 2);
804 if (!sip_save || !dcp_save || !envp_save) {
805 free(sip_save);
806 free(dcp_save);
807 free(envp_save);
808 reply.error = NDMP_NO_MEM_ERR;
809 ndmp_send_reply(connection, (void *)&reply,
810 "error sending ndmp_config_get_scsi_info reply");
811 return;
814 reply.error = NDMP_NO_ERR;
815 for (i = n = 0; i < max; i++) {
816 if (!(sl = sasd_dev_slink(i)) || !(sd = sasd_drive(i)))
817 continue;
818 if (sl->sl_type != DTYPE_CHANGER)
819 continue;
821 * Don't report dead links.
823 if ((access(sd->sd_name, F_OK) == -1) && (errno == ENOENT))
824 continue;
826 NDMP_LOG(LOG_DEBUG,
827 "model \"%s\" dev \"%s\"", sd->sd_id, sd->sd_name);
829 envp_head = envp;
830 NDMP_SETENV(envp, "SERIAL_NUMBER", sd->sd_serial);
831 NDMP_SETENV(envp, "WORLD_WIDE_NAME", sd->sd_wwn);
833 sip->model = sd->sd_id; /* like "Powerstor L200 " */
834 sip->caplist.caplist_len = 1;
835 sip->caplist.caplist_val = dcp;
836 dcp->device = sd->sd_name; /* like "isp1m000" */
838 dcp->attr = 0;
839 dcp->capability.capability_len = 2;
840 dcp->capability.capability_val = envp_head;
841 sip++;
842 dcp++;
843 n++;
846 NDMP_LOG(LOG_DEBUG, "n %d", n);
848 reply.scsi_info.scsi_info_len = n;
849 reply.scsi_info.scsi_info_val = sip_save;
851 ndmp_send_reply(connection, (void *)&reply,
852 "error sending ndmp_config_get_scsi_info reply");
854 free(sip_save);
855 free(dcp_save);
856 free(envp_save);
861 * ndmpd_config_get_server_info_v3
863 * This handler handles the ndmp_config_get_server_info request.
864 * Host specific information is returned.
866 * Parameters:
867 * connection (input) - connection handle.
868 * body (input) - request message body.
870 * Returns:
871 * void
873 /*ARGSUSED*/
874 void
875 ndmpd_config_get_server_info_v3(ndmp_connection_t *connection, void *body)
877 ndmp_config_get_server_info_reply_v3 reply;
878 ndmp_auth_type auth_types[2];
879 char rev_number[10];
880 ndmpd_session_t *session = ndmp_get_client_data(connection);
882 (void) memset((void*)&reply, 0, sizeof (reply));
883 reply.error = NDMP_NO_ERR;
885 if (connection->conn_authorized ||
886 session->ns_protocol_version != NDMPV4) {
887 reply.vendor_name = VENDOR_NAME;
888 reply.product_name = PRODUCT_NAME;
889 (void) snprintf(rev_number, sizeof (rev_number), "%d",
890 ndmp_ver);
891 reply.revision_number = rev_number;
892 } else {
893 reply.vendor_name = "\0";
894 reply.product_name = "\0";
895 reply.revision_number = "\0";
898 NDMP_LOG(LOG_DEBUG,
899 "vendor \"%s\", product \"%s\" rev \"%s\"",
900 reply.vendor_name, reply.product_name, reply.revision_number);
902 auth_types[0] = NDMP_AUTH_TEXT;
903 auth_types[1] = NDMP_AUTH_MD5;
904 reply.auth_type.auth_type_len = ARRAY_LEN(auth_types, ndmp_auth_type);
905 reply.auth_type.auth_type_val = auth_types;
907 ndmp_send_reply(connection, (void *)&reply,
908 "error sending ndmp_config_get_server_info reply");
914 * ************************************************************************
915 * NDMP V4 HANDLERS
916 * ************************************************************************
920 * ndmpd_config_get_butype_info_v4
922 * This handler handles the ndmp_config_get_butype_info_request.
923 * Information about all supported backup types are returned.
925 * Parameters:
926 * connection (input) - connection handle.
927 * body (input) - request message body.
929 * Returns:
930 * void
932 /*ARGSUSED*/
933 void
934 ndmpd_config_get_butype_info_v4(ndmp_connection_t *connection, void *body)
936 ndmp_config_get_butype_info_reply_v4 reply;
937 ndmp_butype_info info[3];
939 ndmp_pval envs[12];
940 ulong_t attrs;
941 ndmp_pval *envp = envs;
943 ndmp_pval zfs_envs[11];
944 ulong_t zfs_attrs;
945 ndmp_pval *zfs_envp = zfs_envs;
948 (void) memset((void*)&reply, 0, sizeof (reply));
951 * Supported environment variables and their default values
952 * for dump and tar.
954 * The environment variables for dump and tar format are the
955 * same, because we use the same backup engine for both.
957 NDMP_SETENV(envp, "FILESYSTEM", "");
958 NDMP_SETENV(envp, "DIRECT", "n");
959 NDMP_SETENV(envp, "RECURSIVE", "n");
960 NDMP_SETENV(envp, "TYPE", "");
961 NDMP_SETENV(envp, "USER", "");
962 NDMP_SETENV(envp, "HIST", "n");
963 NDMP_SETENV(envp, "PATHNAME_SEPARATOR", "/");
964 NDMP_SETENV(envp, "LEVEL", "0");
965 NDMP_SETENV(envp, "EXTRACT", "y");
966 NDMP_SETENV(envp, "UPDATE", "y");
967 NDMP_SETENV(envp, "CMD", "");
968 NDMP_SETENV(envp, "BASE_DATE", "");
970 attrs = NDMP_BUTYPE_RECOVER_FILELIST |
971 NDMP_BUTYPE_BACKUP_DIRECT |
972 NDMP_BUTYPE_BACKUP_INCREMENTAL |
973 NDMP_BUTYPE_BACKUP_UTF8 |
974 NDMP_BUTYPE_RECOVER_UTF8 |
975 NDMP_BUTYPE_BACKUP_FH_FILE |
976 NDMP_BUTYPE_BACKUP_FH_DIR |
977 NDMP_BUTYPE_RECOVER_FH_FILE |
978 NDMP_BUTYPE_RECOVER_FH_DIR;
980 /* If DAR supported */
981 if (ndmp_dar_support)
982 attrs |= NDMP_BUTYPE_RECOVER_DIRECT;
984 /* tar backup type */
985 info[0].butype_name = "tar";
986 info[0].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval);
987 info[0].default_env.default_env_val = envs;
988 info[0].attrs = attrs;
990 /* dump backup type */
991 info[1].butype_name = "dump";
992 info[1].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval);
993 info[1].default_env.default_env_val = envs;
994 info[1].attrs = attrs;
997 * Supported environment variables and their default values
998 * for type "zfs."
1001 NDMP_SETENV(zfs_envp, "USER", "");
1002 NDMP_SETENV(zfs_envp, "CMD", "");
1003 NDMP_SETENV(zfs_envp, "FILESYSTEM", "");
1004 NDMP_SETENV(zfs_envp, "PATHNAME_SEPARATOR", "/");
1005 NDMP_SETENV(zfs_envp, "TYPE", "zfs");
1006 NDMP_SETENV(zfs_envp, "HIST", "n");
1007 NDMP_SETENV(zfs_envp, "LEVEL", "0");
1008 NDMP_SETENV(zfs_envp, "ZFS_MODE", "recursive");
1009 NDMP_SETENV(zfs_envp, "ZFS_FORCE", "n");
1010 NDMP_SETENV(zfs_envp, "UPDATE", "y");
1011 NDMP_SETENV(zfs_envp, "DMP_NAME", "level");
1013 zfs_attrs = NDMP_BUTYPE_BACKUP_UTF8 |
1014 NDMP_BUTYPE_RECOVER_UTF8 |
1015 NDMP_BUTYPE_BACKUP_DIRECT |
1016 NDMP_BUTYPE_BACKUP_INCREMENTAL;
1018 /* zfs backup type */
1019 info[2].butype_name = "zfs";
1020 info[2].default_env.default_env_len = ARRAY_LEN(zfs_envs, ndmp_pval);
1021 info[2].default_env.default_env_val = zfs_envs;
1022 info[2].attrs = zfs_attrs;
1024 reply.error = NDMP_NO_ERR;
1025 reply.butype_info.butype_info_len = ARRAY_LEN(info, ndmp_butype_info);
1026 reply.butype_info.butype_info_val = info;
1028 ndmp_send_reply(connection, (void *)&reply,
1029 "sending ndmp_config_get_butype_info reply");
1034 * ndmpd_config_get_ext_list_v4
1036 * This handler handles the ndmpd_config_get_ext_list_v4 request.
1038 * Parameters:
1039 * connection (input) - connection handle.
1040 * body (input) - request message body.
1042 * Returns:
1043 * void
1045 /*ARGSUSED*/
1046 void
1047 ndmpd_config_get_ext_list_v4(ndmp_connection_t *connection, void *body)
1049 ndmp_config_get_ext_list_reply_v4 reply;
1050 ndmpd_session_t *session = ndmp_get_client_data(connection);
1052 (void) memset((void*)&reply, 0, sizeof (reply));
1054 if (session->ns_set_ext_list) {
1056 * Illegal request if extensions have already been selected.
1058 NDMP_LOG(LOG_ERR, "Extensions have already been selected.");
1059 reply.error = NDMP_EXT_DANDN_ILLEGAL_ERR;
1060 } else {
1062 * Reply with an empty set of extensions.
1064 session->ns_get_ext_list = B_TRUE;
1065 reply.error = NDMP_NO_ERR;
1068 reply.class_list.class_list_val = NULL;
1069 reply.class_list.class_list_len = 0;
1071 ndmp_send_reply(connection, (void *)&reply,
1072 "error sending ndmp_config_get_ext_list reply");
1076 * ndmpd_config_set_ext_list_v4
1078 * This handler handles the ndmpd_config_get_ext_list_v4 request.
1080 * Parameters:
1081 * connection (input) - connection handle.
1082 * body (input) - request message body.
1084 * Returns:
1085 * void
1087 void
1088 ndmpd_config_set_ext_list_v4(ndmp_connection_t *connection, void *body)
1090 ndmp_config_set_ext_list_reply_v4 reply;
1091 ndmp_config_set_ext_list_request_v4 *request;
1092 ndmpd_session_t *session = ndmp_get_client_data(connection);
1094 request = (ndmp_config_set_ext_list_request_v4 *)body;
1096 (void) memset((void*)&reply, 0, sizeof (reply));
1098 if (!session->ns_get_ext_list) {
1100 * The DMA is required to issue a NDMP_GET_EXT_LIST request
1101 * prior sending a NDMP_SET_EXT_LIST request.
1103 NDMP_LOG(LOG_ERR, "No prior ndmp_config_get_ext_list issued.");
1104 reply.error = NDMP_PRECONDITION_ERR;
1105 } else if (session->ns_set_ext_list) {
1107 * Illegal request if extensions have already been selected.
1109 NDMP_LOG(LOG_ERR, "Extensions have already been selected.");
1110 reply.error = NDMP_EXT_DANDN_ILLEGAL_ERR;
1111 } else {
1113 * We currently do not support any extensions, but the DMA
1114 * may test NDMP_CONFIG_SET_EXT_LIST with an empty list.
1116 if (request->ndmp_selected_ext.ndmp_selected_ext_len != 0) {
1117 reply.error = NDMP_CLASS_NOT_SUPPORTED_ERR;
1118 } else {
1119 session->ns_set_ext_list = B_TRUE;
1120 reply.error = NDMP_NO_ERR;
1124 ndmp_send_reply(connection, (void *)&reply,
1125 "error sending ndmp_config_set_ext_list reply");
1131 * ************************************************************************
1132 * LOCALS
1133 * ************************************************************************
1137 * simple_get_attrs
1139 * Set the default attrs for dump mode
1141 * Parameters:
1142 * attributes (output) - the attributes for dump mode
1144 * Returns:
1145 * void
1147 static void
1148 simple_get_attrs(ulong_t *attributes)
1150 *attributes = NDMP_NO_RECOVER_FHINFO;