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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 #include "cfga_ib.h" 31 #include "cfga_conf.h" 32 #include <sys/stat.h> 33 34 /* 35 * cfga_conf.c 36 * 37 * This file supports adding/deleting/listing services from IBCONF_FILE. 38 */ 39 40 /* 41 * function prototypes: 42 */ 43 static ib_service_type_t ib_get_var_type(char *); 44 static ib_token_t ib_lex(char *, char **); 45 static void ib_find_eol(); 46 static int ib_get_string(char **, char *); 47 static int ib_service_record_add(char *, 48 ib_service_type_t); 49 static ib_token_t ib_get_services(char **); 50 static boolean_t ib_cmp_service(); 51 static void ib_free_service_recs(void); 52 static int ib_cleanup_file(int); 53 static int ib_init_file(char **); 54 int ib_add_service(char **); 55 int ib_delete_service(char **); 56 int ib_list_services(struct cfga_msg *, char **); 57 static cfga_ib_ret_t ib_conf_control_ioctl(char *, uint_t); 58 static int ib_service_record_valid(char *); 59 60 extern void cfga_msg(struct cfga_msg *, const char *); 61 62 63 /* Global variables */ 64 65 /* 66 * supported "name=value" pairs from IBCONF_FILE 67 */ 68 static ibcfg_var_t ibcfg_varlist[] = { 69 { "name", IB_NAME }, 70 { "class", IB_CLASS }, 71 { "port-svc-list", IB_PORT_SERVICE }, 72 { "vppa-svc-list", IB_VPPA_SERVICE }, 73 { "hca-svc-list", IB_HCASVC_SERVICE }, 74 { NULL, IB_NONE } 75 }; 76 77 static char ibconf_file[] = IBCONF_FILE; /* file being read */ 78 static int ibcfg_linenum = 1; /* track line#s */ 79 static int ibcfg_cntr = 0; /* current char read */ 80 static int ibcfg_brec = 0; /* beginning of rec */ 81 static int bvpparec = 0; /* begin of vppa rec */ 82 static int bportrec = 0; /* begin of port rec */ 83 static int bhcarec = 0; /* begin of HCA rec */ 84 static int ibcfg_btoken = 0; /* begin of new token */ 85 static mutex_t ibcfg_lock = DEFAULTMUTEX; /* lock for the file */ 86 static int ibcfg_fd = -1; /* file descriptor */ 87 static int ibcfg_tmpfd = 0; /* tmp file "fd" */ 88 static char *file_buf = (char *)NULL; /* read file into buf */ 89 static char *tmpnamef = (char *)NULL; /* tmp file name */ 90 static boolean_t wrote_tmp = B_FALSE; /* tmp file write in */ 91 /* progress indicator */ 92 static struct stat ibcfg_st; /* file stat struct */ 93 94 static int ibcfg_nport_services; /* # of PORT services */ 95 static int ibcfg_nvppa_services; /* # of VPPA services */ 96 static int ibcfg_nhca_services; /* # of HCA services */ 97 static ib_svc_rec_t *ibcfg_vppa_head; /* VPPA service recs */ 98 static ib_svc_rec_t *ibcfg_port_head; /* PORT service recs */ 99 static ib_svc_rec_t *ibcfg_hca_head; /* HCA service recs */ 100 101 extern char *service_name; /* service name */ 102 extern ib_service_type_t service_type; /* service type */ 103 104 105 /* 106 * Function: 107 * ib_get_var_type 108 * Input: 109 * str - A parsed string from IBCONF_FILE 110 * Output: 111 * NONE 112 * Returns: 113 * Service type 114 * Description: 115 * Returns the field from the token 116 */ 117 static ib_service_type_t 118 ib_get_var_type(char *str) 119 { 120 register ibcfg_var_t *cfgvar; 121 122 cfgvar = &ibcfg_varlist[0]; 123 while (cfgvar->type != IB_NONE) { 124 if (strcasecmp(cfgvar->name, str) == NULL) 125 break; 126 else 127 cfgvar++; 128 } 129 return (cfgvar->type); 130 } 131 132 133 /* 134 * Function: 135 * ib_lex 136 * Input: 137 * NONE 138 * Output: 139 * val - value just read 140 * errmsg - pointer to error message string, if there are any errors 141 * Returns: 142 * valid IB token 143 * Description: 144 * Read tokens from the IBCONF_FILE and parse them 145 */ 146 /* ARGSUSED */ 147 static ib_token_t 148 ib_lex(char *val, char **errmsg) 149 { 150 int ch, oval, badquote; 151 char *cp = val; 152 ib_token_t token; 153 154 while ((ch = GETC(file_buf, ibcfg_cntr)) == ' ' || ch == '\t'); 155 156 /* make a note of the beginning of token */ 157 ibcfg_btoken = ibcfg_cntr - 1; 158 159 *cp++ = (char)ch; 160 switch (ch) { 161 case '=': 162 token = EQUALS; 163 break; 164 case '&': 165 token = AMPERSAND; 166 break; 167 case '|': 168 token = BIT_OR; 169 break; 170 case '*': 171 token = STAR; 172 break; 173 case '#': 174 token = POUND; 175 break; 176 case ':': 177 token = COLON; 178 break; 179 case ';': 180 token = SEMICOLON; 181 break; 182 case ',': 183 token = COMMA; 184 break; 185 case '/': 186 token = SLASH; 187 break; 188 case ' ': 189 case '\t': 190 case '\f': 191 while ((ch = GETC(file_buf, ibcfg_cntr)) == ' ' || 192 ch == '\t' || ch == '\f') 193 *cp++ = (char)ch; 194 (void) UNGETC(ibcfg_cntr); 195 token = WHITE_SPACE; 196 break; 197 case '\n': 198 case '\r': 199 token = NEWLINE; 200 break; 201 case '"': 202 cp--; 203 badquote = 0; 204 while (!badquote && (ch = GETC(file_buf, ibcfg_cntr)) != '"') { 205 switch (ch) { 206 case '\n': 207 case -1: 208 (void) snprintf(*errmsg, MAXPATHLEN, 209 "Missing \""); 210 cp = val; 211 *cp++ = '\n'; 212 badquote = 1; 213 /* since we consumed the newline/EOF */ 214 (void) UNGETC(ibcfg_cntr); 215 break; 216 217 case '\\': 218 ch = (char)GETC(file_buf, ibcfg_cntr); 219 if (!isdigit(ch)) { 220 /* escape the character */ 221 *cp++ = (char)ch; 222 break; 223 } 224 oval = 0; 225 while (ch >= '0' && ch <= '7') { 226 ch -= '0'; 227 oval = (oval << 3) + ch; 228 ch = (char)GETC(file_buf, ibcfg_cntr); 229 } 230 (void) UNGETC(ibcfg_cntr); 231 /* check for character overflow? */ 232 if (oval > 127) { 233 (void) snprintf(*errmsg, MAXPATHLEN, 234 "Character overflow detected.\n"); 235 } 236 *cp++ = (char)oval; 237 break; 238 default: 239 *cp++ = (char)ch; 240 break; 241 } 242 } 243 token = STRING; 244 break; 245 default: 246 if (ch == -1) { 247 token = EOF; 248 break; 249 } 250 /* 251 * detect a lone '-' (including at the end of a line), and 252 * identify it as a 'name' 253 */ 254 if (ch == '-') { 255 *cp++ = (char)(ch = GETC(file_buf, ibcfg_cntr)); 256 if (iswhite(ch) || (ch == '\n')) { 257 (void) UNGETC(ibcfg_cntr); 258 cp--; 259 token = NAME; 260 break; 261 } 262 } else if (isunary(ch)) { 263 *cp++ = (char)(ch = GETC(file_buf, ibcfg_cntr)); 264 } 265 266 if (isdigit(ch)) { 267 if (ch == '0') { 268 if ((ch = GETC(file_buf, ibcfg_cntr)) == 'x') { 269 *cp++ = (char)ch; 270 ch = GETC(file_buf, ibcfg_cntr); 271 while (isxdigit(ch)) { 272 *cp++ = (char)ch; 273 ch = GETC(file_buf, ibcfg_cntr); 274 } 275 (void) UNGETC(ibcfg_cntr); 276 token = HEXVAL; 277 } else { 278 goto digit; 279 } 280 } else { 281 ch = GETC(file_buf, ibcfg_cntr); 282 digit: 283 while (isdigit(ch)) { 284 *cp++ = (char)ch; 285 ch = GETC(file_buf, ibcfg_cntr); 286 } 287 (void) UNGETC(ibcfg_cntr); 288 token = DECVAL; 289 } 290 } else if (isalpha(ch) || ch == '\\') { 291 if (ch != '\\') { 292 ch = GETC(file_buf, ibcfg_cntr); 293 } else { 294 /* 295 * if the character was a backslash, 296 * back up so we can overwrite it with 297 * the next (i.e. escaped) character. 298 */ 299 cp--; 300 } 301 302 while (isnamechar(ch) || ch == '\\') { 303 if (ch == '\\') 304 ch = GETC(file_buf, ibcfg_cntr); 305 *cp++ = (char)ch; 306 ch = GETC(file_buf, ibcfg_cntr); 307 } 308 (void) UNGETC(ibcfg_cntr); 309 token = NAME; 310 } else 311 return (-1); 312 break; 313 } 314 *cp = '\0'; 315 return (token); 316 } 317 318 319 /* 320 * Function: 321 * ib_find_eol 322 * Input: 323 * NONE 324 * Output: 325 * NONE 326 * Returns: 327 * NONE 328 * Description: 329 * Leave NEWLINE as the next character. 330 */ 331 static void 332 ib_find_eol() 333 { 334 int ch; 335 336 while ((ch = GETC(file_buf, ibcfg_cntr)) != -1) { 337 if (isnewline(ch)) { 338 (void) UNGETC(ibcfg_cntr); 339 break; 340 } 341 } 342 } 343 344 345 /* 346 * Function: 347 * ib_get_string 348 * Input: 349 * tchar - name of the string 350 * Output: 351 * llptr - Valid string 352 * Returns: 353 * 1 for success, NULL for errors. 354 * Description: 355 * The next item on the line is a string value. Allocate memory for 356 * it and copy the string. Return 1, and set arg ptr to newly allocated 357 * and initialized buffer, or NULL if an error occurs. 358 */ 359 static int 360 ib_get_string(char **llptr, char *tchar) 361 { 362 int tlen = strlen(tchar); 363 char *cp; 364 char *start = (char *)0; 365 366 start = tchar; 367 /* copy string */ 368 if ((cp = (char *)calloc(tlen + 1, sizeof (char))) == (char *)NULL) { 369 *llptr = NULL; 370 return (0); 371 } 372 bzero(cp, tlen + 1); 373 374 *llptr = cp; 375 for (; tlen > 0; tlen--) { 376 /* convert some common escape sequences */ 377 if (*start == '\\') { 378 switch (*(start + 1)) { 379 case 't': 380 /* tab */ 381 *cp++ = '\t'; 382 tlen--; 383 start += 2; 384 break; 385 case 'n': 386 /* new line */ 387 *cp++ = '\n'; 388 tlen--; 389 start += 2; 390 break; 391 case 'b': 392 /* back space */ 393 *cp++ = '\b'; 394 tlen--; 395 start += 2; 396 break; 397 default: 398 /* simply copy it */ 399 *cp++ = *start++; 400 break; 401 } 402 } else { 403 *cp++ = *start++; 404 } 405 } 406 *cp = '\0'; 407 return (1); 408 } 409 410 411 /* 412 * Function: 413 * ib_service_record_add 414 * Input: 415 * service - name of the service 416 * type - type of the service 417 * Output: 418 * rec - one valid service record 419 * Returns: 420 * CFGA_IB_OK on success or an appropriate error 421 * Description: 422 * Add one record to internal data structures 423 */ 424 static int 425 ib_service_record_add(char *service, ib_service_type_t type) 426 { 427 ib_svc_rec_t *tmp, *recp; 428 429 DPRINTF("ib_service_record_add: (%x, %s) " 430 "(#port = %d #vppa = %d #hca = %d)\n", type, service, 431 ibcfg_nport_services, ibcfg_nvppa_services, 432 ibcfg_nhca_services); 433 recp = (ib_svc_rec_t *)calloc(1, sizeof (ib_svc_rec_t)); 434 if (recp == NULL) 435 return (CFGA_IB_ALLOC_FAIL); 436 437 recp->type = type; 438 recp->name = strdup((char *)service); 439 if (type == IB_PORT_SERVICE) { 440 if (ibcfg_port_head) { 441 for (tmp = ibcfg_port_head; tmp->next != NULL; ) 442 tmp = tmp->next; 443 tmp->next = recp; 444 } else 445 ibcfg_port_head = recp; 446 ibcfg_nport_services++; 447 } else if (type == IB_VPPA_SERVICE) { 448 if (ibcfg_vppa_head) { 449 for (tmp = ibcfg_vppa_head; tmp->next != NULL; ) 450 tmp = tmp->next; 451 tmp->next = recp; 452 } else 453 ibcfg_vppa_head = recp; 454 ibcfg_nvppa_services++; 455 } else if (type == IB_HCASVC_SERVICE) { 456 if (ibcfg_hca_head) { 457 for (tmp = ibcfg_hca_head; tmp->next != NULL; ) 458 tmp = tmp->next; 459 tmp->next = recp; 460 } else 461 ibcfg_hca_head = recp; 462 ibcfg_nhca_services++; 463 } 464 465 return (CFGA_IB_OK); 466 } 467 468 469 /* 470 * Function: 471 * ib_get_services 472 * Input: 473 * errmsg - Error message filled in case of a failure 474 * Output: 475 * rec - one valid service record 476 * Returns: 477 * CFGA_IB_OK on success or an appropriate error 478 * Description: 479 * Fetch one record from the IBCONF_FILE 480 */ 481 static ib_token_t 482 ib_get_services(char **errmsg) 483 { 484 char tokval[MAXLINESIZE]; 485 char *llptr; 486 boolean_t sor = B_TRUE; 487 ib_token_t token; 488 ib_service_type_t cfgvar; 489 ib_parse_state_t parse_state = IB_NEWVAR; 490 491 token = ib_lex(tokval, errmsg); 492 while ((token != EOF) && (token != SEMICOLON)) { 493 if (token == STAR || token == POUND) { 494 /* skip comments */ 495 ib_find_eol(); 496 } else if (token == NEWLINE) { 497 ibcfg_linenum++; 498 } else if (token == NAME || token == STRING) { 499 if (parse_state == IB_NEWVAR) { 500 cfgvar = ib_get_var_type(tokval); 501 if (cfgvar == IB_NONE) { 502 parse_state = IB_ERROR; 503 (void) snprintf(*errmsg, MAXPATHLEN, 504 "Syntax Error: Invalid type %s", 505 tokval); 506 } else { 507 /* Note the beginning of the entry */ 508 if (sor) { 509 ibcfg_brec = ibcfg_btoken; 510 sor = B_FALSE; 511 } 512 parse_state = IB_CONFIG_VAR; 513 if (cfgvar == IB_PORT_SERVICE) 514 bportrec = ibcfg_cntr + 1; 515 else if (cfgvar == IB_VPPA_SERVICE) 516 bvpparec = ibcfg_cntr + 1; 517 else if (cfgvar == IB_HCASVC_SERVICE) 518 bhcarec = ibcfg_cntr + 1; 519 } 520 521 } else if (parse_state == IB_VAR_VALUE) { 522 llptr = NULL; 523 if (ib_get_string(&llptr, tokval)) { 524 if ((cfgvar == IB_PORT_SERVICE) || 525 (cfgvar == IB_VPPA_SERVICE) || 526 (cfgvar == IB_HCASVC_SERVICE)) { 527 if (ib_service_record_valid( 528 llptr)) { 529 if (ib_service_record_add( 530 (char *)llptr, cfgvar) 531 != CFGA_IB_OK) 532 return (E_O_F); 533 parse_state = 534 IB_CONFIG_VAR; 535 } else { 536 parse_state = 537 IB_CONFIG_VAR; 538 } 539 } else if ((cfgvar == IB_NAME) || 540 (cfgvar == IB_CLASS)) { 541 free((char *)llptr); 542 parse_state = IB_NEWVAR; 543 } else { 544 free((char *)llptr); 545 parse_state = IB_ERROR; 546 } 547 } else { 548 parse_state = IB_ERROR; 549 (void) snprintf(*errmsg, MAXPATHLEN, 550 "Syntax Error: Invalid value %s " 551 "for type: %s\n", tokval, 552 ibcfg_varlist[cfgvar].name); 553 } 554 } else if (parse_state == IB_ERROR) { 555 /* just skip */ 556 DPRINTF("ib_get_services: ERROR\n"); 557 } else { 558 parse_state = IB_ERROR; 559 (void) snprintf(*errmsg, MAXPATHLEN, 560 "Syntax Error: at %s", tokval); 561 } 562 } else if (token == COMMA || token == EQUALS) { 563 if (parse_state == IB_CONFIG_VAR) { 564 if (cfgvar == IB_NONE) { 565 parse_state = IB_ERROR; 566 (void) snprintf(*errmsg, MAXPATHLEN, 567 "Syntax Error: unexpected '='"); 568 } else { 569 parse_state = IB_VAR_VALUE; 570 } 571 } else if (parse_state != IB_ERROR) { 572 (void) snprintf(*errmsg, MAXPATHLEN, 573 "Syntax Error: unexpected '='"); 574 parse_state = IB_ERROR; 575 } 576 } else { 577 (void) snprintf(*errmsg, MAXPATHLEN, 578 "Syntax Error: at: %s", tokval); 579 parse_state = IB_ERROR; 580 } 581 token = ib_lex(tokval, errmsg); 582 if (ib_get_var_type(tokval) != IB_NONE) 583 parse_state = IB_NEWVAR; 584 } 585 return (token); 586 } 587 588 /* 589 * Function: 590 * ib_cmp_service 591 * Input: 592 * NONE 593 * Output: 594 * NONE 595 * Returns: 596 * B_TRUE if this service is already seen. B_FALSE if not. 597 * Description: 598 * Compare the service just read from the services already seen. 599 * Check if this service was already seen or not. 600 */ 601 static boolean_t 602 ib_cmp_service() 603 { 604 ib_svc_rec_t *recp; 605 606 DPRINTF("ib_cmp_service: (%x, %s) " 607 "(#port = %d #vppa = %d #hca = %d)\n", service_type, 608 service_name, ibcfg_nport_services, ibcfg_nvppa_services, 609 ibcfg_nhca_services); 610 611 for (recp = ibcfg_port_head; recp != NULL; recp = recp->next) { 612 DPRINTF("ib_cmp_service:P usvc = %s, usvc_name = %s\n", 613 service_name, recp->name ? recp->name : "NONE"); 614 if (recp->name && strcmp(recp->name, service_name) == 0) 615 return (B_TRUE); 616 } 617 for (recp = ibcfg_vppa_head; recp != NULL; recp = recp->next) { 618 DPRINTF("ib_cmp_service:V utype = %x, usvc_name = %s\n", 619 recp->type, recp->name ? recp->name : "NONE"); 620 if (recp->name && strcmp(recp->name, service_name) == 0) 621 return (B_TRUE); 622 } 623 for (recp = ibcfg_hca_head; recp != NULL; recp = recp->next) { 624 DPRINTF("ib_cmp_service:V utype = %x, usvc_name = %s\n", 625 recp->type, recp->name ? recp->name : "NONE"); 626 if (recp->name && strcmp(recp->name, service_name) == 0) 627 return (B_TRUE); 628 } 629 630 return (B_FALSE); 631 } 632 633 634 /* 635 * Function: 636 * ib_free_service_recs 637 * Input: 638 * NONE 639 * Output: 640 * NONE 641 * Returns: 642 * CFGA_IB_OK on success or an appropriate error 643 * Description: 644 * Free the service records allocated in ib_get_services 645 */ 646 static void 647 ib_free_service_recs(void) 648 { 649 ib_svc_rec_t *tmp, *recp; 650 651 DPRINTF("ib_free_service_recs: " 652 "#port_services = %d, #vppa_services = %d, #hca_services = %d\n", 653 ibcfg_nport_services, ibcfg_nvppa_services, ibcfg_nhca_services); 654 655 for (recp = ibcfg_port_head; recp != NULL; ) { 656 if (recp && strlen(recp->name)) 657 S_FREE(recp->name); 658 tmp = recp; 659 recp = recp->next; 660 S_FREE(tmp); 661 } 662 663 for (recp = ibcfg_vppa_head; recp != NULL; ) { 664 if (recp && strlen(recp->name)) 665 S_FREE(recp->name); 666 tmp = recp; 667 recp = recp->next; 668 S_FREE(tmp); 669 } 670 671 for (recp = ibcfg_hca_head; recp != NULL; ) { 672 if (recp && strlen(recp->name)) 673 S_FREE(recp->name); 674 tmp = recp; 675 recp = recp->next; 676 S_FREE(tmp); 677 } 678 } 679 680 681 /* 682 * Function: 683 * ib_cleanup_file 684 * Input: 685 * rval - error return value 686 * Output: 687 * NONE 688 * Returns: 689 * CFGA_IB_OK on success or an appropriate error 690 * Description: 691 * Cleanup IBCONF_FILE etc. 692 */ 693 static int 694 ib_cleanup_file(int rval) 695 { 696 int rv = rval; 697 698 ib_free_service_recs(); 699 if (lockf(ibcfg_fd, F_ULOCK, 0) == -1) { 700 DPRINTF("ib_cleanup_file: unlock file %s failed\n", 701 ibconf_file); 702 rv = CFGA_IB_UNLOCK_FILE_ERR; 703 } 704 S_FREE(file_buf); 705 close(ibcfg_fd); 706 ibcfg_fd = -1; 707 if (ibcfg_tmpfd && wrote_tmp == B_TRUE) { 708 DPRINTF("ib_cleanup_file: tmpfile %s being renamed to %s\n", 709 tmpnamef, IBCONF_FILE); 710 close(ibcfg_tmpfd); 711 rename((const char *)tmpnamef, (const char *)IBCONF_FILE); 712 unlink(tmpnamef); 713 } 714 (void) mutex_unlock(&ibcfg_lock); 715 return (rv); 716 } 717 718 719 /* 720 * Function: 721 * ib_init_file 722 * Input: 723 * NONE 724 * Output: 725 * errmsg - Error message filled in case of a failure 726 * Returns: 727 * CFGA_IB_OK on success or an appropriate error 728 * Description: 729 * Initialize IBCONF_FILE for reading 730 */ 731 static int 732 ib_init_file(char **errmsg) 733 { 734 (void) mutex_lock(&ibcfg_lock); 735 736 if (*errmsg == (char *)NULL) { 737 if ((*errmsg = calloc(MAXPATHLEN, 1)) == (char *)NULL) { 738 (void) mutex_unlock(&ibcfg_lock); 739 DPRINTF("ib_init_file: calloc errmsg failed\n"); 740 return (CFGA_IB_CONFIG_FILE_ERR); 741 } 742 } 743 744 /* Open the .conf file */ 745 if ((ibcfg_fd = open(ibconf_file, O_RDWR, 0666)) == -1) { 746 (void) snprintf(*errmsg, MAXPATHLEN, 747 "failed to open %s file\n", ibconf_file); 748 (void) mutex_unlock(&ibcfg_lock); 749 return (CFGA_IB_CONFIG_FILE_ERR); 750 } 751 752 /* Lock the file so that another cfgadm instance doesn't modify it */ 753 if (lockf(ibcfg_fd, F_TLOCK, 0) == -1) { 754 (void) snprintf(*errmsg, MAXPATHLEN, 755 "failed to lock %s file\n", ibconf_file); 756 close(ibcfg_fd); 757 ibcfg_fd = -1; 758 (void) mutex_unlock(&ibcfg_lock); 759 return (CFGA_IB_LOCK_FILE_ERR); 760 } 761 762 if (fstat(ibcfg_fd, &ibcfg_st) != 0) { 763 DPRINTF("ib_init_file: failed to fstat %s file\n", ibconf_file); 764 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 765 } 766 767 /* Allocate a buffer for the file */ 768 if ((file_buf = (char *)malloc(ibcfg_st.st_size)) == NULL) { 769 DPRINTF("ib_init_file: failed to fstat %s file\n", 770 ibconf_file); 771 return (ib_cleanup_file(CFGA_IB_ALLOC_FAIL)); 772 } 773 774 /* Check if size matches */ 775 if (ibcfg_st.st_size != read(ibcfg_fd, file_buf, ibcfg_st.st_size)) { 776 DPRINTF("ib_init_file: failed to read %s file\n", ibconf_file); 777 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 778 } 779 780 /* 781 * These variables need to be reinitialized here as they may 782 * have been modified by a previous thread that called this 783 * function 784 */ 785 ibcfg_linenum = 1; 786 ibcfg_cntr = 0; 787 ibcfg_brec = 0; 788 ibcfg_btoken = 0; 789 790 ibcfg_nport_services = 0; 791 ibcfg_nvppa_services = 0; 792 ibcfg_nhca_services = 0; 793 ibcfg_port_head = (ib_svc_rec_t *)NULL; 794 ibcfg_vppa_head = (ib_svc_rec_t *)NULL; 795 ibcfg_hca_head = (ib_svc_rec_t *)NULL; 796 return (CFGA_IB_OK); 797 } 798 799 800 /* 801 * Function: 802 * ib_add_service 803 * Input: 804 * NONE 805 * Output: 806 * errmsg - Error message filled in case of a failure 807 * Returns: 808 * CFGA_IB_OK on success or an appropriate error 809 * Description: 810 * open IBCONF_FILE and add "service_name". 811 */ 812 int 813 ib_add_service(char **errmsg) 814 { 815 int rval; 816 char *sbuf; 817 boolean_t found = B_FALSE; 818 ib_token_t token = NEWLINE; 819 820 DPRINTF("ib_add_service: type = %x, service_name=%s\n", service_type, 821 service_name); 822 if ((rval = ib_init_file(errmsg)) != CFGA_IB_OK) { 823 DPRINTF("ib_add_service: initializing file failed\n"); 824 return (rval); 825 } 826 827 /* Start reading the file */ 828 while (token != EOF) { 829 token = ib_get_services(errmsg); 830 found = ib_cmp_service(); 831 if (found == B_TRUE) { 832 DPRINTF("ib_add_service: token=%x, found=%x\n", 833 token, found); 834 break; 835 } 836 } 837 838 /* Service shouldn't already exist while adding */ 839 if (found) { 840 (void) snprintf(*errmsg, MAXPATHLEN, "service entry %s exists ", 841 service_name); 842 DPRINTF("ib_add_service: invalid add operation\n"); 843 return (ib_cleanup_file(CFGA_IB_SVC_EXISTS_ERR)); 844 } 845 846 DPRINTF("!FOUND and adding\n"); 847 switch (service_type) { 848 case IB_PORT_SERVICE : 849 ibcfg_brec = bportrec; 850 break; 851 case IB_VPPA_SERVICE : 852 ibcfg_brec = bvpparec; 853 break; 854 case IB_HCASVC_SERVICE : 855 ibcfg_brec = bhcarec; 856 break; 857 default : 858 DPRINTF("ib_add_service: invalid add operation\n"); 859 return (ib_cleanup_file(CFGA_IB_SVC_INVAL_ERR)); 860 } 861 862 863 if ((sbuf = (char *)calloc(12, sizeof (char))) == NULL) { 864 DPRINTF("ib_add_service: failed to calloc sbuf %s file\n", 865 ibconf_file); 866 return (ib_cleanup_file(CFGA_IB_ALLOC_FAIL)); 867 } 868 if (file_buf[ibcfg_brec] == '"' && file_buf[ibcfg_brec + 1] == '"') { 869 (void) snprintf(sbuf, 9, "%s", service_name); 870 ibcfg_brec += 1; 871 } else 872 (void) snprintf(sbuf, 9, "\"%s\", ", service_name); 873 874 875 /* Seek to the beginning of the file */ 876 if (lseek(ibcfg_fd, ibcfg_brec, SEEK_SET) == -1) { 877 DPRINTF("ib_add_service: lseek %s file failed\n", ibconf_file); 878 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 879 } 880 881 /* Add service to w/ IBNEX */ 882 if (ib_conf_control_ioctl(service_name, IBNEX_CONF_ENTRY_ADD)) { 883 DPRINTF("ib_add_service: ioctl add failed %d\n", errno); 884 (void) snprintf(*errmsg, MAXPATHLEN, "failed to add " 885 "%s service incore ", service_name); 886 return (ib_cleanup_file(CFGA_IB_SVC_EXISTS_ERR)); 887 } 888 889 /* Write the modified file */ 890 if (write(ibcfg_fd, sbuf, strlen(sbuf)) == -1) { 891 DPRINTF("ib_add_service: write %s file failed\n", ibconf_file); 892 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 893 } 894 895 /* Write the rest of the file as it was */ 896 if (write(ibcfg_fd, file_buf + ibcfg_brec, 897 ibcfg_st.st_size - ibcfg_brec) == -1) { 898 DPRINTF("ib_add_service: write %s file failed 2\n", 899 ibconf_file); 900 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 901 } 902 903 return (ib_cleanup_file(rval)); 904 } 905 906 907 /* 908 * Function: 909 * ib_delete_service 910 * Input: 911 * NONE 912 * Output: 913 * errmsg - Error message filled in case of a failure 914 * Returns: 915 * CFGA_IB_OK on success or an appropriate error 916 * Description: 917 * open ib.conf file and delete "service_name" 918 */ 919 int 920 ib_delete_service(char **errmsg) 921 { 922 int rval; 923 int num_svcs; 924 int skip_len; 925 int sbuf_len; 926 int tot_len; 927 char tmp[12]; 928 char *sbuf = (char *)NULL; 929 boolean_t found = B_FALSE; 930 ib_token_t token = NEWLINE; 931 ib_svc_rec_t *recp; 932 933 DPRINTF("ib_delete_service: type = %x, service_name=%s\n", 934 service_type, service_name); 935 if ((rval = ib_init_file(errmsg)) != CFGA_IB_OK) { 936 DPRINTF("ib_delete_service: initializing file failed\n"); 937 return (rval); 938 } 939 940 /* Start reading the file */ 941 while (token != EOF) { 942 token = ib_get_services(errmsg); 943 found = ib_cmp_service(); /* search for a match */ 944 if (found == B_TRUE) { 945 DPRINTF("ib_delete_service: token=%x, found=%x\n", 946 token, found); 947 break; 948 } 949 } 950 951 /* No service found, return */ 952 if (!found) { 953 DPRINTF("ib_delete_service: invalid delete operation\n"); 954 (void) snprintf(*errmsg, MAXPATHLEN, "service entry %s " 955 "does not exist ", service_name); 956 return (ib_cleanup_file(CFGA_IB_SVC_NO_EXIST_ERR)); 957 } 958 959 DPRINTF("FOUND and deleting \n"); 960 961 switch (service_type) { 962 case IB_PORT_SERVICE : 963 ibcfg_brec = bportrec; 964 num_svcs = ibcfg_nport_services; 965 break; 966 case IB_VPPA_SERVICE : 967 ibcfg_brec = bvpparec; 968 num_svcs = ibcfg_nvppa_services; 969 break; 970 case IB_HCASVC_SERVICE : 971 ibcfg_brec = bhcarec; 972 num_svcs = ibcfg_nhca_services; 973 break; 974 default : 975 DPRINTF("ib_delete_service: invalid delete " 976 "operation\n"); 977 return (ib_cleanup_file(CFGA_IB_SVC_INVAL_ERR)); 978 } 979 980 if ((sbuf = (char *)calloc(num_svcs * 8, sizeof (char))) == NULL) { 981 DPRINTF("ib_delete_service: sbuf alloc failed %s\n", 982 ibconf_file); 983 return (ib_cleanup_file(CFGA_IB_ALLOC_FAIL)); 984 } 985 986 if (num_svcs == 1) { 987 (void) snprintf(sbuf, 9, "\"\"; "); 988 skip_len = 2; 989 } else { 990 if (service_type == IB_PORT_SERVICE) { 991 for (recp = ibcfg_port_head; recp; recp = recp->next) { 992 if (strcmp(recp->name, service_name) == 0) 993 continue; 994 (void) snprintf(tmp, 9, "\"%s\", ", recp->name); 995 (void) strcat(sbuf, tmp); 996 } 997 998 } else if (service_type == IB_VPPA_SERVICE) { 999 for (recp = ibcfg_vppa_head; recp; recp = recp->next) { 1000 if (strcmp(recp->name, service_name) == 0) 1001 continue; 1002 (void) snprintf(tmp, 9, "\"%s\", ", recp->name); 1003 (void) strcat(sbuf, tmp); 1004 } 1005 } else { 1006 for (recp = ibcfg_hca_head; recp; recp = recp->next) { 1007 if (strcmp(recp->name, service_name) == 0) 1008 continue; 1009 (void) snprintf(tmp, 9, "\"%s\", ", recp->name); 1010 (void) strcat(sbuf, tmp); 1011 } 1012 } 1013 skip_len = 4; 1014 } 1015 1016 tot_len = strlen(service_name) + skip_len; 1017 sbuf_len = strlen(sbuf); 1018 if (sbuf[sbuf_len - 2] == ',') 1019 sbuf[sbuf_len - 2] = ';'; 1020 1021 tmpnamef = tmpnam(ibconf_file); 1022 DPRINTF("ib_delete_service: tmpnamef = %s\n", tmpnamef); 1023 if ((ibcfg_tmpfd = creat(tmpnamef, 0666)) == -1) { 1024 (void) snprintf(*errmsg, MAXPATHLEN, 1025 "failed to creat %s file\n", ibconf_file); 1026 DPRINTF("ib_delete_service: failed to creat tmpnamef\n"); 1027 return (ib_cleanup_file(CFGA_IB_ALLOC_FAIL)); 1028 } 1029 1030 /* Delete service from IBNEX */ 1031 if (ib_conf_control_ioctl(service_name, IBNEX_CONF_ENTRY_DEL)) { 1032 DPRINTF("ib_delete_service: ioctl delete failed %d\n", errno); 1033 (void) snprintf(*errmsg, MAXPATHLEN, "failed to delete " 1034 "in core %s entry ", service_name); 1035 close(ibcfg_tmpfd); 1036 unlink(tmpnamef); 1037 return (ib_cleanup_file(CFGA_IB_SVC_EXISTS_ERR)); 1038 } 1039 1040 /* write till ibcfg_brec */ 1041 if (write(ibcfg_tmpfd, file_buf, ibcfg_brec) == -1) { 1042 DPRINTF("ib_delete_service: write %s file failed 1\n", 1043 ibconf_file); 1044 close(ibcfg_tmpfd); 1045 unlink(tmpnamef); 1046 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 1047 } 1048 1049 /* write modified buffer */ 1050 if (write(ibcfg_tmpfd, sbuf, sbuf_len) == -1) { 1051 DPRINTF("ib_delete_service: write %s file failed 2\n", 1052 ibconf_file); 1053 close(ibcfg_tmpfd); 1054 unlink(tmpnamef); 1055 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 1056 } 1057 1058 /* Write the rest of the file as it was */ 1059 if (write(ibcfg_tmpfd, file_buf + ibcfg_brec + sbuf_len + tot_len, 1060 ibcfg_st.st_size - ibcfg_brec - sbuf_len - skip_len) == -1) { 1061 DPRINTF("ib_delete_service: write %s file failed 3\n", 1062 ibconf_file); 1063 close(ibcfg_tmpfd); 1064 unlink(tmpnamef); 1065 return (ib_cleanup_file(CFGA_IB_CONFIG_FILE_ERR)); 1066 } 1067 wrote_tmp = B_TRUE; 1068 1069 /* No error encountered */ 1070 return (ib_cleanup_file(rval)); 1071 } 1072 1073 1074 /* 1075 * Function: 1076 * ib_list_services 1077 * Input: 1078 * msgp - CFGADM message pointer 1079 * Output: 1080 * errmsg - Error message filled in case of a failure 1081 * Returns: 1082 * CFGA_IB_OK on success or an appropriate error 1083 * Description: 1084 * open IBCONF_FILE and list services. 1085 */ 1086 int 1087 ib_list_services(struct cfga_msg *msgp, char **errmsg) 1088 { 1089 int rval = CFGA_IB_OK; 1090 char pbuf[IBCONF_SERVICE_HDR_LEN]; 1091 ib_token_t token = NEWLINE; 1092 ib_svc_rec_t *recp; 1093 1094 DPRINTF("ib_list_services:\n"); 1095 if ((rval = ib_init_file(errmsg)) != CFGA_IB_OK) { 1096 DPRINTF("ib_list_services: initializing file failed\n"); 1097 return (rval); 1098 } 1099 1100 /* start reading the file */ 1101 while (token != EOF) 1102 token = ib_get_services(errmsg); 1103 1104 DPRINTF("ib_list_services: #port_services = %d, #vppa_services = %d," 1105 " #hca_services = %d\n", ibcfg_nport_services, 1106 ibcfg_nvppa_services, ibcfg_nhca_services); 1107 1108 bzero(pbuf, IBCONF_SERVICE_HDR_LEN); 1109 if (ibcfg_nport_services) { 1110 (void) snprintf(pbuf, IBCONF_SERVICE_HDR_LEN, 1111 IBCONF_PORT_SERVICE_HDR); 1112 cfga_msg(msgp, pbuf); 1113 for (recp = ibcfg_port_head; recp; recp = recp->next) { 1114 DPRINTF("ib_list_services: svc_name = %s\n", 1115 recp->name ? recp->name : "NONE"); 1116 (void) snprintf(pbuf, 14, "\t\t%s\n", recp->name); 1117 cfga_msg(msgp, pbuf); 1118 } 1119 (void) snprintf(pbuf, 2, "\n"); 1120 cfga_msg(msgp, pbuf); 1121 } 1122 1123 if (ibcfg_nvppa_services) { 1124 (void) snprintf(pbuf, IBCONF_SERVICE_HDR_LEN, 1125 IBCONF_VPPA_SERVICE_HDR); 1126 cfga_msg(msgp, pbuf); 1127 for (recp = ibcfg_vppa_head; recp; recp = recp->next) { 1128 DPRINTF("ib_list_services: svc_name = %s\n", 1129 strlen(recp->name) > 0 ? recp->name : "NONE"); 1130 (void) snprintf(pbuf, 14, "\t\t%s\n", recp->name); 1131 cfga_msg(msgp, pbuf); 1132 } 1133 } 1134 1135 if (ibcfg_nhca_services) { 1136 (void) snprintf(pbuf, IBCONF_SERVICE_HDR_LEN, 1137 IBCONF_HCA_SERVICE_HDR); 1138 cfga_msg(msgp, pbuf); 1139 for (recp = ibcfg_hca_head; recp; recp = recp->next) { 1140 DPRINTF("ib_list_services: svc_name = %s\n", 1141 strlen(recp->name) > 0 ? recp->name : "NONE"); 1142 (void) snprintf(pbuf, 14, "\t\t%s\n", recp->name); 1143 cfga_msg(msgp, pbuf); 1144 } 1145 } 1146 return (ib_cleanup_file(CFGA_IB_OK)); 1147 } 1148 1149 1150 /* 1151 * Function: 1152 * ib_conf_control_ioctl 1153 * Input: 1154 * svc - Service being added/deleted 1155 * cmd - Command to DEVCTL_AP_CONTROL devctl 1156 * Output: 1157 * NONE 1158 * Returns: 1159 * CFGA_IB_OK if it succeeds or an appropriate error. 1160 * Description: 1161 * Issues DEVCTL_AP_CONTROL devctl with cmd 1162 */ 1163 static cfga_ib_ret_t 1164 ib_conf_control_ioctl(char *svc, uint_t cmd) 1165 { 1166 int apid_fd = -1; 1167 cfga_ib_ret_t rv = CFGA_IB_OK; 1168 struct ibnex_ioctl_data ioctl_data; 1169 1170 DPRINTF("Service = %s len = %x, type = %x\n", svc, 1171 strlen(svc), service_type); 1172 1173 /* try to open the static IB ap_id */ 1174 if ((apid_fd = open(IB_STATIC_APID, O_RDONLY)) == -1) { 1175 DPRINTF("ib_conf_control_ioctl: open failed: errno = %d\n", 1176 errno); 1177 /* Provides a more useful error msg */ 1178 rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_OPEN_ERR; 1179 return (rv); 1180 } 1181 1182 ioctl_data.cmd = cmd; 1183 ioctl_data.misc_arg = (uint_t)service_type; 1184 ioctl_data.buf = (caddr_t)svc; 1185 ioctl_data.bufsiz = strlen(svc); 1186 ioctl_data.ap_id = (caddr_t)IB_STATIC_APID; 1187 ioctl_data.ap_id_len = strlen(IB_STATIC_APID); 1188 1189 if (ioctl(apid_fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) { 1190 DPRINTF("ib_conf_control_ioctl: size ioctl ERR, errno: %d\n", 1191 errno); 1192 rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_IOCTL_ERR; 1193 } 1194 (void) close(apid_fd); 1195 return (rv); 1196 } 1197 1198 /* 1199 * This functions checks if the service name is valid. Valid 1200 * service names have : 1201 * 0 < strlen(name) <= 4 1202 * Service name is unique 1203 * Returns: 0 - Name is not valid, 1 - Name is valid 1204 */ 1205 static int 1206 ib_service_record_valid(char *sname) 1207 { 1208 int rc = 1, len; 1209 char *tmp_service_name; 1210 1211 tmp_service_name = service_name; 1212 service_name = strdup(sname); 1213 len = strlen(sname); 1214 if (len == 0 || len > 4) { 1215 S_FREE(service_name); 1216 service_name = tmp_service_name; 1217 return (0); 1218 } 1219 if (ib_cmp_service() == B_TRUE) 1220 rc = 0; 1221 S_FREE(service_name); 1222 service_name = tmp_service_name; 1223 return (rc); 1224 } 1225