str2host.c
Go to the documentation of this file.
00001 /*
00002  * str2host.c
00003  *
00004  * conversion routines from the presentation format
00005  * to the host format
00006  *
00007  * a Net::DNS like library for C
00008  *
00009  * (c) NLnet Labs, 2004-2006
00010  *
00011  * See the file LICENSE for the license
00012  */
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/ldns.h>
00016 
00017 #ifdef HAVE_SYS_SOCKET_H
00018 #include <sys/socket.h>
00019 #endif
00020 #ifdef HAVE_ARPA_INET_H
00021 #include <arpa/inet.h>
00022 #endif
00023 #include <time.h>
00024 
00025 #include <errno.h>
00026 #ifdef HAVE_NETDB_H
00027 #include <netdb.h>
00028 #endif
00029 
00030 #include <limits.h>
00031 #ifdef HAVE_SYS_PARAM_H
00032 #include <sys/param.h>
00033 #endif
00034 
00035 ldns_status
00036 ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
00037 {
00038         char *end = NULL;
00039         uint16_t *r;
00040         r = LDNS_MALLOC(uint16_t);
00041         if(!r) return LDNS_STATUS_MEM_ERR;
00042 
00043         *r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
00044 
00045         if(*end != 0) {
00046                 LDNS_FREE(r);
00047                 return LDNS_STATUS_INVALID_INT;
00048         } else {
00049                 *rd = ldns_rdf_new_frm_data(
00050                         LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
00051                 LDNS_FREE(r);
00052                 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00053         }
00054 }
00055 
00056 ldns_status
00057 ldns_str2rdf_time(ldns_rdf **rd, const char *time)
00058 {
00059         /* convert a time YYYYDDMMHHMMSS to wireformat */
00060         uint16_t *r = NULL;
00061         struct tm tm;
00062         uint32_t l;
00063         char *end;
00064 
00065         /* Try to scan the time... */
00066         r = (uint16_t*)LDNS_MALLOC(uint32_t);
00067         if(!r) return LDNS_STATUS_MEM_ERR;
00068 
00069         memset(&tm, 0, sizeof(tm));
00070 
00071         if (strlen(time) == 14 &&
00072             sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6
00073            ) {
00074                 tm.tm_year -= 1900;
00075                 tm.tm_mon--;
00076                 /* Check values */
00077                 if (tm.tm_year < 70) {
00078                         goto bad_format;
00079                 }
00080                 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
00081                         goto bad_format;
00082                 }
00083                 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
00084                         goto bad_format;
00085                 }
00086 
00087                 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
00088                         goto bad_format;
00089                 }
00090 
00091                 if (tm.tm_min < 0 || tm.tm_min > 59) {
00092                         goto bad_format;
00093                 }
00094 
00095                 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
00096                         goto bad_format;
00097                 }
00098 
00099                 l = htonl(mktime_from_utc(&tm));
00100                 memcpy(r, &l, sizeof(uint32_t));
00101                 *rd = ldns_rdf_new_frm_data(
00102                         LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
00103                 LDNS_FREE(r);
00104                 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00105         } else {
00106                 /* handle it as 32 bits timestamp */
00107                 l = htonl((uint32_t)strtol((char*)time, &end, 10));
00108                 if(*end != 0) {
00109                         LDNS_FREE(r);
00110                         return LDNS_STATUS_ERR;
00111                 } else {
00112                         memcpy(r, &l, sizeof(uint32_t));
00113                         *rd = ldns_rdf_new_frm_data(
00114                                 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
00115                         LDNS_FREE(r);
00116                         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00117                 }
00118         }
00119 
00120         bad_format:
00121         LDNS_FREE(r);
00122         return LDNS_STATUS_INVALID_TIME;
00123 }
00124 
00125 ldns_status
00126 ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
00127 {
00128         uint8_t salt_length;
00129         int c;
00130         int salt_length_str;
00131 
00132         uint8_t *salt;
00133         uint8_t *data;
00134         if(rd == NULL) {
00135                 return LDNS_STATUS_NULL;
00136         }
00137 
00138         salt_length_str = (int)strlen(salt_str);
00139         if (salt_length_str == 1 && salt_str[0] == '-') {
00140                 salt_length_str = 0;
00141         } else if (salt_length_str % 2 != 0) {
00142                 return LDNS_STATUS_INVALID_HEX;
00143         }
00144         if (salt_length_str > 512) {
00145                 return LDNS_STATUS_INVALID_HEX;
00146         }
00147 
00148         salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
00149         if(!salt) {
00150                 return LDNS_STATUS_MEM_ERR;
00151         }
00152         for (c = 0; c < salt_length_str; c += 2) {
00153                 if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) {
00154                         salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 +
00155                                           ldns_hexdigit_to_int(salt_str[c+1]);
00156                 } else {
00157                         LDNS_FREE(salt);
00158                         return LDNS_STATUS_INVALID_HEX;
00159                 }
00160         }
00161         salt_length = (uint8_t) (salt_length_str / 2);
00162 
00163         data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
00164         if(!data) {
00165                 LDNS_FREE(salt);
00166                 return LDNS_STATUS_MEM_ERR;
00167         }
00168         data[0] = salt_length;
00169         memcpy(&data[1], salt, salt_length);
00170         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data);
00171         LDNS_FREE(data);
00172         LDNS_FREE(salt);
00173 
00174         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00175 }
00176 
00177 ldns_status
00178 ldns_str2rdf_period(ldns_rdf **rd,const char *period)
00179 {
00180         uint32_t p;
00181         const char *end;
00182 
00183         /* Allocate required space... */
00184         p = ldns_str2period(period, &end);
00185 
00186         if (*end != 0) {
00187                 return LDNS_STATUS_ERR;
00188         } else {
00189                 p = (uint32_t) htonl(p);
00190                 *rd = ldns_rdf_new_frm_data(
00191                         LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
00192         }
00193         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00194 }
00195 
00196 ldns_status
00197 ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
00198 {
00199         char *end;
00200         uint16_t *r = NULL;
00201         uint32_t l;
00202 
00203         r = (uint16_t*)LDNS_MALLOC(uint32_t);
00204         if(!r) return LDNS_STATUS_MEM_ERR;
00205         errno = 0; /* must set to zero before call,
00206                         note race condition on errno */
00207         if(*longstr == '-')
00208                 l = htonl((uint32_t)strtol((char*)longstr, &end, 10));
00209         else    l = htonl((uint32_t)strtoul((char*)longstr, &end, 10));
00210 
00211         if(*end != 0) {
00212                 LDNS_FREE(r);
00213                 return LDNS_STATUS_ERR;
00214      } else {
00215                 if (errno == ERANGE) {
00216                         LDNS_FREE(r);
00217                         return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW;
00218                 }
00219                 memcpy(r, &l, sizeof(uint32_t));
00220                 *rd = ldns_rdf_new_frm_data(
00221                         LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
00222                 LDNS_FREE(r);
00223                 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00224         }
00225 }
00226 
00227 ldns_status
00228 ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
00229 {
00230         char *end;
00231         uint8_t *r = NULL;
00232 
00233         r = LDNS_MALLOC(uint8_t);
00234         if(!r) return LDNS_STATUS_MEM_ERR;
00235 
00236         *r = (uint8_t)strtol((char*)bytestr, &end, 10);
00237 
00238         if(*end != 0) {
00239                 LDNS_FREE(r);
00240                 return LDNS_STATUS_ERR;
00241         } else {
00242                 *rd = ldns_rdf_new_frm_data(
00243                         LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
00244                 LDNS_FREE(r);
00245                 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00246         }
00247 }
00248 
00249 
00250 /*
00251  * Checks whether the escaped value at **s is an octal value or
00252  * a 'normally' escaped character (and not eos)
00253  *
00254  * The string pointer at *s is increased by either 0 (on error), 1 (on
00255  * normal escapes), or 3 (on octals)
00256  *
00257  * Returns the number of bytes read from the escaped string, or
00258  * 0 on error
00259  */
00260 static int
00261 parse_escape(uint8_t *s, uint8_t *q) {
00262         uint16_t val;
00263         if (strlen((char *)s) > 3 &&
00264             isdigit((int) s[1]) &&
00265             isdigit((int) s[2]) &&
00266             isdigit((int) s[3])) {
00267                 /* cast this so it fits */
00268                 val = (uint16_t) ldns_hexdigit_to_int((char) s[1]) * 100 +
00269                                 ldns_hexdigit_to_int((char) s[2]) * 10 +
00270                                 ldns_hexdigit_to_int((char) s[3]);
00271                 if (val > 255) {
00272                         /* outside range */
00273                         return 0;
00274                 }
00275                 *q = (uint8_t) val;
00276                 return 3;
00277         } else {
00278                 s++;
00279                 if (*s == '\0' || isdigit((int) *s)) {
00280                         /* apparently the string terminator
00281                          * or a digit has been escaped...
00282                          */
00283                         return 0;
00284                 }
00285                 *q = *s;
00286                 return 1;
00287         }
00288 }
00289 
00290 /*
00291  * No special care is taken, all dots are translated into
00292  * label seperators.
00293  * Could be made more efficient....we do 3 memcpy's in total...
00294  */
00295 ldns_status
00296 ldns_str2rdf_dname(ldns_rdf **d, const char *str)
00297 {
00298         size_t len;
00299 
00300         int esc;
00301         uint8_t *s, *q, *pq, label_len;
00302         uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
00303         *d = NULL;
00304 
00305         len = strlen((char*)str);
00306         /* octet representation can make strings a lot longer than actual length */
00307         if (len > LDNS_MAX_DOMAINLEN * 4) {
00308                 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00309         }
00310         if (0 == len) {
00311                 return LDNS_STATUS_DOMAINNAME_UNDERFLOW;
00312         }
00313 
00314         /* root label */
00315         if (1 == len && *str == '.') {
00316                 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0");
00317                 return LDNS_STATUS_OK;
00318         }
00319 
00320         /* get on with the rest */
00321 
00322         /* s is on the current character in the string
00323          * pq points to where the labellength is going to go
00324          * label_len keeps track of the current label's length
00325          * q builds the dname inside the buf array
00326          */
00327         len = 0;
00328         q = buf+1;
00329         pq = buf;
00330         label_len = 0;
00331         for (s = (uint8_t *)str; *s; s++, q++) {
00332                 if (q > buf + LDNS_MAX_DOMAINLEN) {
00333                         return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00334                 }
00335                 *q = 0;
00336                 switch (*s) {
00337                 case '.':
00338                         if (label_len > LDNS_MAX_LABELLEN) {
00339                                 return LDNS_STATUS_LABEL_OVERFLOW;
00340                         }
00341                         if (label_len == 0) {
00342                                 return LDNS_STATUS_EMPTY_LABEL;
00343                         }
00344                         len += label_len + 1;
00345                         *pq = label_len;
00346                         label_len = 0;
00347                         pq = q;
00348                         break;
00349                 case '\\':
00350                         /* octet value or literal char */
00351                         esc = parse_escape(s, q);
00352                         if (esc > 0) {
00353                                 s += esc;
00354                                 label_len++;
00355                         } else {
00356                                 return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
00357                         }
00358                         break;
00359                 default:
00360                         *q = *s;
00361                         label_len++;
00362                 }
00363         }
00364 
00365         /* add root label if last char was not '.' */
00366         if (!ldns_dname_str_absolute(str)) {
00367                 if (q > buf + LDNS_MAX_DOMAINLEN) {
00368                         return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00369                 }
00370                 if (label_len > LDNS_MAX_LABELLEN) {
00371                         return LDNS_STATUS_LABEL_OVERFLOW;
00372                 }
00373                 if (label_len == 0) { /* label_len 0 but not . at end? */
00374                         return LDNS_STATUS_EMPTY_LABEL;
00375                 }
00376                 len += label_len + 1;
00377                 *pq = label_len;
00378                 *q = 0;
00379         }
00380         len++;
00381 
00382         *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf);
00383         return LDNS_STATUS_OK;
00384 }
00385 
00386 ldns_status
00387 ldns_str2rdf_a(ldns_rdf **rd, const char *str)
00388 {
00389         in_addr_t address;
00390         if (inet_pton(AF_INET, (char*)str, &address) != 1) {
00391                 return LDNS_STATUS_INVALID_IP4;
00392         } else {
00393                 *rd = ldns_rdf_new_frm_data(
00394                         LDNS_RDF_TYPE_A, sizeof(address), &address);
00395         }
00396         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00397 }
00398 
00399 ldns_status
00400 ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
00401 {
00402         uint8_t address[LDNS_IP6ADDRLEN + 1];
00403 
00404         if (inet_pton(AF_INET6, (char*)str, address) != 1) {
00405                 return LDNS_STATUS_INVALID_IP6;
00406         } else {
00407                 *rd = ldns_rdf_new_frm_data(
00408                         LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
00409         }
00410         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00411 }
00412 
00413 ldns_status
00414 ldns_str2rdf_str(ldns_rdf **rd, const char *str)
00415 {
00416         uint8_t *data;
00417         size_t i, str_i, esc_i;
00418 
00419         if (strlen(str) > 255) {
00420                 return LDNS_STATUS_INVALID_STR;
00421         }
00422 
00423         data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
00424         if(!data) return LDNS_STATUS_MEM_ERR;
00425         i = 1;
00426 
00427         for (str_i = 0; str_i < strlen(str); str_i++) {
00428                 if (str[str_i] == '\\') {
00429                         /* octet value or literal char */
00430                         esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]);
00431                         if (esc_i == 0) {
00432                                 LDNS_FREE(data);
00433                                 return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
00434                         }
00435                         str_i += esc_i;
00436                 } else {
00437                         data[i] = (uint8_t) str[str_i];
00438                 }
00439                 i++;
00440         }
00441         data[0] = i - 1;
00442         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data);
00443 
00444         LDNS_FREE(data);
00445         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00446 }
00447 
00448 ldns_status
00449 ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
00450 {
00451         const char *my_str = str;
00452 
00453         char *my_ip_str;
00454         size_t ip_str_len;
00455 
00456         uint16_t family;
00457         bool negation;
00458         uint8_t afdlength = 0;
00459         uint8_t *afdpart;
00460         uint8_t prefix;
00461 
00462         uint8_t *data;
00463 
00464         size_t i = 0;
00465 
00466         /* [!]afi:address/prefix */
00467         if (strlen(my_str) < 2
00468                         || strchr(my_str, ':') == NULL
00469                         || strchr(my_str, '/') == NULL
00470                         || strchr(my_str, ':') > strchr(my_str, '/')) {
00471                 return LDNS_STATUS_INVALID_STR;
00472         }
00473 
00474         if (my_str[0] == '!') {
00475                 negation = true;
00476                 my_str += 1;
00477         } else {
00478                 negation = false;
00479         }
00480 
00481         family = (uint16_t) atoi(my_str);
00482 
00483         my_str = strchr(my_str, ':') + 1;
00484 
00485         /* need ip addr and only ip addr for inet_pton */
00486         ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
00487         my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
00488         if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
00489         strncpy(my_ip_str, my_str, ip_str_len + 1);
00490         my_ip_str[ip_str_len] = '\0';
00491 
00492         if (family == 1) {
00493                 /* ipv4 */
00494                 afdpart = LDNS_XMALLOC(uint8_t, 4);
00495                 if(!afdpart) {
00496                         LDNS_FREE(my_ip_str);
00497                         return LDNS_STATUS_MEM_ERR;
00498                 }
00499                 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
00500                         LDNS_FREE(my_ip_str);
00501                         LDNS_FREE(afdpart);
00502                         return LDNS_STATUS_INVALID_STR;
00503                 }
00504                 for (i = 0; i < 4; i++) {
00505                         if (afdpart[i] != 0) {
00506                                 afdlength = i + 1;
00507                         }
00508                 }
00509         } else if (family == 2) {
00510                 /* ipv6 */
00511                 afdpart = LDNS_XMALLOC(uint8_t, 16);
00512                 if(!afdpart) {
00513                         LDNS_FREE(my_ip_str);
00514                         return LDNS_STATUS_MEM_ERR;
00515                 }
00516                 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
00517                         LDNS_FREE(my_ip_str);
00518                         LDNS_FREE(afdpart);
00519                         return LDNS_STATUS_INVALID_STR;
00520                 }
00521                 for (i = 0; i < 16; i++) {
00522                         if (afdpart[i] != 0) {
00523                                 afdlength = i + 1;
00524                         }
00525                 }
00526         } else {
00527                 /* unknown family */
00528                 LDNS_FREE(my_ip_str);
00529                 return LDNS_STATUS_INVALID_STR;
00530         }
00531 
00532         my_str = strchr(my_str, '/') + 1;
00533         prefix = (uint8_t) atoi(my_str);
00534 
00535         data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
00536         if(!data) {
00537                 LDNS_FREE(my_ip_str);
00538                 return LDNS_STATUS_INVALID_STR;
00539         }
00540         ldns_write_uint16(data, family);
00541         data[2] = prefix;
00542         data[3] = afdlength;
00543         if (negation) {
00544                 /* set bit 1 of byte 3 */
00545                 data[3] = data[3] | 0x80;
00546         }
00547 
00548         memcpy(data + 4, afdpart, afdlength);
00549 
00550         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
00551         LDNS_FREE(afdpart);
00552         LDNS_FREE(data);
00553         LDNS_FREE(my_ip_str);
00554 
00555         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00556 }
00557 
00558 ldns_status
00559 ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
00560 {
00561         uint8_t *buffer;
00562         int16_t i;
00563 
00564         buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
00565         if(!buffer) {
00566                 return LDNS_STATUS_MEM_ERR;
00567         }
00568 
00569         i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
00570                                                    ldns_b64_ntop_calculate_size(strlen(str)));
00571         if (-1 == i) {
00572                 LDNS_FREE(buffer);
00573                 return LDNS_STATUS_INVALID_B64;
00574         } else {
00575                 *rd = ldns_rdf_new_frm_data(
00576                         LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
00577         }
00578         LDNS_FREE(buffer);
00579 
00580         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00581 }
00582 
00583 ldns_status
00584 ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
00585 {
00586         uint8_t *buffer;
00587         int i;
00588         /* first byte contains length of actual b32 data */
00589         uint8_t len = ldns_b32_pton_calculate_size(strlen(str));
00590         buffer = LDNS_XMALLOC(uint8_t, len + 1);
00591         if(!buffer) {
00592                 return LDNS_STATUS_MEM_ERR;
00593         }
00594         buffer[0] = len;
00595 
00596         i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1,
00597                                                          ldns_b32_ntop_calculate_size(strlen(str)));
00598         if (i < 0) {
00599                 LDNS_FREE(buffer);
00600                 return LDNS_STATUS_INVALID_B32_EXT;
00601         } else {
00602                 *rd = ldns_rdf_new_frm_data(
00603                         LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
00604         }
00605         LDNS_FREE(buffer);
00606 
00607         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00608 }
00609 
00610 ldns_status
00611 ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
00612 {
00613         uint8_t *t, *t_orig;
00614         int i;
00615         size_t len;
00616 
00617         len = strlen(str);
00618 
00619         if (len > LDNS_MAX_RDFLEN * 2) {
00620                 return LDNS_STATUS_LABEL_OVERFLOW;
00621         } else {
00622                 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
00623                 if(!t) {
00624                         return LDNS_STATUS_MEM_ERR;
00625                 }
00626                 t_orig = t;
00627                 /* Now process octet by octet... */
00628                 while (*str) {
00629                         *t = 0;
00630                         if (isspace((int) *str)) {
00631                                 str++;
00632                         } else {
00633                                 for (i = 16; i >= 1; i -= 15) {
00634                                         while (*str && isspace((int) *str)) { str++; }
00635                                         if (*str) {
00636                                                 if (isxdigit((int) *str)) {
00637                                                         *t += ldns_hexdigit_to_int(*str) * i;
00638                                                 } else {
00639                                                         LDNS_FREE(t_orig);
00640                                                         return LDNS_STATUS_ERR;
00641                                                 }
00642                                                 ++str;
00643                                         }
00644                                 }
00645                                 ++t;
00646                         }
00647                 }
00648                 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
00649                                             (size_t) (t - t_orig),
00650                                             t_orig);
00651                 LDNS_FREE(t_orig);
00652         }
00653         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00654 }
00655 
00656 ldns_status
00657 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
00658 {
00659         const char *delimiters = "\n\t ";
00660         char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
00661         ldns_buffer *str_buf;
00662         ssize_t c;
00663         uint16_t cur_type;
00664         size_t type_count = 0;
00665         ldns_rr_type type_list[65536];
00666         if(!token) return LDNS_STATUS_MEM_ERR;
00667         if(rd == NULL) {
00668                 LDNS_FREE(token);
00669                 return LDNS_STATUS_NULL;
00670         }
00671 
00672         str_buf = LDNS_MALLOC(ldns_buffer);
00673         if(!str_buf) {
00674                 LDNS_FREE(token);
00675                 return LDNS_STATUS_MEM_ERR;
00676         }
00677         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
00678         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
00679                 LDNS_FREE(str_buf);
00680                 LDNS_FREE(token);
00681                 return LDNS_STATUS_MEM_ERR;
00682         }
00683 
00684         while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
00685                 if(type_count >= sizeof(type_list)) {
00686                         LDNS_FREE(str_buf);
00687                         LDNS_FREE(token);
00688                         return LDNS_STATUS_ERR;
00689                 }
00690                 cur_type = ldns_get_rr_type_by_name(token);
00691                 type_list[type_count] = cur_type;
00692                 type_count++;
00693         }
00694 
00695         *rd = ldns_dnssec_create_nsec_bitmap(type_list,
00696                                              type_count,
00697                                              LDNS_RR_TYPE_NSEC);
00698 
00699         LDNS_FREE(token);
00700         ldns_buffer_free(str_buf);
00701         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00702 }
00703 
00704 ldns_status
00705 ldns_str2rdf_type(ldns_rdf **rd, const char *str)
00706 {
00707         uint16_t type;
00708         type = htons(ldns_get_rr_type_by_name(str));
00709         /* ldns_rr_type is a 16 bit value */
00710         *rd = ldns_rdf_new_frm_data(
00711                 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
00712         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00713 }
00714 
00715 ldns_status
00716 ldns_str2rdf_class(ldns_rdf **rd, const char *str)
00717 {
00718         uint16_t klass;
00719         klass = htons(ldns_get_rr_class_by_name(str));
00720         /* class is 16 bit */
00721         *rd = ldns_rdf_new_frm_data(
00722                 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
00723         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
00724 }
00725 
00726 /* An certificate alg field can either be specified as a 8 bits number
00727  * or by its symbolic name. Handle both
00728  */
00729 ldns_status
00730 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
00731 {
00732         ldns_lookup_table *lt;
00733         ldns_status st;
00734         uint8_t idd[2];
00735         lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
00736         st = LDNS_STATUS_OK;
00737 
00738         if (lt) {
00739                 ldns_write_uint16(idd, (uint16_t) lt->id);
00740                 *rd = ldns_rdf_new_frm_data(
00741                         LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
00742                 if (!*rd) {
00743                         st = LDNS_STATUS_ERR;
00744                 }
00745         } else {
00746                 /* try as-is (a number) */
00747                 st = ldns_str2rdf_int16(rd, str);
00748                 if (st == LDNS_STATUS_OK &&
00749                     ldns_rdf2native_int16(*rd) == 0) {
00750                         st = LDNS_STATUS_CERT_BAD_ALGORITHM;
00751                 }
00752         }
00753 
00754         return st;
00755 }
00756 
00757 /* An alg field can either be specified as a 8 bits number
00758  * or by its symbolic name. Handle both
00759  */
00760 ldns_status
00761 ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
00762 {
00763         ldns_lookup_table *lt;
00764         ldns_status st;
00765 
00766         lt = ldns_lookup_by_name(ldns_algorithms, str);
00767         st = LDNS_STATUS_OK;
00768 
00769         if (lt) {
00770                 /* it was given as a integer */
00771                 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
00772                 if (!*rd) {
00773                         st = LDNS_STATUS_ERR;
00774                 }
00775         } else {
00776                 /* try as-is (a number) */
00777                 st = ldns_str2rdf_int8(rd, str);
00778         }
00779         return st;
00780 }
00781 
00782 ldns_status
00783 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd)
00784                     , ATTR_UNUSED(const char *str)
00785                     )
00786 {
00787         /* this should be caught in an earlier time (general str2host for
00788            rr's */
00789         return LDNS_STATUS_NOT_IMPL;
00790 }
00791 
00792 ldns_status
00793 ldns_str2rdf_tsig( ATTR_UNUSED(ldns_rdf **rd)
00794                  , ATTR_UNUSED(const char *str)
00795                  )
00796 {
00797         /* there is no string representation for TSIG rrs */
00798         return LDNS_STATUS_NOT_IMPL;
00799 }
00800 
00801 ldns_status
00802 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd)
00803                     , ATTR_UNUSED(const char *str)
00804                     )
00805 {
00806         /* is this used? is this actually WKS? or SRV? */
00807         return LDNS_STATUS_NOT_IMPL;
00808 }
00809 
00810 static int
00811 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
00812 {
00813         /* read <digits>[.<digits>][mM] */
00814         /* into mantissa exponent format for LOC type */
00815         uint32_t meters = 0, cm = 0, val;
00816         while (isblank(*my_str)) {
00817                 my_str++;
00818         }
00819         meters = (uint32_t)strtol(my_str, &my_str, 10);
00820         if (*my_str == '.') {
00821                 my_str++;
00822                 cm = (uint32_t)strtol(my_str, &my_str, 10);
00823         }
00824         if (meters >= 1) {
00825                 *e = 2;
00826                 val = meters;
00827         } else  {
00828                 *e = 0;
00829                 val = cm;
00830         }
00831         while(val >= 10) {
00832                 (*e)++;
00833                 val /= 10;
00834         }
00835         *m = (uint8_t)val;
00836 
00837         if (*e > 9)
00838                 return 0;
00839         if (*my_str == 'm' || *my_str == 'M') {
00840                 my_str++;
00841         }
00842         *endstr = my_str;
00843         return 1;
00844 }
00845 
00846 ldns_status
00847 ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
00848 {
00849         uint32_t latitude = 0;
00850         uint32_t longitude = 0;
00851         uint32_t altitude = 0;
00852 
00853         uint8_t *data;
00854         uint32_t equator = (uint32_t) ldns_power(2, 31);
00855 
00856         uint32_t h = 0;
00857         uint32_t m = 0;
00858         uint8_t size_b = 1, size_e = 2;
00859         uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
00860         uint8_t vert_pre_b = 1, vert_pre_e = 3;
00861 
00862         double s = 0.0;
00863         bool northerness;
00864         bool easterness;
00865 
00866         char *my_str = (char *) str;
00867 
00868         /* only support version 0 */
00869         if (isdigit((int) *my_str)) {
00870                 h = (uint32_t) strtol(my_str, &my_str, 10);
00871         } else {
00872                 return LDNS_STATUS_INVALID_STR;
00873         }
00874 
00875         while (isblank((int) *my_str)) {
00876                 my_str++;
00877         }
00878 
00879         if (isdigit((int) *my_str)) {
00880                 m = (uint32_t) strtol(my_str, &my_str, 10);
00881         } else if (*my_str == 'N' || *my_str == 'S') {
00882                 goto north;
00883         } else {
00884                 return LDNS_STATUS_INVALID_STR;
00885         }
00886 
00887         while (isblank((int) *my_str)) {
00888                 my_str++;
00889         }
00890 
00891         if (isdigit((int) *my_str)) {
00892                 s = strtod(my_str, &my_str);
00893         }
00894 north:
00895         while (isblank((int) *my_str)) {
00896                 my_str++;
00897         }
00898 
00899         if (*my_str == 'N') {
00900                 northerness = true;
00901         } else if (*my_str == 'S') {
00902                 northerness = false;
00903         } else {
00904                 return LDNS_STATUS_INVALID_STR;
00905         }
00906 
00907         my_str++;
00908 
00909         /* store number */
00910         s = 1000.0 * s;
00911         /* add a little to make floor in conversion a round */
00912         s += 0.0005;
00913         latitude = (uint32_t) s;
00914         latitude += 1000 * 60 * m;
00915         latitude += 1000 * 60 * 60 * h;
00916         if (northerness) {
00917                 latitude = equator + latitude;
00918         } else {
00919                 latitude = equator - latitude;
00920         }
00921         while (isblank(*my_str)) {
00922                 my_str++;
00923         }
00924 
00925         if (isdigit((int) *my_str)) {
00926                 h = (uint32_t) strtol(my_str, &my_str, 10);
00927         } else {
00928                 return LDNS_STATUS_INVALID_STR;
00929         }
00930 
00931         while (isblank((int) *my_str)) {
00932                 my_str++;
00933         }
00934 
00935         if (isdigit((int) *my_str)) {
00936                 m = (uint32_t) strtol(my_str, &my_str, 10);
00937         } else if (*my_str == 'E' || *my_str == 'W') {
00938                 goto east;
00939         } else {
00940                 return LDNS_STATUS_INVALID_STR;
00941         }
00942 
00943         while (isblank(*my_str)) {
00944                 my_str++;
00945         }
00946 
00947         if (isdigit((int) *my_str)) {
00948                 s = strtod(my_str, &my_str);
00949         }
00950 
00951 east:
00952         while (isblank(*my_str)) {
00953                 my_str++;
00954         }
00955 
00956         if (*my_str == 'E') {
00957                 easterness = true;
00958         } else if (*my_str == 'W') {
00959                 easterness = false;
00960         } else {
00961                 return LDNS_STATUS_INVALID_STR;
00962         }
00963 
00964         my_str++;
00965 
00966         /* store number */
00967         s *= 1000.0;
00968         /* add a little to make floor in conversion a round */
00969         s += 0.0005;
00970         longitude = (uint32_t) s;
00971         longitude += 1000 * 60 * m;
00972         longitude += 1000 * 60 * 60 * h;
00973 
00974         if (easterness) {
00975                 longitude += equator;
00976         } else {
00977                 longitude = equator - longitude;
00978         }
00979 
00980         altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
00981                 10000000.0 + 0.5);
00982         if (*my_str == 'm' || *my_str == 'M') {
00983                 my_str++;
00984         }
00985 
00986         if (strlen(my_str) > 0) {
00987                 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
00988                         return LDNS_STATUS_INVALID_STR;
00989         }
00990 
00991         if (strlen(my_str) > 0) {
00992                 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
00993                         return LDNS_STATUS_INVALID_STR;
00994         }
00995 
00996         if (strlen(my_str) > 0) {
00997                 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
00998                         return LDNS_STATUS_INVALID_STR;
00999         }
01000 
01001         data = LDNS_XMALLOC(uint8_t, 16);
01002         if(!data) {
01003                 return LDNS_STATUS_MEM_ERR;
01004         }
01005         data[0] = 0;
01006         data[1] = 0;
01007         data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
01008         data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
01009         data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
01010         ldns_write_uint32(data + 4, latitude);
01011         ldns_write_uint32(data + 8, longitude);
01012         ldns_write_uint32(data + 12, altitude);
01013 
01014         *rd = ldns_rdf_new_frm_data(
01015                 LDNS_RDF_TYPE_LOC, 16, data);
01016 
01017         LDNS_FREE(data);
01018         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
01019 }
01020 
01021 ldns_status
01022 ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
01023 {
01024         uint8_t *bitmap = NULL;
01025         uint8_t *data;
01026         int bm_len = 0;
01027 
01028         struct protoent *proto = NULL;
01029         struct servent *serv = NULL;
01030         int serv_port;
01031 
01032         ldns_buffer *str_buf;
01033 
01034         char *proto_str = NULL;
01035         char *token;
01036         if(strlen(str) == 0)
01037                 token = LDNS_XMALLOC(char, 50);
01038         else    token = LDNS_XMALLOC(char, strlen(str)+2);
01039         if(!token) return LDNS_STATUS_MEM_ERR;
01040 
01041         str_buf = LDNS_MALLOC(ldns_buffer);
01042         if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
01043         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
01044         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
01045                 LDNS_FREE(str_buf);
01046                 LDNS_FREE(token);
01047                 return LDNS_STATUS_MEM_ERR;
01048         }
01049 
01050         while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
01051                 if (!proto_str) {
01052                         proto_str = strdup(token);
01053                         if (!proto_str) {
01054                                 LDNS_FREE(bitmap);
01055                                 LDNS_FREE(token);
01056                                 ldns_buffer_free(str_buf);
01057                                 return LDNS_STATUS_INVALID_STR;
01058                         }
01059                 } else {
01060                         serv = getservbyname(token, proto_str);
01061                         if (serv) {
01062                                 serv_port = (int) ntohs((uint16_t) serv->s_port);
01063                         } else {
01064                                 serv_port = atoi(token);
01065                         }
01066                         if (serv_port / 8 >= bm_len) {
01067                                 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
01068                                 if(!b2) {
01069                                         LDNS_FREE(bitmap);
01070                                         LDNS_FREE(token);
01071                                         ldns_buffer_free(str_buf);
01072                                         free(proto_str);
01073                                         return LDNS_STATUS_INVALID_STR;
01074                                 }
01075                                 bitmap = b2;
01076                                 /* set to zero to be sure */
01077                                 for (; bm_len <= serv_port / 8; bm_len++) {
01078                                         bitmap[bm_len] = 0;
01079                                 }
01080                         }
01081                         ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
01082                 }
01083         }
01084 
01085         if (!proto_str || !bitmap) {
01086                 LDNS_FREE(bitmap);
01087                 LDNS_FREE(token);
01088                 ldns_buffer_free(str_buf);
01089                 free(proto_str);
01090                 return LDNS_STATUS_INVALID_STR;
01091         }
01092 
01093         data = LDNS_XMALLOC(uint8_t, bm_len + 1);
01094         if(!data) {
01095                 LDNS_FREE(token);
01096                 ldns_buffer_free(str_buf);
01097                 LDNS_FREE(bitmap);
01098                 free(proto_str);
01099                 return LDNS_STATUS_INVALID_STR;
01100         }
01101     if (proto_str)
01102                 proto = getprotobyname(proto_str);
01103         if (proto) {
01104                 data[0] = (uint8_t) proto->p_proto;
01105         } else if (proto_str) {
01106                 data[0] = (uint8_t) atoi(proto_str);
01107         } else {
01108                 data[0] = 0;
01109         }
01110         memcpy(data + 1, bitmap, (size_t) bm_len);
01111 
01112         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
01113 
01114         LDNS_FREE(data);
01115         LDNS_FREE(token);
01116         ldns_buffer_free(str_buf);
01117         LDNS_FREE(bitmap);
01118         free(proto_str);
01119 #ifdef HAVE_ENDSERVENT
01120         endservent();
01121 #endif
01122 #ifdef HAVE_ENDPROTOENT
01123         endprotoent();
01124 #endif
01125 
01126         if(!*rd) return LDNS_STATUS_MEM_ERR;
01127 
01128         return LDNS_STATUS_OK;
01129 }
01130 
01131 ldns_status
01132 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
01133 {
01134     size_t len, i;
01135     char* nsap_str = (char*) str;
01136 
01137         /* just a hex string with optional dots? */
01138         if (str[0] != '0' || str[1] != 'x') {
01139                 return LDNS_STATUS_INVALID_STR;
01140         } else {
01141                 len = strlen(str);
01142                 for (i=0; i < len; i++) {
01143                         if (nsap_str[i] == '.')
01144                                 nsap_str[i] = ' ';
01145         }
01146                 return ldns_str2rdf_hex(rd, str+2);
01147         }
01148 }
01149 
01150 ldns_status
01151 ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
01152 {
01153     size_t len, i;
01154     char* atma_str = (char*) str;
01155         ldns_status status;
01156 
01157         /* just a hex string with optional dots? */
01158         len = strlen(str);
01159         for (i=0; i < len; i++) {
01160                 if (atma_str[i] == '.')
01161                         atma_str[i] = ' ';
01162         }
01163         status = ldns_str2rdf_hex(rd, str);
01164     if (status != LDNS_STATUS_OK) {
01165                 ; /* probably in e.164 format than */
01166         }
01167         return status;
01168 }
01169 
01170 ldns_status
01171 ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
01172 {
01173         uint8_t precedence = 0;
01174         uint8_t gateway_type = 0;
01175         uint8_t algorithm = 0;
01176         char* gateway = NULL;
01177         char* publickey = NULL;
01178         uint8_t *data;
01179         ldns_buffer *str_buf;
01180         char *token;
01181         int token_count = 0;
01182         int ipseckey_len = 0;
01183         ldns_rdf* gateway_rdf = NULL;
01184         ldns_rdf* publickey_rdf = NULL;
01185         ldns_status status = LDNS_STATUS_OK;
01186         
01187         if(strlen(str) == 0)
01188                 token = LDNS_XMALLOC(char, 256);
01189         else    token = LDNS_XMALLOC(char, strlen(str)+2);
01190         if(!token) return LDNS_STATUS_MEM_ERR;
01191 
01192         str_buf = LDNS_MALLOC(ldns_buffer);
01193         if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
01194         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
01195         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
01196                 LDNS_FREE(str_buf);
01197                 LDNS_FREE(token);
01198                 return LDNS_STATUS_MEM_ERR;
01199         }
01200         while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
01201                 switch (token_count) {
01202                                 case 0:
01203                                         precedence = (uint8_t)atoi(token);
01204                                         break;
01205                                 case 1:
01206                                         gateway_type = (uint8_t)atoi(token);
01207                                         break;
01208                                 case 2:
01209                                         algorithm = (uint8_t)atoi(token);
01210                                         break;
01211                                 case 3:
01212                                         gateway = strdup(token);
01213                                         if (!gateway || (gateway_type == 0 &&
01214                                                         (token[0] != '.' || token[1] != '\0'))) {
01215                                                 LDNS_FREE(gateway);
01216                                                 LDNS_FREE(token);
01217                                                 ldns_buffer_free(str_buf);
01218                                                 return LDNS_STATUS_INVALID_STR;
01219                                         }
01220                                         break;
01221                                 case 4:
01222                                         publickey = strdup(token);
01223                                         break;
01224                                 default:
01225                                         LDNS_FREE(token);
01226                                         ldns_buffer_free(str_buf);
01227                                         return LDNS_STATUS_INVALID_STR;
01228                                         break;
01229                 }
01230                 token_count++;
01231         }
01232 
01233         if (!gateway || !publickey) {
01234                 if (gateway)
01235                         LDNS_FREE(gateway);
01236                 if (publickey)
01237                         LDNS_FREE(publickey);
01238                 LDNS_FREE(token);
01239                 ldns_buffer_free(str_buf);
01240                 return LDNS_STATUS_INVALID_STR;
01241         }
01242 
01243         if (gateway_type == 1) {
01244                 status = ldns_str2rdf_a(&gateway_rdf, gateway);
01245         } else if (gateway_type == 2) {
01246                 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
01247         } else if (gateway_type == 3) {
01248                 status = ldns_str2rdf_dname(&gateway_rdf, gateway);
01249         }
01250 
01251         if (status != LDNS_STATUS_OK) {
01252                 if (gateway)
01253                         LDNS_FREE(gateway);
01254                 if (publickey)
01255                         LDNS_FREE(publickey);
01256                 LDNS_FREE(token);
01257                 ldns_buffer_free(str_buf);
01258                 return LDNS_STATUS_INVALID_STR;
01259         }
01260 
01261         status = ldns_str2rdf_b64(&publickey_rdf, publickey);
01262 
01263         if (status != LDNS_STATUS_OK) {
01264                 if (gateway)
01265                         LDNS_FREE(gateway);
01266                 if (publickey)
01267                         LDNS_FREE(publickey);
01268                 LDNS_FREE(token);
01269                 ldns_buffer_free(str_buf);
01270                 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
01271                 return LDNS_STATUS_INVALID_STR;
01272         }
01273 
01274         /* now copy all into one ipseckey rdf */
01275         if (gateway_type)
01276                 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
01277         else
01278                 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
01279 
01280         data = LDNS_XMALLOC(uint8_t, ipseckey_len);
01281         if(!data) {
01282                 if (gateway)
01283                         LDNS_FREE(gateway);
01284                 if (publickey)
01285                         LDNS_FREE(publickey);
01286                 LDNS_FREE(token);
01287                 ldns_buffer_free(str_buf);
01288                 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
01289                 if (publickey_rdf) ldns_rdf_free(publickey_rdf);
01290                 return LDNS_STATUS_MEM_ERR;
01291         }
01292 
01293         data[0] = precedence;
01294         data[1] = gateway_type;
01295         data[2] = algorithm;
01296 
01297         if (gateway_type) {
01298                 memcpy(data + 3,
01299                         ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
01300                 memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
01301                         ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
01302         } else {
01303                 memcpy(data + 3,
01304                         ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
01305         }
01306 
01307         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
01308 
01309         if (gateway)
01310                 LDNS_FREE(gateway);
01311         if (publickey)
01312                 LDNS_FREE(publickey);
01313         LDNS_FREE(token);
01314         ldns_buffer_free(str_buf);
01315         ldns_rdf_free(gateway_rdf);
01316         ldns_rdf_free(publickey_rdf);
01317         LDNS_FREE(data);
01318         if(!*rd) return LDNS_STATUS_MEM_ERR;
01319         return LDNS_STATUS_OK;
01320 }