dns.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #ifndef __PJLIB_UTIL_DNS_H__
  20. #define __PJLIB_UTIL_DNS_H__
  21. /**
  22. * @file dns.h
  23. * @brief Low level DNS message parsing and packetization.
  24. */
  25. #include <pjlib-util/types.h>
  26. #include <pj/sock.h>
  27. PJ_BEGIN_DECL
  28. /**
  29. * @defgroup PJ_DNS DNS and Asynchronous DNS Resolver
  30. * @ingroup PJ_PROTOCOLS
  31. */
  32. /**
  33. * @defgroup PJ_DNS_PARSING Low-level DNS Message Parsing and Packetization
  34. * @ingroup PJ_DNS
  35. * @{
  36. *
  37. * This module provides low-level services to parse and packetize DNS queries
  38. * and responses. The functions support building a DNS query packet and parse
  39. * the data in the DNS response. This implementation conforms to the
  40. * following specifications:
  41. * - RFC 1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
  42. * - RFC 1886: DNS Extensions to support IP version 6
  43. *
  44. * To create a DNS query packet, application should call #pj_dns_make_query()
  45. * function, specifying the desired DNS query type, the name to be resolved,
  46. * and the buffer where the DNS packet will be built into.
  47. *
  48. * When incoming DNS query or response packet arrives, application can use
  49. * #pj_dns_parse_packet() to parse the TCP/UDP payload into parsed DNS packet
  50. * structure.
  51. *
  52. * This module does not provide any networking functionalities to send or
  53. * receive DNS packets. This functionality should be provided by higher layer
  54. * modules such as @ref PJ_DNS_RESOLVER.
  55. */
  56. enum
  57. {
  58. PJ_DNS_CLASS_IN = 1 /**< DNS class IN. */
  59. };
  60. /**
  61. * This enumeration describes standard DNS record types as described by
  62. * RFC 1035, RFC 2782, and others.
  63. */
  64. typedef enum pj_dns_type
  65. {
  66. PJ_DNS_TYPE_A = 1, /**< Host address (A) record. */
  67. PJ_DNS_TYPE_NS = 2, /**< Authoritative name server (NS) */
  68. PJ_DNS_TYPE_MD = 3, /**< Mail destination (MD) record. */
  69. PJ_DNS_TYPE_MF = 4, /**< Mail forwarder (MF) record. */
  70. PJ_DNS_TYPE_CNAME = 5, /**< Canonical name (CNAME) record. */
  71. PJ_DNS_TYPE_SOA = 6, /**< Marks start of zone authority. */
  72. PJ_DNS_TYPE_MB = 7, /**< Mailbox domain name (MB). */
  73. PJ_DNS_TYPE_MG = 8, /**< Mail group member (MG). */
  74. PJ_DNS_TYPE_MR = 9, /**< Mail rename domain name. */
  75. PJ_DNS_TYPE_NULL = 10, /**< NULL RR. */
  76. PJ_DNS_TYPE_WKS = 11, /**< Well known service description */
  77. PJ_DNS_TYPE_PTR = 12, /**< Domain name pointer. */
  78. PJ_DNS_TYPE_HINFO = 13, /**< Host information. */
  79. PJ_DNS_TYPE_MINFO = 14, /**< Mailbox or mail list information. */
  80. PJ_DNS_TYPE_MX = 15, /**< Mail exchange record. */
  81. PJ_DNS_TYPE_TXT = 16, /**< Text string. */
  82. PJ_DNS_TYPE_RP = 17, /**< Responsible person. */
  83. PJ_DNS_TYPE_AFSB = 18, /**< AFS cell database. */
  84. PJ_DNS_TYPE_X25 = 19, /**< X.25 calling address. */
  85. PJ_DNS_TYPE_ISDN = 20, /**< ISDN calling address. */
  86. PJ_DNS_TYPE_RT = 21, /**< Router. */
  87. PJ_DNS_TYPE_NSAP = 22, /**< NSAP address. */
  88. PJ_DNS_TYPE_NSAP_PTR= 23, /**< NSAP reverse address. */
  89. PJ_DNS_TYPE_SIG = 24, /**< Signature. */
  90. PJ_DNS_TYPE_KEY = 25, /**< Key. */
  91. PJ_DNS_TYPE_PX = 26, /**< X.400 mail mapping. */
  92. PJ_DNS_TYPE_GPOS = 27, /**< Geographical position (withdrawn) */
  93. PJ_DNS_TYPE_AAAA = 28, /**< IPv6 address. */
  94. PJ_DNS_TYPE_LOC = 29, /**< Location. */
  95. PJ_DNS_TYPE_NXT = 30, /**< Next valid name in the zone. */
  96. PJ_DNS_TYPE_EID = 31, /**< Endpoint idenfitier. */
  97. PJ_DNS_TYPE_NIMLOC = 32, /**< Nimrod locator. */
  98. PJ_DNS_TYPE_SRV = 33, /**< Server selection (SRV) record. */
  99. PJ_DNS_TYPE_ATMA = 34, /**< DNS ATM address record. */
  100. PJ_DNS_TYPE_NAPTR = 35, /**< DNS Naming authority pointer record. */
  101. PJ_DNS_TYPE_KX = 36, /**< DNS key exchange record. */
  102. PJ_DNS_TYPE_CERT = 37, /**< DNS certificate record. */
  103. PJ_DNS_TYPE_A6 = 38, /**< DNS IPv6 address (experimental) */
  104. PJ_DNS_TYPE_DNAME = 39, /**< DNS non-terminal name redirection rec. */
  105. PJ_DNS_TYPE_OPT = 41, /**< DNS options - contains EDNS metadata. */
  106. PJ_DNS_TYPE_APL = 42, /**< DNS Address Prefix List (APL) record. */
  107. PJ_DNS_TYPE_DS = 43, /**< DNS Delegation Signer (DS) */
  108. PJ_DNS_TYPE_SSHFP = 44, /**< DNS SSH Key Fingerprint */
  109. PJ_DNS_TYPE_IPSECKEY= 45, /**< DNS IPSEC Key. */
  110. PJ_DNS_TYPE_RRSIG = 46, /**< DNS Resource Record signature. */
  111. PJ_DNS_TYPE_NSEC = 47, /**< DNS Next Secure Name. */
  112. PJ_DNS_TYPE_DNSKEY = 48 /**< DNSSEC Key. */
  113. } pj_dns_type;
  114. /**
  115. * Standard DNS header, according to RFC 1035, which will be present in
  116. * both DNS query and DNS response.
  117. *
  118. * Note that all values seen by application would be in
  119. * host by order. The library would convert them to network
  120. * byte order as necessary.
  121. */
  122. typedef struct pj_dns_hdr
  123. {
  124. pj_uint16_t id; /**< Transaction ID. */
  125. pj_uint16_t flags; /**< Flags. */
  126. pj_uint16_t qdcount; /**< Nb. of queries. */
  127. pj_uint16_t anscount; /**< Nb. of res records */
  128. pj_uint16_t nscount; /**< Nb. of NS records. */
  129. pj_uint16_t arcount; /**< Nb. of additional records */
  130. } pj_dns_hdr;
  131. /** Create RCODE flag */
  132. #define PJ_DNS_SET_RCODE(c) ((pj_uint16_t)((c) & 0x0F))
  133. /** Create RA (Recursion Available) bit */
  134. #define PJ_DNS_SET_RA(on) ((pj_uint16_t)((on) << 7))
  135. /** Create RD (Recursion Desired) bit */
  136. #define PJ_DNS_SET_RD(on) ((pj_uint16_t)((on) << 8))
  137. /** Create TC (Truncated) bit */
  138. #define PJ_DNS_SET_TC(on) ((pj_uint16_t)((on) << 9))
  139. /** Create AA (Authoritative Answer) bit */
  140. #define PJ_DNS_SET_AA(on) ((pj_uint16_t)((on) << 10))
  141. /** Create four bits opcode */
  142. #define PJ_DNS_SET_OPCODE(o) ((pj_uint16_t)((o) << 11))
  143. /** Create query/response bit */
  144. #define PJ_DNS_SET_QR(on) ((pj_uint16_t)((on) << 15))
  145. /** Get RCODE value */
  146. #define PJ_DNS_GET_RCODE(val) (((val) & PJ_DNS_SET_RCODE(0x0F)) >> 0)
  147. /** Get RA bit */
  148. #define PJ_DNS_GET_RA(val) (((val) & PJ_DNS_SET_RA(1)) >> 7)
  149. /** Get RD bit */
  150. #define PJ_DNS_GET_RD(val) (((val) & PJ_DNS_SET_RD(1)) >> 8)
  151. /** Get TC bit */
  152. #define PJ_DNS_GET_TC(val) (((val) & PJ_DNS_SET_TC(1)) >> 9)
  153. /** Get AA bit */
  154. #define PJ_DNS_GET_AA(val) (((val) & PJ_DNS_SET_AA(1)) >> 10)
  155. /** Get OPCODE value */
  156. #define PJ_DNS_GET_OPCODE(val) (((val) & PJ_DNS_SET_OPCODE(0x0F)) >> 11)
  157. /** Get QR bit */
  158. #define PJ_DNS_GET_QR(val) (((val) & PJ_DNS_SET_QR(1)) >> 15)
  159. /**
  160. * These constants describe DNS RCODEs. Application can fold these constants
  161. * into PJLIB pj_status_t namespace by calling #PJ_STATUS_FROM_DNS_RCODE()
  162. * macro.
  163. */
  164. typedef enum pj_dns_rcode
  165. {
  166. PJ_DNS_RCODE_FORMERR = 1, /**< Format error. */
  167. PJ_DNS_RCODE_SERVFAIL = 2, /**< Server failure. */
  168. PJ_DNS_RCODE_NXDOMAIN = 3, /**< Name Error. */
  169. PJ_DNS_RCODE_NOTIMPL = 4, /**< Not Implemented. */
  170. PJ_DNS_RCODE_REFUSED = 5, /**< Refused. */
  171. PJ_DNS_RCODE_YXDOMAIN = 6, /**< The name exists. */
  172. PJ_DNS_RCODE_YXRRSET = 7, /**< The RRset (name, type) exists. */
  173. PJ_DNS_RCODE_NXRRSET = 8, /**< The RRset (name, type) doesn't exist*/
  174. PJ_DNS_RCODE_NOTAUTH = 9, /**< Not authorized. */
  175. PJ_DNS_RCODE_NOTZONE = 10 /**< The zone specified is not a zone. */
  176. } pj_dns_rcode;
  177. /**
  178. * This structure describes a DNS query record.
  179. */
  180. typedef struct pj_dns_parsed_query
  181. {
  182. pj_str_t name; /**< The domain in the query. */
  183. pj_uint16_t type; /**< Type of the query (pj_dns_type) */
  184. pj_uint16_t dnsclass; /**< Network class (PJ_DNS_CLASS_IN=1) */
  185. } pj_dns_parsed_query;
  186. /**
  187. * This structure describes a Resource Record parsed from the DNS packet.
  188. * All integral values are in host byte order.
  189. */
  190. typedef struct pj_dns_parsed_rr
  191. {
  192. pj_str_t name; /**< The domain name which this rec pertains. */
  193. pj_uint16_t type; /**< RR type code. */
  194. pj_uint16_t dnsclass; /**< Class of data (PJ_DNS_CLASS_IN=1). */
  195. pj_uint32_t ttl; /**< Time to live. */
  196. pj_uint16_t rdlength; /**< Resource data length. */
  197. void *data; /**< Pointer to the raw resource data, only
  198. when the type is not known. If it is known,
  199. the data will be put in rdata below. */
  200. /** For resource types that are recognized/supported by this library,
  201. * the parsed resource data will be placed in this rdata union.
  202. */
  203. union rdata
  204. {
  205. /** SRV Resource Data (PJ_DNS_TYPE_SRV, 33) */
  206. struct srv {
  207. pj_uint16_t prio; /**< Target priority (lower is higher). */
  208. pj_uint16_t weight; /**< Weight/proportion */
  209. pj_uint16_t port; /**< Port number of the service */
  210. pj_str_t target; /**< Target name. */
  211. } srv; /**< SRV Resource Data (PJ_DNS_TYPE_SRV, 33) */
  212. /** CNAME Resource Data (PJ_DNS_TYPE_CNAME, 5) */
  213. struct cname {
  214. pj_str_t name; /**< Primary canonical name for an alias. */
  215. } cname; /**< CNAME Resource Data (PJ_DNS_TYPE_CNAME, 5) */
  216. /** NS Resource Data (PJ_DNS_TYPE_NS, 2) */
  217. struct ns {
  218. pj_str_t name; /**< Primary name server. */
  219. } ns; /**< NS Resource Data (PJ_DNS_TYPE_NS, 2) */
  220. /** PTR Resource Data (PJ_DNS_TYPE_PTR, 12) */
  221. struct ptr {
  222. pj_str_t name; /**< PTR name. */
  223. } ptr; /**< PTR Resource Data (PJ_DNS_TYPE_PTR, 12) */
  224. /** A Resource Data (PJ_DNS_TYPE_A, 1) */
  225. struct a {
  226. pj_in_addr ip_addr;/**< IPv4 address in network byte order. */
  227. } a; /**< A Resource Data (PJ_DNS_TYPE_A, 1) */
  228. /** AAAA Resource Data (PJ_DNS_TYPE_AAAA, 28) */
  229. struct aaaa {
  230. pj_in6_addr ip_addr;/**< IPv6 address in network byte order. */
  231. } aaaa; /**< AAAA Resource Data (PJ_DNS_TYPE_AAAA, 28) */
  232. } rdata;
  233. } pj_dns_parsed_rr;
  234. /**
  235. * This structure describes the parsed repersentation of the raw DNS packet.
  236. * Note that all integral values in the parsed packet are represented in
  237. * host byte order.
  238. */
  239. typedef struct pj_dns_parsed_packet
  240. {
  241. pj_dns_hdr hdr; /**< Pointer to DNS hdr, in host byte order */
  242. pj_dns_parsed_query *q; /**< Array of DNS queries. */
  243. pj_dns_parsed_rr *ans; /**< Array of DNS RR answer. */
  244. pj_dns_parsed_rr *ns; /**< Array of NS record in the answer. */
  245. pj_dns_parsed_rr *arr; /**< Array of additional RR answer. */
  246. } pj_dns_parsed_packet;
  247. /**
  248. * Option flags to be specified when calling #pj_dns_packet_dup() function.
  249. * These flags can be combined with bitwise OR operation.
  250. */
  251. enum pj_dns_dup_options
  252. {
  253. PJ_DNS_NO_QD = 1, /**< Do not duplicate the query section. */
  254. PJ_DNS_NO_ANS = 2, /**< Do not duplicate the answer section. */
  255. PJ_DNS_NO_NS = 4, /**< Do not duplicate the NS section. */
  256. PJ_DNS_NO_AR = 8 /**< Do not duplicate the additional rec section */
  257. };
  258. /**
  259. * Create DNS query packet to resolve the specified names. This function
  260. * can be used to build any types of DNS query, such as A record or DNS SRV
  261. * record.
  262. *
  263. * Application specifies the type of record and the name to be queried,
  264. * and the function will build the DNS query packet into the buffer
  265. * specified. Once the packet is successfully built, application can send
  266. * the packet via TCP or UDP connection.
  267. *
  268. * @param packet The buffer to put the DNS query packet.
  269. * @param size On input, it specifies the size of the buffer.
  270. * On output, it will be filled with the actual size of
  271. * the DNS query packet.
  272. * @param id DNS query ID to associate DNS response with the
  273. * query.
  274. * @param qtype DNS type of record to be queried (see #pj_dns_type).
  275. * @param name Name to be queried from the DNS server.
  276. *
  277. * @return PJ_SUCCESS on success, or the appropriate error code.
  278. */
  279. PJ_DECL(pj_status_t) pj_dns_make_query(void *packet,
  280. unsigned *size,
  281. pj_uint16_t id,
  282. int qtype,
  283. const pj_str_t *name);
  284. /**
  285. * Parse raw DNS packet into parsed DNS packet structure. This function is
  286. * able to parse few DNS resource records such as A record, PTR record,
  287. * CNAME record, NS record, and SRV record.
  288. *
  289. * @param pool Pool to allocate memory for the parsed packet.
  290. * @param packet Pointer to the DNS packet (the TCP/UDP payload of
  291. * the raw packet).
  292. * @param size The size of the DNS packet.
  293. * @param p_res Pointer to store the resulting parsed packet.
  294. *
  295. * @return PJ_SUCCESS on success, or the appropriate error code.
  296. */
  297. PJ_DECL(pj_status_t) pj_dns_parse_packet(pj_pool_t *pool,
  298. const void *packet,
  299. unsigned size,
  300. pj_dns_parsed_packet **p_res);
  301. /**
  302. * Duplicate DNS packet.
  303. *
  304. * @param pool The pool to allocate memory for the duplicated packet.
  305. * @param p The DNS packet to be cloned.
  306. * @param options Option flags, from pj_dns_dup_options.
  307. * @param p_dst Pointer to store the cloned DNS packet.
  308. */
  309. PJ_DECL(void) pj_dns_packet_dup(pj_pool_t *pool,
  310. const pj_dns_parsed_packet*p,
  311. unsigned options,
  312. pj_dns_parsed_packet **p_dst);
  313. /**
  314. * Utility function to get the type name string of the specified DNS type.
  315. *
  316. * @param type DNS type (see #pj_dns_type).
  317. *
  318. * @return String name of the type (e.g. "A", "SRV", etc.).
  319. */
  320. PJ_DECL(const char *) pj_dns_get_type_name(int type);
  321. /**
  322. * Initialize DNS record as DNS SRV record.
  323. *
  324. * @param rec The DNS resource record to be initialized as DNS
  325. * SRV record.
  326. * @param res_name Resource name.
  327. * @param dnsclass DNS class.
  328. * @param ttl Resource TTL value.
  329. * @param prio DNS SRV priority.
  330. * @param weight DNS SRV weight.
  331. * @param port Target port.
  332. * @param target Target name.
  333. */
  334. PJ_DECL(void) pj_dns_init_srv_rr(pj_dns_parsed_rr *rec,
  335. const pj_str_t *res_name,
  336. unsigned dnsclass,
  337. unsigned ttl,
  338. unsigned prio,
  339. unsigned weight,
  340. unsigned port,
  341. const pj_str_t *target);
  342. /**
  343. * Initialize DNS record as DNS CNAME record.
  344. *
  345. * @param rec The DNS resource record to be initialized as DNS
  346. * CNAME record.
  347. * @param res_name Resource name.
  348. * @param dnsclass DNS class.
  349. * @param ttl Resource TTL value.
  350. * @param name Host name.
  351. */
  352. PJ_DECL(void) pj_dns_init_cname_rr(pj_dns_parsed_rr *rec,
  353. const pj_str_t *res_name,
  354. unsigned dnsclass,
  355. unsigned ttl,
  356. const pj_str_t *name);
  357. /**
  358. * Initialize DNS record as DNS A record.
  359. *
  360. * @param rec The DNS resource record to be initialized as DNS
  361. * A record.
  362. * @param res_name Resource name.
  363. * @param dnsclass DNS class.
  364. * @param ttl Resource TTL value.
  365. * @param ip_addr Host address.
  366. */
  367. PJ_DECL(void) pj_dns_init_a_rr(pj_dns_parsed_rr *rec,
  368. const pj_str_t *res_name,
  369. unsigned dnsclass,
  370. unsigned ttl,
  371. const pj_in_addr *ip_addr);
  372. /**
  373. * Initialize DNS record as DNS AAAA record.
  374. *
  375. * @param rec The DNS resource record to be initialized as DNS
  376. * AAAA record.
  377. * @param res_name Resource name.
  378. * @param dnsclass DNS class.
  379. * @param ttl Resource TTL value.
  380. * @param ip_addr Host address.
  381. */
  382. PJ_DECL(void) pj_dns_init_aaaa_rr(pj_dns_parsed_rr *rec,
  383. const pj_str_t *res_name,
  384. unsigned dnsclass,
  385. unsigned ttl,
  386. const pj_in6_addr *ip_addr);
  387. /**
  388. * Dump DNS packet to standard log.
  389. *
  390. * @param res The DNS packet.
  391. */
  392. PJ_DECL(void) pj_dns_dump_packet(const pj_dns_parsed_packet *res);
  393. /**
  394. * @}
  395. */
  396. PJ_END_DECL
  397. #endif /* __PJLIB_UTIL_DNS_H__ */