1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * SMB specific functions 31 */ 32 #include <stdio.h> 33 #include <string.h> 34 #include <ctype.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <zone.h> 38 #include <errno.h> 39 #include <locale.h> 40 #include <signal.h> 41 #include <fcntl.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <syslog.h> 45 #include "libshare.h" 46 #include "libshare_impl.h" 47 #include <pwd.h> 48 #include <limits.h> 49 #include <libscf.h> 50 #include <strings.h> 51 #include "libshare_smbfs.h" 52 #include <rpcsvc/daemon_utils.h> 53 #include <arpa/inet.h> 54 #include <uuid/uuid.h> 55 #include <netsmb/smb_lib.h> 56 57 #define SMBFS_PROTOCOL_NAME "smbfs" 58 59 /* internal functions */ 60 static uint64_t smbfs_features(); 61 static int smbfs_init(); 62 static void smbfs_fini(); 63 static int smbfs_set_proto_prop(sa_property_t); 64 static sa_protocol_properties_t smbfs_get_proto_set(); 65 static char *smbfs_get_status(); 66 static int smbfs_delete_section(char *); 67 static int smbfs_delete_property_group(char *); 68 69 static int range_check_validator(int, char *, char *); 70 static int string_length_check_validator(int, char *, char *); 71 static int yes_no_validator(int, char *, char *); 72 static int ip_address_validator(int, char *, char *); 73 static int minauth_validator(int, char *, char *); 74 static int password_validator(int, char *, char *); 75 #ifdef NOT_DEFINED 76 static int nbscope_validator(int, char *, char *); 77 #endif 78 79 int propset_changed = 0; 80 81 /* 82 * ops vector that provides the protocol specific info and operations 83 * for share management. 84 */ 85 86 struct sa_plugin_ops sa_plugin_ops = { 87 SA_PLUGIN_VERSION, 88 SMBFS_PROTOCOL_NAME, 89 smbfs_init, 90 smbfs_fini, 91 NULL, /* share */ 92 NULL, /* unshare */ 93 NULL, /* valid_prop */ 94 NULL, /* valid_space */ 95 NULL, /* security_prop */ 96 NULL, /* legacy_opts */ 97 NULL, /* legacy_format */ 98 smbfs_set_proto_prop, 99 smbfs_get_proto_set, 100 smbfs_get_status, 101 NULL, /* space_alias */ 102 NULL, /* update_legacy */ 103 NULL, /* delete_legacy */ 104 NULL, /* change_notify */ 105 NULL, /* enable_resource */ 106 NULL, /* disable_resource */ 107 smbfs_features, 108 NULL, /* get_transient_shares */ 109 NULL, /* notify_resource */ 110 NULL, /* rename_resource */ 111 NULL, /* run_command */ 112 NULL, /* command_help */ 113 smbfs_delete_section, 114 }; 115 116 /* 117 * is_a_number(number) 118 * 119 * is the string a number in one of the forms we want to use? 120 */ 121 122 static int 123 is_a_number(char *number) 124 { 125 int ret = 1; 126 int hex = 0; 127 128 if (strncmp(number, "0x", 2) == 0) { 129 number += 2; 130 hex = 1; 131 } else if (*number == '-') { 132 number++; /* skip the minus */ 133 } 134 135 while (ret == 1 && *number != '\0') { 136 if (hex) { 137 ret = isxdigit(*number++); 138 } else { 139 ret = isdigit(*number++); 140 } 141 } 142 return (ret); 143 } 144 145 /* 146 * Protocol management functions 147 * 148 * properties defined in the default files are defined in 149 * proto_option_defs for parsing and validation. 150 */ 151 152 struct smbclnt_proto_option_defs smbclnt_proto_options[] = { 153 { "section", NULL, PROTO_OPT_SECTION, 154 0, 0, MAX_VALUE_BUFLEN, 155 string_length_check_validator}, 156 { "addr", NULL, PROTO_OPT_ADDR, 157 0, 0, MAX_VALUE_BUFLEN, 158 ip_address_validator}, 159 { "minauth", NULL, PROTO_OPT_MINAUTH, 160 0, 0, MAX_VALUE_BUFLEN, 161 minauth_validator}, 162 { "nbns_broadcast", NULL, PROTO_OPT_NBNS_BROADCAST, 163 0, 0, 0, 164 yes_no_validator}, 165 { "nbns_enable", NULL, PROTO_OPT_NBNS_ENABLE, 166 0, 0, 0, 167 yes_no_validator}, 168 { "nbns", NULL, PROTO_OPT_NBNSADDR, 169 0, 0, MAX_VALUE_BUFLEN, 170 ip_address_validator}, 171 { "password", NULL, PROTO_OPT_PASSWORD, 172 0, 0, MAX_VALUE_BUFLEN, 173 password_validator}, 174 { "timeout", NULL, PROTO_OPT_TIMEOUT, 175 0, 0, 60, 176 range_check_validator}, 177 { "user", NULL, PROTO_OPT_USER, 178 0, 0, MAX_VALUE_BUFLEN, 179 string_length_check_validator}, 180 { "domain", NULL, PROTO_OPT_DOMAIN, 181 0, 0, MAX_VALUE_BUFLEN, 182 string_length_check_validator}, 183 { "workgroup", NULL, PROTO_OPT_WORKGROUP, 184 0, 0, MAX_VALUE_BUFLEN, 185 string_length_check_validator}, 186 #ifdef NOT_DEFINED 187 { "nbscope", NULL, PROTO_OPT_NBSCOPE, 188 0, 0, MAX_VALUE_BUFLEN, 189 nbscope_validator}, 190 { "nbtimeout", NULL, PROTO_OPT_NBTIMEOUT, 191 0, 0, 60, 192 range_check_validator}, 193 { "retry_count", NULL, PROTO_OPT_RETRY_COUNT, 194 0, 0, 10, 195 range_check_validator}, 196 { "use_negprot_domain", NULL, PROTO_OPT_USE_NEGPROT_DOMAIN, 197 0, 0, 0, 198 yes_no_validator}, 199 { "charset", NULL, PROTO_OPT_CHARSETS, 200 0, 0, MAX_VALUE_BUFLEN, 201 ip_address_validator}, 202 #endif 203 {NULL} 204 }; 205 206 /* 207 * Check the range of value as int range. 208 */ 209 /*ARGSUSED*/ 210 static int 211 range_check_validator(int index, char *section, char *value) 212 { 213 int ret = SA_OK; 214 215 if (value == NULL) 216 return (SA_BAD_VALUE); 217 if (strlen(value) == 0) 218 return (SA_OK); 219 if (!is_a_number(value)) { 220 ret = SA_BAD_VALUE; 221 } else { 222 int val; 223 val = strtoul(value, NULL, 0); 224 if (val < smbclnt_proto_options[index].minval || 225 val > smbclnt_proto_options[index].maxval) 226 ret = SA_BAD_VALUE; 227 } 228 return (ret); 229 } 230 231 /* 232 * Check the length of the string 233 */ 234 /*ARGSUSED*/ 235 static int 236 string_length_check_validator(int index, char *section, char *value) 237 { 238 int ret = SA_OK; 239 240 if (value == NULL) 241 return (SA_BAD_VALUE); 242 if (strlen(value) == 0) 243 return (SA_OK); 244 if (strlen(value) > smbclnt_proto_options[index].maxval) 245 ret = SA_BAD_VALUE; 246 return (ret); 247 } 248 249 /* 250 * Check yes/no 251 */ 252 /*ARGSUSED*/ 253 static int 254 yes_no_validator(int index, char *section, char *value) 255 { 256 if (value == NULL) 257 return (SA_BAD_VALUE); 258 if (strlen(value) == 0) 259 return (SA_OK); 260 if ((strcasecmp(value, "yes") == 0) || 261 (strcasecmp(value, "no") == 0) || 262 (strcasecmp(value, "true") == 0) || 263 (strcasecmp(value, "false") == 0)) 264 return (SA_OK); 265 return (SA_BAD_VALUE); 266 } 267 268 /* 269 * Check IP address. 270 */ 271 /*ARGSUSED*/ 272 static int 273 ip_address_validator(int index, char *section, char *value) 274 { 275 int len; 276 277 if (value == NULL) 278 return (SA_BAD_VALUE); 279 len = strlen(value); 280 if (len == 0) 281 return (SA_OK); 282 if (len > MAX_VALUE_BUFLEN) 283 return (SA_BAD_VALUE); 284 return (SA_OK); 285 } 286 287 /*ARGSUSED*/ 288 static int 289 minauth_validator(int index, char *section, char *value) 290 { 291 if (value == NULL) 292 return (SA_BAD_VALUE); 293 if (strlen(value) == 0) 294 return (SA_OK); 295 if (strcmp(value, "kerberos") == 0 || 296 strcmp(value, "ntlmv2") == 0 || 297 strcmp(value, "ntlm") == 0 || 298 strcmp(value, "lm") == 0 || 299 strcmp(value, "none") == 0) 300 return (SA_OK); 301 else 302 return (SA_BAD_VALUE); 303 } 304 305 #ifdef NOT_DEFINED 306 /*ARGSUSED*/ 307 static int 308 nbscope_validator(int index, char *section, char *value) 309 { 310 /* 311 * XXX - not sure what's legal here. Looks like it's not 312 * used in nb_name_encode() right now anyway. 313 */ 314 return (SA_OK); 315 } 316 #endif 317 318 /*ARGSUSED*/ 319 static int 320 password_validator(int index, char *section, char *value) 321 { 322 char buffer[100]; 323 324 /* mangled passwords will start with this pattern */ 325 if (strlen(value) == 0) 326 return (SA_OK); 327 if (strncmp(value, "$$1", 3) != 0) 328 return (SA_PASSWORD_ENC); 329 if (smb_simpledecrypt(buffer, value) != 0) 330 return (SA_BAD_VALUE); 331 return (SA_OK); 332 } 333 334 335 /* 336 * the protoset holds the defined options so we don't have to read 337 * them multiple times 338 */ 339 sa_protocol_properties_t protoset; 340 341 static int 342 findprotoopt(char *name) 343 { 344 int i; 345 for (i = 0; smbclnt_proto_options[i].name != NULL; i++) { 346 if (strcasecmp(smbclnt_proto_options[i].name, name) == 0) 347 return (i); 348 } 349 return (-1); 350 } 351 352 /* 353 * Load the persistent settings from SMF. Each section is an SMF 354 * property group with an "S-" prefix and a UUID, and the section 355 * is itself a property which can have a more flexible name than 356 * a property group name can have. The section name need not be 357 * the first property, so we have to be a little flexible, but 358 * the change of name of the property groups is a reliable way 359 * to know that we're seeing a different section. 360 */ 361 int 362 smbclnt_config_load() 363 { 364 scf_simple_app_props_t *props = NULL; 365 scf_simple_prop_t *prop = NULL, *lastprop = NULL; 366 char *lastpgname = NULL, *pgname = NULL; 367 char *name = NULL, *value = NULL; 368 sa_property_t sect, node; 369 int pending = 0; 370 #ifdef DEBUG 371 char *sectname = NULL; 372 #endif 373 374 props = scf_simple_app_props_get(NULL, SMBC_DEFAULT_INSTANCE_FMRI); 375 if (props == NULL) 376 return (-1); 377 378 while ((prop = (scf_simple_prop_t *) 379 scf_simple_app_props_next(props, lastprop)) != NULL) { 380 381 /* Ignore properties that don't have our prefix */ 382 pgname = scf_simple_prop_pgname(prop); 383 if (strncmp("S-", pgname, 2) != 0) { 384 lastprop = prop; 385 continue; 386 } 387 388 /* Note property group name changes, which mark sections */ 389 if (lastpgname == NULL || strcmp(lastpgname, pgname) != 0) { 390 #ifdef DEBUG 391 if (pending) 392 fprintf(stderr, "smbclnt_config_load: " 393 "Ignoring empty section %s\n", sectname); 394 fprintf(stderr, "smbclnt_config_load: new pg=%s\n", 395 pgname); 396 #endif 397 sect = sa_create_section(NULL, pgname+2); 398 (void) xmlSetProp(sect, (xmlChar *)"type", 399 (xmlChar *)SMBFS_PROTOCOL_NAME); 400 if (lastpgname) 401 free(lastpgname); 402 lastpgname = strdup(pgname); 403 pending = 1; 404 } 405 name = scf_simple_prop_name(prop); 406 value = scf_simple_prop_next_astring(prop); 407 408 /* If we get a section name, apply it and consume it */ 409 if (strncmp("section", name, 7) == 0 && value != NULL) { 410 #ifdef DEBUG 411 if (sectname) 412 free(sectname); 413 sectname = strdup(value); 414 fprintf(stderr, "smbclnt_config_load: section=%s\n", 415 sectname); 416 #endif 417 (void) xmlSetProp(sect, (xmlChar *)"name", 418 (xmlChar *)value); 419 lastprop = prop; 420 continue; 421 } 422 #ifdef DEBUG 423 fprintf(stderr, "pg=%s, sect=%s, nm=%s, val=%s\n", 424 pgname, sectname ? sectname : "NULL", name, value); 425 #endif 426 /* 427 * If we have an ordinary property, add to the section. 428 * Also, if this is the first ordinary property, we 429 * can commit the non-empty section to the protoset. 430 */ 431 node = sa_create_property(name, value); 432 (void) sa_add_protocol_property(sect, node); 433 lastprop = prop; 434 if (pending) { 435 (void) sa_add_protocol_property(protoset, sect); 436 pending = 0; 437 } 438 } 439 scf_simple_app_props_free(props); 440 if (pending) { 441 #ifdef DEBUG 442 fprintf(stderr, "smbclnt_config_load: " 443 "Deleting empty section %s\n", sectname); 444 #endif 445 (void) smbfs_delete_property_group(lastpgname); 446 } 447 if (lastpgname) 448 free(lastpgname); 449 return (0); 450 } 451 452 /* 453 * Save the set of properties for a particular section, which is 454 * stored as a single property group. Properties will have been 455 * changed earlier by one or more calls to smbfs_save_property(), 456 * which only set the value in our array and marked them as 457 * SMBC_MODIFIED. 458 */ 459 int 460 smbfs_save_propset() 461 { 462 smb_scfhandle_t *handle = NULL; 463 char propgroup[256]; 464 char *section = smbclnt_proto_options[PROTO_OPT_SECTION].value; 465 char *uu = NULL; 466 uuid_t uuid; 467 int i, ret = 0; 468 sa_property_t propset; 469 int new = 0, nonnull = 0; 470 471 propset = sa_get_protocol_section(protoset, section); 472 (void) strncpy(propgroup, SMBC_PG_PREFIX, SMBC_PG_PREFIX_LEN); 473 propgroup[SMBC_PG_PREFIX_LEN] = '\0'; 474 uu = sa_get_property_attr(propset, "extra"); 475 if (uu != NULL) { 476 (void) strncat(propgroup, uu, UUID_PRINTABLE_STRING_LENGTH); 477 free(uu); 478 } else { 479 new = 1; 480 smbclnt_proto_options[PROTO_OPT_SECTION].flags |= SMBC_MODIFIED; 481 uuid_generate(uuid); 482 uuid_unparse(uuid, &propgroup[SMBC_PG_PREFIX_LEN]); 483 } 484 #ifdef DEBUG 485 fprintf(stderr, "smbfs_save_propset: %s pgname=%s\n", 486 new ? "new" : "old", propgroup); 487 #endif 488 489 handle = smb_smf_scf_init(SMBC_FMRI_PREFIX); 490 if (handle == NULL) { 491 return (1); 492 } 493 494 if ((ret = smb_smf_instance_create(handle, SMBC_FMRI_PREFIX, 495 SMBC_PG_INSTANCE)) != SMBC_SMF_OK) { 496 goto out; 497 } 498 499 if ((ret = smb_smf_create_instance_pgroup(handle, propgroup)) 500 != SMBC_SMF_OK) { 501 goto out; 502 } 503 504 if ((ret = smb_smf_start_transaction(handle)) != SMBC_SMF_OK) { 505 goto out; 506 } 507 508 for (i = PROTO_OPT_SECTION+1; i <= SMBC_OPT_MAX; i++) { 509 if ((smbclnt_proto_options[i].flags & SMBC_MODIFIED) == 0) 510 continue; 511 #ifdef DEBUG 512 fprintf(stderr, "smbfs_save_propset: saving " 513 "i=%d/name=%s/value=%s\n", i, 514 smbclnt_proto_options[i].name, 515 smbclnt_proto_options[i].value); 516 #endif 517 if (strcmp(smbclnt_proto_options[i].value, "") == 0) 518 ret = smb_smf_delete_property(handle, 519 smbclnt_proto_options[i].name); 520 else { 521 ret = smb_smf_set_string_property(handle, 522 smbclnt_proto_options[i].name, 523 smbclnt_proto_options[i].value); 524 nonnull = 1; 525 } 526 free(smbclnt_proto_options[i].value); 527 smbclnt_proto_options[i].value = NULL; 528 smbclnt_proto_options[i].flags &= ~SMBC_MODIFIED; 529 if (ret != SMBC_SMF_OK) 530 goto outtrans; 531 } 532 /* 533 * Suppress new, null entries by not saving the section name. 534 */ 535 if (!new || nonnull) { 536 #ifdef DEBUG 537 fprintf(stderr, "smbfs_save_propset: saving " 538 "i=%d/name=%s/value=%s\n", PROTO_OPT_SECTION, 539 smbclnt_proto_options[PROTO_OPT_SECTION].name, 540 smbclnt_proto_options[PROTO_OPT_SECTION].value); 541 #endif 542 ret = smb_smf_set_string_property(handle, 543 smbclnt_proto_options[PROTO_OPT_SECTION].name, 544 smbclnt_proto_options[PROTO_OPT_SECTION].value); 545 free(smbclnt_proto_options[PROTO_OPT_SECTION].value); 546 smbclnt_proto_options[PROTO_OPT_SECTION].value = NULL; 547 smbclnt_proto_options[PROTO_OPT_SECTION].flags &= 548 ~SMBC_MODIFIED; 549 } 550 propset_changed = 0; 551 552 outtrans: 553 ret = smb_smf_end_transaction(handle); 554 out: 555 smb_smf_scf_fini(handle); 556 return (ret); 557 } 558 559 /* 560 * initprotofromdefault() 561 * 562 * read the default file(s) and add the defined values to the 563 * protoset. Note that default values are known from the built in 564 * table in case the file doesn't have a definition. 565 */ 566 567 static int 568 initprotofromdefault() 569 { 570 protoset = sa_create_protocol_properties(SMBFS_PROTOCOL_NAME); 571 if (protoset == NULL) 572 return (SA_NO_MEMORY); 573 if (smbclnt_config_load() != 0) 574 return (SA_OK); 575 576 return (SA_OK); 577 } 578 579 /* 580 * 581 * smbfs_features() 582 * 583 * Report the plugin's features 584 */ 585 static uint64_t 586 smbfs_features() 587 { 588 return (SA_FEATURE_HAS_SECTIONS | SA_FEATURE_ADD_PROPERTIES); 589 } 590 591 /* 592 * smbfs_init() 593 * 594 * Initialize the smb plugin. 595 */ 596 597 static int 598 smbfs_init() 599 { 600 int ret = SA_OK; 601 602 if (sa_plugin_ops.sa_init != smbfs_init) { 603 return (SA_SYSTEM_ERR); 604 } 605 606 if (initprotofromdefault() != SA_OK) { 607 return (SA_SYSTEM_ERR); 608 } 609 610 return (ret); 611 } 612 613 /* 614 * smbfs_fini() 615 * 616 * uninitialize the smb plugin. Want to avoid memory leaks. 617 */ 618 619 static void 620 smbfs_fini() 621 { 622 if (propset_changed) 623 (void) smbfs_save_propset(); 624 } 625 626 /* 627 * smbfs_get_proto_set() 628 * 629 * Return an optionset with all the protocol specific properties in 630 * it. 631 */ 632 633 static sa_protocol_properties_t 634 smbfs_get_proto_set() 635 { 636 return (protoset); 637 } 638 639 /* 640 * smbfs_validate_proto_prop(index, name, value) 641 * 642 * Verify that the property specifed by name can take the new 643 * value. This is a sanity check to prevent bad values getting into 644 * the default files. 645 */ 646 static int 647 smbfs_validate_proto_prop(int index, char *section, char *name, char *value) 648 { 649 if ((section == NULL) || (name == NULL) || (index < 0)) 650 return (SA_BAD_VALUE); 651 652 if (smbclnt_proto_options[index].validator == NULL) 653 return (SA_OK); 654 655 return (smbclnt_proto_options[index].validator(index, section, value)); 656 } 657 658 /* 659 * Save a property to our array; it will be stored to SMF later by 660 * smbfs_save_propset(). 661 */ 662 int 663 smbfs_save_property(int index, char *section, char *value) 664 { 665 char *s; 666 667 if (index == PROTO_OPT_WORKGROUP) { 668 #ifdef DEBUG 669 fprintf(stderr, "smbfs_save_property: " 670 "index %d being mapped to %d\n", 671 index, PROTO_OPT_DOMAIN); 672 #endif 673 index = PROTO_OPT_DOMAIN; 674 } 675 #ifdef DEBUG 676 fprintf(stderr, "smbfs_save_property: " 677 "section=%s, index=%d, name=%s, value=%s\n", 678 section, index, smbclnt_proto_options[index].name, value); 679 #endif 680 propset_changed = 1; 681 s = strdup(section); 682 if (s == NULL) 683 return (-1); 684 smbclnt_proto_options[PROTO_OPT_SECTION].value = s; 685 s = strdup(value); 686 if (s == NULL) 687 return (-1); 688 smbclnt_proto_options[index].value = s; 689 smbclnt_proto_options[index].flags |= SMBC_MODIFIED; 690 return (0); 691 } 692 693 /* 694 * smbfs_set_proto_prop(prop) 695 * 696 * check that prop is valid. 697 */ 698 /*ARGSUSED*/ 699 static int 700 smbfs_set_proto_prop(sa_property_t prop) 701 { 702 int ret = SA_OK; 703 char *name; 704 char *value; 705 char *section; 706 int i = -1; 707 708 section = sa_get_property_attr(prop, "section"); 709 if (section == NULL) 710 return (SA_NO_SECTION); 711 name = sa_get_property_attr(prop, "type"); 712 value = sa_get_property_attr(prop, "value"); 713 if (name != NULL && value != NULL) { 714 i = findprotoopt(name); 715 if (i >= 0) { 716 ret = smbfs_validate_proto_prop(i, section, 717 name, value); 718 if (ret == SA_OK) { 719 if (smbfs_save_property(i, section, 720 value) != 0) { 721 ret = SA_SYSTEM_ERR; 722 errno = EIO; 723 } 724 } 725 } else 726 ret = SA_INVALID_NAME; 727 } 728 if (name != NULL) 729 sa_free_attr_string(name); 730 if (value != NULL) 731 sa_free_attr_string(value); 732 733 return (ret); 734 } 735 736 /* 737 * smbfs_get_status() 738 * 739 * What is the current status of the smbd? We use the SMF state here. 740 * Caller must free the returned value. 741 */ 742 743 static char * 744 smbfs_get_status() 745 { 746 char *state = "enabled"; 747 state = smf_get_state(SMBC_DEFAULT_INSTANCE_FMRI); 748 return (state != NULL ? state : strdup("-")); 749 } 750 751 /* 752 * Delete a section by its name, which we will have read into an 753 * XML optionset above. We need to find it and find its UUID to 754 * be able to generate the property group name in order to call 755 * smbfs_delete_property_group(). 756 */ 757 static int 758 smbfs_delete_section(char *section) 759 { 760 char propgroup[256]; 761 char *uu = NULL; 762 sa_property_t propset; 763 int ret = SA_SYSTEM_ERR; 764 765 propset = sa_get_protocol_section(protoset, section); 766 (void) strncpy(propgroup, SMBC_PG_PREFIX, SMBC_PG_PREFIX_LEN); 767 propgroup[SMBC_PG_PREFIX_LEN] = '\0'; 768 uu = sa_get_property_attr(propset, "extra"); 769 if (uu == NULL) 770 goto out; 771 (void) strncat(propgroup, uu, UUID_PRINTABLE_STRING_LENGTH); 772 free(uu); 773 if ((ret = smbfs_delete_property_group(propgroup)) != SMBC_SMF_OK) 774 goto out; 775 ret = SA_OK; 776 out: 777 return (ret); 778 } 779 780 /* 781 * Delete a property group by its name. Called to do a 'delsect' 782 * or called when smbclnt_config_load() notices an empty section 783 * at the end of the properties. 784 */ 785 static int 786 smbfs_delete_property_group(char *propgroup) 787 { 788 smb_scfhandle_t *handle = NULL; 789 int ret = SA_SYSTEM_ERR; 790 791 #ifdef DEBUG 792 fprintf(stderr, "smbfs_delete_property_group: pgname=%s\n", propgroup); 793 #endif 794 795 handle = smb_smf_scf_init(SMBC_FMRI_PREFIX); 796 if (handle == NULL) 797 goto out; 798 799 if ((ret = smb_smf_instance_create(handle, SMBC_FMRI_PREFIX, 800 SMBC_PG_INSTANCE)) != SMBC_SMF_OK) 801 goto out; 802 803 if ((ret = smb_smf_delete_instance_pgroup(handle, propgroup)) 804 != SMBC_SMF_OK) 805 goto out; 806 ret = SA_OK; 807 out: 808 smb_smf_scf_fini(handle); 809 #ifdef DEBUG 810 fprintf(stderr, "smbfs_delete_property_group: returning %d\n", ret); 811 #endif 812 return (ret); 813 } 814