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.
53 Check values are in approrpriate endian order
.
55 Double check memory allocations on unmarhsalling
62 #include "port_before.h"
64 #include <sys/types.h>
65 #include <sys/socket.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69 #include <arpa/nameser.h>
83 #include <isc/memcluster.h>
84 #include <isc/irpmarshall.h>
86 #include "port_after.h"
90 static char *strndup(const char *str
, size_t len
);
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
);
99 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
100 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
102 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
104 static char COMMA
= ',';
106 static const char *COMMASTR
= ",";
107 static const char *COLONSTR
= ":";
111 /* See big comment at bottom of irpmarshall.h for description. */
115 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
118 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
126 * 0 on sucess, -1 on failure.
131 irp_marshall_pw(const struct passwd
*pw
, char **buffer
, size_t *len
) {
132 size_t need
= 1 ; /*%< for null byte */
138 const char *fieldsep
= COLONSTR
;
140 if (pw
== NULL
|| len
== NULL
) {
145 sprintf(pwUid
, "%ld", (long)pw
->pw_uid
);
146 sprintf(pwGid
, "%ld", (long)pw
->pw_gid
);
148 #ifdef HAVE_PW_CHANGE
149 sprintf(pwChange
, "%ld", (long)pw
->pw_change
);
155 #ifdef HAVE_PW_EXPIRE
156 sprintf(pwExpire
, "%ld", (long)pw
->pw_expire
);
163 pwClass
= pw
->pw_class
;
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;
179 if (buffer
== NULL
) {
184 if (*buffer
!= NULL
&& need
> *len
) {
189 if (*buffer
== NULL
) {
190 need
+= 2; /*%< for CRLF */
191 *buffer
= memget(need
);
192 if (*buffer
== NULL
) {
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
);
215 * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
223 * 0 on success, -1 on failure
228 irp_unmarshall_pw(struct passwd
*pw
, char *buffer
) {
229 char *name
, *pass
, *class, *gecos
, *dir
, *shell
;
237 char *tb
= &tmpbuf
[0];
239 int myerrno
= EINVAL
;
241 name
= pass
= class = gecos
= dir
= shell
= NULL
;
246 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0) {
250 /* pw_passwd field */
252 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) { /*%< field can be empty */
259 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
263 t
= strtol(tmpbuf
, &tb
, 10);
265 goto error
; /*%< junk in value */
268 if ((long) pwuid
!= t
) { /*%< value must have been too big. */
276 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
280 t
= strtol(tmpbuf
, &tb
, 10);
282 goto error
; /*%< junk in value */
285 if ((long)pwgid
!= t
) { /*%< value must have been too big. */
293 if (getfield(&class, 0, &p
, fieldsep
) == NULL
) {
299 /* pw_change field */
301 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
305 t
= strtol(tmpbuf
, &tb
, 10);
307 goto error
; /*%< junk in value */
309 pwchange
= (time_t)t
;
310 if ((long)pwchange
!= t
) { /*%< value must have been too big. */
316 /* pw_expire field */
318 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
322 t
= strtol(tmpbuf
, &tb
, 10);
324 goto error
; /*%< junk in value */
326 pwexpire
= (time_t)t
;
327 if ((long) pwexpire
!= t
) { /*%< value must have been too big. */
335 if (getfield(&gecos
, 0, &p
, fieldsep
) == NULL
) {
343 if (getfield(&dir
, 0, &p
, fieldsep
) == NULL
) {
351 if (getfield(&shell
, 0, &p
, fieldsep
) == NULL
) {
358 pw
->pw_passwd
= pass
;
361 pw
->pw_gecos
= gecos
;
363 pw
->pw_shell
= shell
;
365 #ifdef HAVE_PW_CHANGE
366 pw
->pw_change
= pwchange
;
369 pw
->pw_class
= class;
371 #ifdef HAVE_PW_EXPIRE
372 pw
->pw_expire
= pwexpire
;
389 /* ------------------------- struct passwd ------------------------- */
390 #endif /* WANT_IRS_PW */
391 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
394 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
402 * 0 on success, -1 on failure
406 irp_marshall_gr(const struct group
*gr
, char **buffer
, size_t *len
) {
407 size_t need
= 1; /*%< for null byte */
409 const char *fieldsep
= COLONSTR
;
411 if (gr
== NULL
|| len
== NULL
) {
416 sprintf(grGid
, "%ld", (long)gr
->gr_gid
);
418 need
+= strlen(gr
->gr_name
) + 1;
419 #ifndef MISSING_GR_PASSWD
420 need
+= strlen(gr
->gr_passwd
) + 1;
424 need
+= strlen(grGid
) + 1;
425 need
+= joinlength(gr
->gr_mem
) + 1;
427 if (buffer
== NULL
) {
432 if (*buffer
!= NULL
&& need
> *len
) {
437 if (*buffer
== NULL
) {
438 need
+= 2; /*%< for CRLF */
439 *buffer
= memget(need
);
440 if (*buffer
== NULL
) {
448 strcpy(*buffer
, gr
->gr_name
); strcat(*buffer
, fieldsep
);
449 #ifndef MISSING_GR_PASSWD
450 strcat(*buffer
, gr
->gr_passwd
);
452 strcat(*buffer
, fieldsep
);
453 strcat(*buffer
, grGid
); strcat(*buffer
, fieldsep
);
454 joinarray(gr
->gr_mem
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
460 * int irp_unmarshall_gr(struct group *gr, char *buffer)
468 * 0 on success and -1 on failure.
473 irp_unmarshall_gr(struct group
*gr
, char *buffer
) {
479 char **members
= NULL
;
483 int myerrno
= EINVAL
;
485 if (gr
== NULL
|| buffer
== NULL
) {
494 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
499 /* gr_passwd field */
501 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) {
508 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
512 t
= strtol(tmpbuf
, &tb
, 10);
514 goto error
; /*%< junk in value */
517 if ((long) grgid
!= t
) { /*%< value must have been too big. */
522 /* gr_mem field. Member names are separated by commas */
523 q
= strchr(p
, fieldsep
);
527 members
= splitarray(p
, q
, COMMA
);
528 if (members
== NULL
) {
536 #ifndef MISSING_GR_PASSWD
537 gr
->gr_passwd
= pass
;
540 gr
->gr_mem
= members
;
554 /* ------------------------- struct group ------------------------- */
559 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
562 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
570 * 0 on success, -1 on failure.
575 irp_marshall_sv(const struct servent
*sv
, char **buffer
, size_t *len
) {
576 size_t need
= 1; /*%< for null byte */
578 const char *fieldsep
= COLONSTR
;
581 if (sv
== NULL
|| len
== NULL
) {
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
);
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;
596 if (buffer
== NULL
) {
601 if (*buffer
!= NULL
&& need
> *len
) {
606 if (*buffer
== NULL
) {
607 need
+= 2; /*%< for CRLF */
608 *buffer
= memget(need
);
609 if (*buffer
== NULL
) {
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
);
626 * int irp_unmarshall_sv(struct servent *sv, char *buffer)
634 * 0 on success, -1 on failure.
639 irp_unmarshall_sv(struct servent
*sv
, char *buffer
) {
645 char **aliases
= NULL
;
649 int myerrno
= EINVAL
;
651 if (sv
== NULL
|| buffer
== NULL
)
659 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
664 /* s_aliases field */
665 q
= strchr(p
, fieldsep
);
669 aliases
= splitarray(p
, q
, COMMA
);
670 if (aliases
== NULL
) {
679 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
683 t
= strtol(tmpbuf
, &tb
, 10);
685 goto error
; /*%< junk in value */
688 if ((long) svport
!= t
) { /*%< value must have been too big. */
691 svport
= htons(svport
);
695 if (getfield(&proto
, 0, &p
, fieldsep
) == NULL
) {
700 sv
->s_aliases
= aliases
;
711 free_array(aliases
, 0);
717 /* ------------------------- struct servent ------------------------- */
719 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
722 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
730 * 0 on success and -1 on failure.
735 irp_marshall_pr(struct protoent
*pr
, char **buffer
, size_t *len
) {
736 size_t need
= 1; /*%< for null byte */
738 const char *fieldsep
= COLONSTR
;
740 if (pr
== NULL
|| len
== NULL
) {
745 sprintf(prProto
, "%d", (int)pr
->p_proto
);
747 need
+= strlen(pr
->p_name
) + 1;
748 need
+= joinlength(pr
->p_aliases
) + 1;
749 need
+= strlen(prProto
) + 1;
751 if (buffer
== NULL
) {
756 if (*buffer
!= NULL
&& need
> *len
) {
761 if (*buffer
== NULL
) {
762 need
+= 2; /*%< for CRLF */
763 *buffer
= memget(need
);
764 if (*buffer
== NULL
) {
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
);
781 * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
789 * 0 on success, -1 on failure
793 int irp_unmarshall_pr(struct protoent
*pr
, char *buffer
) {
798 char **aliases
= NULL
;
802 int myerrno
= EINVAL
;
804 if (pr
== NULL
|| buffer
== NULL
) {
813 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
818 /* p_aliases field */
819 q
= strchr(p
, fieldsep
);
823 aliases
= splitarray(p
, q
, COMMA
);
824 if (aliases
== NULL
) {
833 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
837 t
= strtol(tmpbuf
, &tb
, 10);
839 goto error
; /*%< junk in value */
842 if ((long) prproto
!= t
) { /*%< value must have been too big. */
847 pr
->p_aliases
= aliases
;
848 pr
->p_proto
= prproto
;
856 free_array(aliases
, 0);
861 /* ------------------------- struct protoent ------------------------- */
865 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
868 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
876 * 0 on success, -1 on failure.
881 irp_marshall_ho(struct hostent
*ho
, char **buffer
, size_t *len
) {
882 size_t need
= 1; /*%< for null byte */
890 const char *fieldsep
= "@";
892 if (ho
== NULL
|| len
== NULL
) {
897 switch(ho
->h_addrtype
) {
899 strcpy(hoaddrtype
, "AF_INET");
903 strcpy(hoaddrtype
, "AF_INET6");
911 sprintf(holength
, "%d", ho
->h_length
);
913 need
+= strlen(ho
->h_name
) + 1;
914 need
+= joinlength(ho
->h_aliases
) + 1;
915 need
+= strlen(hoaddrtype
) + 1;
916 need
+= strlen(holength
) + 1;
918 /* we determine an upper bound on the string length needed, not an
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
++)
924 if (buffer
== NULL
) {
929 if (*buffer
!= NULL
&& need
> *len
) {
934 if (*buffer
== NULL
) {
935 need
+= 2; /*%< for CRLF */
936 *buffer
= memget(need
);
937 if (*buffer
== NULL
) {
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
);
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
) {
957 if (*(av
+ 1) != NULL
)
962 strcat(*buffer
, fieldsep
);
968 memput(*buffer
, need
);
975 * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
983 * 0 on success, -1 on failure.
988 irp_unmarshall_ho(struct hostent
*ho
, char *buffer
) {
994 char **aliases
= NULL
;
995 char **hohaddrlist
= NULL
;
1001 char fieldsep
= '@';
1002 int myerrno
= EINVAL
;
1004 if (ho
== NULL
|| buffer
== NULL
) {
1013 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1018 /* h_aliases field */
1019 q
= strchr(p
, fieldsep
);
1023 aliases
= splitarray(p
, q
, COMMA
);
1024 if (aliases
== NULL
) {
1031 /* h_addrtype field */
1033 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1037 if (strcmp(tmpbuf
, "AF_INET") == 0)
1038 hoaddrtype
= AF_INET
;
1039 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1040 hoaddrtype
= AF_INET6
;
1045 /* h_length field */
1047 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1051 t
= strtol(tmpbuf
, &tb
, 10);
1053 goto error
; /*%< junk in value */
1056 if ((long) holength
!= t
) { /*%< value must have been too big. */
1061 /* h_addr_list field */
1062 q
= strchr(p
, fieldsep
);
1066 /* count how many addresss are in there */
1068 for (addrcount
= 1, r
= p
; r
!= q
; r
++) {
1076 hoaddrsize
= (addrcount
+ 1) * sizeof (char *);
1077 hohaddrlist
= malloc(hoaddrsize
);
1078 if (hohaddrlist
== NULL
) {
1083 memset(hohaddrlist
, 0x0, hoaddrsize
);
1085 alist
= hohaddrlist
;
1086 for (t
= 0, r
= p
; r
!= q
; p
= r
+ 1, t
++) {
1088 while (r
!= q
&& *r
!= COMMA
) r
++;
1092 alist
[t
] = malloc(hoaddrtype
== AF_INET
? 4 : 16);
1093 if (alist
[t
] == NULL
) {
1098 if (inet_pton(hoaddrtype
, p
, alist
[t
]) == -1)
1105 ho
->h_aliases
= aliases
;
1106 ho
->h_addrtype
= hoaddrtype
;
1107 ho
->h_length
= holength
;
1108 ho
->h_addr_list
= hohaddrlist
;
1116 free_array(hohaddrlist
, 0);
1117 free_array(aliases
, 0);
1122 /* ------------------------- struct hostent------------------------- */
1126 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1129 * int irp_marshall_ng(const char *host, const char *user,
1130 * const char *domain, char *buffer, size_t *len)
1134 * See note for irp_marshall_ng_start
1138 * 0 on success, 0 on failure.
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
= ",";
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
));
1158 if (buffer
== NULL
) {
1161 } else if (*buffer
!= NULL
&& need
> *len
) {
1166 if (*buffer
== NULL
) {
1167 need
+= 2; /*%< for CRLF */
1168 *buffer
= memget(need
);
1169 if (*buffer
== NULL
) {
1178 (*buffer
)[1] = '\0';
1181 strcat(*buffer
, host
);
1182 strcat(*buffer
, fieldsep
);
1185 strcat(*buffer
, user
);
1186 strcat(*buffer
, fieldsep
);
1189 strcat(*buffer
, domain
);
1190 strcat(*buffer
, ")");
1200 * int irp_unmarshall_ng(const char **host, const char **user,
1201 * const char **domain, char *buffer)
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.
1211 * 0 on success and -1 on failure.
1215 irp_unmarshall_ng(const char **hostp
, const char **userp
, const char **domainp
,
1219 char fieldsep
= ',';
1220 int myerrno
= EINVAL
;
1221 char *host
, *user
, *domain
;
1223 if (userp
== NULL
|| hostp
== NULL
||
1224 domainp
== NULL
|| buffer
== NULL
) {
1229 host
= user
= domain
= NULL
;
1232 while (isspace((unsigned char)*p
)) {
1240 while (*q
&& *q
!= fieldsep
)
1244 } else if (q
> p
+ 1) {
1245 host
= strndup(p
, q
- p
);
1251 } else if (*p
!= fieldsep
) {
1253 while (*q
&& *q
!= fieldsep
)
1258 user
= strndup(p
, q
- p
);
1265 } else if (*p
!= ')') {
1267 while (*q
&& *q
!= ')')
1272 domain
= strndup(p
, q
- p
);
1289 /* ------------------------- struct netgrp ------------------------- */
1294 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1297 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1305 * 0 on success and -1 on failure.
1310 irp_marshall_nw(struct nwent
*ne
, char **buffer
, size_t *len
) {
1311 size_t need
= 1; /*%< for null byte */
1313 char nNet
[MAXPADDRSIZE
];
1314 const char *fieldsep
= COLONSTR
;
1316 if (ne
== NULL
|| len
== NULL
) {
1320 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1322 if (inet_net_ntop(ne
->n_addrtype
, ne
->n_addr
, ne
->n_length
,
1323 nNet
, sizeof nNet
) == NULL
) {
1328 need
+= strlen(ne
->n_name
) + 1;
1329 need
+= joinlength(ne
->n_aliases
) + 1;
1330 need
+= strlen(nAddrType
) + 1;
1331 need
+= strlen(nNet
) + 1;
1333 if (buffer
== NULL
) {
1338 if (*buffer
!= NULL
&& need
> *len
) {
1343 if (*buffer
== NULL
) {
1344 need
+= 2; /*%< for CRLF */
1345 *buffer
= memget(need
);
1346 if (*buffer
== NULL
) {
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
);
1363 * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1371 * 0 on success and -1 on failure.
1376 irp_unmarshall_nw(struct nwent
*ne
, char *buffer
) {
1382 char **aliases
= NULL
;
1385 char fieldsep
= ':';
1386 int myerrno
= EINVAL
;
1388 if (ne
== NULL
|| buffer
== NULL
) {
1396 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1401 /* n_aliases field. Aliases are separated by commas */
1402 q
= strchr(p
, fieldsep
);
1406 aliases
= splitarray(p
, q
, COMMA
);
1407 if (aliases
== NULL
) {
1414 /* h_addrtype field */
1416 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1420 if (strcmp(tmpbuf
, "AF_INET") == 0)
1421 naddrtype
= AF_INET
;
1422 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1423 naddrtype
= AF_INET6
;
1430 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1435 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1440 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
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
) {
1451 memcpy(ne
->n_addr
, &nnet
, sizeof nnet
);
1459 free_array(aliases
, 0);
1465 /* ------------------------- struct nwent ------------------------- */
1468 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1471 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1479 * 0 on success and -1 on failure.
1484 irp_marshall_ne(struct netent
*ne
, char **buffer
, size_t *len
) {
1485 size_t need
= 1; /*%< for null byte */
1487 char nNet
[MAXPADDRSIZE
];
1488 const char *fieldsep
= COLONSTR
;
1491 if (ne
== NULL
|| len
== NULL
) {
1495 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1497 nval
= htonl(ne
->n_net
);
1498 if (inet_ntop(ne
->n_addrtype
, &nval
, nNet
, sizeof nNet
) == NULL
) {
1502 need
+= strlen(ne
->n_name
) + 1;
1503 need
+= joinlength(ne
->n_aliases
) + 1;
1504 need
+= strlen(nAddrType
) + 1;
1505 need
+= strlen(nNet
) + 1;
1507 if (buffer
== NULL
) {
1512 if (*buffer
!= NULL
&& need
> *len
) {
1517 if (*buffer
== NULL
) {
1518 need
+= 2; /*%< for CRLF */
1519 *buffer
= memget(need
);
1520 if (*buffer
== NULL
) {
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
);
1537 * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1545 * 0 on success and -1 on failure.
1550 irp_unmarshall_ne(struct netent
*ne
, char *buffer
) {
1556 char **aliases
= NULL
;
1559 char fieldsep
= ':';
1560 int myerrno
= EINVAL
;
1562 if (ne
== NULL
|| buffer
== NULL
) {
1570 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1575 /* n_aliases field. Aliases are separated by commas */
1576 q
= strchr(p
, fieldsep
);
1580 aliases
= splitarray(p
, q
, COMMA
);
1581 if (aliases
== NULL
) {
1588 /* h_addrtype field */
1590 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1594 if (strcmp(tmpbuf
, "AF_INET") == 0)
1595 naddrtype
= AF_INET
;
1596 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1597 naddrtype
= AF_INET6
;
1604 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1608 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1615 ne
->n_aliases
= aliases
;
1616 ne
->n_addrtype
= naddrtype
;
1625 free_array(aliases
, 0);
1631 /* ------------------------- struct netent ------------------------- */
1634 /* =========================================================================== */
1637 * static char ** splitarray(const char *buffer, const char *buffend, char delim)
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
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.
1656 splitarray(const char *buffer
, const char *buffend
, char delim
) {
1662 if (buffend
< buffer
)
1664 else if (buffend
> buffer
&& *buffer
== delim
)
1666 else if (buffend
> buffer
&& *(buffend
- 1) == delim
)
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
++) {
1673 if (q
> buffer
&& (*(q
- 1) == delim
)) {
1683 count
++ ; /*%< for NULL at end */
1684 aptr
= arr
= malloc(count
* sizeof (char *));
1690 memset(arr
, 0x0, count
* sizeof (char *));
1691 for (p
= buffer
; p
< buffend
; p
++) {
1692 for (q
= p
; *q
!= delim
&& q
!= buffend
; q
++)
1694 *aptr
= strndup(p
, q
- p
);
1701 arr
= malloc(sizeof (char *));
1714 * static size_t joinlength(char * const *argv)
1718 * the number of bytes in all the arrays pointed at
1719 * by argv, including their null bytes(which will usually be turned
1726 joinlength(char * const *argv
) {
1729 while (argv
&& *argv
) {
1730 len
+= (strlen(*argv
) + 1);
1738 * int joinarray(char * const *argv, char *buffer, char delim)
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.
1748 * 0 unless argv or buffer is NULL.
1754 joinarray(char * const *argv
, char *buffer
, char delim
) {
1758 if (argv
== NULL
|| buffer
== NULL
) {
1766 for (p
= argv
; *p
!= NULL
; p
++) {
1768 if (*(p
+ 1) != NULL
) {
1769 strcat(buffer
, sep
);
1777 * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
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.
1789 * If there was no delimiter, then NULL is returned,
1790 * otherewise *RES is returned.
1795 getfield(char **res
, size_t reslen
, char **ptr
, char delim
) {
1798 if (res
== NULL
|| ptr
== NULL
|| *ptr
== NULL
) {
1803 q
= strchr(*ptr
, delim
);
1810 *res
= strndup(*ptr
, q
- *ptr
);
1812 if ((size_t)(q
- *ptr
+ 1) > reslen
) { /*%< to big for res */
1816 strncpy(*res
, *ptr
, q
- *ptr
);
1817 (*res
)[q
- *ptr
] = 0x0;
1830 #ifndef HAVE_STRNDUP
1832 * static char * strndup(const char *str, size_t len)
1836 * like strdup, except do len bytes instead of the whole string. Always
1841 * The newly malloced string.
1846 strndup(const char *str
, size_t len
) {
1847 char *p
= malloc(len
+ 1);
1851 strncpy(p
, str
, len
);
1860 * static int strcmp_nws(const char *a, const char *b)
1864 * do a strcmp, except uneven lengths of whitespace compare the same
1871 strcmp_nws(const char *a
, const char *b
) {
1873 if (isspace(*a
) && isspace(*b
)) {
1876 } while (isspace(*a
));
1879 } while (isspace(*b
));
1901 * static void free_array(char **argv, size_t entries)
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.
1913 free_array(char **argv
, size_t entries
) {
1915 int useEntries
= (entries
> 0U);
1920 while ((useEntries
&& entries
> 0U) || *p
) {
1933 /* ************************************************** */
1937 /*% takes an option to indicate what sort of marshalling(read the code) and
1938 an argument. If the argument looks like a marshalled buffer(has a ':'
1939 embedded) then it's unmarshalled and the remarshalled and the new string
1940 is compared to the old one.
1944 main(int argc
, char **argv
) {
1946 char *b
= &buffer
[0];
1947 size_t len
= sizeof buffer
;
1950 if (argc
< 2 || argv
[1][0] != '-')
1953 option
= argv
[1][1];
1961 char *p
= argv
[1], *q
= &buff
[0];
1963 while (getfield(&q
, sizeof buff
, &p
, ':') != NULL
) {
1964 printf("field: \"%s\"\n", q
);
1967 printf("p is now \"%s\"\n", p
);
1973 char **x
= splitarray(argv
[1], argv
[1] + strlen(argv
[1]),
1978 printf("split failed\n");
1980 for (p
= x
; p
!= NULL
&& *p
!= NULL
; p
++) {
1981 printf("\"%s\"\n", *p
);
1992 if (strchr(argv
[1], ':') != NULL
) {
1993 if (irp_unmarshall_nw(&ne
, argv
[1]) != 0) {
1994 printf("Unmarhsalling failed\n");
1998 printf("Name: \"%s\"\n", ne
.n_name
);
2000 for (i
= 0 ; ne
.n_aliases
[i
] != NULL
; i
++)
2001 printf("\n\t\"%s\"", ne
.n_aliases
[i
]);
2002 printf("\nAddrtype: %s\n", ADDR_T_STR(ne
.n_addrtype
));
2003 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2004 buffer
, sizeof buffer
);
2005 printf("Net: \"%s\"\n", buffer
);
2006 *((long*)ne
.n_addr
) = htonl(*((long*)ne
.n_addr
));
2007 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2008 buffer
, sizeof buffer
);
2009 printf("Corrected Net: \"%s\"\n", buffer
);
2011 struct netent
*np1
= getnetbyname(argv
[1]);
2012 ne
.n_name
= np1
->n_name
;
2013 ne
.n_aliases
= np1
->n_aliases
;
2014 ne
.n_addrtype
= np1
->n_addrtype
;
2015 ne
.n_addr
= &np1
->n_net
;
2016 ne
.n_length
= (IN_CLASSA(np1
->n_net
) ?
2018 (IN_CLASSB(np1
->n_net
) ?
2020 (IN_CLASSC(np1
->n_net
) ?
2022 np1
->n_net
= htonl(np1
->n_net
);
2023 if (irp_marshall_nw(&ne
, &b
, &len
) != 0) {
2024 printf("Marshalling failed\n");
2033 char **hosts
, **users
, **domains
;
2040 if (strchr(argv
[1], '(') != NULL
) {
2041 if (irp_unmarshall_ng(&ngname
, &entries
,
2042 &hosts
, &users
, &domains
,
2044 printf("unmarshall failed\n");
2048 #define STRVAL(x) (x == NULL ? "*" : x)
2050 printf("%s {\n", ngname
);
2051 for (i
= 0 ; i
< entries
; i
++)
2052 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2055 STRVAL(domains
[i
]));
2059 irp_marshall_ng_start(ngname
, NULL
, &size
);
2060 for (i
= 0 ; i
< entries
; i
++)
2061 irp_marshall_ng_next(hosts
[i
], users
[i
],
2062 domains
[i
], NULL
, &size
);
2063 irp_marshall_ng_end(NULL
, &size
);
2065 buff
= malloc(size
);
2067 irp_marshall_ng_start(ngname
, buff
, &size
);
2068 for (i
= 0 ; i
< entries
; i
++) {
2069 if (irp_marshall_ng_next(hosts
[i
], users
[i
],
2072 printf("next marshalling failed.\n");
2074 irp_marshall_ng_end(buff
, &size
);
2076 if (strcmp_nws(argv
[1], buff
) != 0) {
2077 printf("compare failed:\n\t%s\n\t%s\n",
2080 printf("compare ok\n");
2083 char *h
, *u
, *d
, *buff
;
2086 /* run through two times. First to figure out how
2087 much of a buffer we need. Second to do the
2088 actual marshalling */
2090 setnetgrent(argv
[1]);
2091 irp_marshall_ng_start(argv
[1], NULL
, &size
);
2092 while (getnetgrent(&h
, &u
, &d
) == 1)
2093 irp_marshall_ng_next(h
, u
, d
, NULL
, &size
);
2094 irp_marshall_ng_end(NULL
, &size
);
2095 endnetgrent(argv
[1]);
2097 buff
= malloc(size
);
2099 setnetgrent(argv
[1]);
2100 if (irp_marshall_ng_start(argv
[1], buff
, &size
) != 0)
2101 printf("Marshalling start failed\n");
2103 while (getnetgrent(&h
, &u
, &d
) == 1) {
2104 if (irp_marshall_ng_next(h
, u
, d
, buff
, &size
)
2106 printf("Marshalling failed\n");
2110 irp_marshall_ng_end(buff
, &size
);
2113 printf("success: %s\n", buff
);
2121 struct hostent he
, *hp
;
2125 if (strchr(argv
[1], '@') != NULL
) {
2126 if (irp_unmarshall_ho(&he
, argv
[1]) != 0) {
2127 printf("unmarshall failed\n");
2131 printf("Host: \"%s\"\nAliases:", he
.h_name
);
2132 for (i
= 0 ; he
.h_aliases
[i
] != NULL
; i
++)
2133 printf("\n\t\t\"%s\"", he
.h_aliases
[i
]);
2134 printf("\nAddr Type: \"%s\"\n",
2135 ADDR_T_STR(he
.h_addrtype
));
2136 printf("Length: %d\nAddresses:", he
.h_length
);
2137 for (i
= 0 ; he
.h_addr_list
[i
] != 0 ; i
++) {
2138 inet_ntop(he
.h_addrtype
, he
.h_addr_list
[i
],
2139 buffer
, sizeof buffer
);
2140 printf("\n\t\"%s\"\n", buffer
);
2144 irp_marshall_ho(&he
, &b
, &len
);
2145 if (strcmp(argv
[1], buffer
) != 0) {
2146 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2149 printf("compare ok\n");
2152 if ((hp
= gethostbyname(argv
[1])) == NULL
) {
2153 perror("gethostbyname");
2154 printf("\"%s\"\n", argv
[1]);
2158 if (irp_marshall_ho(hp
, &b
, &len
) != 0) {
2159 printf("irp_marshall_ho failed\n");
2163 printf("success: \"%s\"\n", buffer
);
2173 if (strchr(argv
[1], ':') != NULL
) {
2175 memset(sv
, 0xef, sizeof (struct servent
));
2176 if (irp_unmarshall_sv(sv
, argv
[1]) != 0) {
2177 printf("unmarshall failed\n");
2181 irp_marshall_sv(sv
, &b
, &len
);
2182 if (strcmp(argv
[1], buffer
) != 0) {
2183 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2186 printf("compare ok\n");
2189 if ((sv
= getservbyname(argv
[1], argv
[2])) == NULL
) {
2190 perror("getservent");
2194 if (irp_marshall_sv(sv
, &b
, &len
) != 0) {
2195 printf("irp_marshall_sv failed\n");
2199 printf("success: \"%s\"\n", buffer
);
2208 if (strchr(argv
[1], ':') != NULL
) {
2210 memset(gr
, 0xef, sizeof (struct group
));
2211 if (irp_unmarshall_gr(gr
, argv
[1]) != 0) {
2212 printf("unmarshall failed\n");
2216 irp_marshall_gr(gr
, &b
, &len
);
2217 if (strcmp(argv
[1], buffer
) != 0) {
2218 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2221 printf("compare ok\n");
2224 if ((gr
= getgrnam(argv
[1])) == NULL
) {
2229 if (irp_marshall_gr(gr
, &b
, &len
) != 0) {
2230 printf("irp_marshall_gr failed\n");
2234 printf("success: \"%s\"\n", buffer
);
2244 if (strchr(argv
[1], ':') != NULL
) {
2246 memset(pw
, 0xef, sizeof (*pw
));
2247 if (irp_unmarshall_pw(pw
, argv
[1]) != 0) {
2248 printf("unmarshall failed\n");
2252 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2253 pw
->pw_name
, pw
->pw_passwd
, (long)pw
->pw_uid
,
2255 printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
2256 pw
->pw_class
, (long)pw
->pw_change
, pw
->pw_gecos
);
2257 printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
2258 pw
->pw_shell
, pw
->pw_dir
);
2260 pw
= getpwnam(pw
->pw_name
);
2261 irp_marshall_pw(pw
, &b
, &len
);
2262 if (strcmp(argv
[1], buffer
) != 0) {
2263 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2266 printf("compare ok\n");
2269 if ((pw
= getpwnam(argv
[1])) == NULL
) {
2274 if (irp_marshall_pw(pw
, &b
, &len
) != 0) {
2275 printf("irp_marshall_pw failed\n");
2279 printf("success: \"%s\"\n", buffer
);
2285 printf("Wrong option: %c\n", option
);