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 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <ipsec_util.h> 32 #include <stdlib.h> 33 #include <strings.h> 34 #include <netdb.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <libintl.h> 38 #include <errno.h> 39 40 static char *preamble = 41 "# /etc/inet/ipsecalgs output from ipsecalgs(1m)\n" 42 "#\n" 43 "# DO NOT EDIT OR PARSE THIS FILE!\n" 44 "#\n" 45 "# Use the ipsecalgs(1m) command to change the contents of this file.\n" 46 "\n"; 47 48 #define CFG_PERMS S_IRUSR | S_IRGRP | S_IROTH /* Perms 0444. */ 49 #define CFG_OWNER 0 /* root */ 50 #define CFG_GROUP 1 /* "other" */ 51 52 /* 53 * write_new_algfile() helper macros to check for write errors. 54 */ 55 56 #define FPRINTF_ERR(fcall) if ((fcall) < 0) { \ 57 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \ 58 goto bail; \ 59 } 60 61 #define FPUT_ERR(fcall) if ((fcall) == EOF) { \ 62 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \ 63 goto bail; \ 64 } 65 66 /* 67 * Helper macros to start and finish a list of entries that were added 68 * as part of a package installation. 69 */ 70 71 #define PKG_SEC_START(pkgname, doing_pkg, cur_pkg) { \ 72 (void) strcpy((cur_pkg), (pkgname)); \ 73 FPRINTF_ERR(fprintf(f, "%s%s\n", \ 74 LIBIPSEC_ALGS_LINE_PKGSTART, (cur_pkg))); \ 75 (doing_pkg) = B_TRUE; \ 76 } 77 78 #define PKG_SEC_END(doing_pkg, cur_pkg) { \ 79 if (doing_pkg) { \ 80 FPRINTF_ERR(fprintf(f, "%s%s\n", \ 81 LIBIPSEC_ALGS_LINE_PKGEND, (cur_pkg))); \ 82 (doing_pkg) = B_FALSE; \ 83 } \ 84 } 85 86 /* 87 * Take a zero-terminated int array and print int1,int2...,intN. 88 * If zero-only, then print a single '0'. 89 * Returns 0 on success, -1 if an error occurred while writing to 90 * the specified file. 91 */ 92 int 93 list_ints(FILE *f, int *floater) 94 { 95 boolean_t executed = B_FALSE; 96 97 while (*floater != 0) { 98 executed = B_TRUE; 99 if (fprintf(f, "%d", *floater) < 0) 100 return (-1); 101 if (*(++floater) != 0) 102 if (fputc(',', f) == EOF) 103 return (-1); 104 } 105 106 if (!executed) 107 if (fputc('0', f) == EOF) 108 return (-1); 109 110 return (0); 111 } 112 113 /* 114 * If the specified algorithm was defined within a package section, i.e. 115 * between the lines "# Start <pkgname>" and "# End <pkgname>", returns 116 * the value of <pkgname>. 117 */ 118 static char * 119 alg_has_pkg(ipsec_proto_t *proto, struct ipsecalgent *alg) 120 { 121 int i; 122 123 if (proto->proto_algs_pkgs == NULL) 124 return (NULL); 125 126 for (i = 0; i < proto->proto_algs_npkgs; i++) 127 if (proto->proto_algs_pkgs[i].alg_num == alg->a_alg_num) 128 return (proto->proto_algs_pkgs[i].pkg_name); 129 130 return (NULL); 131 } 132 133 /* 134 * Writes the package start/end delimiters according to the package 135 * name associated with the current protocol or algorithm, and 136 * the state of the packaging information already written to the file. 137 * Called by write_new_algfile(). Returns 0 on success, one of the 138 * LIBIPSEC_DIAG codes on failure. 139 */ 140 static int 141 pkg_section(FILE *f, char *pkg_name, boolean_t *doing_pkg, char *cur_pkg) 142 { 143 int rc = 0; 144 145 if (pkg_name != NULL) { 146 /* protocol or algorithm is associated with a package */ 147 if (!*doing_pkg) { 148 /* start of a new package section */ 149 PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg); 150 } else { 151 /* already in a package section */ 152 if (strcmp(pkg_name, cur_pkg) != 0) { 153 /* different package name */ 154 PKG_SEC_END(*doing_pkg, cur_pkg); 155 PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg); 156 } 157 } 158 } else if (*doing_pkg) { 159 /* in a package section when the entry isn't */ 160 PKG_SEC_END(*doing_pkg, cur_pkg); 161 } 162 bail: 163 return (rc); 164 } 165 166 /* 167 * Given a list of protocols and number, write them to a new algorithm file. 168 * This function takes num_protos + num_protos * dois-per-alg operations. 169 * Also free the protocol structure. 170 * 171 * Note that no locking spans the read/update/write phases that can be 172 * used by callers of this routine. This could cause this function to suffer 173 * from the "lost update" problem. Since updates to the IPsec protocols 174 * and algorithm tables are very infrequent, this should not be a issue in 175 * practice. 176 */ 177 static int 178 write_new_algfile(ipsec_proto_t *protos, int num_protos) 179 { 180 FILE *f; 181 int fd, i, j, k; 182 int rc = 0; 183 struct ipsecalgent *alg; 184 char cur_pkg[1024]; 185 boolean_t doing_pkg = B_FALSE; 186 char *alg_pkg; 187 char *tmp_name_template = INET_IPSECALGSPATH "ipsecalgsXXXXXX"; 188 char *tmp_name; 189 190 /* 191 * In order to avoid potentially corrupting the configuration 192 * file on file system failure, write the new configuration info 193 * to a temporary file which is then renamed to the configuration 194 * file (INET_IPSECALGSFILE.) 195 */ 196 tmp_name = mktemp(tmp_name_template); 197 198 fd = open(tmp_name, O_WRONLY|O_CREAT|O_EXCL, CFG_PERMS); 199 if (fd == -1) { 200 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN; 201 goto bail; 202 } 203 204 f = fdopen(fd, "w"); 205 if (f == NULL) { 206 (void) close(fd); 207 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN; 208 goto bail; 209 } 210 211 FPUT_ERR(fputs(preamble, f)); 212 213 /* Write protocol entries. */ 214 for (i = 0; i < num_protos; i++) { 215 216 /* add package section delimiters if needed */ 217 rc = pkg_section(f, protos[i].proto_pkg, &doing_pkg, cur_pkg); 218 if (rc != 0) 219 goto bail; 220 221 FPRINTF_ERR(fprintf(f, "%s%d|%s|", 222 LIBIPSEC_ALGS_LINE_PROTO, 223 protos[i].proto_num, protos[i].proto_name)); 224 switch (protos[i].proto_exec_mode) { 225 case LIBIPSEC_ALGS_EXEC_SYNC: 226 FPRINTF_ERR(fprintf(f, "sync\n")); 227 break; 228 case LIBIPSEC_ALGS_EXEC_ASYNC: 229 FPRINTF_ERR(fprintf(f, "async\n")); 230 break; 231 } 232 } 233 234 /* terminate the package section for the protocols if needed */ 235 PKG_SEC_END(doing_pkg, cur_pkg); 236 237 FPUT_ERR(fputs("\n", f)); 238 239 /* Write algorithm entries. */ 240 241 for (i = 0; i < num_protos; i++) { 242 for (j = 0; j < protos[i].proto_numalgs; j++) { 243 alg = protos[i].proto_algs[j]; 244 245 /* add package section delimiters if needed */ 246 alg_pkg = alg_has_pkg(&protos[i], alg); 247 rc = pkg_section(f, alg_pkg, &doing_pkg, cur_pkg); 248 if (rc != 0) 249 goto bail; 250 251 /* protocol and algorithm numbers */ 252 FPRINTF_ERR(fprintf(f, "%s%d|%d|", 253 LIBIPSEC_ALGS_LINE_ALG, 254 alg->a_proto_num, alg->a_alg_num)); 255 256 /* algorithm names */ 257 for (k = 0; alg->a_names[k] != NULL; k++) { 258 FPRINTF_ERR(fprintf(f, "%s", alg->a_names[k])); 259 if (alg->a_names[k+1] != NULL) 260 FPRINTF_ERR(fprintf(f, ",")); 261 } 262 263 /* mechanism name */ 264 FPRINTF_ERR(fprintf(f, "|%s|", alg->a_mech_name)); 265 266 /* key sizes */ 267 if (alg->a_key_increment == 0) { 268 /* key sizes defined by enumeration */ 269 if (list_ints(f, alg->a_key_sizes) == -1) { 270 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; 271 goto bail; 272 } 273 } else { 274 /* key sizes defined by range */ 275 FPRINTF_ERR(fprintf(f, "%d/%d-%d,%d", 276 alg->a_key_sizes[0], alg->a_key_sizes[1], 277 alg->a_key_sizes[2], alg->a_key_increment)); 278 } 279 FPUT_ERR(fputc('|', f)); 280 281 /* block sizes */ 282 if (list_ints(f, alg->a_block_sizes) == -1) { 283 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; 284 goto bail; 285 } 286 FPUT_ERR(fputc('\n', f)); 287 } 288 } 289 290 /* terminate the package section for the algorithms if needed */ 291 PKG_SEC_END(doing_pkg, cur_pkg); 292 293 if (fchmod(fd, CFG_PERMS) == -1) { 294 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD; 295 goto bail; 296 } 297 if (fchown(fd, CFG_OWNER, CFG_GROUP) == -1) { 298 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN; 299 goto bail; 300 } 301 if (fclose(f) == EOF) { 302 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE; 303 goto bail; 304 } 305 306 if (rename(tmp_name, INET_IPSECALGSFILE) == -1) 307 rc = LIBIPSEC_ALGS_DIAG_ALGSFILERENAME; 308 309 bail: 310 _clean_trash(protos, num_protos); 311 return (rc); 312 } 313 314 /* 315 * Return a pointer to the protocol entry corresponding to the specified 316 * protocol num proto_num. Also builds the list of currently defined 317 * protocols. 318 */ 319 static ipsec_proto_t * 320 proto_setup(ipsec_proto_t **protos, int *num_protos, int proto_num, 321 boolean_t cleanup) 322 { 323 int i; 324 ipsec_proto_t *current_proto, *ret_proto = NULL; 325 326 _build_internal_algs(protos, num_protos); 327 328 if (*protos == NULL) 329 return (NULL); 330 331 for (i = 0; i < *num_protos; i++) { 332 current_proto = (*protos) + i; 333 if (current_proto->proto_num == proto_num) { 334 ret_proto = current_proto; 335 break; 336 } 337 } 338 339 if (ret_proto == NULL) { 340 if (cleanup) 341 _clean_trash(*protos, *num_protos); 342 /* else caller wants parsed /etc/inet/ipsecalgs anyway */ 343 } 344 345 return (ret_proto); 346 } 347 348 /* 349 * Delete the first found algorithm of the specified protocol which 350 * has the same name as the one specified by alg_name. Deletion of 351 * the entry takes place only if the delete_it flag is set. If an 352 * entry was found, return B_TRUE, otherwise return B_FALSE. 353 */ 354 static boolean_t 355 delipsecalgbyname_common(const char *name, ipsec_proto_t *proto, 356 boolean_t delete_it) 357 { 358 int i; 359 char **name_check; 360 boolean_t found_match = B_FALSE; 361 362 for (i = 0; i < proto->proto_numalgs; i++) { 363 if (!found_match) { 364 for (name_check = 365 proto->proto_algs[i]->a_names; 366 *name_check != NULL; name_check++) { 367 /* 368 * Can use strcmp because the algorithm names 369 * are bound. 370 */ 371 if (strcmp(*name_check, name) == 0) { 372 found_match = B_TRUE; 373 if (!delete_it) 374 return (found_match); 375 freeipsecalgent(proto->proto_algs[i]); 376 break; 377 } 378 } 379 } else { 380 proto->proto_algs[i - 1] = proto->proto_algs[i]; 381 } 382 } 383 384 if (found_match) 385 proto->proto_numalgs--; 386 387 return (found_match); 388 } 389 390 /* 391 * Returns B_TRUE if the specified 0-terminated lists of key or 392 * block sizes match, B_FALSE otherwise. 393 */ 394 static boolean_t 395 sizes_match(int *a1, int *a2) 396 { 397 int i; 398 399 for (i = 0; (a1[i] != 0) && (a2[i] != 0); i++) { 400 if (a1[i] != a2[i]) 401 return (B_FALSE); 402 } 403 if ((a1[i] != 0) || (a2[i] != 0)) 404 return (B_FALSE); 405 406 return (B_TRUE); 407 } 408 409 /* 410 * Returns B_TRUE if an _exact_ equivalent of the specified algorithm 411 * already exists, B_FALSE otherwise. 412 */ 413 static boolean_t 414 ipsecalg_exists(struct ipsecalgent *newbie, ipsec_proto_t *proto) 415 { 416 struct ipsecalgent *curalg; 417 char **curname, **newbiename; 418 int i; 419 boolean_t match; 420 421 for (i = 0; i < proto->proto_numalgs; i++) { 422 curalg = proto->proto_algs[i]; 423 424 if (curalg->a_alg_num != newbie->a_alg_num) 425 continue; 426 427 if (curalg->a_key_increment != newbie->a_key_increment) 428 continue; 429 430 if (strcmp(curalg->a_mech_name, newbie->a_mech_name) != 0) 431 continue; 432 433 curname = curalg->a_names; 434 newbiename = newbie->a_names; 435 match = B_TRUE; 436 while ((*curname != NULL) && (*newbiename != NULL) && match) { 437 match = (strcmp(*curname, *newbiename) == 0); 438 curname++; 439 newbiename++; 440 } 441 if (!match || (*curname != NULL) || (*newbiename != NULL)) 442 continue; 443 444 if (!sizes_match(curalg->a_block_sizes, newbie->a_block_sizes)) 445 continue; 446 447 if (!sizes_match(curalg->a_key_sizes, newbie->a_key_sizes)) 448 continue; 449 450 /* we found an exact match */ 451 return (B_TRUE); 452 } 453 454 return (B_FALSE); 455 } 456 457 /* 458 * Add a new algorithm to the /etc/inet/ipsecalgs file. Caller must free 459 * or otherwise address "newbie". 460 */ 461 int 462 addipsecalg(struct ipsecalgent *newbie, uint_t flags) 463 { 464 ipsec_proto_t *protos, *current_proto; 465 struct ipsecalgent *clone, **holder; 466 int num_protos, i; 467 char **name_check; 468 boolean_t forced_add = (flags & LIBIPSEC_ALGS_ADD_FORCE) != 0; 469 boolean_t found_match; 470 471 if ((current_proto = proto_setup(&protos, &num_protos, 472 newbie->a_proto_num, B_TRUE)) == NULL) 473 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 474 475 /* 476 * If an algorithm that matches _exactly_ the new algorithm 477 * already exists, we're done. 478 */ 479 if (ipsecalg_exists(newbie, current_proto)) 480 return (0); 481 482 /* 483 * We don't allow a new algorithm to be created if one of 484 * its names is already defined for an existing algorithm, 485 * unless the operation is forced, in which case existing 486 * algorithm entries that conflict with the new one are 487 * deleted. 488 */ 489 for (name_check = newbie->a_names; *name_check != NULL; name_check++) { 490 found_match = delipsecalgbyname_common(*name_check, 491 current_proto, forced_add); 492 if (found_match && !forced_add) { 493 /* 494 * Duplicate entry found, but the addition was 495 * not forced. 496 */ 497 _clean_trash(protos, num_protos); 498 return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS); 499 } 500 } 501 502 for (i = 0; i < current_proto->proto_numalgs; i++) { 503 if (current_proto->proto_algs[i]->a_alg_num == 504 newbie->a_alg_num) { 505 /* 506 * An algorithm with the same protocol number 507 * and algorithm number already exists. Fail 508 * addition unless the operation is forced. 509 */ 510 if (flags & LIBIPSEC_ALGS_ADD_FORCE) { 511 clone = _duplicate_alg(newbie); 512 if (clone != NULL) { 513 freeipsecalgent( 514 current_proto->proto_algs[i]); 515 current_proto->proto_algs[i] = clone; 516 return (write_new_algfile(protos, 517 num_protos)); 518 } else { 519 _clean_trash(protos, num_protos); 520 return (LIBIPSEC_ALGS_DIAG_NOMEM); 521 } 522 } else { 523 _clean_trash(protos, num_protos); 524 return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS); 525 } 526 } 527 } 528 529 /* append the new algorithm */ 530 holder = realloc(current_proto->proto_algs, 531 sizeof (struct ipsecalgent *) * (i + 1)); 532 if (holder == NULL) { 533 _clean_trash(protos, num_protos); 534 return (LIBIPSEC_ALGS_DIAG_NOMEM); 535 } 536 clone = _duplicate_alg(newbie); 537 if (clone == NULL) { 538 free(holder); 539 _clean_trash(protos, num_protos); 540 return (LIBIPSEC_ALGS_DIAG_NOMEM); 541 } 542 current_proto->proto_numalgs++; 543 current_proto->proto_algs = holder; 544 current_proto->proto_algs[i] = clone; 545 return (write_new_algfile(protos, num_protos)); 546 } 547 548 /* 549 * Delete an algorithm by name & protocol number from /etc/inet/ipsecalgs. 550 * Only deletes the first encountered instance. 551 */ 552 int 553 delipsecalgbyname(const char *name, int proto_num) 554 { 555 ipsec_proto_t *protos, *current_proto; 556 int num_protos; 557 558 if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 559 B_TRUE)) == NULL) 560 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 561 562 if (delipsecalgbyname_common(name, current_proto, B_TRUE)) 563 return (write_new_algfile(protos, num_protos)); 564 565 _clean_trash(protos, num_protos); 566 return (LIBIPSEC_ALGS_DIAG_UNKN_ALG); 567 } 568 569 /* 570 * Delete an algorithm by num + protocol num from /etc/inet/ipsecalgs. 571 */ 572 int 573 delipsecalgbynum(int alg_num, int proto_num) 574 { 575 ipsec_proto_t *protos, *current_proto; 576 int i, num_protos; 577 boolean_t found_match = B_FALSE; 578 579 if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 580 B_TRUE)) == NULL) 581 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 582 583 for (i = 0; i < current_proto->proto_numalgs; i++) { 584 if (!found_match) { 585 if (current_proto->proto_algs[i]->a_alg_num == 586 alg_num) { 587 found_match = B_TRUE; 588 freeipsecalgent(current_proto->proto_algs[i]); 589 } 590 } else { 591 current_proto->proto_algs[i - 1] = 592 current_proto->proto_algs[i]; 593 } 594 } 595 596 if (found_match) { 597 current_proto->proto_numalgs--; 598 return (write_new_algfile(protos, num_protos)); 599 } 600 601 _clean_trash(protos, num_protos); 602 return (LIBIPSEC_ALGS_DIAG_UNKN_ALG); 603 } 604 605 /* 606 * Remove the specified protocol entry from the list of protocols. 607 */ 608 static void 609 delipsecproto_common(ipsec_proto_t *protos, int num_protos, 610 ipsec_proto_t *proto) 611 { 612 int i; 613 614 /* free protocol storage */ 615 free(proto->proto_name); 616 for (i = 0; i < proto->proto_numalgs; i++) 617 freeipsecalgent(proto->proto_algs[i]); 618 619 /* remove from list of prototocols */ 620 for (i = (proto - protos + 1); i < num_protos; i++) 621 protos[i - 1] = protos[i]; 622 } 623 624 /* 625 * Add an IPsec protocol to /etc/inet/ipsecalgs. 626 */ 627 int 628 addipsecproto(const char *proto_name, int proto_num, 629 ipsecalgs_exec_mode_t proto_exec_mode, uint_t flags) 630 { 631 ipsec_proto_t *protos, *current_proto, *new_proto; 632 int i, num_protos; 633 634 /* 635 * NOTE:If build_internal_algs returns NULL for any 636 * reason, we will end up clobbering /etc/inet/ipsecalgs! 637 */ 638 639 current_proto = proto_setup(&protos, &num_protos, proto_num, B_FALSE); 640 641 /* check for protocol with duplicate id */ 642 if (current_proto != NULL) { 643 if ((strcmp(proto_name, current_proto->proto_name) == 0) && 644 (proto_exec_mode == current_proto->proto_exec_mode)) { 645 /* 646 * The current protocol being added matches 647 * exactly an existing protocol, we're done. 648 */ 649 return (0); 650 } 651 if (!(flags & LIBIPSEC_ALGS_ADD_FORCE)) 652 return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS); 653 delipsecproto_common(protos, num_protos--, current_proto); 654 } 655 656 /* check for protocol with duplicate name */ 657 for (i = 0; i < num_protos; i++) { 658 if (strcmp(protos[i].proto_name, proto_name) == 0) { 659 if (!(flags & LIBIPSEC_ALGS_ADD_FORCE)) 660 return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS); 661 delipsecproto_common(protos, num_protos--, &protos[i]); 662 break; 663 } 664 } 665 666 /* add new protocol */ 667 num_protos++; 668 new_proto = realloc(protos, num_protos * 669 sizeof (ipsec_proto_t)); 670 if (new_proto == NULL) { 671 _clean_trash(protos, num_protos - 1); 672 return (LIBIPSEC_ALGS_DIAG_NOMEM); 673 } 674 protos = new_proto; 675 new_proto += (num_protos - 1); 676 677 /* initialize protocol entry */ 678 new_proto->proto_num = proto_num; 679 new_proto->proto_numalgs = 0; 680 new_proto->proto_algs = NULL; 681 new_proto->proto_name = strdup(proto_name); 682 if (new_proto->proto_name == NULL) { 683 _clean_trash(protos, num_protos); 684 return (LIBIPSEC_ALGS_DIAG_NOMEM); 685 } 686 new_proto->proto_pkg = NULL; 687 new_proto->proto_algs_pkgs = NULL; 688 new_proto->proto_algs_npkgs = 0; 689 new_proto->proto_exec_mode = proto_exec_mode; 690 691 return (write_new_algfile(protos, num_protos)); 692 } 693 694 /* 695 * Delete an IPsec protocol entry from /etc/inet/ipsecalgs. This also 696 * nukes the associated algorithms. 697 */ 698 int 699 delipsecprotobynum(int proto_num) 700 { 701 ipsec_proto_t *protos, *current_proto; 702 int num_protos; 703 704 if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 705 B_TRUE)) == NULL) 706 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 707 708 delipsecproto_common(protos, num_protos--, current_proto); 709 710 return (write_new_algfile(protos, num_protos)); 711 } 712 713 int 714 delipsecprotobyname(const char *proto_name) 715 { 716 int proto_num; 717 718 proto_num = getipsecprotobyname(proto_name); 719 if (proto_num == -1) 720 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 721 722 return (delipsecprotobynum(proto_num)); 723 } 724 725 /* 726 * Implement these in libnsl since these are read-only operations. 727 */ 728 int * 729 getipsecprotos(int *nentries) 730 { 731 return (_real_getipsecprotos(nentries)); 732 } 733 734 int * 735 getipsecalgs(int *nentries, int proto_num) 736 { 737 return (_real_getipsecalgs(nentries, proto_num)); 738 } 739 740 const char * 741 ipsecalgs_diag(int diag) 742 { 743 switch (diag) { 744 case LIBIPSEC_ALGS_DIAG_ALG_EXISTS: 745 return (gettext("Algorithm already exists")); 746 case LIBIPSEC_ALGS_DIAG_PROTO_EXISTS: 747 return (gettext("Protocol already exists")); 748 case LIBIPSEC_ALGS_DIAG_UNKN_PROTO: 749 return (gettext("Unknown protocol")); 750 case LIBIPSEC_ALGS_DIAG_UNKN_ALG: 751 return (gettext("Unknown algorithm")); 752 case LIBIPSEC_ALGS_DIAG_NOMEM: 753 return (gettext("Out of memory")); 754 case LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN: 755 return (gettext("open() failed")); 756 case LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN: 757 return (gettext("fdopen() failed")); 758 case LIBIPSEC_ALGS_DIAG_ALGSFILELOCK: 759 return (gettext("lockf() failed")); 760 case LIBIPSEC_ALGS_DIAG_ALGSFILERENAME: 761 return (gettext("rename() failed")); 762 case LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE: 763 return (gettext("write to file failed")); 764 case LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD: 765 return (gettext("chmod() failed")); 766 case LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN: 767 return (gettext("chown() failed")); 768 case LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE: 769 return (gettext("close() failed")); 770 default: 771 return (gettext("failed")); 772 } 773 } 774 775 /* 776 * Get the execution mode corresponding to the specified protocol. 777 * Returns 0 on success, one of the LIBIPSEC_ALGS_DIAG_* values on 778 * failure. 779 */ 780 int 781 ipsecproto_get_exec_mode(int proto_num, ipsecalgs_exec_mode_t *exec_mode) 782 { 783 ipsec_proto_t *protos, *current_proto; 784 int num_protos; 785 786 if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 787 B_TRUE)) == NULL) 788 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 789 790 *exec_mode = current_proto->proto_exec_mode; 791 792 _clean_trash(protos, num_protos); 793 return (0); 794 } 795 796 /* 797 * Set the execution mode of the specified protocol. Returns 0 on success, 798 * or one of the LIBIPSEC_ALGS_DIAG_* values on failure. 799 */ 800 int 801 ipsecproto_set_exec_mode(int proto_num, ipsecalgs_exec_mode_t exec_mode) 802 { 803 ipsec_proto_t *protos, *current_proto; 804 int num_protos; 805 806 if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 807 B_TRUE)) == NULL) 808 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 809 810 current_proto->proto_exec_mode = exec_mode; 811 812 return (write_new_algfile(protos, num_protos)); 813 } 814