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 
86  const ldns_rr *rr,
87  int section)
88 {
89  uint16_t i;
90  uint16_t rdl_pos = 0;
91  bool pre_rfc3597 = false;
92  switch (ldns_rr_get_type(rr)) {
93  case LDNS_RR_TYPE_NS:
94  case LDNS_RR_TYPE_MD:
95  case LDNS_RR_TYPE_MF:
96  case LDNS_RR_TYPE_CNAME:
97  case LDNS_RR_TYPE_SOA:
98  case LDNS_RR_TYPE_MB:
99  case LDNS_RR_TYPE_MG:
100  case LDNS_RR_TYPE_MR:
101  case LDNS_RR_TYPE_PTR:
102  case LDNS_RR_TYPE_HINFO:
103  case LDNS_RR_TYPE_MINFO:
104  case LDNS_RR_TYPE_MX:
105  case LDNS_RR_TYPE_RP:
106  case LDNS_RR_TYPE_AFSDB:
107  case LDNS_RR_TYPE_RT:
108  case LDNS_RR_TYPE_SIG:
109  case LDNS_RR_TYPE_PX:
110  case LDNS_RR_TYPE_NXT:
111  case LDNS_RR_TYPE_NAPTR:
112  case LDNS_RR_TYPE_KX:
113  case LDNS_RR_TYPE_SRV:
114  case LDNS_RR_TYPE_DNAME:
115  case LDNS_RR_TYPE_A6:
116  case LDNS_RR_TYPE_RRSIG:
117  pre_rfc3597 = true;
118  break;
119  default:
120  break;
121  }
122 
123  if (ldns_rr_owner(rr)) {
124  (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
125  }
126 
127  if (ldns_buffer_reserve(buffer, 4)) {
128  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
129  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
130  }
131 
132  if (section != LDNS_SECTION_QUESTION) {
133  if (ldns_buffer_reserve(buffer, 6)) {
134  ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
135  /* remember pos for later */
136  rdl_pos = ldns_buffer_position(buffer);
137  ldns_buffer_write_u16(buffer, 0);
138  }
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 
150  if (rdl_pos != 0) {
151  ldns_buffer_write_u16_at(buffer, rdl_pos,
152  ldns_buffer_position(buffer)
153  - rdl_pos - 2);
154  }
155  }
156  return ldns_buffer_status(buffer);
157 }
158 
160 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
161 {
162  uint16_t i;
163  uint16_t rdl_pos = 0;
164 
165  if (ldns_rr_owner(rr)) {
166  (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
167  }
168 
169  if (ldns_buffer_reserve(buffer, 4)) {
170  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
171  (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
172  }
173 
174  if (section != LDNS_SECTION_QUESTION) {
175  if (ldns_buffer_reserve(buffer, 6)) {
176  ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
177  /* remember pos for later */
178  rdl_pos = ldns_buffer_position(buffer);
179  ldns_buffer_write_u16(buffer, 0);
180  }
181 
182  for (i = 0; i < ldns_rr_rd_count(rr); i++) {
183  (void) ldns_rdf2buffer_wire(
184  buffer, ldns_rr_rdf(rr, i));
185  }
186 
187  if (rdl_pos != 0) {
188  ldns_buffer_write_u16_at(buffer, rdl_pos,
189  ldns_buffer_position(buffer)
190  - rdl_pos - 2);
191  }
192  }
193  return ldns_buffer_status(buffer);
194 }
195 
198 {
199  uint16_t i;
200 
201  /* it must be a sig RR */
203  return LDNS_STATUS_ERR;
204  }
205 
206  /* Convert all the rdfs, except the actual signature data
207  * rdf number 8 - the last, hence: -1 */
208  for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
209  (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i));
210  }
211 
212  return ldns_buffer_status(buffer);
213 }
214 
217 {
218  uint16_t i;
219  /* convert all the rdf's */
220  for (i = 0; i < ldns_rr_rd_count(rr); i++) {
221  (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
222  }
223 
224  return ldns_buffer_status(buffer);
225 }
226 
227 /*
228  * Copies the packet header data to the buffer in wire format
229  */
230 static ldns_status
231 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
232 {
233  uint8_t flags;
234  uint16_t arcount;
235 
236  if (ldns_buffer_reserve(buffer, 12)) {
237  ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
238 
239  flags = ldns_pkt_qr(packet) << 7
240  | ldns_pkt_get_opcode(packet) << 3
241  | ldns_pkt_aa(packet) << 2
242  | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
243  ldns_buffer_write_u8(buffer, flags);
244 
245  flags = ldns_pkt_ra(packet) << 7
246  /*| ldns_pkt_z(packet) << 6*/
247  | ldns_pkt_ad(packet) << 5
248  | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet);
249  ldns_buffer_write_u8(buffer, flags);
250 
251  ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
252  ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
253  ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
254  /* add EDNS0 and TSIG to additional if they are there */
255  arcount = ldns_pkt_arcount(packet);
256  if (ldns_pkt_tsig(packet)) {
257  arcount++;
258  }
259  if (ldns_pkt_edns(packet)) {
260  arcount++;
261  }
262  ldns_buffer_write_u16(buffer, arcount);
263  }
264 
265  return ldns_buffer_status(buffer);
266 }
267 
270 {
271  ldns_rr_list *rr_list;
272  uint16_t i;
273 
274  /* edns tmp vars */
275  ldns_rr *edns_rr;
276  uint8_t edata[4];
277 
278  (void) ldns_hdr2buffer_wire(buffer, packet);
279 
280  rr_list = ldns_pkt_question(packet);
281  if (rr_list) {
282  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
283  (void) ldns_rr2buffer_wire(buffer,
285  }
286  }
287  rr_list = ldns_pkt_answer(packet);
288  if (rr_list) {
289  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
290  (void) ldns_rr2buffer_wire(buffer,
291  ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
292  }
293  }
294  rr_list = ldns_pkt_authority(packet);
295  if (rr_list) {
296  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
297  (void) ldns_rr2buffer_wire(buffer,
299  }
300  }
301  rr_list = ldns_pkt_additional(packet);
302  if (rr_list) {
303  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
304  (void) ldns_rr2buffer_wire(buffer,
306  }
307  }
308 
309  /* add EDNS to additional if it is needed */
310  if (ldns_pkt_edns(packet)) {
311  edns_rr = ldns_rr_new();
312  if(!edns_rr) return LDNS_STATUS_MEM_ERR;
313  ldns_rr_set_owner(edns_rr,
316  ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
317  edata[0] = ldns_pkt_edns_extended_rcode(packet);
318  edata[1] = ldns_pkt_edns_version(packet);
319  ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
320  ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
321  /* don't forget to add the edns rdata (if any) */
322  if (packet->_edns_data)
323  ldns_rr_push_rdf (edns_rr, packet->_edns_data);
324  (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
325  /* take the edns rdata back out of the rr before we free rr */
326  if (packet->_edns_data)
327  (void)ldns_rr_pop_rdf (edns_rr);
328  ldns_rr_free(edns_rr);
329  }
330 
331  /* add TSIG to additional if it is there */
332  if (ldns_pkt_tsig(packet)) {
333  (void) ldns_rr2buffer_wire(buffer,
335  }
336 
337  return LDNS_STATUS_OK;
338 }
339 
341 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
342 {
344  ldns_status status;
345  *result_size = 0;
346  *dest = NULL;
347  if(!buffer) return LDNS_STATUS_MEM_ERR;
348 
349  status = ldns_rdf2buffer_wire(buffer, rdf);
350  if (status == LDNS_STATUS_OK) {
351  *result_size = ldns_buffer_position(buffer);
352  *dest = (uint8_t *) ldns_buffer_export(buffer);
353  }
354  ldns_buffer_free(buffer);
355  return status;
356 }
357 
359 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
360 {
362  ldns_status status;
363  *result_size = 0;
364  *dest = NULL;
365  if(!buffer) return LDNS_STATUS_MEM_ERR;
366 
367  status = ldns_rr2buffer_wire(buffer, rr, section);
368  if (status == LDNS_STATUS_OK) {
369  *result_size = ldns_buffer_position(buffer);
370  *dest = (uint8_t *) ldns_buffer_export(buffer);
371  }
372  ldns_buffer_free(buffer);
373  return status;
374 }
375 
377 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
378 {
380  ldns_status status;
381  *result_size = 0;
382  *dest = NULL;
383  if(!buffer) return LDNS_STATUS_MEM_ERR;
384 
385  status = ldns_pkt2buffer_wire(buffer, packet);
386  if (status == LDNS_STATUS_OK) {
387  *result_size = ldns_buffer_position(buffer);
388  *dest = (uint8_t *) ldns_buffer_export(buffer);
389  }
390  ldns_buffer_free(buffer);
391  return status;
392 }