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.5.18.2 2006/03/10 00:20:08 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 +++++++++++++++++++++++++ */
122 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
130 * 0 on sucess, -1 on failure.
135 irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) {
136 size_t need = 1 ; /*%< for null byte */
142 const char *fieldsep = COLONSTR;
144 if (pw == NULL || len == NULL) {
149 sprintf(pwUid, "%ld", (long)pw->pw_uid);
150 sprintf(pwGid, "%ld", (long)pw->pw_gid);
152 #ifdef HAVE_PW_CHANGE
153 sprintf(pwChange, "%ld", (long)pw->pw_change);
159 #ifdef HAVE_PW_EXPIRE
160 sprintf(pwExpire, "%ld", (long)pw->pw_expire);
167 pwClass = pw->pw_class;
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;
183 if (buffer == NULL) {
188 if (*buffer != NULL && need > *len) {
193 if (*buffer == NULL) {
194 need += 2; /*%< for CRLF */
195 *buffer = memget(need);
196 if (*buffer == NULL) {
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);
219 * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
227 * 0 on success, -1 on failure
232 irp_unmarshall_pw(struct passwd *pw, char *buffer) {
233 char *name, *pass, *class, *gecos, *dir, *shell;
241 char *tb = &tmpbuf[0];
243 int myerrno = EINVAL;
245 name = pass = class = gecos = dir = shell = NULL;
250 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
254 /* pw_passwd field */
256 if (getfield(&pass, 0, &p, fieldsep) == NULL) { /*%< field can be empty */
263 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
267 t = strtol(tmpbuf, &tb, 10);
269 goto error; /*%< junk in value */
272 if ((long) pwuid != t) { /*%< value must have been too big. */
280 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
284 t = strtol(tmpbuf, &tb, 10);
286 goto error; /*%< junk in value */
289 if ((long)pwgid != t) { /*%< value must have been too big. */
297 if (getfield(&class, 0, &p, fieldsep) == NULL) {
303 /* pw_change field */
305 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
309 t = strtol(tmpbuf, &tb, 10);
311 goto error; /*%< junk in value */
313 pwchange = (time_t)t;
314 if ((long)pwchange != t) { /*%< value must have been too big. */
320 /* pw_expire field */
322 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
326 t = strtol(tmpbuf, &tb, 10);
328 goto error; /*%< junk in value */
330 pwexpire = (time_t)t;
331 if ((long) pwexpire != t) { /*%< value must have been too big. */
339 if (getfield(&gecos, 0, &p, fieldsep) == NULL) {
347 if (getfield(&dir, 0, &p, fieldsep) == NULL) {
355 if (getfield(&shell, 0, &p, fieldsep) == NULL) {
362 pw->pw_passwd = pass;
365 pw->pw_gecos = gecos;
367 pw->pw_shell = shell;
369 #ifdef HAVE_PW_CHANGE
370 pw->pw_change = pwchange;
373 pw->pw_class = class;
375 #ifdef HAVE_PW_EXPIRE
376 pw->pw_expire = pwexpire;
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);
393 /* ------------------------- struct passwd ------------------------- */
394 #endif /* WANT_IRS_PW */
395 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
398 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
406 * 0 on success, -1 on failure
410 irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) {
411 size_t need = 1; /*%< for null byte */
413 const char *fieldsep = COLONSTR;
415 if (gr == NULL || len == NULL) {
420 sprintf(grGid, "%ld", (long)gr->gr_gid);
422 need += strlen(gr->gr_name) + 1;
423 #ifndef MISSING_GR_PASSWD
424 need += strlen(gr->gr_passwd) + 1;
428 need += strlen(grGid) + 1;
429 need += joinlength(gr->gr_mem) + 1;
431 if (buffer == NULL) {
436 if (*buffer != NULL && need > *len) {
441 if (*buffer == NULL) {
442 need += 2; /*%< for CRLF */
443 *buffer = memget(need);
444 if (*buffer == NULL) {
452 strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep);
453 #ifndef MISSING_GR_PASSWD
454 strcat(*buffer, gr->gr_passwd);
456 strcat(*buffer, fieldsep);
457 strcat(*buffer, grGid); strcat(*buffer, fieldsep);
458 joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep);
464 * int irp_unmarshall_gr(struct group *gr, char *buffer)
472 * 0 on success and -1 on failure.
477 irp_unmarshall_gr(struct group *gr, char *buffer) {
483 char **members = NULL;
487 int myerrno = EINVAL;
489 if (gr == NULL || buffer == NULL) {
498 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
503 /* gr_passwd field */
505 if (getfield(&pass, 0, &p, fieldsep) == NULL) {
512 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
516 t = strtol(tmpbuf, &tb, 10);
518 goto error; /*%< junk in value */
521 if ((long) grgid != t) { /*%< value must have been too big. */
526 /* gr_mem field. Member names are separated by commas */
527 q = strchr(p, fieldsep);
531 members = splitarray(p, q, COMMA);
532 if (members == NULL) {
540 #ifndef MISSING_GR_PASSWD
541 gr->gr_passwd = pass;
544 gr->gr_mem = members;
551 if (name != NULL) free(name);
552 if (pass != NULL) free(pass);
558 /* ------------------------- struct group ------------------------- */
563 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
566 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
574 * 0 on success, -1 on failure.
579 irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) {
580 size_t need = 1; /*%< for null byte */
582 const char *fieldsep = COLONSTR;
585 if (sv == NULL || len == NULL) {
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);
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;
600 if (buffer == NULL) {
605 if (*buffer != NULL && need > *len) {
610 if (*buffer == NULL) {
611 need += 2; /*%< for CRLF */
612 *buffer = memget(need);
613 if (*buffer == NULL) {
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);
630 * int irp_unmarshall_sv(struct servent *sv, char *buffer)
638 * 0 on success, -1 on failure.
643 irp_unmarshall_sv(struct servent *sv, char *buffer) {
649 char **aliases = NULL;
653 int myerrno = EINVAL;
655 if (sv == NULL || buffer == NULL)
663 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
668 /* s_aliases field */
669 q = strchr(p, fieldsep);
673 aliases = splitarray(p, q, COMMA);
674 if (aliases == NULL) {
683 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
687 t = strtol(tmpbuf, &tb, 10);
689 goto error; /*%< junk in value */
692 if ((long) svport != t) { /*%< value must have been too big. */
695 svport = htons(svport);
699 if (getfield(&proto, 0, &p, fieldsep) == NULL) {
704 sv->s_aliases = aliases;
713 if (name != NULL) free(name);
714 if (proto != NULL) free(proto);
715 free_array(aliases, 0);
721 /* ------------------------- struct servent ------------------------- */
723 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
726 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
734 * 0 on success and -1 on failure.
739 irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) {
740 size_t need = 1; /*%< for null byte */
742 const char *fieldsep = COLONSTR;
744 if (pr == NULL || len == NULL) {
749 sprintf(prProto, "%d", (int)pr->p_proto);
751 need += strlen(pr->p_name) + 1;
752 need += joinlength(pr->p_aliases) + 1;
753 need += strlen(prProto) + 1;
755 if (buffer == NULL) {
760 if (*buffer != NULL && need > *len) {
765 if (*buffer == NULL) {
766 need += 2; /*%< for CRLF */
767 *buffer = memget(need);
768 if (*buffer == NULL) {
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);
785 * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
793 * 0 on success, -1 on failure
797 int irp_unmarshall_pr(struct protoent *pr, char *buffer) {
802 char **aliases = NULL;
806 int myerrno = EINVAL;
808 if (pr == NULL || buffer == NULL) {
817 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
822 /* p_aliases field */
823 q = strchr(p, fieldsep);
827 aliases = splitarray(p, q, COMMA);
828 if (aliases == NULL) {
837 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
841 t = strtol(tmpbuf, &tb, 10);
843 goto error; /*%< junk in value */
846 if ((long) prproto != t) { /*%< value must have been too big. */
851 pr->p_aliases = aliases;
852 pr->p_proto = prproto;
859 if (name != NULL) free(name);
860 free_array(aliases, 0);
865 /* ------------------------- struct protoent ------------------------- */
869 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
872 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
880 * 0 on success, -1 on failure.
885 irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) {
886 size_t need = 1; /*%< for null byte */
894 const char *fieldsep = "@";
896 if (ho == NULL || len == NULL) {
901 switch(ho->h_addrtype) {
903 strcpy(hoaddrtype, "AF_INET");
907 strcpy(hoaddrtype, "AF_INET6");
915 sprintf(holength, "%d", ho->h_length);
917 need += strlen(ho->h_name) + 1;
918 need += joinlength(ho->h_aliases) + 1;
919 need += strlen(hoaddrtype) + 1;
920 need += strlen(holength) + 1;
922 /* we determine an upper bound on the string length needed, not an
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++)
928 if (buffer == NULL) {
933 if (*buffer != NULL && need > *len) {
938 if (*buffer == NULL) {
939 need += 2; /*%< for CRLF */
940 *buffer = memget(need);
941 if (*buffer == NULL) {
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);
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) {
961 if (*(av + 1) != NULL)
966 strcat(*buffer, fieldsep);
972 memput(*buffer, need);
979 * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
987 * 0 on success, -1 on failure.
992 irp_unmarshall_ho(struct hostent *ho, char *buffer) {
998 char **aliases = NULL;
999 char **hohaddrlist = NULL;
1005 char fieldsep = '@';
1006 int myerrno = EINVAL;
1008 if (ho == NULL || buffer == NULL) {
1017 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1022 /* h_aliases field */
1023 q = strchr(p, fieldsep);
1027 aliases = splitarray(p, q, COMMA);
1028 if (aliases == NULL) {
1035 /* h_addrtype field */
1037 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1041 if (strcmp(tmpbuf, "AF_INET") == 0)
1042 hoaddrtype = AF_INET;
1043 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1044 hoaddrtype = AF_INET6;
1049 /* h_length field */
1051 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1055 t = strtol(tmpbuf, &tb, 10);
1057 goto error; /*%< junk in value */
1060 if ((long) holength != t) { /*%< value must have been too big. */
1065 /* h_addr_list field */
1066 q = strchr(p, fieldsep);
1070 /* count how many addresss are in there */
1072 for (addrcount = 1, r = p ; r != q ; r++) {
1080 hoaddrsize = (addrcount + 1) * sizeof (char *);
1081 hohaddrlist = malloc(hoaddrsize);
1082 if (hohaddrlist == NULL) {
1087 memset(hohaddrlist, 0x0, hoaddrsize);
1089 alist = hohaddrlist;
1090 for (t = 0, r = p ; r != q ; p = r + 1, t++) {
1092 while (r != q && *r != COMMA) r++;
1096 alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16);
1097 if (alist[t] == NULL) {
1102 if (inet_pton(hoaddrtype, p, alist[t]) == -1)
1109 ho->h_aliases = aliases;
1110 ho->h_addrtype = hoaddrtype;
1111 ho->h_length = holength;
1112 ho->h_addr_list = hohaddrlist;
1119 if (name != NULL) free(name);
1120 free_array(hohaddrlist, 0);
1121 free_array(aliases, 0);
1126 /* ------------------------- struct hostent------------------------- */
1130 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1133 * int irp_marshall_ng(const char *host, const char *user,
1134 * const char *domain, char *buffer, size_t *len)
1138 * See note for irp_marshall_ng_start
1142 * 0 on success, 0 on failure.
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 = ",";
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));
1162 if (buffer == NULL) {
1165 } else if (*buffer != NULL && need > *len) {
1170 if (*buffer == NULL) {
1171 need += 2; /*%< for CRLF */
1172 *buffer = memget(need);
1173 if (*buffer == NULL) {
1182 (*buffer)[1] = '\0';
1185 strcat(*buffer, host);
1186 strcat(*buffer, fieldsep);
1189 strcat(*buffer, user);
1190 strcat(*buffer, fieldsep);
1193 strcat(*buffer, domain);
1194 strcat(*buffer, ")");
1204 * int irp_unmarshall_ng(const char **host, const char **user,
1205 * const char **domain, char *buffer)
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.
1215 * 0 on success and -1 on failure.
1219 irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp,
1223 char fieldsep = ',';
1224 int myerrno = EINVAL;
1225 char *host, *user, *domain;
1227 if (userp == NULL || hostp == NULL ||
1228 domainp == NULL || buffer == NULL) {
1233 host = user = domain = NULL;
1236 while (isspace((unsigned char)*p)) {
1244 while (*q && *q != fieldsep)
1248 } else if (q > p + 1) {
1249 host = strndup(p, q - p);
1255 } else if (*p != fieldsep) {
1257 while (*q && *q != fieldsep)
1262 user = strndup(p, q - p);
1269 } else if (*p != ')') {
1271 while (*q && *q != ')')
1276 domain = strndup(p, q - p);
1287 if (host != NULL) free(host);
1288 if (user != NULL) free(user);
1293 /* ------------------------- struct netgrp ------------------------- */
1298 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1301 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1309 * 0 on success and -1 on failure.
1314 irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) {
1315 size_t need = 1; /*%< for null byte */
1317 char nNet[MAXPADDRSIZE];
1318 const char *fieldsep = COLONSTR;
1320 if (ne == NULL || len == NULL) {
1324 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1326 if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length,
1327 nNet, sizeof nNet) == NULL) {
1332 need += strlen(ne->n_name) + 1;
1333 need += joinlength(ne->n_aliases) + 1;
1334 need += strlen(nAddrType) + 1;
1335 need += strlen(nNet) + 1;
1337 if (buffer == NULL) {
1342 if (*buffer != NULL && need > *len) {
1347 if (*buffer == NULL) {
1348 need += 2; /*%< for CRLF */
1349 *buffer = memget(need);
1350 if (*buffer == NULL) {
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);
1367 * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1375 * 0 on success and -1 on failure.
1380 irp_unmarshall_nw(struct nwent *ne, char *buffer) {
1386 char **aliases = NULL;
1389 char fieldsep = ':';
1390 int myerrno = EINVAL;
1392 if (ne == NULL || buffer == NULL) {
1400 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1405 /* n_aliases field. Aliases are separated by commas */
1406 q = strchr(p, fieldsep);
1410 aliases = splitarray(p, q, COMMA);
1411 if (aliases == NULL) {
1418 /* h_addrtype field */
1420 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1424 if (strcmp(tmpbuf, "AF_INET") == 0)
1425 naddrtype = AF_INET;
1426 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1427 naddrtype = AF_INET6;
1434 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1439 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1444 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
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) {
1455 memcpy(ne->n_addr, &nnet, sizeof nnet);
1462 if (name != NULL) free(name);
1463 free_array(aliases, 0);
1469 /* ------------------------- struct nwent ------------------------- */
1472 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1475 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1483 * 0 on success and -1 on failure.
1488 irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) {
1489 size_t need = 1; /*%< for null byte */
1491 char nNet[MAXPADDRSIZE];
1492 const char *fieldsep = COLONSTR;
1495 if (ne == NULL || len == NULL) {
1499 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1501 nval = htonl(ne->n_net);
1502 if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) {
1506 need += strlen(ne->n_name) + 1;
1507 need += joinlength(ne->n_aliases) + 1;
1508 need += strlen(nAddrType) + 1;
1509 need += strlen(nNet) + 1;
1511 if (buffer == NULL) {
1516 if (*buffer != NULL && need > *len) {
1521 if (*buffer == NULL) {
1522 need += 2; /*%< for CRLF */
1523 *buffer = memget(need);
1524 if (*buffer == NULL) {
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);
1541 * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1549 * 0 on success and -1 on failure.
1554 irp_unmarshall_ne(struct netent *ne, char *buffer) {
1560 char **aliases = NULL;
1563 char fieldsep = ':';
1564 int myerrno = EINVAL;
1566 if (ne == NULL || buffer == NULL) {
1574 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1579 /* n_aliases field. Aliases are separated by commas */
1580 q = strchr(p, fieldsep);
1584 aliases = splitarray(p, q, COMMA);
1585 if (aliases == NULL) {
1592 /* h_addrtype field */
1594 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1598 if (strcmp(tmpbuf, "AF_INET") == 0)
1599 naddrtype = AF_INET;
1600 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1601 naddrtype = AF_INET6;
1608 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1612 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1619 ne->n_aliases = aliases;
1620 ne->n_addrtype = naddrtype;
1628 if (name != NULL) free(name);
1629 free_array(aliases, 0);
1635 /* ------------------------- struct netent ------------------------- */
1638 /* =========================================================================== */
1641 * static char ** splitarray(const char *buffer, const char *buffend, char delim)
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
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.
1660 splitarray(const char *buffer, const char *buffend, char delim) {
1666 if (buffend < buffer)
1668 else if (buffend > buffer && *buffer == delim)
1670 else if (buffend > buffer && *(buffend - 1) == delim)
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++) {
1677 if (q > buffer && (*(q - 1) == delim)) {
1687 count++ ; /*%< for NULL at end */
1688 aptr = arr = malloc(count * sizeof (char *));
1694 memset(arr, 0x0, count * sizeof (char *));
1695 for (p = buffer ; p < buffend ; p++) {
1696 for (q = p ; *q != delim && q != buffend ; q++)
1698 *aptr = strndup(p, q - p);
1705 arr = malloc(sizeof (char *));
1718 * static size_t joinlength(char * const *argv)
1722 * the number of bytes in all the arrays pointed at
1723 * by argv, including their null bytes(which will usually be turned
1730 joinlength(char * const *argv) {
1733 while (argv && *argv) {
1734 len += (strlen(*argv) + 1);
1742 * int joinarray(char * const *argv, char *buffer, char delim)
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.
1752 * 0 unless argv or buffer is NULL.
1758 joinarray(char * const *argv, char *buffer, char delim) {
1762 if (argv == NULL || buffer == NULL) {
1770 for (p = argv ; *p != NULL ; p++) {
1772 if (*(p + 1) != NULL) {
1773 strcat(buffer, sep);
1781 * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
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.
1793 * If there was no delimiter, then NULL is returned,
1794 * otherewise *RES is returned.
1799 getfield(char **res, size_t reslen, char **ptr, char delim) {
1802 if (res == NULL || ptr == NULL || *ptr == NULL) {
1807 q = strchr(*ptr, delim);
1814 *res = strndup(*ptr, q - *ptr);
1816 if ((size_t)(q - *ptr + 1) > reslen) { /*%< to big for res */
1820 strncpy(*res, *ptr, q - *ptr);
1821 (*res)[q - *ptr] = 0x0;
1834 #ifndef HAVE_STRNDUP
1836 * static char * strndup(const char *str, size_t len)
1840 * like strdup, except do len bytes instead of the whole string. Always
1845 * The newly malloced string.
1850 strndup(const char *str, size_t len) {
1851 char *p = malloc(len + 1);
1855 strncpy(p, str, len);
1864 * static int strcmp_nws(const char *a, const char *b)
1868 * do a strcmp, except uneven lengths of whitespace compare the same
1875 strcmp_nws(const char *a, const char *b) {
1877 if (isspace(*a) && isspace(*b)) {
1880 } while (isspace(*a));
1883 } while (isspace(*b));
1905 * static void free_array(char **argv, size_t entries)
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.
1917 free_array(char **argv, size_t entries) {
1919 int useEntries = (entries > 0U);
1924 while ((useEntries && entries > 0U) || *p) {
1938 /* ************************************************** */
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.
1949 main(int argc, char **argv) {
1951 char *b = &buffer[0];
1952 size_t len = sizeof buffer;
1955 if (argc < 2 || argv[1][0] != '-')
1958 option = argv[1][1];
1966 char *p = argv[1], *q = &buff[0];
1968 while (getfield(&q, sizeof buff, &p, ':') != NULL) {
1969 printf("field: \"%s\"\n", q);
1972 printf("p is now \"%s\"\n", p);
1978 char **x = splitarray(argv[1], argv[1] + strlen(argv[1]),
1983 printf("split failed\n");
1985 for (p = x ; p != NULL && *p != NULL ; p++) {
1986 printf("\"%s\"\n", *p);
1997 if (strchr(argv[1], ':') != NULL) {
1998 if (irp_unmarshall_nw(&ne, argv[1]) != 0) {
1999 printf("Unmarhsalling failed\n");
2003 printf("Name: \"%s\"\n", ne.n_name);
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);
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) ?
2023 (IN_CLASSB(np1->n_net) ?
2025 (IN_CLASSC(np1->n_net) ?
2027 np1->n_net = htonl(np1->n_net);
2028 if (irp_marshall_nw(&ne, &b, &len) != 0) {
2029 printf("Marshalling failed\n");
2038 char **hosts, **users, **domains;
2045 if (strchr(argv[1], '(') != NULL) {
2046 if (irp_unmarshall_ng(&ngname, &entries,
2047 &hosts, &users, &domains,
2049 printf("unmarshall failed\n");
2053 #define STRVAL(x) (x == NULL ? "*" : x)
2055 printf("%s {\n", ngname);
2056 for (i = 0 ; i < entries ; i++)
2057 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2060 STRVAL(domains[i]));
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);
2070 buff = malloc(size);
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],
2077 printf("next marshalling failed.\n");
2079 irp_marshall_ng_end(buff, &size);
2081 if (strcmp_nws(argv[1], buff) != 0) {
2082 printf("compare failed:\n\t%s\n\t%s\n",
2085 printf("compare ok\n");
2088 char *h, *u, *d, *buff;
2091 /* run through two times. First to figure out how
2092 much of a buffer we need. Second to do the
2093 actual marshalling */
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]);
2102 buff = malloc(size);
2104 setnetgrent(argv[1]);
2105 if (irp_marshall_ng_start(argv[1], buff, &size) != 0)
2106 printf("Marshalling start failed\n");
2108 while (getnetgrent(&h, &u, &d) == 1) {
2109 if (irp_marshall_ng_next(h, u, d, buff, &size)
2111 printf("Marshalling failed\n");
2115 irp_marshall_ng_end(buff, &size);
2118 printf("success: %s\n", buff);
2126 struct hostent he, *hp;
2130 if (strchr(argv[1], '@') != NULL) {
2131 if (irp_unmarshall_ho(&he, argv[1]) != 0) {
2132 printf("unmarshall failed\n");
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);
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",
2154 printf("compare ok\n");
2157 if ((hp = gethostbyname(argv[1])) == NULL) {
2158 perror("gethostbyname");
2159 printf("\"%s\"\n", argv[1]);
2163 if (irp_marshall_ho(hp, &b, &len) != 0) {
2164 printf("irp_marshall_ho failed\n");
2168 printf("success: \"%s\"\n", buffer);
2178 if (strchr(argv[1], ':') != NULL) {
2180 memset(sv, 0xef, sizeof (struct servent));
2181 if (irp_unmarshall_sv(sv, argv[1]) != 0) {
2182 printf("unmarshall failed\n");
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",
2191 printf("compare ok\n");
2194 if ((sv = getservbyname(argv[1], argv[2])) == NULL) {
2195 perror("getservent");
2199 if (irp_marshall_sv(sv, &b, &len) != 0) {
2200 printf("irp_marshall_sv failed\n");
2204 printf("success: \"%s\"\n", buffer);
2213 if (strchr(argv[1], ':') != NULL) {
2215 memset(gr, 0xef, sizeof (struct group));
2216 if (irp_unmarshall_gr(gr, argv[1]) != 0) {
2217 printf("unmarshall failed\n");
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",
2226 printf("compare ok\n");
2229 if ((gr = getgrnam(argv[1])) == NULL) {
2234 if (irp_marshall_gr(gr, &b, &len) != 0) {
2235 printf("irp_marshall_gr failed\n");
2239 printf("success: \"%s\"\n", buffer);
2249 if (strchr(argv[1], ':') != NULL) {
2251 memset(pw, 0xef, sizeof (*pw));
2252 if (irp_unmarshall_pw(pw, argv[1]) != 0) {
2253 printf("unmarshall failed\n");
2257 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2258 pw->pw_name, pw->pw_passwd, (long)pw->pw_uid,
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);
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",
2271 printf("compare ok\n");
2274 if ((pw = getpwnam(argv[1])) == NULL) {
2279 if (irp_marshall_pw(pw, &b, &len) != 0) {
2280 printf("irp_marshall_pw failed\n");
2284 printf("success: \"%s\"\n", buffer);
2290 printf("Wrong option: %c\n", option);