1 /* Public domain, from djbdns-1.05. */
2
3 #include <unistd.h>
4 #include "taia.h"
5 #include "env.h"
6 #include "byte.h"
7 #include "str.h"
8 #include "openreadclose.h"
9 #include "dns.h"
10
11 static stralloc data = {0};
12
init(stralloc * rules)13 static int init(stralloc *rules)
14 {
15 char host[256];
16 const char *x;
17 unsigned int i;
18 unsigned int j;
19 int k;
20
21 if (!stralloc_copys(rules,"")) return -1;
22
23 x = env_get("DNSREWRITEFILE");
24 if (!x) x = "/etc/dnsrewrite";
25
26 k = openreadclose(x,&data,64);
27 if (k == -1) return -1;
28
29 if (k) {
30 if (!stralloc_append(&data,'\n')) return -1;
31 i = 0;
32 for (j = 0;j < data.len;++j)
33 if (data.s[j] == '\n') {
34 if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
35 while (rules->len) {
36 if (rules->s[rules->len - 1] != ' ')
37 if (rules->s[rules->len - 1] != '\t')
38 if (rules->s[rules->len - 1] != '\r')
39 break;
40 --rules->len;
41 }
42 if (!stralloc_0(rules)) return -1;
43 i = j + 1;
44 }
45 return 0;
46 }
47
48 x = env_get("LOCALDOMAIN");
49 if (x) {
50 if (!stralloc_copys(&data,x)) return -1;
51 if (!stralloc_append(&data,' ')) return -1;
52 if (!stralloc_copys(rules,"?:")) return -1;
53 i = 0;
54 for (j = 0;j < data.len;++j)
55 if (data.s[j] == ' ') {
56 if (!stralloc_cats(rules,"+.")) return -1;
57 if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
58 i = j + 1;
59 }
60 if (!stralloc_0(rules)) return -1;
61 if (!stralloc_cats(rules,"*.:")) return -1;
62 if (!stralloc_0(rules)) return -1;
63 return 0;
64 }
65
66 k = openreadclose("/etc/resolv.conf",&data,64);
67 if (k == -1) return -1;
68
69 if (k) {
70 if (!stralloc_append(&data,'\n')) return -1;
71 i = 0;
72 for (j = 0;j < data.len;++j)
73 if (data.s[j] == '\n') {
74 if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) {
75 if (!stralloc_copys(rules,"?:")) return -1;
76 i += 7;
77 while (i < j) {
78 k = byte_chr(data.s + i,j - i,' ');
79 k = byte_chr(data.s + i,k,'\t');
80 if (!k) { ++i; continue; }
81 if (!stralloc_cats(rules,"+.")) return -1;
82 if (!stralloc_catb(rules,data.s + i,k)) return -1;
83 i += k;
84 }
85 if (!stralloc_0(rules)) return -1;
86 if (!stralloc_cats(rules,"*.:")) return -1;
87 if (!stralloc_0(rules)) return -1;
88 return 0;
89 }
90 i = j + 1;
91 }
92 }
93
94 host[0] = 0;
95 if (gethostname(host,sizeof host) == -1) return -1;
96 host[(sizeof host) - 1] = 0;
97 i = str_chr(host,'.');
98 if (host[i]) {
99 if (!stralloc_copys(rules,"?:")) return -1;
100 if (!stralloc_cats(rules,host + i)) return -1;
101 if (!stralloc_0(rules)) return -1;
102 }
103 if (!stralloc_cats(rules,"*.:")) return -1;
104 if (!stralloc_0(rules)) return -1;
105
106 return 0;
107 }
108
109 static int ok = 0;
110 static unsigned int uses;
111 static struct taia deadline;
112 static stralloc rules = {0}; /* defined if ok */
113
dns_resolvconfrewrite(stralloc * out)114 int dns_resolvconfrewrite(stralloc *out)
115 {
116 struct taia now;
117
118 taia_now(&now);
119 if (taia_less(&deadline,&now)) ok = 0;
120 if (!uses) ok = 0;
121
122 if (!ok) {
123 if (init(&rules) == -1) return -1;
124 taia_uint(&deadline,600);
125 taia_add(&deadline,&now,&deadline);
126 uses = 10000;
127 ok = 1;
128 }
129
130 --uses;
131 if (!stralloc_copy(out,&rules)) return -1;
132 return 0;
133 }
134