inform.c 4.0 KB

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