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