2 * Copyright(c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36 * Portions Copyright (c) 1996 by Internet Software Consortium.
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.
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.
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid
[] = "$Id: irpmarshall.c,v 1.3.2.3 2004/03/17 01:15:47 marka Exp $";
53 #endif /* LIBC_SCCS and not lint */
57 Check values are in approrpriate endian order
.
59 Double check memory allocations on unmarhsalling
66 #include "port_before.h"
68 #include <sys/types.h>
69 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <arpa/nameser.h>
87 #include <isc/memcluster.h>
88 #include <isc/irpmarshall.h>
90 #include "port_after.h"
94 static char *strndup(const char *str
, size_t len
);
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
);
103 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
104 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
106 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
108 static char COMMA
= ',';
110 static const char *COMMASTR
= ",";
111 static const char *COLONSTR
= ":";
115 /* See big comment at bottom of irpmarshall.h for description. */
119 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
123 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
131 * 0 on sucess, -1 on failure.
136 irp_marshall_pw(const struct passwd
*pw
, char **buffer
, size_t *len
) {
137 size_t need
= 1 ; /* for null byte */
143 const char *fieldsep
= COLONSTR
;
145 if (pw
== NULL
|| len
== NULL
) {
150 sprintf(pwUid
, "%ld", (long)pw
->pw_uid
);
151 sprintf(pwGid
, "%ld", (long)pw
->pw_gid
);
153 #ifdef HAVE_PW_CHANGE
154 sprintf(pwChange
, "%ld", (long)pw
->pw_change
);
160 #ifdef HAVE_PW_EXPIRE
161 sprintf(pwExpire
, "%ld", (long)pw
->pw_expire
);
168 pwClass
= pw
->pw_class
;
173 need
+= strlen(pw
->pw_name
) + 1; /* one for fieldsep */
174 need
+= strlen(pw
->pw_passwd
) + 1;
175 need
+= strlen(pwUid
) + 1;
176 need
+= strlen(pwGid
) + 1;
177 need
+= strlen(pwClass
) + 1;
178 need
+= strlen(pwChange
) + 1;
179 need
+= strlen(pwExpire
) + 1;
180 need
+= strlen(pw
->pw_gecos
) + 1;
181 need
+= strlen(pw
->pw_dir
) + 1;
182 need
+= strlen(pw
->pw_shell
) + 1;
184 if (buffer
== NULL
) {
189 if (*buffer
!= NULL
&& need
> *len
) {
194 if (*buffer
== NULL
) {
195 need
+= 2; /* for CRLF */
196 *buffer
= memget(need
);
197 if (*buffer
== NULL
) {
205 strcpy(*buffer
, pw
->pw_name
); strcat(*buffer
, fieldsep
);
206 strcat(*buffer
, pw
->pw_passwd
); strcat(*buffer
, fieldsep
);
207 strcat(*buffer
, pwUid
); strcat(*buffer
, fieldsep
);
208 strcat(*buffer
, pwGid
); strcat(*buffer
, fieldsep
);
209 strcat(*buffer
, pwClass
); strcat(*buffer
, fieldsep
);
210 strcat(*buffer
, pwChange
); strcat(*buffer
, fieldsep
);
211 strcat(*buffer
, pwExpire
); strcat(*buffer
, fieldsep
);
212 strcat(*buffer
, pw
->pw_gecos
); strcat(*buffer
, fieldsep
);
213 strcat(*buffer
, pw
->pw_dir
); strcat(*buffer
, fieldsep
);
214 strcat(*buffer
, pw
->pw_shell
); strcat(*buffer
, fieldsep
);
224 * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
232 * 0 on success, -1 on failure
237 irp_unmarshall_pw(struct passwd
*pw
, char *buffer
) {
238 char *name
, *pass
, *class, *gecos
, *dir
, *shell
;
246 char *tb
= &tmpbuf
[0];
248 int myerrno
= EINVAL
;
250 name
= pass
= class = gecos
= dir
= shell
= NULL
;
255 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0) {
259 /* pw_passwd field */
261 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) { /* field can be empty */
268 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
272 t
= strtol(tmpbuf
, &tb
, 10);
274 goto error
; /* junk in value */
277 if ((long) pwuid
!= t
) { /* value must have been too big. */
285 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
289 t
= strtol(tmpbuf
, &tb
, 10);
291 goto error
; /* junk in value */
294 if ((long)pwgid
!= t
) { /* value must have been too big. */
302 if (getfield(&class, 0, &p
, fieldsep
) == NULL
) {
308 /* pw_change field */
310 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
314 t
= strtol(tmpbuf
, &tb
, 10);
316 goto error
; /* junk in value */
318 pwchange
= (time_t)t
;
319 if ((long)pwchange
!= t
) { /* value must have been too big. */
325 /* pw_expire field */
327 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
331 t
= strtol(tmpbuf
, &tb
, 10);
333 goto error
; /* junk in value */
335 pwexpire
= (time_t)t
;
336 if ((long) pwexpire
!= t
) { /* value must have been too big. */
344 if (getfield(&gecos
, 0, &p
, fieldsep
) == NULL
) {
352 if (getfield(&dir
, 0, &p
, fieldsep
) == NULL
) {
360 if (getfield(&shell
, 0, &p
, fieldsep
) == NULL
) {
367 pw
->pw_passwd
= pass
;
370 pw
->pw_gecos
= gecos
;
372 pw
->pw_shell
= shell
;
374 #ifdef HAVE_PW_CHANGE
375 pw
->pw_change
= pwchange
;
378 pw
->pw_class
= class;
380 #ifdef HAVE_PW_EXPIRE
381 pw
->pw_expire
= pwexpire
;
389 if (name
!= NULL
) free(name
);
390 if (pass
!= NULL
) free(pass
);
391 if (gecos
!= NULL
) free(gecos
);
392 if (dir
!= NULL
) free(dir
);
393 if (shell
!= NULL
) free(shell
);
398 /* ------------------------- struct passwd ------------------------- */
399 #endif /* WANT_IRS_PW */
403 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
408 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
416 * 0 on success, -1 on failure
420 irp_marshall_gr(const struct group
*gr
, char **buffer
, size_t *len
) {
421 size_t need
= 1; /* for null byte */
423 const char *fieldsep
= COLONSTR
;
425 if (gr
== NULL
|| len
== NULL
) {
430 sprintf(grGid
, "%ld", (long)gr
->gr_gid
);
432 need
+= strlen(gr
->gr_name
) + 1;
433 #ifndef MISSING_GR_PASSWD
434 need
+= strlen(gr
->gr_passwd
) + 1;
438 need
+= strlen(grGid
) + 1;
439 need
+= joinlength(gr
->gr_mem
) + 1;
441 if (buffer
== NULL
) {
446 if (*buffer
!= NULL
&& need
> *len
) {
451 if (*buffer
== NULL
) {
452 need
+= 2; /* for CRLF */
453 *buffer
= memget(need
);
454 if (*buffer
== NULL
) {
462 strcpy(*buffer
, gr
->gr_name
); strcat(*buffer
, fieldsep
);
463 #ifndef MISSING_GR_PASSWD
464 strcat(*buffer
, gr
->gr_passwd
);
466 strcat(*buffer
, fieldsep
);
467 strcat(*buffer
, grGid
); strcat(*buffer
, fieldsep
);
468 joinarray(gr
->gr_mem
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
477 * int irp_unmarshall_gr(struct group *gr, char *buffer)
485 * 0 on success and -1 on failure.
490 irp_unmarshall_gr(struct group
*gr
, char *buffer
) {
496 char **members
= NULL
;
500 int myerrno
= EINVAL
;
502 if (gr
== NULL
|| buffer
== NULL
) {
511 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
516 /* gr_passwd field */
518 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) {
525 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
529 t
= strtol(tmpbuf
, &tb
, 10);
531 goto error
; /* junk in value */
534 if ((long) grgid
!= t
) { /* value must have been too big. */
539 /* gr_mem field. Member names are separated by commas */
540 q
= strchr(p
, fieldsep
);
544 members
= splitarray(p
, q
, COMMA
);
545 if (members
== NULL
) {
553 #ifndef MISSING_GR_PASSWD
554 gr
->gr_passwd
= pass
;
557 gr
->gr_mem
= members
;
564 if (name
!= NULL
) free(name
);
565 if (pass
!= NULL
) free(pass
);
571 /* ------------------------- struct group ------------------------- */
576 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
581 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
589 * 0 on success, -1 on failure.
594 irp_marshall_sv(const struct servent
*sv
, char **buffer
, size_t *len
) {
595 size_t need
= 1; /* for null byte */
597 const char *fieldsep
= COLONSTR
;
600 if (sv
== NULL
|| len
== NULL
) {
605 /* the int s_port field is actually a short in network order. We
606 want host order to make the marshalled data look correct */
607 realport
= ntohs((short)sv
->s_port
);
608 sprintf(svPort
, "%d", realport
);
610 need
+= strlen(sv
->s_name
) + 1;
611 need
+= joinlength(sv
->s_aliases
) + 1;
612 need
+= strlen(svPort
) + 1;
613 need
+= strlen(sv
->s_proto
) + 1;
615 if (buffer
== NULL
) {
620 if (*buffer
!= NULL
&& need
> *len
) {
625 if (*buffer
== NULL
) {
626 need
+= 2; /* for CRLF */
627 *buffer
= memget(need
);
628 if (*buffer
== NULL
) {
636 strcpy(*buffer
, sv
->s_name
); strcat(*buffer
, fieldsep
);
637 joinarray(sv
->s_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
638 strcat(*buffer
, svPort
); strcat(*buffer
, fieldsep
);
639 strcat(*buffer
, sv
->s_proto
); strcat(*buffer
, fieldsep
);
649 * int irp_unmarshall_sv(struct servent *sv, char *buffer)
657 * 0 on success, -1 on failure.
662 irp_unmarshall_sv(struct servent
*sv
, char *buffer
) {
668 char **aliases
= NULL
;
672 int myerrno
= EINVAL
;
674 if (sv
== NULL
|| buffer
== NULL
)
682 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
687 /* s_aliases field */
688 q
= strchr(p
, fieldsep
);
692 aliases
= splitarray(p
, q
, COMMA
);
693 if (aliases
== NULL
) {
702 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
706 t
= strtol(tmpbuf
, &tb
, 10);
708 goto error
; /* junk in value */
711 if ((long) svport
!= t
) { /* value must have been too big. */
714 svport
= htons(svport
);
718 if (getfield(&proto
, 0, &p
, fieldsep
) == NULL
) {
723 sv
->s_aliases
= aliases
;
732 if (name
!= NULL
) free(name
);
733 if (proto
!= NULL
) free(proto
);
734 free_array(aliases
, 0);
740 /* ------------------------- struct servent ------------------------- */
742 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
747 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
755 * 0 on success and -1 on failure.
760 irp_marshall_pr(struct protoent
*pr
, char **buffer
, size_t *len
) {
761 size_t need
= 1; /* for null byte */
763 const char *fieldsep
= COLONSTR
;
765 if (pr
== NULL
|| len
== NULL
) {
770 sprintf(prProto
, "%d", (int)pr
->p_proto
);
772 need
+= strlen(pr
->p_name
) + 1;
773 need
+= joinlength(pr
->p_aliases
) + 1;
774 need
+= strlen(prProto
) + 1;
776 if (buffer
== NULL
) {
781 if (*buffer
!= NULL
&& need
> *len
) {
786 if (*buffer
== NULL
) {
787 need
+= 2; /* for CRLF */
788 *buffer
= memget(need
);
789 if (*buffer
== NULL
) {
797 strcpy(*buffer
, pr
->p_name
); strcat(*buffer
, fieldsep
);
798 joinarray(pr
->p_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
799 strcat(*buffer
, prProto
); strcat(*buffer
, fieldsep
);
808 * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
816 * 0 on success, -1 on failure
820 int irp_unmarshall_pr(struct protoent
*pr
, char *buffer
) {
825 char **aliases
= NULL
;
829 int myerrno
= EINVAL
;
831 if (pr
== NULL
|| buffer
== NULL
) {
840 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
845 /* p_aliases field */
846 q
= strchr(p
, fieldsep
);
850 aliases
= splitarray(p
, q
, COMMA
);
851 if (aliases
== NULL
) {
860 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
864 t
= strtol(tmpbuf
, &tb
, 10);
866 goto error
; /* junk in value */
869 if ((long) prproto
!= t
) { /* value must have been too big. */
874 pr
->p_aliases
= aliases
;
875 pr
->p_proto
= prproto
;
882 if (name
!= NULL
) free(name
);
883 free_array(aliases
, 0);
888 /* ------------------------- struct protoent ------------------------- */
892 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
896 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
904 * 0 on success, -1 on failure.
909 irp_marshall_ho(struct hostent
*ho
, char **buffer
, size_t *len
) {
910 size_t need
= 1; /* for null byte */
918 const char *fieldsep
= "@";
920 if (ho
== NULL
|| len
== NULL
) {
925 switch(ho
->h_addrtype
) {
927 strcpy(hoaddrtype
, "AF_INET");
931 strcpy(hoaddrtype
, "AF_INET6");
939 sprintf(holength
, "%d", ho
->h_length
);
941 need
+= strlen(ho
->h_name
) + 1;
942 need
+= joinlength(ho
->h_aliases
) + 1;
943 need
+= strlen(hoaddrtype
) + 1;
944 need
+= strlen(holength
) + 1;
946 /* we determine an upper bound on the string length needed, not an
948 addrlen
= (ho
->h_addrtype
== AF_INET
? 16 : 46) ; /* XX other AF's?? */
949 for (av
= ho
->h_addr_list
; av
!= NULL
&& *av
!= NULL
; av
++)
952 if (buffer
== NULL
) {
957 if (*buffer
!= NULL
&& need
> *len
) {
962 if (*buffer
== NULL
) {
963 need
+= 2; /* for CRLF */
964 *buffer
= memget(need
);
965 if (*buffer
== NULL
) {
974 strcpy(*buffer
, ho
->h_name
); strcat(*buffer
, fieldsep
);
975 joinarray(ho
->h_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
976 strcat(*buffer
, hoaddrtype
); strcat(*buffer
, fieldsep
);
977 strcat(*buffer
, holength
); strcat(*buffer
, fieldsep
);
979 p
= *buffer
+ strlen(*buffer
);
980 remlen
= need
- strlen(*buffer
);
981 for (av
= ho
->h_addr_list
; av
!= NULL
&& *av
!= NULL
; av
++) {
982 if (inet_ntop(ho
->h_addrtype
, *av
, p
, remlen
) == NULL
) {
985 if (*(av
+ 1) != NULL
)
990 strcat(*buffer
, fieldsep
);
996 memput(*buffer
, need
);
1005 * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
1013 * 0 on success, -1 on failure.
1018 irp_unmarshall_ho(struct hostent
*ho
, char *buffer
) {
1024 char **aliases
= NULL
;
1025 char **hohaddrlist
= NULL
;
1031 char fieldsep
= '@';
1032 int myerrno
= EINVAL
;
1034 if (ho
== NULL
|| buffer
== NULL
) {
1043 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1048 /* h_aliases field */
1049 q
= strchr(p
, fieldsep
);
1053 aliases
= splitarray(p
, q
, COMMA
);
1054 if (aliases
== NULL
) {
1061 /* h_addrtype field */
1063 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1067 if (strcmp(tmpbuf
, "AF_INET") == 0)
1068 hoaddrtype
= AF_INET
;
1069 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1070 hoaddrtype
= AF_INET6
;
1075 /* h_length field */
1077 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1081 t
= strtol(tmpbuf
, &tb
, 10);
1083 goto error
; /* junk in value */
1086 if ((long) holength
!= t
) { /* value must have been too big. */
1091 /* h_addr_list field */
1092 q
= strchr(p
, fieldsep
);
1096 /* count how many addresss are in there */
1098 for (addrcount
= 1, r
= p
; r
!= q
; r
++) {
1106 hoaddrsize
= (addrcount
+ 1) * sizeof (char *);
1107 hohaddrlist
= malloc(hoaddrsize
);
1108 if (hohaddrlist
== NULL
) {
1113 memset(hohaddrlist
, 0x0, hoaddrsize
);
1115 alist
= hohaddrlist
;
1116 for (t
= 0, r
= p
; r
!= q
; p
= r
+ 1, t
++) {
1118 while (r
!= q
&& *r
!= COMMA
) r
++;
1122 alist
[t
] = malloc(hoaddrtype
== AF_INET
? 4 : 16);
1123 if (alist
[t
] == NULL
) {
1128 if (inet_pton(hoaddrtype
, p
, alist
[t
]) == -1)
1135 ho
->h_aliases
= aliases
;
1136 ho
->h_addrtype
= hoaddrtype
;
1137 ho
->h_length
= holength
;
1138 ho
->h_addr_list
= hohaddrlist
;
1145 if (name
!= NULL
) free(name
);
1146 free_array(aliases
, 0);
1151 /* ------------------------- struct hostent------------------------- */
1155 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1159 * int irp_marshall_ng(const char *host, const char *user,
1160 * const char *domain, char *buffer, size_t *len)
1164 * See note for irp_marshall_ng_start
1168 * 0 on success, 0 on failure.
1173 irp_marshall_ng(const char *host
, const char *user
, const char *domain
,
1174 char **buffer
, size_t *len
) {
1175 size_t need
= 1; /* for nul byte */
1176 const char *fieldsep
= ",";
1183 need
+= 4; /* two parens and two commas */
1184 need
+= (host
== NULL
? 0 : strlen(host
));
1185 need
+= (user
== NULL
? 0 : strlen(user
));
1186 need
+= (domain
== NULL
? 0 : strlen(domain
));
1188 if (buffer
== NULL
) {
1191 } else if (*buffer
!= NULL
&& need
> *len
) {
1196 if (*buffer
== NULL
) {
1197 need
+= 2; /* for CRLF */
1198 *buffer
= memget(need
);
1199 if (*buffer
== NULL
) {
1208 (*buffer
)[1] = '\0';
1211 strcat(*buffer
, host
);
1212 strcat(*buffer
, fieldsep
);
1215 strcat(*buffer
, user
);
1216 strcat(*buffer
, fieldsep
);
1219 strcat(*buffer
, domain
);
1220 strcat(*buffer
, ")");
1231 * int irp_unmarshall_ng(const char **host, const char **user,
1232 * const char **domain, char *buffer)
1236 * Unpacks the BUFFER into 3 character arrays it allocates and assigns
1237 * to *HOST, *USER and *DOMAIN. If any field of the value is empty,
1238 * then the corresponding paramater value will be set to NULL.
1242 * 0 on success and -1 on failure.
1246 irp_unmarshall_ng(const char **hostp
, const char **userp
, const char **domainp
,
1250 char fieldsep
= ',';
1251 int myerrno
= EINVAL
;
1252 char *host
, *user
, *domain
;
1254 if (userp
== NULL
|| hostp
== NULL
||
1255 domainp
== NULL
|| buffer
== NULL
) {
1260 host
= user
= domain
= NULL
;
1263 while (isspace((unsigned char)*p
)) {
1271 while (*q
&& *q
!= fieldsep
)
1275 } else if (q
> p
+ 1) {
1276 host
= strndup(p
, q
- p
);
1282 } else if (*p
!= fieldsep
) {
1284 while (*q
&& *q
!= fieldsep
)
1289 user
= strndup(p
, q
- p
);
1296 } else if (*p
!= ')') {
1298 while (*q
&& *q
!= ')')
1303 domain
= strndup(p
, q
- p
);
1314 if (host
!= NULL
) free(host
);
1315 if (user
!= NULL
) free(user
);
1316 if (domain
!= NULL
) free(domain
);
1321 /* ------------------------- struct netgrp ------------------------- */
1326 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1330 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1338 * 0 on success and -1 on failure.
1343 irp_marshall_nw(struct nwent
*ne
, char **buffer
, size_t *len
) {
1344 size_t need
= 1; /* for null byte */
1346 char nNet
[MAXPADDRSIZE
];
1347 const char *fieldsep
= COLONSTR
;
1349 if (ne
== NULL
|| len
== NULL
) {
1353 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1355 if (inet_net_ntop(ne
->n_addrtype
, ne
->n_addr
, ne
->n_length
,
1356 nNet
, sizeof nNet
) == NULL
) {
1361 need
+= strlen(ne
->n_name
) + 1;
1362 need
+= joinlength(ne
->n_aliases
) + 1;
1363 need
+= strlen(nAddrType
) + 1;
1364 need
+= strlen(nNet
) + 1;
1366 if (buffer
== NULL
) {
1371 if (*buffer
!= NULL
&& need
> *len
) {
1376 if (*buffer
== NULL
) {
1377 need
+= 2; /* for CRLF */
1378 *buffer
= memget(need
);
1379 if (*buffer
== NULL
) {
1387 strcpy(*buffer
, ne
->n_name
); strcat(*buffer
, fieldsep
);
1388 joinarray(ne
->n_aliases
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
1389 strcat(*buffer
, nAddrType
); strcat(*buffer
, fieldsep
);
1390 strcat(*buffer
, nNet
); strcat(*buffer
, fieldsep
);
1398 * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1406 * 0 on success and -1 on failure.
1411 irp_unmarshall_nw(struct nwent
*ne
, char *buffer
) {
1417 char **aliases
= NULL
;
1420 char fieldsep
= ':';
1421 int myerrno
= EINVAL
;
1423 if (ne
== NULL
|| buffer
== NULL
) {
1431 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1436 /* n_aliases field. Aliases are separated by commas */
1437 q
= strchr(p
, fieldsep
);
1441 aliases
= splitarray(p
, q
, COMMA
);
1442 if (aliases
== NULL
) {
1449 /* h_addrtype field */
1451 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1455 if (strcmp(tmpbuf
, "AF_INET") == 0)
1456 naddrtype
= AF_INET
;
1457 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1458 naddrtype
= AF_INET6
;
1465 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1470 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1475 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
1478 ne
->n_aliases
= aliases
;
1479 ne
->n_addrtype
= naddrtype
;
1480 ne
->n_length
= bits
;
1481 ne
->n_addr
= malloc(sizeof nnet
);
1482 if (ne
->n_addr
== NULL
) {
1486 memcpy(ne
->n_addr
, &nnet
, sizeof nnet
);
1493 if (name
!= NULL
) free(name
);
1494 free_array(aliases
, 0);
1500 /* ------------------------- struct nwent ------------------------- */
1503 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1507 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1515 * 0 on success and -1 on failure.
1520 irp_marshall_ne(struct netent
*ne
, char **buffer
, size_t *len
) {
1521 size_t need
= 1; /* for null byte */
1523 char nNet
[MAXPADDRSIZE
];
1524 const char *fieldsep
= COLONSTR
;
1527 if (ne
== NULL
|| len
== NULL
) {
1531 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1533 nval
= htonl(ne
->n_net
);
1534 if (inet_ntop(ne
->n_addrtype
, &nval
, nNet
, sizeof nNet
) == NULL
) {
1538 need
+= strlen(ne
->n_name
) + 1;
1539 need
+= joinlength(ne
->n_aliases
) + 1;
1540 need
+= strlen(nAddrType
) + 1;
1541 need
+= strlen(nNet
) + 1;
1543 if (buffer
== NULL
) {
1548 if (*buffer
!= NULL
&& need
> *len
) {
1553 if (*buffer
== NULL
) {
1554 need
+= 2; /* for CRLF */
1555 *buffer
= memget(need
);
1556 if (*buffer
== NULL
) {
1564 strcpy(*buffer
, ne
->n_name
); strcat(*buffer
, fieldsep
);
1565 joinarray(ne
->n_aliases
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
1566 strcat(*buffer
, nAddrType
); strcat(*buffer
, fieldsep
);
1567 strcat(*buffer
, nNet
); strcat(*buffer
, fieldsep
);
1575 * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1583 * 0 on success and -1 on failure.
1588 irp_unmarshall_ne(struct netent
*ne
, char *buffer
) {
1594 char **aliases
= NULL
;
1597 char fieldsep
= ':';
1598 int myerrno
= EINVAL
;
1600 if (ne
== NULL
|| buffer
== NULL
) {
1608 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1613 /* n_aliases field. Aliases are separated by commas */
1614 q
= strchr(p
, fieldsep
);
1618 aliases
= splitarray(p
, q
, COMMA
);
1619 if (aliases
== NULL
) {
1626 /* h_addrtype field */
1628 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1632 if (strcmp(tmpbuf
, "AF_INET") == 0)
1633 naddrtype
= AF_INET
;
1634 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1635 naddrtype
= AF_INET6
;
1642 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1646 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1653 ne
->n_aliases
= aliases
;
1654 ne
->n_addrtype
= naddrtype
;
1662 if (name
!= NULL
) free(name
);
1663 free_array(aliases
, 0);
1669 /* ------------------------- struct netent ------------------------- */
1672 /* =========================================================================== */
1676 * static char ** splitarray(const char *buffer, const char *buffend, char delim)
1680 * Split a delim separated astring. Not allowed
1681 * to have two delims next to each other. BUFFER points to begining of
1682 * string, BUFFEND points to one past the end of the string
1683 * (i.e. points at where the null byte would be if null
1688 * Returns a malloced array of pointers, each pointer pointing to a
1689 * malloced string. If BUFEER is an empty string, then return values is
1690 * array of 1 pointer that is NULL. Returns NULL on failure.
1695 splitarray(const char *buffer
, const char *buffend
, char delim
) {
1701 if (buffend
< buffer
)
1703 else if (buffend
> buffer
&& *buffer
== delim
)
1705 else if (buffend
> buffer
&& *(buffend
- 1) == delim
)
1708 /* count the number of field and make sure none are empty */
1709 if (buffend
> buffer
+ 1) {
1710 for (count
= 1, q
= buffer
; q
!= buffend
; q
++) {
1712 if (q
> buffer
&& (*(q
- 1) == delim
)) {
1722 count
++ ; /* for NULL at end */
1723 aptr
= arr
= malloc(count
* sizeof (char *));
1729 memset(arr
, 0x0, count
* sizeof (char *));
1730 for (p
= buffer
; p
< buffend
; p
++) {
1731 for (q
= p
; *q
!= delim
&& q
!= buffend
; q
++)
1733 *aptr
= strndup(p
, q
- p
);
1740 arr
= malloc(sizeof (char *));
1756 * static size_t joinlength(char * const *argv)
1760 * the number of bytes in all the arrays pointed at
1761 * by argv, including their null bytes(which will usually be turned
1768 joinlength(char * const *argv
) {
1771 while (argv
&& *argv
) {
1772 len
+= (strlen(*argv
) + 1);
1782 * int joinarray(char * const *argv, char *buffer, char delim)
1786 * Copy all the ARGV strings into the end of BUFFER
1787 * separating them with DELIM. BUFFER is assumed to have
1788 * enough space to hold everything and to be already null-terminated.
1792 * 0 unless argv or buffer is NULL.
1798 joinarray(char * const *argv
, char *buffer
, char delim
) {
1802 if (argv
== NULL
|| buffer
== NULL
) {
1810 for (p
= argv
; *p
!= NULL
; p
++) {
1812 if (*(p
+ 1) != NULL
) {
1813 strcat(buffer
, sep
);
1822 * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
1826 * Stores in *RES, which is a buffer of length RESLEN, a
1827 * copy of the bytes from *PTR up to and including the first
1828 * instance of DELIM. If *RES is NULL, then it will be
1829 * assigned a malloced buffer to hold the copy. *PTR is
1830 * modified to point at the found delimiter.
1834 * If there was no delimiter, then NULL is returned,
1835 * otherewise *RES is returned.
1840 getfield(char **res
, size_t reslen
, char **ptr
, char delim
) {
1843 if (res
== NULL
|| ptr
== NULL
|| *ptr
== NULL
) {
1848 q
= strchr(*ptr
, delim
);
1855 *res
= strndup(*ptr
, q
- *ptr
);
1857 if ((size_t)(q
- *ptr
+ 1) > reslen
) { /* to big for res */
1861 strncpy(*res
, *ptr
, q
- *ptr
);
1862 (*res
)[q
- *ptr
] = 0x0;
1875 #ifndef HAVE_STRNDUP
1877 * static char * strndup(const char *str, size_t len)
1881 * like strdup, except do len bytes instead of the whole string. Always
1886 * The newly malloced string.
1891 strndup(const char *str
, size_t len
) {
1892 char *p
= malloc(len
+ 1);
1896 strncpy(p
, str
, len
);
1905 * static int strcmp_nws(const char *a, const char *b)
1909 * do a strcmp, except uneven lengths of whitespace compare the same
1916 strcmp_nws(const char *a
, const char *b
) {
1918 if (isspace(*a
) && isspace(*b
)) {
1921 } while (isspace(*a
));
1924 } while (isspace(*b
));
1950 * static void free_array(char **argv, size_t entries)
1954 * Free argv and each of the pointers inside it. The end of
1955 * the array is when a NULL pointer is found inside. If
1956 * entries is > 0, then NULL pointers inside the array do
1957 * not indicate the end of the array.
1962 free_array(char **argv
, size_t entries
) {
1964 int useEntries
= (entries
> 0U);
1969 while ((useEntries
&& entries
> 0U) || *p
) {
1983 /* ************************************************** */
1987 /* takes an option to indicate what sort of marshalling(read the code) and
1988 an argument. If the argument looks like a marshalled buffer(has a ':'
1989 embedded) then it's unmarshalled and the remarshalled and the new string
1990 is compared to the old one.
1994 main(int argc
, char **argv
) {
1996 char *b
= &buffer
[0];
1997 size_t len
= sizeof buffer
;
2000 if (argc
< 2 || argv
[1][0] != '-')
2003 option
= argv
[1][1];
2011 char *p
= argv
[1], *q
= &buff
[0];
2013 while (getfield(&q
, sizeof buff
, &p
, ':') != NULL
) {
2014 printf("field: \"%s\"\n", q
);
2017 printf("p is now \"%s\"\n", p
);
2023 char **x
= splitarray(argv
[1], argv
[1] + strlen(argv
[1]),
2028 printf("split failed\n");
2030 for (p
= x
; p
!= NULL
&& *p
!= NULL
; p
++) {
2031 printf("\"%s\"\n", *p
);
2042 if (strchr(argv
[1], ':') != NULL
) {
2043 if (irp_unmarshall_nw(&ne
, argv
[1]) != 0) {
2044 printf("Unmarhsalling failed\n");
2048 printf("Name: \"%s\"\n", ne
.n_name
);
2050 for (i
= 0 ; ne
.n_aliases
[i
] != NULL
; i
++)
2051 printf("\n\t\"%s\"", ne
.n_aliases
[i
]);
2052 printf("\nAddrtype: %s\n", ADDR_T_STR(ne
.n_addrtype
));
2053 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2054 buffer
, sizeof buffer
);
2055 printf("Net: \"%s\"\n", buffer
);
2056 *((long*)ne
.n_addr
) = htonl(*((long*)ne
.n_addr
));
2057 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2058 buffer
, sizeof buffer
);
2059 printf("Corrected Net: \"%s\"\n", buffer
);
2061 struct netent
*np1
= getnetbyname(argv
[1]);
2062 ne
.n_name
= np1
->n_name
;
2063 ne
.n_aliases
= np1
->n_aliases
;
2064 ne
.n_addrtype
= np1
->n_addrtype
;
2065 ne
.n_addr
= &np1
->n_net
;
2066 ne
.n_length
= (IN_CLASSA(np1
->n_net
) ?
2068 (IN_CLASSB(np1
->n_net
) ?
2070 (IN_CLASSC(np1
->n_net
) ?
2072 np1
->n_net
= htonl(np1
->n_net
);
2073 if (irp_marshall_nw(&ne
, &b
, &len
) != 0) {
2074 printf("Marshalling failed\n");
2083 char **hosts
, **users
, **domains
;
2090 if (strchr(argv
[1], '(') != NULL
) {
2091 if (irp_unmarshall_ng(&ngname
, &entries
,
2092 &hosts
, &users
, &domains
,
2094 printf("unmarshall failed\n");
2098 #define STRVAL(x) (x == NULL ? "*" : x)
2100 printf("%s {\n", ngname
);
2101 for (i
= 0 ; i
< entries
; i
++)
2102 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2105 STRVAL(domains
[i
]));
2109 irp_marshall_ng_start(ngname
, NULL
, &size
);
2110 for (i
= 0 ; i
< entries
; i
++)
2111 irp_marshall_ng_next(hosts
[i
], users
[i
],
2112 domains
[i
], NULL
, &size
);
2113 irp_marshall_ng_end(NULL
, &size
);
2115 buff
= malloc(size
);
2117 irp_marshall_ng_start(ngname
, buff
, &size
);
2118 for (i
= 0 ; i
< entries
; i
++) {
2119 if (irp_marshall_ng_next(hosts
[i
], users
[i
],
2122 printf("next marshalling failed.\n");
2124 irp_marshall_ng_end(buff
, &size
);
2126 if (strcmp_nws(argv
[1], buff
) != 0) {
2127 printf("compare failed:\n\t%s\n\t%s\n",
2130 printf("compare ok\n");
2133 char *h
, *u
, *d
, *buff
;
2136 /* run through two times. First to figure out how
2137 much of a buffer we need. Second to do the
2138 actual marshalling */
2140 setnetgrent(argv
[1]);
2141 irp_marshall_ng_start(argv
[1], NULL
, &size
);
2142 while (getnetgrent(&h
, &u
, &d
) == 1)
2143 irp_marshall_ng_next(h
, u
, d
, NULL
, &size
);
2144 irp_marshall_ng_end(NULL
, &size
);
2145 endnetgrent(argv
[1]);
2147 buff
= malloc(size
);
2149 setnetgrent(argv
[1]);
2150 if (irp_marshall_ng_start(argv
[1], buff
, &size
) != 0)
2151 printf("Marshalling start failed\n");
2153 while (getnetgrent(&h
, &u
, &d
) == 1) {
2154 if (irp_marshall_ng_next(h
, u
, d
, buff
, &size
)
2156 printf("Marshalling failed\n");
2160 irp_marshall_ng_end(buff
, &size
);
2163 printf("success: %s\n", buff
);
2171 struct hostent he
, *hp
;
2175 if (strchr(argv
[1], '@') != NULL
) {
2176 if (irp_unmarshall_ho(&he
, argv
[1]) != 0) {
2177 printf("unmarshall failed\n");
2181 printf("Host: \"%s\"\nAliases:", he
.h_name
);
2182 for (i
= 0 ; he
.h_aliases
[i
] != NULL
; i
++)
2183 printf("\n\t\t\"%s\"", he
.h_aliases
[i
]);
2184 printf("\nAddr Type: \"%s\"\n",
2185 ADDR_T_STR(he
.h_addrtype
));
2186 printf("Length: %d\nAddresses:", he
.h_length
);
2187 for (i
= 0 ; he
.h_addr_list
[i
] != 0 ; i
++) {
2188 inet_ntop(he
.h_addrtype
, he
.h_addr_list
[i
],
2189 buffer
, sizeof buffer
);
2190 printf("\n\t\"%s\"\n", buffer
);
2194 irp_marshall_ho(&he
, &b
, &len
);
2195 if (strcmp(argv
[1], buffer
) != 0) {
2196 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2199 printf("compare ok\n");
2202 if ((hp
= gethostbyname(argv
[1])) == NULL
) {
2203 perror("gethostbyname");
2204 printf("\"%s\"\n", argv
[1]);
2208 if (irp_marshall_ho(hp
, &b
, &len
) != 0) {
2209 printf("irp_marshall_ho failed\n");
2213 printf("success: \"%s\"\n", buffer
);
2223 if (strchr(argv
[1], ':') != NULL
) {
2225 memset(sv
, 0xef, sizeof (struct servent
));
2226 if (irp_unmarshall_sv(sv
, argv
[1]) != 0) {
2227 printf("unmarshall failed\n");
2231 irp_marshall_sv(sv
, &b
, &len
);
2232 if (strcmp(argv
[1], buffer
) != 0) {
2233 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2236 printf("compare ok\n");
2239 if ((sv
= getservbyname(argv
[1], argv
[2])) == NULL
) {
2240 perror("getservent");
2244 if (irp_marshall_sv(sv
, &b
, &len
) != 0) {
2245 printf("irp_marshall_sv failed\n");
2249 printf("success: \"%s\"\n", buffer
);
2258 if (strchr(argv
[1], ':') != NULL
) {
2260 memset(gr
, 0xef, sizeof (struct group
));
2261 if (irp_unmarshall_gr(gr
, argv
[1]) != 0) {
2262 printf("unmarshall failed\n");
2266 irp_marshall_gr(gr
, &b
, &len
);
2267 if (strcmp(argv
[1], buffer
) != 0) {
2268 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2271 printf("compare ok\n");
2274 if ((gr
= getgrnam(argv
[1])) == NULL
) {
2279 if (irp_marshall_gr(gr
, &b
, &len
) != 0) {
2280 printf("irp_marshall_gr failed\n");
2284 printf("success: \"%s\"\n", buffer
);
2294 if (strchr(argv
[1], ':') != NULL
) {
2296 memset(pw
, 0xef, sizeof (*pw
));
2297 if (irp_unmarshall_pw(pw
, argv
[1]) != 0) {
2298 printf("unmarshall failed\n");
2302 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2303 pw
->pw_name
, pw
->pw_passwd
, (long)pw
->pw_uid
,
2305 printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
2306 pw
->pw_class
, (long)pw
->pw_change
, pw
->pw_gecos
);
2307 printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
2308 pw
->pw_shell
, pw
->pw_dir
);
2310 pw
= getpwnam(pw
->pw_name
);
2311 irp_marshall_pw(pw
, &b
, &len
);
2312 if (strcmp(argv
[1], buffer
) != 0) {
2313 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2316 printf("compare ok\n");
2319 if ((pw
= getpwnam(argv
[1])) == NULL
) {
2324 if (irp_marshall_pw(pw
, &b
, &len
) != 0) {
2325 printf("irp_marshall_pw failed\n");
2329 printf("success: \"%s\"\n", buffer
);
2335 printf("Wrong option: %c\n", option
);