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