Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 230 lines (198 sloc) 5.19 kb
3eccf34 @pjps New djbdns - initial commit.
pjps authored
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include "buffer.h"
6 #include "cdb_make.h"
7 #include "open.h"
8 #include "alloc.h"
9 #include "gen_allocdefs.h"
10 #include "stralloc.h"
11 #include "getln.h"
12 #include "case.h"
13 #include "strerr.h"
14 #include "str.h"
15 #include "byte.h"
16 #include "scan.h"
17 #include "fmt.h"
18 #include "ip4.h"
19 #include "dns.h"
20
21 #define FATAL "pickdns-data: fatal: "
22
23 void nomem(void)
24 {
25 strerr_die2x(111,FATAL,"out of memory");
26 }
27
28 void ipprefix_cat(stralloc *out,char *s)
29 {
30 unsigned long u;
31 char ch;
32 unsigned int j;
33
34 for (;;)
35 if (*s == '.')
36 ++s;
37 else {
38 j = scan_ulong(s,&u);
39 if (!j) return;
40 s += j;
41 ch = u;
42 if (!stralloc_catb(out,&ch,1)) nomem();
43 }
44 }
45
46 struct address {
47 char *name;
48 unsigned int namelen;
49 char ip[4];
50 char location[2];
51 } ;
52
53 int address_diff(struct address *p,struct address *q)
54 {
55 int r;
56
57 r = byte_diff(p->location,2,q->location);
58 if (r < 0) return -1;
59 if (r > 0) return 1;
60 if (p->namelen < q->namelen) return -1;
61 if (p->namelen > q->namelen) return 1;
62 return case_diffb(p->name,p->namelen,q->name);
63 }
64
65 void address_sort(struct address *z,unsigned int n)
66 {
67 unsigned int i;
68 unsigned int j;
69 unsigned int p;
70 unsigned int q;
71 struct address t;
72
73 i = j = n;
74 --z;
75
76 while (j > 1) {
77 if (i > 1) { --i; t = z[i]; }
78 else { t = z[j]; z[j] = z[i]; --j; }
79 q = i;
80 while ((p = q * 2) < j) {
81 if (address_diff(&z[p + 1],&z[p]) >= 0) ++p;
82 z[q] = z[p]; q = p;
83 }
84 if (p == j) {
85 z[q] = z[p]; q = p;
86 }
87 while ((q > i) && (address_diff(&t,&z[p = q/2]) > 0)) {
88 z[q] = z[p]; q = p;
89 }
90 z[q] = t;
91 }
92 }
93
94 GEN_ALLOC_typedef(address_alloc,struct address,s,len,a)
95 GEN_ALLOC_readyplus(address_alloc,struct address,s,len,a,i,n,x,30,address_alloc_readyplus)
96 GEN_ALLOC_append(address_alloc,struct address,s,len,a,i,n,x,30,address_alloc_readyplus,address_alloc_append)
97
98 static address_alloc x;
99
100 int fd;
101 buffer b;
102 char bspace[1024];
103
104 int fdcdb;
105 struct cdb_make cdb;
106 static stralloc key;
107 static stralloc result;
108
109 static stralloc line;
110 int match = 1;
111 unsigned long linenum = 0;
112
113 #define NUMFIELDS 3
114 static stralloc f[NUMFIELDS];
115
116 char strnum[FMT_ULONG];
117
118 void syntaxerror(const char *why)
119 {
120 strnum[fmt_ulong(strnum,linenum)] = 0;
121 strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why);
122 }
123 void die_datatmp(void)
124 {
125 strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
126 }
127
128 int main()
129 {
130 struct address t;
131 int i;
132 int j;
133 int k;
134 char ch;
135
136 umask(022);
137
138 if (!address_alloc_readyplus(&x,0)) nomem();
139
140 fd = open_read("data");
141 if (fd == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
142 buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);
143
144 fdcdb = open_trunc("data.tmp");
145 if (fdcdb == -1) die_datatmp();
146 if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
147
148 while (match) {
149 ++linenum;
150 if (getln(&b,&line,&match,'\n') == -1)
151 strerr_die2sys(111,FATAL,"unable to read line: ");
152
153 while (line.len) {
154 ch = line.s[line.len - 1];
155 if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
156 --line.len;
157 }
158 if (!line.len) continue;
159
160 j = 1;
161 for (i = 0;i < NUMFIELDS;++i) {
162 if (j >= line.len) {
163 if (!stralloc_copys(&f[i],"")) nomem();
164 }
165 else {
166 k = byte_chr(line.s + j,line.len - j,':');
167 if (!stralloc_copyb(&f[i],line.s + j,k)) nomem();
168 j += k + 1;
169 }
170 }
171
172 switch(line.s[0]) {
173 default:
174 syntaxerror(": unrecognized leading character");
175 case '#':
176 break;
177 case '-':
178 break;
179 case '+':
180 byte_zero(&t,sizeof t);
181 if (!dns_domain_fromdot(&t.name,f[0].s,f[0].len)) nomem();
182 t.namelen = dns_domain_length(t.name);
183 case_lowerb(t.name,t.namelen);
184 if (!stralloc_0(&f[1])) nomem();
185 if (!ip4_scan(f[1].s,t.ip)) syntaxerror(": malformed IP address");
186 if (!stralloc_0(&f[2])) nomem();
187 if (!stralloc_0(&f[2])) nomem();
188 byte_copy(t.location,2,f[2].s);
189 if (!address_alloc_append(&x,&t)) nomem();
190 break;
191 case '%':
192 if (!stralloc_0(&f[0])) nomem();
193 if (!stralloc_0(&f[0])) nomem();
194 if (!stralloc_copyb(&result,f[0].s,2)) nomem();
195 if (!stralloc_0(&f[1])) nomem();
196 if (!stralloc_copys(&key,"%")) nomem();
197 ipprefix_cat(&key,f[1].s);
198 if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1)
199 die_datatmp();
200 break;
201 }
202 }
203
204 close(fd);
205 address_sort(x.s,x.len);
206
207 i = 0;
208 while (i < x.len) {
209 for (j = i + 1;j < x.len;++j)
210 if (address_diff(x.s + i,x.s + j))
211 break;
212 if (!stralloc_copys(&key,"+")) nomem();
213 if (!stralloc_catb(&key,x.s[i].location,2)) nomem();
214 if (!stralloc_catb(&key,x.s[i].name,x.s[i].namelen)) nomem();
215 if (!stralloc_copys(&result,"")) nomem();
216 while (i < j)
217 if (!stralloc_catb(&result,x.s[i++].ip,4)) nomem();
218 if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1)
219 die_datatmp();
220 }
221
222 if (cdb_make_finish(&cdb) == -1) die_datatmp();
223 if (fsync(fdcdb) == -1) die_datatmp();
224 if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
225 if (rename("data.tmp","data.cdb") == -1)
226 strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
227
228 return 0;
229 }
Something went wrong with that request. Please try again.