]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ndb/inform.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / ndb / inform.c
1 /* RFC2136 DNS inform - necessary for Win2k3 DNS servers */
2 #include <u.h>
3 #include <libc.h>
4 #include <bio.h>
5 #include <ndb.h>
6 #include <ip.h>
7 #include "dns.h"
8
9 enum {
10         FQDNMAX = 255,
11 };
12
13 char *errmsgs[] = {
14         [0]  "ok",
15         [1]  "request format error",
16         [2]  "internal server error",
17         [3]  "domain name does not exist",
18         [4]  "request not supported",
19         [5]  "permission denied",
20         [6]  "domain name already exists",
21         [7]  "resource record already exists",
22         [8]  "resource record does not exist",
23         [9]  "server not authoritative",
24         [10] "domain name not in zone",
25 };
26
27 void
28 usage(void)
29 {
30         fprint(2, "usage: %s [-x netmtpt]\n", argv0);
31         exits("usage");
32 }
33
34 void
35 ding(void *, char *msg)
36 {
37         if(strstr(msg, "alarm") != nil)
38                 noted(NCONT);
39         noted(NDFLT);
40 }
41
42 int
43 g16(uchar **p)
44 {
45         int n;
46
47         n  = *(*p)++ << 8;
48         n |= *(*p)++;
49         return n;
50 }
51
52 void
53 p16(uchar **p, int n)
54 {
55         *(*p)++ = n >> 8;
56         *(*p)++ = n;
57 }
58
59 void
60 p32(uchar **p, int n)
61 {
62         *(*p)++ = n >> 24;
63         *(*p)++ = n >> 16;
64         *(*p)++ = n >> 8;
65         *(*p)++ = n;
66 }
67
68 void
69 pmem(uchar **p, void *v, int len)
70 {
71         memmove(*p, v, len);
72         *p += len;
73 }
74
75 void
76 pname(uchar **p, char *s)
77 {
78         uchar *len;
79
80         while (*s){
81                 len = (*p)++;
82                 while(*s && *s != '.')
83                         *(*p)++ = *s++;
84                 *len = *p - len - 1;
85                 if(*s == '.')
86                         s++;
87         }
88         *(*p)++ = 0;
89 }
90
91 void
92 main(int argc, char *argv[])
93 {
94         int debug, len, fd;
95         uint err;
96         char *sysname, *dnsdomain, *dom, *inform, *ns, net[32];
97         uchar *p, buf[4096], addr[IPv4addrlen], v6addr[IPaddrlen];
98         ushort txid;
99         Ndb *db;
100         Ndbtuple *t, *tt;
101         static char *query[] = { "dom", "dnsdomain", "ns", "inform" };
102
103         fmtinstall('I', eipfmt);
104         fmtinstall('V', eipfmt);
105         setnetmtpt(net, sizeof net, nil);
106
107         debug = 0;
108         ns = nil;
109         dom = nil;
110         inform = nil;
111         dnsdomain = nil;
112         ARGBEGIN{
113         case 'd':
114                 debug = 1;
115                 break;
116         case 'x':
117                 setnetmtpt(net, sizeof net, EARGF(usage()));
118                 break;
119         default:
120                 usage();
121         }ARGEND;
122
123         if(argc != 0)
124                 usage();
125
126         if((sysname = getenv("sysname")) == nil)
127                 sysfatal("$sysname not set");
128
129         if((db = ndbopen(nil)) == nil)
130                 sysfatal("can't open ndb: %r");
131         tt = ndbipinfo(db, "sys", sysname, query, nelem(query));
132         for(t = tt; t; t = t->entry){
133                 if(strcmp(t->attr, "ns") == 0)
134                         ns = t->val;
135                 else if(strcmp(t->attr, "dom") == 0)
136                         dom = t->val;
137                 else if(strcmp(t->attr, "dnsdomain") == 0)
138                         dnsdomain = t->val;
139                 else if(strcmp(t->attr, "inform") == 0)
140                         inform = t->val;
141         }
142
143         ndbfree(tt);
144         ndbclose(db);
145
146         if(inform)
147                 dom = inform;
148         if(!ns)
149                 sysfatal("no relevant ns=");
150         if(!dom)
151                 sysfatal("no relevant dom=");
152         if(!dnsdomain)
153                 sysfatal("no relevant dnsdomain=");
154
155         myipaddr(v6addr, net);
156         memmove(addr, v6addr + IPaddrlen - IPv4addrlen, IPv4addrlen);
157
158         if(debug){
159                 print("ip=%V\n", addr);
160                 print("ns=%s\n", ns);
161                 print("dnsdomain=%s\n", dnsdomain);
162                 print("dom=%s\n", dom);
163         }
164
165         if((fd = dial(netmkaddr(ns, "udp", "dns"), 0, 0, 0)) < 0)
166                 sysfatal("can't dial %s: %r", ns);
167
168         txid = time(nil) + getpid();
169
170         p = buf;
171         p16(&p, txid);          /* ID */
172         p16(&p, 5<<11);         /* flags */
173         p16(&p, 1);             /* # Zones */
174         p16(&p, 0);             /* # prerequisites */
175         p16(&p, 2);             /* # updates */
176         p16(&p, 0);             /* # additionals */
177
178         pname(&p, dnsdomain);   /* zone */
179         p16(&p, Tsoa);          /* zone type */
180         p16(&p, Cin);           /* zone class */
181
182         /* delete old name */
183         pname(&p, dom);         /* name */
184         p16(&p, Ta);            /* type: v4 addr */
185         p16(&p, Call);          /* class */
186         p32(&p, 0);             /* TTL */
187         p16(&p, 0);             /* data len */
188
189         /* add new A record */
190         pname(&p, dom);         /* name */
191         p16(&p, Ta);            /* type: v4 addr */
192         p16(&p, Cin);           /* class */
193         p32(&p, 60*60*25);      /* TTL (25 hours) */
194         p16(&p, IPv4addrlen);   /* data len */
195         pmem(&p, addr, IPv4addrlen);    /* v4 address */
196
197         len = p - buf;
198         if(write(fd, buf, len) != len)
199                 sysfatal("write failed: %r");
200
201         notify(ding);
202         alarm(3000);
203         do{
204                 if(read(fd, buf, sizeof buf) < 0)
205                         sysfatal("timeout");
206                 p = buf;
207         }while(g16(&p) != txid);
208         alarm(0);
209
210         close(fd);
211
212         err = g16(&p) & 7;
213         if(err != 0 && err != 7)        /* err==7 is just a "yes, I know" warning */
214                 if(err < nelem(errmsgs))
215                         sysfatal("%s", errmsgs[err]);
216                 else
217                         sysfatal("unknown dns server error %d", err);
218         exits(0);
219 }