1 // hosts2zones.c
2 // hosts2zones
3 //
4 // Created by Dr. Rolf Jansen on 2014-07-06.
5 // Copyright (c) 2014 projectworld.net. All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without modification,
8 // are permitted provided that the following conditions are met:
9 //
10 // 1. Redistributions of source code must retain the above copyright notice,
11 // this list of conditions and the following disclaimer.
12 //
13 // 2. Redistributions in binary form must reproduce the above copyright notice,
14 // this list of conditions and the following disclaimer in the documentation
15 // and/or other materials provided with the distribution.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
24 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdbool.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <sys/stat.h>
33
34 #include "binutils.h"
35 #include "store.h"
36
37
38 #define hcnt 65535
39
40 int hosts_count = 0;
41 int zones_count = 0;
42 FILE *in, *out;
43 Node **domainStore;
44
45
zoneOutput(Node * node)46 void zoneOutput(Node *node)
47 {
48 if (node)
49 {
50 zoneOutput(node->L);
51 zoneOutput(node->R);
52
53 bool ontop = true;
54 int n, level = 0;
55 char *q, *p = node->name;
56
57 for (q = p + node->naml, n = 0; ontop && q > p; q--, n++)
58 if (*q && *(q-1) == '.' && (++level >= 3 || level == 2 && n > 6) && findName(domainStore, q, n))
59 ontop = false;
60
61 if (ontop && level && !node->value.b)
62 {
63 fprintf(out, "local-zone: \"%s\" static\n", node->name);
64 zones_count++;
65 }
66 }
67 }
68
69
main(int argc,const char * argv[])70 int main(int argc, const char *argv[])
71 {
72 if (argc >= 3 && (out = fopen(argv[1], "w")))
73 {
74 domainStore = createTable(hcnt);
75
76 int inc;
77 struct stat st;
78 for (inc = 2; inc < argc; inc++)
79 if (stat(argv[inc], &st) == noerr && st.st_size > 3 && (in = fopen(argv[inc], "r")))
80 {
81 char *hosts = allocate(st.st_size + 2, false);
82 if (fread(hosts, st.st_size, 1, in) == 1)
83 {
84 *(uint16_t *)&hosts[st.st_size] = *(uint16_t *)"\n"; // guaranteed end of line + end of string at the end of the read-in data
85
86 bool iswhite;
87 int dl, ll, wl;
88 char *word, *lineend, *nextword, *nextline;
89 char *line = hosts + blanklen(hosts); // get the start of the first line by skipping leading blanks + blank lines
90
91 while (line < hosts + st.st_size)
92 {
93 ll = linelen(line);
94 lineend = bskip(line+ll); // skip trailing blanks
95 *lineend = '\0'; // separate the entry as string
96
97 nextline = line + ll+1; // get the start of the next line
98 nextline += blanklen(nextline); // by skipping leading blanks + blank lines
99
100 if (*line != '#') // skip comment lines
101 {
102 word = NULL; // assume an inacceptable entry
103
104 line[wl = wordlen(line)] = '\0'; // pickup the first entry on the line
105 if (line+wl == lineend && // accept a single domain name per line which
106 0 < (dl = domainlen(line)) && dl < wl) // must contain at least 1 non-leading & non-traling dot
107 word = line, iswhite = false; // simple domain lists are always black lists
108 // otherwise assume the Hosts file format
109 else if ((iswhite = *(int64_t *)line == *(int64_t *)"1.1.1.1") || // entries starting with 1.1.1.1 shall be white listed
110 /*isblack*/ *(int64_t *)line == *(int64_t *)"0.0.0.0" || // 0.0.0.0 or 127.0.0.1 are black list entries
111 /*isblack*/ *(int16_t *)line == *(int16_t *)"12" &&
112 *(int64_t *)(line+=2) == *(int64_t *)"7.0.0.1")
113 word = line + 8, word += blanklen(word); // skip IP address and leading blanks
114
115 if (word) // only process simple domain entries or entries in Hosts file format
116 while (*word && *word != '#' && word < nextline) // Hosts files may contain more than one domain per line
117 {
118 wl = wordlen(word);
119 nextword = word + wl;
120 *nextword++ = '\0';
121 nextword += blanklen(nextword);
122
123 if (*lowercase(word, wl) && // convert to lowercase, end check if it is a non empty string
124 (*(int64_t *)word != *(int64_t *)"localhos" // don't process 'localhost' entries
125 || *(int16_t *)(word+8) != *(int16_t *)"t") &&
126 !findName(domainStore, word, wl)) // if the entry does not exit in the domain store
127 { // then create a new one for the given domain name
128 Value value = {Simple, .b = iswhite};
129 storeName(domainStore, word, wl, &value);
130 hosts_count++;
131 }
132
133 word = nextword;
134 }
135 }
136
137 line = nextline;
138 }
139 }
140
141 deallocate(VPR(hosts), false);
142 fclose(in);
143 }
144
145 for (size_t h = 1; h <= hcnt; h++)
146 zoneOutput(domainStore[h]);
147
148 releaseTable(domainStore);
149 fclose(out);
150
151 printf("Number of Hosts: %d\nNumber of Zones: %d\n", hosts_count, zones_count);
152
153 return (zones_count > 0) ? 0 : 1;
154 }
155 else
156 return 1;
157 }
158