PageRenderTime 140ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/unix/lwres.c

http://tclsysdns.googlecode.com/
C | 281 lines | 226 code | 32 blank | 23 comment | 16 complexity | 67b34992f1f759d160577017f09e006b MD5 | raw file
  1. /*
  2. * lwres.c --
  3. * DNS resolution using the "lwres" library (http://www.isc.org)
  4. *
  5. * $Id: lwres.c 46 2008-01-06 02:19:40Z khomoutov $
  6. */
  7. #include <tcl.h>
  8. #include <lwres/netdb.h>
  9. #include <errno.h>
  10. #include "tclsysdns.h"
  11. #include "dnsparams.h"
  12. #include "resfmt.h"
  13. #include <stdio.h>
  14. int
  15. Impl_Init (
  16. Tcl_Interp *interp,
  17. ClientData *clientDataPtr
  18. )
  19. {
  20. *clientDataPtr = NULL;
  21. return TCL_OK;
  22. }
  23. void
  24. Impl_Cleanup (
  25. ClientData clientData
  26. )
  27. {
  28. }
  29. int
  30. Impl_GetNameservers (
  31. ClientData clientData,
  32. Tcl_Interp *interp
  33. )
  34. {
  35. Tcl_SetObjResult(interp, Tcl_NewListObj(0, NULL));
  36. return TCL_OK;
  37. }
  38. static void
  39. DNSMsgSetPosixError (
  40. Tcl_Interp *interp,
  41. int errcode
  42. )
  43. {
  44. Tcl_SetErrno(errcode);
  45. Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp), -1));
  46. }
  47. #define DNSMSG_INT16_SIZE (sizeof(unsigned short))
  48. #define DNSMSG_INT32_SIZE (sizeof(unsigned long))
  49. static int
  50. DNSMsgParseAddress (
  51. Tcl_Interp *interp,
  52. struct rdatainfo *rdi,
  53. unsigned long *addrPtr
  54. )
  55. {
  56. if (rdi->rdi_length < DNSMSG_INT32_SIZE) {
  57. DNSMsgSetPosixError(interp, EBADMSG);
  58. return TCL_ERROR;
  59. }
  60. *addrPtr = ((unsigned long *) rdi->rdi_data)[0];
  61. return TCL_OK;
  62. }
  63. static int
  64. DNSParseRRDataA (
  65. Tcl_Interp *interp,
  66. struct rdatainfo *rdi,
  67. const unsigned int resflags,
  68. Tcl_Obj **resObjPtr
  69. )
  70. {
  71. unsigned long addr;
  72. if (DNSMsgParseAddress(interp, rdi, &addr) != TCL_OK) {
  73. return TCL_ERROR;
  74. }
  75. DNSFormatRRDataA(interp, resflags, resObjPtr, addr);
  76. return TCL_OK;
  77. }
  78. static int
  79. DNSParseRRDataUnknown (
  80. Tcl_Interp *interp,
  81. struct rdatainfo *rdi,
  82. const unsigned int resflags,
  83. Tcl_Obj **resObjPtr
  84. )
  85. {
  86. *resObjPtr = Tcl_NewStringObj("UNSUPPORTED", -1);
  87. return TCL_OK;
  88. }
  89. static int
  90. DNSParseRRData (
  91. Tcl_Interp *interp,
  92. const int type,
  93. struct rdatainfo *rdi,
  94. const unsigned int resflags,
  95. Tcl_Obj **resObjPtr
  96. )
  97. {
  98. switch (type) {
  99. case 1: /* A */
  100. return DNSParseRRDataA(interp, rdi, resflags, resObjPtr);
  101. case 6: /* SOA */
  102. /* return DNSMsgParseRRDataSOA(interp, mh, rdlength, resflags, resObjPtr); */
  103. case 2: /* NS */
  104. case 3: /* MD */
  105. case 4: /* MF */
  106. case 5: /* CNAME */
  107. case 7: /* MB */
  108. case 8: /* MG */
  109. case 9: /* MR */
  110. case 12: /* PTR */
  111. /* return DNSMsgParseRRDataPTR(interp, mh, rdlength, resflags, resObjPtr); */
  112. case 14: /* MINFO */
  113. case 17: /* RP */
  114. /* return DNSMsgParseRRDataMINFO(interp, mh, rdlength, resflags, resObjPtr); */
  115. case 15: /* MX */
  116. case 18: /* AFSDB */
  117. case 21: /* RT */
  118. /* return DNSMsgParseRRDataMX(interp, mh, rdlength, resflags, resObjPtr); */
  119. case 13: /* HINFO */
  120. case 16: /* TXT */
  121. case 19: /* X25 */
  122. case 20: /* ISDN */
  123. /* return DNSMsgParseRRDataTXT(interp, mh, rdlength, resflags, resObjPtr); */
  124. case 10: /* NULL */
  125. /* return DNSMsgParseRRDataNULL(interp, mh, rdlength, resflags, resObjPtr); */
  126. case 11: /* WKS */
  127. /* return DNSMsgParseRRDataWKS(interp, mh, rdlength, resflags, resObjPtr); */
  128. case 28: /* AAAA */
  129. /* return DNSMsgParseRRDataAAAA(interp, mh, rdlength, resflags, resObjPtr); */
  130. case 24: /* SIG */
  131. /* return DNSMsgParseRRDataSIG(interp, mh, rdlength, resObjPtr); */
  132. case 25: /* KEY */
  133. /* return DNSMsgParseRRDataKEY(interp, mh, rdlength, resObjPtr); */
  134. case 34: /* ATMA */
  135. /* return DNSMsgParseRRDataATMA(interp, mh, rdlength, resObjPtr); */
  136. case 30: /* NXT (obsolete) */
  137. /* return DNSMsgParseRRDataNXT(interp, mh, rdlength, resObjPtr); */
  138. case 33: /* SRV */
  139. /* return DNSMsgParseRRDataSRV(interp, mh, rdlength, resflags, resObjPtr); */
  140. case 249: /* TKEY */
  141. /* return DNSMsgParseRRDataTKEY(interp, mh, rdlength, resObjPtr); */
  142. case 250: /* TSIG */
  143. /* return DNSMsgParseRRDataTSIG(interp, mh, rdlength, resObjPtr); */
  144. case 0xFF01: /* WINS */
  145. /* return DNSMsgParseRRDataWINS(interp, mh, rdlength, resObjPtr); */
  146. case 0xFF02: /* WINSR, NBSTAT */
  147. /* return DNSMsgParseRRDataWINSR(interp, mh, rdlength, resObjPtr); */
  148. default:
  149. return DNSParseRRDataUnknown(interp, rdi, resflags, resObjPtr);
  150. }
  151. return TCL_OK;
  152. }
  153. static int
  154. DNSParseRRSet (
  155. Tcl_Interp *interp,
  156. struct rrsetinfo *rri,
  157. const unsigned int resflags,
  158. Tcl_Obj *resObj
  159. )
  160. {
  161. int i;
  162. for (i = 0; i < rri->rri_nrdatas; ++i) {
  163. struct rdatainfo *rdi;
  164. Tcl_Obj *dataObj;
  165. rdi = rri->rri_rdatas + i;
  166. if (DNSParseRRData(interp, rri->rri_rdtype,
  167. rdi, resflags, &dataObj) != TCL_OK) {
  168. return TCL_ERROR;
  169. }
  170. if (resflags & RES_DETAIL) {
  171. Tcl_Obj *sectObj = Tcl_NewListObj(0, NULL);
  172. DNSFormatRRHeader(interp, resflags, sectObj,
  173. rri->rri_name,
  174. rri->rri_rdtype,
  175. rri->rri_rdclass,
  176. rri->rri_ttl,
  177. rdi->rdi_length);
  178. Tcl_ListObjAppendElement(interp, sectObj, dataObj);
  179. Tcl_ListObjAppendElement(interp, resObj, sectObj);
  180. } else {
  181. Tcl_ListObjAppendElement(interp, resObj, dataObj);
  182. }
  183. }
  184. return TCL_OK;
  185. }
  186. int
  187. Impl_Resolve (
  188. ClientData clientData,
  189. Tcl_Interp *interp,
  190. Tcl_Obj *queryObj,
  191. const unsigned short qclass,
  192. const unsigned short qtype,
  193. const unsigned int resflags
  194. )
  195. {
  196. struct rrsetinfo *dataPtr;
  197. int res;
  198. Tcl_Obj *answObj;
  199. res = lwres_getrrsetbyname(Tcl_GetString(queryObj), qclass, qtype, 0, &dataPtr);
  200. if (res != 0) {
  201. int error;
  202. const char *errmsg, *posixmsg;
  203. switch (res) {
  204. case ERRSET_NONAME:
  205. case ERRSET_NODATA:
  206. Tcl_ResetResult(interp);
  207. return TCL_OK;
  208. case ERRSET_NOMEMORY:
  209. error = ENOMEM;
  210. errmsg = NULL;
  211. break;
  212. case ERRSET_INVAL:
  213. error = EINVAL;
  214. errmsg = NULL;
  215. break;
  216. case ERRSET_FAIL:
  217. error = ECANCELED;
  218. errmsg = "Unknown failure"
  219. " (probably a configuration problem or resolver is down)";
  220. break;
  221. default:
  222. error = ECANCELED;
  223. errmsg = "Unknown error";
  224. }
  225. Tcl_SetErrno(error);
  226. posixmsg = Tcl_PosixError(interp);
  227. if (errmsg == NULL) {
  228. errmsg = posixmsg;
  229. }
  230. Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, -1));
  231. return TCL_ERROR;
  232. }
  233. answObj = Tcl_NewListObj(0, NULL);
  234. if (DNSParseRRSet(interp, dataPtr, resflags, answObj) != TCL_OK) {
  235. return TCL_ERROR;
  236. }
  237. lwres_freerrset(dataPtr);
  238. Tcl_SetObjResult(interp, answObj);
  239. return TCL_OK;
  240. }
  241. int
  242. Impl_Reinit (
  243. ClientData clientData,
  244. Tcl_Interp *interp,
  245. const int flags
  246. )
  247. {
  248. return TCL_OK;
  249. }