PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/addns/dnsrecord.c

https://github.com/lauria/Samba4
C | 474 lines | 352 code | 87 blank | 35 comment | 44 complexity | 93e189cb4ec2f275475cb282cd407a63 MD5 | raw file
  1. /*
  2. Linux DNS client library implementation
  3. Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
  4. Copyright (C) 2006 Gerald Carter <jerry@samba.org>
  5. ** NOTE! The following LGPL license applies to the libaddns
  6. ** library. This does NOT imply that all of Samba is released
  7. ** under the LGPL
  8. This library is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU Lesser General Public
  10. License as published by the Free Software Foundation; either
  11. version 2.1 of the License, or (at your option) any later version.
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. Lesser General Public License for more details.
  16. You should have received a copy of the GNU Lesser General Public
  17. License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "dns.h"
  20. DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
  21. uint16 q_type, uint16 q_class,
  22. struct dns_request **preq )
  23. {
  24. struct dns_request *req;
  25. struct dns_question *q;
  26. DNS_ERROR err;
  27. if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
  28. !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
  29. !(req->questions[0] = talloc(req->questions,
  30. struct dns_question))) {
  31. TALLOC_FREE(req);
  32. return ERROR_DNS_NO_MEMORY;
  33. }
  34. req->id = random();
  35. req->num_questions = 1;
  36. q = req->questions[0];
  37. err = dns_domain_name_from_string(q, name, &q->name);
  38. if (!ERR_DNS_IS_OK(err)) {
  39. TALLOC_FREE(req);
  40. return err;
  41. }
  42. q->q_type = q_type;
  43. q->q_class = q_class;
  44. *preq = req;
  45. return ERROR_DNS_SUCCESS;
  46. }
  47. DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
  48. struct dns_update_request **preq )
  49. {
  50. struct dns_update_request *req;
  51. struct dns_zone *z;
  52. DNS_ERROR err;
  53. if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
  54. !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
  55. !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
  56. TALLOC_FREE(req);
  57. return ERROR_DNS_NO_MEMORY;
  58. }
  59. req->id = random();
  60. req->flags = 0x2800; /* Dynamic update */
  61. req->num_zones = 1;
  62. z = req->zones[0];
  63. err = dns_domain_name_from_string(z, name, &z->name);
  64. if (!ERR_DNS_IS_OK(err)) {
  65. TALLOC_FREE(req);
  66. return err;
  67. }
  68. z->z_type = QTYPE_SOA;
  69. z->z_class = DNS_CLASS_IN;
  70. *preq = req;
  71. return ERROR_DNS_SUCCESS;
  72. }
  73. DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
  74. uint16 type, uint16 r_class, uint32 ttl,
  75. uint16 data_length, uint8 *data,
  76. struct dns_rrec **prec)
  77. {
  78. struct dns_rrec *rec;
  79. DNS_ERROR err;
  80. if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
  81. return ERROR_DNS_NO_MEMORY;
  82. }
  83. err = dns_domain_name_from_string(rec, name, &rec->name);
  84. if (!(ERR_DNS_IS_OK(err))) {
  85. TALLOC_FREE(rec);
  86. return err;
  87. }
  88. rec->type = type;
  89. rec->r_class = r_class;
  90. rec->ttl = ttl;
  91. rec->data_length = data_length;
  92. rec->data = talloc_move(rec, &data);
  93. *prec = rec;
  94. return ERROR_DNS_SUCCESS;
  95. }
  96. DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
  97. uint32 ttl, const struct sockaddr_storage *pss,
  98. struct dns_rrec **prec)
  99. {
  100. uint8 *data;
  101. DNS_ERROR err;
  102. struct in_addr ip;
  103. if (pss->ss_family != AF_INET) {
  104. return ERROR_DNS_INVALID_PARAMETER;
  105. }
  106. ip = ((const struct sockaddr_in *)pss)->sin_addr;
  107. if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip.s_addr,
  108. sizeof(ip.s_addr)))) {
  109. return ERROR_DNS_NO_MEMORY;
  110. }
  111. err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
  112. sizeof(ip.s_addr), data, prec);
  113. if (!ERR_DNS_IS_OK(err)) {
  114. TALLOC_FREE(data);
  115. }
  116. return err;
  117. }
  118. DNS_ERROR dns_create_aaaa_record(TALLOC_CTX *mem_ctx, const char *host,
  119. uint32 ttl, const struct sockaddr_storage *pss,
  120. struct dns_rrec **prec)
  121. {
  122. #ifdef HAVE_IPV6
  123. uint8 *data;
  124. DNS_ERROR err;
  125. struct in6_addr ip6;
  126. if (pss->ss_family != AF_INET6) {
  127. return ERROR_DNS_INVALID_PARAMETER;
  128. }
  129. ip6 = ((const struct sockaddr_in6 *)pss)->sin6_addr;
  130. if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip6.s6_addr,
  131. sizeof(ip6.s6_addr)))) {
  132. return ERROR_DNS_NO_MEMORY;
  133. }
  134. err = dns_create_rrec(mem_ctx, host, QTYPE_AAAA, DNS_CLASS_IN, ttl,
  135. sizeof(ip6.s6_addr), data, prec);
  136. if (!ERR_DNS_IS_OK(err)) {
  137. TALLOC_FREE(data);
  138. }
  139. return err;
  140. #else
  141. return ERROR_DNS_INVALID_PARAMETER;
  142. #endif
  143. }
  144. DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
  145. const char *name,
  146. const struct sockaddr_storage *ss,
  147. struct dns_rrec **prec)
  148. {
  149. if (ss != NULL) {
  150. switch (ss->ss_family) {
  151. case AF_INET:
  152. return dns_create_a_record(mem_ctx, name, 0, ss, prec);
  153. #ifdef HAVE_IPV6
  154. case AF_INET6:
  155. return dns_create_aaaa_record(mem_ctx, name, 0, ss, prec);
  156. #endif
  157. default:
  158. return ERROR_DNS_INVALID_PARAMETER;
  159. }
  160. }
  161. return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
  162. NULL, prec);
  163. }
  164. DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
  165. const char *name, uint32 type,
  166. struct dns_rrec **prec)
  167. {
  168. return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
  169. 0, NULL, prec);
  170. }
  171. DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
  172. uint16 type, uint16 r_class,
  173. struct dns_rrec **prec)
  174. {
  175. return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
  176. }
  177. DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
  178. const char *algorithm_name, time_t inception,
  179. time_t expiration, uint16 mode, uint16 error,
  180. uint16 key_length, const uint8 *key,
  181. struct dns_rrec **prec)
  182. {
  183. struct dns_buffer *buf;
  184. struct dns_domain_name *algorithm;
  185. DNS_ERROR err;
  186. if (!(buf = dns_create_buffer(mem_ctx))) {
  187. return ERROR_DNS_NO_MEMORY;
  188. }
  189. err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
  190. if (!ERR_DNS_IS_OK(err)) goto error;
  191. dns_marshall_domain_name(buf, algorithm);
  192. dns_marshall_uint32(buf, inception);
  193. dns_marshall_uint32(buf, expiration);
  194. dns_marshall_uint16(buf, mode);
  195. dns_marshall_uint16(buf, error);
  196. dns_marshall_uint16(buf, key_length);
  197. dns_marshall_buffer(buf, key, key_length);
  198. dns_marshall_uint16(buf, 0); /* Other Size */
  199. if (!ERR_DNS_IS_OK(buf->error)) {
  200. err = buf->error;
  201. goto error;
  202. }
  203. err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
  204. buf->offset, buf->data, prec);
  205. error:
  206. TALLOC_FREE(buf);
  207. return err;
  208. }
  209. DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
  210. struct dns_tkey_record **ptkey)
  211. {
  212. struct dns_tkey_record *tkey;
  213. struct dns_buffer buf;
  214. uint32 tmp_inception, tmp_expiration;
  215. if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
  216. return ERROR_DNS_NO_MEMORY;
  217. }
  218. buf.data = rec->data;
  219. buf.size = rec->data_length;
  220. buf.offset = 0;
  221. buf.error = ERROR_DNS_SUCCESS;
  222. dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
  223. dns_unmarshall_uint32(&buf, &tmp_inception);
  224. dns_unmarshall_uint32(&buf, &tmp_expiration);
  225. dns_unmarshall_uint16(&buf, &tkey->mode);
  226. dns_unmarshall_uint16(&buf, &tkey->error);
  227. dns_unmarshall_uint16(&buf, &tkey->key_length);
  228. if (!ERR_DNS_IS_OK(buf.error)) goto error;
  229. if (tkey->key_length) {
  230. if (!(tkey->key = talloc_array(tkey, uint8, tkey->key_length))) {
  231. buf.error = ERROR_DNS_NO_MEMORY;
  232. goto error;
  233. }
  234. } else {
  235. tkey->key = NULL;
  236. }
  237. dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
  238. if (!ERR_DNS_IS_OK(buf.error)) goto error;
  239. tkey->inception = (time_t)tmp_inception;
  240. tkey->expiration = (time_t)tmp_expiration;
  241. *ptkey = tkey;
  242. return ERROR_DNS_SUCCESS;
  243. error:
  244. TALLOC_FREE(tkey);
  245. return buf.error;
  246. }
  247. DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
  248. const char *algorithm_name,
  249. time_t time_signed, uint16 fudge,
  250. uint16 mac_length, const uint8 *mac,
  251. uint16 original_id, uint16 error,
  252. struct dns_rrec **prec)
  253. {
  254. struct dns_buffer *buf;
  255. struct dns_domain_name *algorithm;
  256. DNS_ERROR err;
  257. if (!(buf = dns_create_buffer(mem_ctx))) {
  258. return ERROR_DNS_NO_MEMORY;
  259. }
  260. err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
  261. if (!ERR_DNS_IS_OK(err)) goto error;
  262. dns_marshall_domain_name(buf, algorithm);
  263. dns_marshall_uint16(buf, 0); /* time prefix */
  264. dns_marshall_uint32(buf, time_signed);
  265. dns_marshall_uint16(buf, fudge);
  266. dns_marshall_uint16(buf, mac_length);
  267. dns_marshall_buffer(buf, mac, mac_length);
  268. dns_marshall_uint16(buf, original_id);
  269. dns_marshall_uint16(buf, error);
  270. dns_marshall_uint16(buf, 0); /* Other Size */
  271. if (!ERR_DNS_IS_OK(buf->error)) {
  272. err = buf->error;
  273. goto error;
  274. }
  275. err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
  276. buf->offset, buf->data, prec);
  277. error:
  278. TALLOC_FREE(buf);
  279. return err;
  280. }
  281. DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
  282. uint16 *num_records, struct dns_rrec ***records)
  283. {
  284. struct dns_rrec **new_records;
  285. if (!(new_records = talloc_realloc(mem_ctx, *records,
  286. struct dns_rrec *,
  287. (*num_records)+1))) {
  288. return ERROR_DNS_NO_MEMORY;
  289. }
  290. new_records[*num_records] = talloc_move(new_records, &rec);
  291. *num_records += 1;
  292. *records = new_records;
  293. return ERROR_DNS_SUCCESS;
  294. }
  295. /*
  296. * Create a request that probes a server whether the list of IP addresses
  297. * provides meets our expectations
  298. */
  299. DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
  300. const char *host, int num_ips,
  301. const struct sockaddr_storage *sslist,
  302. struct dns_update_request **preq)
  303. {
  304. struct dns_update_request *req;
  305. struct dns_rrec *rec;
  306. DNS_ERROR err;
  307. uint16 i;
  308. err = dns_create_update(mem_ctx, zone, &req);
  309. if (!ERR_DNS_IS_OK(err)) goto error;
  310. err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
  311. if (!ERR_DNS_IS_OK(err)) goto error;
  312. err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
  313. if (!ERR_DNS_IS_OK(err)) goto error;
  314. for (i=0; i<num_ips; i++) {
  315. err = dns_create_name_in_use_record(req, host,
  316. &sslist[i], &rec);
  317. if (!ERR_DNS_IS_OK(err)) goto error;
  318. err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
  319. if (!ERR_DNS_IS_OK(err)) goto error;
  320. }
  321. *preq = req;
  322. return ERROR_DNS_SUCCESS;
  323. error:
  324. TALLOC_FREE(req);
  325. return err;
  326. }
  327. DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
  328. const char *domainname,
  329. const char *hostname,
  330. const struct sockaddr_storage *ss_addrs,
  331. size_t num_addrs,
  332. struct dns_update_request **preq)
  333. {
  334. struct dns_update_request *req;
  335. struct dns_rrec *rec;
  336. DNS_ERROR err;
  337. size_t i;
  338. err = dns_create_update(mem_ctx, domainname, &req);
  339. if (!ERR_DNS_IS_OK(err)) return err;
  340. /*
  341. * Use the same prereq as WinXP -- No CNAME records for this host.
  342. */
  343. err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
  344. 0, 0, NULL, &rec);
  345. if (!ERR_DNS_IS_OK(err)) goto error;
  346. err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
  347. if (!ERR_DNS_IS_OK(err)) goto error;
  348. /*
  349. * Delete any existing A records
  350. */
  351. err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
  352. &rec);
  353. if (!ERR_DNS_IS_OK(err)) goto error;
  354. err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
  355. if (!ERR_DNS_IS_OK(err)) goto error;
  356. /*
  357. * .. and add our IPs
  358. */
  359. for ( i=0; i<num_addrs; i++ ) {
  360. switch(ss_addrs[i].ss_family) {
  361. case AF_INET:
  362. err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
  363. break;
  364. #ifdef HAVE_IPV6
  365. case AF_INET6:
  366. err = dns_create_aaaa_record(req, hostname, 3600, &ss_addrs[i], &rec);
  367. break;
  368. #endif
  369. default:
  370. continue;
  371. }
  372. if (!ERR_DNS_IS_OK(err))
  373. goto error;
  374. err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
  375. if (!ERR_DNS_IS_OK(err))
  376. goto error;
  377. }
  378. *preq = req;
  379. return ERROR_DNS_SUCCESS;
  380. error:
  381. TALLOC_FREE(req);
  382. return err;
  383. }