1 /*
2 * read a zone that is split up with ldns-zsplit and re-create
3 * the original zone
4 *
5 * From:
6 * zone1: SOA a b c d e f
7 * zone2: SOA f g h i k l
8 *
9 * Go back to:
10 * zone: SOA a b c d e f g h i j k l
11 *
12 * This is useful in combination with ldns-zsplit
13 *
14 * See the file LICENSE for the license
15 */
16
17 #include "config.h"
18 #include <errno.h>
19 #include <ldns/ldns.h>
20
21 #define FIRST_ZONE 0
22 #define MIDDLE_ZONE 1
23 #define LAST_ZONE 2
24
25 static void
usage(FILE * f,char * progname)26 usage(FILE *f, char *progname)
27 {
28 fprintf(f, "Usage: %s [OPTIONS] <zonefiles>\n", progname);
29 fprintf(f, " Concatenate signed zone snippets created with ldns-zsplit\n");
30 fprintf(f, " back together. The generate zone file is printed to stdout\n");
31 fprintf(f, " The new zone should be equal to the original zone (before splitting)\n");
32 fprintf(f, "OPTIONS:\n");
33 fprintf(f, "-o ORIGIN\tUse this as initial origin, for zones starting with @\n");
34 fprintf(f, "-v\t\tShow the version number and exit\n");
35 }
36
37 int
main(int argc,char ** argv)38 main(int argc, char **argv)
39 {
40 char *progname;
41 FILE *fp;
42 int c;
43 ldns_rdf *origin;
44 size_t i, j;
45 int where;
46 ldns_zone *z;
47 ldns_rr_list *zrr;
48 ldns_rr *current_rr;
49 ldns_rr *soa;
50 ldns_rdf *last_owner;
51 ldns_rr *last_rr;
52 ldns_rr *pop_rr;
53
54 progname = strdup(argv[0]);
55 origin = NULL;
56
57 while ((c = getopt(argc, argv, "o:v")) != -1) {
58 switch(c) {
59 case 'o':
60 origin = ldns_dname_new_frm_str(strdup(optarg));
61 if (!origin) {
62 fprintf(stderr, "Cannot convert the origin %s to a domainname\n", optarg);
63 exit(EXIT_FAILURE);
64 }
65 break;
66 case 'v':
67 printf("zone file concatenator version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
68 exit(EXIT_SUCCESS);
69 break;
70 default:
71 fprintf(stderr, "Unrecognized option\n");
72 usage(stdout, progname);
73 exit(EXIT_FAILURE);
74 }
75 }
76
77 argc -= optind;
78 argv += optind;
79
80 if (argc < 1) {
81 usage(stdout, progname);
82 exit(EXIT_FAILURE);
83 }
84
85 for (i = 0; i < (size_t)argc; i++) {
86
87 if (!(fp = fopen(argv[i], "r"))) {
88 fprintf(stderr, "Error opening key file %s: %s\n", argv[i], strerror(errno));
89 exit(EXIT_FAILURE);
90 }
91
92 if (ldns_zone_new_frm_fp(&z, fp, origin, 0, 0) != LDNS_STATUS_OK) {
93 fprintf(stderr, "Zone file %s could not be parsed correctly\n", argv[i]);
94 exit(EXIT_FAILURE);
95 }
96
97 zrr = ldns_zone_rrs(z);
98 soa = ldns_zone_soa(z); /* SOA is stored separately */
99
100 fprintf(stderr, "%s\n", argv[i]);
101
102 if (0 == i) {
103 where = FIRST_ZONE;
104
105 /* remove the last equal named RRs */
106 last_rr = ldns_rr_list_pop_rr(zrr);
107 last_owner = ldns_rr_owner(last_rr);
108 /* remove until no match */
109 do {
110 pop_rr = ldns_rr_list_pop_rr(zrr);
111 } while(ldns_rdf_compare(last_owner, ldns_rr_owner(pop_rr)) == 0) ;
112 /* we popped one to many, put it back */
113 ldns_rr_list_push_rr(zrr, pop_rr);
114 } else if ((size_t)(argc - 1) == i) {
115 where = LAST_ZONE;
116 } else {
117 where = MIDDLE_ZONE;
118
119 /* remove the last equal named RRs */
120 last_rr = ldns_rr_list_pop_rr(zrr);
121 last_owner = ldns_rr_owner(last_rr);
122 /* remove until no match */
123 do {
124 pop_rr = ldns_rr_list_pop_rr(zrr);
125 } while(ldns_rdf_compare(last_owner, ldns_rr_owner(pop_rr)) == 0) ;
126 /* we popped one to many, put it back */
127 ldns_rr_list_push_rr(zrr, pop_rr);
128 }
129
130 /* printing the RRs */
131 for (j = 0; j < ldns_rr_list_rr_count(zrr); j++) {
132
133 current_rr = ldns_rr_list_rr(zrr, j);
134
135 switch(where) {
136 case FIRST_ZONE:
137 if (soa) {
138 ldns_rr_print(stdout, soa);
139 soa = NULL;
140 }
141 break;
142 case MIDDLE_ZONE:
143 /* rm SOA */
144 /* SOA isn't printed by default */
145
146 /* rm SOA aux records
147 * this also takes care of the DNSKEYs + RRSIGS
148 */
149 if (ldns_rdf_compare(ldns_rr_owner(current_rr),
150 ldns_rr_owner(soa)) == 0) {
151 continue;
152 }
153 break;
154 case LAST_ZONE:
155 /* rm SOA */
156 /* SOA isn't printed by default */
157
158 /* rm SOA aux records
159 * this also takes care of the DNSKEYs + RRSIGS
160 */
161 if (ldns_rdf_compare(ldns_rr_owner(current_rr),
162 ldns_rr_owner(soa)) == 0) {
163 continue;
164 }
165 break;
166 }
167 ldns_rr_print(stdout, current_rr);
168 }
169 }
170 exit(EXIT_SUCCESS);
171 }
172