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 ldns_status
00085 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
00086                                                 const ldns_rr *rr,
00087                                                 int section)
00088 {
00089         uint16_t i;
00090         uint16_t rdl_pos = 0;
00091         bool pre_rfc3597 = false;
00092         switch (ldns_rr_get_type(rr)) {
00093         case LDNS_RR_TYPE_NS:
00094         case LDNS_RR_TYPE_MD:
00095         case LDNS_RR_TYPE_MF:
00096         case LDNS_RR_TYPE_CNAME:
00097         case LDNS_RR_TYPE_SOA:
00098         case LDNS_RR_TYPE_MB:
00099         case LDNS_RR_TYPE_MG:
00100         case LDNS_RR_TYPE_MR:
00101         case LDNS_RR_TYPE_PTR:
00102         case LDNS_RR_TYPE_HINFO:
00103         case LDNS_RR_TYPE_MINFO:
00104         case LDNS_RR_TYPE_MX:
00105         case LDNS_RR_TYPE_RP:
00106         case LDNS_RR_TYPE_AFSDB:
00107         case LDNS_RR_TYPE_RT:
00108         case LDNS_RR_TYPE_SIG:
00109         case LDNS_RR_TYPE_PX:
00110         case LDNS_RR_TYPE_NXT:
00111         case LDNS_RR_TYPE_NAPTR:
00112         case LDNS_RR_TYPE_KX:
00113         case LDNS_RR_TYPE_SRV:
00114         case LDNS_RR_TYPE_DNAME:
00115         case LDNS_RR_TYPE_A6:
00116         case LDNS_RR_TYPE_RRSIG:
00117                 pre_rfc3597 = true;
00118                 break;
00119         default:
00120                 break;
00121         }
00122         
00123         if (ldns_rr_owner(rr)) {
00124                 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
00125         }
00126         
00127         if (ldns_buffer_reserve(buffer, 4)) {
00128                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
00129                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
00130         }
00131 
00132         if (section != LDNS_SECTION_QUESTION) {
00133                 if (ldns_buffer_reserve(buffer, 6)) {
00134                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
00135                         /* remember pos for later */
00136                         rdl_pos = ldns_buffer_position(buffer);
00137                         ldns_buffer_write_u16(buffer, 0);
00138                 }       
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                 
00150                 if (rdl_pos != 0) {
00151                         ldns_buffer_write_u16_at(buffer, rdl_pos,
00152                                                  ldns_buffer_position(buffer)
00153                                                    - rdl_pos - 2);
00154                 }
00155         }
00156         return ldns_buffer_status(buffer);
00157 }
00158 
00159 ldns_status
00160 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
00161 {
00162         uint16_t i;
00163         uint16_t rdl_pos = 0;
00164         
00165         if (ldns_rr_owner(rr)) {
00166                 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
00167         }
00168         
00169         if (ldns_buffer_reserve(buffer, 4)) {
00170                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
00171                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
00172         }
00173 
00174         if (section != LDNS_SECTION_QUESTION) {
00175                 if (ldns_buffer_reserve(buffer, 6)) {
00176                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
00177                         /* remember pos for later */
00178                         rdl_pos = ldns_buffer_position(buffer);
00179                         ldns_buffer_write_u16(buffer, 0);
00180                 }       
00181 
00182                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00183                         (void) ldns_rdf2buffer_wire(
00184                                         buffer, ldns_rr_rdf(rr, i));
00185                 }
00186                 
00187                 if (rdl_pos != 0) {
00188                         ldns_buffer_write_u16_at(buffer, rdl_pos,
00189                                                  ldns_buffer_position(buffer)
00190                                                    - rdl_pos - 2);
00191                 }
00192         }
00193         return ldns_buffer_status(buffer);
00194 }
00195 
00196 ldns_status
00197 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00198 {
00199         uint16_t i;
00200 
00201         /* it must be a sig RR */
00202         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
00203                 return LDNS_STATUS_ERR;
00204         }
00205         
00206         /* Convert all the rdfs, except the actual signature data
00207          * rdf number 8  - the last, hence: -1 */
00208         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
00209                 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i));
00210         }
00211 
00212         return ldns_buffer_status(buffer);
00213 }
00214 
00215 ldns_status
00216 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00217 {
00218         uint16_t i;
00219         /* convert all the rdf's */
00220         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00221                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
00222         }
00223 
00224         return ldns_buffer_status(buffer);
00225 }
00226 
00227 /*
00228  * Copies the packet header data to the buffer in wire format
00229  */
00230 static ldns_status
00231 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00232 {
00233         uint8_t flags;
00234         uint16_t arcount;
00235         
00236         if (ldns_buffer_reserve(buffer, 12)) {
00237                 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
00238                 
00239                 flags = ldns_pkt_qr(packet) << 7
00240                         | ldns_pkt_get_opcode(packet) << 3
00241                         | ldns_pkt_aa(packet) << 2
00242                         | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
00243                 ldns_buffer_write_u8(buffer, flags);
00244                 
00245                 flags = ldns_pkt_ra(packet) << 7
00246                         /*| ldns_pkt_z(packet) << 6*/
00247                         | ldns_pkt_ad(packet) << 5
00248                         | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet);
00249                 ldns_buffer_write_u8(buffer, flags);
00250                 
00251                 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
00252                 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
00253                 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
00254                 /* add EDNS0 and TSIG to additional if they are there */
00255                 arcount = ldns_pkt_arcount(packet);
00256                 if (ldns_pkt_tsig(packet)) {
00257                         arcount++;
00258                 }
00259                 if (ldns_pkt_edns(packet)) {
00260                         arcount++;
00261                 }
00262                 ldns_buffer_write_u16(buffer, arcount);
00263         }
00264         
00265         return ldns_buffer_status(buffer);
00266 }
00267 
00268 ldns_status
00269 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00270 {
00271         ldns_rr_list *rr_list;
00272         uint16_t i;
00273         
00274         /* edns tmp vars */
00275         ldns_rr *edns_rr;
00276         uint8_t edata[4];
00277         
00278         (void) ldns_hdr2buffer_wire(buffer, packet);
00279 
00280         rr_list = ldns_pkt_question(packet);
00281         if (rr_list) {
00282                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00283                         (void) ldns_rr2buffer_wire(buffer, 
00284                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
00285                 }
00286         }
00287         rr_list = ldns_pkt_answer(packet);
00288         if (rr_list) {
00289                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00290                         (void) ldns_rr2buffer_wire(buffer, 
00291                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
00292                 }
00293         }
00294         rr_list = ldns_pkt_authority(packet);
00295         if (rr_list) {
00296                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00297                         (void) ldns_rr2buffer_wire(buffer, 
00298                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
00299                 }
00300         }
00301         rr_list = ldns_pkt_additional(packet);
00302         if (rr_list) {
00303                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00304                         (void) ldns_rr2buffer_wire(buffer, 
00305                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
00306                 }
00307         }
00308         
00309         /* add EDNS to additional if it is needed */
00310         if (ldns_pkt_edns(packet)) {
00311                 edns_rr = ldns_rr_new();
00312                 if(!edns_rr) return LDNS_STATUS_MEM_ERR;
00313                 ldns_rr_set_owner(edns_rr,
00314                                 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
00315                 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
00316                 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
00317                 edata[0] = ldns_pkt_edns_extended_rcode(packet);
00318                 edata[1] = ldns_pkt_edns_version(packet);
00319                 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
00320                 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
00321                 /* don't forget to add the edns rdata (if any) */
00322                 if (packet->_edns_data)
00323                         ldns_rr_push_rdf (edns_rr, packet->_edns_data);
00324                 (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
00325                 /* take the edns rdata back out of the rr before we free rr */
00326                 if (packet->_edns_data)
00327                         (void)ldns_rr_pop_rdf (edns_rr);
00328                 ldns_rr_free(edns_rr);
00329         }
00330         
00331         /* add TSIG to additional if it is there */
00332         if (ldns_pkt_tsig(packet)) {
00333                 (void) ldns_rr2buffer_wire(buffer,
00334                                            ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
00335         }
00336         
00337         return LDNS_STATUS_OK;
00338 }
00339 
00340 ldns_status
00341 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
00342 {
00343         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00344         uint8_t *result = NULL;
00345         ldns_status status;
00346         *result_size = 0;
00347         *dest = NULL;
00348         if(!buffer) return LDNS_STATUS_MEM_ERR;
00349         
00350         status = ldns_rdf2buffer_wire(buffer, rdf);
00351         if (status == LDNS_STATUS_OK) {
00352                 *result_size =  ldns_buffer_position(buffer);
00353                 result = (uint8_t *) ldns_buffer_export(buffer);
00354         } else {
00355                 ldns_buffer_free(buffer);
00356                 return status;
00357         }
00358         
00359         if (result) {
00360                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00361                 if(!*dest) {
00362                         ldns_buffer_free(buffer);
00363                         return LDNS_STATUS_MEM_ERR;
00364                 }
00365                 memcpy(*dest, result, ldns_buffer_position(buffer));
00366         }
00367         
00368         ldns_buffer_free(buffer);
00369         return status;
00370 }
00371 
00372 ldns_status
00373 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
00374 {
00375         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00376         uint8_t *result = NULL;
00377         ldns_status status;
00378         *result_size = 0;
00379         *dest = NULL;
00380         if(!buffer) return LDNS_STATUS_MEM_ERR;
00381         
00382         status = ldns_rr2buffer_wire(buffer, rr, section);
00383         if (status == LDNS_STATUS_OK) {
00384                 *result_size =  ldns_buffer_position(buffer);
00385                 result = (uint8_t *) ldns_buffer_export(buffer);
00386         } else {
00387                 ldns_buffer_free(buffer);
00388                 return status;
00389         }
00390         
00391         if (result) {
00392                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00393                 if(!*dest) {
00394                         ldns_buffer_free(buffer);
00395                         return LDNS_STATUS_MEM_ERR;
00396                 }
00397                 memcpy(*dest, result, ldns_buffer_position(buffer));
00398         }
00399         
00400         ldns_buffer_free(buffer);
00401         return status;
00402 }
00403 
00404 ldns_status
00405 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
00406 {
00407         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00408         uint8_t *result = NULL;
00409         ldns_status status;
00410         *result_size = 0;
00411         *dest = NULL;
00412         if(!buffer) return LDNS_STATUS_MEM_ERR;
00413         
00414         status = ldns_pkt2buffer_wire(buffer, packet);
00415         if (status == LDNS_STATUS_OK) {
00416                 *result_size =  ldns_buffer_position(buffer);
00417                 result = (uint8_t *) ldns_buffer_export(buffer);
00418         } else {
00419                 ldns_buffer_free(buffer);
00420                 return status;
00421         }
00422         
00423         if (result) {
00424                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00425                 if(!*dest) {
00426                         ldns_buffer_free(buffer);
00427                         return LDNS_STATUS_MEM_ERR;
00428                 }
00429                 memcpy(*dest, result, ldns_buffer_position(buffer));
00430         }
00431         
00432         ldns_buffer_free(buffer);
00433         return status;
00434 }

Generated on Fri Jun 8 17:07:46 2012 for ldns by  doxygen 1.4.7