1*09a3aaf3SDag-Erling Smørgrav /** 2*09a3aaf3SDag-Erling Smørgrav * str2wire.c - read txt presentation of RRs 3*09a3aaf3SDag-Erling Smørgrav * 4*09a3aaf3SDag-Erling Smørgrav * (c) NLnet Labs, 2005-2006 5*09a3aaf3SDag-Erling Smørgrav * 6*09a3aaf3SDag-Erling Smørgrav * See the file LICENSE for the license 7*09a3aaf3SDag-Erling Smørgrav */ 8*09a3aaf3SDag-Erling Smørgrav 9*09a3aaf3SDag-Erling Smørgrav /** 10*09a3aaf3SDag-Erling Smørgrav * \file 11*09a3aaf3SDag-Erling Smørgrav * 12*09a3aaf3SDag-Erling Smørgrav * Parses text to wireformat. 13*09a3aaf3SDag-Erling Smørgrav */ 14*09a3aaf3SDag-Erling Smørgrav #include "config.h" 15*09a3aaf3SDag-Erling Smørgrav #include "sldns/str2wire.h" 16*09a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h" 17*09a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 18*09a3aaf3SDag-Erling Smørgrav #include "sldns/parse.h" 19*09a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h" 20*09a3aaf3SDag-Erling Smørgrav #include <ctype.h> 21*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_TIME_H 22*09a3aaf3SDag-Erling Smørgrav #include <time.h> 23*09a3aaf3SDag-Erling Smørgrav #endif 24*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_NETDB_H 25*09a3aaf3SDag-Erling Smørgrav #include <netdb.h> 26*09a3aaf3SDag-Erling Smørgrav #endif 27*09a3aaf3SDag-Erling Smørgrav 28*09a3aaf3SDag-Erling Smørgrav /** return an error */ 29*09a3aaf3SDag-Erling Smørgrav #define RET_ERR(e, off) ((int)((e)|((off)<<LDNS_WIREPARSE_SHIFT))) 30*09a3aaf3SDag-Erling Smørgrav /** Move parse error but keep its ID */ 31*09a3aaf3SDag-Erling Smørgrav #define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move)); 32*09a3aaf3SDag-Erling Smørgrav #define LDNS_IP6ADDRLEN (128/8) 33*09a3aaf3SDag-Erling Smørgrav 34*09a3aaf3SDag-Erling Smørgrav /* 35*09a3aaf3SDag-Erling Smørgrav * No special care is taken, all dots are translated into 36*09a3aaf3SDag-Erling Smørgrav * label separators. 37*09a3aaf3SDag-Erling Smørgrav * @param rel: true if the domain is not absolute (not terminated in .). 38*09a3aaf3SDag-Erling Smørgrav * The output is then still terminated with a '0' rootlabel. 39*09a3aaf3SDag-Erling Smørgrav */ 40*09a3aaf3SDag-Erling Smørgrav static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, 41*09a3aaf3SDag-Erling Smørgrav size_t* olen, int* rel) 42*09a3aaf3SDag-Erling Smørgrav { 43*09a3aaf3SDag-Erling Smørgrav size_t len; 44*09a3aaf3SDag-Erling Smørgrav 45*09a3aaf3SDag-Erling Smørgrav const char *s; 46*09a3aaf3SDag-Erling Smørgrav uint8_t *q, *pq, label_len; 47*09a3aaf3SDag-Erling Smørgrav 48*09a3aaf3SDag-Erling Smørgrav if(rel) *rel = 0; 49*09a3aaf3SDag-Erling Smørgrav len = strlen((char*)str); 50*09a3aaf3SDag-Erling Smørgrav /* octet representation can make strings a lot longer than actual length */ 51*09a3aaf3SDag-Erling Smørgrav if (len > LDNS_MAX_DOMAINLEN * 4) { 52*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0); 53*09a3aaf3SDag-Erling Smørgrav } 54*09a3aaf3SDag-Erling Smørgrav if (0 == len) { 55*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0); 56*09a3aaf3SDag-Erling Smørgrav } 57*09a3aaf3SDag-Erling Smørgrav 58*09a3aaf3SDag-Erling Smørgrav /* root label */ 59*09a3aaf3SDag-Erling Smørgrav if (1 == len && *str == '.') { 60*09a3aaf3SDag-Erling Smørgrav if(*olen < 1) 61*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 62*09a3aaf3SDag-Erling Smørgrav buf[0] = 0; 63*09a3aaf3SDag-Erling Smørgrav *olen = 1; 64*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 65*09a3aaf3SDag-Erling Smørgrav } 66*09a3aaf3SDag-Erling Smørgrav 67*09a3aaf3SDag-Erling Smørgrav /* get on with the rest */ 68*09a3aaf3SDag-Erling Smørgrav 69*09a3aaf3SDag-Erling Smørgrav /* s is on the current character in the string 70*09a3aaf3SDag-Erling Smørgrav * pq points to where the labellength is going to go 71*09a3aaf3SDag-Erling Smørgrav * label_len keeps track of the current label's length 72*09a3aaf3SDag-Erling Smørgrav * q builds the dname inside the buf array 73*09a3aaf3SDag-Erling Smørgrav */ 74*09a3aaf3SDag-Erling Smørgrav len = 0; 75*09a3aaf3SDag-Erling Smørgrav if(*olen < 1) 76*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 77*09a3aaf3SDag-Erling Smørgrav q = buf+1; 78*09a3aaf3SDag-Erling Smørgrav pq = buf; 79*09a3aaf3SDag-Erling Smørgrav label_len = 0; 80*09a3aaf3SDag-Erling Smørgrav for (s = str; *s; s++, q++) { 81*09a3aaf3SDag-Erling Smørgrav if (q >= buf + *olen) 82*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 83*09a3aaf3SDag-Erling Smørgrav if (q > buf + LDNS_MAX_DOMAINLEN) 84*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 85*09a3aaf3SDag-Erling Smørgrav switch (*s) { 86*09a3aaf3SDag-Erling Smørgrav case '.': 87*09a3aaf3SDag-Erling Smørgrav if (label_len > LDNS_MAX_LABELLEN) { 88*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 89*09a3aaf3SDag-Erling Smørgrav } 90*09a3aaf3SDag-Erling Smørgrav if (label_len == 0) { 91*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 92*09a3aaf3SDag-Erling Smørgrav } 93*09a3aaf3SDag-Erling Smørgrav len += label_len + 1; 94*09a3aaf3SDag-Erling Smørgrav *q = 0; 95*09a3aaf3SDag-Erling Smørgrav *pq = label_len; 96*09a3aaf3SDag-Erling Smørgrav label_len = 0; 97*09a3aaf3SDag-Erling Smørgrav pq = q; 98*09a3aaf3SDag-Erling Smørgrav break; 99*09a3aaf3SDag-Erling Smørgrav case '\\': 100*09a3aaf3SDag-Erling Smørgrav /* octet value or literal char */ 101*09a3aaf3SDag-Erling Smørgrav s += 1; 102*09a3aaf3SDag-Erling Smørgrav if (!sldns_parse_escape(q, &s)) { 103*09a3aaf3SDag-Erling Smørgrav *q = 0; 104*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf); 105*09a3aaf3SDag-Erling Smørgrav } 106*09a3aaf3SDag-Erling Smørgrav s -= 1; 107*09a3aaf3SDag-Erling Smørgrav label_len++; 108*09a3aaf3SDag-Erling Smørgrav break; 109*09a3aaf3SDag-Erling Smørgrav default: 110*09a3aaf3SDag-Erling Smørgrav *q = (uint8_t)*s; 111*09a3aaf3SDag-Erling Smørgrav label_len++; 112*09a3aaf3SDag-Erling Smørgrav } 113*09a3aaf3SDag-Erling Smørgrav } 114*09a3aaf3SDag-Erling Smørgrav 115*09a3aaf3SDag-Erling Smørgrav /* add root label if last char was not '.' */ 116*09a3aaf3SDag-Erling Smørgrav if(label_len != 0) { 117*09a3aaf3SDag-Erling Smørgrav if(rel) *rel = 1; 118*09a3aaf3SDag-Erling Smørgrav if (q >= buf + *olen) 119*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 120*09a3aaf3SDag-Erling Smørgrav if (q > buf + LDNS_MAX_DOMAINLEN) { 121*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 122*09a3aaf3SDag-Erling Smørgrav } 123*09a3aaf3SDag-Erling Smørgrav if (label_len > LDNS_MAX_LABELLEN) { 124*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 125*09a3aaf3SDag-Erling Smørgrav } 126*09a3aaf3SDag-Erling Smørgrav if (label_len == 0) { /* label_len 0 but not . at end? */ 127*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 128*09a3aaf3SDag-Erling Smørgrav } 129*09a3aaf3SDag-Erling Smørgrav len += label_len + 1; 130*09a3aaf3SDag-Erling Smørgrav *pq = label_len; 131*09a3aaf3SDag-Erling Smørgrav *q = 0; 132*09a3aaf3SDag-Erling Smørgrav } 133*09a3aaf3SDag-Erling Smørgrav len++; 134*09a3aaf3SDag-Erling Smørgrav *olen = len; 135*09a3aaf3SDag-Erling Smørgrav 136*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 137*09a3aaf3SDag-Erling Smørgrav } 138*09a3aaf3SDag-Erling Smørgrav 139*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len) 140*09a3aaf3SDag-Erling Smørgrav { 141*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_dname_buf_rel(str, buf, len, NULL); 142*09a3aaf3SDag-Erling Smørgrav } 143*09a3aaf3SDag-Erling Smørgrav 144*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, 145*09a3aaf3SDag-Erling Smørgrav uint8_t* origin, size_t origin_len) 146*09a3aaf3SDag-Erling Smørgrav { 147*09a3aaf3SDag-Erling Smørgrav size_t dlen = *len; 148*09a3aaf3SDag-Erling Smørgrav int rel = 0; 149*09a3aaf3SDag-Erling Smørgrav int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel); 150*09a3aaf3SDag-Erling Smørgrav if(s) return s; 151*09a3aaf3SDag-Erling Smørgrav 152*09a3aaf3SDag-Erling Smørgrav if(rel && origin && dlen > 0) { 153*09a3aaf3SDag-Erling Smørgrav if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN) 154*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 155*09a3aaf3SDag-Erling Smørgrav LDNS_MAX_DOMAINLEN); 156*09a3aaf3SDag-Erling Smørgrav if(dlen + origin_len - 1 > *len) 157*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 158*09a3aaf3SDag-Erling Smørgrav *len); 159*09a3aaf3SDag-Erling Smørgrav memmove(buf+dlen-1, origin, origin_len); 160*09a3aaf3SDag-Erling Smørgrav *len = dlen + origin_len - 1; 161*09a3aaf3SDag-Erling Smørgrav } else 162*09a3aaf3SDag-Erling Smørgrav *len = dlen; 163*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 164*09a3aaf3SDag-Erling Smørgrav } 165*09a3aaf3SDag-Erling Smørgrav 166*09a3aaf3SDag-Erling Smørgrav uint8_t* sldns_str2wire_dname(const char* str, size_t* len) 167*09a3aaf3SDag-Erling Smørgrav { 168*09a3aaf3SDag-Erling Smørgrav uint8_t dname[LDNS_MAX_DOMAINLEN+1]; 169*09a3aaf3SDag-Erling Smørgrav *len = sizeof(dname); 170*09a3aaf3SDag-Erling Smørgrav if(sldns_str2wire_dname_buf(str, dname, len) == 0) { 171*09a3aaf3SDag-Erling Smørgrav uint8_t* r = (uint8_t*)malloc(*len); 172*09a3aaf3SDag-Erling Smørgrav if(r) return memcpy(r, dname, *len); 173*09a3aaf3SDag-Erling Smørgrav } 174*09a3aaf3SDag-Erling Smørgrav *len = 0; 175*09a3aaf3SDag-Erling Smørgrav return NULL; 176*09a3aaf3SDag-Erling Smørgrav } 177*09a3aaf3SDag-Erling Smørgrav 178*09a3aaf3SDag-Erling Smørgrav /** read owner name */ 179*09a3aaf3SDag-Erling Smørgrav static int 180*09a3aaf3SDag-Erling Smørgrav rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len, 181*09a3aaf3SDag-Erling Smørgrav size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 182*09a3aaf3SDag-Erling Smørgrav size_t prev_len, char* token, size_t token_len) 183*09a3aaf3SDag-Erling Smørgrav { 184*09a3aaf3SDag-Erling Smørgrav /* split the rr in its parts -1 signals trouble */ 185*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 186*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 187*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 188*09a3aaf3SDag-Erling Smørgrav } 189*09a3aaf3SDag-Erling Smørgrav 190*09a3aaf3SDag-Erling Smørgrav if(strcmp(token, "@") == 0) { 191*09a3aaf3SDag-Erling Smørgrav uint8_t* tocopy; 192*09a3aaf3SDag-Erling Smørgrav if (origin) { 193*09a3aaf3SDag-Erling Smørgrav *dname_len = origin_len; 194*09a3aaf3SDag-Erling Smørgrav tocopy = origin; 195*09a3aaf3SDag-Erling Smørgrav } else if (prev) { 196*09a3aaf3SDag-Erling Smørgrav *dname_len = prev_len; 197*09a3aaf3SDag-Erling Smørgrav tocopy = prev; 198*09a3aaf3SDag-Erling Smørgrav } else { 199*09a3aaf3SDag-Erling Smørgrav /* default to root */ 200*09a3aaf3SDag-Erling Smørgrav *dname_len = 1; 201*09a3aaf3SDag-Erling Smørgrav tocopy = (uint8_t*)"\0"; 202*09a3aaf3SDag-Erling Smørgrav } 203*09a3aaf3SDag-Erling Smørgrav if(*len < *dname_len) 204*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 205*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 206*09a3aaf3SDag-Erling Smørgrav memmove(rr, tocopy, *dname_len); 207*09a3aaf3SDag-Erling Smørgrav } else if(strlen(token) == 0) { 208*09a3aaf3SDag-Erling Smørgrav /* no ownername was given, try prev, if that fails 209*09a3aaf3SDag-Erling Smørgrav * origin, else default to root */ 210*09a3aaf3SDag-Erling Smørgrav uint8_t* tocopy; 211*09a3aaf3SDag-Erling Smørgrav if(prev) { 212*09a3aaf3SDag-Erling Smørgrav *dname_len = prev_len; 213*09a3aaf3SDag-Erling Smørgrav tocopy = prev; 214*09a3aaf3SDag-Erling Smørgrav } else if(origin) { 215*09a3aaf3SDag-Erling Smørgrav *dname_len = origin_len; 216*09a3aaf3SDag-Erling Smørgrav tocopy = origin; 217*09a3aaf3SDag-Erling Smørgrav } else { 218*09a3aaf3SDag-Erling Smørgrav *dname_len = 1; 219*09a3aaf3SDag-Erling Smørgrav tocopy = (uint8_t*)"\0"; 220*09a3aaf3SDag-Erling Smørgrav } 221*09a3aaf3SDag-Erling Smørgrav if(*len < *dname_len) 222*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 223*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 224*09a3aaf3SDag-Erling Smørgrav memmove(rr, tocopy, *dname_len); 225*09a3aaf3SDag-Erling Smørgrav } else { 226*09a3aaf3SDag-Erling Smørgrav size_t dlen = *len; 227*09a3aaf3SDag-Erling Smørgrav int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen, 228*09a3aaf3SDag-Erling Smørgrav origin, origin_len); 229*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, 230*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)-strlen(token)); 231*09a3aaf3SDag-Erling Smørgrav *dname_len = dlen; 232*09a3aaf3SDag-Erling Smørgrav } 233*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 234*09a3aaf3SDag-Erling Smørgrav } 235*09a3aaf3SDag-Erling Smørgrav 236*09a3aaf3SDag-Erling Smørgrav /** read ttl */ 237*09a3aaf3SDag-Erling Smørgrav static int 238*09a3aaf3SDag-Erling Smørgrav rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, 239*09a3aaf3SDag-Erling Smørgrav int* not_there, uint32_t* ttl, uint32_t default_ttl) 240*09a3aaf3SDag-Erling Smørgrav { 241*09a3aaf3SDag-Erling Smørgrav const char* endptr; 242*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 243*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, 244*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 245*09a3aaf3SDag-Erling Smørgrav } 246*09a3aaf3SDag-Erling Smørgrav *ttl = (uint32_t) sldns_str2period(token, &endptr); 247*09a3aaf3SDag-Erling Smørgrav 248*09a3aaf3SDag-Erling Smørgrav if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { 249*09a3aaf3SDag-Erling Smørgrav *not_there = 1; 250*09a3aaf3SDag-Erling Smørgrav /* ah, it's not there or something */ 251*09a3aaf3SDag-Erling Smørgrav if (default_ttl == 0) { 252*09a3aaf3SDag-Erling Smørgrav *ttl = LDNS_DEFAULT_TTL; 253*09a3aaf3SDag-Erling Smørgrav } else { 254*09a3aaf3SDag-Erling Smørgrav *ttl = default_ttl; 255*09a3aaf3SDag-Erling Smørgrav } 256*09a3aaf3SDag-Erling Smørgrav } 257*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 258*09a3aaf3SDag-Erling Smørgrav } 259*09a3aaf3SDag-Erling Smørgrav 260*09a3aaf3SDag-Erling Smørgrav /** read class */ 261*09a3aaf3SDag-Erling Smørgrav static int 262*09a3aaf3SDag-Erling Smørgrav rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len, 263*09a3aaf3SDag-Erling Smørgrav int* not_there, uint16_t* cl) 264*09a3aaf3SDag-Erling Smørgrav { 265*09a3aaf3SDag-Erling Smørgrav /* if 'not_there' then we got token from previous parse routine */ 266*09a3aaf3SDag-Erling Smørgrav if(!*not_there) { 267*09a3aaf3SDag-Erling Smørgrav /* parse new token for class */ 268*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 269*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS, 270*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 271*09a3aaf3SDag-Erling Smørgrav } 272*09a3aaf3SDag-Erling Smørgrav } else *not_there = 0; 273*09a3aaf3SDag-Erling Smørgrav *cl = sldns_get_rr_class_by_name(token); 274*09a3aaf3SDag-Erling Smørgrav /* class can be left out too, assume IN, current token must be type */ 275*09a3aaf3SDag-Erling Smørgrav if(*cl == 0 && strcmp(token, "CLASS0") != 0) { 276*09a3aaf3SDag-Erling Smørgrav *not_there = 1; 277*09a3aaf3SDag-Erling Smørgrav *cl = LDNS_RR_CLASS_IN; 278*09a3aaf3SDag-Erling Smørgrav } 279*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 280*09a3aaf3SDag-Erling Smørgrav } 281*09a3aaf3SDag-Erling Smørgrav 282*09a3aaf3SDag-Erling Smørgrav /** read type */ 283*09a3aaf3SDag-Erling Smørgrav static int 284*09a3aaf3SDag-Erling Smørgrav rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len, 285*09a3aaf3SDag-Erling Smørgrav int* not_there, uint16_t* tp) 286*09a3aaf3SDag-Erling Smørgrav { 287*09a3aaf3SDag-Erling Smørgrav /* if 'not_there' then we got token from previous parse routine */ 288*09a3aaf3SDag-Erling Smørgrav if(!*not_there) { 289*09a3aaf3SDag-Erling Smørgrav /* parse new token for type */ 290*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 291*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 292*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 293*09a3aaf3SDag-Erling Smørgrav } 294*09a3aaf3SDag-Erling Smørgrav } 295*09a3aaf3SDag-Erling Smørgrav *tp = sldns_get_rr_type_by_name(token); 296*09a3aaf3SDag-Erling Smørgrav if(*tp == 0 && strcmp(token, "TYPE0") != 0) { 297*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 298*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 299*09a3aaf3SDag-Erling Smørgrav } 300*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 301*09a3aaf3SDag-Erling Smørgrav } 302*09a3aaf3SDag-Erling Smørgrav 303*09a3aaf3SDag-Erling Smørgrav /** put type, class, ttl into rr buffer */ 304*09a3aaf3SDag-Erling Smørgrav static int 305*09a3aaf3SDag-Erling Smørgrav rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len, 306*09a3aaf3SDag-Erling Smørgrav size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question) 307*09a3aaf3SDag-Erling Smørgrav { 308*09a3aaf3SDag-Erling Smørgrav if(question) { 309*09a3aaf3SDag-Erling Smørgrav /* question is : name, type, class */ 310*09a3aaf3SDag-Erling Smørgrav if(dname_len + 4 > len) 311*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 312*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 313*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len, tp); 314*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len+2, cl); 315*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 316*09a3aaf3SDag-Erling Smørgrav } 317*09a3aaf3SDag-Erling Smørgrav 318*09a3aaf3SDag-Erling Smørgrav /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */ 319*09a3aaf3SDag-Erling Smørgrav if(dname_len + 10 > len) 320*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 321*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 322*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len, tp); 323*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len+2, cl); 324*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rr+dname_len+4, ttl); 325*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */ 326*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 327*09a3aaf3SDag-Erling Smørgrav } 328*09a3aaf3SDag-Erling Smørgrav 329*09a3aaf3SDag-Erling Smørgrav /** find delimiters for type */ 330*09a3aaf3SDag-Erling Smørgrav static const char* 331*09a3aaf3SDag-Erling Smørgrav rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max) 332*09a3aaf3SDag-Erling Smørgrav { 333*09a3aaf3SDag-Erling Smørgrav switch(rdftype) { 334*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_B64 : 335*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ 336*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ 337*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ 338*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_IPSECKEY : 339*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { 340*09a3aaf3SDag-Erling Smørgrav return "\n"; 341*09a3aaf3SDag-Erling Smørgrav } 342*09a3aaf3SDag-Erling Smørgrav break; 343*09a3aaf3SDag-Erling Smørgrav default : break; 344*09a3aaf3SDag-Erling Smørgrav } 345*09a3aaf3SDag-Erling Smørgrav return "\n\t "; 346*09a3aaf3SDag-Erling Smørgrav } 347*09a3aaf3SDag-Erling Smørgrav 348*09a3aaf3SDag-Erling Smørgrav /* Syntactic sugar for sldns_rr_new_frm_str_internal */ 349*09a3aaf3SDag-Erling Smørgrav static int 350*09a3aaf3SDag-Erling Smørgrav sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) 351*09a3aaf3SDag-Erling Smørgrav { 352*09a3aaf3SDag-Erling Smørgrav return rdf_type == LDNS_RDF_TYPE_STR || 353*09a3aaf3SDag-Erling Smørgrav rdf_type == LDNS_RDF_TYPE_LONG_STR; 354*09a3aaf3SDag-Erling Smørgrav } 355*09a3aaf3SDag-Erling Smørgrav 356*09a3aaf3SDag-Erling Smørgrav /** see if rdata is quoted */ 357*09a3aaf3SDag-Erling Smørgrav static int 358*09a3aaf3SDag-Erling Smørgrav rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, 359*09a3aaf3SDag-Erling Smørgrav sldns_rdf_type rdftype) 360*09a3aaf3SDag-Erling Smørgrav { 361*09a3aaf3SDag-Erling Smørgrav if(sldns_rdf_type_maybe_quoted(rdftype) && 362*09a3aaf3SDag-Erling Smørgrav sldns_buffer_remaining(strbuf) > 0) { 363*09a3aaf3SDag-Erling Smørgrav 364*09a3aaf3SDag-Erling Smørgrav /* skip spaces */ 365*09a3aaf3SDag-Erling Smørgrav while(sldns_buffer_remaining(strbuf) > 0 && 366*09a3aaf3SDag-Erling Smørgrav *(sldns_buffer_current(strbuf)) == ' ') { 367*09a3aaf3SDag-Erling Smørgrav sldns_buffer_skip(strbuf, 1); 368*09a3aaf3SDag-Erling Smørgrav } 369*09a3aaf3SDag-Erling Smørgrav 370*09a3aaf3SDag-Erling Smørgrav if(sldns_buffer_remaining(strbuf) > 0 && 371*09a3aaf3SDag-Erling Smørgrav *(sldns_buffer_current(strbuf)) == '\"') { 372*09a3aaf3SDag-Erling Smørgrav *delimiters = "\"\0"; 373*09a3aaf3SDag-Erling Smørgrav sldns_buffer_skip(strbuf, 1); 374*09a3aaf3SDag-Erling Smørgrav return 1; 375*09a3aaf3SDag-Erling Smørgrav } 376*09a3aaf3SDag-Erling Smørgrav } 377*09a3aaf3SDag-Erling Smørgrav return 0; 378*09a3aaf3SDag-Erling Smørgrav } 379*09a3aaf3SDag-Erling Smørgrav 380*09a3aaf3SDag-Erling Smørgrav /** spool hex data into rdata */ 381*09a3aaf3SDag-Erling Smørgrav static int 382*09a3aaf3SDag-Erling Smørgrav rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, 383*09a3aaf3SDag-Erling Smørgrav size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size) 384*09a3aaf3SDag-Erling Smørgrav { 385*09a3aaf3SDag-Erling Smørgrav char* p = token; 386*09a3aaf3SDag-Erling Smørgrav while(*p) { 387*09a3aaf3SDag-Erling Smørgrav if(isspace((unsigned char)*p)) { 388*09a3aaf3SDag-Erling Smørgrav p++; 389*09a3aaf3SDag-Erling Smørgrav continue; 390*09a3aaf3SDag-Erling Smørgrav } 391*09a3aaf3SDag-Erling Smørgrav if(!isxdigit((unsigned char)*p)) 392*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 393*09a3aaf3SDag-Erling Smørgrav p-token); 394*09a3aaf3SDag-Erling Smørgrav if(*cur_hex_data_size >= hex_data_size) 395*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 396*09a3aaf3SDag-Erling Smørgrav p-token); 397*09a3aaf3SDag-Erling Smørgrav /* extra robust check */ 398*09a3aaf3SDag-Erling Smørgrav if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len) 399*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 400*09a3aaf3SDag-Erling Smørgrav p-token); 401*09a3aaf3SDag-Erling Smørgrav /* see if 16s or 1s */ 402*09a3aaf3SDag-Erling Smørgrav if( ((*cur_hex_data_size)&1) == 0) { 403*09a3aaf3SDag-Erling Smørgrav rr[rr_cur_len+(*cur_hex_data_size)/2] = 404*09a3aaf3SDag-Erling Smørgrav (uint8_t)sldns_hexdigit_to_int(*p)*16; 405*09a3aaf3SDag-Erling Smørgrav } else { 406*09a3aaf3SDag-Erling Smørgrav rr[rr_cur_len+(*cur_hex_data_size)/2] += 407*09a3aaf3SDag-Erling Smørgrav (uint8_t)sldns_hexdigit_to_int(*p); 408*09a3aaf3SDag-Erling Smørgrav } 409*09a3aaf3SDag-Erling Smørgrav p++; 410*09a3aaf3SDag-Erling Smørgrav (*cur_hex_data_size)++; 411*09a3aaf3SDag-Erling Smørgrav } 412*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 413*09a3aaf3SDag-Erling Smørgrav } 414*09a3aaf3SDag-Erling Smørgrav 415*09a3aaf3SDag-Erling Smørgrav /** read unknown rr type format */ 416*09a3aaf3SDag-Erling Smørgrav static int 417*09a3aaf3SDag-Erling Smørgrav rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, 418*09a3aaf3SDag-Erling Smørgrav uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos) 419*09a3aaf3SDag-Erling Smørgrav { 420*09a3aaf3SDag-Erling Smørgrav const char* delim = "\n\t "; 421*09a3aaf3SDag-Erling Smørgrav size_t hex_data_size, cur_hex_data_size; 422*09a3aaf3SDag-Erling Smørgrav /* go back to before \# 423*09a3aaf3SDag-Erling Smørgrav * and skip it while setting delimiters better 424*09a3aaf3SDag-Erling Smørgrav */ 425*09a3aaf3SDag-Erling Smørgrav sldns_buffer_set_position(strbuf, pre_data_pos); 426*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, delim, token_len) == -1) 427*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */ 428*09a3aaf3SDag-Erling Smørgrav /* read rdata octet length */ 429*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(strbuf, token, delim, token_len) == -1) { 430*09a3aaf3SDag-Erling Smørgrav /* something goes very wrong here */ 431*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 432*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 433*09a3aaf3SDag-Erling Smørgrav } 434*09a3aaf3SDag-Erling Smørgrav hex_data_size = (size_t)atoi(token); 435*09a3aaf3SDag-Erling Smørgrav if(hex_data_size > LDNS_MAX_RDFLEN || 436*09a3aaf3SDag-Erling Smørgrav *rr_cur_len + hex_data_size > *rr_len) { 437*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 438*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 439*09a3aaf3SDag-Erling Smørgrav } 440*09a3aaf3SDag-Erling Smørgrav /* copy hex chars into hex str (2 chars per byte) */ 441*09a3aaf3SDag-Erling Smørgrav hex_data_size *= 2; 442*09a3aaf3SDag-Erling Smørgrav cur_hex_data_size = 0; 443*09a3aaf3SDag-Erling Smørgrav while(cur_hex_data_size < hex_data_size) { 444*09a3aaf3SDag-Erling Smørgrav int status; 445*09a3aaf3SDag-Erling Smørgrav ssize_t c = sldns_bget_token(strbuf, token, delim, token_len); 446*09a3aaf3SDag-Erling Smørgrav if((status = rrinternal_spool_hex(token, rr, *rr_len, 447*09a3aaf3SDag-Erling Smørgrav *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0) 448*09a3aaf3SDag-Erling Smørgrav return RET_ERR_SHIFT(status, 449*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)-strlen(token)); 450*09a3aaf3SDag-Erling Smørgrav if(c == -1) { 451*09a3aaf3SDag-Erling Smørgrav if(cur_hex_data_size != hex_data_size) 452*09a3aaf3SDag-Erling Smørgrav return RET_ERR( 453*09a3aaf3SDag-Erling Smørgrav LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 454*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 455*09a3aaf3SDag-Erling Smørgrav break; 456*09a3aaf3SDag-Erling Smørgrav } 457*09a3aaf3SDag-Erling Smørgrav } 458*09a3aaf3SDag-Erling Smørgrav *rr_cur_len += hex_data_size/2; 459*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 460*09a3aaf3SDag-Erling Smørgrav } 461*09a3aaf3SDag-Erling Smørgrav 462*09a3aaf3SDag-Erling Smørgrav /** parse normal RR rdata element */ 463*09a3aaf3SDag-Erling Smørgrav static int 464*09a3aaf3SDag-Erling Smørgrav rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len, 465*09a3aaf3SDag-Erling Smørgrav uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype, 466*09a3aaf3SDag-Erling Smørgrav uint16_t rr_type, uint16_t r_cnt, uint16_t r_max, size_t dname_len, 467*09a3aaf3SDag-Erling Smørgrav uint8_t* origin, size_t origin_len) 468*09a3aaf3SDag-Erling Smørgrav { 469*09a3aaf3SDag-Erling Smørgrav size_t len; 470*09a3aaf3SDag-Erling Smørgrav int status; 471*09a3aaf3SDag-Erling Smørgrav 472*09a3aaf3SDag-Erling Smørgrav switch(rdftype) { 473*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_DNAME: 474*09a3aaf3SDag-Erling Smørgrav /* check if the origin should be used or concatenated */ 475*09a3aaf3SDag-Erling Smørgrav if(strcmp(token, "@") == 0) { 476*09a3aaf3SDag-Erling Smørgrav uint8_t* tocopy; 477*09a3aaf3SDag-Erling Smørgrav size_t copylen; 478*09a3aaf3SDag-Erling Smørgrav if(origin) { 479*09a3aaf3SDag-Erling Smørgrav copylen = origin_len; 480*09a3aaf3SDag-Erling Smørgrav tocopy = origin; 481*09a3aaf3SDag-Erling Smørgrav } else if(rr_type == LDNS_RR_TYPE_SOA) { 482*09a3aaf3SDag-Erling Smørgrav copylen = dname_len; 483*09a3aaf3SDag-Erling Smørgrav tocopy = rr; /* copy rr owner name */ 484*09a3aaf3SDag-Erling Smørgrav } else { 485*09a3aaf3SDag-Erling Smørgrav copylen = 1; 486*09a3aaf3SDag-Erling Smørgrav tocopy = (uint8_t*)"\0"; 487*09a3aaf3SDag-Erling Smørgrav } 488*09a3aaf3SDag-Erling Smørgrav if((*rr_cur_len) + copylen > rr_len) 489*09a3aaf3SDag-Erling Smørgrav return RET_ERR( 490*09a3aaf3SDag-Erling Smørgrav LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 491*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 492*09a3aaf3SDag-Erling Smørgrav memmove(rr+*rr_cur_len, tocopy, copylen); 493*09a3aaf3SDag-Erling Smørgrav (*rr_cur_len) += copylen; 494*09a3aaf3SDag-Erling Smørgrav } else { 495*09a3aaf3SDag-Erling Smørgrav size_t dlen = rr_len - (*rr_cur_len); 496*09a3aaf3SDag-Erling Smørgrav int s = sldns_str2wire_dname_buf_origin(token, 497*09a3aaf3SDag-Erling Smørgrav rr+*rr_cur_len, &dlen, origin, origin_len); 498*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, 499*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)-strlen(token)); 500*09a3aaf3SDag-Erling Smørgrav (*rr_cur_len) += dlen; 501*09a3aaf3SDag-Erling Smørgrav } 502*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 503*09a3aaf3SDag-Erling Smørgrav 504*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_HEX: 505*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_B64: 506*09a3aaf3SDag-Erling Smørgrav /* When this is the last rdata field, then the 507*09a3aaf3SDag-Erling Smørgrav * rest should be read in (cause then these 508*09a3aaf3SDag-Erling Smørgrav * rdf types may contain spaces). */ 509*09a3aaf3SDag-Erling Smørgrav if(r_cnt == r_max - 1) { 510*09a3aaf3SDag-Erling Smørgrav size_t tlen = strlen(token); 511*09a3aaf3SDag-Erling Smørgrav (void)sldns_bget_token(strbuf, token+tlen, "\n", 512*09a3aaf3SDag-Erling Smørgrav token_len - tlen); 513*09a3aaf3SDag-Erling Smørgrav } 514*09a3aaf3SDag-Erling Smørgrav break; 515*09a3aaf3SDag-Erling Smørgrav default: 516*09a3aaf3SDag-Erling Smørgrav break; 517*09a3aaf3SDag-Erling Smørgrav } 518*09a3aaf3SDag-Erling Smørgrav 519*09a3aaf3SDag-Erling Smørgrav len = rr_len - (*rr_cur_len); 520*09a3aaf3SDag-Erling Smørgrav if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len, 521*09a3aaf3SDag-Erling Smørgrav rdftype)) != 0) 522*09a3aaf3SDag-Erling Smørgrav return RET_ERR_SHIFT(status, 523*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)-strlen(token)); 524*09a3aaf3SDag-Erling Smørgrav *rr_cur_len += len; 525*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 526*09a3aaf3SDag-Erling Smørgrav } 527*09a3aaf3SDag-Erling Smørgrav 528*09a3aaf3SDag-Erling Smørgrav /** 529*09a3aaf3SDag-Erling Smørgrav * Parse one rdf token. Takes care of quotes and parenthesis. 530*09a3aaf3SDag-Erling Smørgrav */ 531*09a3aaf3SDag-Erling Smørgrav static int 532*09a3aaf3SDag-Erling Smørgrav sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, 533*09a3aaf3SDag-Erling Smørgrav int* quoted, int* parens, size_t* pre_data_pos, 534*09a3aaf3SDag-Erling Smørgrav const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 535*09a3aaf3SDag-Erling Smørgrav { 536*09a3aaf3SDag-Erling Smørgrav size_t slen; 537*09a3aaf3SDag-Erling Smørgrav 538*09a3aaf3SDag-Erling Smørgrav /* skip spaces */ 539*09a3aaf3SDag-Erling Smørgrav while(sldns_buffer_remaining(strbuf) > 0 && !*quoted && 540*09a3aaf3SDag-Erling Smørgrav *(sldns_buffer_current(strbuf)) == ' ') { 541*09a3aaf3SDag-Erling Smørgrav sldns_buffer_skip(strbuf, 1); 542*09a3aaf3SDag-Erling Smørgrav } 543*09a3aaf3SDag-Erling Smørgrav 544*09a3aaf3SDag-Erling Smørgrav *pre_data_pos = sldns_buffer_position(strbuf); 545*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters, 546*09a3aaf3SDag-Erling Smørgrav token_len, parens, (*quoted)?NULL:" \t") == -1) { 547*09a3aaf3SDag-Erling Smørgrav return 0; 548*09a3aaf3SDag-Erling Smørgrav } 549*09a3aaf3SDag-Erling Smørgrav slen = strlen(token); 550*09a3aaf3SDag-Erling Smørgrav /* check if not quoted yet, and we have encountered quotes */ 551*09a3aaf3SDag-Erling Smørgrav if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 552*09a3aaf3SDag-Erling Smørgrav slen >= 2 && 553*09a3aaf3SDag-Erling Smørgrav (token[0] == '"' || token[0] == '\'') && 554*09a3aaf3SDag-Erling Smørgrav (token[slen-1] == '"' || token[slen-1] == '\'')) { 555*09a3aaf3SDag-Erling Smørgrav /* move token two smaller (quotes) with endnull */ 556*09a3aaf3SDag-Erling Smørgrav memmove(token, token+1, slen-2); 557*09a3aaf3SDag-Erling Smørgrav token[slen-2] = 0; 558*09a3aaf3SDag-Erling Smørgrav slen -= 2; 559*09a3aaf3SDag-Erling Smørgrav *quoted = 1; 560*09a3aaf3SDag-Erling Smørgrav } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 561*09a3aaf3SDag-Erling Smørgrav slen >= 2 && 562*09a3aaf3SDag-Erling Smørgrav (token[0] == '"' || token[0] == '\'')) { 563*09a3aaf3SDag-Erling Smørgrav /* got the start quote (remove it) but read remainder 564*09a3aaf3SDag-Erling Smørgrav * of quoted string as well into remainder of token */ 565*09a3aaf3SDag-Erling Smørgrav memmove(token, token+1, slen-1); 566*09a3aaf3SDag-Erling Smørgrav token[slen-1] = 0; 567*09a3aaf3SDag-Erling Smørgrav slen -= 1; 568*09a3aaf3SDag-Erling Smørgrav *quoted = 1; 569*09a3aaf3SDag-Erling Smørgrav /* rewind buffer over skipped whitespace */ 570*09a3aaf3SDag-Erling Smørgrav while(sldns_buffer_position(strbuf) > 0 && 571*09a3aaf3SDag-Erling Smørgrav (sldns_buffer_current(strbuf)[-1] == ' ' || 572*09a3aaf3SDag-Erling Smørgrav sldns_buffer_current(strbuf)[-1] == '\t')) { 573*09a3aaf3SDag-Erling Smørgrav sldns_buffer_skip(strbuf, -1); 574*09a3aaf3SDag-Erling Smørgrav } 575*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token_par(strbuf, token+slen, 576*09a3aaf3SDag-Erling Smørgrav "\"", token_len-slen, 577*09a3aaf3SDag-Erling Smørgrav parens, NULL) == -1) { 578*09a3aaf3SDag-Erling Smørgrav return 0; 579*09a3aaf3SDag-Erling Smørgrav } 580*09a3aaf3SDag-Erling Smørgrav slen = strlen(token); 581*09a3aaf3SDag-Erling Smørgrav } 582*09a3aaf3SDag-Erling Smørgrav *token_strlen = slen; 583*09a3aaf3SDag-Erling Smørgrav return 1; 584*09a3aaf3SDag-Erling Smørgrav } 585*09a3aaf3SDag-Erling Smørgrav 586*09a3aaf3SDag-Erling Smørgrav /** Add space and one more rdf token onto the existing token string. */ 587*09a3aaf3SDag-Erling Smørgrav static int 588*09a3aaf3SDag-Erling Smørgrav sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, 589*09a3aaf3SDag-Erling Smørgrav int* quoted, int* parens, size_t* pre_data_pos, 590*09a3aaf3SDag-Erling Smørgrav const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 591*09a3aaf3SDag-Erling Smørgrav { 592*09a3aaf3SDag-Erling Smørgrav size_t addlen = *token_len - *token_strlen; 593*09a3aaf3SDag-Erling Smørgrav size_t addstrlen = 0; 594*09a3aaf3SDag-Erling Smørgrav 595*09a3aaf3SDag-Erling Smørgrav /* add space */ 596*09a3aaf3SDag-Erling Smørgrav if(addlen < 1) return 0; 597*09a3aaf3SDag-Erling Smørgrav token[*token_strlen] = ' '; 598*09a3aaf3SDag-Erling Smørgrav token[++(*token_strlen)] = 0; 599*09a3aaf3SDag-Erling Smørgrav 600*09a3aaf3SDag-Erling Smørgrav /* read another token */ 601*09a3aaf3SDag-Erling Smørgrav addlen = *token_len - *token_strlen; 602*09a3aaf3SDag-Erling Smørgrav if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted, 603*09a3aaf3SDag-Erling Smørgrav parens, pre_data_pos, delimiters, rdftype, &addstrlen)) 604*09a3aaf3SDag-Erling Smørgrav return 0; 605*09a3aaf3SDag-Erling Smørgrav (*token_strlen) += addstrlen; 606*09a3aaf3SDag-Erling Smørgrav return 1; 607*09a3aaf3SDag-Erling Smørgrav } 608*09a3aaf3SDag-Erling Smørgrav 609*09a3aaf3SDag-Erling Smørgrav /** parse rdata from string into rr buffer(-remainder after dname). */ 610*09a3aaf3SDag-Erling Smørgrav static int 611*09a3aaf3SDag-Erling Smørgrav rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, 612*09a3aaf3SDag-Erling Smørgrav uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type, 613*09a3aaf3SDag-Erling Smørgrav uint8_t* origin, size_t origin_len) 614*09a3aaf3SDag-Erling Smørgrav { 615*09a3aaf3SDag-Erling Smørgrav const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type); 616*09a3aaf3SDag-Erling Smørgrav uint16_t r_cnt, r_min, r_max; 617*09a3aaf3SDag-Erling Smørgrav size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen; 618*09a3aaf3SDag-Erling Smørgrav int was_unknown_rr_format = 0, parens = 0, status, quoted; 619*09a3aaf3SDag-Erling Smørgrav const char* delimiters; 620*09a3aaf3SDag-Erling Smørgrav sldns_rdf_type rdftype; 621*09a3aaf3SDag-Erling Smørgrav /* a desc is always returned */ 622*09a3aaf3SDag-Erling Smørgrav if(!desc) return LDNS_WIREPARSE_ERR_GENERAL; 623*09a3aaf3SDag-Erling Smørgrav r_max = sldns_rr_descriptor_maximum(desc); 624*09a3aaf3SDag-Erling Smørgrav r_min = sldns_rr_descriptor_minimum(desc); 625*09a3aaf3SDag-Erling Smørgrav /* robust check */ 626*09a3aaf3SDag-Erling Smørgrav if(rr_cur_len > *rr_len) 627*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 628*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 629*09a3aaf3SDag-Erling Smørgrav 630*09a3aaf3SDag-Erling Smørgrav /* because number of fields can be variable, we can't rely on 631*09a3aaf3SDag-Erling Smørgrav * _maximum() only */ 632*09a3aaf3SDag-Erling Smørgrav for(r_cnt=0; r_cnt < r_max; r_cnt++) { 633*09a3aaf3SDag-Erling Smørgrav rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 634*09a3aaf3SDag-Erling Smørgrav delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max); 635*09a3aaf3SDag-Erling Smørgrav quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype); 636*09a3aaf3SDag-Erling Smørgrav 637*09a3aaf3SDag-Erling Smørgrav if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed, 638*09a3aaf3SDag-Erling Smørgrav &parens, &pre_data_pos, delimiters, rdftype, 639*09a3aaf3SDag-Erling Smørgrav &token_strlen)) 640*09a3aaf3SDag-Erling Smørgrav break; 641*09a3aaf3SDag-Erling Smørgrav 642*09a3aaf3SDag-Erling Smørgrav /* rfc3597 specifies that any type can be represented 643*09a3aaf3SDag-Erling Smørgrav * with \# method, which can contain spaces... 644*09a3aaf3SDag-Erling Smørgrav * it does specify size though... */ 645*09a3aaf3SDag-Erling Smørgrav 646*09a3aaf3SDag-Erling Smørgrav /* unknown RR data */ 647*09a3aaf3SDag-Erling Smørgrav if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && 648*09a3aaf3SDag-Erling Smørgrav !quoted && (token_strlen == 2 || token[2]==' ')) { 649*09a3aaf3SDag-Erling Smørgrav was_unknown_rr_format = 1; 650*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_parse_unknown(strbuf, token, 651*09a3aaf3SDag-Erling Smørgrav token_len, rr, rr_len, &rr_cur_len, 652*09a3aaf3SDag-Erling Smørgrav pre_data_pos)) != 0) 653*09a3aaf3SDag-Erling Smørgrav return status; 654*09a3aaf3SDag-Erling Smørgrav } else if(token_strlen > 0 || quoted) { 655*09a3aaf3SDag-Erling Smørgrav if(rdftype == LDNS_RDF_TYPE_HIP) { 656*09a3aaf3SDag-Erling Smørgrav /* affix the HIT and PK fields, with a space */ 657*09a3aaf3SDag-Erling Smørgrav if(!sldns_affix_token(strbuf, token, 658*09a3aaf3SDag-Erling Smørgrav &token_len, "ed, &parens, 659*09a3aaf3SDag-Erling Smørgrav &pre_data_pos, delimiters, 660*09a3aaf3SDag-Erling Smørgrav rdftype, &token_strlen)) 661*09a3aaf3SDag-Erling Smørgrav break; 662*09a3aaf3SDag-Erling Smørgrav if(!sldns_affix_token(strbuf, token, 663*09a3aaf3SDag-Erling Smørgrav &token_len, "ed, &parens, 664*09a3aaf3SDag-Erling Smørgrav &pre_data_pos, delimiters, 665*09a3aaf3SDag-Erling Smørgrav rdftype, &token_strlen)) 666*09a3aaf3SDag-Erling Smørgrav break; 667*09a3aaf3SDag-Erling Smørgrav } 668*09a3aaf3SDag-Erling Smørgrav 669*09a3aaf3SDag-Erling Smørgrav /* normal RR */ 670*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_parse_rdf(strbuf, token, 671*09a3aaf3SDag-Erling Smørgrav token_len, rr, *rr_len, &rr_cur_len, rdftype, 672*09a3aaf3SDag-Erling Smørgrav rr_type, r_cnt, r_max, dname_len, origin, 673*09a3aaf3SDag-Erling Smørgrav origin_len)) != 0) { 674*09a3aaf3SDag-Erling Smørgrav return status; 675*09a3aaf3SDag-Erling Smørgrav } 676*09a3aaf3SDag-Erling Smørgrav } 677*09a3aaf3SDag-Erling Smørgrav } 678*09a3aaf3SDag-Erling Smørgrav if(!was_unknown_rr_format && r_cnt+1 < r_min) { 679*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, 680*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 681*09a3aaf3SDag-Erling Smørgrav } 682*09a3aaf3SDag-Erling Smørgrav while(parens != 0) { 683*09a3aaf3SDag-Erling Smørgrav /* read remainder, must be "" */ 684*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token_par(strbuf, token, "\n", token_len, 685*09a3aaf3SDag-Erling Smørgrav &parens, " \t") == -1) { 686*09a3aaf3SDag-Erling Smørgrav if(parens != 0) 687*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 688*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 689*09a3aaf3SDag-Erling Smørgrav break; 690*09a3aaf3SDag-Erling Smørgrav } 691*09a3aaf3SDag-Erling Smørgrav if(strcmp(token, "") != 0) 692*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 693*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(strbuf)); 694*09a3aaf3SDag-Erling Smørgrav } 695*09a3aaf3SDag-Erling Smørgrav /* write rdata length */ 696*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rr+dname_len+8, rr_cur_len-dname_len-10); 697*09a3aaf3SDag-Erling Smørgrav *rr_len = rr_cur_len; 698*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 699*09a3aaf3SDag-Erling Smørgrav } 700*09a3aaf3SDag-Erling Smørgrav 701*09a3aaf3SDag-Erling Smørgrav /* 702*09a3aaf3SDag-Erling Smørgrav * trailing spaces are allowed 703*09a3aaf3SDag-Erling Smørgrav * leading spaces are not allowed 704*09a3aaf3SDag-Erling Smørgrav * allow ttl to be optional 705*09a3aaf3SDag-Erling Smørgrav * class is optional too 706*09a3aaf3SDag-Erling Smørgrav * if ttl is missing, and default_ttl is 0, use DEF_TTL 707*09a3aaf3SDag-Erling Smørgrav * allow ttl to be written as 1d3h 708*09a3aaf3SDag-Erling Smørgrav * So the RR should look like. e.g. 709*09a3aaf3SDag-Erling Smørgrav * miek.nl. 3600 IN MX 10 elektron.atoom.net 710*09a3aaf3SDag-Erling Smørgrav * or 711*09a3aaf3SDag-Erling Smørgrav * miek.nl. 1h IN MX 10 elektron.atoom.net 712*09a3aaf3SDag-Erling Smørgrav * or 713*09a3aaf3SDag-Erling Smørgrav * miek.nl. IN MX 10 elektron.atoom.net 714*09a3aaf3SDag-Erling Smørgrav */ 715*09a3aaf3SDag-Erling Smørgrav static int 716*09a3aaf3SDag-Erling Smørgrav sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 717*09a3aaf3SDag-Erling Smørgrav size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 718*09a3aaf3SDag-Erling Smørgrav size_t origin_len, uint8_t* prev, size_t prev_len, int question) 719*09a3aaf3SDag-Erling Smørgrav { 720*09a3aaf3SDag-Erling Smørgrav int status; 721*09a3aaf3SDag-Erling Smørgrav int not_there = 0; 722*09a3aaf3SDag-Erling Smørgrav char token[LDNS_MAX_RDFLEN+1]; 723*09a3aaf3SDag-Erling Smørgrav uint32_t ttl = 0; 724*09a3aaf3SDag-Erling Smørgrav uint16_t tp = 0, cl = 0; 725*09a3aaf3SDag-Erling Smørgrav size_t ddlen = 0; 726*09a3aaf3SDag-Erling Smørgrav 727*09a3aaf3SDag-Erling Smørgrav /* string in buffer */ 728*09a3aaf3SDag-Erling Smørgrav sldns_buffer strbuf; 729*09a3aaf3SDag-Erling Smørgrav sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 730*09a3aaf3SDag-Erling Smørgrav if(!dname_len) dname_len = &ddlen; 731*09a3aaf3SDag-Erling Smørgrav 732*09a3aaf3SDag-Erling Smørgrav /* parse the owner */ 733*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 734*09a3aaf3SDag-Erling Smørgrav origin_len, prev, prev_len, token, sizeof(token))) != 0) 735*09a3aaf3SDag-Erling Smørgrav return status; 736*09a3aaf3SDag-Erling Smørgrav 737*09a3aaf3SDag-Erling Smørgrav /* parse the [ttl] [class] <type> */ 738*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 739*09a3aaf3SDag-Erling Smørgrav ¬_there, &ttl, default_ttl)) != 0) 740*09a3aaf3SDag-Erling Smørgrav return status; 741*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 742*09a3aaf3SDag-Erling Smørgrav ¬_there, &cl)) != 0) 743*09a3aaf3SDag-Erling Smørgrav return status; 744*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 745*09a3aaf3SDag-Erling Smørgrav ¬_there, &tp)) != 0) 746*09a3aaf3SDag-Erling Smørgrav return status; 747*09a3aaf3SDag-Erling Smørgrav /* put ttl, class, type into the rr result */ 748*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 749*09a3aaf3SDag-Erling Smørgrav ttl, question)) != 0) 750*09a3aaf3SDag-Erling Smørgrav return status; 751*09a3aaf3SDag-Erling Smørgrav /* for a question-RR we are done, no rdata */ 752*09a3aaf3SDag-Erling Smørgrav if(question) { 753*09a3aaf3SDag-Erling Smørgrav *len = *dname_len + 4; 754*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 755*09a3aaf3SDag-Erling Smørgrav } 756*09a3aaf3SDag-Erling Smørgrav 757*09a3aaf3SDag-Erling Smørgrav /* rdata */ 758*09a3aaf3SDag-Erling Smørgrav if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 759*09a3aaf3SDag-Erling Smørgrav rr, len, *dname_len, tp, origin, origin_len)) != 0) 760*09a3aaf3SDag-Erling Smørgrav return status; 761*09a3aaf3SDag-Erling Smørgrav 762*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 763*09a3aaf3SDag-Erling Smørgrav } 764*09a3aaf3SDag-Erling Smørgrav 765*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 766*09a3aaf3SDag-Erling Smørgrav size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 767*09a3aaf3SDag-Erling Smørgrav size_t origin_len, uint8_t* prev, size_t prev_len) 768*09a3aaf3SDag-Erling Smørgrav { 769*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 770*09a3aaf3SDag-Erling Smørgrav default_ttl, origin, origin_len, prev, prev_len, 0); 771*09a3aaf3SDag-Erling Smørgrav } 772*09a3aaf3SDag-Erling Smørgrav 773*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 774*09a3aaf3SDag-Erling Smørgrav size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 775*09a3aaf3SDag-Erling Smørgrav size_t prev_len) 776*09a3aaf3SDag-Erling Smørgrav { 777*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 778*09a3aaf3SDag-Erling Smørgrav 0, origin, origin_len, prev, prev_len, 1); 779*09a3aaf3SDag-Erling Smørgrav } 780*09a3aaf3SDag-Erling Smørgrav 781*09a3aaf3SDag-Erling Smørgrav uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 782*09a3aaf3SDag-Erling Smørgrav { 783*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+2) 784*09a3aaf3SDag-Erling Smørgrav return 0; 785*09a3aaf3SDag-Erling Smørgrav return sldns_read_uint16(rr+dname_len); 786*09a3aaf3SDag-Erling Smørgrav } 787*09a3aaf3SDag-Erling Smørgrav 788*09a3aaf3SDag-Erling Smørgrav uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 789*09a3aaf3SDag-Erling Smørgrav { 790*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+4) 791*09a3aaf3SDag-Erling Smørgrav return 0; 792*09a3aaf3SDag-Erling Smørgrav return sldns_read_uint16(rr+dname_len+2); 793*09a3aaf3SDag-Erling Smørgrav } 794*09a3aaf3SDag-Erling Smørgrav 795*09a3aaf3SDag-Erling Smørgrav uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 796*09a3aaf3SDag-Erling Smørgrav { 797*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+8) 798*09a3aaf3SDag-Erling Smørgrav return 0; 799*09a3aaf3SDag-Erling Smørgrav return sldns_read_uint32(rr+dname_len+4); 800*09a3aaf3SDag-Erling Smørgrav } 801*09a3aaf3SDag-Erling Smørgrav 802*09a3aaf3SDag-Erling Smørgrav uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 803*09a3aaf3SDag-Erling Smørgrav { 804*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+10) 805*09a3aaf3SDag-Erling Smørgrav return 0; 806*09a3aaf3SDag-Erling Smørgrav return sldns_read_uint16(rr+dname_len+8); 807*09a3aaf3SDag-Erling Smørgrav } 808*09a3aaf3SDag-Erling Smørgrav 809*09a3aaf3SDag-Erling Smørgrav uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 810*09a3aaf3SDag-Erling Smørgrav { 811*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+10) 812*09a3aaf3SDag-Erling Smørgrav return NULL; 813*09a3aaf3SDag-Erling Smørgrav return rr+dname_len+10; 814*09a3aaf3SDag-Erling Smørgrav } 815*09a3aaf3SDag-Erling Smørgrav 816*09a3aaf3SDag-Erling Smørgrav uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 817*09a3aaf3SDag-Erling Smørgrav { 818*09a3aaf3SDag-Erling Smørgrav if(len < dname_len+10) 819*09a3aaf3SDag-Erling Smørgrav return NULL; 820*09a3aaf3SDag-Erling Smørgrav return rr+dname_len+8; 821*09a3aaf3SDag-Erling Smørgrav } 822*09a3aaf3SDag-Erling Smørgrav 823*09a3aaf3SDag-Erling Smørgrav const char* sldns_get_errorstr_parse(int e) 824*09a3aaf3SDag-Erling Smørgrav { 825*09a3aaf3SDag-Erling Smørgrav sldns_lookup_table *lt; 826*09a3aaf3SDag-Erling Smørgrav lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 827*09a3aaf3SDag-Erling Smørgrav return lt?lt->name:"unknown error"; 828*09a3aaf3SDag-Erling Smørgrav } 829*09a3aaf3SDag-Erling Smørgrav 830*09a3aaf3SDag-Erling Smørgrav /* Strip whitespace from the start and the end of <line>. */ 831*09a3aaf3SDag-Erling Smørgrav static char * 832*09a3aaf3SDag-Erling Smørgrav sldns_strip_ws(char *line) 833*09a3aaf3SDag-Erling Smørgrav { 834*09a3aaf3SDag-Erling Smørgrav char *s = line, *e; 835*09a3aaf3SDag-Erling Smørgrav 836*09a3aaf3SDag-Erling Smørgrav for (s = line; *s && isspace((unsigned char)*s); s++) 837*09a3aaf3SDag-Erling Smørgrav ; 838*09a3aaf3SDag-Erling Smørgrav for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) 839*09a3aaf3SDag-Erling Smørgrav ; 840*09a3aaf3SDag-Erling Smørgrav *e = 0; 841*09a3aaf3SDag-Erling Smørgrav return s; 842*09a3aaf3SDag-Erling Smørgrav } 843*09a3aaf3SDag-Erling Smørgrav 844*09a3aaf3SDag-Erling Smørgrav int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 845*09a3aaf3SDag-Erling Smørgrav struct sldns_file_parse_state* parse_state) 846*09a3aaf3SDag-Erling Smørgrav { 847*09a3aaf3SDag-Erling Smørgrav char line[LDNS_RR_BUF_SIZE+1]; 848*09a3aaf3SDag-Erling Smørgrav ssize_t size; 849*09a3aaf3SDag-Erling Smørgrav 850*09a3aaf3SDag-Erling Smørgrav /* read an entire line in from the file */ 851*09a3aaf3SDag-Erling Smørgrav if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 852*09a3aaf3SDag-Erling Smørgrav LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 853*09a3aaf3SDag-Erling Smørgrav == -1) { 854*09a3aaf3SDag-Erling Smørgrav /* if last line was empty, we are now at feof, which is not 855*09a3aaf3SDag-Erling Smørgrav * always a parse error (happens when for instance last line 856*09a3aaf3SDag-Erling Smørgrav * was a comment) 857*09a3aaf3SDag-Erling Smørgrav */ 858*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX; 859*09a3aaf3SDag-Erling Smørgrav } 860*09a3aaf3SDag-Erling Smørgrav 861*09a3aaf3SDag-Erling Smørgrav /* we can have the situation, where we've read ok, but still got 862*09a3aaf3SDag-Erling Smørgrav * no bytes to play with, in this case size is 0 */ 863*09a3aaf3SDag-Erling Smørgrav if(size == 0) { 864*09a3aaf3SDag-Erling Smørgrav *len = 0; 865*09a3aaf3SDag-Erling Smørgrav *dname_len = 0; 866*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 867*09a3aaf3SDag-Erling Smørgrav } 868*09a3aaf3SDag-Erling Smørgrav 869*09a3aaf3SDag-Erling Smørgrav if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { 870*09a3aaf3SDag-Erling Smørgrav int s; 871*09a3aaf3SDag-Erling Smørgrav *len = 0; 872*09a3aaf3SDag-Erling Smørgrav *dname_len = 0; 873*09a3aaf3SDag-Erling Smørgrav if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 874*09a3aaf3SDag-Erling Smørgrav parse_state->origin_len = sizeof(parse_state->origin); 875*09a3aaf3SDag-Erling Smørgrav s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), 876*09a3aaf3SDag-Erling Smørgrav parse_state->origin, &parse_state->origin_len); 877*09a3aaf3SDag-Erling Smørgrav if(s) parse_state->origin_len = 0; 878*09a3aaf3SDag-Erling Smørgrav return s; 879*09a3aaf3SDag-Erling Smørgrav } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { 880*09a3aaf3SDag-Erling Smørgrav const char* end = NULL; 881*09a3aaf3SDag-Erling Smørgrav *len = 0; 882*09a3aaf3SDag-Erling Smørgrav *dname_len = 0; 883*09a3aaf3SDag-Erling Smørgrav if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 884*09a3aaf3SDag-Erling Smørgrav parse_state->default_ttl = sldns_str2period( 885*09a3aaf3SDag-Erling Smørgrav sldns_strip_ws(line+5), &end); 886*09a3aaf3SDag-Erling Smørgrav } else if (strncmp(line, "$INCLUDE", 8) == 0) { 887*09a3aaf3SDag-Erling Smørgrav *len = 0; 888*09a3aaf3SDag-Erling Smørgrav *dname_len = 0; 889*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INCLUDE; 890*09a3aaf3SDag-Erling Smørgrav } else { 891*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_rr_buf(line, rr, len, dname_len, 892*09a3aaf3SDag-Erling Smørgrav parse_state?parse_state->default_ttl:0, 893*09a3aaf3SDag-Erling Smørgrav (parse_state&&parse_state->origin_len)? 894*09a3aaf3SDag-Erling Smørgrav parse_state->origin:NULL, 895*09a3aaf3SDag-Erling Smørgrav parse_state->origin_len, 896*09a3aaf3SDag-Erling Smørgrav (parse_state&&parse_state->prev_rr_len)? 897*09a3aaf3SDag-Erling Smørgrav parse_state->prev_rr:NULL, 898*09a3aaf3SDag-Erling Smørgrav parse_state->prev_rr_len); 899*09a3aaf3SDag-Erling Smørgrav } 900*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 901*09a3aaf3SDag-Erling Smørgrav } 902*09a3aaf3SDag-Erling Smørgrav 903*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 904*09a3aaf3SDag-Erling Smørgrav sldns_rdf_type rdftype) 905*09a3aaf3SDag-Erling Smørgrav { 906*09a3aaf3SDag-Erling Smørgrav switch (rdftype) { 907*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_DNAME: 908*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_dname_buf(str, rd, len); 909*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_INT8: 910*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_int8_buf(str, rd, len); 911*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_INT16: 912*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_int16_buf(str, rd, len); 913*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_INT32: 914*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_int32_buf(str, rd, len); 915*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_A: 916*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_a_buf(str, rd, len); 917*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_AAAA: 918*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_aaaa_buf(str, rd, len); 919*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_STR: 920*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_str_buf(str, rd, len); 921*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_APL: 922*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_apl_buf(str, rd, len); 923*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_B64: 924*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_b64_buf(str, rd, len); 925*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_B32_EXT: 926*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_b32_ext_buf(str, rd, len); 927*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_HEX: 928*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_hex_buf(str, rd, len); 929*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NSEC: 930*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_nsec_buf(str, rd, len); 931*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_TYPE: 932*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_type_buf(str, rd, len); 933*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_CLASS: 934*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_class_buf(str, rd, len); 935*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_CERT_ALG: 936*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_cert_alg_buf(str, rd, len); 937*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_ALG: 938*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_alg_buf(str, rd, len); 939*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_TIME: 940*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_time_buf(str, rd, len); 941*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_PERIOD: 942*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_period_buf(str, rd, len); 943*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_LOC: 944*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_loc_buf(str, rd, len); 945*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_WKS: 946*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_wks_buf(str, rd, len); 947*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NSAP: 948*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_nsap_buf(str, rd, len); 949*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_ATMA: 950*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_atma_buf(str, rd, len); 951*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_IPSECKEY: 952*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_ipseckey_buf(str, rd, len); 953*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NSEC3_SALT: 954*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_nsec3_salt_buf(str, rd, len); 955*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 956*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_b32_ext_buf(str, rd, len); 957*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_ILNP64: 958*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_ilnp64_buf(str, rd, len); 959*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_EUI48: 960*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_eui48_buf(str, rd, len); 961*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_EUI64: 962*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_eui64_buf(str, rd, len); 963*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_TAG: 964*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_tag_buf(str, rd, len); 965*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_LONG_STR: 966*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_long_str_buf(str, rd, len); 967*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_HIP: 968*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_hip_buf(str, rd, len); 969*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_INT16_DATA: 970*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_int16_data_buf(str, rd, len); 971*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_UNKNOWN: 972*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_SERVICE: 973*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_NOT_IMPL; 974*09a3aaf3SDag-Erling Smørgrav case LDNS_RDF_TYPE_NONE: 975*09a3aaf3SDag-Erling Smørgrav default: 976*09a3aaf3SDag-Erling Smørgrav break; 977*09a3aaf3SDag-Erling Smørgrav } 978*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_GENERAL; 979*09a3aaf3SDag-Erling Smørgrav } 980*09a3aaf3SDag-Erling Smørgrav 981*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 982*09a3aaf3SDag-Erling Smørgrav { 983*09a3aaf3SDag-Erling Smørgrav char* end; 984*09a3aaf3SDag-Erling Smørgrav uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 985*09a3aaf3SDag-Erling Smørgrav if(*end != 0) 986*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 987*09a3aaf3SDag-Erling Smørgrav if(*len < 1) 988*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 989*09a3aaf3SDag-Erling Smørgrav rd[0] = r; 990*09a3aaf3SDag-Erling Smørgrav *len = 1; 991*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 992*09a3aaf3SDag-Erling Smørgrav } 993*09a3aaf3SDag-Erling Smørgrav 994*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 995*09a3aaf3SDag-Erling Smørgrav { 996*09a3aaf3SDag-Erling Smørgrav char* end; 997*09a3aaf3SDag-Erling Smørgrav uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 998*09a3aaf3SDag-Erling Smørgrav if(*end != 0) 999*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1000*09a3aaf3SDag-Erling Smørgrav if(*len < 2) 1001*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1002*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd, r); 1003*09a3aaf3SDag-Erling Smørgrav *len = 2; 1004*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1005*09a3aaf3SDag-Erling Smørgrav } 1006*09a3aaf3SDag-Erling Smørgrav 1007*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 1008*09a3aaf3SDag-Erling Smørgrav { 1009*09a3aaf3SDag-Erling Smørgrav char* end; 1010*09a3aaf3SDag-Erling Smørgrav uint32_t r; 1011*09a3aaf3SDag-Erling Smørgrav errno = 0; /* must set to zero before call, 1012*09a3aaf3SDag-Erling Smørgrav note race condition on errno */ 1013*09a3aaf3SDag-Erling Smørgrav if(*str == '-') 1014*09a3aaf3SDag-Erling Smørgrav r = (uint32_t)strtol((char*)str, &end, 10); 1015*09a3aaf3SDag-Erling Smørgrav else r = (uint32_t)strtoul((char*)str, &end, 10); 1016*09a3aaf3SDag-Erling Smørgrav if(*end != 0) 1017*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1018*09a3aaf3SDag-Erling Smørgrav if(errno == ERANGE) 1019*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1020*09a3aaf3SDag-Erling Smørgrav if(*len < 4) 1021*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1022*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd, r); 1023*09a3aaf3SDag-Erling Smørgrav *len = 4; 1024*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1025*09a3aaf3SDag-Erling Smørgrav } 1026*09a3aaf3SDag-Erling Smørgrav 1027*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1028*09a3aaf3SDag-Erling Smørgrav { 1029*09a3aaf3SDag-Erling Smørgrav struct in_addr address; 1030*09a3aaf3SDag-Erling Smørgrav if(inet_pton(AF_INET, (char*)str, &address) != 1) 1031*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1032*09a3aaf3SDag-Erling Smørgrav if(*len < sizeof(address)) 1033*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1034*09a3aaf3SDag-Erling Smørgrav memmove(rd, &address, sizeof(address)); 1035*09a3aaf3SDag-Erling Smørgrav *len = sizeof(address); 1036*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1037*09a3aaf3SDag-Erling Smørgrav } 1038*09a3aaf3SDag-Erling Smørgrav 1039*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1040*09a3aaf3SDag-Erling Smørgrav { 1041*09a3aaf3SDag-Erling Smørgrav #ifdef AF_INET6 1042*09a3aaf3SDag-Erling Smørgrav uint8_t address[LDNS_IP6ADDRLEN + 1]; 1043*09a3aaf3SDag-Erling Smørgrav if(inet_pton(AF_INET6, (char*)str, address) != 1) 1044*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1045*09a3aaf3SDag-Erling Smørgrav if(*len < LDNS_IP6ADDRLEN) 1046*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1047*09a3aaf3SDag-Erling Smørgrav memmove(rd, address, LDNS_IP6ADDRLEN); 1048*09a3aaf3SDag-Erling Smørgrav *len = LDNS_IP6ADDRLEN; 1049*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1050*09a3aaf3SDag-Erling Smørgrav #else 1051*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_NOT_IMPL; 1052*09a3aaf3SDag-Erling Smørgrav #endif 1053*09a3aaf3SDag-Erling Smørgrav } 1054*09a3aaf3SDag-Erling Smørgrav 1055*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1056*09a3aaf3SDag-Erling Smørgrav { 1057*09a3aaf3SDag-Erling Smørgrav uint8_t ch = 0; 1058*09a3aaf3SDag-Erling Smørgrav size_t sl = 0; 1059*09a3aaf3SDag-Erling Smørgrav const char* s = str; 1060*09a3aaf3SDag-Erling Smørgrav /* skip length byte */ 1061*09a3aaf3SDag-Erling Smørgrav if(*len < 1) 1062*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1063*09a3aaf3SDag-Erling Smørgrav 1064*09a3aaf3SDag-Erling Smørgrav /* read characters */ 1065*09a3aaf3SDag-Erling Smørgrav while(sldns_parse_char(&ch, &s)) { 1066*09a3aaf3SDag-Erling Smørgrav if(sl >= 255) 1067*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1068*09a3aaf3SDag-Erling Smørgrav if(*len < sl+1) 1069*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1070*09a3aaf3SDag-Erling Smørgrav s-str); 1071*09a3aaf3SDag-Erling Smørgrav rd[++sl] = ch; 1072*09a3aaf3SDag-Erling Smørgrav } 1073*09a3aaf3SDag-Erling Smørgrav if(!s) 1074*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1075*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t)sl; 1076*09a3aaf3SDag-Erling Smørgrav *len = sl+1; 1077*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1078*09a3aaf3SDag-Erling Smørgrav } 1079*09a3aaf3SDag-Erling Smørgrav 1080*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1081*09a3aaf3SDag-Erling Smørgrav { 1082*09a3aaf3SDag-Erling Smørgrav const char *my_str = str; 1083*09a3aaf3SDag-Erling Smørgrav 1084*09a3aaf3SDag-Erling Smørgrav char my_ip_str[64]; 1085*09a3aaf3SDag-Erling Smørgrav size_t ip_str_len; 1086*09a3aaf3SDag-Erling Smørgrav 1087*09a3aaf3SDag-Erling Smørgrav uint16_t family; 1088*09a3aaf3SDag-Erling Smørgrav int negation; 1089*09a3aaf3SDag-Erling Smørgrav size_t adflength = 0; 1090*09a3aaf3SDag-Erling Smørgrav uint8_t data[16+4]; 1091*09a3aaf3SDag-Erling Smørgrav uint8_t prefix; 1092*09a3aaf3SDag-Erling Smørgrav size_t i; 1093*09a3aaf3SDag-Erling Smørgrav 1094*09a3aaf3SDag-Erling Smørgrav if(strlen(my_str) == 0) { 1095*09a3aaf3SDag-Erling Smørgrav /* empty APL element, no data, no string */ 1096*09a3aaf3SDag-Erling Smørgrav *len = 0; 1097*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1098*09a3aaf3SDag-Erling Smørgrav } 1099*09a3aaf3SDag-Erling Smørgrav 1100*09a3aaf3SDag-Erling Smørgrav /* [!]afi:address/prefix */ 1101*09a3aaf3SDag-Erling Smørgrav if (strlen(my_str) < 2 1102*09a3aaf3SDag-Erling Smørgrav || strchr(my_str, ':') == NULL 1103*09a3aaf3SDag-Erling Smørgrav || strchr(my_str, '/') == NULL 1104*09a3aaf3SDag-Erling Smørgrav || strchr(my_str, ':') > strchr(my_str, '/')) { 1105*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1106*09a3aaf3SDag-Erling Smørgrav } 1107*09a3aaf3SDag-Erling Smørgrav 1108*09a3aaf3SDag-Erling Smørgrav if (my_str[0] == '!') { 1109*09a3aaf3SDag-Erling Smørgrav negation = 1; 1110*09a3aaf3SDag-Erling Smørgrav my_str += 1; 1111*09a3aaf3SDag-Erling Smørgrav } else { 1112*09a3aaf3SDag-Erling Smørgrav negation = 0; 1113*09a3aaf3SDag-Erling Smørgrav } 1114*09a3aaf3SDag-Erling Smørgrav 1115*09a3aaf3SDag-Erling Smørgrav family = (uint16_t) atoi(my_str); 1116*09a3aaf3SDag-Erling Smørgrav 1117*09a3aaf3SDag-Erling Smørgrav my_str = strchr(my_str, ':') + 1; 1118*09a3aaf3SDag-Erling Smørgrav 1119*09a3aaf3SDag-Erling Smørgrav /* need ip addr and only ip addr for inet_pton */ 1120*09a3aaf3SDag-Erling Smørgrav ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1121*09a3aaf3SDag-Erling Smørgrav if(ip_str_len+1 > sizeof(my_ip_str)) 1122*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1123*09a3aaf3SDag-Erling Smørgrav (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1124*09a3aaf3SDag-Erling Smørgrav my_ip_str[ip_str_len] = 0; 1125*09a3aaf3SDag-Erling Smørgrav 1126*09a3aaf3SDag-Erling Smørgrav if (family == 1) { 1127*09a3aaf3SDag-Erling Smørgrav /* ipv4 */ 1128*09a3aaf3SDag-Erling Smørgrav if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1129*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1130*09a3aaf3SDag-Erling Smørgrav for (i = 0; i < 4; i++) { 1131*09a3aaf3SDag-Erling Smørgrav if (data[i+4] != 0) { 1132*09a3aaf3SDag-Erling Smørgrav adflength = i + 1; 1133*09a3aaf3SDag-Erling Smørgrav } 1134*09a3aaf3SDag-Erling Smørgrav } 1135*09a3aaf3SDag-Erling Smørgrav } else if (family == 2) { 1136*09a3aaf3SDag-Erling Smørgrav /* ipv6 */ 1137*09a3aaf3SDag-Erling Smørgrav if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1138*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1139*09a3aaf3SDag-Erling Smørgrav for (i = 0; i < 16; i++) { 1140*09a3aaf3SDag-Erling Smørgrav if (data[i+4] != 0) { 1141*09a3aaf3SDag-Erling Smørgrav adflength = i + 1; 1142*09a3aaf3SDag-Erling Smørgrav } 1143*09a3aaf3SDag-Erling Smørgrav } 1144*09a3aaf3SDag-Erling Smørgrav } else { 1145*09a3aaf3SDag-Erling Smørgrav /* unknown family */ 1146*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1147*09a3aaf3SDag-Erling Smørgrav } 1148*09a3aaf3SDag-Erling Smørgrav 1149*09a3aaf3SDag-Erling Smørgrav my_str = strchr(my_str, '/') + 1; 1150*09a3aaf3SDag-Erling Smørgrav prefix = (uint8_t) atoi(my_str); 1151*09a3aaf3SDag-Erling Smørgrav 1152*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(data, family); 1153*09a3aaf3SDag-Erling Smørgrav data[2] = prefix; 1154*09a3aaf3SDag-Erling Smørgrav data[3] = (uint8_t)adflength; 1155*09a3aaf3SDag-Erling Smørgrav if (negation) { 1156*09a3aaf3SDag-Erling Smørgrav /* set bit 1 of byte 3 */ 1157*09a3aaf3SDag-Erling Smørgrav data[3] = data[3] | 0x80; 1158*09a3aaf3SDag-Erling Smørgrav } 1159*09a3aaf3SDag-Erling Smørgrav 1160*09a3aaf3SDag-Erling Smørgrav if(*len < 4+adflength) 1161*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1162*09a3aaf3SDag-Erling Smørgrav memmove(rd, data, 4+adflength); 1163*09a3aaf3SDag-Erling Smørgrav *len = 4+adflength; 1164*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1165*09a3aaf3SDag-Erling Smørgrav } 1166*09a3aaf3SDag-Erling Smørgrav 1167*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1168*09a3aaf3SDag-Erling Smørgrav { 1169*09a3aaf3SDag-Erling Smørgrav size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1170*09a3aaf3SDag-Erling Smørgrav int n; 1171*09a3aaf3SDag-Erling Smørgrav if(*len < sz) 1172*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1173*09a3aaf3SDag-Erling Smørgrav n = sldns_b64_pton(str, rd, *len); 1174*09a3aaf3SDag-Erling Smørgrav if(n < 0) 1175*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1176*09a3aaf3SDag-Erling Smørgrav *len = (size_t)n; 1177*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1178*09a3aaf3SDag-Erling Smørgrav } 1179*09a3aaf3SDag-Erling Smørgrav 1180*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1181*09a3aaf3SDag-Erling Smørgrav { 1182*09a3aaf3SDag-Erling Smørgrav size_t slen = strlen(str); 1183*09a3aaf3SDag-Erling Smørgrav size_t sz = sldns_b32_pton_calculate_size(slen); 1184*09a3aaf3SDag-Erling Smørgrav int n; 1185*09a3aaf3SDag-Erling Smørgrav if(*len < 1+sz) 1186*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1187*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t)sz; 1188*09a3aaf3SDag-Erling Smørgrav n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1189*09a3aaf3SDag-Erling Smørgrav if(n < 0) 1190*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1191*09a3aaf3SDag-Erling Smørgrav *len = (size_t)n+1; 1192*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1193*09a3aaf3SDag-Erling Smørgrav } 1194*09a3aaf3SDag-Erling Smørgrav 1195*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1196*09a3aaf3SDag-Erling Smørgrav { 1197*09a3aaf3SDag-Erling Smørgrav const char* s = str; 1198*09a3aaf3SDag-Erling Smørgrav size_t dlen = 0; /* number of hexdigits parsed */ 1199*09a3aaf3SDag-Erling Smørgrav while(*s) { 1200*09a3aaf3SDag-Erling Smørgrav if(isspace((unsigned char)*s)) { 1201*09a3aaf3SDag-Erling Smørgrav s++; 1202*09a3aaf3SDag-Erling Smørgrav continue; 1203*09a3aaf3SDag-Erling Smørgrav } 1204*09a3aaf3SDag-Erling Smørgrav if(!isxdigit((unsigned char)*s)) 1205*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1206*09a3aaf3SDag-Erling Smørgrav if(*len < dlen/2 + 1) 1207*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1208*09a3aaf3SDag-Erling Smørgrav s-str); 1209*09a3aaf3SDag-Erling Smørgrav if((dlen&1)==0) 1210*09a3aaf3SDag-Erling Smørgrav rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1211*09a3aaf3SDag-Erling Smørgrav else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1212*09a3aaf3SDag-Erling Smørgrav dlen++; 1213*09a3aaf3SDag-Erling Smørgrav } 1214*09a3aaf3SDag-Erling Smørgrav if((dlen&1)!=0) 1215*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1216*09a3aaf3SDag-Erling Smørgrav *len = dlen/2; 1217*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1218*09a3aaf3SDag-Erling Smørgrav } 1219*09a3aaf3SDag-Erling Smørgrav 1220*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 1221*09a3aaf3SDag-Erling Smørgrav { 1222*09a3aaf3SDag-Erling Smørgrav const char *delim = "\n\t "; 1223*09a3aaf3SDag-Erling Smørgrav char token[64]; /* for a type name */ 1224*09a3aaf3SDag-Erling Smørgrav size_t type_count = 0; 1225*09a3aaf3SDag-Erling Smørgrav int block; 1226*09a3aaf3SDag-Erling Smørgrav size_t used = 0; 1227*09a3aaf3SDag-Erling Smørgrav uint16_t maxtype = 0; 1228*09a3aaf3SDag-Erling Smørgrav uint8_t typebits[8192]; /* 65536 bits */ 1229*09a3aaf3SDag-Erling Smørgrav uint8_t window_in_use[256]; 1230*09a3aaf3SDag-Erling Smørgrav 1231*09a3aaf3SDag-Erling Smørgrav /* string in buffer */ 1232*09a3aaf3SDag-Erling Smørgrav sldns_buffer strbuf; 1233*09a3aaf3SDag-Erling Smørgrav sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1234*09a3aaf3SDag-Erling Smørgrav 1235*09a3aaf3SDag-Erling Smørgrav /* parse the types */ 1236*09a3aaf3SDag-Erling Smørgrav memset(typebits, 0, sizeof(typebits)); 1237*09a3aaf3SDag-Erling Smørgrav memset(window_in_use, 0, sizeof(window_in_use)); 1238*09a3aaf3SDag-Erling Smørgrav while(sldns_buffer_remaining(&strbuf) > 0 && 1239*09a3aaf3SDag-Erling Smørgrav sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 1240*09a3aaf3SDag-Erling Smørgrav uint16_t t = sldns_get_rr_type_by_name(token); 1241*09a3aaf3SDag-Erling Smørgrav if(token[0] == 0) 1242*09a3aaf3SDag-Erling Smørgrav continue; 1243*09a3aaf3SDag-Erling Smørgrav if(t == 0 && strcmp(token, "TYPE0") != 0) 1244*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 1245*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1246*09a3aaf3SDag-Erling Smørgrav typebits[t/8] |= (0x80>>(t%8)); 1247*09a3aaf3SDag-Erling Smørgrav window_in_use[t/256] = 1; 1248*09a3aaf3SDag-Erling Smørgrav type_count++; 1249*09a3aaf3SDag-Erling Smørgrav if(t > maxtype) maxtype = t; 1250*09a3aaf3SDag-Erling Smørgrav } 1251*09a3aaf3SDag-Erling Smørgrav 1252*09a3aaf3SDag-Erling Smørgrav /* empty NSEC bitmap */ 1253*09a3aaf3SDag-Erling Smørgrav if(type_count == 0) { 1254*09a3aaf3SDag-Erling Smørgrav *len = 0; 1255*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1256*09a3aaf3SDag-Erling Smørgrav } 1257*09a3aaf3SDag-Erling Smørgrav 1258*09a3aaf3SDag-Erling Smørgrav /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 1259*09a3aaf3SDag-Erling Smørgrav * block is 0-255 upper octet of types, length if 0-32. */ 1260*09a3aaf3SDag-Erling Smørgrav for(block = 0; block <= (int)maxtype/256; block++) { 1261*09a3aaf3SDag-Erling Smørgrav int i, blocklen = 0; 1262*09a3aaf3SDag-Erling Smørgrav if(!window_in_use[block]) 1263*09a3aaf3SDag-Erling Smørgrav continue; 1264*09a3aaf3SDag-Erling Smørgrav for(i=0; i<32; i++) { 1265*09a3aaf3SDag-Erling Smørgrav if(typebits[block*32+i] != 0) 1266*09a3aaf3SDag-Erling Smørgrav blocklen = i+1; 1267*09a3aaf3SDag-Erling Smørgrav } 1268*09a3aaf3SDag-Erling Smørgrav if(blocklen == 0) 1269*09a3aaf3SDag-Erling Smørgrav continue; /* empty window should have been !in_use */ 1270*09a3aaf3SDag-Erling Smørgrav if(used+blocklen+2 > *len) 1271*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1272*09a3aaf3SDag-Erling Smørgrav rd[used+0] = (uint8_t)block; 1273*09a3aaf3SDag-Erling Smørgrav rd[used+1] = (uint8_t)blocklen; 1274*09a3aaf3SDag-Erling Smørgrav for(i=0; i<blocklen; i++) { 1275*09a3aaf3SDag-Erling Smørgrav rd[used+2+i] = typebits[block*32+i]; 1276*09a3aaf3SDag-Erling Smørgrav } 1277*09a3aaf3SDag-Erling Smørgrav used += blocklen+2; 1278*09a3aaf3SDag-Erling Smørgrav } 1279*09a3aaf3SDag-Erling Smørgrav *len = used; 1280*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1281*09a3aaf3SDag-Erling Smørgrav } 1282*09a3aaf3SDag-Erling Smørgrav 1283*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 1284*09a3aaf3SDag-Erling Smørgrav { 1285*09a3aaf3SDag-Erling Smørgrav uint16_t t = sldns_get_rr_type_by_name(str); 1286*09a3aaf3SDag-Erling Smørgrav if(t == 0 && strcmp(str, "TYPE0") != 0) 1287*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 1288*09a3aaf3SDag-Erling Smørgrav if(*len < 2) 1289*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1290*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd, t); 1291*09a3aaf3SDag-Erling Smørgrav *len = 2; 1292*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1293*09a3aaf3SDag-Erling Smørgrav } 1294*09a3aaf3SDag-Erling Smørgrav 1295*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 1296*09a3aaf3SDag-Erling Smørgrav { 1297*09a3aaf3SDag-Erling Smørgrav uint16_t c = sldns_get_rr_class_by_name(str); 1298*09a3aaf3SDag-Erling Smørgrav if(c == 0 && strcmp(str, "CLASS0") != 0) 1299*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 1300*09a3aaf3SDag-Erling Smørgrav if(*len < 2) 1301*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1302*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd, c); 1303*09a3aaf3SDag-Erling Smørgrav *len = 2; 1304*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1305*09a3aaf3SDag-Erling Smørgrav } 1306*09a3aaf3SDag-Erling Smørgrav 1307*09a3aaf3SDag-Erling Smørgrav /* An certificate alg field can either be specified as a 8 bits number 1308*09a3aaf3SDag-Erling Smørgrav * or by its symbolic name. Handle both */ 1309*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 1310*09a3aaf3SDag-Erling Smørgrav { 1311*09a3aaf3SDag-Erling Smørgrav sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 1312*09a3aaf3SDag-Erling Smørgrav str); 1313*09a3aaf3SDag-Erling Smørgrav if(*len < 2) 1314*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1315*09a3aaf3SDag-Erling Smørgrav if(lt) { 1316*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd, (uint16_t)lt->id); 1317*09a3aaf3SDag-Erling Smørgrav } else { 1318*09a3aaf3SDag-Erling Smørgrav int s = sldns_str2wire_int16_buf(str, rd, len); 1319*09a3aaf3SDag-Erling Smørgrav if(s) return s; 1320*09a3aaf3SDag-Erling Smørgrav if(sldns_read_uint16(rd) == 0) 1321*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 1322*09a3aaf3SDag-Erling Smørgrav } 1323*09a3aaf3SDag-Erling Smørgrav *len = 2; 1324*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1325*09a3aaf3SDag-Erling Smørgrav } 1326*09a3aaf3SDag-Erling Smørgrav 1327*09a3aaf3SDag-Erling Smørgrav /* An alg field can either be specified as a 8 bits number 1328*09a3aaf3SDag-Erling Smørgrav * or by its symbolic name. Handle both */ 1329*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 1330*09a3aaf3SDag-Erling Smørgrav { 1331*09a3aaf3SDag-Erling Smørgrav sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 1332*09a3aaf3SDag-Erling Smørgrav if(*len < 1) 1333*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1334*09a3aaf3SDag-Erling Smørgrav if(lt) { 1335*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t)lt->id; 1336*09a3aaf3SDag-Erling Smørgrav *len = 1; 1337*09a3aaf3SDag-Erling Smørgrav } else { 1338*09a3aaf3SDag-Erling Smørgrav /* try as-is (a number) */ 1339*09a3aaf3SDag-Erling Smørgrav return sldns_str2wire_int8_buf(str, rd, len); 1340*09a3aaf3SDag-Erling Smørgrav } 1341*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1342*09a3aaf3SDag-Erling Smørgrav } 1343*09a3aaf3SDag-Erling Smørgrav 1344*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 1345*09a3aaf3SDag-Erling Smørgrav { 1346*09a3aaf3SDag-Erling Smørgrav /* convert a time YYYYDDMMHHMMSS to wireformat */ 1347*09a3aaf3SDag-Erling Smørgrav struct tm tm; 1348*09a3aaf3SDag-Erling Smørgrav if(*len < 4) 1349*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1350*09a3aaf3SDag-Erling Smørgrav 1351*09a3aaf3SDag-Erling Smørgrav /* Try to scan the time... */ 1352*09a3aaf3SDag-Erling Smørgrav memset(&tm, 0, sizeof(tm)); 1353*09a3aaf3SDag-Erling Smørgrav if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 1354*09a3aaf3SDag-Erling Smørgrav &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 1355*09a3aaf3SDag-Erling Smørgrav &tm.tm_min, &tm.tm_sec) == 6) { 1356*09a3aaf3SDag-Erling Smørgrav tm.tm_year -= 1900; 1357*09a3aaf3SDag-Erling Smørgrav tm.tm_mon--; 1358*09a3aaf3SDag-Erling Smørgrav /* Check values */ 1359*09a3aaf3SDag-Erling Smørgrav if (tm.tm_year < 70) 1360*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1361*09a3aaf3SDag-Erling Smørgrav if (tm.tm_mon < 0 || tm.tm_mon > 11) 1362*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1363*09a3aaf3SDag-Erling Smørgrav if (tm.tm_mday < 1 || tm.tm_mday > 31) 1364*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1365*09a3aaf3SDag-Erling Smørgrav if (tm.tm_hour < 0 || tm.tm_hour > 23) 1366*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1367*09a3aaf3SDag-Erling Smørgrav if (tm.tm_min < 0 || tm.tm_min > 59) 1368*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1369*09a3aaf3SDag-Erling Smørgrav if (tm.tm_sec < 0 || tm.tm_sec > 59) 1370*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1371*09a3aaf3SDag-Erling Smørgrav 1372*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd, sldns_mktime_from_utc(&tm)); 1373*09a3aaf3SDag-Erling Smørgrav } else { 1374*09a3aaf3SDag-Erling Smørgrav /* handle it as 32 bits timestamp */ 1375*09a3aaf3SDag-Erling Smørgrav char *end; 1376*09a3aaf3SDag-Erling Smørgrav uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 1377*09a3aaf3SDag-Erling Smørgrav if(*end != 0) 1378*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 1379*09a3aaf3SDag-Erling Smørgrav end-(char*)str); 1380*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd, l); 1381*09a3aaf3SDag-Erling Smørgrav } 1382*09a3aaf3SDag-Erling Smørgrav *len = 4; 1383*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1384*09a3aaf3SDag-Erling Smørgrav } 1385*09a3aaf3SDag-Erling Smørgrav 1386*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 1387*09a3aaf3SDag-Erling Smørgrav { 1388*09a3aaf3SDag-Erling Smørgrav const char* end; 1389*09a3aaf3SDag-Erling Smørgrav uint32_t p = sldns_str2period(str, &end); 1390*09a3aaf3SDag-Erling Smørgrav if(*end != 0) 1391*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 1392*09a3aaf3SDag-Erling Smørgrav if(*len < 4) 1393*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1394*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd, p); 1395*09a3aaf3SDag-Erling Smørgrav *len = 4; 1396*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1397*09a3aaf3SDag-Erling Smørgrav } 1398*09a3aaf3SDag-Erling Smørgrav 1399*09a3aaf3SDag-Erling Smørgrav /** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 1400*09a3aaf3SDag-Erling Smørgrav static int 1401*09a3aaf3SDag-Erling Smørgrav loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 1402*09a3aaf3SDag-Erling Smørgrav { 1403*09a3aaf3SDag-Erling Smørgrav uint32_t meters = 0, cm = 0, val; 1404*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) { 1405*09a3aaf3SDag-Erling Smørgrav my_str++; 1406*09a3aaf3SDag-Erling Smørgrav } 1407*09a3aaf3SDag-Erling Smørgrav meters = (uint32_t)strtol(my_str, &my_str, 10); 1408*09a3aaf3SDag-Erling Smørgrav if (*my_str == '.') { 1409*09a3aaf3SDag-Erling Smørgrav my_str++; 1410*09a3aaf3SDag-Erling Smørgrav cm = (uint32_t)strtol(my_str, &my_str, 10); 1411*09a3aaf3SDag-Erling Smørgrav } 1412*09a3aaf3SDag-Erling Smørgrav if (meters >= 1) { 1413*09a3aaf3SDag-Erling Smørgrav *e = 2; 1414*09a3aaf3SDag-Erling Smørgrav val = meters; 1415*09a3aaf3SDag-Erling Smørgrav } else { 1416*09a3aaf3SDag-Erling Smørgrav *e = 0; 1417*09a3aaf3SDag-Erling Smørgrav val = cm; 1418*09a3aaf3SDag-Erling Smørgrav } 1419*09a3aaf3SDag-Erling Smørgrav while(val >= 10) { 1420*09a3aaf3SDag-Erling Smørgrav (*e)++; 1421*09a3aaf3SDag-Erling Smørgrav val /= 10; 1422*09a3aaf3SDag-Erling Smørgrav } 1423*09a3aaf3SDag-Erling Smørgrav *m = (uint8_t)val; 1424*09a3aaf3SDag-Erling Smørgrav 1425*09a3aaf3SDag-Erling Smørgrav if (*e > 9) 1426*09a3aaf3SDag-Erling Smørgrav return 0; 1427*09a3aaf3SDag-Erling Smørgrav if (*my_str == 'm' || *my_str == 'M') { 1428*09a3aaf3SDag-Erling Smørgrav my_str++; 1429*09a3aaf3SDag-Erling Smørgrav } 1430*09a3aaf3SDag-Erling Smørgrav *endstr = my_str; 1431*09a3aaf3SDag-Erling Smørgrav return 1; 1432*09a3aaf3SDag-Erling Smørgrav } 1433*09a3aaf3SDag-Erling Smørgrav 1434*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 1435*09a3aaf3SDag-Erling Smørgrav { 1436*09a3aaf3SDag-Erling Smørgrav uint32_t latitude = 0; 1437*09a3aaf3SDag-Erling Smørgrav uint32_t longitude = 0; 1438*09a3aaf3SDag-Erling Smørgrav uint32_t altitude = 0; 1439*09a3aaf3SDag-Erling Smørgrav 1440*09a3aaf3SDag-Erling Smørgrav uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 1441*09a3aaf3SDag-Erling Smørgrav 1442*09a3aaf3SDag-Erling Smørgrav /* only support version 0 */ 1443*09a3aaf3SDag-Erling Smørgrav uint32_t h = 0; 1444*09a3aaf3SDag-Erling Smørgrav uint32_t m = 0; 1445*09a3aaf3SDag-Erling Smørgrav uint8_t size_b = 1, size_e = 2; 1446*09a3aaf3SDag-Erling Smørgrav uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 1447*09a3aaf3SDag-Erling Smørgrav uint8_t vert_pre_b = 1, vert_pre_e = 3; 1448*09a3aaf3SDag-Erling Smørgrav 1449*09a3aaf3SDag-Erling Smørgrav double s = 0.0; 1450*09a3aaf3SDag-Erling Smørgrav int northerness; 1451*09a3aaf3SDag-Erling Smørgrav int easterness; 1452*09a3aaf3SDag-Erling Smørgrav 1453*09a3aaf3SDag-Erling Smørgrav char *my_str = (char *) str; 1454*09a3aaf3SDag-Erling Smørgrav 1455*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1456*09a3aaf3SDag-Erling Smørgrav h = (uint32_t) strtol(my_str, &my_str, 10); 1457*09a3aaf3SDag-Erling Smørgrav } else { 1458*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1459*09a3aaf3SDag-Erling Smørgrav } 1460*09a3aaf3SDag-Erling Smørgrav 1461*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char) *my_str)) { 1462*09a3aaf3SDag-Erling Smørgrav my_str++; 1463*09a3aaf3SDag-Erling Smørgrav } 1464*09a3aaf3SDag-Erling Smørgrav 1465*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1466*09a3aaf3SDag-Erling Smørgrav m = (uint32_t) strtol(my_str, &my_str, 10); 1467*09a3aaf3SDag-Erling Smørgrav } else if (*my_str == 'N' || *my_str == 'S') { 1468*09a3aaf3SDag-Erling Smørgrav goto north; 1469*09a3aaf3SDag-Erling Smørgrav } else { 1470*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1471*09a3aaf3SDag-Erling Smørgrav } 1472*09a3aaf3SDag-Erling Smørgrav 1473*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char) *my_str)) { 1474*09a3aaf3SDag-Erling Smørgrav my_str++; 1475*09a3aaf3SDag-Erling Smørgrav } 1476*09a3aaf3SDag-Erling Smørgrav 1477*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1478*09a3aaf3SDag-Erling Smørgrav s = strtod(my_str, &my_str); 1479*09a3aaf3SDag-Erling Smørgrav } 1480*09a3aaf3SDag-Erling Smørgrav 1481*09a3aaf3SDag-Erling Smørgrav /* skip blanks before norterness */ 1482*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char) *my_str)) { 1483*09a3aaf3SDag-Erling Smørgrav my_str++; 1484*09a3aaf3SDag-Erling Smørgrav } 1485*09a3aaf3SDag-Erling Smørgrav 1486*09a3aaf3SDag-Erling Smørgrav north: 1487*09a3aaf3SDag-Erling Smørgrav if (*my_str == 'N') { 1488*09a3aaf3SDag-Erling Smørgrav northerness = 1; 1489*09a3aaf3SDag-Erling Smørgrav } else if (*my_str == 'S') { 1490*09a3aaf3SDag-Erling Smørgrav northerness = 0; 1491*09a3aaf3SDag-Erling Smørgrav } else { 1492*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1493*09a3aaf3SDag-Erling Smørgrav } 1494*09a3aaf3SDag-Erling Smørgrav 1495*09a3aaf3SDag-Erling Smørgrav my_str++; 1496*09a3aaf3SDag-Erling Smørgrav 1497*09a3aaf3SDag-Erling Smørgrav /* store number */ 1498*09a3aaf3SDag-Erling Smørgrav s = 1000.0 * s; 1499*09a3aaf3SDag-Erling Smørgrav /* add a little to make floor in conversion a round */ 1500*09a3aaf3SDag-Erling Smørgrav s += 0.0005; 1501*09a3aaf3SDag-Erling Smørgrav latitude = (uint32_t) s; 1502*09a3aaf3SDag-Erling Smørgrav latitude += 1000 * 60 * m; 1503*09a3aaf3SDag-Erling Smørgrav latitude += 1000 * 60 * 60 * h; 1504*09a3aaf3SDag-Erling Smørgrav if (northerness) { 1505*09a3aaf3SDag-Erling Smørgrav latitude = equator + latitude; 1506*09a3aaf3SDag-Erling Smørgrav } else { 1507*09a3aaf3SDag-Erling Smørgrav latitude = equator - latitude; 1508*09a3aaf3SDag-Erling Smørgrav } 1509*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) { 1510*09a3aaf3SDag-Erling Smørgrav my_str++; 1511*09a3aaf3SDag-Erling Smørgrav } 1512*09a3aaf3SDag-Erling Smørgrav 1513*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1514*09a3aaf3SDag-Erling Smørgrav h = (uint32_t) strtol(my_str, &my_str, 10); 1515*09a3aaf3SDag-Erling Smørgrav } else { 1516*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1517*09a3aaf3SDag-Erling Smørgrav } 1518*09a3aaf3SDag-Erling Smørgrav 1519*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char) *my_str)) { 1520*09a3aaf3SDag-Erling Smørgrav my_str++; 1521*09a3aaf3SDag-Erling Smørgrav } 1522*09a3aaf3SDag-Erling Smørgrav 1523*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1524*09a3aaf3SDag-Erling Smørgrav m = (uint32_t) strtol(my_str, &my_str, 10); 1525*09a3aaf3SDag-Erling Smørgrav } else if (*my_str == 'E' || *my_str == 'W') { 1526*09a3aaf3SDag-Erling Smørgrav goto east; 1527*09a3aaf3SDag-Erling Smørgrav } else { 1528*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1529*09a3aaf3SDag-Erling Smørgrav } 1530*09a3aaf3SDag-Erling Smørgrav 1531*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) { 1532*09a3aaf3SDag-Erling Smørgrav my_str++; 1533*09a3aaf3SDag-Erling Smørgrav } 1534*09a3aaf3SDag-Erling Smørgrav 1535*09a3aaf3SDag-Erling Smørgrav if (isdigit((unsigned char) *my_str)) { 1536*09a3aaf3SDag-Erling Smørgrav s = strtod(my_str, &my_str); 1537*09a3aaf3SDag-Erling Smørgrav } 1538*09a3aaf3SDag-Erling Smørgrav 1539*09a3aaf3SDag-Erling Smørgrav /* skip blanks before easterness */ 1540*09a3aaf3SDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) { 1541*09a3aaf3SDag-Erling Smørgrav my_str++; 1542*09a3aaf3SDag-Erling Smørgrav } 1543*09a3aaf3SDag-Erling Smørgrav 1544*09a3aaf3SDag-Erling Smørgrav east: 1545*09a3aaf3SDag-Erling Smørgrav if (*my_str == 'E') { 1546*09a3aaf3SDag-Erling Smørgrav easterness = 1; 1547*09a3aaf3SDag-Erling Smørgrav } else if (*my_str == 'W') { 1548*09a3aaf3SDag-Erling Smørgrav easterness = 0; 1549*09a3aaf3SDag-Erling Smørgrav } else { 1550*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1551*09a3aaf3SDag-Erling Smørgrav } 1552*09a3aaf3SDag-Erling Smørgrav 1553*09a3aaf3SDag-Erling Smørgrav my_str++; 1554*09a3aaf3SDag-Erling Smørgrav 1555*09a3aaf3SDag-Erling Smørgrav /* store number */ 1556*09a3aaf3SDag-Erling Smørgrav s *= 1000.0; 1557*09a3aaf3SDag-Erling Smørgrav /* add a little to make floor in conversion a round */ 1558*09a3aaf3SDag-Erling Smørgrav s += 0.0005; 1559*09a3aaf3SDag-Erling Smørgrav longitude = (uint32_t) s; 1560*09a3aaf3SDag-Erling Smørgrav longitude += 1000 * 60 * m; 1561*09a3aaf3SDag-Erling Smørgrav longitude += 1000 * 60 * 60 * h; 1562*09a3aaf3SDag-Erling Smørgrav 1563*09a3aaf3SDag-Erling Smørgrav if (easterness) { 1564*09a3aaf3SDag-Erling Smørgrav longitude += equator; 1565*09a3aaf3SDag-Erling Smørgrav } else { 1566*09a3aaf3SDag-Erling Smørgrav longitude = equator - longitude; 1567*09a3aaf3SDag-Erling Smørgrav } 1568*09a3aaf3SDag-Erling Smørgrav 1569*09a3aaf3SDag-Erling Smørgrav altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1570*09a3aaf3SDag-Erling Smørgrav 10000000.0 + 0.5); 1571*09a3aaf3SDag-Erling Smørgrav if (*my_str == 'm' || *my_str == 'M') { 1572*09a3aaf3SDag-Erling Smørgrav my_str++; 1573*09a3aaf3SDag-Erling Smørgrav } 1574*09a3aaf3SDag-Erling Smørgrav 1575*09a3aaf3SDag-Erling Smørgrav if (strlen(my_str) > 0) { 1576*09a3aaf3SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1577*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1578*09a3aaf3SDag-Erling Smørgrav } 1579*09a3aaf3SDag-Erling Smørgrav 1580*09a3aaf3SDag-Erling Smørgrav if (strlen(my_str) > 0) { 1581*09a3aaf3SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1582*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1583*09a3aaf3SDag-Erling Smørgrav } 1584*09a3aaf3SDag-Erling Smørgrav 1585*09a3aaf3SDag-Erling Smørgrav if (strlen(my_str) > 0) { 1586*09a3aaf3SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1587*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1588*09a3aaf3SDag-Erling Smørgrav } 1589*09a3aaf3SDag-Erling Smørgrav 1590*09a3aaf3SDag-Erling Smørgrav if(*len < 16) 1591*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1592*09a3aaf3SDag-Erling Smørgrav rd[0] = 0; 1593*09a3aaf3SDag-Erling Smørgrav rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1594*09a3aaf3SDag-Erling Smørgrav rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1595*09a3aaf3SDag-Erling Smørgrav rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1596*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd + 4, latitude); 1597*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd + 8, longitude); 1598*09a3aaf3SDag-Erling Smørgrav sldns_write_uint32(rd + 12, altitude); 1599*09a3aaf3SDag-Erling Smørgrav *len = 16; 1600*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1601*09a3aaf3SDag-Erling Smørgrav } 1602*09a3aaf3SDag-Erling Smørgrav 1603*09a3aaf3SDag-Erling Smørgrav static void 1604*09a3aaf3SDag-Erling Smørgrav ldns_tolower_str(char* s) 1605*09a3aaf3SDag-Erling Smørgrav { 1606*09a3aaf3SDag-Erling Smørgrav if(s) { 1607*09a3aaf3SDag-Erling Smørgrav while(*s) { 1608*09a3aaf3SDag-Erling Smørgrav *s = (char)tolower((unsigned char)*s); 1609*09a3aaf3SDag-Erling Smørgrav s++; 1610*09a3aaf3SDag-Erling Smørgrav } 1611*09a3aaf3SDag-Erling Smørgrav } 1612*09a3aaf3SDag-Erling Smørgrav } 1613*09a3aaf3SDag-Erling Smørgrav 1614*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 1615*09a3aaf3SDag-Erling Smørgrav { 1616*09a3aaf3SDag-Erling Smørgrav int rd_len = 1; 1617*09a3aaf3SDag-Erling Smørgrav int have_proto = 0; 1618*09a3aaf3SDag-Erling Smørgrav char token[50], proto_str[50]; 1619*09a3aaf3SDag-Erling Smørgrav sldns_buffer strbuf; 1620*09a3aaf3SDag-Erling Smørgrav sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1621*09a3aaf3SDag-Erling Smørgrav proto_str[0]=0; 1622*09a3aaf3SDag-Erling Smørgrav 1623*09a3aaf3SDag-Erling Smørgrav /* check we have one byte for proto */ 1624*09a3aaf3SDag-Erling Smørgrav if(*len < 1) 1625*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1626*09a3aaf3SDag-Erling Smørgrav 1627*09a3aaf3SDag-Erling Smørgrav while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 1628*09a3aaf3SDag-Erling Smørgrav ldns_tolower_str(token); 1629*09a3aaf3SDag-Erling Smørgrav if(!have_proto) { 1630*09a3aaf3SDag-Erling Smørgrav struct protoent *p = getprotobyname(token); 1631*09a3aaf3SDag-Erling Smørgrav have_proto = 1; 1632*09a3aaf3SDag-Erling Smørgrav if(p) rd[0] = (uint8_t)p->p_proto; 1633*09a3aaf3SDag-Erling Smørgrav else rd[0] = (uint8_t)atoi(token); 1634*09a3aaf3SDag-Erling Smørgrav (void)strlcpy(proto_str, token, sizeof(proto_str)); 1635*09a3aaf3SDag-Erling Smørgrav } else { 1636*09a3aaf3SDag-Erling Smørgrav int serv_port; 1637*09a3aaf3SDag-Erling Smørgrav struct servent *serv = getservbyname(token, proto_str); 1638*09a3aaf3SDag-Erling Smørgrav if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 1639*09a3aaf3SDag-Erling Smørgrav else { 1640*09a3aaf3SDag-Erling Smørgrav serv_port = atoi(token); 1641*09a3aaf3SDag-Erling Smørgrav if(serv_port == 0 && strcmp(token, "0") != 0) { 1642*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDSERVENT 1643*09a3aaf3SDag-Erling Smørgrav endservent(); 1644*09a3aaf3SDag-Erling Smørgrav #endif 1645*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDPROTOENT 1646*09a3aaf3SDag-Erling Smørgrav endprotoent(); 1647*09a3aaf3SDag-Erling Smørgrav #endif 1648*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1649*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1650*09a3aaf3SDag-Erling Smørgrav } 1651*09a3aaf3SDag-Erling Smørgrav if(serv_port < 0 || serv_port > 65535) { 1652*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDSERVENT 1653*09a3aaf3SDag-Erling Smørgrav endservent(); 1654*09a3aaf3SDag-Erling Smørgrav #endif 1655*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDPROTOENT 1656*09a3aaf3SDag-Erling Smørgrav endprotoent(); 1657*09a3aaf3SDag-Erling Smørgrav #endif 1658*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1659*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1660*09a3aaf3SDag-Erling Smørgrav } 1661*09a3aaf3SDag-Erling Smørgrav } 1662*09a3aaf3SDag-Erling Smørgrav if(rd_len < 1+serv_port/8+1) { 1663*09a3aaf3SDag-Erling Smørgrav /* bitmap is larger, init new bytes at 0 */ 1664*09a3aaf3SDag-Erling Smørgrav if(*len < 1+(size_t)serv_port/8+1) { 1665*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDSERVENT 1666*09a3aaf3SDag-Erling Smørgrav endservent(); 1667*09a3aaf3SDag-Erling Smørgrav #endif 1668*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDPROTOENT 1669*09a3aaf3SDag-Erling Smørgrav endprotoent(); 1670*09a3aaf3SDag-Erling Smørgrav #endif 1671*09a3aaf3SDag-Erling Smørgrav return RET_ERR( 1672*09a3aaf3SDag-Erling Smørgrav LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1673*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1674*09a3aaf3SDag-Erling Smørgrav } 1675*09a3aaf3SDag-Erling Smørgrav memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 1676*09a3aaf3SDag-Erling Smørgrav rd_len = 1+serv_port/8+1; 1677*09a3aaf3SDag-Erling Smørgrav } 1678*09a3aaf3SDag-Erling Smørgrav rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 1679*09a3aaf3SDag-Erling Smørgrav } 1680*09a3aaf3SDag-Erling Smørgrav } 1681*09a3aaf3SDag-Erling Smørgrav *len = (size_t)rd_len; 1682*09a3aaf3SDag-Erling Smørgrav 1683*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDSERVENT 1684*09a3aaf3SDag-Erling Smørgrav endservent(); 1685*09a3aaf3SDag-Erling Smørgrav #endif 1686*09a3aaf3SDag-Erling Smørgrav #ifdef HAVE_ENDPROTOENT 1687*09a3aaf3SDag-Erling Smørgrav endprotoent(); 1688*09a3aaf3SDag-Erling Smørgrav #endif 1689*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1690*09a3aaf3SDag-Erling Smørgrav } 1691*09a3aaf3SDag-Erling Smørgrav 1692*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 1693*09a3aaf3SDag-Erling Smørgrav { 1694*09a3aaf3SDag-Erling Smørgrav const char* s = str; 1695*09a3aaf3SDag-Erling Smørgrav size_t slen; 1696*09a3aaf3SDag-Erling Smørgrav size_t dlen = 0; /* number of hexdigits parsed */ 1697*09a3aaf3SDag-Erling Smørgrav 1698*09a3aaf3SDag-Erling Smørgrav /* just a hex string with optional dots? */ 1699*09a3aaf3SDag-Erling Smørgrav if (s[0] != '0' || s[1] != 'x') 1700*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_INVALID_STR; 1701*09a3aaf3SDag-Erling Smørgrav s += 2; 1702*09a3aaf3SDag-Erling Smørgrav slen = strlen(s); 1703*09a3aaf3SDag-Erling Smørgrav if(slen > LDNS_MAX_RDFLEN*2) 1704*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1705*09a3aaf3SDag-Erling Smørgrav while(*s) { 1706*09a3aaf3SDag-Erling Smørgrav if(isspace((unsigned char)*s) || *s == '.') { 1707*09a3aaf3SDag-Erling Smørgrav s++; 1708*09a3aaf3SDag-Erling Smørgrav continue; 1709*09a3aaf3SDag-Erling Smørgrav } 1710*09a3aaf3SDag-Erling Smørgrav if(!isxdigit((unsigned char)*s)) 1711*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1712*09a3aaf3SDag-Erling Smørgrav if(*len < dlen/2 + 1) 1713*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1714*09a3aaf3SDag-Erling Smørgrav s-str); 1715*09a3aaf3SDag-Erling Smørgrav if((dlen&1)==0) 1716*09a3aaf3SDag-Erling Smørgrav rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1717*09a3aaf3SDag-Erling Smørgrav else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1718*09a3aaf3SDag-Erling Smørgrav dlen++; 1719*09a3aaf3SDag-Erling Smørgrav } 1720*09a3aaf3SDag-Erling Smørgrav if((dlen&1)!=0) 1721*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1722*09a3aaf3SDag-Erling Smørgrav *len = dlen/2; 1723*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1724*09a3aaf3SDag-Erling Smørgrav } 1725*09a3aaf3SDag-Erling Smørgrav 1726*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 1727*09a3aaf3SDag-Erling Smørgrav { 1728*09a3aaf3SDag-Erling Smørgrav const char* s = str; 1729*09a3aaf3SDag-Erling Smørgrav size_t slen = strlen(str); 1730*09a3aaf3SDag-Erling Smørgrav size_t dlen = 0; /* number of hexdigits parsed */ 1731*09a3aaf3SDag-Erling Smørgrav 1732*09a3aaf3SDag-Erling Smørgrav /* just a hex string with optional dots? */ 1733*09a3aaf3SDag-Erling Smørgrav /* notimpl e.164 format */ 1734*09a3aaf3SDag-Erling Smørgrav if(slen > LDNS_MAX_RDFLEN*2) 1735*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1736*09a3aaf3SDag-Erling Smørgrav while(*s) { 1737*09a3aaf3SDag-Erling Smørgrav if(isspace((unsigned char)*s) || *s == '.') { 1738*09a3aaf3SDag-Erling Smørgrav s++; 1739*09a3aaf3SDag-Erling Smørgrav continue; 1740*09a3aaf3SDag-Erling Smørgrav } 1741*09a3aaf3SDag-Erling Smørgrav if(!isxdigit((unsigned char)*s)) 1742*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1743*09a3aaf3SDag-Erling Smørgrav if(*len < dlen/2 + 1) 1744*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1745*09a3aaf3SDag-Erling Smørgrav s-str); 1746*09a3aaf3SDag-Erling Smørgrav if((dlen&1)==0) 1747*09a3aaf3SDag-Erling Smørgrav rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1748*09a3aaf3SDag-Erling Smørgrav else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1749*09a3aaf3SDag-Erling Smørgrav dlen++; 1750*09a3aaf3SDag-Erling Smørgrav } 1751*09a3aaf3SDag-Erling Smørgrav if((dlen&1)!=0) 1752*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1753*09a3aaf3SDag-Erling Smørgrav *len = dlen/2; 1754*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1755*09a3aaf3SDag-Erling Smørgrav } 1756*09a3aaf3SDag-Erling Smørgrav 1757*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 1758*09a3aaf3SDag-Erling Smørgrav { 1759*09a3aaf3SDag-Erling Smørgrav size_t gwlen = 0, keylen = 0; 1760*09a3aaf3SDag-Erling Smørgrav int s; 1761*09a3aaf3SDag-Erling Smørgrav uint8_t gwtype; 1762*09a3aaf3SDag-Erling Smørgrav char token[512]; 1763*09a3aaf3SDag-Erling Smørgrav sldns_buffer strbuf; 1764*09a3aaf3SDag-Erling Smørgrav sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1765*09a3aaf3SDag-Erling Smørgrav 1766*09a3aaf3SDag-Erling Smørgrav if(*len < 3) 1767*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1768*09a3aaf3SDag-Erling Smørgrav /* precedence */ 1769*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1770*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1771*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1772*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t)atoi(token); 1773*09a3aaf3SDag-Erling Smørgrav /* gateway_type */ 1774*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1775*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1776*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1777*09a3aaf3SDag-Erling Smørgrav rd[1] = (uint8_t)atoi(token); 1778*09a3aaf3SDag-Erling Smørgrav gwtype = rd[1]; 1779*09a3aaf3SDag-Erling Smørgrav /* algorithm */ 1780*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1781*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1782*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1783*09a3aaf3SDag-Erling Smørgrav rd[2] = (uint8_t)atoi(token); 1784*09a3aaf3SDag-Erling Smørgrav 1785*09a3aaf3SDag-Erling Smørgrav /* gateway */ 1786*09a3aaf3SDag-Erling Smørgrav if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1787*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1788*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1789*09a3aaf3SDag-Erling Smørgrav if(gwtype == 0) { 1790*09a3aaf3SDag-Erling Smørgrav /* NOGATEWAY */ 1791*09a3aaf3SDag-Erling Smørgrav if(strcmp(token, ".") != 0) 1792*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1793*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1794*09a3aaf3SDag-Erling Smørgrav gwlen = 0; 1795*09a3aaf3SDag-Erling Smørgrav } else if(gwtype == 1) { 1796*09a3aaf3SDag-Erling Smørgrav /* IP4 */ 1797*09a3aaf3SDag-Erling Smørgrav gwlen = *len - 3; 1798*09a3aaf3SDag-Erling Smørgrav s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 1799*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1800*09a3aaf3SDag-Erling Smørgrav } else if(gwtype == 2) { 1801*09a3aaf3SDag-Erling Smørgrav /* IP6 */ 1802*09a3aaf3SDag-Erling Smørgrav gwlen = *len - 3; 1803*09a3aaf3SDag-Erling Smørgrav s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 1804*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1805*09a3aaf3SDag-Erling Smørgrav } else if(gwtype == 3) { 1806*09a3aaf3SDag-Erling Smørgrav /* DNAME */ 1807*09a3aaf3SDag-Erling Smørgrav gwlen = *len - 3; 1808*09a3aaf3SDag-Erling Smørgrav s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 1809*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1810*09a3aaf3SDag-Erling Smørgrav } else { 1811*09a3aaf3SDag-Erling Smørgrav /* unknown gateway type */ 1812*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1813*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1814*09a3aaf3SDag-Erling Smørgrav } 1815*09a3aaf3SDag-Erling Smørgrav /* double check for size */ 1816*09a3aaf3SDag-Erling Smørgrav if(*len < 3 + gwlen) 1817*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1818*09a3aaf3SDag-Erling Smørgrav sldns_buffer_position(&strbuf)); 1819*09a3aaf3SDag-Erling Smørgrav 1820*09a3aaf3SDag-Erling Smørgrav /* publickey in remainder of strbuf */ 1821*09a3aaf3SDag-Erling Smørgrav keylen = *len - 3 - gwlen; 1822*09a3aaf3SDag-Erling Smørgrav s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 1823*09a3aaf3SDag-Erling Smørgrav rd+3+gwlen, &keylen); 1824*09a3aaf3SDag-Erling Smørgrav if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1825*09a3aaf3SDag-Erling Smørgrav 1826*09a3aaf3SDag-Erling Smørgrav *len = 3 + gwlen + keylen; 1827*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1828*09a3aaf3SDag-Erling Smørgrav } 1829*09a3aaf3SDag-Erling Smørgrav 1830*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 1831*09a3aaf3SDag-Erling Smørgrav { 1832*09a3aaf3SDag-Erling Smørgrav int i, salt_length_str = (int)strlen(str); 1833*09a3aaf3SDag-Erling Smørgrav if (salt_length_str == 1 && str[0] == '-') { 1834*09a3aaf3SDag-Erling Smørgrav salt_length_str = 0; 1835*09a3aaf3SDag-Erling Smørgrav } else if (salt_length_str % 2 != 0) { 1836*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1837*09a3aaf3SDag-Erling Smørgrav } 1838*09a3aaf3SDag-Erling Smørgrav if (salt_length_str > 512) 1839*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1840*09a3aaf3SDag-Erling Smørgrav if(*len < 1+(size_t)salt_length_str / 2) 1841*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1842*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t) (salt_length_str / 2); 1843*09a3aaf3SDag-Erling Smørgrav for (i = 0; i < salt_length_str; i += 2) { 1844*09a3aaf3SDag-Erling Smørgrav if (isxdigit((unsigned char)str[i]) && 1845*09a3aaf3SDag-Erling Smørgrav isxdigit((unsigned char)str[i+1])) { 1846*09a3aaf3SDag-Erling Smørgrav rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 1847*09a3aaf3SDag-Erling Smørgrav + sldns_hexdigit_to_int(str[i+1])); 1848*09a3aaf3SDag-Erling Smørgrav } else { 1849*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 1850*09a3aaf3SDag-Erling Smørgrav } 1851*09a3aaf3SDag-Erling Smørgrav } 1852*09a3aaf3SDag-Erling Smørgrav *len = 1 + (size_t)rd[0]; 1853*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1854*09a3aaf3SDag-Erling Smørgrav } 1855*09a3aaf3SDag-Erling Smørgrav 1856*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 1857*09a3aaf3SDag-Erling Smørgrav { 1858*09a3aaf3SDag-Erling Smørgrav unsigned int a, b, c, d; 1859*09a3aaf3SDag-Erling Smørgrav uint16_t shorts[4]; 1860*09a3aaf3SDag-Erling Smørgrav int l; 1861*09a3aaf3SDag-Erling Smørgrav if(*len < sizeof(shorts)) 1862*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1863*09a3aaf3SDag-Erling Smørgrav 1864*09a3aaf3SDag-Erling Smørgrav if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1865*09a3aaf3SDag-Erling Smørgrav l != (int)strlen(str) || /* more data to read */ 1866*09a3aaf3SDag-Erling Smørgrav strpbrk(str, "+-") /* signed hexes */ 1867*09a3aaf3SDag-Erling Smørgrav ) 1868*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 1869*09a3aaf3SDag-Erling Smørgrav shorts[0] = htons(a); 1870*09a3aaf3SDag-Erling Smørgrav shorts[1] = htons(b); 1871*09a3aaf3SDag-Erling Smørgrav shorts[2] = htons(c); 1872*09a3aaf3SDag-Erling Smørgrav shorts[3] = htons(d); 1873*09a3aaf3SDag-Erling Smørgrav memmove(rd, &shorts, sizeof(shorts)); 1874*09a3aaf3SDag-Erling Smørgrav *len = sizeof(shorts); 1875*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1876*09a3aaf3SDag-Erling Smørgrav } 1877*09a3aaf3SDag-Erling Smørgrav 1878*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 1879*09a3aaf3SDag-Erling Smørgrav { 1880*09a3aaf3SDag-Erling Smørgrav unsigned int a, b, c, d, e, f; 1881*09a3aaf3SDag-Erling Smørgrav int l; 1882*09a3aaf3SDag-Erling Smørgrav 1883*09a3aaf3SDag-Erling Smørgrav if(*len < 6) 1884*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1885*09a3aaf3SDag-Erling Smørgrav if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1886*09a3aaf3SDag-Erling Smørgrav &a, &b, &c, &d, &e, &f, &l) != 6 || 1887*09a3aaf3SDag-Erling Smørgrav l != (int)strlen(str)) 1888*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 1889*09a3aaf3SDag-Erling Smørgrav rd[0] = a; 1890*09a3aaf3SDag-Erling Smørgrav rd[1] = b; 1891*09a3aaf3SDag-Erling Smørgrav rd[2] = c; 1892*09a3aaf3SDag-Erling Smørgrav rd[3] = d; 1893*09a3aaf3SDag-Erling Smørgrav rd[4] = e; 1894*09a3aaf3SDag-Erling Smørgrav rd[5] = f; 1895*09a3aaf3SDag-Erling Smørgrav *len = 6; 1896*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1897*09a3aaf3SDag-Erling Smørgrav } 1898*09a3aaf3SDag-Erling Smørgrav 1899*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 1900*09a3aaf3SDag-Erling Smørgrav { 1901*09a3aaf3SDag-Erling Smørgrav unsigned int a, b, c, d, e, f, g, h; 1902*09a3aaf3SDag-Erling Smørgrav int l; 1903*09a3aaf3SDag-Erling Smørgrav 1904*09a3aaf3SDag-Erling Smørgrav if(*len < 8) 1905*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1906*09a3aaf3SDag-Erling Smørgrav if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1907*09a3aaf3SDag-Erling Smørgrav &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1908*09a3aaf3SDag-Erling Smørgrav l != (int)strlen(str)) 1909*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 1910*09a3aaf3SDag-Erling Smørgrav rd[0] = a; 1911*09a3aaf3SDag-Erling Smørgrav rd[1] = b; 1912*09a3aaf3SDag-Erling Smørgrav rd[2] = c; 1913*09a3aaf3SDag-Erling Smørgrav rd[3] = d; 1914*09a3aaf3SDag-Erling Smørgrav rd[4] = e; 1915*09a3aaf3SDag-Erling Smørgrav rd[5] = f; 1916*09a3aaf3SDag-Erling Smørgrav rd[6] = g; 1917*09a3aaf3SDag-Erling Smørgrav rd[7] = h; 1918*09a3aaf3SDag-Erling Smørgrav *len = 8; 1919*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1920*09a3aaf3SDag-Erling Smørgrav } 1921*09a3aaf3SDag-Erling Smørgrav 1922*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 1923*09a3aaf3SDag-Erling Smørgrav { 1924*09a3aaf3SDag-Erling Smørgrav size_t slen = strlen(str); 1925*09a3aaf3SDag-Erling Smørgrav const char* ptr; 1926*09a3aaf3SDag-Erling Smørgrav 1927*09a3aaf3SDag-Erling Smørgrav if (slen > 255) 1928*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 1929*09a3aaf3SDag-Erling Smørgrav if(*len < slen+1) 1930*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1931*09a3aaf3SDag-Erling Smørgrav for (ptr = str; *ptr; ptr++) { 1932*09a3aaf3SDag-Erling Smørgrav if(!isalnum((unsigned char)*ptr)) 1933*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 1934*09a3aaf3SDag-Erling Smørgrav } 1935*09a3aaf3SDag-Erling Smørgrav rd[0] = slen; 1936*09a3aaf3SDag-Erling Smørgrav memmove(rd+1, str, slen); 1937*09a3aaf3SDag-Erling Smørgrav *len = slen+1; 1938*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1939*09a3aaf3SDag-Erling Smørgrav } 1940*09a3aaf3SDag-Erling Smørgrav 1941*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 1942*09a3aaf3SDag-Erling Smørgrav { 1943*09a3aaf3SDag-Erling Smørgrav uint8_t ch = 0; 1944*09a3aaf3SDag-Erling Smørgrav const char* pstr = str; 1945*09a3aaf3SDag-Erling Smørgrav size_t length = 0; 1946*09a3aaf3SDag-Erling Smørgrav 1947*09a3aaf3SDag-Erling Smørgrav /* Fill data with parsed bytes */ 1948*09a3aaf3SDag-Erling Smørgrav while (sldns_parse_char(&ch, &pstr)) { 1949*09a3aaf3SDag-Erling Smørgrav if(*len < length+1) 1950*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1951*09a3aaf3SDag-Erling Smørgrav rd[length++] = ch; 1952*09a3aaf3SDag-Erling Smørgrav } 1953*09a3aaf3SDag-Erling Smørgrav if(!pstr) 1954*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1955*09a3aaf3SDag-Erling Smørgrav *len = length; 1956*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 1957*09a3aaf3SDag-Erling Smørgrav } 1958*09a3aaf3SDag-Erling Smørgrav 1959*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 1960*09a3aaf3SDag-Erling Smørgrav { 1961*09a3aaf3SDag-Erling Smørgrav char* s, *end; 1962*09a3aaf3SDag-Erling Smørgrav int e; 1963*09a3aaf3SDag-Erling Smørgrav size_t hitlen, pklen = 0; 1964*09a3aaf3SDag-Erling Smørgrav /* presentation format: 1965*09a3aaf3SDag-Erling Smørgrav * pk-algo HIThex pubkeybase64 1966*09a3aaf3SDag-Erling Smørgrav * wireformat: 1967*09a3aaf3SDag-Erling Smørgrav * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 1968*09a3aaf3SDag-Erling Smørgrav if(*len < 4) 1969*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1970*09a3aaf3SDag-Erling Smørgrav 1971*09a3aaf3SDag-Erling Smørgrav /* read PK algorithm */ 1972*09a3aaf3SDag-Erling Smørgrav rd[1] = (uint8_t)strtol((char*)str, &s, 10); 1973*09a3aaf3SDag-Erling Smørgrav if(*s != ' ') 1974*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 1975*09a3aaf3SDag-Erling Smørgrav s++; 1976*09a3aaf3SDag-Erling Smørgrav while(*s == ' ') 1977*09a3aaf3SDag-Erling Smørgrav s++; 1978*09a3aaf3SDag-Erling Smørgrav 1979*09a3aaf3SDag-Erling Smørgrav /* read HIT hex tag */ 1980*09a3aaf3SDag-Erling Smørgrav /* zero terminate the tag (replace later) */ 1981*09a3aaf3SDag-Erling Smørgrav end = strchr(s, ' '); 1982*09a3aaf3SDag-Erling Smørgrav if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 1983*09a3aaf3SDag-Erling Smørgrav *end = 0; 1984*09a3aaf3SDag-Erling Smørgrav hitlen = *len - 4; 1985*09a3aaf3SDag-Erling Smørgrav if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 1986*09a3aaf3SDag-Erling Smørgrav *end = ' '; 1987*09a3aaf3SDag-Erling Smørgrav return RET_ERR_SHIFT(e, s-(char*)str); 1988*09a3aaf3SDag-Erling Smørgrav } 1989*09a3aaf3SDag-Erling Smørgrav if(hitlen > 255) { 1990*09a3aaf3SDag-Erling Smørgrav *end = ' '; 1991*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 1992*09a3aaf3SDag-Erling Smørgrav } 1993*09a3aaf3SDag-Erling Smørgrav rd[0] = (uint8_t)hitlen; 1994*09a3aaf3SDag-Erling Smørgrav *end = ' '; 1995*09a3aaf3SDag-Erling Smørgrav s = end+1; 1996*09a3aaf3SDag-Erling Smørgrav 1997*09a3aaf3SDag-Erling Smørgrav /* read pubkey base64 sequence */ 1998*09a3aaf3SDag-Erling Smørgrav pklen = *len - 4 - hitlen; 1999*09a3aaf3SDag-Erling Smørgrav if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 2000*09a3aaf3SDag-Erling Smørgrav return RET_ERR_SHIFT(e, s-(char*)str); 2001*09a3aaf3SDag-Erling Smørgrav if(pklen > 65535) 2002*09a3aaf3SDag-Erling Smørgrav return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 2003*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd+2, pklen); 2004*09a3aaf3SDag-Erling Smørgrav 2005*09a3aaf3SDag-Erling Smørgrav *len = 4 + hitlen + pklen; 2006*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 2007*09a3aaf3SDag-Erling Smørgrav } 2008*09a3aaf3SDag-Erling Smørgrav 2009*09a3aaf3SDag-Erling Smørgrav int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 2010*09a3aaf3SDag-Erling Smørgrav { 2011*09a3aaf3SDag-Erling Smørgrav size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 2012*09a3aaf3SDag-Erling Smørgrav int n; 2013*09a3aaf3SDag-Erling Smørgrav if(*len < sz+2) 2014*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2015*09a3aaf3SDag-Erling Smørgrav if(sz > 65535) 2016*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2017*09a3aaf3SDag-Erling Smørgrav n = sldns_b64_pton(str, rd+2, (*len)-2); 2018*09a3aaf3SDag-Erling Smørgrav if(n < 0) 2019*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_SYNTAX_B64; 2020*09a3aaf3SDag-Erling Smørgrav sldns_write_uint16(rd, (uint16_t)n); 2021*09a3aaf3SDag-Erling Smørgrav *len = (size_t)n; 2022*09a3aaf3SDag-Erling Smørgrav return LDNS_WIREPARSE_ERR_OK; 2023*09a3aaf3SDag-Erling Smørgrav } 2024