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