1 /* RFC2136 DNS inform - necessary for Win2k3 DNS servers */
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",
27 static uchar loopbacknet[IPaddrlen] = {
33 static uchar loopbackmask[IPaddrlen] = {
34 0xff, 0xff, 0xff, 0xff,
35 0xff, 0xff, 0xff, 0xff,
36 0xff, 0xff, 0xff, 0xff,
39 static uchar loopback6[IPaddrlen] = {
49 fprint(2, "usage: %s [-x netmtpt]\n", argv0);
54 ding(void *, char *msg)
56 if(strstr(msg, "alarm") != nil)
88 pmem(uchar **p, void *v, int len)
95 pname(uchar **p, char *s)
101 while(*s && *s != '.')
111 main(int argc, char *argv[])
113 static char *query[] = { "dom", "dnsdomain", "ns", "inform" };
114 char *sysname, *dnsdomain, *dom, *inform, *ns, net[32], dn[256], ds[256];
117 uchar *p, buf[4096], mynet[IPaddrlen];
124 fmtinstall('I', eipfmt);
125 fmtinstall('V', eipfmt);
126 setnetmtpt(net, sizeof net, nil);
138 setnetmtpt(net, sizeof net, EARGF(usage()));
147 if((sysname = getenv("sysname")) == nil)
148 sysfatal("$sysname not set");
150 if((db = ndbopen(nil)) == nil)
151 sysfatal("can't open ndb: %r");
152 tt = ndbipinfo(db, "sys", sysname, query, nelem(query));
153 for(t = tt; t; t = t->entry){
154 if(strcmp(t->attr, "ns") == 0)
156 else if(strcmp(t->attr, "dom") == 0)
158 else if(strcmp(t->attr, "dnsdomain") == 0)
160 else if(strcmp(t->attr, "inform") == 0)
170 sysfatal("no relevant ns=");
172 sysfatal("no relevant dom=");
174 sysfatal("no relevant dnsdomain=");
177 if(utf2idn(dom, dn, sizeof(dn)) <= 0)
178 sysfatal("cannot convert dom");
180 if(utf2idn(dnsdomain, ds, sizeof(ds)) <= 0)
181 sysfatal("cannot convert dnsdomain");
184 print("ns=%s\n", ns);
185 print("dnsdomain=%s\n", dnsdomain);
186 print("dom=%s\n", dom);
189 if((fd = dial(netmkaddr(ns, "udp", "dns"), 0, 0, 0)) < 0)
190 sysfatal("can't dial %s: %r", ns);
192 txid = time(nil) + getpid();
195 p16(&p, txid); /* ID */
196 p16(&p, 5<<11); /* flags */
197 p16(&p, 1); /* # Zones */
198 p16(&p, 0); /* # prerequisites */
199 p16(&p, 2); /* # updates */
200 p16(&p, 0); /* # additionals */
202 pname(&p, ds); /* zone */
203 p16(&p, Tsoa); /* zone type */
204 p16(&p, Cin); /* zone class */
206 /* delete old name */
207 pname(&p, dn); /* name */
208 p16(&p, Ta); /* type: v4 addr */
209 p16(&p, Call); /* class */
210 p32(&p, 0); /* TTL */
211 p16(&p, 0); /* data len */
213 pname(&p, dn); /* name */
214 p16(&p, Taaaa); /* type: v6 addr */
215 p16(&p, Call); /* class */
216 p32(&p, 0); /* TTL */
217 p16(&p, 0); /* data len */
219 for(ifc = readipifc(net, nil, -1); ifc != nil; ifc = ifc->next){
220 for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
222 if(ipcmp(lifc->ip, IPnoaddr) == 0)
226 if(ipcmp(lifc->ip, loopback6) == 0)
230 maskip(lifc->ip, loopbackmask, mynet);
231 if(ipcmp(mynet, loopbacknet) == 0)
235 print("ip=%I\n", lifc->ip);
237 /* add new A record */
238 pname(&p, dn); /* name */
239 p16(&p, isv4(lifc->ip)?Ta:Taaaa);
240 p16(&p, Cin); /* class */
241 p32(&p, 60*60*25); /* TTL (25 hours) */
243 p16(&p, IPv4addrlen);
244 pmem(&p, lifc->ip+IPv4off, IPv4addrlen);
247 pmem(&p, lifc->ip, IPaddrlen);
253 if(write(fd, buf, len) != len)
254 sysfatal("write failed: %r");
259 if(read(fd, buf, sizeof buf) < 0)
262 }while(g16(&p) != txid);
266 if(err != 0 && err != 7) /* err==7 is just a "yes, I know" warning */
267 if(err < nelem(errmsgs))
268 sysfatal("%s", errmsgs[err]);
270 sysfatal("unknown dns server error %d", err);