djbdnscurve6 45
djbdnscurve6
Loading...
Searching...
No Matches
tinydns-edit.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include "stralloc.h"
5#include "buffer.h"
6#include "exit.h"
7#include "open.h"
8#include "getln.h"
9#include "logmsg.h"
10#include "scan.h"
11#include "byte.h"
12#include "str.h"
13#include "fmt.h"
14#include "ip.h"
15#include "dns.h"
16
17#define WHO "tinydns-edit"
18
19#define TTL_NS 259200
20#define TTL_POSITIVE 86400
21
22char *fn;
23char *fnnew;
24
25int rename(const char *,const char *); // keep compiler silent
26
28{
29 logmsg(WHO,100,USAGE,"tinydns-edit data data.new add [ns|childns|host|alias|mx] domain a.b.c.d\n"
30 "tinydns-edit data data.new add [ns|childns|host6|alias6|mx] domain a:b:c:d:e:f:g:h");
31}
32void nomem()
33{
34 logmsg(WHO,111,FATAL,"out of memory");
35}
37{
38 logmsg(WHO,100,FATAL,B("fatal: unable to read: ",fn));
39}
41{
42 logmsg(WHO,111,FATAL,B("fatal: unable to write: ",fnnew));
43}
44
45char mode;
46static char *target;
47char targetip4[4];
48char targetip6[16];
49
50int fd;
51buffer b;
52char bspace[1024];
53
55buffer bnew;
56char bnewspace[1024];
57
58static stralloc line;
59int match = 1;
60
61#define NUMFIELDS 10
62static stralloc f[NUMFIELDS];
63
64static char *d1;
65static char *d2;
66char ip4[4];
67char ip6[16];
68char ip4str[IP4_FMT];
69char ip6str[IP6_FMT];
70char strnum[FMT_ULONG];
71
72static char *names[26];
73static int used[26];
74
75void put(const char *buf,unsigned int len)
76{
77 if (buffer_putalign(&bnew,buf,len) == -1) die_write();
78}
79
80int main(int argc,char **argv)
81{
82 unsigned long ttl;
83 struct stat st;
84 int i;
85 int j;
86 int k;
87 char ch;
88 int ipflag = 0;
89
90 if (!*argv) die_usage();
91
92 if (!*++argv) die_usage();
93 fn = *argv;
94
95 if (!*++argv) die_usage();
96 fnnew = *argv;
97
98 if (!*++argv) die_usage();
99 if (str_diff(*argv,"add")) die_usage();
100
101 if (!*++argv) die_usage();
102 if (str_equal(*argv,"ns")) mode = '.';
103 else if (str_equal(*argv,"childns")) mode = '&';
104 else if (str_equal(*argv,"host")) mode = '=';
105 else if (str_equal(*argv,"host6")) mode = ':';
106 else if (str_equal(*argv,"alias")) mode = '+';
107 else if (str_equal(*argv,"alias6")) mode = '~';
108 else if (str_equal(*argv,"mx")) mode = '@';
109 else die_usage();
110
111 if (!*++argv) die_usage();
112 if (dns_domain_fromdot(&target,*argv,str_len(*argv)) <= 0) nomem();
113
114 if (!*++argv) die_usage();
115 if (ip6_scan(*argv,targetip6)) ipflag = 2;
116 if (ip4_scan(*argv,targetip4)) ipflag = 1;
117 if (!ipflag) die_usage();
118
119 umask(077);
120
121 fd = open_read(fn);
122 if (fd == -1) die_read();
123 if (fstat(fd,&st) == -1) die_read();
124 buffer_init(&b,buffer_unixread,fd,bspace,sizeof(bspace));
125
126 fdnew = open_trunc(fnnew);
127 if (fdnew == -1) die_write();
128 if (fchmod(fdnew,st.st_mode & 0644) == -1) die_write();
129 buffer_init(&bnew,buffer_unixwrite,fdnew,bnewspace,sizeof(bnewspace));
130
131 switch (mode) {
132 case '.': case '&':
133 ttl = TTL_NS;
134 for (i = 0; i < 26; ++i) {
135 ch = 'a' + i;
136 if (!stralloc_copyb(&f[0],&ch,1)) nomem();
137 if (!stralloc_cats(&f[0],".ns.")) nomem();
138 if (dns_domain_todot_cat(&f[0],target) <= 0) nomem();
139 if (dns_domain_fromdot(&names[i],f[0].s,f[0].len) <= 0) nomem();
140 }
141 break;
142 case '+': case '=': case ':': case '~':
143 ttl = TTL_POSITIVE;
144 break;
145 case '@':
146 ttl = TTL_POSITIVE;
147 for (i = 0; i < 26; ++i) {
148 ch = 'a' + i;
149 if (!stralloc_copyb(&f[0],&ch,1)) nomem();
150 if (!stralloc_cats(&f[0],".mx.")) nomem();
151 if (dns_domain_todot_cat(&f[0],target) <= 0) nomem();
152 if (dns_domain_fromdot(&names[i],f[0].s,f[0].len) <= 0) nomem();
153 }
154 break;
155 }
156
157 while (match) {
158 if (getln(&b,&line,&match,'\n') == -1) die_read();
159
160 put(line.s,line.len);
161 if (line.len && !match) put("\n",1);
162
163 while (line.len) {
164 ch = line.s[line.len - 1];
165 if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
166 --line.len;
167 }
168 if (!line.len) continue;
169 if (line.s[0] == '#') continue;
170
171 j = 1;
172 for (i = 0; i < NUMFIELDS; ++i) {
173 if (j >= line.len) {
174 if (!stralloc_copys(&f[i],"")) nomem();
175 }
176 else {
177 k = byte_chr(line.s + j,line.len - j,'|');
178 if (!stralloc_copyb(&f[i],line.s + j,k)) nomem();
179 j += k + 1;
180 }
181 }
182
183 switch (mode) {
184 case '.': case '&':
185 if (line.s[0] == mode) {
186 if (dns_domain_fromdot(&d1,f[0].s,f[0].len) <= 0) nomem();
187 if (dns_domain_equal(d1,target)) {
188 if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
189 if (!stralloc_cats(&f[2],".ns.")) nomem();
190 if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
191 }
192 if (dns_domain_fromdot(&d2,f[2].s,f[2].len) <= 0) nomem();
193 if (!stralloc_0(&f[3])) nomem();
194 if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS;
195 for (i = 0; i < 26; ++i)
196 if (dns_domain_equal(d2,names[i])) {
197 used[i] = 1;
198 break;
199 }
200 }
201 }
202 break;
203
204 case '=':
205 if (line.s[0] == '=') {
206 if (dns_domain_fromdot(&d1,f[0].s,f[0].len) <= 0) nomem();
207 if (dns_domain_equal(d1,target))
208 logmsg(WHO,100,FATAL,"host name already used");
209 if (!stralloc_0(&f[1])) nomem();
210 if (ip4_scan(f[1].s,ip4))
211 if (byte_equal(ip4,4,targetip4))
212 logmsg(WHO,100,FATAL,"IP address already used");
213 }
214 break;
215
216 case ':':
217 if (line.s[0] == ':') {
218 if (dns_domain_fromdot(&d1,f[0].s,f[0].len) <= 0) nomem();
219 if (dns_domain_equal(d1,target))
220 logmsg(WHO,100,FATAL,"host name already used");
221 if (!stralloc_0(&f[1])) nomem();
222 if (ip6_scan(f[1].s,ip6))
223 if (byte_equal(ip6,16,targetip6))
224 logmsg(WHO,100,FATAL,"IPv6 address already used");
225 }
226 break;
227
228 case '@':
229 if (line.s[0] == '@') {
230 if (dns_domain_fromdot(&d1,f[0].s,f[0].len) <= 0) nomem();
231 if (dns_domain_equal(d1,target)) {
232 if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
233 if (!stralloc_cats(&f[2],".mx.")) nomem();
234 if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
235 }
236 if (dns_domain_fromdot(&d2,f[2].s,f[2].len) <= 0) nomem();
237 if (!stralloc_0(&f[4])) nomem();
238 if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE;
239 for (i = 0; i < 26; ++i)
240 if (dns_domain_equal(d2,names[i])) {
241 used[i] = 1;
242 break;
243 }
244 }
245 }
246 break;
247 }
248 }
249
250 if (!stralloc_copyb(&f[0],&mode,1)) nomem();
251 if (dns_domain_todot_cat(&f[0],target) <= 0) nomem();
252 if (!stralloc_cats(&f[0],"|")) nomem();
253 if (ipflag == 2) {
254 if (!stralloc_catb(&f[0],ip6str,ip6_fmt(ip6str,targetip6))) nomem();
255 } else {
256 if (!stralloc_catb(&f[0],ip4str,ip4_fmt(ip4str,targetip4))) nomem();
257 }
258 switch (mode) {
259 case '.': case '&': case '@':
260 for (i = 0; i < 26; ++i)
261 if (!used[i])
262 break;
263 if (i >= 26)
264 logmsg(WHO,100,FATAL,"too many records for that domain");
265 ch = 'a' + i;
266 if (!stralloc_cats(&f[0],"|")) nomem();
267 if (!stralloc_catb(&f[0],&ch,1)) nomem();
268 if (mode == '@')
269 if (!stralloc_cats(&f[0],"|")) nomem();
270 break;
271 }
272 if (!stralloc_cats(&f[0],"|")) nomem();
273 if (!stralloc_catb(&f[0],strnum,fmt_ulong(strnum,ttl))) nomem();
274 if (!stralloc_cats(&f[0],"\n")) nomem();
275 put(f[0].s,f[0].len);
276
277 if (buffer_flush(&bnew) == -1) die_write();
278 if (fsync(fdnew) == -1) die_write();
279 if (close(fdnew) == -1) die_write(); /* NFS dorks */
280 if (rename(fnnew,fn) == -1)
281 logmsg(WHO,111,FATAL,B("unable to move ",fnnew," to: ",fn));
282 _exit(0);
283}
uint16 len
Definition: axfrdns.c:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
int main()
Definition: axfrdns.c:323
int dns_domain_fromdot(char **out, const char *buf, unsigned int n)
Definition: dns_dfd.c:6
int dns_domain_equal(const char *dn1, const char *dn2)
Definition: dns_domain.c:39
int dns_domain_todot_cat(stralloc *out, const char *d)
Definition: dns_dtda.c:11
Definition: dnsfilter.c:23
char mode
Definition: tinydns-edit.c:45
char ip6str[IP6_FMT]
Definition: tinydns-edit.c:69
int fdnew
Definition: tinydns-edit.c:54
char bspace[1024]
Definition: tinydns-edit.c:52
char * fnnew
Definition: tinydns-edit.c:23
char strnum[FMT_ULONG]
Definition: tinydns-edit.c:70
void die_usage()
Definition: tinydns-edit.c:27
char targetip4[4]
Definition: tinydns-edit.c:47
int rename(const char *, const char *)
buffer bnew
Definition: tinydns-edit.c:55
char ip6[16]
Definition: tinydns-edit.c:67
void put(const char *buf, unsigned int len)
Definition: tinydns-edit.c:75
buffer b
Definition: tinydns-edit.c:51
int fd
Definition: tinydns-edit.c:50
void die_write()
Definition: tinydns-edit.c:40
char bnewspace[1024]
Definition: tinydns-edit.c:56
#define TTL_POSITIVE
Definition: tinydns-edit.c:20
void nomem()
Definition: tinydns-edit.c:32
#define TTL_NS
Definition: tinydns-edit.c:19
void die_read()
Definition: tinydns-edit.c:36
#define NUMFIELDS
Definition: tinydns-edit.c:61
char targetip6[16]
Definition: tinydns-edit.c:48
char ip4[4]
Definition: tinydns-edit.c:66
char * fn
Definition: tinydns-edit.c:22
int match
Definition: tinydns-edit.c:59
#define WHO
Definition: tinydns-edit.c:17
char ip4str[IP4_FMT]
Definition: tinydns-edit.c:68