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