xref: /illumos-gate/usr/src/lib/libresolv2/common/irs/irpmarshall.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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