1 /* 2 * Copyright(c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 36 * Portions Copyright (c) 1996 by Internet Software Consortium. 37 * 38 * Permission to use, copy, modify, and distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 48 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 #if 0 52 53 Check values are in approrpriate endian order. 54 55 Double check memory allocations on unmarhsalling 56 57 #endif 58 59 60 /* Extern */ 61 62 #include "port_before.h" 63 64 #include <sys/types.h> 65 #include <sys/socket.h> 66 67 #include <netinet/in.h> 68 #include <arpa/inet.h> 69 #include <arpa/nameser.h> 70 71 #include <stdio.h> 72 #include <ctype.h> 73 #include <pwd.h> 74 #include <stdlib.h> 75 #include <string.h> 76 #include <syslog.h> 77 #include <utmp.h> 78 #include <unistd.h> 79 #include <assert.h> 80 #include <errno.h> 81 82 #include <irs.h> 83 #include <isc/memcluster.h> 84 #include <isc/irpmarshall.h> 85 86 #include "port_after.h" 87 88 89 #ifndef HAVE_STRNDUP 90 static char *strndup(const char *str, size_t len); 91 #endif 92 93 static char **splitarray(const char *buffer, const char *buffend, char delim); 94 static int joinarray(char * const * argv, char *buffer, char delim); 95 static char *getfield(char **res, size_t reslen, char **buffer, char delim); 96 static size_t joinlength(char * const *argv); 97 static void free_array(char **argv, size_t entries); 98 99 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ 100 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) 101 102 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) 103 104 static char COMMA = ','; 105 106 static const char *COMMASTR = ","; 107 static const char *COLONSTR = ":"; 108 109 110 111 /* See big comment at bottom of irpmarshall.h for description. */ 112 113 114 #ifdef WANT_IRS_PW 115 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ 116 117 /*% 118 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) 119 * 120 * notes: \li 121 * 122 * See irpmarshall.h 123 * 124 * return: \li 125 * 126 * 0 on sucess, -1 on failure. 127 * 128 */ 129 130 int 131 irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { 132 size_t need = 1 ; /*%< for null byte */ 133 char pwUid[24]; 134 char pwGid[24]; 135 char pwChange[24]; 136 char pwExpire[24]; 137 const char *pwClass; 138 const char *fieldsep = COLONSTR; 139 140 if (pw == NULL || len == NULL) { 141 errno = EINVAL; 142 return (-1); 143 } 144 145 sprintf(pwUid, "%ld", (long)pw->pw_uid); 146 sprintf(pwGid, "%ld", (long)pw->pw_gid); 147 148 #ifdef HAVE_PW_CHANGE 149 sprintf(pwChange, "%ld", (long)pw->pw_change); 150 #else 151 pwChange[0] = '0'; 152 pwChange[1] = '\0'; 153 #endif 154 155 #ifdef HAVE_PW_EXPIRE 156 sprintf(pwExpire, "%ld", (long)pw->pw_expire); 157 #else 158 pwExpire[0] = '0'; 159 pwExpire[1] = '\0'; 160 #endif 161 162 #ifdef HAVE_PW_CLASS 163 pwClass = pw->pw_class; 164 #else 165 pwClass = ""; 166 #endif 167 168 need += strlen(pw->pw_name) + 1; /*%< one for fieldsep */ 169 need += strlen(pw->pw_passwd) + 1; 170 need += strlen(pwUid) + 1; 171 need += strlen(pwGid) + 1; 172 need += strlen(pwClass) + 1; 173 need += strlen(pwChange) + 1; 174 need += strlen(pwExpire) + 1; 175 need += strlen(pw->pw_gecos) + 1; 176 need += strlen(pw->pw_dir) + 1; 177 need += strlen(pw->pw_shell) + 1; 178 179 if (buffer == NULL) { 180 *len = need; 181 return (0); 182 } 183 184 if (*buffer != NULL && need > *len) { 185 errno = EINVAL; 186 return (-1); 187 } 188 189 if (*buffer == NULL) { 190 need += 2; /*%< for CRLF */ 191 *buffer = memget(need); 192 if (*buffer == NULL) { 193 errno = ENOMEM; 194 return (-1); 195 } 196 197 *len = need; 198 } 199 200 strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep); 201 strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep); 202 strcat(*buffer, pwUid); strcat(*buffer, fieldsep); 203 strcat(*buffer, pwGid); strcat(*buffer, fieldsep); 204 strcat(*buffer, pwClass); strcat(*buffer, fieldsep); 205 strcat(*buffer, pwChange); strcat(*buffer, fieldsep); 206 strcat(*buffer, pwExpire); strcat(*buffer, fieldsep); 207 strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep); 208 strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep); 209 strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep); 210 211 return (0); 212 } 213 214 /*% 215 * int irp_unmarshall_pw(struct passwd *pw, char *buffer) 216 * 217 * notes: \li 218 * 219 * See irpmarshall.h 220 * 221 * return: \li 222 * 223 * 0 on success, -1 on failure 224 * 225 */ 226 227 int 228 irp_unmarshall_pw(struct passwd *pw, char *buffer) { 229 char *name, *pass, *class, *gecos, *dir, *shell; 230 uid_t pwuid; 231 gid_t pwgid; 232 time_t pwchange; 233 time_t pwexpire; 234 char *p; 235 long t; 236 char tmpbuf[24]; 237 char *tb = &tmpbuf[0]; 238 char fieldsep = ':'; 239 int myerrno = EINVAL; 240 241 name = pass = class = gecos = dir = shell = NULL; 242 p = buffer; 243 244 /* pw_name field */ 245 name = NULL; 246 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { 247 goto error; 248 } 249 250 /* pw_passwd field */ 251 pass = NULL; 252 if (getfield(&pass, 0, &p, fieldsep) == NULL) { /*%< field can be empty */ 253 goto error; 254 } 255 256 257 /* pw_uid field */ 258 tb = tmpbuf; 259 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 260 strlen(tb) == 0) { 261 goto error; 262 } 263 t = strtol(tmpbuf, &tb, 10); 264 if (*tb) { 265 goto error; /*%< junk in value */ 266 } 267 pwuid = (uid_t)t; 268 if ((long) pwuid != t) { /*%< value must have been too big. */ 269 goto error; 270 } 271 272 273 274 /* pw_gid field */ 275 tb = tmpbuf; 276 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 277 strlen(tb) == 0) { 278 goto error; 279 } 280 t = strtol(tmpbuf, &tb, 10); 281 if (*tb) { 282 goto error; /*%< junk in value */ 283 } 284 pwgid = (gid_t)t; 285 if ((long)pwgid != t) { /*%< value must have been too big. */ 286 goto error; 287 } 288 289 290 291 /* pw_class field */ 292 class = NULL; 293 if (getfield(&class, 0, &p, fieldsep) == NULL) { 294 goto error; 295 } 296 297 298 299 /* pw_change field */ 300 tb = tmpbuf; 301 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 302 strlen(tb) == 0) { 303 goto error; 304 } 305 t = strtol(tmpbuf, &tb, 10); 306 if (*tb) { 307 goto error; /*%< junk in value */ 308 } 309 pwchange = (time_t)t; 310 if ((long)pwchange != t) { /*%< value must have been too big. */ 311 goto error; 312 } 313 314 315 316 /* pw_expire field */ 317 tb = tmpbuf; 318 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 319 strlen(tb) == 0) { 320 goto error; 321 } 322 t = strtol(tmpbuf, &tb, 10); 323 if (*tb) { 324 goto error; /*%< junk in value */ 325 } 326 pwexpire = (time_t)t; 327 if ((long) pwexpire != t) { /*%< value must have been too big. */ 328 goto error; 329 } 330 331 332 333 /* pw_gecos field */ 334 gecos = NULL; 335 if (getfield(&gecos, 0, &p, fieldsep) == NULL) { 336 goto error; 337 } 338 339 340 341 /* pw_dir field */ 342 dir = NULL; 343 if (getfield(&dir, 0, &p, fieldsep) == NULL) { 344 goto error; 345 } 346 347 348 349 /* pw_shell field */ 350 shell = NULL; 351 if (getfield(&shell, 0, &p, fieldsep) == NULL) { 352 goto error; 353 } 354 355 356 357 pw->pw_name = name; 358 pw->pw_passwd = pass; 359 pw->pw_uid = pwuid; 360 pw->pw_gid = pwgid; 361 pw->pw_gecos = gecos; 362 pw->pw_dir = dir; 363 pw->pw_shell = shell; 364 365 #ifdef HAVE_PW_CHANGE 366 pw->pw_change = pwchange; 367 #endif 368 #ifdef HAVE_PW_CLASS 369 pw->pw_class = class; 370 #endif 371 #ifdef HAVE_PW_EXPIRE 372 pw->pw_expire = pwexpire; 373 #endif 374 375 return (0); 376 377 error: 378 errno = myerrno; 379 380 if (name != NULL) free(name); 381 if (pass != NULL) free(pass); 382 if (gecos != NULL) free(gecos); 383 if (dir != NULL) free(dir); 384 if (shell != NULL) free(shell); 385 386 return (-1); 387 } 388 389 /* ------------------------- struct passwd ------------------------- */ 390 #endif /* WANT_IRS_PW */ 391 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ 392 393 /*% 394 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) 395 * 396 * notes: \li 397 * 398 * See irpmarshall.h. 399 * 400 * return: \li 401 * 402 * 0 on success, -1 on failure 403 */ 404 405 int 406 irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) { 407 size_t need = 1; /*%< for null byte */ 408 char grGid[24]; 409 const char *fieldsep = COLONSTR; 410 411 if (gr == NULL || len == NULL) { 412 errno = EINVAL; 413 return (-1); 414 } 415 416 sprintf(grGid, "%ld", (long)gr->gr_gid); 417 418 need += strlen(gr->gr_name) + 1; 419 #ifndef MISSING_GR_PASSWD 420 need += strlen(gr->gr_passwd) + 1; 421 #else 422 need++; 423 #endif 424 need += strlen(grGid) + 1; 425 need += joinlength(gr->gr_mem) + 1; 426 427 if (buffer == NULL) { 428 *len = need; 429 return (0); 430 } 431 432 if (*buffer != NULL && need > *len) { 433 errno = EINVAL; 434 return (-1); 435 } 436 437 if (*buffer == NULL) { 438 need += 2; /*%< for CRLF */ 439 *buffer = memget(need); 440 if (*buffer == NULL) { 441 errno = ENOMEM; 442 return (-1); 443 } 444 445 *len = need; 446 } 447 448 strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep); 449 #ifndef MISSING_GR_PASSWD 450 strcat(*buffer, gr->gr_passwd); 451 #endif 452 strcat(*buffer, fieldsep); 453 strcat(*buffer, grGid); strcat(*buffer, fieldsep); 454 joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep); 455 456 return (0); 457 } 458 459 /*% 460 * int irp_unmarshall_gr(struct group *gr, char *buffer) 461 * 462 * notes: \li 463 * 464 * See irpmarshall.h 465 * 466 * return: \li 467 * 468 * 0 on success and -1 on failure. 469 * 470 */ 471 472 int 473 irp_unmarshall_gr(struct group *gr, char *buffer) { 474 char *p, *q; 475 gid_t grgid; 476 long t; 477 char *name = NULL; 478 char *pass = NULL; 479 char **members = NULL; 480 char tmpbuf[24]; 481 char *tb; 482 char fieldsep = ':'; 483 int myerrno = EINVAL; 484 485 if (gr == NULL || buffer == NULL) { 486 errno = EINVAL; 487 return (-1); 488 } 489 490 p = buffer; 491 492 /* gr_name field */ 493 name = NULL; 494 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 495 goto error; 496 } 497 498 499 /* gr_passwd field */ 500 pass = NULL; 501 if (getfield(&pass, 0, &p, fieldsep) == NULL) { 502 goto error; 503 } 504 505 506 /* gr_gid field */ 507 tb = tmpbuf; 508 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 509 strlen(tb) == 0U) { 510 goto error; 511 } 512 t = strtol(tmpbuf, &tb, 10); 513 if (*tb) { 514 goto error; /*%< junk in value */ 515 } 516 grgid = (gid_t)t; 517 if ((long) grgid != t) { /*%< value must have been too big. */ 518 goto error; 519 } 520 521 522 /* gr_mem field. Member names are separated by commas */ 523 q = strchr(p, fieldsep); 524 if (q == NULL) { 525 goto error; 526 } 527 members = splitarray(p, q, COMMA); 528 if (members == NULL) { 529 myerrno = errno; 530 goto error; 531 } 532 p = q + 1; 533 534 535 gr->gr_name = name; 536 #ifndef MISSING_GR_PASSWD 537 gr->gr_passwd = pass; 538 #endif 539 gr->gr_gid = grgid; 540 gr->gr_mem = members; 541 542 return (0); 543 544 error: 545 errno = myerrno; 546 547 if (name != NULL) free(name); 548 if (pass != NULL) free(pass); 549 550 return (-1); 551 } 552 553 554 /* ------------------------- struct group ------------------------- */ 555 556 557 558 559 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ 560 561 /*% 562 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) 563 * 564 * notes: \li 565 * 566 * See irpmarshall.h 567 * 568 * return: \li 569 * 570 * 0 on success, -1 on failure. 571 * 572 */ 573 574 int 575 irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) { 576 size_t need = 1; /*%< for null byte */ 577 char svPort[24]; 578 const char *fieldsep = COLONSTR; 579 short realport; 580 581 if (sv == NULL || len == NULL) { 582 errno = EINVAL; 583 return (-1); 584 } 585 586 /* the int s_port field is actually a short in network order. We 587 want host order to make the marshalled data look correct */ 588 realport = ntohs((short)sv->s_port); 589 sprintf(svPort, "%d", realport); 590 591 need += strlen(sv->s_name) + 1; 592 need += joinlength(sv->s_aliases) + 1; 593 need += strlen(svPort) + 1; 594 need += strlen(sv->s_proto) + 1; 595 596 if (buffer == NULL) { 597 *len = need; 598 return (0); 599 } 600 601 if (*buffer != NULL && need > *len) { 602 errno = EINVAL; 603 return (-1); 604 } 605 606 if (*buffer == NULL) { 607 need += 2; /*%< for CRLF */ 608 *buffer = memget(need); 609 if (*buffer == NULL) { 610 errno = ENOMEM; 611 return (-1); 612 } 613 614 *len = need; 615 } 616 617 strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep); 618 joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); 619 strcat(*buffer, svPort); strcat(*buffer, fieldsep); 620 strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep); 621 622 return (0); 623 } 624 625 /*% 626 * int irp_unmarshall_sv(struct servent *sv, char *buffer) 627 * 628 * notes: \li 629 * 630 * See irpmarshall.h 631 * 632 * return: \li 633 * 634 * 0 on success, -1 on failure. 635 * 636 */ 637 638 int 639 irp_unmarshall_sv(struct servent *sv, char *buffer) { 640 char *p, *q; 641 short svport; 642 long t; 643 char *name = NULL; 644 char *proto = NULL; 645 char **aliases = NULL; 646 char tmpbuf[24]; 647 char *tb; 648 char fieldsep = ':'; 649 int myerrno = EINVAL; 650 651 if (sv == NULL || buffer == NULL) 652 return (-1); 653 654 p = buffer; 655 656 657 /* s_name field */ 658 name = NULL; 659 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 660 goto error; 661 } 662 663 664 /* s_aliases field */ 665 q = strchr(p, fieldsep); 666 if (q == NULL) { 667 goto error; 668 } 669 aliases = splitarray(p, q, COMMA); 670 if (aliases == NULL) { 671 myerrno = errno; 672 goto error; 673 } 674 p = q + 1; 675 676 677 /* s_port field */ 678 tb = tmpbuf; 679 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 680 strlen(tb) == 0U) { 681 goto error; 682 } 683 t = strtol(tmpbuf, &tb, 10); 684 if (*tb) { 685 goto error; /*%< junk in value */ 686 } 687 svport = (short)t; 688 if ((long) svport != t) { /*%< value must have been too big. */ 689 goto error; 690 } 691 svport = htons(svport); 692 693 /* s_proto field */ 694 proto = NULL; 695 if (getfield(&proto, 0, &p, fieldsep) == NULL) { 696 goto error; 697 } 698 699 sv->s_name = name; 700 sv->s_aliases = aliases; 701 sv->s_port = svport; 702 sv->s_proto = proto; 703 704 return (0); 705 706 error: 707 errno = myerrno; 708 709 if (name != NULL) free(name); 710 if (proto != NULL) free(proto); 711 free_array(aliases, 0); 712 713 return (-1); 714 } 715 716 717 /* ------------------------- struct servent ------------------------- */ 718 719 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ 720 721 /*% 722 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) 723 * 724 * notes: \li 725 * 726 * See irpmarshall.h 727 * 728 * return: \li 729 * 730 * 0 on success and -1 on failure. 731 * 732 */ 733 734 int 735 irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) { 736 size_t need = 1; /*%< for null byte */ 737 char prProto[24]; 738 const char *fieldsep = COLONSTR; 739 740 if (pr == NULL || len == NULL) { 741 errno = EINVAL; 742 return (-1); 743 } 744 745 sprintf(prProto, "%d", (int)pr->p_proto); 746 747 need += strlen(pr->p_name) + 1; 748 need += joinlength(pr->p_aliases) + 1; 749 need += strlen(prProto) + 1; 750 751 if (buffer == NULL) { 752 *len = need; 753 return (0); 754 } 755 756 if (*buffer != NULL && need > *len) { 757 errno = EINVAL; 758 return (-1); 759 } 760 761 if (*buffer == NULL) { 762 need += 2; /*%< for CRLF */ 763 *buffer = memget(need); 764 if (*buffer == NULL) { 765 errno = ENOMEM; 766 return (-1); 767 } 768 769 *len = need; 770 } 771 772 strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep); 773 joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); 774 strcat(*buffer, prProto); strcat(*buffer, fieldsep); 775 776 return (0); 777 778 } 779 780 /*% 781 * int irp_unmarshall_pr(struct protoent *pr, char *buffer) 782 * 783 * notes: \li 784 * 785 * See irpmarshall.h 786 * 787 * return: \li 788 * 789 * 0 on success, -1 on failure 790 * 791 */ 792 793 int irp_unmarshall_pr(struct protoent *pr, char *buffer) { 794 char *p, *q; 795 int prproto; 796 long t; 797 char *name = NULL; 798 char **aliases = NULL; 799 char tmpbuf[24]; 800 char *tb; 801 char fieldsep = ':'; 802 int myerrno = EINVAL; 803 804 if (pr == NULL || buffer == NULL) { 805 errno = EINVAL; 806 return (-1); 807 } 808 809 p = buffer; 810 811 /* p_name field */ 812 name = NULL; 813 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 814 goto error; 815 } 816 817 818 /* p_aliases field */ 819 q = strchr(p, fieldsep); 820 if (q == NULL) { 821 goto error; 822 } 823 aliases = splitarray(p, q, COMMA); 824 if (aliases == NULL) { 825 myerrno = errno; 826 goto error; 827 } 828 p = q + 1; 829 830 831 /* p_proto field */ 832 tb = tmpbuf; 833 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 834 strlen(tb) == 0U) { 835 goto error; 836 } 837 t = strtol(tmpbuf, &tb, 10); 838 if (*tb) { 839 goto error; /*%< junk in value */ 840 } 841 prproto = (int)t; 842 if ((long) prproto != t) { /*%< value must have been too big. */ 843 goto error; 844 } 845 846 pr->p_name = name; 847 pr->p_aliases = aliases; 848 pr->p_proto = prproto; 849 850 return (0); 851 852 error: 853 errno = myerrno; 854 855 if (name != NULL) free(name); 856 free_array(aliases, 0); 857 858 return (-1); 859 } 860 861 /* ------------------------- struct protoent ------------------------- */ 862 863 864 865 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ 866 867 /*% 868 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) 869 * 870 * notes: \li 871 * 872 * See irpmarshall.h. 873 * 874 * return: \li 875 * 876 * 0 on success, -1 on failure. 877 * 878 */ 879 880 int 881 irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) { 882 size_t need = 1; /*%< for null byte */ 883 char hoaddrtype[24]; 884 char holength[24]; 885 char **av; 886 char *p; 887 int addrlen; 888 int malloced = 0; 889 size_t remlen; 890 const char *fieldsep = "@"; 891 892 if (ho == NULL || len == NULL) { 893 errno = EINVAL; 894 return (-1); 895 } 896 897 switch(ho->h_addrtype) { 898 case AF_INET: 899 strcpy(hoaddrtype, "AF_INET"); 900 break; 901 902 case AF_INET6: 903 strcpy(hoaddrtype, "AF_INET6"); 904 break; 905 906 default: 907 errno = EINVAL; 908 return (-1); 909 } 910 911 sprintf(holength, "%d", ho->h_length); 912 913 need += strlen(ho->h_name) + 1; 914 need += joinlength(ho->h_aliases) + 1; 915 need += strlen(hoaddrtype) + 1; 916 need += strlen(holength) + 1; 917 918 /* we determine an upper bound on the string length needed, not an 919 exact length. */ 920 addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /*%< XX other AF's?? */ 921 for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++) 922 need += addrlen; 923 924 if (buffer == NULL) { 925 *len = need; 926 return (0); 927 } 928 929 if (*buffer != NULL && need > *len) { 930 errno = EINVAL; 931 return (-1); 932 } 933 934 if (*buffer == NULL) { 935 need += 2; /*%< for CRLF */ 936 *buffer = memget(need); 937 if (*buffer == NULL) { 938 errno = ENOMEM; 939 return (-1); 940 } 941 942 *len = need; 943 malloced = 1; 944 } 945 946 strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep); 947 joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); 948 strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep); 949 strcat(*buffer, holength); strcat(*buffer, fieldsep); 950 951 p = *buffer + strlen(*buffer); 952 remlen = need - strlen(*buffer); 953 for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) { 954 if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) { 955 goto error; 956 } 957 if (*(av + 1) != NULL) 958 strcat(p, COMMASTR); 959 remlen -= strlen(p); 960 p += strlen(p); 961 } 962 strcat(*buffer, fieldsep); 963 964 return (0); 965 966 error: 967 if (malloced) { 968 memput(*buffer, need); 969 } 970 971 return (-1); 972 } 973 974 /*% 975 * int irp_unmarshall_ho(struct hostent *ho, char *buffer) 976 * 977 * notes: \li 978 * 979 * See irpmarshall.h. 980 * 981 * return: \li 982 * 983 * 0 on success, -1 on failure. 984 * 985 */ 986 987 int 988 irp_unmarshall_ho(struct hostent *ho, char *buffer) { 989 char *p, *q, *r; 990 int hoaddrtype; 991 int holength; 992 long t; 993 char *name; 994 char **aliases = NULL; 995 char **hohaddrlist = NULL; 996 size_t hoaddrsize; 997 char tmpbuf[24]; 998 char *tb; 999 char **alist; 1000 int addrcount; 1001 char fieldsep = '@'; 1002 int myerrno = EINVAL; 1003 1004 if (ho == NULL || buffer == NULL) { 1005 errno = EINVAL; 1006 return (-1); 1007 } 1008 1009 p = buffer; 1010 1011 /* h_name field */ 1012 name = NULL; 1013 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1014 goto error; 1015 } 1016 1017 1018 /* h_aliases field */ 1019 q = strchr(p, fieldsep); 1020 if (q == NULL) { 1021 goto error; 1022 } 1023 aliases = splitarray(p, q, COMMA); 1024 if (aliases == NULL) { 1025 myerrno = errno; 1026 goto error; 1027 } 1028 p = q + 1; 1029 1030 1031 /* h_addrtype field */ 1032 tb = tmpbuf; 1033 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1034 strlen(tb) == 0U) { 1035 goto error; 1036 } 1037 if (strcmp(tmpbuf, "AF_INET") == 0) 1038 hoaddrtype = AF_INET; 1039 else if (strcmp(tmpbuf, "AF_INET6") == 0) 1040 hoaddrtype = AF_INET6; 1041 else 1042 goto error; 1043 1044 1045 /* h_length field */ 1046 tb = tmpbuf; 1047 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1048 strlen(tb) == 0U) { 1049 goto error; 1050 } 1051 t = strtol(tmpbuf, &tb, 10); 1052 if (*tb) { 1053 goto error; /*%< junk in value */ 1054 } 1055 holength = (int)t; 1056 if ((long) holength != t) { /*%< value must have been too big. */ 1057 goto error; 1058 } 1059 1060 1061 /* h_addr_list field */ 1062 q = strchr(p, fieldsep); 1063 if (q == NULL) 1064 goto error; 1065 1066 /* count how many addresss are in there */ 1067 if (q > p + 1) { 1068 for (addrcount = 1, r = p ; r != q ; r++) { 1069 if (*r == COMMA) 1070 addrcount++; 1071 } 1072 } else { 1073 addrcount = 0; 1074 } 1075 1076 hoaddrsize = (addrcount + 1) * sizeof (char *); 1077 hohaddrlist = malloc(hoaddrsize); 1078 if (hohaddrlist == NULL) { 1079 myerrno = ENOMEM; 1080 goto error; 1081 } 1082 1083 memset(hohaddrlist, 0x0, hoaddrsize); 1084 1085 alist = hohaddrlist; 1086 for (t = 0, r = p ; r != q ; p = r + 1, t++) { 1087 char saved; 1088 while (r != q && *r != COMMA) r++; 1089 saved = *r; 1090 *r = 0x0; 1091 1092 alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); 1093 if (alist[t] == NULL) { 1094 myerrno = ENOMEM; 1095 goto error; 1096 } 1097 1098 if (inet_pton(hoaddrtype, p, alist[t]) == -1) 1099 goto error; 1100 *r = saved; 1101 } 1102 alist[t] = NULL; 1103 1104 ho->h_name = name; 1105 ho->h_aliases = aliases; 1106 ho->h_addrtype = hoaddrtype; 1107 ho->h_length = holength; 1108 ho->h_addr_list = hohaddrlist; 1109 1110 return (0); 1111 1112 error: 1113 errno = myerrno; 1114 1115 if (name != NULL) free(name); 1116 free_array(hohaddrlist, 0); 1117 free_array(aliases, 0); 1118 1119 return (-1); 1120 } 1121 1122 /* ------------------------- struct hostent------------------------- */ 1123 1124 1125 1126 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ 1127 1128 /*% 1129 * int irp_marshall_ng(const char *host, const char *user, 1130 * const char *domain, char *buffer, size_t *len) 1131 * 1132 * notes: \li 1133 * 1134 * See note for irp_marshall_ng_start 1135 * 1136 * return: \li 1137 * 1138 * 0 on success, 0 on failure. 1139 * 1140 */ 1141 1142 int 1143 irp_marshall_ng(const char *host, const char *user, const char *domain, 1144 char **buffer, size_t *len) { 1145 size_t need = 1; /*%< for nul byte */ 1146 const char *fieldsep = ","; 1147 1148 if (len == NULL) { 1149 errno = EINVAL; 1150 return (-1); 1151 } 1152 1153 need += 4; /*%< two parens and two commas */ 1154 need += (host == NULL ? 0 : strlen(host)); 1155 need += (user == NULL ? 0 : strlen(user)); 1156 need += (domain == NULL ? 0 : strlen(domain)); 1157 1158 if (buffer == NULL) { 1159 *len = need; 1160 return (0); 1161 } else if (*buffer != NULL && need > *len) { 1162 errno = EINVAL; 1163 return (-1); 1164 } 1165 1166 if (*buffer == NULL) { 1167 need += 2; /*%< for CRLF */ 1168 *buffer = memget(need); 1169 if (*buffer == NULL) { 1170 errno = ENOMEM; 1171 return (-1); 1172 } 1173 1174 *len = need; 1175 } 1176 1177 (*buffer)[0] = '('; 1178 (*buffer)[1] = '\0'; 1179 1180 if (host != NULL) 1181 strcat(*buffer, host); 1182 strcat(*buffer, fieldsep); 1183 1184 if (user != NULL) 1185 strcat(*buffer, user); 1186 strcat(*buffer, fieldsep); 1187 1188 if (domain != NULL) 1189 strcat(*buffer, domain); 1190 strcat(*buffer, ")"); 1191 1192 return (0); 1193 } 1194 1195 1196 1197 /* ---------- */ 1198 1199 /*% 1200 * int irp_unmarshall_ng(const char **host, const char **user, 1201 * const char **domain, char *buffer) 1202 * 1203 * notes: \li 1204 * 1205 * Unpacks the BUFFER into 3 character arrays it allocates and assigns 1206 * to *HOST, *USER and *DOMAIN. If any field of the value is empty, 1207 * then the corresponding paramater value will be set to NULL. 1208 * 1209 * return: \li 1210 * 1211 * 0 on success and -1 on failure. 1212 */ 1213 1214 int 1215 irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, 1216 char *buffer) 1217 { 1218 char *p, *q; 1219 char fieldsep = ','; 1220 int myerrno = EINVAL; 1221 char *host, *user, *domain; 1222 1223 if (userp == NULL || hostp == NULL || 1224 domainp == NULL || buffer == NULL) { 1225 errno = EINVAL; 1226 return (-1); 1227 } 1228 1229 host = user = domain = NULL; 1230 1231 p = buffer; 1232 while (isspace((unsigned char)*p)) { 1233 p++; 1234 } 1235 if (*p != '(') { 1236 goto error; 1237 } 1238 1239 q = p + 1; 1240 while (*q && *q != fieldsep) 1241 q++; 1242 if (!*q) { 1243 goto error; 1244 } else if (q > p + 1) { 1245 host = strndup(p, q - p); 1246 } 1247 1248 p = q + 1; 1249 if (!*p) { 1250 goto error; 1251 } else if (*p != fieldsep) { 1252 q = p + 1; 1253 while (*q && *q != fieldsep) 1254 q++; 1255 if (!*q) { 1256 goto error; 1257 } 1258 user = strndup(p, q - p); 1259 } else { 1260 p++; 1261 } 1262 1263 if (!*p) { 1264 goto error; 1265 } else if (*p != ')') { 1266 q = p + 1; 1267 while (*q && *q != ')') 1268 q++; 1269 if (!*q) { 1270 goto error; 1271 } 1272 domain = strndup(p, q - p); 1273 } 1274 *hostp = host; 1275 *userp = user; 1276 *domainp = domain; 1277 1278 return (0); 1279 1280 error: 1281 errno = myerrno; 1282 1283 if (host != NULL) free(host); 1284 if (user != NULL) free(user); 1285 1286 return (-1); 1287 } 1288 1289 /* ------------------------- struct netgrp ------------------------- */ 1290 1291 1292 1293 1294 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ 1295 1296 /*% 1297 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) 1298 * 1299 * notes: \li 1300 * 1301 * See at top. 1302 * 1303 * return: \li 1304 * 1305 * 0 on success and -1 on failure. 1306 * 1307 */ 1308 1309 int 1310 irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) { 1311 size_t need = 1; /*%< for null byte */ 1312 char nAddrType[24]; 1313 char nNet[MAXPADDRSIZE]; 1314 const char *fieldsep = COLONSTR; 1315 1316 if (ne == NULL || len == NULL) { 1317 return (-1); 1318 } 1319 1320 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); 1321 1322 if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, 1323 nNet, sizeof nNet) == NULL) { 1324 return (-1); 1325 } 1326 1327 1328 need += strlen(ne->n_name) + 1; 1329 need += joinlength(ne->n_aliases) + 1; 1330 need += strlen(nAddrType) + 1; 1331 need += strlen(nNet) + 1; 1332 1333 if (buffer == NULL) { 1334 *len = need; 1335 return (0); 1336 } 1337 1338 if (*buffer != NULL && need > *len) { 1339 errno = EINVAL; 1340 return (-1); 1341 } 1342 1343 if (*buffer == NULL) { 1344 need += 2; /*%< for CRLF */ 1345 *buffer = memget(need); 1346 if (*buffer == NULL) { 1347 errno = ENOMEM; 1348 return (-1); 1349 } 1350 1351 *len = need; 1352 } 1353 1354 strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); 1355 joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); 1356 strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); 1357 strcat(*buffer, nNet); strcat(*buffer, fieldsep); 1358 1359 return (0); 1360 } 1361 1362 /*% 1363 * int irp_unmarshall_nw(struct nwent *ne, char *buffer) 1364 * 1365 * notes: \li 1366 * 1367 * See note up top. 1368 * 1369 * return: \li 1370 * 1371 * 0 on success and -1 on failure. 1372 * 1373 */ 1374 1375 int 1376 irp_unmarshall_nw(struct nwent *ne, char *buffer) { 1377 char *p, *q; 1378 int naddrtype; 1379 long nnet; 1380 int bits; 1381 char *name = NULL; 1382 char **aliases = NULL; 1383 char tmpbuf[24]; 1384 char *tb; 1385 char fieldsep = ':'; 1386 int myerrno = EINVAL; 1387 1388 if (ne == NULL || buffer == NULL) { 1389 goto error; 1390 } 1391 1392 p = buffer; 1393 1394 /* n_name field */ 1395 name = NULL; 1396 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1397 goto error; 1398 } 1399 1400 1401 /* n_aliases field. Aliases are separated by commas */ 1402 q = strchr(p, fieldsep); 1403 if (q == NULL) { 1404 goto error; 1405 } 1406 aliases = splitarray(p, q, COMMA); 1407 if (aliases == NULL) { 1408 myerrno = errno; 1409 goto error; 1410 } 1411 p = q + 1; 1412 1413 1414 /* h_addrtype field */ 1415 tb = tmpbuf; 1416 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1417 strlen(tb) == 0U) { 1418 goto error; 1419 } 1420 if (strcmp(tmpbuf, "AF_INET") == 0) 1421 naddrtype = AF_INET; 1422 else if (strcmp(tmpbuf, "AF_INET6") == 0) 1423 naddrtype = AF_INET6; 1424 else 1425 goto error; 1426 1427 1428 /* n_net field */ 1429 tb = tmpbuf; 1430 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1431 strlen(tb) == 0U) { 1432 goto error; 1433 } 1434 nnet = 0; 1435 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); 1436 if (bits < 0) { 1437 goto error; 1438 } 1439 1440 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ 1441 1442 ne->n_name = name; 1443 ne->n_aliases = aliases; 1444 ne->n_addrtype = naddrtype; 1445 ne->n_length = bits; 1446 ne->n_addr = malloc(sizeof nnet); 1447 if (ne->n_addr == NULL) { 1448 goto error; 1449 } 1450 1451 memcpy(ne->n_addr, &nnet, sizeof nnet); 1452 1453 return (0); 1454 1455 error: 1456 errno = myerrno; 1457 1458 if (name != NULL) free(name); 1459 free_array(aliases, 0); 1460 1461 return (-1); 1462 } 1463 1464 1465 /* ------------------------- struct nwent ------------------------- */ 1466 1467 1468 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ 1469 1470 /*% 1471 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) 1472 * 1473 * notes: \li 1474 * 1475 * See at top. 1476 * 1477 * return: \li 1478 * 1479 * 0 on success and -1 on failure. 1480 * 1481 */ 1482 1483 int 1484 irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) { 1485 size_t need = 1; /*%< for null byte */ 1486 char nAddrType[24]; 1487 char nNet[MAXPADDRSIZE]; 1488 const char *fieldsep = COLONSTR; 1489 long nval; 1490 1491 if (ne == NULL || len == NULL) { 1492 return (-1); 1493 } 1494 1495 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); 1496 1497 nval = htonl(ne->n_net); 1498 if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { 1499 return (-1); 1500 } 1501 1502 need += strlen(ne->n_name) + 1; 1503 need += joinlength(ne->n_aliases) + 1; 1504 need += strlen(nAddrType) + 1; 1505 need += strlen(nNet) + 1; 1506 1507 if (buffer == NULL) { 1508 *len = need; 1509 return (0); 1510 } 1511 1512 if (*buffer != NULL && need > *len) { 1513 errno = EINVAL; 1514 return (-1); 1515 } 1516 1517 if (*buffer == NULL) { 1518 need += 2; /*%< for CRLF */ 1519 *buffer = memget(need); 1520 if (*buffer == NULL) { 1521 errno = ENOMEM; 1522 return (-1); 1523 } 1524 1525 *len = need; 1526 } 1527 1528 strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); 1529 joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); 1530 strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); 1531 strcat(*buffer, nNet); strcat(*buffer, fieldsep); 1532 1533 return (0); 1534 } 1535 1536 /*% 1537 * int irp_unmarshall_ne(struct netent *ne, char *buffer) 1538 * 1539 * notes: \li 1540 * 1541 * See note up top. 1542 * 1543 * return: \li 1544 * 1545 * 0 on success and -1 on failure. 1546 * 1547 */ 1548 1549 int 1550 irp_unmarshall_ne(struct netent *ne, char *buffer) { 1551 char *p, *q; 1552 int naddrtype; 1553 long nnet; 1554 int bits; 1555 char *name = NULL; 1556 char **aliases = NULL; 1557 char tmpbuf[24]; 1558 char *tb; 1559 char fieldsep = ':'; 1560 int myerrno = EINVAL; 1561 1562 if (ne == NULL || buffer == NULL) { 1563 goto error; 1564 } 1565 1566 p = buffer; 1567 1568 /* n_name field */ 1569 name = NULL; 1570 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1571 goto error; 1572 } 1573 1574 1575 /* n_aliases field. Aliases are separated by commas */ 1576 q = strchr(p, fieldsep); 1577 if (q == NULL) { 1578 goto error; 1579 } 1580 aliases = splitarray(p, q, COMMA); 1581 if (aliases == NULL) { 1582 myerrno = errno; 1583 goto error; 1584 } 1585 p = q + 1; 1586 1587 1588 /* h_addrtype field */ 1589 tb = tmpbuf; 1590 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1591 strlen(tb) == 0U) { 1592 goto error; 1593 } 1594 if (strcmp(tmpbuf, "AF_INET") == 0) 1595 naddrtype = AF_INET; 1596 else if (strcmp(tmpbuf, "AF_INET6") == 0) 1597 naddrtype = AF_INET6; 1598 else 1599 goto error; 1600 1601 1602 /* n_net field */ 1603 tb = tmpbuf; 1604 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1605 strlen(tb) == 0U) { 1606 goto error; 1607 } 1608 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); 1609 if (bits < 0) { 1610 goto error; 1611 } 1612 nnet = ntohl(nnet); 1613 1614 ne->n_name = name; 1615 ne->n_aliases = aliases; 1616 ne->n_addrtype = naddrtype; 1617 ne->n_net = nnet; 1618 1619 return (0); 1620 1621 error: 1622 errno = myerrno; 1623 1624 if (name != NULL) free(name); 1625 free_array(aliases, 0); 1626 1627 return (-1); 1628 } 1629 1630 1631 /* ------------------------- struct netent ------------------------- */ 1632 1633 1634 /* =========================================================================== */ 1635 1636 /*% 1637 * static char ** splitarray(const char *buffer, const char *buffend, char delim) 1638 * 1639 * notes: \li 1640 * 1641 * Split a delim separated astring. Not allowed 1642 * to have two delims next to each other. BUFFER points to begining of 1643 * string, BUFFEND points to one past the end of the string 1644 * (i.e. points at where the null byte would be if null 1645 * terminated). 1646 * 1647 * return: \li 1648 * 1649 * Returns a malloced array of pointers, each pointer pointing to a 1650 * malloced string. If BUFEER is an empty string, then return values is 1651 * array of 1 pointer that is NULL. Returns NULL on failure. 1652 * 1653 */ 1654 1655 static char ** 1656 splitarray(const char *buffer, const char *buffend, char delim) { 1657 const char *p, *q; 1658 int count = 0; 1659 char **arr = NULL; 1660 char **aptr; 1661 1662 if (buffend < buffer) 1663 return (NULL); 1664 else if (buffend > buffer && *buffer == delim) 1665 return (NULL); 1666 else if (buffend > buffer && *(buffend - 1) == delim) 1667 return (NULL); 1668 1669 /* count the number of field and make sure none are empty */ 1670 if (buffend > buffer + 1) { 1671 for (count = 1, q = buffer ; q != buffend ; q++) { 1672 if (*q == delim) { 1673 if (q > buffer && (*(q - 1) == delim)) { 1674 errno = EINVAL; 1675 return (NULL); 1676 } 1677 count++; 1678 } 1679 } 1680 } 1681 1682 if (count > 0) { 1683 count++ ; /*%< for NULL at end */ 1684 aptr = arr = malloc(count * sizeof (char *)); 1685 if (aptr == NULL) { 1686 errno = ENOMEM; 1687 return (NULL); 1688 } 1689 1690 memset(arr, 0x0, count * sizeof (char *)); 1691 for (p = buffer ; p < buffend ; p++) { 1692 for (q = p ; *q != delim && q != buffend ; q++) 1693 /* nothing */; 1694 *aptr = strndup(p, q - p); 1695 1696 p = q; 1697 aptr++; 1698 } 1699 *aptr = NULL; 1700 } else { 1701 arr = malloc(sizeof (char *)); 1702 if (arr == NULL) { 1703 errno = ENOMEM; 1704 return (NULL); 1705 } 1706 1707 *arr = NULL; 1708 } 1709 1710 return (arr); 1711 } 1712 1713 /*% 1714 * static size_t joinlength(char * const *argv) 1715 * 1716 * return: \li 1717 * 1718 * the number of bytes in all the arrays pointed at 1719 * by argv, including their null bytes(which will usually be turned 1720 * into commas). 1721 * 1722 * 1723 */ 1724 1725 static size_t 1726 joinlength(char * const *argv) { 1727 int len = 0; 1728 1729 while (argv && *argv) { 1730 len += (strlen(*argv) + 1); 1731 argv++; 1732 } 1733 1734 return (len); 1735 } 1736 1737 /*% 1738 * int joinarray(char * const *argv, char *buffer, char delim) 1739 * 1740 * notes: \li 1741 * 1742 * Copy all the ARGV strings into the end of BUFFER 1743 * separating them with DELIM. BUFFER is assumed to have 1744 * enough space to hold everything and to be already null-terminated. 1745 * 1746 * return: \li 1747 * 1748 * 0 unless argv or buffer is NULL. 1749 * 1750 * 1751 */ 1752 1753 static int 1754 joinarray(char * const *argv, char *buffer, char delim) { 1755 char * const *p; 1756 char sep[2]; 1757 1758 if (argv == NULL || buffer == NULL) { 1759 errno = EINVAL; 1760 return (-1); 1761 } 1762 1763 sep[0] = delim; 1764 sep[1] = 0x0; 1765 1766 for (p = argv ; *p != NULL ; p++) { 1767 strcat(buffer, *p); 1768 if (*(p + 1) != NULL) { 1769 strcat(buffer, sep); 1770 } 1771 } 1772 1773 return (0); 1774 } 1775 1776 /*% 1777 * static char * getfield(char **res, size_t reslen, char **ptr, char delim) 1778 * 1779 * notes: \li 1780 * 1781 * Stores in *RES, which is a buffer of length RESLEN, a 1782 * copy of the bytes from *PTR up to and including the first 1783 * instance of DELIM. If *RES is NULL, then it will be 1784 * assigned a malloced buffer to hold the copy. *PTR is 1785 * modified to point at the found delimiter. 1786 * 1787 * return: \li 1788 * 1789 * If there was no delimiter, then NULL is returned, 1790 * otherewise *RES is returned. 1791 * 1792 */ 1793 1794 static char * 1795 getfield(char **res, size_t reslen, char **ptr, char delim) { 1796 char *q; 1797 1798 if (res == NULL || ptr == NULL || *ptr == NULL) { 1799 errno = EINVAL; 1800 return (NULL); 1801 } 1802 1803 q = strchr(*ptr, delim); 1804 1805 if (q == NULL) { 1806 errno = EINVAL; 1807 return (NULL); 1808 } else { 1809 if (*res == NULL) { 1810 *res = strndup(*ptr, q - *ptr); 1811 } else { 1812 if ((size_t)(q - *ptr + 1) > reslen) { /*%< to big for res */ 1813 errno = EINVAL; 1814 return (NULL); 1815 } else { 1816 strncpy(*res, *ptr, q - *ptr); 1817 (*res)[q - *ptr] = 0x0; 1818 } 1819 } 1820 *ptr = q + 1; 1821 } 1822 1823 return (*res); 1824 } 1825 1826 1827 1828 1829 1830 #ifndef HAVE_STRNDUP 1831 /* 1832 * static char * strndup(const char *str, size_t len) 1833 * 1834 * notes: \li 1835 * 1836 * like strdup, except do len bytes instead of the whole string. Always 1837 * null-terminates. 1838 * 1839 * return: \li 1840 * 1841 * The newly malloced string. 1842 * 1843 */ 1844 1845 static char * 1846 strndup(const char *str, size_t len) { 1847 char *p = malloc(len + 1); 1848 1849 if (p == NULL) 1850 return (NULL); 1851 strncpy(p, str, len); 1852 p[len] = 0x0; 1853 return (p); 1854 } 1855 #endif 1856 1857 #if WANT_MAIN 1858 1859 /*% 1860 * static int strcmp_nws(const char *a, const char *b) 1861 * 1862 * notes: \li 1863 * 1864 * do a strcmp, except uneven lengths of whitespace compare the same 1865 * 1866 * return: \li 1867 * 1868 */ 1869 1870 static int 1871 strcmp_nws(const char *a, const char *b) { 1872 while (*a && *b) { 1873 if (isspace(*a) && isspace(*b)) { 1874 do { 1875 a++; 1876 } while (isspace(*a)); 1877 do { 1878 b++; 1879 } while (isspace(*b)); 1880 } 1881 if (*a < *b) 1882 return (-1); 1883 else if (*a > *b) 1884 return (1); 1885 1886 a++; 1887 b++;; 1888 } 1889 1890 if (*a == *b) 1891 return (0); 1892 else if (*a > *b) 1893 return (1); 1894 else 1895 return (-1); 1896 } 1897 1898 #endif 1899 1900 /*% 1901 * static void free_array(char **argv, size_t entries) 1902 * 1903 * notes: \li 1904 * 1905 * Free argv and each of the pointers inside it. The end of 1906 * the array is when a NULL pointer is found inside. If 1907 * entries is > 0, then NULL pointers inside the array do 1908 * not indicate the end of the array. 1909 * 1910 */ 1911 1912 static void 1913 free_array(char **argv, size_t entries) { 1914 char **p = argv; 1915 int useEntries = (entries > 0U); 1916 1917 if (argv == NULL) 1918 return; 1919 1920 while ((useEntries && entries > 0U) || *p) { 1921 if (*p) 1922 free(*p); 1923 p++; 1924 if (useEntries) 1925 entries--; 1926 } 1927 free(argv); 1928 } 1929 1930 1931 1932 1933 1934 /* ************************************************** */ 1935 1936 #if WANT_MAIN 1937 1938 /*% takes an option to indicate what sort of marshalling(read the code) and 1939 an argument. If the argument looks like a marshalled buffer(has a ':' 1940 embedded) then it's unmarshalled and the remarshalled and the new string 1941 is compared to the old one. 1942 */ 1943 1944 int 1945 main(int argc, char **argv) { 1946 char buffer[1024]; 1947 char *b = &buffer[0]; 1948 size_t len = sizeof buffer; 1949 char option; 1950 1951 if (argc < 2 || argv[1][0] != '-') 1952 exit(1); 1953 1954 option = argv[1][1]; 1955 argv++; 1956 argc--; 1957 1958 1959 #if 0 1960 { 1961 char buff[10]; 1962 char *p = argv[1], *q = &buff[0]; 1963 1964 while (getfield(&q, sizeof buff, &p, ':') != NULL) { 1965 printf("field: \"%s\"\n", q); 1966 p++; 1967 } 1968 printf("p is now \"%s\"\n", p); 1969 } 1970 #endif 1971 1972 #if 0 1973 { 1974 char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), 1975 argv[2][0]); 1976 char **p; 1977 1978 if (x == NULL) 1979 printf("split failed\n"); 1980 1981 for (p = x ; p != NULL && *p != NULL ; p++) { 1982 printf("\"%s\"\n", *p); 1983 } 1984 } 1985 #endif 1986 1987 #if 1 1988 switch(option) { 1989 case 'n': { 1990 struct nwent ne; 1991 int i; 1992 1993 if (strchr(argv[1], ':') != NULL) { 1994 if (irp_unmarshall_nw(&ne, argv[1]) != 0) { 1995 printf("Unmarhsalling failed\n"); 1996 exit(1); 1997 } 1998 1999 printf("Name: \"%s\"\n", ne.n_name); 2000 printf("Aliases:"); 2001 for (i = 0 ; ne.n_aliases[i] != NULL ; i++) 2002 printf("\n\t\"%s\"", ne.n_aliases[i]); 2003 printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype)); 2004 inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, 2005 buffer, sizeof buffer); 2006 printf("Net: \"%s\"\n", buffer); 2007 *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr)); 2008 inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, 2009 buffer, sizeof buffer); 2010 printf("Corrected Net: \"%s\"\n", buffer); 2011 } else { 2012 struct netent *np1 = getnetbyname(argv[1]); 2013 ne.n_name = np1->n_name; 2014 ne.n_aliases = np1->n_aliases; 2015 ne.n_addrtype = np1->n_addrtype; 2016 ne.n_addr = &np1->n_net; 2017 ne.n_length = (IN_CLASSA(np1->n_net) ? 2018 8 : 2019 (IN_CLASSB(np1->n_net) ? 2020 16 : 2021 (IN_CLASSC(np1->n_net) ? 2022 24 : -1))); 2023 np1->n_net = htonl(np1->n_net); 2024 if (irp_marshall_nw(&ne, &b, &len) != 0) { 2025 printf("Marshalling failed\n"); 2026 } 2027 printf("%s\n", b); 2028 } 2029 break; 2030 } 2031 2032 2033 case 'r': { 2034 char **hosts, **users, **domains; 2035 size_t entries; 2036 int i; 2037 char *buff; 2038 size_t size; 2039 char *ngname; 2040 2041 if (strchr(argv[1], '(') != NULL) { 2042 if (irp_unmarshall_ng(&ngname, &entries, 2043 &hosts, &users, &domains, 2044 argv[1]) != 0) { 2045 printf("unmarshall failed\n"); 2046 exit(1); 2047 } 2048 2049 #define STRVAL(x) (x == NULL ? "*" : x) 2050 2051 printf("%s {\n", ngname); 2052 for (i = 0 ; i < entries ; i++) 2053 printf("\t\"%s\" : \"%s\" : \"%s\"\n", 2054 STRVAL(hosts[i]), 2055 STRVAL(users[i]), 2056 STRVAL(domains[i])); 2057 printf("}\n\n\n"); 2058 2059 2060 irp_marshall_ng_start(ngname, NULL, &size); 2061 for (i = 0 ; i < entries ; i++) 2062 irp_marshall_ng_next(hosts[i], users[i], 2063 domains[i], NULL, &size); 2064 irp_marshall_ng_end(NULL, &size); 2065 2066 buff = malloc(size); 2067 2068 irp_marshall_ng_start(ngname, buff, &size); 2069 for (i = 0 ; i < entries ; i++) { 2070 if (irp_marshall_ng_next(hosts[i], users[i], 2071 domains[i], buff, 2072 &size) != 0) 2073 printf("next marshalling failed.\n"); 2074 } 2075 irp_marshall_ng_end(buff, &size); 2076 2077 if (strcmp_nws(argv[1], buff) != 0) { 2078 printf("compare failed:\n\t%s\n\t%s\n", 2079 buffer, argv[1]); 2080 } else { 2081 printf("compare ok\n"); 2082 } 2083 } else { 2084 char *h, *u, *d, *buff; 2085 size_t size; 2086 2087 /* run through two times. First to figure out how 2088 much of a buffer we need. Second to do the 2089 actual marshalling */ 2090 2091 setnetgrent(argv[1]); 2092 irp_marshall_ng_start(argv[1], NULL, &size); 2093 while (getnetgrent(&h, &u, &d) == 1) 2094 irp_marshall_ng_next(h, u, d, NULL, &size); 2095 irp_marshall_ng_end(NULL, &size); 2096 endnetgrent(argv[1]); 2097 2098 buff = malloc(size); 2099 2100 setnetgrent(argv[1]); 2101 if (irp_marshall_ng_start(argv[1], buff, &size) != 0) 2102 printf("Marshalling start failed\n"); 2103 2104 while (getnetgrent(&h, &u, &d) == 1) { 2105 if (irp_marshall_ng_next(h, u, d, buff, &size) 2106 != 0) { 2107 printf("Marshalling failed\n"); 2108 } 2109 } 2110 2111 irp_marshall_ng_end(buff, &size); 2112 endnetgrent(); 2113 2114 printf("success: %s\n", buff); 2115 } 2116 break; 2117 } 2118 2119 2120 2121 case 'h': { 2122 struct hostent he, *hp; 2123 int i; 2124 2125 2126 if (strchr(argv[1], '@') != NULL) { 2127 if (irp_unmarshall_ho(&he, argv[1]) != 0) { 2128 printf("unmarshall failed\n"); 2129 exit(1); 2130 } 2131 2132 printf("Host: \"%s\"\nAliases:", he.h_name); 2133 for (i = 0 ; he.h_aliases[i] != NULL ; i++) 2134 printf("\n\t\t\"%s\"", he.h_aliases[i]); 2135 printf("\nAddr Type: \"%s\"\n", 2136 ADDR_T_STR(he.h_addrtype)); 2137 printf("Length: %d\nAddresses:", he.h_length); 2138 for (i = 0 ; he.h_addr_list[i] != 0 ; i++) { 2139 inet_ntop(he.h_addrtype, he.h_addr_list[i], 2140 buffer, sizeof buffer); 2141 printf("\n\t\"%s\"\n", buffer); 2142 } 2143 printf("\n\n"); 2144 2145 irp_marshall_ho(&he, &b, &len); 2146 if (strcmp(argv[1], buffer) != 0) { 2147 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", 2148 buffer, argv[1]); 2149 } else { 2150 printf("compare ok\n"); 2151 } 2152 } else { 2153 if ((hp = gethostbyname(argv[1])) == NULL) { 2154 perror("gethostbyname"); 2155 printf("\"%s\"\n", argv[1]); 2156 exit(1); 2157 } 2158 2159 if (irp_marshall_ho(hp, &b, &len) != 0) { 2160 printf("irp_marshall_ho failed\n"); 2161 exit(1); 2162 } 2163 2164 printf("success: \"%s\"\n", buffer); 2165 } 2166 break; 2167 } 2168 2169 2170 case 's': { 2171 struct servent *sv; 2172 struct servent sv1; 2173 2174 if (strchr(argv[1], ':') != NULL) { 2175 sv = &sv1; 2176 memset(sv, 0xef, sizeof (struct servent)); 2177 if (irp_unmarshall_sv(sv, argv[1]) != 0) { 2178 printf("unmarshall failed\n"); 2179 2180 } 2181 2182 irp_marshall_sv(sv, &b, &len); 2183 if (strcmp(argv[1], buffer) != 0) { 2184 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", 2185 buffer, argv[1]); 2186 } else { 2187 printf("compare ok\n"); 2188 } 2189 } else { 2190 if ((sv = getservbyname(argv[1], argv[2])) == NULL) { 2191 perror("getservent"); 2192 exit(1); 2193 } 2194 2195 if (irp_marshall_sv(sv, &b, &len) != 0) { 2196 printf("irp_marshall_sv failed\n"); 2197 exit(1); 2198 } 2199 2200 printf("success: \"%s\"\n", buffer); 2201 } 2202 break; 2203 } 2204 2205 case 'g': { 2206 struct group *gr; 2207 struct group gr1; 2208 2209 if (strchr(argv[1], ':') != NULL) { 2210 gr = &gr1; 2211 memset(gr, 0xef, sizeof (struct group)); 2212 if (irp_unmarshall_gr(gr, argv[1]) != 0) { 2213 printf("unmarshall failed\n"); 2214 2215 } 2216 2217 irp_marshall_gr(gr, &b, &len); 2218 if (strcmp(argv[1], buffer) != 0) { 2219 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", 2220 buffer, argv[1]); 2221 } else { 2222 printf("compare ok\n"); 2223 } 2224 } else { 2225 if ((gr = getgrnam(argv[1])) == NULL) { 2226 perror("getgrnam"); 2227 exit(1); 2228 } 2229 2230 if (irp_marshall_gr(gr, &b, &len) != 0) { 2231 printf("irp_marshall_gr failed\n"); 2232 exit(1); 2233 } 2234 2235 printf("success: \"%s\"\n", buffer); 2236 } 2237 break; 2238 } 2239 2240 2241 case 'p': { 2242 struct passwd *pw; 2243 struct passwd pw1; 2244 2245 if (strchr(argv[1], ':') != NULL) { 2246 pw = &pw1; 2247 memset(pw, 0xef, sizeof (*pw)); 2248 if (irp_unmarshall_pw(pw, argv[1]) != 0) { 2249 printf("unmarshall failed\n"); 2250 exit(1); 2251 } 2252 2253 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n", 2254 pw->pw_name, pw->pw_passwd, (long)pw->pw_uid, 2255 (long)pw->pw_gid); 2256 printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n", 2257 pw->pw_class, (long)pw->pw_change, pw->pw_gecos); 2258 printf("Shell: \"%s\"\nDirectory: \"%s\"\n", 2259 pw->pw_shell, pw->pw_dir); 2260 2261 pw = getpwnam(pw->pw_name); 2262 irp_marshall_pw(pw, &b, &len); 2263 if (strcmp(argv[1], buffer) != 0) { 2264 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", 2265 buffer, argv[1]); 2266 } else { 2267 printf("compare ok\n"); 2268 } 2269 } else { 2270 if ((pw = getpwnam(argv[1])) == NULL) { 2271 perror("getpwnam"); 2272 exit(1); 2273 } 2274 2275 if (irp_marshall_pw(pw, &b, &len) != 0) { 2276 printf("irp_marshall_pw failed\n"); 2277 exit(1); 2278 } 2279 2280 printf("success: \"%s\"\n", buffer); 2281 } 2282 break; 2283 } 2284 2285 default: 2286 printf("Wrong option: %c\n", option); 2287 break; 2288 } 2289 2290 #endif 2291 2292 return (0); 2293 } 2294 2295 #endif 2296 2297 /*! \file */ 2298