1ee5153b7Sflorian /* xfr-inspect - list the contents and inspect an zone transfer XFR file
2ee5153b7Sflorian * By W.C.A. Wijngaards
3ee5153b7Sflorian * Copyright 2017, NLnet Labs.
4ee5153b7Sflorian * BSD, see LICENSE.
5ee5153b7Sflorian */
6ee5153b7Sflorian
7ee5153b7Sflorian #include "config.h"
8ee5153b7Sflorian #include "util.h"
9ee5153b7Sflorian #include "buffer.h"
10ee5153b7Sflorian #include "packet.h"
11ee5153b7Sflorian #include "rdata.h"
12ee5153b7Sflorian #include "namedb.h"
13ee5153b7Sflorian #include "difffile.h"
14ee5153b7Sflorian #include <stdio.h>
15ee5153b7Sflorian #include <errno.h>
16ee5153b7Sflorian #include <string.h>
17ee5153b7Sflorian #include <stdlib.h>
18ee5153b7Sflorian #include <unistd.h>
19ee5153b7Sflorian #include <ctype.h>
20ee5153b7Sflorian
21ee5153b7Sflorian /** verbosity for inspect */
22ee5153b7Sflorian static int v = 0;
23ee5153b7Sflorian /** shorthand for ease */
24ee5153b7Sflorian #ifdef ULL
25ee5153b7Sflorian #undef ULL
26ee5153b7Sflorian #endif
27ee5153b7Sflorian #define ULL (unsigned long long)
28ee5153b7Sflorian
29ee5153b7Sflorian /** print usage text */
30ee5153b7Sflorian static void
usage(void)31ee5153b7Sflorian usage(void)
32ee5153b7Sflorian {
33ee5153b7Sflorian printf("usage: xfr-inspect [options] file\n");
34ee5153b7Sflorian printf(" -h this help\n");
35ee5153b7Sflorian printf(" -v increase verbosity: "
36ee5153b7Sflorian "with -v(list chunks), -vv(inside chunks)\n");
37ee5153b7Sflorian printf(" -l list contents of transfer\n");
38ee5153b7Sflorian }
39ee5153b7Sflorian
40ee5153b7Sflorian static int
xi_diff_read_64(FILE * in,uint64_t * result)41ee5153b7Sflorian xi_diff_read_64(FILE *in, uint64_t* result)
42ee5153b7Sflorian {
43ee5153b7Sflorian if (fread(result, sizeof(*result), 1, in) == 1) {
44ee5153b7Sflorian return 1;
45ee5153b7Sflorian } else {
46ee5153b7Sflorian return 0;
47ee5153b7Sflorian }
48ee5153b7Sflorian }
49ee5153b7Sflorian
50ee5153b7Sflorian static int
xi_diff_read_32(FILE * in,uint32_t * result)51ee5153b7Sflorian xi_diff_read_32(FILE *in, uint32_t* result)
52ee5153b7Sflorian {
53ee5153b7Sflorian if (fread(result, sizeof(*result), 1, in) == 1) {
54ee5153b7Sflorian *result = ntohl(*result);
55ee5153b7Sflorian return 1;
56ee5153b7Sflorian } else {
57ee5153b7Sflorian return 0;
58ee5153b7Sflorian }
59ee5153b7Sflorian }
60ee5153b7Sflorian
61ee5153b7Sflorian static int
xi_diff_read_8(FILE * in,uint8_t * result)62ee5153b7Sflorian xi_diff_read_8(FILE *in, uint8_t* result)
63ee5153b7Sflorian {
64ee5153b7Sflorian if (fread(result, sizeof(*result), 1, in) == 1) {
65ee5153b7Sflorian return 1;
66ee5153b7Sflorian } else {
67ee5153b7Sflorian return 0;
68ee5153b7Sflorian }
69ee5153b7Sflorian }
70ee5153b7Sflorian
71ee5153b7Sflorian static int
xi_diff_read_str(FILE * in,char * buf,size_t len)72ee5153b7Sflorian xi_diff_read_str(FILE* in, char* buf, size_t len)
73ee5153b7Sflorian {
74ee5153b7Sflorian uint32_t disklen;
75ee5153b7Sflorian if(!xi_diff_read_32(in, &disklen))
76ee5153b7Sflorian return 0;
77ee5153b7Sflorian if(disklen >= len)
78ee5153b7Sflorian return 0;
79ee5153b7Sflorian if(fread(buf, disklen, 1, in) != 1)
80ee5153b7Sflorian return 0;
81ee5153b7Sflorian buf[disklen] = 0;
82ee5153b7Sflorian return 1;
83ee5153b7Sflorian }
84ee5153b7Sflorian
85ee5153b7Sflorian
86ee5153b7Sflorian /** inspect header of xfr file, return num_parts */
87ee5153b7Sflorian static int
inspect_header(FILE * in)88ee5153b7Sflorian inspect_header(FILE* in)
89ee5153b7Sflorian {
90ee5153b7Sflorian char zone_buf[3072];
91ee5153b7Sflorian char patname_buf[2048];
92ee5153b7Sflorian
93ee5153b7Sflorian uint32_t old_serial, new_serial, num_parts, type;
94ee5153b7Sflorian uint64_t time_end_0, time_start_0;
95ee5153b7Sflorian uint32_t time_end_1, time_start_1;
96ee5153b7Sflorian uint8_t committed;
97ee5153b7Sflorian
98ee5153b7Sflorian time_t time_end, time_start;
99ee5153b7Sflorian
100ee5153b7Sflorian if(!xi_diff_read_32(in, &type)) {
101ee5153b7Sflorian printf("could not read type, file short\n");
102ee5153b7Sflorian fclose(in);
103ee5153b7Sflorian exit(1);
104ee5153b7Sflorian }
105ee5153b7Sflorian if(type != DIFF_PART_XFRF) {
106ee5153b7Sflorian printf("type: %x (BAD FILE TYPE)\n", type);
107ee5153b7Sflorian fclose(in);
108ee5153b7Sflorian exit(1);
109ee5153b7Sflorian }
110ee5153b7Sflorian if(!xi_diff_read_8(in, &committed) ||
111ee5153b7Sflorian !xi_diff_read_32(in, &num_parts) ||
112ee5153b7Sflorian !xi_diff_read_64(in, &time_end_0) ||
113ee5153b7Sflorian !xi_diff_read_32(in, &time_end_1) ||
114ee5153b7Sflorian !xi_diff_read_32(in, &old_serial) ||
115ee5153b7Sflorian !xi_diff_read_32(in, &new_serial) ||
116ee5153b7Sflorian !xi_diff_read_64(in, &time_start_0) ||
117ee5153b7Sflorian !xi_diff_read_32(in, &time_start_1) ||
118ee5153b7Sflorian !xi_diff_read_str(in, zone_buf, sizeof(zone_buf)) ||
119ee5153b7Sflorian !xi_diff_read_str(in, patname_buf, sizeof(patname_buf))) {
120ee5153b7Sflorian printf("diff file bad commit part, file too short");
121ee5153b7Sflorian fclose(in);
122ee5153b7Sflorian exit(1);
123ee5153b7Sflorian }
124ee5153b7Sflorian time_end = (time_t)time_end_0;
125ee5153b7Sflorian time_start = (time_t)time_start_0;
126ee5153b7Sflorian
127ee5153b7Sflorian /* printf("type: %x\n", (int)type); */
128ee5153b7Sflorian printf("committed: %d (%s)\n", (int)committed,
129ee5153b7Sflorian committed?"yes":"no");
130ee5153b7Sflorian printf("num_parts: %d\n", (int)num_parts);
131ee5153b7Sflorian printf("time_end: %d.%6.6d %s", (int)time_end_0,
132ee5153b7Sflorian (int)time_end_1, ctime(&time_end));
133ee5153b7Sflorian printf("old_serial: %u\n", (unsigned)old_serial);
134ee5153b7Sflorian printf("new_serial: %u\n", (unsigned)new_serial);
135ee5153b7Sflorian printf("time_start: %d.%6.6d %s", (int)time_start_0,
136ee5153b7Sflorian (int)time_start_1, ctime(&time_start));
137ee5153b7Sflorian printf("zone: %s\n", zone_buf);
138ee5153b7Sflorian printf("patname: %s\n", patname_buf);
139ee5153b7Sflorian
140ee5153b7Sflorian return num_parts;
141ee5153b7Sflorian }
142ee5153b7Sflorian
143ee5153b7Sflorian /** print records in packet */
144ee5153b7Sflorian static void
print_records(region_type * region,buffer_type * pkt,int num,int qsection)145ee5153b7Sflorian print_records(region_type* region, buffer_type* pkt, int num, int qsection)
146ee5153b7Sflorian {
147ee5153b7Sflorian domain_table_type* table;
148ee5153b7Sflorian int i;
149ee5153b7Sflorian rr_type* rr;
150ee5153b7Sflorian region_type* tmpregion = region_create(xalloc, free);
151ee5153b7Sflorian buffer_type* tmpbuf;
152ee5153b7Sflorian if(!tmpregion) {
153ee5153b7Sflorian printf("out of memory\n");
154ee5153b7Sflorian return;
155ee5153b7Sflorian }
156ee5153b7Sflorian tmpbuf = buffer_create(region, QIOBUFSZ);
157ee5153b7Sflorian if(!tmpbuf) {
158ee5153b7Sflorian printf("out of memory\n");
159ee5153b7Sflorian return;
160ee5153b7Sflorian }
161ee5153b7Sflorian table = domain_table_create(tmpregion);
162ee5153b7Sflorian if(!table) {
163ee5153b7Sflorian printf("out of memory\n");
164ee5153b7Sflorian return;
165ee5153b7Sflorian }
166ee5153b7Sflorian
167ee5153b7Sflorian for(i=0; i<num; ++i) {
168ee5153b7Sflorian rr = packet_read_rr(region, table, pkt, qsection);
169ee5153b7Sflorian if(!rr) {
170ee5153b7Sflorian printf("; cannot read rr %d\n", i);
171ee5153b7Sflorian return;
172ee5153b7Sflorian }
173ee5153b7Sflorian if(qsection) {
174ee5153b7Sflorian printf("%s", dname_to_string(domain_dname(rr->owner),
175ee5153b7Sflorian NULL));
176ee5153b7Sflorian printf("\t%s", rrclass_to_string(rr->klass));
177ee5153b7Sflorian if(rr->type == TYPE_IXFR)
178ee5153b7Sflorian printf("\tIXFR\n");
179ee5153b7Sflorian else if(rr->type == TYPE_AXFR)
180ee5153b7Sflorian printf("\tAXFR\n");
181ee5153b7Sflorian else printf("\t%s\n", rrtype_to_string(rr->type));
182ee5153b7Sflorian } else {
183ee5153b7Sflorian if(!print_rr(stdout, NULL, rr, tmpregion, tmpbuf)) {
184ee5153b7Sflorian printf("; cannot print rr %d\n", i);
185ee5153b7Sflorian }
186ee5153b7Sflorian }
187ee5153b7Sflorian }
188ee5153b7Sflorian region_destroy(tmpregion);
189ee5153b7Sflorian }
190ee5153b7Sflorian
191ee5153b7Sflorian /** inspect packet (IXFR or AXFR) */
192ee5153b7Sflorian static void
inspect_packet(region_type * region,buffer_type * pkt)193ee5153b7Sflorian inspect_packet(region_type* region, buffer_type* pkt)
194ee5153b7Sflorian {
195ee5153b7Sflorian printf("\n");
196ee5153b7Sflorian if(buffer_limit(pkt) < QHEADERSZ) {
197ee5153b7Sflorian printf("packet too short\n");
198ee5153b7Sflorian return;
199ee5153b7Sflorian }
200ee5153b7Sflorian printf("; id=%4.4x ; flags%s%s%s%s%s%s%s%s ; rcode %s ; opcode %d\n",
201ee5153b7Sflorian ID(pkt), QR(pkt)?" QR":"", AA(pkt)?" AA":"", TC(pkt)?" TC":"",
202ee5153b7Sflorian RD(pkt)?" RD":"", RA(pkt)?" RA":"", Z(pkt)?" Z":"",
203ee5153b7Sflorian AD(pkt)?" AD":"", CD(pkt)?" CD":"", rcode2str(RCODE(pkt)),
204ee5153b7Sflorian OPCODE(pkt));
205ee5153b7Sflorian printf("; qdcount %d ; ancount %d ; nscount %d ; arcount %d\n",
206ee5153b7Sflorian QDCOUNT(pkt), ANCOUNT(pkt), NSCOUNT(pkt), ARCOUNT(pkt));
207ee5153b7Sflorian buffer_skip(pkt, QHEADERSZ);
208ee5153b7Sflorian
209ee5153b7Sflorian if(QDCOUNT(pkt) != 0) {
210ee5153b7Sflorian printf("; QUESTION SECTION\n");
211ee5153b7Sflorian print_records(region, pkt, QDCOUNT(pkt), 1);
212ee5153b7Sflorian }
213ee5153b7Sflorian if(ANCOUNT(pkt) != 0) {
214ee5153b7Sflorian printf("; ANSWER SECTION\n");
215ee5153b7Sflorian print_records(region, pkt, ANCOUNT(pkt), 0);
216ee5153b7Sflorian }
217ee5153b7Sflorian if(NSCOUNT(pkt) != 0) {
218ee5153b7Sflorian printf("; AUTHORITY SECTION\n");
219ee5153b7Sflorian print_records(region, pkt, NSCOUNT(pkt), 0);
220ee5153b7Sflorian }
221ee5153b7Sflorian if(ARCOUNT(pkt) != 0) {
222ee5153b7Sflorian printf("; ADDITIONAL SECTION\n");
223ee5153b7Sflorian print_records(region, pkt, ARCOUNT(pkt), 0);
224ee5153b7Sflorian }
225ee5153b7Sflorian }
226ee5153b7Sflorian
227ee5153b7Sflorian /** inspect part of xfr file */
228ee5153b7Sflorian static void
inspect_part(FILE * in,int partnum)229ee5153b7Sflorian inspect_part(FILE* in, int partnum)
230ee5153b7Sflorian {
231ee5153b7Sflorian uint32_t pkttype, msglen, msglen2;
232ee5153b7Sflorian region_type* region;
233ee5153b7Sflorian buffer_type* packet;
234ee5153b7Sflorian region = region_create(xalloc, free);
235ee5153b7Sflorian if(!region) {
236ee5153b7Sflorian printf("out of memory\n");
237ee5153b7Sflorian fclose(in);
238ee5153b7Sflorian exit(1);
239ee5153b7Sflorian }
240ee5153b7Sflorian packet = buffer_create(region, QIOBUFSZ);
241ee5153b7Sflorian if(!xi_diff_read_32(in, &pkttype)) {
242ee5153b7Sflorian printf("cannot read part %d\n", partnum);
243ee5153b7Sflorian fclose(in);
244ee5153b7Sflorian exit(1);
245ee5153b7Sflorian }
246ee5153b7Sflorian if(pkttype != DIFF_PART_XXFR) {
247ee5153b7Sflorian printf("bad part %d: not type XXFR\n", partnum);
248ee5153b7Sflorian fclose(in);
249ee5153b7Sflorian exit(1);
250ee5153b7Sflorian }
251ee5153b7Sflorian if(!xi_diff_read_32(in, &msglen)) {
252ee5153b7Sflorian printf("bad part %d: not msglen, file too short\n", partnum);
253ee5153b7Sflorian fclose(in);
254ee5153b7Sflorian exit(1);
255ee5153b7Sflorian }
256ee5153b7Sflorian if(msglen < QHEADERSZ || msglen > QIOBUFSZ) {
257ee5153b7Sflorian printf("bad part %d: msglen %u (too short or too long)\n",
258ee5153b7Sflorian partnum, (unsigned)msglen);
259ee5153b7Sflorian fclose(in);
260ee5153b7Sflorian exit(1);
261ee5153b7Sflorian }
262ee5153b7Sflorian if(fread(buffer_begin(packet), msglen, 1, in) != 1) {
263ee5153b7Sflorian printf("bad part %d: short packet, file too short, %s\n",
264ee5153b7Sflorian partnum, strerror(errno));
265ee5153b7Sflorian fclose(in);
266ee5153b7Sflorian exit(1);
267ee5153b7Sflorian }
268ee5153b7Sflorian if(!xi_diff_read_32(in, &msglen2)) {
269ee5153b7Sflorian printf("bad part %d: cannot read msglen2, file too short\n", partnum);
270ee5153b7Sflorian fclose(in);
271ee5153b7Sflorian exit(1);
272ee5153b7Sflorian }
273ee5153b7Sflorian if(v==0) {
274ee5153b7Sflorian region_destroy(region);
275ee5153b7Sflorian return;
276ee5153b7Sflorian }
277ee5153b7Sflorian
278ee5153b7Sflorian printf("\n");
279ee5153b7Sflorian /* printf("type : %x\n", pkttype); */
280ee5153b7Sflorian printf("part : %d\n", partnum);
281ee5153b7Sflorian printf("msglen : %u\n", (unsigned)msglen);
282ee5153b7Sflorian printf("msglen2 : %u (%s)\n", (unsigned)msglen2,
283ee5153b7Sflorian (msglen==msglen2)?"ok":"wrong");
284ee5153b7Sflorian
285ee5153b7Sflorian if(v>=2) {
286ee5153b7Sflorian buffer_set_limit(packet, msglen);
287ee5153b7Sflorian inspect_packet(region, packet);
288ee5153b7Sflorian }
289ee5153b7Sflorian
290ee5153b7Sflorian region_destroy(region);
291ee5153b7Sflorian }
292ee5153b7Sflorian
293ee5153b7Sflorian /** inspect parts of xfr file */
294ee5153b7Sflorian static void
inspect_parts(FILE * in,int num)295ee5153b7Sflorian inspect_parts(FILE* in, int num)
296ee5153b7Sflorian {
297ee5153b7Sflorian int i;
298ee5153b7Sflorian for(i=0; i<num; i++) {
299ee5153b7Sflorian inspect_part(in, i);
300ee5153b7Sflorian }
301ee5153b7Sflorian }
302ee5153b7Sflorian
303ee5153b7Sflorian /** inspect trail of xfr file */
304ee5153b7Sflorian static void
inspect_trail(FILE * in)305ee5153b7Sflorian inspect_trail(FILE* in)
306ee5153b7Sflorian {
307ee5153b7Sflorian char log_buf[5120];
308ee5153b7Sflorian if(!xi_diff_read_str(in, log_buf, sizeof(log_buf))) {
309ee5153b7Sflorian printf("bad trail: cannot read log string\n");
310ee5153b7Sflorian fclose(in);
311ee5153b7Sflorian exit(1);
312ee5153b7Sflorian }
313ee5153b7Sflorian printf("\n");
314ee5153b7Sflorian printf("log: %s\n", log_buf);
315ee5153b7Sflorian }
316ee5153b7Sflorian
317ee5153b7Sflorian /** inspect contents of xfr file */
318ee5153b7Sflorian static void
inspect_file(char * fname)319ee5153b7Sflorian inspect_file(char* fname)
320ee5153b7Sflorian {
321ee5153b7Sflorian FILE* in;
322ee5153b7Sflorian int num;
323ee5153b7Sflorian log_init("udb-inspect");
324ee5153b7Sflorian if(!(in=fopen(fname, "r"))) {
325ee5153b7Sflorian printf("cannot open %s: %s\n", fname, strerror(errno));
326ee5153b7Sflorian exit(1);
327ee5153b7Sflorian }
328ee5153b7Sflorian printf("file: %s\n", fname);
329ee5153b7Sflorian num = inspect_header(in);
330ee5153b7Sflorian inspect_parts(in, num);
331ee5153b7Sflorian inspect_trail(in);
332ee5153b7Sflorian fclose(in);
333ee5153b7Sflorian }
334ee5153b7Sflorian
335ee5153b7Sflorian /** list header of xfr file, return num_parts */
336ee5153b7Sflorian static int
list_header(FILE * in)337ee5153b7Sflorian list_header(FILE* in)
338ee5153b7Sflorian {
339ee5153b7Sflorian char zone_buf[3072];
340ee5153b7Sflorian char patname_buf[2048];
341ee5153b7Sflorian
342ee5153b7Sflorian uint32_t old_serial, new_serial, num_parts, type;
343ee5153b7Sflorian uint64_t time_end_0, time_start_0;
344ee5153b7Sflorian uint32_t time_end_1, time_start_1;
345ee5153b7Sflorian uint8_t committed;
346ee5153b7Sflorian
347ee5153b7Sflorian time_t time_end, time_start;
348ee5153b7Sflorian
349ee5153b7Sflorian if(!xi_diff_read_32(in, &type)) {
350ee5153b7Sflorian printf("could not read type, file short\n");
351ee5153b7Sflorian fclose(in);
352ee5153b7Sflorian exit(1);
353ee5153b7Sflorian }
354ee5153b7Sflorian if(type != DIFF_PART_XFRF) {
355ee5153b7Sflorian printf("type: %x (BAD FILE TYPE)\n", type);
356ee5153b7Sflorian fclose(in);
357ee5153b7Sflorian exit(1);
358ee5153b7Sflorian }
359ee5153b7Sflorian if(!xi_diff_read_8(in, &committed) ||
360ee5153b7Sflorian !xi_diff_read_32(in, &num_parts) ||
361ee5153b7Sflorian !xi_diff_read_64(in, &time_end_0) ||
362ee5153b7Sflorian !xi_diff_read_32(in, &time_end_1) ||
363ee5153b7Sflorian !xi_diff_read_32(in, &old_serial) ||
364ee5153b7Sflorian !xi_diff_read_32(in, &new_serial) ||
365ee5153b7Sflorian !xi_diff_read_64(in, &time_start_0) ||
366ee5153b7Sflorian !xi_diff_read_32(in, &time_start_1) ||
367ee5153b7Sflorian !xi_diff_read_str(in, zone_buf, sizeof(zone_buf)) ||
368ee5153b7Sflorian !xi_diff_read_str(in, patname_buf, sizeof(patname_buf))) {
369ee5153b7Sflorian printf("diff file bad commit part, file too short");
370ee5153b7Sflorian fclose(in);
371ee5153b7Sflorian exit(1);
372ee5153b7Sflorian }
373ee5153b7Sflorian time_end = (time_t)time_end_0;
374ee5153b7Sflorian time_start = (time_t)time_start_0;
375ee5153b7Sflorian
376ee5153b7Sflorian /* printf("; type: %x\n", (int)type); */
377*bfd0b123Sflorian printf("; committed: %d (%s)\n", (int)committed,
378ee5153b7Sflorian committed?"yes":"no");
379ee5153b7Sflorian printf("; num_parts: %d\n", (int)num_parts);
380ee5153b7Sflorian printf("; time_end: %d.%6.6d %s", (int)time_end_0,
381ee5153b7Sflorian (int)time_end_1, ctime(&time_end));
382ee5153b7Sflorian printf("; old_serial: %u\n", (unsigned)old_serial);
383ee5153b7Sflorian printf("; new_serial: %u\n", (unsigned)new_serial);
384ee5153b7Sflorian printf("; time_start: %d.%6.6d %s", (int)time_start_0,
385ee5153b7Sflorian (int)time_start_1, ctime(&time_start));
386ee5153b7Sflorian printf("; zone: %s\n", zone_buf);
387ee5153b7Sflorian printf("; patname: %s\n", patname_buf);
388ee5153b7Sflorian
389ee5153b7Sflorian return num_parts;
390ee5153b7Sflorian }
391ee5153b7Sflorian
392ee5153b7Sflorian /** list packet (IXFR or AXFR) */
393ee5153b7Sflorian static void
list_packet(region_type * region,buffer_type * pkt,int partnum)394ee5153b7Sflorian list_packet(region_type* region, buffer_type* pkt, int partnum)
395ee5153b7Sflorian {
396ee5153b7Sflorian if(buffer_limit(pkt) < QHEADERSZ) {
397ee5153b7Sflorian printf("packet too short\n");
398ee5153b7Sflorian return;
399ee5153b7Sflorian }
400ee5153b7Sflorian buffer_skip(pkt, QHEADERSZ);
401ee5153b7Sflorian
402ee5153b7Sflorian if(partnum == 0 && QDCOUNT(pkt) == 1) {
403ee5153b7Sflorian /* print query AXFR or IXFR */
404ee5153b7Sflorian printf("; ");
405ee5153b7Sflorian print_records(region, pkt, QDCOUNT(pkt), 1);
406ee5153b7Sflorian }
407ee5153b7Sflorian if(ANCOUNT(pkt) != 0) {
408ee5153b7Sflorian print_records(region, pkt, ANCOUNT(pkt), 0);
409ee5153b7Sflorian }
410ee5153b7Sflorian }
411ee5153b7Sflorian
412ee5153b7Sflorian /** list part of xfr file */
413ee5153b7Sflorian static void
list_part(FILE * in,int partnum)414ee5153b7Sflorian list_part(FILE* in, int partnum)
415ee5153b7Sflorian {
416ee5153b7Sflorian uint32_t pkttype, msglen, msglen2;
417ee5153b7Sflorian region_type* region;
418ee5153b7Sflorian buffer_type* packet;
419ee5153b7Sflorian region = region_create(xalloc, free);
420ee5153b7Sflorian if(!region) {
421ee5153b7Sflorian printf("out of memory\n");
422ee5153b7Sflorian fclose(in);
423ee5153b7Sflorian exit(1);
424ee5153b7Sflorian }
425ee5153b7Sflorian packet = buffer_create(region, QIOBUFSZ);
426ee5153b7Sflorian if(!xi_diff_read_32(in, &pkttype)) {
427ee5153b7Sflorian printf("cannot read part %d\n", partnum);
428ee5153b7Sflorian fclose(in);
429ee5153b7Sflorian exit(1);
430ee5153b7Sflorian }
431ee5153b7Sflorian if(pkttype != DIFF_PART_XXFR) {
432ee5153b7Sflorian printf("bad part %d: not type XXFR\n", partnum);
433ee5153b7Sflorian fclose(in);
434ee5153b7Sflorian exit(1);
435ee5153b7Sflorian }
436ee5153b7Sflorian if(!xi_diff_read_32(in, &msglen)) {
437ee5153b7Sflorian printf("bad part %d: not msglen, file too short\n", partnum);
438ee5153b7Sflorian fclose(in);
439ee5153b7Sflorian exit(1);
440ee5153b7Sflorian }
441ee5153b7Sflorian if(msglen < QHEADERSZ || msglen > QIOBUFSZ) {
442ee5153b7Sflorian printf("bad part %d: msglen %u (too short or too long)\n",
443ee5153b7Sflorian partnum, (unsigned)msglen);
444ee5153b7Sflorian fclose(in);
445ee5153b7Sflorian exit(1);
446ee5153b7Sflorian }
447ee5153b7Sflorian if(fread(buffer_begin(packet), msglen, 1, in) != 1) {
448ee5153b7Sflorian printf("bad part %d: short packet, file too short, %s\n",
449ee5153b7Sflorian partnum, strerror(errno));
450ee5153b7Sflorian fclose(in);
451ee5153b7Sflorian exit(1);
452ee5153b7Sflorian }
453ee5153b7Sflorian if(!xi_diff_read_32(in, &msglen2)) {
454ee5153b7Sflorian printf("bad part %d: cannot read msglen2, file too short\n", partnum);
455ee5153b7Sflorian fclose(in);
456ee5153b7Sflorian exit(1);
457ee5153b7Sflorian }
458ee5153b7Sflorian
459ee5153b7Sflorian buffer_set_limit(packet, msglen);
460ee5153b7Sflorian list_packet(region, packet, partnum);
461ee5153b7Sflorian region_destroy(region);
462ee5153b7Sflorian }
463ee5153b7Sflorian
464ee5153b7Sflorian /** list parts of xfr file */
465ee5153b7Sflorian static void
list_parts(FILE * in,int num)466ee5153b7Sflorian list_parts(FILE* in, int num)
467ee5153b7Sflorian {
468ee5153b7Sflorian int i;
469ee5153b7Sflorian for(i=0; i<num; i++) {
470ee5153b7Sflorian list_part(in, i);
471ee5153b7Sflorian }
472ee5153b7Sflorian }
473ee5153b7Sflorian
474ee5153b7Sflorian /** list contents of xfr file */
475ee5153b7Sflorian static void
list_file(char * fname)476ee5153b7Sflorian list_file(char* fname)
477ee5153b7Sflorian {
478ee5153b7Sflorian FILE* in;
479ee5153b7Sflorian int num;
480ee5153b7Sflorian log_init("udb-inspect");
481ee5153b7Sflorian if(!(in=fopen(fname, "r"))) {
482ee5153b7Sflorian printf("cannot open %s: %s\n", fname, strerror(errno));
483ee5153b7Sflorian exit(1);
484ee5153b7Sflorian }
485ee5153b7Sflorian num = list_header(in);
486ee5153b7Sflorian list_parts(in, num);
487ee5153b7Sflorian
488ee5153b7Sflorian fclose(in);
489ee5153b7Sflorian }
490ee5153b7Sflorian
491ee5153b7Sflorian /** getopt global, in case header files fail to declare it. */
492ee5153b7Sflorian extern int optind;
493ee5153b7Sflorian /** getopt global, in case header files fail to declare it. */
494ee5153b7Sflorian extern char* optarg;
495ee5153b7Sflorian
496ee5153b7Sflorian /**
497ee5153b7Sflorian * main program. Set options given commandline arguments.
498ee5153b7Sflorian * @param argc: number of commandline arguments.
499ee5153b7Sflorian * @param argv: array of commandline arguments.
500ee5153b7Sflorian * @return: exit status of the program.
501ee5153b7Sflorian */
502ee5153b7Sflorian int
main(int argc,char * argv[])503ee5153b7Sflorian main(int argc, char* argv[])
504ee5153b7Sflorian {
505ee5153b7Sflorian int c, list=0;
506ee5153b7Sflorian while( (c=getopt(argc, argv, "hlv")) != -1) {
507ee5153b7Sflorian switch(c) {
508ee5153b7Sflorian case 'l':
509ee5153b7Sflorian list=1;
510ee5153b7Sflorian break;
511ee5153b7Sflorian case 'v':
512ee5153b7Sflorian v++;
513ee5153b7Sflorian break;
514ee5153b7Sflorian default:
515ee5153b7Sflorian case 'h':
516ee5153b7Sflorian usage();
517ee5153b7Sflorian return 1;
518ee5153b7Sflorian }
519ee5153b7Sflorian }
520ee5153b7Sflorian argc -= optind;
521ee5153b7Sflorian argv += optind;
522ee5153b7Sflorian if(argc != 1) {
523ee5153b7Sflorian usage();
524ee5153b7Sflorian return 1;
525ee5153b7Sflorian }
526ee5153b7Sflorian if(list) list_file(argv[0]);
527ee5153b7Sflorian else inspect_file(argv[0]);
528ee5153b7Sflorian
529ee5153b7Sflorian return 0;
530ee5153b7Sflorian }
531