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_write_uint16(rdf_data, value);
00136         return ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
00137 }
00138 
00139 ldns_rdf *
00140 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
00141 {
00142         uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
00143         ldns_write_uint32(rdf_data, value);
00144         return ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
00145 }
00146 
00147 ldns_rdf *
00148 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
00149 {
00150         uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
00151         ldns_write_uint16(rdf_data, size);
00152         memcpy(rdf_data + 2, data, size);
00153         return ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
00154 }
00155 
00156 ldns_rdf *
00157 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
00158 {
00159         ldns_rdf *rd;
00160         rd = LDNS_MALLOC(ldns_rdf);
00161         if (!rd) {
00162                 return NULL;
00163         }
00164         ldns_rdf_set_size(rd, size);
00165         ldns_rdf_set_type(rd, type);
00166         ldns_rdf_set_data(rd, data);
00167         return rd;
00168 }
00169 
00170 ldns_rdf *
00171 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
00172 {
00173         ldns_rdf *rdf;
00174         rdf = LDNS_MALLOC(ldns_rdf);
00175         if (!rdf) {
00176                 return NULL;
00177         }
00178         if (size > LDNS_MAX_RDFLEN) {
00179                 return NULL;
00180         }
00181         rdf->_data = LDNS_XMALLOC(uint8_t, size);
00182         if (!rdf->_data) {
00183                 return NULL;
00184         }
00185         
00186         ldns_rdf_set_type(rdf, type);
00187         ldns_rdf_set_size(rdf, size);
00188         memcpy(rdf->_data, data, size);
00189         return rdf;
00190 }
00191 
00192 ldns_rdf *
00193 ldns_rdf_clone(const ldns_rdf *rd)
00194 {
00195         if (rd) {
00196                 return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
00197                         ldns_rdf_size(rd), ldns_rdf_data(rd)));
00198         } else {
00199                 return NULL;
00200         }
00201 }
00202 
00203 void
00204 ldns_rdf_deep_free(ldns_rdf *rd)
00205 {
00206         if (rd) {
00207                 if (rd->_data) {
00208                         LDNS_FREE(rd->_data);
00209                 }
00210                 LDNS_FREE(rd);
00211         }
00212 }
00213 
00214 void 
00215 ldns_rdf_free(ldns_rdf *rd)
00216 {
00217         if (rd) {
00218                 LDNS_FREE(rd);
00219         }
00220 }
00221 
00222 ldns_rdf *
00223 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
00224 {
00225         ldns_rdf *rdf = NULL;
00226         ldns_status status;
00227 
00228         switch (type) {
00229         case LDNS_RDF_TYPE_DNAME:
00230                 status = ldns_str2rdf_dname(&rdf, str);
00231                 break;
00232         case LDNS_RDF_TYPE_INT8:
00233                 status = ldns_str2rdf_int8(&rdf, str);
00234                 break;
00235         case LDNS_RDF_TYPE_INT16:
00236                 status = ldns_str2rdf_int16(&rdf, str);
00237                 break;
00238         case LDNS_RDF_TYPE_INT32:
00239                 status = ldns_str2rdf_int32(&rdf, str);
00240                 break;
00241         case LDNS_RDF_TYPE_A:
00242                 status = ldns_str2rdf_a(&rdf, str);
00243                 break;
00244         case LDNS_RDF_TYPE_AAAA:
00245                 status = ldns_str2rdf_aaaa(&rdf, str);
00246                 break;
00247         case LDNS_RDF_TYPE_STR:
00248                 status = ldns_str2rdf_str(&rdf, str);
00249                 break;
00250         case LDNS_RDF_TYPE_APL:
00251                 status = ldns_str2rdf_apl(&rdf, str);
00252                 break;
00253         case LDNS_RDF_TYPE_B64:
00254                 status = ldns_str2rdf_b64(&rdf, str);
00255                 break;
00256         case LDNS_RDF_TYPE_HEX:
00257                 status = ldns_str2rdf_hex(&rdf, str);
00258                 break;
00259         case LDNS_RDF_TYPE_NSEC:
00260                 status = ldns_str2rdf_nsec(&rdf, str);
00261                 break;
00262         case LDNS_RDF_TYPE_TYPE:
00263                 status = ldns_str2rdf_type(&rdf, str);
00264                 break;
00265         case LDNS_RDF_TYPE_CLASS:
00266                 status = ldns_str2rdf_class(&rdf, str);
00267                 break;
00268         case LDNS_RDF_TYPE_CERT_ALG:
00269                 status = ldns_str2rdf_cert_alg(&rdf, str);
00270                 break;
00271         case LDNS_RDF_TYPE_ALG:
00272                 status = ldns_str2rdf_alg(&rdf, str);
00273                 break;
00274         case LDNS_RDF_TYPE_UNKNOWN:
00275                 status = ldns_str2rdf_unknown(&rdf, str);
00276                 break;
00277         case LDNS_RDF_TYPE_TIME:
00278                 status = ldns_str2rdf_time(&rdf, str);
00279                 break;
00280         case LDNS_RDF_TYPE_PERIOD:
00281                 status = ldns_str2rdf_period(&rdf, str);
00282                 break;
00283         case LDNS_RDF_TYPE_TSIG:
00284                 status = ldns_str2rdf_tsig(&rdf, str);
00285                 break;
00286         case LDNS_RDF_TYPE_SERVICE:
00287                 status = ldns_str2rdf_service(&rdf, str);
00288                 break;
00289         case LDNS_RDF_TYPE_LOC:
00290                 status = ldns_str2rdf_loc(&rdf, str);
00291                 break;
00292         case LDNS_RDF_TYPE_WKS:
00293                 status = ldns_str2rdf_wks(&rdf, str);
00294                 break;
00295         case LDNS_RDF_TYPE_NSAP:
00296                 status = ldns_str2rdf_nsap(&rdf, str);
00297                 break;
00298         case LDNS_RDF_TYPE_NONE:
00299         default:
00300                 /* default default ??? */
00301                 status = LDNS_STATUS_ERR;
00302                 break;
00303         }
00304         if (LDNS_STATUS_OK != status || !rdf) {
00305                 return NULL;
00306         } else {
00307                 ldns_rdf_set_type(rdf, type);
00308                 return rdf;
00309         }
00310 }
00311 
00312 ldns_status
00313 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
00314 {
00315         return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
00316 }
00317 
00318 ldns_status
00319 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
00320 {
00321         char *line;
00322         ldns_rdf *r;
00323         ssize_t t;
00324 
00325         line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00326         if (!line) {
00327                 return LDNS_STATUS_MEM_ERR;
00328         }
00329 
00330         /* read an entire line in from the file */
00331         if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1) {
00332                 LDNS_FREE(line);
00333                 return LDNS_STATUS_SYNTAX_RDATA_ERR;
00334         }
00335         r =  ldns_rdf_new_frm_str(type, (const char*) line);
00336         LDNS_FREE(line);
00337         if (rdf) {
00338                 *rdf = r;
00339                 return LDNS_STATUS_OK;
00340         } else {
00341                 return LDNS_STATUS_NULL;
00342         }
00343 }
00344 
00345 ldns_rdf *
00346 ldns_rdf_address_reverse(ldns_rdf *rd)
00347 {
00348         uint8_t buf_4[LDNS_IP4ADDRLEN];
00349         uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
00350         ldns_rdf *rev;
00351         ldns_rdf *in_addr;
00352         ldns_rdf *ret_dname;
00353         uint8_t octet;
00354         uint8_t nnibble;
00355         uint8_t nibble;
00356         uint8_t i, j;
00357 
00358         char *char_dname;
00359         int nbit;
00360 
00361         if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
00362                         ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
00363                 return NULL;
00364         }
00365 
00366         in_addr = NULL;
00367         ret_dname = NULL;
00368 
00369         switch(ldns_rdf_get_type(rd)) {
00370                 case LDNS_RDF_TYPE_A:
00371                         /* the length of the buffer is 4 */
00372                         buf_4[3] = ldns_rdf_data(rd)[0];
00373                         buf_4[2] = ldns_rdf_data(rd)[1];
00374                         buf_4[1] = ldns_rdf_data(rd)[2];
00375                         buf_4[0] = ldns_rdf_data(rd)[3];
00376                         in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
00377                         if (!in_addr) {
00378                                 return NULL;
00379                         }
00380                         /* make a new rdf and convert that back  */
00381                         rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
00382                                 LDNS_IP4ADDRLEN, (void*)&buf_4);
00383 
00384                         /* convert rev to a string */
00385                         char_dname = ldns_rdf2str(rev);
00386                         if (!char_dname) {
00387                                 return NULL;
00388                         }
00389                         /* transform back to rdf with type dname */
00390                         ret_dname = ldns_dname_new_frm_str(char_dname);
00391                         if (!ret_dname) {
00392                                 return NULL;
00393                         }
00394                         /* not needed anymore */
00395                         ldns_rdf_deep_free(rev);
00396                         LDNS_FREE(char_dname);
00397                         break;
00398                 case LDNS_RDF_TYPE_AAAA:
00399                         /* some foo magic to reverse the nibbles ... */
00400 
00401                         for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
00402                                 /* calculate octett (8 bit) */
00403                                 octet = ( ((unsigned int) nbit) & 0x78) >> 3;
00404                                 /* calculate nibble */
00405                                 nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
00406                                 /* extract nibble */
00407                                 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
00408                                                  nnibble)) ) ) >> ( 4 * (1 - 
00409                                                 nnibble));
00410 
00411                                 buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
00412                                         (octet * 2 + nnibble)] = 
00413                                                 (uint8_t)ldns_int_to_hexdigit((int)nibble);
00414                         }
00415 
00416                         char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
00417                         if (!char_dname) {
00418                                 return NULL;
00419                         }
00420                         char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
00421 
00422                         /* walk the string and add . 's */
00423                         for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
00424                                 char_dname[j] = (char)buf_6[i];
00425                                 if (i != LDNS_IP6ADDRLEN * 2 - 1) {
00426                                         char_dname[j + 1] = '.';
00427                                 }
00428                         }
00429                         in_addr = ldns_dname_new_frm_str("ip6.arpa.");
00430                         if (!in_addr) {
00431                                 return NULL;
00432                         }
00433                 
00434                         /* convert rev to a string */
00435                         ret_dname = ldns_dname_new_frm_str(char_dname);
00436                         if (!ret_dname) {
00437                                 return NULL;
00438                         }
00439                         LDNS_FREE(char_dname);
00440                         break;
00441                 default:
00442                         break;
00443         }
00444         /* add the suffix */
00445         rev = ldns_dname_cat_clone(ret_dname, in_addr);
00446         
00447         ldns_rdf_deep_free(ret_dname);
00448         ldns_rdf_deep_free(in_addr);
00449         return rev;
00450 }
00451 
00452 ldns_status
00453 ldns_octet(char *word, size_t *length)
00454 {
00455     char *s; 
00456     char *p;
00457     *length = 0;
00458 
00459     for (s = p = word; *s != '\0'; s++,p++) {
00460         switch (*s) {
00461             case '.':
00462                 if (s[1] == '.') {
00463                     return LDNS_STATUS_EMPTY_LABEL;
00464                 }
00465                 *p = *s;
00466                 (*length)++;
00467                 break;
00468             case '\\':
00469                 if ('0' <= s[1] && s[1] <= '9' &&
00470                     '0' <= s[2] && s[2] <= '9' &&
00471                     '0' <= s[3] && s[3] <= '9') {
00472                     /* \DDD seen */
00473                     int val = ((s[1] - '0') * 100 +
00474                            (s[2] - '0') * 10 + (s[3] - '0'));
00475 
00476                     if (0 <= val && val <= 255) {
00477                         /* this also handles \0 */
00478                         s += 3;
00479                         *p = val;
00480                         (*length)++;
00481                     } else {
00482                         return LDNS_STATUS_DDD_OVERFLOW;
00483                     }
00484                 } else {
00485                     /* an espaced character, like <space> ? 
00486                     * remove the '\' keep the rest */
00487                     *p = *++s;
00488                     (*length)++;
00489                 }
00490                 break;
00491             case '\"':
00492                 /* non quoted " Is either first or the last character in
00493                  * the string */
00494 
00495                 *p = *++s; /* skip it */
00496                 (*length)++;
00497                 /* I'm not sure if this is needed in libdns... MG */
00498                 if ( *s == '\0' ) {
00499                     /* ok, it was the last one */
00500                     *p  = '\0'; 
00501                     return LDNS_STATUS_OK;
00502                 }
00503                 break;
00504             default:
00505                 *p = *s;
00506                 (*length)++;
00507                 break;
00508         }
00509     }
00510     *p = '\0';
00511     return LDNS_STATUS_OK;
00512 }
00513 
00514 int
00515 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
00516 {
00517         uint16_t i1, i2, i;
00518         uint8_t *d1, *d2;
00519 
00520         /* only when both are not NULL we can say anything about them */
00521         if (!rd1 && !rd2) {
00522                 return 0;
00523         }
00524         if (!rd1 || !rd2) {
00525                 return -1;
00526         }
00527         i1 = ldns_rdf_size(rd1);
00528         i2 = ldns_rdf_size(rd1);
00529 
00530         if (i1 < i2) {
00531                 return -1;
00532         } else if (i1 > i2) {
00533                 return +1;
00534         } else {
00535                 d1 = (uint8_t*)ldns_rdf_data(rd1);
00536                 d2 = (uint8_t*)ldns_rdf_data(rd2);
00537                 for(i = 0; i < i1; i++) {
00538                         if (d1[i] < d2[i]) {
00539                                 return -1;
00540                         } else if (d1[i] > d2[i]) {
00541                                 return +1;
00542                         }
00543                 }
00544         }
00545         return 0;
00546 }
00547 
00548 uint32_t
00549 ldns_str2period(const char *nptr, const char **endptr)
00550 {
00551         int sign = 0;
00552         uint32_t i = 0;
00553         uint32_t seconds = 0;
00554 
00555         for(*endptr = nptr; **endptr; (*endptr)++) {
00556                 switch (**endptr) {
00557                         case ' ':
00558                         case '\t':
00559                                 break;
00560                         case '-':
00561                                 if(sign == 0) {
00562                                         sign = -1;
00563                                 } else {
00564                                         return seconds;
00565                                 }
00566                                 break;
00567                         case '+':
00568                                 if(sign == 0) {
00569                                         sign = 1;
00570                                 } else {
00571                                         return seconds;
00572                                 }
00573                                 break;
00574                         case 's':
00575                         case 'S':
00576                                 seconds += i;
00577                                 i = 0;
00578                                 break;
00579                         case 'm':
00580                         case 'M':
00581                                 seconds += i * 60;
00582                                 i = 0;
00583                                 break;
00584                         case 'h':
00585                         case 'H':
00586                                 seconds += i * 60 * 60;
00587                                 i = 0;
00588                                 break;
00589                         case 'd':
00590                         case 'D':
00591                                 seconds += i * 60 * 60 * 24;
00592                                 i = 0;
00593                                 break;
00594                         case 'w':
00595                         case 'W':
00596                                 seconds += i * 60 * 60 * 24 * 7;
00597                                 i = 0;
00598                                 break;
00599                         case '0':
00600                         case '1':
00601                         case '2':
00602                         case '3':
00603                         case '4':
00604                         case '5':
00605                         case '6':
00606                         case '7':
00607                         case '8':
00608                         case '9':
00609                                 i *= 10;
00610                                 i += (**endptr - '0');
00611                                 break;
00612                         default:
00613                                 seconds += i;
00614                                 /* disregard signedness */
00615                                 return seconds;
00616                 }
00617         }
00618         seconds += i;
00619         /* disregard signedness */
00620         return seconds;
00621 }

Generated on Sat Dec 8 05:43:31 2007 for ldns by  doxygen 1.5.4