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 /* convert a rr list to wireformat */
00045 ldns_status
00046 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
00047 {
00048         uint16_t rr_count;
00049         uint16_t i;
00050 
00051         rr_count = ldns_rr_list_rr_count(rr_list);
00052         for(i = 0; i < rr_count; i++) {
00053                 (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 
00054                                           LDNS_SECTION_ANY);
00055         }
00056         return ldns_buffer_status(buffer);
00057 }
00058 
00059 ldns_status
00060 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
00061 {
00062         uint16_t i;
00063         uint16_t rdl_pos = 0;
00064         
00065         if (ldns_rr_owner(rr)) {
00066                 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
00067         }
00068         
00069         if (ldns_buffer_reserve(buffer, 4)) {
00070                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
00071                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
00072         }
00073 
00074         if (section != LDNS_SECTION_QUESTION) {
00075                 if (ldns_buffer_reserve(buffer, 6)) {
00076                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
00077                         /* remember pos for later */
00078                         rdl_pos = ldns_buffer_position(buffer);
00079                         ldns_buffer_write_u16(buffer, 0);
00080                 }       
00081 
00082                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00083                         (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
00084                 }
00085                 
00086                 if (rdl_pos != 0) {
00087                         ldns_buffer_write_u16_at(buffer, rdl_pos,
00088                                                  ldns_buffer_position(buffer)
00089                                                    - rdl_pos - 2);
00090                 }
00091         }
00092         return ldns_buffer_status(buffer);
00093 }
00094 
00095 ldns_status
00096 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00097 {
00098         uint16_t i;
00099 
00100         /* it must be a sig RR */
00101         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
00102                 return LDNS_STATUS_ERR;
00103         }
00104         
00105         /* Convert all the rdfs, except the actual signature data
00106          * rdf number 8  - the last, hence: -1 */
00107         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
00108                 if (ldns_rr_rdf(rr, i)) {
00109                         (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
00110                 }
00111         }
00112 
00113         return ldns_buffer_status(buffer);
00114 }
00115 
00116 ldns_status
00117 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
00118 {
00119         uint16_t i;
00120         /* convert all the rdf's */
00121         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
00122                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
00123         }
00124 
00125         return ldns_buffer_status(buffer);
00126 }
00127 
00128 /*
00129  * Copies the packet header data to the buffer in wire format
00130  */
00131 static ldns_status
00132 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00133 {
00134         uint8_t flags;
00135         uint16_t arcount;
00136         
00137         if (ldns_buffer_reserve(buffer, 12)) {
00138                 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
00139                 
00140                 flags = ldns_pkt_qr(packet) << 7
00141                         | ldns_pkt_get_opcode(packet) << 3
00142                         | ldns_pkt_aa(packet) << 2
00143                         | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
00144                 ldns_buffer_write_u8(buffer, flags);
00145                 
00146                 flags = ldns_pkt_ra(packet) << 7
00147                         /*| ldns_pkt_z(packet) << 6*/
00148                         | ldns_pkt_ad(packet) << 5
00149                         | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet);
00150                 ldns_buffer_write_u8(buffer, flags);
00151                 
00152                 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
00153                 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
00154                 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
00155                 /* add EDNS0 and TSIG to additional if they are there */
00156                 arcount = ldns_pkt_arcount(packet);
00157                 if (ldns_pkt_tsig(packet)) {
00158                         arcount++;
00159                 }
00160                 if (ldns_pkt_edns(packet)) {
00161                         arcount++;
00162                 }
00163                 ldns_buffer_write_u16(buffer, arcount);
00164         }
00165         
00166         return ldns_buffer_status(buffer);
00167 }
00168 
00169 ldns_status
00170 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
00171 {
00172         ldns_rr_list *rr_list;
00173         uint16_t i;
00174         
00175         /* edns tmp vars */
00176         ldns_rr *edns_rr;
00177         uint8_t edata[4];
00178         
00179         (void) ldns_hdr2buffer_wire(buffer, packet);
00180 
00181         rr_list = ldns_pkt_question(packet);
00182         if (rr_list) {
00183                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00184                         (void) ldns_rr2buffer_wire(buffer, 
00185                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
00186                 }
00187         }
00188         rr_list = ldns_pkt_answer(packet);
00189         if (rr_list) {
00190                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00191                         (void) ldns_rr2buffer_wire(buffer, 
00192                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
00193                 }
00194         }
00195         rr_list = ldns_pkt_authority(packet);
00196         if (rr_list) {
00197                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00198                         (void) ldns_rr2buffer_wire(buffer, 
00199                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
00200                 }
00201         }
00202         rr_list = ldns_pkt_additional(packet);
00203         if (rr_list) {
00204                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00205                         (void) ldns_rr2buffer_wire(buffer, 
00206                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
00207                 }
00208         }
00209         
00210         /* add EDNS to additional if it is needed */
00211         if (ldns_pkt_edns(packet)) {
00212                 edns_rr = ldns_rr_new();
00213                 ldns_rr_set_owner(edns_rr,
00214                                 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
00215                 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
00216                 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
00217                 edata[0] = ldns_pkt_edns_extended_rcode(packet);
00218                 edata[1] = ldns_pkt_edns_version(packet);
00219                 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
00220                 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
00221                 (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
00222                 ldns_rr_free(edns_rr);
00223         }
00224         
00225         /* add TSIG to additional if it is there */
00226         if (ldns_pkt_tsig(packet)) {
00227                 (void) ldns_rr2buffer_wire(buffer,
00228                                            ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
00229         }
00230         
00231         return LDNS_STATUS_OK;
00232 }
00233 
00234 ldns_status
00235 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
00236 {
00237         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00238         uint8_t *result = NULL;
00239         ldns_status status;
00240         *result_size = 0;
00241         *dest = NULL;
00242         
00243         status = ldns_rdf2buffer_wire(buffer, rdf);
00244         if (status == LDNS_STATUS_OK) {
00245                 *result_size =  ldns_buffer_position(buffer);
00246                 result = (uint8_t *) ldns_buffer_export(buffer);
00247         } else {
00248                 return status;
00249         }
00250         
00251         if (result) {
00252                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00253                 memcpy(*dest, result, ldns_buffer_position(buffer));
00254         }
00255         
00256         ldns_buffer_free(buffer);
00257         return status;
00258 }
00259 
00260 ldns_status
00261 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
00262 {
00263         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00264         uint8_t *result = NULL;
00265         ldns_status status;
00266         *result_size = 0;
00267         *dest = NULL;
00268         
00269         status = ldns_rr2buffer_wire(buffer, rr, section);
00270         if (status == LDNS_STATUS_OK) {
00271                 *result_size =  ldns_buffer_position(buffer);
00272                 result = (uint8_t *) ldns_buffer_export(buffer);
00273         } else {
00274                 return status;
00275         }
00276         
00277         if (result) {
00278                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00279                 memcpy(*dest, result, ldns_buffer_position(buffer));
00280         }
00281         
00282         ldns_buffer_free(buffer);
00283         return status;
00284 }
00285 
00286 ldns_status
00287 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
00288 {
00289         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00290         uint8_t *result = NULL;
00291         ldns_status status;
00292         *result_size = 0;
00293         *dest = NULL;
00294         
00295         status = ldns_pkt2buffer_wire(buffer, packet);
00296         if (status == LDNS_STATUS_OK) {
00297                 *result_size =  ldns_buffer_position(buffer);
00298                 result = (uint8_t *) ldns_buffer_export(buffer);
00299         } else {
00300                 return status;
00301         }
00302         
00303         if (result) {
00304                 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
00305                 memcpy(*dest, result, ldns_buffer_position(buffer));
00306         }
00307         
00308         ldns_buffer_free(buffer);
00309         return status;
00310 }

Generated on Fri Nov 23 00:48:29 2007 for ldns by  doxygen 1.5.3-20071008