1 /** 2 * @file dns/hdr.c DNS header encoding 3 * 4 * Copyright (C) 2010 Creytiv.com 5 */ 6 #include <re_types.h> 7 #include <re_fmt.h> 8 #include <re_list.h> 9 #include <re_mbuf.h> 10 #include <re_net.h> 11 #include <re_dns.h> 12 13 14 enum { 15 QUERY_RESPONSE = 15, 16 OPCODE = 11, 17 AUTH_ANSWER = 10, 18 TRUNCATED = 9, 19 RECURSION_DESIRED = 8, 20 RECURSION_AVAILABLE = 7, 21 ZERO = 4 22 }; 23 24 25 /** 26 * Encode a DNS header 27 * 28 * @param mb Memory buffer to encode header into 29 * @param hdr DNS header 30 * 31 * @return 0 if success, otherwise errorcode 32 */ 33 int dns_hdr_encode(struct mbuf *mb, const struct dnshdr *hdr) 34 { 35 uint16_t flags = 0; 36 int err = 0; 37 38 if (!mb || !hdr) 39 return EINVAL; 40 41 flags |= hdr->qr <<QUERY_RESPONSE; 42 flags |= hdr->opcode <<OPCODE; 43 flags |= hdr->aa <<AUTH_ANSWER; 44 flags |= hdr->tc <<TRUNCATED; 45 flags |= hdr->rd <<RECURSION_DESIRED; 46 flags |= hdr->ra <<RECURSION_AVAILABLE; 47 flags |= hdr->z <<ZERO; 48 flags |= hdr->rcode; 49 50 err |= mbuf_write_u16(mb, htons(hdr->id)); 51 err |= mbuf_write_u16(mb, htons(flags)); 52 err |= mbuf_write_u16(mb, htons(hdr->nq)); 53 err |= mbuf_write_u16(mb, htons(hdr->nans)); 54 err |= mbuf_write_u16(mb, htons(hdr->nauth)); 55 err |= mbuf_write_u16(mb, htons(hdr->nadd)); 56 57 return err; 58 } 59 60 61 /** 62 * Decode a DNS header from a memory buffer 63 * 64 * @param mb Memory buffer to decode header from 65 * @param hdr DNS header (output) 66 * 67 * @return 0 if success, otherwise errorcode 68 */ 69 int dns_hdr_decode(struct mbuf *mb, struct dnshdr *hdr) 70 { 71 uint16_t flags = 0; 72 73 if (!mb || !hdr || (mbuf_get_left(mb) < DNS_HEADER_SIZE)) 74 return EINVAL; 75 76 hdr->id = ntohs(mbuf_read_u16(mb)); 77 flags = ntohs(mbuf_read_u16(mb)); 78 79 hdr->qr = 0x1 & (flags >> QUERY_RESPONSE); 80 hdr->opcode = 0xf & (flags >> OPCODE); 81 hdr->aa = 0x1 & (flags >> AUTH_ANSWER); 82 hdr->tc = 0x1 & (flags >> TRUNCATED); 83 hdr->rd = 0x1 & (flags >> RECURSION_DESIRED); 84 hdr->ra = 0x1 & (flags >> RECURSION_AVAILABLE); 85 hdr->z = 0x7 & (flags >> ZERO); 86 hdr->rcode = 0xf & (flags >> 0); 87 88 hdr->nq = ntohs(mbuf_read_u16(mb)); 89 hdr->nans = ntohs(mbuf_read_u16(mb)); 90 hdr->nauth = ntohs(mbuf_read_u16(mb)); 91 hdr->nadd = ntohs(mbuf_read_u16(mb)); 92 93 return 0; 94 } 95 96 97 /** 98 * Get the string of a DNS opcode 99 * 100 * @param opcode DNS opcode 101 * 102 * @return Opcode string 103 */ 104 const char *dns_hdr_opcodename(uint8_t opcode) 105 { 106 switch (opcode) { 107 108 case DNS_OPCODE_QUERY: return "QUERY"; 109 case DNS_OPCODE_IQUERY: return "IQUERY"; 110 case DNS_OPCODE_STATUS: return "STATUS"; 111 case DNS_OPCODE_NOTIFY: return "NOTIFY"; 112 default: return "??"; 113 } 114 } 115 116 117 /** 118 * Get the string of a DNS response code 119 * 120 * @param rcode Response code 121 * 122 * @return Response code string 123 */ 124 const char *dns_hdr_rcodename(uint8_t rcode) 125 { 126 switch (rcode) { 127 128 case DNS_RCODE_OK: return "OK"; 129 case DNS_RCODE_FMT_ERR: return "Format Error"; 130 case DNS_RCODE_SRV_FAIL: return "Server Failure"; 131 case DNS_RCODE_NAME_ERR: return "Name Error"; 132 case DNS_RCODE_NOT_IMPL: return "Not Implemented"; 133 case DNS_RCODE_REFUSED: return "Refused"; 134 case DNS_RCODE_NOT_AUTH: return "Server Not Authoritative for zone"; 135 default: return "??"; 136 } 137 } 138