1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * - Neither the name of The Storage Networking Industry Association (SNIA) 23 * nor the names of its contributors may be used to endorse or promote 24 * products derived from this software without specific prior written 25 * permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 /* Copyright (c) 2007, The Storage Networking Industry Association. */ 40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 41 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" 58 59 static void simple_get_attrs(ulong_t *attributes); 60 61 /* 62 * Number of environment variable for the file system 63 * info in V3 net_fs_info. 64 */ 65 #define V3_N_FS_ENVS 4 66 67 /* 68 * Is the file system a valid one to be reported to the 69 * clients? 70 */ 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)) 77 78 #define MNTTYPE_LEN 10 79 80 extern struct fs_ops sfs2_ops; 81 extern struct fs_ops sfs2cpv_ops; 82 83 84 /* 85 * ************************************************************************ 86 * NDMP V2 HANDLERS 87 * ************************************************************************ 88 */ 89 90 /* 91 * ndmpd_config_get_host_info_v2 92 * 93 * This handler handles the ndmp_config_get_host_info request. 94 * Host specific information is returned. 95 * 96 * Parameters: 97 * connection (input) - connection handle. 98 * body (input) - request message body. 99 * 100 * Returns: 101 * void 102 */ 103 /*ARGSUSED*/ 104 void 105 ndmpd_config_get_host_info_v2(ndmp_connection_t *connection, void *body) 106 { 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; 113 114 (void) memset((void*)&reply, 0, sizeof (reply)); 115 (void) memset(buf, 0, sizeof (buf)); 116 (void) gethostname(buf, sizeof (buf)); 117 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; 123 124 if (sysinfo(SI_HW_SERIAL, hostidstr, sizeof (hostidstr)) < 0) { 125 NDMP_LOG(LOG_DEBUG, "sysinfo error: %m."); 126 reply.error = NDMP_UNDEFINED_ERR; 127 } 128 129 /* 130 * Convert the hostid to hex. The returned string must match 131 * the string returned by hostid(1). 132 */ 133 hostid = strtoul(hostidstr, 0, 0); 134 (void) snprintf(hostidstr, sizeof (hostidstr), "%lx", hostid); 135 reply.hostid = hostidstr; 136 137 auth_types[0] = NDMP_AUTH_TEXT; 138 reply.auth_type.auth_type_len = 1; 139 reply.auth_type.auth_type_val = auth_types; 140 141 ndmp_send_reply(connection, (void *) &reply, 142 "sending ndmp_config_get_host_info reply"); 143 } 144 145 146 /* 147 * ndmpd_config_get_butype_attr_v2 148 * 149 * This handler handles the ndmp_config_get_butype_attr request. 150 * Information about the specified backup type is returned. 151 * 152 * Parameters: 153 * connection (input) - connection handle. 154 * body (input) - request message body. 155 * 156 * Returns: 157 * void 158 */ 159 void 160 ndmpd_config_get_butype_attr_v2(ndmp_connection_t *connection, void *body) 161 { 162 ndmp_config_get_butype_attr_request *request; 163 ndmp_config_get_butype_attr_reply reply; 164 165 request = (ndmp_config_get_butype_attr_request *)body; 166 167 reply.error = NDMP_NO_ERR; 168 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; 178 } 179 180 ndmp_send_reply(connection, (void *) &reply, 181 "sending ndmp_config_get_butype_attr reply"); 182 } 183 184 185 /* 186 * ndmpd_config_get_mover_type_v2 187 * 188 * This handler handles the ndmp_config_get_mover_type request. 189 * Information about the supported mover types is returned. 190 * 191 * Parameters: 192 * connection (input) - connection handle. 193 * body (input) - request message body. 194 * 195 * Returns: 196 * void 197 */ 198 /*ARGSUSED*/ 199 void 200 ndmpd_config_get_mover_type_v2(ndmp_connection_t *connection, void *body) 201 { 202 ndmp_config_get_mover_type_reply reply; 203 ndmp_addr_type types[2]; 204 205 types[0] = NDMP_ADDR_LOCAL; 206 types[1] = NDMP_ADDR_TCP; 207 208 reply.error = NDMP_NO_ERR; 209 reply.methods.methods_len = 2; 210 reply.methods.methods_val = types; 211 212 ndmp_send_reply(connection, (void *) &reply, 213 "sending ndmp_config_get_mover_type reply"); 214 } 215 216 217 218 /* 219 * ndmpd_config_get_auth_attr_v2 220 * 221 * This handler handles the ndmp_config_get_auth_attr request. 222 * Authorization type specific information is returned. 223 * 224 * Parameters: 225 * connection (input) - connection handle. 226 * body (input) - request message body. 227 * 228 * Returns: 229 * void 230 */ 231 void 232 ndmpd_config_get_auth_attr_v2(ndmp_connection_t *connection, void *body) 233 { 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); 237 238 request = (ndmp_config_get_auth_attr_request *)body; 239 240 reply.error = NDMP_NO_ERR; 241 reply.server_attr.auth_type = request->auth_type; 242 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; 261 } 262 263 ndmp_send_reply(connection, (void *) &reply, 264 "sending ndmp_config_get_auth_attr reply"); 265 } 266 267 268 /* 269 * ************************************************************************ 270 * NDMP V3 HANDLERS 271 * ************************************************************************ 272 */ 273 274 /* 275 * ndmpd_config_get_host_info_v3 276 * 277 * This handler handles the ndmp_config_get_host_info request. 278 * Host specific information is returned. 279 * 280 * Parameters: 281 * connection (input) - connection handle. 282 * body (input) - request message body. 283 * 284 * Returns: 285 * void 286 */ 287 /*ARGSUSED*/ 288 void 289 ndmpd_config_get_host_info_v3(ndmp_connection_t *connection, void *body) 290 { 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; 296 297 (void) memset((void*)&reply, 0, sizeof (reply)); 298 (void) memset(buf, 0, sizeof (buf)); 299 (void) gethostname(buf, sizeof (buf)); 300 301 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; 307 308 if (sysinfo(SI_HW_SERIAL, hostidstr, sizeof (hostidstr)) < 0) { 309 310 NDMP_LOG(LOG_DEBUG, "sysinfo error: %m."); 311 reply.error = NDMP_UNDEFINED_ERR; 312 } 313 314 /* 315 * Convert the hostid to hex. The returned string must match 316 * the string returned by hostid(1). 317 */ 318 hostid = strtoul(hostidstr, 0, 0); 319 (void) snprintf(hostidstr, sizeof (hostidstr), "%lx", hostid); 320 reply.hostid = hostidstr; 321 322 ndmp_send_reply(connection, (void *) &reply, 323 "sending ndmp_config_get_host_info reply"); 324 } 325 326 327 /* 328 * ndmpd_config_get_connection_type_v3 329 * 330 * This handler handles the ndmp_config_get_connection_type_request. 331 * A list of supported data connection types is returned. 332 * 333 * Parameters: 334 * connection (input) - connection handle. 335 * body (input) - request message body. 336 * 337 * Returns: 338 * void 339 */ 340 /*ARGSUSED*/ 341 void 342 ndmpd_config_get_connection_type_v3(ndmp_connection_t *connection, 343 void *body) 344 { 345 ndmp_config_get_connection_type_reply_v3 reply; 346 ndmp_addr_type addr_types[2]; 347 348 (void) memset((void*)&reply, 0, sizeof (reply)); 349 350 reply.error = NDMP_NO_ERR; 351 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; 356 357 ndmp_send_reply(connection, (void *) &reply, 358 "sending config_get_connection_type_v3 reply"); 359 } 360 361 362 363 /* 364 * ndmpd_config_get_auth_attr_v3 365 * 366 * This handler handles the ndmp_config_get_auth_attr request. 367 * Authorization type specific information is returned. 368 * 369 * Parameters: 370 * connection (input) - connection handle. 371 * body (input) - request message body. 372 * 373 * Returns: 374 * void 375 */ 376 void 377 ndmpd_config_get_auth_attr_v3(ndmp_connection_t *connection, void *body) 378 { 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); 382 383 request = (ndmp_config_get_auth_attr_request *)body; 384 385 (void) memset((void*)&reply, 0, sizeof (reply)); 386 reply.error = NDMP_NO_ERR; 387 reply.server_attr.auth_type = request->auth_type; 388 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; 407 } 408 409 ndmp_send_reply(connection, (void *) &reply, 410 "sending ndmp_config_get_auth_attr_v3 reply"); 411 } 412 413 414 /* 415 * ndmpd_config_get_butype_info_v3 416 * 417 * This handler handles the ndmp_config_get_butype_info_request. 418 * Information about all supported backup types are returned. 419 * 420 * Parameters: 421 * connection (input) - connection handle. 422 * body (input) - request message body. 423 * 424 * Returns: 425 * void 426 */ 427 /*ARGSUSED*/ 428 void 429 ndmpd_config_get_butype_info_v3(ndmp_connection_t *connection, void *body) 430 { 431 ndmp_config_get_butype_info_reply_v3 reply; 432 ndmp_butype_info info[2]; 433 ndmp_pval envs[8]; 434 ulong_t attrs; 435 ndmp_pval *envp = envs; 436 437 (void) memset((void*)&reply, 0, sizeof (reply)); 438 439 /* 440 * Supported environment variables and their default values. 441 * The environment variables for dump and tar format are the 442 * same, because we use the same backup engine for both. 443 */ 444 NDMP_SETENV(envp, "PREFIX", ""); 445 NDMP_SETENV(envp, "TYPE", ""); 446 NDMP_SETENV(envp, "DIRECT", "n"); 447 NDMP_SETENV(envp, "HIST", "n"); 448 NDMP_SETENV(envp, "FILESYSTEM", ""); 449 NDMP_SETENV(envp, "LEVEL", "0"); 450 NDMP_SETENV(envp, "UPDATE", "TRUE"); 451 NDMP_SETENV(envp, "BASE_DATE", ""); 452 453 attrs = NDMP_BUTYPE_BACKUP_FILE_HISTORY | 454 NDMP_BUTYPE_RECOVER_FILELIST | 455 NDMP_BUTYPE_BACKUP_DIRECT | 456 NDMP_BUTYPE_BACKUP_INCREMENTAL | 457 NDMP_BUTYPE_BACKUP_UTF8 | 458 NDMP_BUTYPE_RECOVER_UTF8; 459 460 /* If DAR supported */ 461 if (ndmp_dar_support) 462 attrs |= NDMP_BUTYPE_RECOVER_DIRECT; 463 464 /* tar backup type */ 465 info[0].butype_name = "tar"; 466 info[0].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval); 467 info[0].default_env.default_env_val = envs; 468 info[0].attrs = attrs; 469 470 /* dump backup type */ 471 info[1].butype_name = "dump"; 472 info[1].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval); 473 info[1].default_env.default_env_val = envs; 474 info[1].attrs = attrs; 475 476 reply.error = NDMP_NO_ERR; 477 reply.butype_info.butype_info_len = ARRAY_LEN(info, ndmp_butype_info); 478 reply.butype_info.butype_info_val = info; 479 480 ndmp_send_reply(connection, (void *)&reply, 481 "sending ndmp_config_get_butype_info reply"); 482 } 483 484 /* 485 * ndmpd_config_get_fs_info_v3 486 * 487 * This handler handles the ndmp_config_get_fs_info_request. 488 * Information about all mounted file systems is returned. 489 * 490 * Parameters: 491 * connection (input) - connection handle. 492 * body (input) - request message body. 493 * 494 * Returns: 495 * void 496 */ 497 /*ARGSUSED*/ 498 void 499 ndmpd_config_get_fs_info_v3(ndmp_connection_t *connection, void *body) 500 { 501 ndmp_config_get_fs_info_reply_v3 reply; 502 ndmp_fs_info_v3 *fsip, *fsip_save; /* FS info pointer */ 503 int i, nmnt, fd; 504 int log_dev_len; 505 FILE *fp = NULL; 506 struct mnttab mt, *fs; 507 struct statvfs64 stat_buf; 508 ndmp_pval *envp, *save; 509 510 (void) memset((void*)&reply, 0, sizeof (reply)); 511 reply.error = NDMP_NO_ERR; 512 513 if ((fd = open(MNTTAB, O_RDONLY)) == -1) { 514 NDMP_LOG(LOG_ERR, "File mnttab open error: %m."); 515 reply.error = NDMP_UNDEFINED_ERR; 516 ndmp_send_reply(connection, (void *)&reply, 517 "sending ndmp_config_get_fs_info reply"); 518 return; 519 } 520 521 /* nothing was found, send an empty reply */ 522 if (ioctl(fd, MNTIOC_NMNTS, &nmnt) != 0 || nmnt <= 0) { 523 NDMP_LOG(LOG_ERR, "No file system found."); 524 ndmp_send_reply(connection, (void *)&reply, 525 "sending ndmp_config_get_fs_info reply"); 526 return; 527 } 528 529 fp = fopen(MNTTAB, "r"); 530 if (!fp) { 531 NDMP_LOG(LOG_ERR, "File mnttab open error: %m."); 532 reply.error = NDMP_UNDEFINED_ERR; 533 ndmp_send_reply(connection, (void *)&reply, 534 "sending ndmp_config_get_fs_info reply"); 535 return; 536 } 537 538 fsip_save = fsip = ndmp_malloc(sizeof (ndmp_fs_info_v3) * nmnt); 539 if (!fsip) { 540 (void) fclose(fp); 541 reply.error = NDMP_NO_MEM_ERR; 542 ndmp_send_reply(connection, (void *)&reply, 543 "error sending ndmp_config_get_fs_info reply"); 544 return; 545 } 546 547 /* 548 * Re-read the directory and set up file system information. 549 */ 550 i = 0; 551 rewind(fp); 552 while (i < nmnt && (getmntent(fp, &mt) == 0)) 553 554 { 555 fs = &mt; 556 log_dev_len = strlen(mt.mnt_mountp)+2; 557 if (!IS_VALID_FS(fs)) 558 continue; 559 560 fsip->fs_logical_device = ndmp_malloc(log_dev_len); 561 fsip->fs_type = ndmp_malloc(MNTTYPE_LEN); 562 if (!fsip->fs_logical_device || !fsip->fs_type) { 563 reply.error = NDMP_NO_MEM_ERR; 564 free(fsip->fs_logical_device); 565 free(fsip->fs_type); 566 break; 567 } 568 (void) snprintf(fsip->fs_type, MNTTYPE_LEN, "%s", 569 fs->mnt_fstype); 570 (void) snprintf(fsip->fs_logical_device, log_dev_len, "%s", 571 fs->mnt_mountp); 572 fsip->invalid = 0; 573 574 if (statvfs64(fs->mnt_mountp, &stat_buf) < 0) { 575 NDMP_LOG(LOG_DEBUG, 576 "statvfs(%s) error.", fs->mnt_mountp); 577 fsip->fs_status = 578 "statvfs error: unable to determine filesystem" 579 " attributes"; 580 } else { 581 fsip->invalid = 0; 582 fsip->total_size = 583 long_long_to_quad((u_longlong_t)stat_buf.f_frsize * 584 (u_longlong_t)stat_buf.f_blocks); 585 fsip->used_size = 586 long_long_to_quad((u_longlong_t)stat_buf.f_frsize * 587 (u_longlong_t)(stat_buf.f_blocks-stat_buf.f_bfree)); 588 589 fsip->avail_size = 590 long_long_to_quad((u_longlong_t)stat_buf.f_frsize * 591 (u_longlong_t)stat_buf.f_bfree); 592 fsip->total_inodes = 593 long_long_to_quad((u_longlong_t)stat_buf.f_files); 594 fsip->used_inodes = 595 long_long_to_quad((u_longlong_t)(stat_buf.f_files - 596 stat_buf.f_ffree)); 597 fsip->fs_status = ""; 598 } 599 save = envp = ndmp_malloc(sizeof (ndmp_pval) * V3_N_FS_ENVS); 600 if (!envp) { 601 reply.error = NDMP_NO_MEM_ERR; 602 break; 603 } 604 (void) memset((void*)save, 0, 605 V3_N_FS_ENVS * sizeof (ndmp_pval)); 606 607 fsip->fs_env.fs_env_val = envp; 608 NDMP_SETENV(envp, "LOCAL", "y"); 609 NDMP_SETENV(envp, "TYPE", fsip->fs_type); 610 NDMP_SETENV(envp, "AVAILABLE_BACKUP", "tar,dump"); 611 612 if (FS_READONLY(fs) == 0) { 613 NDMP_SETENV(envp, "AVAILABLE_RECOVERY", "tar,dump"); 614 } 615 616 fsip->fs_env.fs_env_len = envp - save; 617 i++; 618 fsip++; 619 } 620 (void) fclose(fp); 621 if (reply.error == NDMP_NO_ERR) { 622 reply.fs_info.fs_info_len = i; 623 reply.fs_info.fs_info_val = fsip_save; 624 } else { 625 reply.fs_info.fs_info_len = 0; 626 reply.fs_info.fs_info_val = NULL; 627 } 628 ndmp_send_reply(connection, (void *)&reply, 629 "error sending ndmp_config_get_fs_info reply"); 630 631 fsip = fsip_save; 632 while (--i >= 0) { 633 free(fsip->fs_logical_device); 634 free(fsip->fs_env.fs_env_val); 635 free(fsip->fs_type); 636 fsip++; 637 } 638 639 free(fsip_save); 640 } 641 642 643 /* 644 * ndmpd_config_get_tape_info_v3 645 * 646 * This handler handles the ndmp_config_get_tape_info_request. 647 * Information about all connected tape drives is returned. 648 * 649 * Parameters: 650 * connection (input) - connection handle. 651 * body (input) - request message body. 652 * 653 * Returns: 654 * void 655 */ 656 /*ARGSUSED*/ 657 void 658 ndmpd_config_get_tape_info_v3(ndmp_connection_t *connection, void *body) 659 { 660 ndmp_config_get_tape_info_reply_v3 reply; 661 ndmp_device_info_v3 *tip, *tip_save = NULL; /* tape info pointer */ 662 ndmp_device_capability_v3 *dcp; 663 ndmp_device_capability_v3 *dcp_save = NULL; /* dev capability pointer */ 664 int i, n, max; 665 sasd_drive_t *sd; 666 scsi_link_t *sl; 667 ndmp_pval *envp, *envp_save = NULL; 668 ndmp_pval *envp_head; 669 670 (void) memset((void*)&reply, 0, sizeof (reply)); 671 max = sasd_dev_count(); 672 673 tip_save = tip = ndmp_malloc(sizeof (ndmp_device_info_v3) * max); 674 dcp_save = dcp = ndmp_malloc(sizeof (ndmp_device_capability_v3) * max); 675 envp_save = envp = ndmp_malloc(sizeof (ndmp_pval) * max * 3); 676 if (!tip_save || !dcp_save || !envp_save) { 677 free(tip_save); 678 free(dcp_save); 679 free(envp_save); 680 reply.error = NDMP_NO_MEM_ERR; 681 ndmp_send_reply(connection, (void *)&reply, 682 "error sending ndmp_config_get_tape_info reply"); 683 return; 684 } 685 686 reply.error = NDMP_NO_ERR; 687 688 for (i = n = 0; i < max; i++) { 689 if (!(sl = sasd_dev_slink(i)) || !(sd = sasd_drive(i))) 690 continue; 691 if (sl->sl_type != DTYPE_SEQUENTIAL) 692 continue; 693 694 NDMP_LOG(LOG_DEBUG, 695 "model \"%s\" dev \"%s\"", sd->sd_id, sd->sd_name); 696 697 envp_head = envp; 698 NDMP_SETENV(envp, "EXECUTE_CDB", "b"); 699 NDMP_SETENV(envp, "SERIAL_NUMBER", sd->sd_serial); 700 NDMP_SETENV(envp, "WORLD_WIDE_NAME", sd->sd_wwn); 701 702 tip->model = sd->sd_id; /* like "DLT7000 " */ 703 tip->caplist.caplist_len = 1; 704 tip->caplist.caplist_val = dcp; 705 dcp->device = sd->sd_name; /* like "isp1t060" */ 706 dcp->attr = 0; 707 dcp->capability.capability_len = 3; 708 dcp->capability.capability_val = envp_head; 709 tip++; 710 dcp++; 711 n++; 712 } 713 714 NDMP_LOG(LOG_DEBUG, "n %d", n); 715 716 /* 717 * We should not receive the get_tape_info when three-way backup is 718 * running and we are acting as just data, but some clients try 719 * to get the Tape information anyway. 720 */ 721 if (n == 0 || max <= 0) { 722 reply.error = NDMP_NO_DEVICE_ERR; 723 ndmp_send_reply(connection, (void *)&reply, 724 "error sending ndmp_config_get_tape_info reply"); 725 free(tip_save); free(dcp_save); free(envp_save); 726 return; 727 } 728 729 730 reply.tape_info.tape_info_len = n; 731 reply.tape_info.tape_info_val = tip_save; 732 733 ndmp_send_reply(connection, (void *)&reply, 734 "error sending ndmp_config_get_tape_info reply"); 735 736 free(tip_save); 737 free(dcp_save); 738 free(envp_save); 739 } 740 741 742 /* 743 * ndmpd_config_get_scsi_info_v3 744 * 745 * This handler handles the ndmp_config_get_tape_scsi_request. 746 * Information about all connected scsi tape stacker and jukeboxes 747 * is returned. 748 * 749 * Parameters: 750 * connection (input) - connection handle. 751 * body (input) - request message body. 752 * 753 * Returns: 754 * void 755 */ 756 /*ARGSUSED*/ 757 void 758 ndmpd_config_get_scsi_info_v3(ndmp_connection_t *connection, void *body) 759 { 760 ndmp_config_get_scsi_info_reply_v3 reply; 761 ndmp_device_info_v3 *sip, *sip_save; 762 ndmp_device_capability_v3 *dcp, *dcp_save; 763 int i, n, max; 764 sasd_drive_t *sd; 765 scsi_link_t *sl; 766 ndmp_pval *envp, *envp_save = NULL; 767 ndmp_pval *envp_head; 768 769 (void) memset((void*)&reply, 0, sizeof (reply)); 770 max = sasd_dev_count(); 771 sip_save = sip = ndmp_malloc(sizeof (ndmp_device_info_v3) * max); 772 dcp_save = dcp = ndmp_malloc(sizeof (ndmp_device_capability_v3) * max); 773 envp_save = envp = ndmp_malloc(sizeof (ndmp_pval) * max * 2); 774 if (!sip_save || !dcp_save || !envp_save) { 775 free(sip_save); 776 free(dcp_save); 777 free(envp_save); 778 reply.error = NDMP_NO_MEM_ERR; 779 ndmp_send_reply(connection, (void *)&reply, 780 "error sending ndmp_config_get_scsi_info reply"); 781 return; 782 } 783 784 reply.error = NDMP_NO_ERR; 785 for (i = n = 0; i < max; i++) { 786 if (!(sl = sasd_dev_slink(i)) || !(sd = sasd_drive(i))) 787 continue; 788 if (sl->sl_type != DTYPE_CHANGER) 789 continue; 790 791 NDMP_LOG(LOG_DEBUG, 792 "model \"%s\" dev \"%s\"", sd->sd_id, sd->sd_name); 793 794 envp_head = envp; 795 NDMP_SETENV(envp, "SERIAL_NUMBER", sd->sd_serial); 796 NDMP_SETENV(envp, "WORLD_WIDE_NAME", sd->sd_wwn); 797 798 sip->model = sd->sd_id; /* like "Powerstor L200 " */ 799 sip->caplist.caplist_len = 1; 800 sip->caplist.caplist_val = dcp; 801 dcp->device = sd->sd_name; /* like "isp1m000" */ 802 803 dcp->attr = 0; 804 dcp->capability.capability_len = 2; 805 dcp->capability.capability_val = envp_head; 806 sip++; 807 dcp++; 808 n++; 809 } 810 811 NDMP_LOG(LOG_DEBUG, "n %d", n); 812 813 reply.scsi_info.scsi_info_len = n; 814 reply.scsi_info.scsi_info_val = sip_save; 815 816 ndmp_send_reply(connection, (void *)&reply, 817 "error sending ndmp_config_get_scsi_info reply"); 818 819 free(sip_save); 820 free(dcp_save); 821 free(envp_save); 822 } 823 824 825 /* 826 * ndmpd_config_get_server_info_v3 827 * 828 * This handler handles the ndmp_config_get_server_info request. 829 * Host specific information is returned. 830 * 831 * Parameters: 832 * connection (input) - connection handle. 833 * body (input) - request message body. 834 * 835 * Returns: 836 * void 837 */ 838 /*ARGSUSED*/ 839 void 840 ndmpd_config_get_server_info_v3(ndmp_connection_t *connection, void *body) 841 { 842 ndmp_config_get_server_info_reply_v3 reply; 843 ndmp_auth_type auth_types[2]; 844 char rev_number[10]; 845 ndmpd_session_t *session = ndmp_get_client_data(connection); 846 847 (void) memset((void*)&reply, 0, sizeof (reply)); 848 reply.error = NDMP_NO_ERR; 849 850 if (connection->conn_authorized || 851 session->ns_protocol_version != NDMPV4) { 852 reply.vendor_name = VENDOR_NAME; 853 reply.product_name = PRODUCT_NAME; 854 (void) snprintf(rev_number, sizeof (rev_number), "%d", 855 ndmp_ver); 856 reply.revision_number = rev_number; 857 } else { 858 reply.vendor_name = "\0"; 859 reply.product_name = "\0"; 860 reply.revision_number = "\0"; 861 } 862 863 NDMP_LOG(LOG_DEBUG, 864 "vendor \"%s\", product \"%s\" rev \"%s\"", 865 reply.vendor_name, reply.product_name, reply.revision_number); 866 867 auth_types[0] = NDMP_AUTH_TEXT; 868 auth_types[1] = NDMP_AUTH_MD5; 869 reply.auth_type.auth_type_len = ARRAY_LEN(auth_types, ndmp_auth_type); 870 reply.auth_type.auth_type_val = auth_types; 871 872 ndmp_send_reply(connection, (void *)&reply, 873 "error sending ndmp_config_get_server_info reply"); 874 } 875 876 877 878 /* 879 * ************************************************************************ 880 * NDMP V4 HANDLERS 881 * ************************************************************************ 882 */ 883 884 /* 885 * ndmpd_config_get_butype_info_v4 886 * 887 * This handler handles the ndmp_config_get_butype_info_request. 888 * Information about all supported backup types are returned. 889 * 890 * Parameters: 891 * connection (input) - connection handle. 892 * body (input) - request message body. 893 * 894 * Returns: 895 * void 896 */ 897 /*ARGSUSED*/ 898 void 899 ndmpd_config_get_butype_info_v4(ndmp_connection_t *connection, void *body) 900 { 901 ndmp_config_get_butype_info_reply_v4 reply; 902 ndmp_butype_info info[2]; 903 ndmp_pval envs[12]; 904 ulong_t attrs; 905 ndmp_pval *envp = envs; 906 907 (void) memset((void*)&reply, 0, sizeof (reply)); 908 909 /* 910 * Supported environment variables and their default values. 911 * The environment variables for dump and tar format are the 912 * same, because we use the same backup engine for both. 913 */ 914 NDMP_SETENV(envp, "FILESYSTEM", ""); 915 NDMP_SETENV(envp, "DIRECT", "n"); 916 NDMP_SETENV(envp, "RECURSIVE", "n"); 917 NDMP_SETENV(envp, "TYPE", ""); 918 NDMP_SETENV(envp, "USER", ""); 919 NDMP_SETENV(envp, "HIST", "n"); 920 NDMP_SETENV(envp, "PATHNAME_SEPARATOR", "/"); 921 NDMP_SETENV(envp, "LEVEL", "0"); 922 NDMP_SETENV(envp, "EXTRACT", "y"); 923 NDMP_SETENV(envp, "UPDATE", "y"); 924 NDMP_SETENV(envp, "CMD", ""); 925 NDMP_SETENV(envp, "BASE_DATE", ""); 926 927 attrs = NDMP_BUTYPE_RECOVER_FILELIST | 928 NDMP_BUTYPE_BACKUP_DIRECT | 929 NDMP_BUTYPE_BACKUP_INCREMENTAL | 930 NDMP_BUTYPE_BACKUP_UTF8 | 931 NDMP_BUTYPE_RECOVER_UTF8 | 932 NDMP_BUTYPE_BACKUP_FH_FILE | 933 NDMP_BUTYPE_BACKUP_FH_DIR | 934 NDMP_BUTYPE_RECOVER_FH_FILE | 935 NDMP_BUTYPE_RECOVER_FH_DIR; 936 937 /* If DAR supported */ 938 if (ndmp_dar_support) 939 attrs |= NDMP_BUTYPE_RECOVER_DIRECT; 940 941 /* tar backup type */ 942 info[0].butype_name = "tar"; 943 info[0].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval); 944 info[0].default_env.default_env_val = envs; 945 info[0].attrs = attrs; 946 947 /* dump backup type */ 948 info[1].butype_name = "dump"; 949 info[1].default_env.default_env_len = ARRAY_LEN(envs, ndmp_pval); 950 info[1].default_env.default_env_val = envs; 951 info[1].attrs = attrs; 952 953 reply.error = NDMP_NO_ERR; 954 reply.butype_info.butype_info_len = ARRAY_LEN(info, ndmp_butype_info); 955 reply.butype_info.butype_info_val = info; 956 957 ndmp_send_reply(connection, (void *)&reply, 958 "sending ndmp_config_get_butype_info reply"); 959 } 960 961 962 /* 963 * ndmpd_config_get_ext_list_v4 964 * 965 * This handler handles the ndmpd_config_get_ext_list_v4 request. 966 * 967 * Parameters: 968 * connection (input) - connection handle. 969 * body (input) - request message body. 970 * 971 * Returns: 972 * void 973 */ 974 /*ARGSUSED*/ 975 void 976 ndmpd_config_get_ext_list_v4(ndmp_connection_t *connection, void *body) 977 { 978 ndmp_config_get_ext_list_reply_v4 reply; 979 ndmpd_session_t *session = ndmp_get_client_data(connection); 980 981 (void) memset((void*)&reply, 0, sizeof (reply)); 982 983 if (session->ns_set_ext_list == FALSE) 984 reply.error = NDMP_EXT_DANDN_ILLEGAL_ERR; 985 else 986 reply.error = NDMP_NO_ERR; 987 988 reply.class_list.class_list_val = NULL; 989 reply.class_list.class_list_len = 0; 990 991 992 ndmp_send_reply(connection, (void *)&reply, 993 "error sending ndmp_config_get_ext_list reply"); 994 } 995 996 /* 997 * ndmpd_config_set_ext_list_v4 998 * 999 * This handler handles the ndmpd_config_get_ext_list_v4 request. 1000 * 1001 * Parameters: 1002 * connection (input) - connection handle. 1003 * body (input) - request message body. 1004 * 1005 * Returns: 1006 * void 1007 */ 1008 /*ARGSUSED*/ 1009 void 1010 ndmpd_config_set_ext_list_v4(ndmp_connection_t *connection, void *body) 1011 { 1012 ndmp_config_set_ext_list_reply_v4 reply; 1013 ndmpd_session_t *session = ndmp_get_client_data(connection); 1014 1015 (void) memset((void*)&reply, 0, sizeof (reply)); 1016 if (session->ns_set_ext_list == TRUE) { 1017 reply.error = NDMP_EXT_DANDN_ILLEGAL_ERR; 1018 } else { 1019 session->ns_set_ext_list = TRUE; 1020 /* 1021 * NOTE: for now we are not supporting any extension list, 1022 * hence this error, when we start to support extensions, 1023 * this should be validated 1024 */ 1025 1026 reply.error = NDMP_VERSION_NOT_SUPPORTED_ERR; 1027 } 1028 1029 ndmp_send_reply(connection, (void *)&reply, 1030 "error sending ndmp_config_set_ext_list reply"); 1031 } 1032 1033 1034 1035 /* 1036 * ************************************************************************ 1037 * LOCALS 1038 * ************************************************************************ 1039 */ 1040 1041 /* 1042 * simple_get_attrs 1043 * 1044 * Set the default attrs for dump mode 1045 * 1046 * Parameters: 1047 * attributes (output) - the attributes for dump mode 1048 * 1049 * Returns: 1050 * void 1051 */ 1052 static void 1053 simple_get_attrs(ulong_t *attributes) 1054 { 1055 *attributes = NDMP_NO_RECOVER_FHINFO; 1056 } 1057