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