1 /* Copyright (c) 2020-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
17 /* cachedumper - dump a human-readable representation of a cache file. */
24 #include <sys/types.h>
27 #include <arpa/inet.h>
29 #include <sys/param.h>
34 static void *the_cache
;
36 #define NO_REF ((ref_t) -1)
38 /* Given a chunk of raw data CP of length LEN, print it in a hopefully
39 user-readable format, including colorizing non-readable characters.
40 STR prefixes it, if non-NULL. If LEN is -1, CP is
43 data_string (unsigned char *cp
, const char *str
, int len
)
46 unsigned char *cpe
= cp
+ len
;
48 while (len
== -1 || cp
< cpe
)
53 printf ("\033[%dm<%02x>\033[0m", *cp
% 6 + 31, *cp
);
54 if (len
== -1 && *cp
== 0)
65 nscd_print_cache (const char *name
)
71 if (stat (name
, &st
) < 0)
77 fd
= open (name
, O_RDONLY
);
79 the_cache
= mmap (NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
81 struct database_pers_head
*dps
= (struct database_pers_head
*) the_cache
;
83 /* Shortcut for "print the cache offset (address) of X in the
85 #define A(x) (int) ((char *) &(x) - (char *) the_cache)
87 /* Common code for "print field DPS->F, it's offset, and contents". */
88 #define DPS(f) printf("%08x: %24s : %10d %08x\n", A (dps->f), #f, (int) dps->f, (int) dps->f);
95 DPS (nscd_certainly_running
);
114 char *data
= (char *) &dps
->array
[roundup (dps
->module
,
115 ALIGN
/ sizeof (ref_t
))];
117 /* Loop through each entry in the hash table, which is of size
118 dps->module. Raw data is stored after the hash table in the
120 for (i
= 0; i
< dps
->module
; i
++)
122 ref_t r
= dps
->array
[i
];
127 printf ("hash[%4d] = 0x%x\n", i
, r
);
131 struct hashentry
*here
= (struct hashentry
*) (data
+ r
);
133 unsigned char *key
= (unsigned char *) data
+ here
->key
;
135 printf ("\n%08x: type %s key %p \"", A (*here
),
136 serv2str
[here
->type
], key
);
138 data_string (key
, "", here
->len
);
140 struct datahead
*dh
= (struct datahead
*) (data
+ here
->packet
);
141 printf ("\" (len:%ld) Data %08lx\n", (long) here
->len
,
142 (long unsigned int) ((char *) dh
- (char *) the_cache
));
146 /* Common code for printing fields in struct DATAHEAD DH. */
147 #define DH(f) printf ("%08x; %24s : %10d %08x\n", A (dh->f), #f, (int) dh->f, (int) dh->f);
158 unsigned char *cp
= (unsigned char *) (&dh
->data
[0]);
160 (unsigned char *) (&dh
->data
[0]) + dh
->allocsize
;
168 data_string (cp
, _(" - all data: "), cpe
- cp
);
172 /* These two are common to all responses. */
174 dh
->data
[0].pwdata
.version
, dh
->data
[0].pwdata
.found
);
176 /* Shortcut for the common case where we iterate through
177 fixed-length strings stored in the data portion of the
178 cache. CP is updated to point to the next string. */
179 #define DSTR(str, l) cp = data_string (cp, str, l)
186 pw_response_header
*pw
= &(dh
->data
[0].pwdata
);
188 DSTR (" name ", pw
->pw_name_len
);
189 DSTR (" passwd ", pw
->pw_passwd_len
);
190 printf (" uid %d gid %d", pw
->pw_uid
, pw
->pw_gid
);
191 DSTR (" gecos ", pw
->pw_gecos_len
);
192 DSTR (" dir ", pw
->pw_dir_len
);
193 DSTR (" shell ", pw
->pw_shell_len
);
194 DSTR (" byuid ", -1);
203 gr_response_header
*gr
= &(dh
->data
[0].grdata
);
205 grplens
= (uint32_t *) cp
;
206 cp
+= gr
->gr_mem_cnt
* sizeof (uint32_t);
207 DSTR (" name ", gr
->gr_name_len
);
208 DSTR (" passwd ", gr
->gr_passwd_len
);
209 printf (" gid %d members %d [ ", (int) gr
->gr_gid
,
210 (int) gr
->gr_mem_cnt
);
211 for (i
= 0; i
< gr
->gr_mem_cnt
; i
++)
212 DSTR (" ", grplens
[i
]);
213 DSTR (" ] bygid ", -1);
220 case GETHOSTBYADDRv6
:
222 case GETHOSTBYNAMEv6
:
224 hst_response_header
*hst
= &(dh
->data
[0].hstdata
);
225 printf (" addrtype %d error %d", hst
->h_addrtype
, hst
->error
);
227 DSTR (" name ", hst
->h_name_len
);
228 uint32_t *aliases_len
= (uint32_t *) cp
;
229 cp
+= hst
->h_aliases_cnt
* sizeof (uint32_t);
230 uint32_t *addrs
= (uint32_t *) cp
;
231 cp
+= hst
->h_length
* hst
->h_addr_list_cnt
;
233 if (hst
->h_aliases_cnt
)
235 printf (" aliases [");
236 for (i
= 0; i
< hst
->h_aliases_cnt
; i
++)
237 DSTR (" ", aliases_len
[i
]);
240 if (hst
->h_addr_list_cnt
)
242 char buf
[INET6_ADDRSTRLEN
];
243 printf (" addresses [");
244 for (i
= 0; i
< hst
->h_addr_list_cnt
; i
++)
246 inet_ntop (hst
->h_addrtype
, addrs
, buf
, sizeof (buf
));
248 addrs
+= hst
->h_length
;
259 ai_response_header
*ai
= &(dh
->data
[0].aidata
);
260 printf (" naddrs %ld addrslen %ld canonlen %ld error %d [",
261 (long) ai
->naddrs
, (long) ai
->addrslen
,
262 (long) ai
->canonlen
, ai
->error
);
264 unsigned char *addrs
= cp
;
265 unsigned char *families
= cp
+ ai
->addrslen
;
266 cp
= families
+ ai
->naddrs
;
267 char buf
[INET6_ADDRSTRLEN
];
269 for (i
= 0; i
< ai
->naddrs
; i
++)
274 inet_ntop (*families
, addrs
, buf
, sizeof (buf
));
279 inet_ntop (*families
, addrs
, buf
, sizeof (buf
));
286 DSTR (" ] canon ", ai
->canonlen
);
294 initgr_response_header
*ig
= &(dh
->data
[0].initgrdata
);
295 printf (" nresults %d groups [", (int) ig
->ngrps
);
297 grplens
= (uint32_t *) cp
;
298 cp
+= ig
->ngrps
* sizeof (uint32_t);
299 for (i
= 0; i
< ig
->ngrps
; i
++)
300 printf (" %d", grplens
[i
]);
301 DSTR (" ] key ", -1);
309 serv_response_header
*serv
= &(dh
->data
[0].servdata
);
310 printf (" alias_cnt %ld port %d (stored as %d)",
311 (long) serv
->s_aliases_cnt
,
312 ((serv
->s_port
& 0xff00) >> 8) | ((serv
->
315 cp
+= sizeof (*serv
);
316 DSTR (" name ", serv
->s_name_len
);
317 DSTR (" proto ", serv
->s_proto_len
);
318 if (serv
->s_aliases_cnt
)
320 uint32_t *alias_len
= (uint32_t *) cp
;
321 printf (" aliases [");
322 cp
+= sizeof (uint32_t) * serv
->s_aliases_cnt
;
323 for (i
= 0; i
< serv
->s_aliases_cnt
; i
++)
324 DSTR (" ", alias_len
[i
]);
333 netgroup_response_header
*ng
= &(dh
->data
[0].netgroupdata
);
334 printf (" nresults %d len %d\n",
335 (int) ng
->nresults
, (int) ng
->result_len
);
337 for (i
= 0; i
< ng
->nresults
; i
++)
350 innetgroup_response_header
*ing
=
351 &(dh
->data
[0].innetgroupdata
);
352 printf (" result %d\n", ing
->result
);
360 if (debug_level
> 2 && cp
&& cp
< cpe
)
362 printf (_(" - remaining data %p: "), cp
);
363 data_string (cp
, "", cpe
- cp
);
372 munmap (the_cache
, st
.st_size
);