host2wire.c
Go to the documentation of this file.
1 /*
2  * host2wire.c
3  *
4  * conversion routines from the host to the wire format.
5  * This will usually just a re-ordering of the
6  * data (as we store it in network format)
7  *
8  * a Net::DNS like library for C
9  *
10  * (c) NLnet Labs, 2004-2006
11  *
12  * See the file LICENSE for the license
13  */
14 
15 #include <ldns/config.h>
16 
17 #include <ldns/ldns.h>
18 
19 /* TODO Jelte
20  add a pointer to a 'possiblecompression' structure
21  to all the needed functions?
22  something like an array of name, pointer values?
23  every dname part could be added to it
24 */
25 
28 {
29  if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
30  ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
31  }
32  return ldns_buffer_status(buffer);
33 }
34 
37 {
38  if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
39  ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
40  }
41  return ldns_buffer_status(buffer);
42 }
43 
46 {
47  size_t i;
48  uint8_t *rdf_data;
49 
51  if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
52  rdf_data = ldns_rdf_data(rdf);
53  for (i = 0; i < ldns_rdf_size(rdf); i++) {
54  ldns_buffer_write_u8(buffer,
55  (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
56  }
57  }
58  } else {
59  /* direct copy for all other types */
60  if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
61  ldns_buffer_write(buffer,
62  ldns_rdf_data(rdf),
63  ldns_rdf_size(rdf));
64  }
65  }
66  return ldns_buffer_status(buffer);
67 }
68 
69 /* convert a rr list to wireformat */
72 {
73  uint16_t rr_count;
74  uint16_t i;
75 
76  rr_count = ldns_rr_list_rr_count(rr_list);
77  for(i = 0; i < rr_count; i++) {
78  (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i),
80  }
81  return ldns_buffer_status(buffer);
82 }
83 
84 
87  const ldns_rr *rr,
88  int section)
89 {
90  uint16_t i;
91  uint16_t rdl_pos = 0;
92  bool pre_rfc3597 = false;
93  switch (ldns_rr_get_type(rr)) {
94  case LDNS_RR_TYPE_NS:
95  case LDNS_RR_TYPE_MD:
96  case LDNS_RR_TYPE_MF:
97  case LDNS_RR_TYPE_CNAME:
98  case LDNS_RR_TYPE_SOA:
99  case LDNS_RR_TYPE_MB:
100  case LDNS_RR_TYPE_MG:
101  case LDNS_RR_TYPE_MR:
102  case LDNS_RR_TYPE_PTR:
103  case LDNS_RR_TYPE_HINFO:
104  case LDNS_RR_TYPE_MINFO:
105  case LDNS_RR_TYPE_MX:
106  case LDNS_RR_TYPE_RP:
107  case LDNS_RR_TYPE_AFSDB:
108  case LDNS_RR_TYPE_RT:
109  case LDNS_RR_TYPE_SIG:
110  case LDNS_RR_TYPE_PX:
111  case LDNS_RR_TYPE_NXT:
112  case LDNS_RR_TYPE_NAPTR:
113  case LDNS_RR_TYPE_KX:
114  case LDNS_RR_TYPE_SRV:
115  case LDNS_RR_TYPE_DNAME:
116  case LDNS_RR_TYPE_A6:
117  case LDNS_RR_TYPE_RRSIG:
118  pre_rfc3597 = true;
119  break;
120  default:
121  break;
122  }
123 
124  if (ldns_rr_owner(rr)) {
125  (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
126  }
127 
128  if (ldns_buffer_reserve(buffer, 4)) {
129  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
130  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
131  }
132 
133  if (section != LDNS_SECTION_QUESTION) {
134  if (ldns_buffer_reserve(buffer, 6)) {
135  ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
136  /* remember pos for later */
137  rdl_pos = ldns_buffer_position(buffer);
138  ldns_buffer_write_u16(buffer, 0);
139  }
140  for (i = 0; i < ldns_rr_rd_count(rr); i++) {
141  if (pre_rfc3597) {
143  buffer, ldns_rr_rdf(rr, i));
144  } else {
145  (void) ldns_rdf2buffer_wire(
146  buffer, ldns_rr_rdf(rr, i));
147  }
148  }
149  if (rdl_pos != 0) {
150  ldns_buffer_write_u16_at(buffer, rdl_pos,
151  ldns_buffer_position(buffer)
152  - rdl_pos - 2);
153  }
154  }
155  return ldns_buffer_status(buffer);
156 }
157 
159 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
160 {
161  uint16_t i;
162  uint16_t rdl_pos = 0;
163 
164  if (ldns_rr_owner(rr)) {
165  (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
166  }
167 
168  if (ldns_buffer_reserve(buffer, 4)) {
169  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
170  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
171  }
172 
173  if (section != LDNS_SECTION_QUESTION) {
174  if (ldns_buffer_reserve(buffer, 6)) {
175  ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
176  /* remember pos for later */
177  rdl_pos = ldns_buffer_position(buffer);
178  ldns_buffer_write_u16(buffer, 0);
179  }
180  for (i = 0; i < ldns_rr_rd_count(rr); i++) {
181  (void) ldns_rdf2buffer_wire(
182  buffer, ldns_rr_rdf(rr, i));
183  }
184  if (rdl_pos != 0) {
185  ldns_buffer_write_u16_at(buffer, rdl_pos,
186  ldns_buffer_position(buffer)
187  - rdl_pos - 2);
188  }
189  }
190  return ldns_buffer_status(buffer);
191 }
192 
195 {
196  uint16_t i;
197 
198  /* it must be a sig RR */
200  return LDNS_STATUS_ERR;
201  }
202 
203  /* Convert all the rdfs, except the actual signature data
204  * rdf number 8 - the last, hence: -1 */
205  for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
206  (void) ldns_rdf2buffer_wire_canonical(buffer,
207  ldns_rr_rdf(rr, i));
208  }
209 
210  return ldns_buffer_status(buffer);
211 }
212 
215 {
216  uint16_t i;
217  /* convert all the rdf's */
218  for (i = 0; i < ldns_rr_rd_count(rr); i++) {
219  (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
220  }
221  return ldns_buffer_status(buffer);
222 }
223 
224 /*
225  * Copies the packet header data to the buffer in wire format
226  */
227 static ldns_status
228 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
229 {
230  uint8_t flags;
231  uint16_t arcount;
232 
233  if (ldns_buffer_reserve(buffer, 12)) {
234  ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
235 
236  flags = ldns_pkt_qr(packet) << 7
237  | ldns_pkt_get_opcode(packet) << 3
238  | ldns_pkt_aa(packet) << 2
239  | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
240  ldns_buffer_write_u8(buffer, flags);
241 
242  flags = ldns_pkt_ra(packet) << 7
243  /*| ldns_pkt_z(packet) << 6*/
244  | ldns_pkt_ad(packet) << 5
245  | ldns_pkt_cd(packet) << 4
246  | ldns_pkt_get_rcode(packet);
247  ldns_buffer_write_u8(buffer, flags);
248 
249  ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
250  ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
251  ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
252  /* add EDNS0 and TSIG to additional if they are there */
253  arcount = ldns_pkt_arcount(packet);
254  if (ldns_pkt_tsig(packet)) {
255  arcount++;
256  }
257  if (ldns_pkt_edns(packet)) {
258  arcount++;
259  }
260  ldns_buffer_write_u16(buffer, arcount);
261  }
262 
263  return ldns_buffer_status(buffer);
264 }
265 
268 {
269  ldns_rr_list *rr_list;
270  uint16_t i;
271 
272  /* edns tmp vars */
273  ldns_rr *edns_rr;
274  uint8_t edata[4];
275 
276  (void) ldns_hdr2buffer_wire(buffer, packet);
277 
278  rr_list = ldns_pkt_question(packet);
279  if (rr_list) {
280  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
281  (void) ldns_rr2buffer_wire(buffer,
283  }
284  }
285  rr_list = ldns_pkt_answer(packet);
286  if (rr_list) {
287  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
288  (void) ldns_rr2buffer_wire(buffer,
289  ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
290  }
291  }
292  rr_list = ldns_pkt_authority(packet);
293  if (rr_list) {
294  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
295  (void) ldns_rr2buffer_wire(buffer,
297  }
298  }
299  rr_list = ldns_pkt_additional(packet);
300  if (rr_list) {
301  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
302  (void) ldns_rr2buffer_wire(buffer,
304  }
305  }
306 
307  /* add EDNS to additional if it is needed */
308  if (ldns_pkt_edns(packet)) {
309  edns_rr = ldns_rr_new();
310  if(!edns_rr) return LDNS_STATUS_MEM_ERR;
311  ldns_rr_set_owner(edns_rr,
314  ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
315  edata[0] = ldns_pkt_edns_extended_rcode(packet);
316  edata[1] = ldns_pkt_edns_version(packet);
317  ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
318  ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
319  /* don't forget to add the edns rdata (if any) */
320  if (packet->_edns_data)
321  ldns_rr_push_rdf (edns_rr, packet->_edns_data);
322  (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
323  /* take the edns rdata back out of the rr before we free rr */
324  if (packet->_edns_data)
325  (void)ldns_rr_pop_rdf (edns_rr);
326  ldns_rr_free(edns_rr);
327  }
328 
329  /* add TSIG to additional if it is there */
330  if (ldns_pkt_tsig(packet)) {
331  (void) ldns_rr2buffer_wire(buffer,
333  }
334 
335  return LDNS_STATUS_OK;
336 }
337 
339 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
340 {
342  ldns_status status;
343  *result_size = 0;
344  *dest = NULL;
345  if(!buffer) return LDNS_STATUS_MEM_ERR;
346 
347  status = ldns_rdf2buffer_wire(buffer, rdf);
348  if (status == LDNS_STATUS_OK) {
349  *result_size = ldns_buffer_position(buffer);
350  *dest = (uint8_t *) ldns_buffer_export(buffer);
351  }
352  ldns_buffer_free(buffer);
353  return status;
354 }
355 
357 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
358 {
360  ldns_status status;
361  *result_size = 0;
362  *dest = NULL;
363  if(!buffer) return LDNS_STATUS_MEM_ERR;
364 
365  status = ldns_rr2buffer_wire(buffer, rr, section);
366  if (status == LDNS_STATUS_OK) {
367  *result_size = ldns_buffer_position(buffer);
368  *dest = (uint8_t *) ldns_buffer_export(buffer);
369  }
370  ldns_buffer_free(buffer);
371  return status;
372 }
373 
375 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
376 {
378  ldns_status status;
379  *result_size = 0;
380  *dest = NULL;
381  if(!buffer) return LDNS_STATUS_MEM_ERR;
382 
383  status = ldns_pkt2buffer_wire(buffer, packet);
384  if (status == LDNS_STATUS_OK) {
385  *result_size = ldns_buffer_position(buffer);
386  *dest = (uint8_t *) ldns_buffer_export(buffer);
387  }
388  ldns_buffer_free(buffer);
389  return status;
390 }
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
Definition: rr.c:873
implementation of buffers to ease operations
Definition: buffer.h:50
mailbox or mail list information
Definition: rr.h:109
RFC1183.
Definition: rr.h:123
uint16_t ldns_pkt_arcount(const ldns_pkt *packet)
Return the packet's ar count.
Definition: packet.c:117
ldns_rdf * _edns_data
Arbitrary EDNS rdata.
Definition: packet.h:257
void * ldns_buffer_export(ldns_buffer *buffer)
Makes the buffer fixed and returns a pointer to the data.
Definition: buffer.c:150
2535typecode
Definition: rr.h:141
void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type)
sets the type in the rr.
Definition: rr.c:792
RFC1183.
Definition: rr.h:117
the canonical name for an alias
Definition: rr.h:91
DNSSEC.
Definition: rr.h:173
ldns_rr_list * ldns_pkt_question(const ldns_pkt *packet)
Return the packet's question section.
Definition: packet.c:123
Pseudo OPT record...
Definition: rr.h:163
ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
Allocates an array of uint8_t at dest, and puts the wireformat of the given packet in that array...
Definition: host2wire.c:375
List or Set of Resource Records.
Definition: rr.h:327
bool ldns_pkt_tc(const ldns_pkt *packet)
Read the packet's tc bit.
Definition: packet.c:57
ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *packet)
Return the packet's respons code.
Definition: packet.c:93
RFC2163.
Definition: rr.h:133
uint16_t ldns_pkt_qdcount(const ldns_pkt *packet)
Return the packet's qd count.
Definition: packet.c:99
uint8_t ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
return the packet's edns extended rcode
Definition: packet.c:212
ldns_status ldns_rr_list2buffer_wire(ldns_buffer *buffer, const ldns_rr_list *rr_list)
Copies the rr_list data to the buffer in wire format.
Definition: host2wire.c:71
uint16_t ldns_pkt_id(const ldns_pkt *packet)
Read the packet id.
Definition: packet.c:39
RFC2230.
Definition: rr.h:153
bool ldns_pkt_edns(const ldns_pkt *pkt)
returns true if this packet needs and EDNS rr to be sent.
Definition: packet.c:720
size_t ldns_rdf_size(const ldns_rdf *rd)
returns the size of the rdf.
Definition: rdata.c:24
ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *packet)
Read the packet's code.
Definition: packet.c:87
bool ldns_pkt_aa(const ldns_pkt *packet)
Read the packet's aa bit.
Definition: packet.c:51
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition: buffer.c:137
size_t ldns_rr_rd_count(const ldns_rr *rr)
returns the rd_count of an rr structure.
Definition: rr.c:901
#define LDNS_MAX_PACKETLEN
Definition: packet.h:24
void ldns_rr_free(ldns_rr *rr)
frees an RR structure
Definition: rr.c:75
Resource Record.
Definition: rr.h:299
ldns_status ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
Copies the rdata data to the buffer in wire format.
Definition: host2wire.c:36
a mailbox domain name (EXPERIMENTAL)
Definition: rr.h:95
Including this file will include all ldns files, and define some lookup tables.
marks the start of a zone of authority
Definition: rr.h:93
uint16_t ldns_pkt_nscount(const ldns_pkt *packet)
Return the packet's ns count.
Definition: packet.c:111
uint8_t * ldns_rdf_data(const ldns_rdf *rd)
returns the data of the rdf.
Definition: rdata.c:38
ldns_rr * ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
returns a specific rr of an rrlist.
Definition: rr.c:954
void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class)
sets the class in the rr.
Definition: rr.c:798
ldns_status ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
Copies the packet data to the buffer in wire format.
Definition: host2wire.c:267
bogus section, if not interested
Definition: packet.h:278
uint16_t ldns_pkt_ancount(const ldns_pkt *packet)
Return the packet's an count.
Definition: packet.c:105
bool ldns_pkt_cd(const ldns_pkt *packet)
Read the packet's cd bit.
Definition: packet.c:69
bool ldns_pkt_ra(const ldns_pkt *packet)
Read the packet's ra bit.
Definition: packet.c:75
ldns_rdf * ldns_rr_pop_rdf(ldns_rr *rr)
removes a rd_field member, it will be popped from the last position.
Definition: rr.c:844
ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rr *rr, int section)
Copies the rr data to the buffer in wire format, in canonical format according to RFC3597 (every dnam...
Definition: host2wire.c:86
ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
Copies the dname data to the buffer in wire format.
Definition: host2wire.c:27
ldns_rdf * ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
creates a new rdf from a string.
Definition: rdata.c:249
ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
Converts an rr's rdata to wireformat, while excluding the ownername and all the stuff before the rdat...
Definition: host2wire.c:214
ldns_status ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
Copies the rr data to the buffer in wire format.
Definition: host2wire.c:159
bool ldns_pkt_rd(const ldns_pkt *packet)
Read the packet's rd bit.
Definition: packet.c:63
uint8_t ldns_pkt_edns_version(const ldns_pkt *packet)
return the packet's edns version
Definition: packet.c:218
ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
Allocates an array of uint8_t at dest, and puts the wireformat of the given rdf in that array...
Definition: host2wire.c:339
ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd)
returns the type of the rdf.
Definition: rdata.c:31
DNS packet.
Definition: packet.h:233
a domain name pointer
Definition: rr.h:105
void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner)
sets the owner in the rr structure.
Definition: rr.c:768
RFC2874.
Definition: rr.h:157
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition: rr.c:907
a mail group member (EXPERIMENTAL)
Definition: rr.h:97
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
Definition: rr.c:780
enum ldns_enum_status ldns_status
Definition: error.h:131
ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
Allocates an array of uint8_t at dest, and puts the wireformat of the given rr in that array...
Definition: host2wire.c:357
a mail destination (Obsolete - use MX)
Definition: rr.h:87
2535typecode
Definition: rr.h:129
ldns_buffer * ldns_buffer_new(size_t capacity)
creates a new buffer with the specified capacity.
Definition: buffer.c:16
bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
ensures BUFFER can contain at least AMOUNT more bytes.
Definition: buffer.c:79
uint16_t ldns_pkt_edns_udp_size(const ldns_pkt *packet)
return the packet's edns udp size
Definition: packet.c:206
SRV record RFC2782.
Definition: rr.h:147
host information
Definition: rr.h:107
bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f)
sets rd_field member, it will be placed in the next available spot.
Definition: rr.c:821
a mail rename domain name (EXPERIMENTAL)
Definition: rr.h:99
RFC2915.
Definition: rr.h:151
bool ldns_pkt_qr(const ldns_pkt *packet)
Read the packet's qr bit.
Definition: packet.c:45
Resource record data field.
Definition: rdata.h:166
ldns_rr * ldns_pkt_tsig(const ldns_pkt *pkt)
Return the packet's tsig pseudo rr's.
Definition: packet.c:444
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition: rr.c:883
ldns_rr * ldns_rr_new(void)
creates a new rr structure.
Definition: rr.c:24
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr's in an rr_list.
Definition: rr.c:921
bool ldns_pkt_ad(const ldns_pkt *packet)
Read the packet's ad bit.
Definition: packet.c:81
ldns_rr_list * ldns_pkt_authority(const ldns_pkt *packet)
Return the packet's authority section.
Definition: packet.c:135
an authoritative name server
Definition: rr.h:85
ldns_status ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata This is needed in DNSSEC verification...
Definition: host2wire.c:194
uint32_t ldns_rr_ttl(const ldns_rr *rr)
returns the ttl of an rr structure.
Definition: rr.c:895
ldns_rr_class ldns_rr_get_class(const ldns_rr *rr)
returns the class of the rr.
Definition: rr.c:913
domain name
Definition: rdata.h:50
ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
Copies the rdata data to the buffer in wire format If the rdata is a dname, the letters will be lower...
Definition: host2wire.c:45
mail exchange
Definition: rr.h:111
ldns_rr_list * ldns_pkt_additional(const ldns_pkt *packet)
Return the packet's additional section.
Definition: packet.c:141
ldns_rr_list * ldns_pkt_answer(const ldns_pkt *packet)
Return the packet's answer section.
Definition: packet.c:129
uint16_t ldns_pkt_edns_z(const ldns_pkt *packet)
return the packet's edns z value
Definition: packet.c:224
RFC1183.
Definition: rr.h:115
#define LDNS_DNAME_NORMALIZE
Definition: dname.h:49
RFC2672.
Definition: rr.h:159
a mail forwarder (Obsolete - use MX)
Definition: rr.h:89