rdata.c
Go to the documentation of this file.
00001 /*
00002  * rdata.c
00003  *
00004  * rdata implementation
00005  *
00006  * a Net::DNS like library for C
00007  *
00008  * (c) NLnet Labs, 2004-2006
00009  *
00010  * See the file LICENSE for the license
00011  */
00012 
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/ldns.h>
00016 
00017 /*
00018  * Access functions 
00019  * do this as functions to get type checking
00020  */
00021 
00022 /* read */
00023 size_t
00024 ldns_rdf_size(const ldns_rdf *rd)
00025 {
00026         assert(rd != NULL);
00027         return rd->_size;
00028 }
00029 
00030 ldns_rdf_type
00031 ldns_rdf_get_type(const ldns_rdf *rd)
00032 {
00033         assert(rd != NULL);
00034         return rd->_type;
00035 }
00036 
00037 uint8_t *
00038 ldns_rdf_data(const ldns_rdf *rd)
00039 {
00040         assert(rd != NULL);
00041         return rd->_data;
00042 }
00043 
00044 /* write */
00045 void
00046 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
00047 {
00048         assert(rd != NULL);
00049         rd->_size = size;
00050 }
00051 
00052 void
00053 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
00054 {
00055         assert(rd != NULL);
00056         rd->_type = type;
00057 }
00058 
00059 void
00060 ldns_rdf_set_data(ldns_rdf *rd, void *data)
00061 {
00062         /* only copy the pointer */
00063         assert(rd != NULL);
00064         rd->_data = data;
00065 }
00066 
00067 /* for types that allow it, return
00068  * the native/host order type */
00069 uint8_t
00070 ldns_rdf2native_int8(const ldns_rdf *rd)
00071 {
00072         uint8_t data;
00073 
00074         /* only allow 8 bit rdfs */
00075         if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
00076                 return 0;
00077         }
00078         
00079         memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00080         return data;
00081 }
00082 
00083 uint16_t
00084 ldns_rdf2native_int16(const ldns_rdf *rd)
00085 {
00086         uint16_t data;
00087 
00088         /* only allow 16 bit rdfs */
00089         if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
00090                 return 0;
00091         }
00092         
00093         memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00094         return ntohs(data);
00095 }
00096 
00097 uint32_t
00098 ldns_rdf2native_int32(const ldns_rdf *rd)
00099 {
00100         uint32_t data;
00101 
00102         /* only allow 32 bit rdfs */
00103         if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
00104                 return 0;
00105         }
00106         
00107         memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00108         return ntohl(data);
00109 }
00110 
00111 time_t
00112 ldns_rdf2native_time_t(const ldns_rdf *rd)
00113 {
00114         uint32_t data;
00115         
00116         switch(ldns_rdf_get_type(rd)) {
00117                 case LDNS_RDF_TYPE_TIME:
00118                         memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00119                         return (time_t)ntohl(data);
00120                 default:
00121                         return 0;
00122         }
00123 }
00124 
00125 ldns_rdf *
00126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
00127 {
00128         return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
00129 }
00130 
00131 ldns_rdf *
00132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
00133 {
00134         uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
00135         ldns_rdf* rdf;
00136         if (!rdf_data) {
00137                 return NULL;
00138         }
00139         ldns_write_uint16(rdf_data, value);
00140         rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
00141         if(!rdf)
00142                 LDNS_FREE(rdf_data);
00143         return rdf;
00144 }
00145 
00146 ldns_rdf *
00147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
00148 {
00149         uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
00150         ldns_rdf* rdf;
00151         if (!rdf_data) {
00152                 return NULL;
00153         }
00154         ldns_write_uint32(rdf_data, value);
00155         rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
00156         if(!rdf)
00157                 LDNS_FREE(rdf_data);
00158         return rdf;
00159 }
00160 
00161 ldns_rdf *
00162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
00163 {
00164         uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
00165         ldns_rdf* rdf;
00166         if (!rdf_data) {
00167                 return NULL;
00168         }
00169         ldns_write_uint16(rdf_data, size);
00170         memcpy(rdf_data + 2, data, size);
00171         rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
00172         if(!rdf)
00173                 LDNS_FREE(rdf_data);
00174         return rdf;
00175 }
00176 
00177 /* note: data must be allocated memory */
00178 ldns_rdf *
00179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
00180 {
00181         ldns_rdf *rd;
00182         rd = LDNS_MALLOC(ldns_rdf);
00183         if (!rd) {
00184                 return NULL;
00185         }
00186         ldns_rdf_set_size(rd, size);
00187         ldns_rdf_set_type(rd, type);
00188         ldns_rdf_set_data(rd, data);
00189         return rd;
00190 }
00191 
00192 ldns_rdf *
00193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
00194 {
00195         ldns_rdf *rdf;
00196 
00197         /* if the size is too big, fail */
00198         if (size > LDNS_MAX_RDFLEN) {
00199                 return NULL;
00200         }
00201 
00202         /* allocate space */
00203         rdf = LDNS_MALLOC(ldns_rdf);
00204         if (!rdf) {
00205                 return NULL;
00206         }
00207         rdf->_data = LDNS_XMALLOC(uint8_t, size);
00208         if (!rdf->_data) {
00209                 LDNS_FREE(rdf);
00210                 return NULL;
00211         }
00212         
00213         /* set the values */
00214         ldns_rdf_set_type(rdf, type);
00215         ldns_rdf_set_size(rdf, size);
00216         memcpy(rdf->_data, data, size);
00217 
00218         return rdf;
00219 }
00220 
00221 ldns_rdf *
00222 ldns_rdf_clone(const ldns_rdf *rd)
00223 {
00224         assert(rd != NULL);
00225         return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
00226                 ldns_rdf_size(rd), ldns_rdf_data(rd)));
00227 }
00228 
00229 void
00230 ldns_rdf_deep_free(ldns_rdf *rd)
00231 {
00232         if (rd) {
00233                 if (rd->_data) {
00234                         LDNS_FREE(rd->_data);
00235                 }
00236                 LDNS_FREE(rd);
00237         }
00238 }
00239 
00240 void 
00241 ldns_rdf_free(ldns_rdf *rd)
00242 {
00243         if (rd) {
00244                 LDNS_FREE(rd);
00245         }
00246 }
00247 
00248 ldns_rdf *
00249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
00250 {
00251         ldns_rdf *rdf = NULL;
00252         ldns_status status;
00253 
00254         switch (type) {
00255         case LDNS_RDF_TYPE_DNAME:
00256                 status = ldns_str2rdf_dname(&rdf, str);
00257                 break;
00258         case LDNS_RDF_TYPE_INT8:
00259                 status = ldns_str2rdf_int8(&rdf, str);
00260                 break;
00261         case LDNS_RDF_TYPE_INT16:
00262                 status = ldns_str2rdf_int16(&rdf, str);
00263                 break;
00264         case LDNS_RDF_TYPE_INT32:
00265                 status = ldns_str2rdf_int32(&rdf, str);
00266                 break;
00267         case LDNS_RDF_TYPE_A:
00268                 status = ldns_str2rdf_a(&rdf, str);
00269                 break;
00270         case LDNS_RDF_TYPE_AAAA:
00271                 status = ldns_str2rdf_aaaa(&rdf, str);
00272                 break;
00273         case LDNS_RDF_TYPE_STR:
00274                 status = ldns_str2rdf_str(&rdf, str);
00275                 break;
00276         case LDNS_RDF_TYPE_APL:
00277                 status = ldns_str2rdf_apl(&rdf, str);
00278                 break;
00279         case LDNS_RDF_TYPE_B64:
00280                 status = ldns_str2rdf_b64(&rdf, str);
00281                 break;
00282         case LDNS_RDF_TYPE_B32_EXT:
00283                 status = ldns_str2rdf_b32_ext(&rdf, str);
00284                 break;
00285         case LDNS_RDF_TYPE_HEX:
00286                 status = ldns_str2rdf_hex(&rdf, str);
00287                 break;
00288         case LDNS_RDF_TYPE_NSEC:
00289                 status = ldns_str2rdf_nsec(&rdf, str);
00290                 break;
00291         case LDNS_RDF_TYPE_TYPE:
00292                 status = ldns_str2rdf_type(&rdf, str);
00293                 break;
00294         case LDNS_RDF_TYPE_CLASS:
00295                 status = ldns_str2rdf_class(&rdf, str);
00296                 break;
00297         case LDNS_RDF_TYPE_CERT_ALG:
00298                 status = ldns_str2rdf_cert_alg(&rdf, str);
00299                 break;
00300         case LDNS_RDF_TYPE_ALG:
00301                 status = ldns_str2rdf_alg(&rdf, str);
00302                 break;
00303         case LDNS_RDF_TYPE_UNKNOWN:
00304                 status = ldns_str2rdf_unknown(&rdf, str);
00305                 break;
00306         case LDNS_RDF_TYPE_TIME:
00307                 status = ldns_str2rdf_time(&rdf, str);
00308                 break;
00309         case LDNS_RDF_TYPE_PERIOD:
00310                 status = ldns_str2rdf_period(&rdf, str);
00311                 break;
00312         case LDNS_RDF_TYPE_TSIG:
00313                 status = ldns_str2rdf_tsig(&rdf, str);
00314                 break;
00315         case LDNS_RDF_TYPE_SERVICE:
00316                 status = ldns_str2rdf_service(&rdf, str);
00317                 break;
00318         case LDNS_RDF_TYPE_LOC:
00319                 status = ldns_str2rdf_loc(&rdf, str);
00320                 break;
00321         case LDNS_RDF_TYPE_WKS:
00322                 status = ldns_str2rdf_wks(&rdf, str);
00323                 break;
00324         case LDNS_RDF_TYPE_NSAP:
00325                 status = ldns_str2rdf_nsap(&rdf, str);
00326                 break;
00327         case LDNS_RDF_TYPE_ATMA:
00328                 status = ldns_str2rdf_atma(&rdf, str);
00329                 break;
00330         case LDNS_RDF_TYPE_IPSECKEY:
00331                 status = ldns_str2rdf_ipseckey(&rdf, str);
00332                 break;
00333         case LDNS_RDF_TYPE_NSEC3_SALT:
00334                 status = ldns_str2rdf_nsec3_salt(&rdf, str);
00335                 break;
00336         case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
00337                 status = ldns_str2rdf_b32_ext(&rdf, str);
00338                 break;
00339         case LDNS_RDF_TYPE_NONE:
00340         default:
00341                 /* default default ??? */
00342                 status = LDNS_STATUS_ERR;
00343                 break;
00344         }
00345         if (LDNS_STATUS_OK == status) {
00346                 ldns_rdf_set_type(rdf, type);
00347                 return rdf;
00348         }
00349         if (rdf) {
00350                 LDNS_FREE(rdf);
00351         }
00352         return NULL;
00353 }
00354 
00355 ldns_status
00356 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
00357 {
00358         return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
00359 }
00360 
00361 ldns_status
00362 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
00363 {
00364         char *line;
00365         ldns_rdf *r;
00366         ssize_t t;
00367 
00368         line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00369         if (!line) {
00370                 return LDNS_STATUS_MEM_ERR;
00371         }
00372 
00373         /* read an entire line in from the file */
00374         if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
00375                 LDNS_FREE(line);
00376                 return LDNS_STATUS_SYNTAX_RDATA_ERR;
00377         }
00378         r =  ldns_rdf_new_frm_str(type, (const char*) line);
00379         LDNS_FREE(line);
00380         if (rdf) {
00381                 *rdf = r;
00382                 return LDNS_STATUS_OK;
00383         } else {
00384                 return LDNS_STATUS_NULL;
00385         }
00386 }
00387 
00388 ldns_rdf *
00389 ldns_rdf_address_reverse(ldns_rdf *rd)
00390 {
00391         uint8_t buf_4[LDNS_IP4ADDRLEN];
00392         uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
00393         ldns_rdf *rev;
00394         ldns_rdf *in_addr;
00395         ldns_rdf *ret_dname;
00396         uint8_t octet;
00397         uint8_t nnibble;
00398         uint8_t nibble;
00399         uint8_t i, j;
00400 
00401         char *char_dname;
00402         int nbit;
00403 
00404         if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
00405                         ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
00406                 return NULL;
00407         }
00408 
00409         in_addr = NULL;
00410         ret_dname = NULL;
00411 
00412         switch(ldns_rdf_get_type(rd)) {
00413                 case LDNS_RDF_TYPE_A:
00414                         /* the length of the buffer is 4 */
00415                         buf_4[3] = ldns_rdf_data(rd)[0];
00416                         buf_4[2] = ldns_rdf_data(rd)[1];
00417                         buf_4[1] = ldns_rdf_data(rd)[2];
00418                         buf_4[0] = ldns_rdf_data(rd)[3];
00419                         in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
00420                         if (!in_addr) {
00421                                 return NULL;
00422                         }
00423                         /* make a new rdf and convert that back  */
00424                         rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
00425                                 LDNS_IP4ADDRLEN, (void*)&buf_4);
00426                         if (!rev) {
00427                                 LDNS_FREE(in_addr);
00428                                 return NULL;
00429                         }
00430 
00431                         /* convert rev to a string */
00432                         char_dname = ldns_rdf2str(rev);
00433                         if (!char_dname) {
00434                                 LDNS_FREE(in_addr);
00435                                 ldns_rdf_deep_free(rev);
00436                                 return NULL;
00437                         }
00438                         /* transform back to rdf with type dname */
00439                         ret_dname = ldns_dname_new_frm_str(char_dname);
00440                         if (!ret_dname) {
00441                                 LDNS_FREE(in_addr);
00442                                 ldns_rdf_deep_free(rev);
00443                                 LDNS_FREE(char_dname);
00444                                 return NULL;
00445                         }
00446                         /* not needed anymore */
00447                         ldns_rdf_deep_free(rev);
00448                         LDNS_FREE(char_dname);
00449                         break;
00450                 case LDNS_RDF_TYPE_AAAA:
00451                         /* some foo magic to reverse the nibbles ... */
00452 
00453                         for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
00454                                 /* calculate octett (8 bit) */
00455                                 octet = ( ((unsigned int) nbit) & 0x78) >> 3;
00456                                 /* calculate nibble */
00457                                 nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
00458                                 /* extract nibble */
00459                                 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
00460                                                  nnibble)) ) ) >> ( 4 * (1 - 
00461                                                 nnibble));
00462 
00463                                 buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
00464                                         (octet * 2 + nnibble)] = 
00465                                                 (uint8_t)ldns_int_to_hexdigit((int)nibble);
00466                         }
00467 
00468                         char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
00469                         if (!char_dname) {
00470                                 return NULL;
00471                         }
00472                         char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
00473 
00474                         /* walk the string and add . 's */
00475                         for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
00476                                 char_dname[j] = (char)buf_6[i];
00477                                 if (i != LDNS_IP6ADDRLEN * 2 - 1) {
00478                                         char_dname[j + 1] = '.';
00479                                 }
00480                         }
00481                         in_addr = ldns_dname_new_frm_str("ip6.arpa.");
00482                         if (!in_addr) {
00483                                 LDNS_FREE(char_dname);
00484                                 return NULL;
00485                         }
00486 
00487                         /* convert rev to a string */
00488                         ret_dname = ldns_dname_new_frm_str(char_dname);
00489                         LDNS_FREE(char_dname);
00490                         if (!ret_dname) {
00491                                 ldns_rdf_deep_free(in_addr);
00492                                 return NULL;
00493                         }
00494                         break;
00495                 default:
00496                         break;
00497         }
00498         /* add the suffix */
00499         rev = ldns_dname_cat_clone(ret_dname, in_addr);
00500 
00501         ldns_rdf_deep_free(ret_dname);
00502         ldns_rdf_deep_free(in_addr);
00503         return rev;
00504 }
00505 
00506 ldns_status
00507 ldns_octet(char *word, size_t *length)
00508 {
00509     char *s; 
00510     char *p;
00511     *length = 0;
00512 
00513     for (s = p = word; *s != '\0'; s++,p++) {
00514         switch (*s) {
00515             case '.':
00516                 if (s[1] == '.') {
00517                     return LDNS_STATUS_EMPTY_LABEL;
00518                 }
00519                 *p = *s;
00520                 (*length)++;
00521                 break;
00522             case '\\':
00523                 if ('0' <= s[1] && s[1] <= '9' &&
00524                     '0' <= s[2] && s[2] <= '9' &&
00525                     '0' <= s[3] && s[3] <= '9') {
00526                     /* \DDD seen */
00527                     int val = ((s[1] - '0') * 100 +
00528                            (s[2] - '0') * 10 + (s[3] - '0'));
00529 
00530                     if (0 <= val && val <= 255) {
00531                         /* this also handles \0 */
00532                         s += 3;
00533                         *p = val;
00534                         (*length)++;
00535                     } else {
00536                         return LDNS_STATUS_DDD_OVERFLOW;
00537                     }
00538                 } else {
00539                     /* an espaced character, like <space> ? 
00540                     * remove the '\' keep the rest */
00541                     *p = *++s;
00542                     (*length)++;
00543                 }
00544                 break;
00545             case '\"':
00546                 /* non quoted " Is either first or the last character in
00547                  * the string */
00548 
00549                 *p = *++s; /* skip it */
00550                 (*length)++;
00551                 /* I'm not sure if this is needed in libdns... MG */
00552                 if ( *s == '\0' ) {
00553                     /* ok, it was the last one */
00554                     *p  = '\0'; 
00555                     return LDNS_STATUS_OK;
00556                 }
00557                 break;
00558             default:
00559                 *p = *s;
00560                 (*length)++;
00561                 break;
00562         }
00563     }
00564     *p = '\0';
00565     return LDNS_STATUS_OK;
00566 }
00567 
00568 int
00569 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
00570 {
00571         uint16_t i1, i2, i;
00572         uint8_t *d1, *d2;
00573 
00574         /* only when both are not NULL we can say anything about them */
00575         if (!rd1 && !rd2) {
00576                 return 0;
00577         }
00578         if (!rd1 || !rd2) {
00579                 return -1;
00580         }
00581         i1 = ldns_rdf_size(rd1);
00582         i2 = ldns_rdf_size(rd2);
00583 
00584         if (i1 < i2) {
00585                 return -1;
00586         } else if (i1 > i2) {
00587                 return +1;
00588         } else {
00589                 d1 = (uint8_t*)ldns_rdf_data(rd1);
00590                 d2 = (uint8_t*)ldns_rdf_data(rd2);
00591                 for(i = 0; i < i1; i++) {
00592                         if (d1[i] < d2[i]) {
00593                                 return -1;
00594                         } else if (d1[i] > d2[i]) {
00595                                 return +1;
00596                         }
00597                 }
00598         }
00599         return 0;
00600 }
00601 
00602 uint32_t
00603 ldns_str2period(const char *nptr, const char **endptr)
00604 {
00605         int sign = 0;
00606         uint32_t i = 0;
00607         uint32_t seconds = 0;
00608 
00609         for(*endptr = nptr; **endptr; (*endptr)++) {
00610                 switch (**endptr) {
00611                         case ' ':
00612                         case '\t':
00613                                 break;
00614                         case '-':
00615                                 if(sign == 0) {
00616                                         sign = -1;
00617                                 } else {
00618                                         return seconds;
00619                                 }
00620                                 break;
00621                         case '+':
00622                                 if(sign == 0) {
00623                                         sign = 1;
00624                                 } else {
00625                                         return seconds;
00626                                 }
00627                                 break;
00628                         case 's':
00629                         case 'S':
00630                                 seconds += i;
00631                                 i = 0;
00632                                 break;
00633                         case 'm':
00634                         case 'M':
00635                                 seconds += i * 60;
00636                                 i = 0;
00637                                 break;
00638                         case 'h':
00639                         case 'H':
00640                                 seconds += i * 60 * 60;
00641                                 i = 0;
00642                                 break;
00643                         case 'd':
00644                         case 'D':
00645                                 seconds += i * 60 * 60 * 24;
00646                                 i = 0;
00647                                 break;
00648                         case 'w':
00649                         case 'W':
00650                                 seconds += i * 60 * 60 * 24 * 7;
00651                                 i = 0;
00652                                 break;
00653                         case '0':
00654                         case '1':
00655                         case '2':
00656                         case '3':
00657                         case '4':
00658                         case '5':
00659                         case '6':
00660                         case '7':
00661                         case '8':
00662                         case '9':
00663                                 i *= 10;
00664                                 i += (**endptr - '0');
00665                                 break;
00666                         default:
00667                                 seconds += i;
00668                                 /* disregard signedness */
00669                                 return seconds;
00670                 }
00671         }
00672         seconds += i;
00673         /* disregard signedness */
00674         return seconds;
00675 }