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