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