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