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 #include <sys/types.h>
00018 #include <sys/socket.h>
00019 #include <arpa/inet.h>
00020 #include <time.h>
00021 
00022 #include <errno.h>
00023 #include <netdb.h> 
00024 
00025 #include <limits.h>
00026 #ifdef HAVE_SYS_PARAM_H
00027 #include <sys/param.h>
00028 #endif
00029 
00030 ldns_status
00031 ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
00032 {
00033         char *end = NULL;    
00034         uint16_t *r;
00035         r = LDNS_MALLOC(uint16_t);
00036         
00037         *r = htons((uint16_t)strtol((char *)shortstr, &end, 0));
00038         
00039         if(*end != 0) {
00040                 LDNS_FREE(r);
00041                 return LDNS_STATUS_INVALID_INT;
00042         } else {
00043                 *rd = ldns_rdf_new_frm_data(
00044                         LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
00045                 LDNS_FREE(r);
00046                 return LDNS_STATUS_OK;
00047         }
00048 }
00049 
00050 ldns_status
00051 ldns_str2rdf_time(ldns_rdf **rd, const char *time)
00052 {
00053         /* convert a time YYYYDDMMHHMMSS to wireformat */
00054         uint16_t *r = NULL;
00055         struct tm tm;
00056         uint32_t l;
00057         char *end;
00058 
00059         /* Try to scan the time... */
00060         r = (uint16_t*)LDNS_MALLOC(uint32_t);
00061 
00062         memset(&tm, 0, sizeof(tm));
00063 
00064         if (strlen(time) == 14 &&
00065             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)
00066            ) {
00067                 tm.tm_year -= 1900;
00068                 tm.tm_mon--;
00069                 /* Check values */
00070                 if (tm.tm_year < 70) {
00071                         goto bad_format;
00072                 }
00073                 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
00074                         goto bad_format;
00075                 }
00076                 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
00077                         goto bad_format;
00078                 }
00079                 
00080                 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
00081                         goto bad_format;
00082                 }
00083 
00084                 if (tm.tm_min < 0 || tm.tm_min > 59) {
00085                         goto bad_format;
00086                 }
00087 
00088                 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
00089                         goto bad_format;
00090                 }
00091 
00092                 l = htonl(mktime_from_utc(&tm));
00093                 memcpy(r, &l, sizeof(uint32_t));
00094                 *rd = ldns_rdf_new_frm_data(
00095                         LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
00096                 LDNS_FREE(r);
00097                 return LDNS_STATUS_OK;
00098         } else {
00099                 /* handle it as 32 bits timestamp */
00100                 l = htonl((uint32_t)strtol((char*)time, &end, 0));
00101                 if(*end != 0) {
00102                         LDNS_FREE(r);
00103                         return LDNS_STATUS_ERR;
00104                 } else {
00105                         memcpy(r, &l, sizeof(uint32_t));
00106                         *rd = ldns_rdf_new_frm_data(
00107                                 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
00108                         LDNS_FREE(r);
00109                         return LDNS_STATUS_OK;
00110                 }
00111         }
00112         
00113         bad_format:
00114         LDNS_FREE(r);
00115         return LDNS_STATUS_INVALID_TIME;
00116 }
00117 
00118 ldns_status
00119 ldns_str2rdf_period(ldns_rdf **rd,const char *period)
00120 {
00121         uint32_t p;
00122         const char *end;
00123 
00124         /* Allocate required space... */
00125         p = ldns_str2period(period, &end);
00126 
00127         if (*end != 0) {
00128                 return LDNS_STATUS_ERR;
00129         } else {
00130                 p = (uint32_t) htonl(p);
00131                 *rd = ldns_rdf_new_frm_data(
00132                         LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
00133         }
00134         return LDNS_STATUS_OK;
00135 }
00136 
00137 ldns_status 
00138 ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
00139 {
00140         char *end;  
00141         uint16_t *r = NULL;
00142         uint32_t l;
00143 
00144         r = (uint16_t*)LDNS_MALLOC(uint32_t);
00145         l = htonl((uint32_t)strtol((char*)longstr, &end, 0));
00146 
00147         if(*end != 0) {
00148                 LDNS_FREE(r);
00149                 return LDNS_STATUS_ERR;
00150         } else {
00151                 memcpy(r, &l, sizeof(uint32_t));
00152                 *rd = ldns_rdf_new_frm_data(
00153                         LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
00154                 LDNS_FREE(r);
00155                 return LDNS_STATUS_OK;
00156         }
00157 }
00158 
00159 ldns_status
00160 ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
00161 {
00162         char *end;     
00163         uint8_t *r = NULL;
00164 
00165         r = LDNS_MALLOC(uint8_t);
00166  
00167         *r = (uint8_t)strtol((char*)bytestr, &end, 0);
00168 
00169         if(*end != 0) {
00170                 LDNS_FREE(r);
00171                 return LDNS_STATUS_ERR;
00172         } else {
00173                 *rd = ldns_rdf_new_frm_data(
00174                         LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
00175                 LDNS_FREE(r);
00176                 return LDNS_STATUS_OK;
00177         }
00178 }
00179 
00180 /*
00181  * No special care is taken, all dots are translated into
00182  * label seperators.
00183  * Could be made more efficient....we do 3 memcpy's in total...
00184  */
00185 ldns_status
00186 ldns_str2rdf_dname(ldns_rdf **d, const char *str)
00187 {
00188         size_t len;
00189 
00190         uint8_t *s,*p,*q, *pq, val, label_len;
00191         uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
00192         *d = NULL;
00193         
00194         len = strlen((char*)str);
00195         /* octet representation can make strings a lot longer than actual length */
00196         if (len > LDNS_MAX_DOMAINLEN * 3) {
00197                 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00198         }
00199         if (0 == len) {
00200                 return LDNS_STATUS_DOMAINNAME_UNDERFLOW;
00201         } 
00202         
00203         /* root label */
00204         if (1 == len && *str == '.') {
00205                 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); 
00206                 return LDNS_STATUS_OK;
00207         }
00208 
00209         /* get on with the rest */
00210 
00211         /* s is on the current dot
00212          * p on the previous one
00213          * q builds the dname
00214          */
00215         len = 0;
00216         q = buf+1;
00217         pq = buf;
00218         label_len = 0;
00219         for (s = p = (uint8_t *) str; *s; s++, q++) {
00220                 *q = 0;
00221                 switch (*s) {
00222                 case '.':
00223                         if (label_len > LDNS_MAX_LABELLEN) {
00224                                 return LDNS_STATUS_LABEL_OVERFLOW;
00225                         }
00226                         if (label_len == 0) {
00227                                 return LDNS_STATUS_EMPTY_LABEL;
00228                         }
00229                         len += label_len + 1;
00230                         *pq = label_len;
00231                         label_len = 0;
00232                         pq = q;
00233                         p = s+1;
00234                         break;
00235                 case '\\':
00236                         /* octet value or literal char */
00237                         if (strlen((char *)s) > 3 &&
00238                             isdigit((int) s[1]) &&
00239                             isdigit((int) s[2]) &&
00240                             isdigit((int) s[3])) {
00241                                 /* cast this so it fits */
00242                                 val = (uint8_t) ldns_hexdigit_to_int((char) s[1]) * 100 +
00243                                                 ldns_hexdigit_to_int((char) s[2]) * 10 +
00244                                                 ldns_hexdigit_to_int((char) s[3]);
00245                                 *q = val;
00246                                 s += 3;
00247                         } else {
00248                                 s++;
00249                                 *q = *s;
00250                         }
00251                         label_len++;
00252                         break;
00253                 default:
00254                         *q = *s;
00255                         label_len++;
00256                 }
00257         }
00258 
00259         /* add root label if last char was not '.' */
00260         if (!ldns_dname_str_absolute(str)) {
00261                 len += label_len + 1;
00262                 *pq = label_len;
00263                 *q = 0;
00264         }
00265         len++;
00266 
00267         *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); 
00268         return LDNS_STATUS_OK;
00269 }
00270 
00271 ldns_status
00272 ldns_str2rdf_a(ldns_rdf **rd, const char *str)
00273 {
00274         in_addr_t address;
00275         if (inet_pton(AF_INET, (char*)str, &address) != 1) {
00276                 return LDNS_STATUS_INVALID_IP4;
00277         } else {
00278                 *rd = ldns_rdf_new_frm_data(
00279                         LDNS_RDF_TYPE_A, sizeof(address), &address);
00280         }
00281         return LDNS_STATUS_OK;
00282 }
00283 
00284 ldns_status
00285 ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
00286 {
00287         uint8_t address[LDNS_IP6ADDRLEN + 1];
00288 
00289         if (inet_pton(AF_INET6, (char*)str, address) != 1) {
00290                 return LDNS_STATUS_INVALID_IP6;
00291         } else {
00292                 *rd = ldns_rdf_new_frm_data(
00293                         LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
00294         }
00295         return LDNS_STATUS_OK;
00296 }
00297 
00298 ldns_status
00299 ldns_str2rdf_str(ldns_rdf **rd, const char *str)
00300 {
00301         uint8_t *data;
00302         uint8_t val;
00303         size_t i, str_i;
00304         
00305         if (strlen(str) > 255) {
00306                 return LDNS_STATUS_INVALID_STR;
00307         }
00308 
00309         data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
00310         i = 1;
00311         for (str_i = 0; str_i < strlen(str); str_i++) {
00312                 if (str[str_i] == '\\') {
00313                         if(str_i + 3 < strlen(str) && 
00314                            isdigit(str[str_i + 1]) &&
00315                            isdigit(str[str_i + 2]) &&
00316                            isdigit(str[str_i + 3])) {
00317                                 val = (uint8_t) ldns_hexdigit_to_int((char) str[str_i + 1]) * 100 +
00318                                                 ldns_hexdigit_to_int((char) str[str_i + 2]) * 10 +
00319                                                 ldns_hexdigit_to_int((char) str[str_i + 3]);
00320                                 data[i] = val;
00321                                 i++;
00322                                 str_i += 3;
00323                         } else {
00324                                 str_i++;
00325                                 data[i] = (uint8_t) str[str_i];
00326                                 i++;
00327                         }
00328                 } else {
00329                         data[i] = (uint8_t) str[str_i];
00330                         i++;
00331                 }
00332         }
00333         data[0] = i - 1;
00334         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data);
00335         LDNS_FREE(data);
00336         return LDNS_STATUS_OK;
00337 }
00338 
00339 ldns_status
00340 ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
00341 {
00342         const char *my_str = str;
00343 
00344         char *my_ip_str;
00345         size_t ip_str_len;
00346 
00347         uint16_t family;
00348         bool negation;
00349         uint8_t afdlength = 0;
00350         uint8_t *afdpart;
00351         uint8_t prefix;
00352 
00353         uint8_t *data;
00354         
00355         size_t i = 0;
00356 
00357         /* [!]afi:address/prefix */
00358         if (strlen(my_str) < 2) {
00359                 return LDNS_STATUS_INVALID_STR;
00360         }
00361 
00362         if (my_str[0] == '!') {
00363                 negation = true;
00364                 my_str += 1;
00365         } else {
00366                 negation = false;
00367         }
00368 
00369         family = (uint16_t) atoi(my_str);
00370         
00371         my_str = strchr(my_str, ':') + 1;
00372 
00373         /* need ip addr and only ip addr for inet_pton */
00374         ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
00375         my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
00376         strncpy(my_ip_str, my_str, ip_str_len + 1);
00377         my_ip_str[ip_str_len] = '\0';
00378 
00379         if (family == 1) {
00380                 /* ipv4 */
00381                 afdpart = LDNS_XMALLOC(uint8_t, 4);
00382                 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
00383                         return LDNS_STATUS_INVALID_STR;
00384                 }
00385                 for (i = 0; i < 4; i++) {
00386                         if (afdpart[i] != 0) {
00387                                 afdlength = i + 1;
00388                         }
00389                 }
00390         } else if (family == 2) {
00391                 /* ipv6 */
00392                 afdpart = LDNS_XMALLOC(uint8_t, 16);
00393                 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
00394                         return LDNS_STATUS_INVALID_STR;
00395                 }
00396                 for (i = 0; i < 16; i++) {
00397                         if (afdpart[i] != 0) {
00398                                 afdlength = i + 1;
00399                         }
00400                 }
00401         } else {
00402                 /* unknown family */
00403                 LDNS_FREE(my_ip_str);
00404                 return LDNS_STATUS_INVALID_STR;
00405         }
00406 
00407         my_str = strchr(my_str, '/') + 1;
00408         prefix = (uint8_t) atoi(my_str);
00409 
00410         data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
00411         ldns_write_uint16(data, family);
00412         data[2] = prefix;
00413         data[3] = afdlength;
00414         if (negation) {
00415                 /* set bit 1 of byte 3 */
00416                 data[3] = data[3] | 0x80;
00417         }
00418         
00419         memcpy(data + 4, afdpart, afdlength);
00420 
00421         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
00422         LDNS_FREE(afdpart);
00423         LDNS_FREE(data);
00424         LDNS_FREE(my_ip_str);
00425 
00426         return LDNS_STATUS_OK;
00427 }
00428 
00429 ldns_status
00430 ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
00431 {
00432         uint8_t *buffer;
00433         int16_t i;
00434         
00435         buffer = LDNS_XMALLOC(uint8_t, b64_ntop_calculate_size(strlen(str)));
00436         
00437         i = (uint16_t)b64_pton((const char*)str, buffer, 
00438                                 b64_ntop_calculate_size(strlen(str)));
00439         if (-1 == i) {
00440                 LDNS_FREE(buffer);
00441                 return LDNS_STATUS_INVALID_B64;
00442         } else {
00443                 *rd = ldns_rdf_new_frm_data(
00444                         LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
00445         }
00446         LDNS_FREE(buffer);
00447 
00448         return LDNS_STATUS_OK;
00449 }
00450 
00451 ldns_status
00452 ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
00453 {
00454         uint8_t *t, *t_orig;
00455         int i;
00456         size_t len;
00457 
00458         len = strlen(str);
00459 
00460         if (len % 2 != 0) {
00461                 return LDNS_STATUS_INVALID_HEX;
00462         } else if (len > LDNS_MAX_RDFLEN * 2) {
00463                 return LDNS_STATUS_LABEL_OVERFLOW;
00464         } else {
00465                 t = LDNS_XMALLOC(uint8_t, (len / 2));
00466                 t_orig = t;
00467                 /* Now process octet by octet... */
00468                 while (*str) {
00469                         *t = 0;
00470                         for (i = 16; i >= 1; i -= 15) {
00471                                 if (isxdigit(*str)) {
00472                                         *t += ldns_hexdigit_to_int(*str) * i;
00473                                 } else {
00474                                         /* error or be lenient and skip? */
00475                                         /*return LDNS_STATUS_ERR;*/
00476                                 }
00477                                 ++str;
00478                         }
00479                         ++t;
00480                 }
00481                 t = t_orig;
00482                 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, len / 2, t);
00483                 LDNS_FREE(t);
00484         }
00485         return LDNS_STATUS_OK;
00486 }
00487 
00488 ldns_status
00489 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
00490 {
00491         const char *delimiters = "\n\t ";
00492         char token[LDNS_MAX_RDFLEN];
00493         uint8_t *bitmap = LDNS_XMALLOC(uint8_t, 1);
00494         uint16_t bm_len = 0;
00495         ldns_buffer *str_buf;
00496         ssize_t c;
00497         uint16_t cur_type;
00498         uint8_t cur_data[32];
00499         uint8_t cur_window = 0;
00500         uint8_t cur_window_max = 0;
00501         uint16_t cur_data_size = 0;
00502         uint16_t i;
00503         uint8_t *data = NULL;
00504 
00505         str_buf = LDNS_MALLOC(ldns_buffer);
00506         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
00507 
00508         bitmap[0] = 0;
00509         while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1) {
00510                 cur_type = ldns_get_rr_type_by_name(token);
00511                 if ((cur_type / 8) + 1 > bm_len) {
00512                         bitmap = LDNS_XREALLOC(bitmap, uint8_t, (cur_type / 8) + 1);
00513                         /* set to 0 */
00514                         for (; bm_len <= cur_type / 8; bm_len++) {
00515                                 bitmap[bm_len] = 0;
00516                         }
00517                 }
00518                 ldns_set_bit(bitmap + (int) cur_type / 8, (int) (7 - (cur_type % 8)), true);
00519         }
00520 
00521         memset(cur_data, 0, 32);
00522         for (i = 0; i < bm_len; i++) {
00523                 if (i / 32 > cur_window) {
00524                         /* check, copy, new */
00525                         if (cur_window_max > 0) {
00526                                 /* this window has stuff, add it */
00527                                 data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
00528                                 data[cur_data_size] = cur_window;
00529                                 data[cur_data_size + 1] = cur_window_max + 1;
00530                                 memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
00531                                 cur_data_size += cur_window_max + 3;
00532                         }
00533                         cur_window++;
00534                         cur_window_max = 0;
00535                         memset(cur_data, 0, 32);
00536                 } else {
00537                         cur_data[i%32] = bitmap[i];
00538                         if (bitmap[i] > 0) {
00539                                 cur_window_max = i%32;
00540                         }
00541                 }
00542         }
00543         if (cur_window_max > 0) {
00544                 /* this window has stuff, add it */
00545                 data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
00546                 data[cur_data_size] = cur_window;
00547                 data[cur_data_size + 1] = cur_window_max + 1;
00548                 memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
00549                 cur_data_size += cur_window_max + 3;
00550         }
00551 
00552         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data);
00553         if(data)
00554                 LDNS_FREE(data);
00555         if(bitmap)
00556                 LDNS_FREE(bitmap);
00557         ldns_buffer_free(str_buf);
00558         return LDNS_STATUS_OK;
00559 }
00560 
00561 ldns_status
00562 ldns_str2rdf_type(ldns_rdf **rd, const char *str)
00563 {
00564         uint16_t type;
00565         type = htons(ldns_get_rr_type_by_name(str));
00566         /* ldns_rr_type is a 16 bit value */
00567         *rd = ldns_rdf_new_frm_data(
00568                 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
00569         return LDNS_STATUS_OK;
00570 }
00571 
00572 ldns_status
00573 ldns_str2rdf_class(ldns_rdf **rd, const char *str)
00574 {
00575         uint16_t klass;
00576         klass = htons(ldns_get_rr_class_by_name(str));
00577         /* class is 16 bit */
00578         *rd = ldns_rdf_new_frm_data(
00579                 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
00580         return LDNS_STATUS_OK;
00581 }
00582 
00583 /* An certificate alg field can either be specified as a 8 bits number
00584  * or by its symbolic name. Handle both
00585  */
00586 ldns_status
00587 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
00588 {
00589         ldns_lookup_table *lt;
00590         ldns_status st;
00591         uint8_t idd[2];
00592         lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
00593         st = LDNS_STATUS_OK;
00594 
00595         if (lt) {
00596                 ldns_write_uint16(idd, (uint16_t) lt->id);
00597                 *rd = ldns_rdf_new_frm_data(
00598                         LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
00599                 if (!*rd) {
00600                         st = LDNS_STATUS_ERR;
00601                 }
00602         } else {
00603                 /* try as-is (a number) */
00604                 st = ldns_str2rdf_int16(rd, str);
00605                 if (st == LDNS_STATUS_OK &&
00606                     ldns_rdf2native_int16(*rd) == 0) {
00607                         st = LDNS_STATUS_CERT_BAD_ALGORITHM;
00608                 }
00609         }
00610 
00611         return st;
00612 }
00613                 
00614 /* An alg field can either be specified as a 8 bits number
00615  * or by its symbolic name. Handle both
00616  */
00617 ldns_status
00618 ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
00619 {
00620         ldns_lookup_table *lt;
00621         ldns_status st;
00622 
00623         lt = ldns_lookup_by_name(ldns_algorithms, str);
00624         st = LDNS_STATUS_OK;
00625 
00626         if (lt) {
00627                 /* it was given as a integer */
00628                 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
00629                 if (!*rd) {
00630                         st = LDNS_STATUS_ERR;
00631                 }
00632         } else {
00633                 /* try as-is (a number) */
00634                 st = ldns_str2rdf_int8(rd, str);
00635         }
00636         return st;
00637 }
00638                 
00639 ldns_status
00640 ldns_str2rdf_unknown(ldns_rdf **rd, const char *str)
00641 {
00642         /* this should be caught in an earlier time (general str2host for 
00643            rr's */
00644         rd = rd;
00645         str = str;
00646         return LDNS_STATUS_NOT_IMPL;
00647 }
00648 
00649 ldns_status
00650 ldns_str2rdf_tsig(ldns_rdf **rd, const char *str)
00651 {
00652         /* there is no strign representation for TSIG rrs */
00653         rd = rd;
00654         str = str;
00655         return LDNS_STATUS_NOT_IMPL;
00656 }
00657 
00658 ldns_status
00659 ldns_str2rdf_service(ldns_rdf **rd, const char *str)
00660 {
00661         /* is this used? is this actually WKS? or SRV? */
00662         rd = rd;
00663         str = str;
00664         return LDNS_STATUS_NOT_IMPL;
00665 }
00666 
00667 static int
00668 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
00669 {
00670         /* read <digits>[.<digits>][mM] */
00671         /* into mantissa exponent format for LOC type */
00672         uint32_t meters = 0, cm = 0, val;
00673         while (isblank(*my_str)) {
00674                 my_str++;
00675         }
00676         meters = (uint32_t)strtol(my_str, &my_str, 10);
00677         if (*my_str == '.') {
00678                 my_str++;
00679                 cm = (uint32_t)strtol(my_str, &my_str, 10);
00680         }
00681         if (meters >= 1) {
00682                 *e = 2;
00683                 val = meters;
00684         } else  {
00685                 *e = 0;
00686                 val = cm;
00687         }
00688         while(val >= 10) {
00689                 (*e)++;
00690                 val /= 10;
00691         }
00692         *m = (uint8_t)val;
00693         
00694         if (*e > 9)
00695                 return 0;
00696         if (*my_str == 'm' || *my_str == 'M') {
00697                 my_str++;
00698         }
00699         *endstr = my_str;
00700         return 1;
00701 }
00702 
00703 ldns_status
00704 ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
00705 {
00706         uint32_t latitude = 0;
00707         uint32_t longitude = 0;
00708         uint32_t altitude = 0;
00709 
00710         uint8_t *data;
00711         uint32_t equator = (uint32_t) ldns_power(2, 31);
00712 
00713         uint32_t h = 0;
00714         uint32_t m = 0;
00715         uint8_t size_b = 1, size_e = 2;
00716         uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
00717         uint8_t vert_pre_b = 1, vert_pre_e = 3;
00718         
00719         double s = 0.0;
00720         bool northerness;
00721         bool easterness;
00722 
00723         char *my_str = (char *) str;
00724 
00725         /* only support version 0 */
00726         if (isdigit(*my_str)) {
00727                 h = (uint32_t) strtol(my_str, &my_str, 10);
00728         } else {
00729                 return LDNS_STATUS_INVALID_STR;
00730         }
00731 
00732         while (isblank(*my_str)) {
00733                 my_str++;
00734         }
00735 
00736         if (isdigit(*my_str)) {
00737                 m = (uint32_t) strtol(my_str, &my_str, 10);
00738         } else if (*my_str == 'N' || *my_str == 'S') {
00739                 goto north;
00740         } else {
00741                 return LDNS_STATUS_INVALID_STR;
00742         }
00743 
00744         while (isblank(*my_str)) {
00745                 my_str++;
00746         }
00747 
00748         if (isdigit(*my_str)) {
00749                 s = strtod(my_str, &my_str);
00750         }
00751 north:
00752         while (isblank(*my_str)) {
00753                 my_str++;
00754         }
00755 
00756         if (*my_str == 'N') {
00757                 northerness = true;
00758         } else if (*my_str == 'S') {
00759                 northerness = false;
00760         } else {
00761                 return LDNS_STATUS_INVALID_STR;
00762         }
00763 
00764         my_str++;
00765 
00766         /* store number */
00767         s = 1000.0 * s;
00768         /* add a little to make floor in conversion a round */
00769         s += 0.0005;
00770         latitude = (uint32_t) s;
00771         latitude += 1000 * 60 * m;
00772         latitude += 1000 * 60 * 60 * h;
00773         if (northerness) {
00774                 latitude = equator + latitude;
00775         } else {
00776                 latitude = equator - latitude;
00777         }
00778         while (isblank(*my_str)) {
00779                 my_str++;
00780         }
00781 
00782         if (isdigit(*my_str)) {
00783                 h = (uint32_t) strtol(my_str, &my_str, 10);
00784         } else {
00785                 return LDNS_STATUS_INVALID_STR;
00786         }
00787 
00788         while (isblank(*my_str)) {
00789                 my_str++;
00790         }
00791 
00792         if (isdigit(*my_str)) {
00793                 m = (uint32_t) strtol(my_str, &my_str, 10);
00794         } else if (*my_str == 'E' || *my_str == 'W') {
00795                 goto east;
00796         } else {
00797                 return LDNS_STATUS_INVALID_STR;
00798         }
00799 
00800         while (isblank(*my_str)) {
00801                 my_str++;
00802         }
00803 
00804         if (isdigit(*my_str)) {
00805                 s = strtod(my_str, &my_str);
00806         }
00807 
00808 east:
00809         while (isblank(*my_str)) {
00810                 my_str++;
00811         }
00812 
00813         if (*my_str == 'E') {
00814                 easterness = true;
00815         } else if (*my_str == 'W') {
00816                 easterness = false;
00817         } else {
00818                 return LDNS_STATUS_INVALID_STR;
00819         }
00820 
00821         my_str++;
00822 
00823         /* store number */
00824         s *= 1000.0;
00825         /* add a little to make floor in conversion a round */
00826         s += 0.0005;
00827         longitude = (uint32_t) s;
00828         longitude += 1000 * 60 * m;
00829         longitude += 1000 * 60 * 60 * h;
00830 
00831         if (easterness) {
00832                 longitude += equator;
00833         } else {
00834                 longitude = equator - longitude;
00835         }
00836 
00837         altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
00838                 10000000.0 + 0.5);
00839         if (*my_str == 'm' || *my_str == 'M') {
00840                 my_str++;
00841         }
00842 
00843         if (strlen(my_str) > 0) {
00844                 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
00845                         return LDNS_STATUS_INVALID_STR;
00846         }
00847 
00848         if (strlen(my_str) > 0) {
00849                 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
00850                         return LDNS_STATUS_INVALID_STR;
00851         }
00852 
00853         if (strlen(my_str) > 0) {
00854                 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
00855                         return LDNS_STATUS_INVALID_STR;
00856         }
00857 
00858         data = LDNS_XMALLOC(uint8_t, 16);
00859         data[0] = 0;
00860         data[1] = 0;
00861         data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
00862         data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
00863         data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
00864         ldns_write_uint32(data + 4, latitude);
00865         ldns_write_uint32(data + 8, longitude);
00866         ldns_write_uint32(data + 12, altitude);
00867 
00868         *rd = ldns_rdf_new_frm_data(
00869                 LDNS_RDF_TYPE_LOC, 16, data);
00870 
00871         LDNS_FREE(data);
00872         return LDNS_STATUS_OK;
00873 }
00874 
00875 ldns_status
00876 ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
00877 {
00878         uint8_t *bitmap = NULL;
00879         uint8_t *data;
00880         int bm_len = 0;
00881         
00882         struct protoent *proto = NULL;
00883         struct servent *serv = NULL;
00884         int serv_port;
00885         
00886         ldns_buffer *str_buf;
00887         
00888         char *proto_str = NULL;
00889         char *token = LDNS_XMALLOC(char, 50);
00890         
00891         str_buf = LDNS_MALLOC(ldns_buffer);
00892         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
00893 
00894         while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
00895                 if (!proto_str) {
00896                         proto_str = strdup(token);
00897                         if (!proto_str) {
00898                                 LDNS_FREE(token);
00899                                 LDNS_FREE(str_buf);
00900                                 return LDNS_STATUS_INVALID_STR;
00901                         }
00902                 } else {
00903                         serv = getservbyname(token, proto_str);
00904                         if (serv) {
00905                                 serv_port = (int) ntohs((uint16_t) serv->s_port);
00906                         } else {
00907                                 serv_port = atoi(token);
00908                         }
00909                         if (serv_port / 8 > bm_len) {
00910                                 bitmap = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
00911                                 /* set to zero to be sure */
00912                                 for (; bm_len <= serv_port / 8; bm_len++) {
00913                                         bitmap[bm_len] = 0;
00914                                 }
00915                         }
00916                         ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
00917                 }
00918         }
00919         
00920         data = LDNS_XMALLOC(uint8_t, bm_len + 1);
00921         proto = getprotobyname(proto_str);
00922         if (proto) {
00923                 data[0] = (uint8_t) proto->p_proto;
00924         } else {
00925                 data[0] = (uint8_t) atoi(proto_str);
00926         }
00927         memcpy(data + 1, bitmap, (size_t) bm_len);
00928         
00929         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
00930 
00931         LDNS_FREE(token);
00932         ldns_buffer_free(str_buf);
00933         LDNS_FREE(bitmap);
00934         LDNS_FREE(data);
00935         free(proto_str);
00936         endservent();
00937         endprotoent();
00938         
00939         return LDNS_STATUS_OK;
00940 }
00941 
00942 ldns_status
00943 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
00944 {
00945         /* just a hex string with optional dots? */
00946         if (str[0] != '0' || str[1] != 'x') {
00947                 return LDNS_STATUS_INVALID_STR;
00948         } else {
00949                 return ldns_str2rdf_hex(rd, str+2);
00950         }
00951 }

Generated on Tue Nov 20 07:14:15 2007 for ldns by  doxygen 1.5.3-20071008