host2wire.c
Go to the documentation of this file.
00001 /*
00002  * host2wire.c
00003  *
00004  * conversion routines from the host to the wire format.
00005  * This will usually just a re-ordering of the
00006  * data (as we store it in network format)
00007  *
00008  * a Net::DNS like library for C
00009  *
00010  * (c) NLnet Labs, 2004-2006
00011  *
00012  * See the file LICENSE for the license
00013  */
00014 
00015 #include <ldns/config.h>
00016 
00017 #include <ldns/ldns.h>
00018 
00019 /* TODO Jelte
00020   add a pointer to a 'possiblecompression' structure
00021   to all the needed functions?
00022   something like an array of name, pointer values?
00023   every dname part could be added to it
00024 */
00025 
00026 ldns_status
00027 ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
00028 {
00029         if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
00030                 ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
00031         }
00032         return ldns_buffer_status(buffer);
00033 }
00034 
00035 ldns_status
00036 ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
00037 {
00038         if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
00039                 ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
00040         }
00041         return ldns_buffer_status(buffer);
00042 }
00043 
00044 ldns_status
00045 ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
00046 {
00047         size_t i;
00048         uint8_t *rdf_data;
00049 
00050         if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
00051                 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
00052                         rdf_data = ldns_rdf_data(rdf);
00053                         for (i = 0; i < ldns_rdf_size(rdf); i++) {
00054                                 ldns_buffer_write_u8(buffer,
00055                                     (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
00056                         }
00057                 }
00058         } else {
00059                 /* direct copy for all other types */
00060                 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
00061                         ldns_buffer_write(buffer,
00062                                                    ldns_rdf_data(rdf),
00063                                                    ldns_rdf_size(rdf));
00064                 }
00065         }
00066         return ldns_buffer_status(buffer);
00067 }
00068 
00069 /* convert a rr list to wireformat */
00070 ldns_status
00071 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
00072 {
00073         uint16_t rr_count;
00074         uint16_t i;
00075 
00076         rr_count = ldns_rr_list_rr_count(rr_list);
00077         for(i = 0; i < rr_count; i++) {
00078                 (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 
00079                                           LDNS_SECTION_ANY);
00080         }
00081         return ldns_buffer_status(buffer);
00082 }
00083 
00084 
00085 ldns_status
00086 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
00087                                                 const ldns_rr *rr,
00088                                                 int section)
00089 {
00090         uint16_t i;
00091         uint16_t rdl_pos = 0;
00092         bool pre_rfc3597 = false;
00093         switch (ldns_rr_get_type(rr)) {
00094         case LDNS_RR_TYPE_NS:
00095         case LDNS_RR_TYPE_MD:
00096         case LDNS_RR_TYPE_MF:
00097         case LDNS_RR_TYPE_CNAME:
00098         case LDNS_RR_TYPE_SOA:
00099         case LDNS_RR_TYPE_MB:
00100         case LDNS_RR_TYPE_MG:
00101         case LDNS_RR_TYPE_MR:
00102         case LDNS_RR_TYPE_PTR:
00103         case LDNS_RR_TYPE_HINFO:
00104         case LDNS_RR_TYPE_MINFO:
00105         case LDNS_RR_TYPE_MX:
00106         case LDNS_RR_TYPE_RP:
00107         case LDNS_RR_TYPE_AFSDB:
00108         case LDNS_RR_TYPE_RT:
00109         case LDNS_RR_TYPE_SIG:
00110         case LDNS_RR_TYPE_PX:
00111         case LDNS_RR_TYPE_NXT:
00112         case LDNS_RR_TYPE_NAPTR:
00113         case LDNS_RR_TYPE_KX:
00114         case LDNS_RR_TYPE_SRV:
00115         case LDNS_RR_TYPE_DNAME:
00116         case LDNS_RR_TYPE_A6:
00117         case LDNS_RR_TYPE_RRSIG:
00118                 pre_rfc3597 = true;
00119                 break;
00120         default:
00121                 break;
00122         }
00123         
00124         if (ldns_rr_owner(rr)) {
00125                 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
00126         }
00127         
00128         if (ldns_buffer_reserve(buffer, 4)) {
00129                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
00130                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
00131         }
00132 
00133         if (section != LDNS_SECTION_QUESTION) {
00134                 if (ldns_buffer_reserve(buffer, 6)) {
00135                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
00136                         /* remember pos for later */
00137                         rdl_pos = ldns_buffer_position(buffer);
00138                         ldns_buffer_write_u16(buffer, 0);
00139                 }       
00140                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00141                         if (pre_rfc3597) {
00142                                 (void) ldns_rdf2buffer_wire_canonical(
00143                                         buffer, ldns_rr_rdf(rr, i));
00144                         } else {
00145                                 (void) ldns_rdf2buffer_wire(
00146                                         buffer, ldns_rr_rdf(rr, i));
00147                         }
00148                 }
00149                 if (rdl_pos != 0) {
00150                         ldns_buffer_write_u16_at(buffer, rdl_pos,
00151                                                  ldns_buffer_position(buffer)
00152                                                    - rdl_pos - 2);
00153                 }
00154         }
00155         return ldns_buffer_status(buffer);
00156 }
00157 
00158 ldns_status
00159 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
00160 {
00161         uint16_t i;
00162         uint16_t rdl_pos = 0;
00163         
00164         if (ldns_rr_owner(rr)) {
00165                 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
00166         }
00167         
00168         if (ldns_buffer_reserve(buffer, 4)) {
00169                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
00170                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
00171         }
00172 
00173         if (section != LDNS_SECTION_QUESTION) {
00174                 if (ldns_buffer_reserve(buffer, 6)) {
00175                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
00176                         /* remember pos for later */
00177                         rdl_pos = ldns_buffer_position(buffer);
00178                         ldns_buffer_write_u16(buffer, 0);
00179                 }
00180                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00181                         (void) ldns_rdf2buffer_wire(
00182                                         buffer, ldns_rr_rdf(rr, i));
00183                 }
00184                 if (rdl_pos != 0) {
00185                         ldns_buffer_write_u16_at(buffer, rdl_pos,
00186                                                  ldns_buffer_position(buffer)
00187                                                    - rdl_pos - 2);
00188                 }
00189         }
00190         return ldns_buffer_status(buffer);
00191 }
00192 
00193 ldns_status
00194 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00195 {
00196         uint16_t i;
00197 
00198         /* it must be a sig RR */
00199         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
00200                 return LDNS_STATUS_ERR;
00201         }
00202         
00203         /* Convert all the rdfs, except the actual signature data
00204          * rdf number 8  - the last, hence: -1 */
00205         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
00206                 (void) ldns_rdf2buffer_wire_canonical(buffer, 
00207                                 ldns_rr_rdf(rr, i));
00208         }
00209 
00210         return ldns_buffer_status(buffer);
00211 }
00212 
00213 ldns_status
00214 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00215 {
00216         uint16_t i;
00217         /* convert all the rdf's */
00218         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00219                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
00220         }
00221         return ldns_buffer_status(buffer);
00222 }
00223 
00224 /*
00225  * Copies the packet header data to the buffer in wire format
00226  */
00227 static ldns_status
00228 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00229 {
00230         uint8_t flags;
00231         uint16_t arcount;
00232         
00233         if (ldns_buffer_reserve(buffer, 12)) {
00234                 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
00235                 
00236                 flags = ldns_pkt_qr(packet) << 7
00237                         | ldns_pkt_get_opcode(packet) << 3
00238                         | ldns_pkt_aa(packet) << 2
00239                         | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
00240                 ldns_buffer_write_u8(buffer, flags);
00241                 
00242                 flags = ldns_pkt_ra(packet) << 7
00243                         /*| ldns_pkt_z(packet) << 6*/
00244                         | ldns_pkt_ad(packet) << 5
00245                         | ldns_pkt_cd(packet) << 4
00246                         | ldns_pkt_get_rcode(packet);
00247                 ldns_buffer_write_u8(buffer, flags);
00248                 
00249                 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
00250                 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
00251                 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
00252                 /* add EDNS0 and TSIG to additional if they are there */
00253                 arcount = ldns_pkt_arcount(packet);
00254                 if (ldns_pkt_tsig(packet)) {
00255                         arcount++;
00256                 }
00257                 if (ldns_pkt_edns(packet)) {
00258                         arcount++;
00259                 }
00260                 ldns_buffer_write_u16(buffer, arcount);
00261         }
00262         
00263         return ldns_buffer_status(buffer);
00264 }
00265 
00266 ldns_status
00267 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00268 {
00269         ldns_rr_list *rr_list;
00270         uint16_t i;
00271         
00272         /* edns tmp vars */
00273         ldns_rr *edns_rr;
00274         uint8_t edata[4];
00275         
00276         (void) ldns_hdr2buffer_wire(buffer, packet);
00277 
00278         rr_list = ldns_pkt_question(packet);
00279         if (rr_list) {
00280                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00281                         (void) ldns_rr2buffer_wire(buffer, 
00282                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
00283                 }
00284         }
00285         rr_list = ldns_pkt_answer(packet);
00286         if (rr_list) {
00287                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00288                         (void) ldns_rr2buffer_wire(buffer, 
00289                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
00290                 }
00291         }
00292         rr_list = ldns_pkt_authority(packet);
00293         if (rr_list) {
00294                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00295                         (void) ldns_rr2buffer_wire(buffer, 
00296                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
00297                 }
00298         }
00299         rr_list = ldns_pkt_additional(packet);
00300         if (rr_list) {
00301                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00302                         (void) ldns_rr2buffer_wire(buffer, 
00303                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
00304                 }
00305         }
00306         
00307         /* add EDNS to additional if it is needed */
00308         if (ldns_pkt_edns(packet)) {
00309                 edns_rr = ldns_rr_new();
00310                 if(!edns_rr) return LDNS_STATUS_MEM_ERR;
00311                 ldns_rr_set_owner(edns_rr,
00312                                 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
00313                 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
00314                 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
00315                 edata[0] = ldns_pkt_edns_extended_rcode(packet);
00316                 edata[1] = ldns_pkt_edns_version(packet);
00317                 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
00318                 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
00319                 /* don't forget to add the edns rdata (if any) */
00320                 if (packet->_edns_data)
00321                         ldns_rr_push_rdf (edns_rr, packet->_edns_data);
00322                 (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
00323                 /* take the edns rdata back out of the rr before we free rr */
00324                 if (packet->_edns_data)
00325                         (void)ldns_rr_pop_rdf (edns_rr);
00326                 ldns_rr_free(edns_rr);
00327         }
00328         
00329         /* add TSIG to additional if it is there */
00330         if (ldns_pkt_tsig(packet)) {
00331                 (void) ldns_rr2buffer_wire(buffer,
00332                                            ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
00333         }
00334         
00335         return LDNS_STATUS_OK;
00336 }
00337 
00338 ldns_status
00339 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
00340 {
00341         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00342         ldns_status status;
00343         *result_size = 0;
00344         *dest = NULL;
00345         if(!buffer) return LDNS_STATUS_MEM_ERR;
00346         
00347         status = ldns_rdf2buffer_wire(buffer, rdf);
00348         if (status == LDNS_STATUS_OK) {
00349                 *result_size =  ldns_buffer_position(buffer);
00350                 *dest = (uint8_t *) ldns_buffer_export(buffer);
00351         }
00352         ldns_buffer_free(buffer);
00353         return status;
00354 }
00355 
00356 ldns_status
00357 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
00358 {
00359         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00360         ldns_status status;
00361         *result_size = 0;
00362         *dest = NULL;
00363         if(!buffer) return LDNS_STATUS_MEM_ERR;
00364         
00365         status = ldns_rr2buffer_wire(buffer, rr, section);
00366         if (status == LDNS_STATUS_OK) {
00367                 *result_size =  ldns_buffer_position(buffer);
00368                 *dest = (uint8_t *) ldns_buffer_export(buffer);
00369         }
00370         ldns_buffer_free(buffer);
00371         return status;
00372 }
00373 
00374 ldns_status
00375 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
00376 {
00377         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00378         ldns_status status;
00379         *result_size = 0;
00380         *dest = NULL;
00381         if(!buffer) return LDNS_STATUS_MEM_ERR;
00382         
00383         status = ldns_pkt2buffer_wire(buffer, packet);
00384         if (status == LDNS_STATUS_OK) {
00385                 *result_size =  ldns_buffer_position(buffer);
00386                 *dest = (uint8_t *) ldns_buffer_export(buffer);
00387         }
00388         ldns_buffer_free(buffer);
00389         return status;
00390 }