/*-- Cat pdnet;NET;Sock Form VADDR *NET_Str2Addr(char *str, int proto); Description Parses the address from a string. proto identifies the expected protocol. --*/ VADDR *NET_Str2Addr(char *str, int proto) { VADDR *tmp; char *s; switch(proto) { case PROTO_IPV4UDP: case PROTO_IPV4TCP: tmp=gcalloc(sizeof(VADDR)); tmp->proto=proto; // tmp->ipv4.addr=htonl(str2ipv4(str, &tmp->ipv4.port)); tmp->ipv4.port=htons(tmp->ipv4.port); break; case PROTO_IPV6UDP: case PROTO_IPV6TCP: tmp=gcalloc(sizeof(VADDR)); tmp->proto=proto; s=str2ipv6(tmp->ipv6.addr, str); sscanf(s, ":%d", &tmp->ipv6.port); tmp->ipv6.port=htons(tmp->ipv6.port); break; default: tmp=NULL; break; } return(tmp); }
int RRParserParseTextRdata(RRParser *psr, RRSet **rs, zone *z) { int err = OK_CODE; uint16_t type = psr->type; char *tok; char buf[4096]; char *ptr = buf; uint16_t rdlength = 0; ptr += 2; size_t nameLen; int remain = RRParserRemainTokens(psr); switch (type) { case DNS_TYPE_A: tok = RRParserNextToken(psr); if (tok == NULL) { snprintf(psr->errstr, ERR_STR_LEN, "A record needs a ipv4 address"); goto error; } char ipv4[4]; if (str2ipv4(tok, ipv4) == false) { snprintf(psr->errstr, ERR_STR_LEN, "%s is an invalid ipv4 address.", tok); goto error; } memcpy(ptr, ipv4, 4); ptr += 4; break; case DNS_TYPE_AAAA: tok = RRParserNextToken(psr); if (tok == NULL) { snprintf(psr->errstr, ERR_STR_LEN, "AAAA record needs a ipv6 address"); goto error; } char ipv6[16]; if (str2ipv6(tok, ipv6) == false) { snprintf(psr->errstr, ERR_STR_LEN, "%s is an invalid ipv6 address.", tok); goto error; } memcpy(ptr, ipv6, 16); ptr += 16; break; case DNS_TYPE_NS: case DNS_TYPE_CNAME: tok = RRParserNextToken(psr); if (tok == NULL) { snprintf(psr->errstr, ERR_STR_LEN, "need a domain name."); goto error; } dot2lenlabel(tok, NULL); if (checkLenLabel(tok, 0) == ERR_CODE) { snprintf(psr->errstr, ERR_STR_LEN, "%s is an invalid domain name", tok); goto error; } nameLen = strlen(tok) + 1; memcpy(ptr, tok, nameLen); ptr += nameLen; break; case DNS_TYPE_MX: if (remain != 2) { snprintf(psr->errstr, ERR_STR_LEN, "MX record needs 2 tokens, but got %d.", remain); goto error; } tok = RRParserNextToken(psr); int pref = atoi(tok); if (pref > 0xffff) { snprintf(psr->errstr, ERR_STR_LEN, "preference of MX record is too big(%d)", pref); goto error; } dump16be((uint16_t)pref, ptr); ptr+=2; tok = RRParserNextToken(psr); if (tok == NULL) { snprintf(psr->errstr, ERR_STR_LEN, "no name for MX Record"); goto error; } dot2lenlabel(tok, NULL); if (checkLenLabel(tok, 0) == ERR_CODE) { snprintf(psr->errstr, ERR_STR_LEN, "%s is an invalid domain name.", tok); goto error; } nameLen = strlen(tok) + 1; memcpy(ptr, tok, nameLen); ptr += nameLen; break; case DNS_TYPE_TXT: if (remain < 1) { snprintf(psr->errstr, ERR_STR_LEN, "TXT records should at least has 1 token."); goto error; } for (; ; ) { tok = RRParserNextToken(psr); if (tok == NULL) break; tok = strip(tok, "\""); size_t txtLen = strlen(tok); if (txtLen > 255) { snprintf(psr->errstr, ERR_STR_LEN, "txt string is too long %zu", txtLen); goto error; } if (ptr+txtLen+1 - buf >= (int)sizeof(buf)) { snprintf(psr->errstr, ERR_STR_LEN, "TXT records is too long"); goto error; } *ptr = (uint8_t)txtLen; ptr++; memcpy(ptr, tok, txtLen); ptr += txtLen; } break; case DNS_TYPE_SOA: if (remain != 7) { snprintf(psr->errstr, ERR_STR_LEN, "SOA record needs 7 tokens, but gives %d field", remain); return ERR_CODE; } tok = RRParserNextToken(psr); dot2lenlabel(tok, NULL); nameLen = strlen(tok) + 1; memcpy(ptr, tok, nameLen); ptr += nameLen; tok = RRParserNextToken(psr); dot2lenlabel(tok, NULL); nameLen = strlen(tok) + 1; memcpy(ptr, tok, nameLen); ptr += nameLen; tok = RRParserNextToken(psr); uint32_t sn = (uint32_t)strtoul(tok, NULL, 10); z->sn = sn; dump32be(sn, ptr); ptr += 4; tok = RRParserNextToken(psr); uint32_t refresh = (uint32_t)parsetime(tok); z->refresh = refresh; dump32be(refresh, ptr); ptr += 4; tok = RRParserNextToken(psr); uint32_t retry = (uint32_t)parsetime(tok); z->retry = retry; dump32be(retry, ptr); ptr += 4; tok = RRParserNextToken(psr); uint32_t expiry = (uint32_t)parsetime(tok); z->expiry = expiry; dump32be(expiry, ptr); ptr += 4; tok = RRParserNextToken(psr); uint32_t nx = (uint32_t)parsetime(tok); z->nx = nx; dump32be(nx, ptr); ptr += 4; break; case DNS_TYPE_SRV: if (remain != 4) { snprintf(psr->errstr, ERR_STR_LEN, "SRV record needs 4 field, but gives %d field", remain); goto error; } tok = RRParserNextToken(psr); int priority = atoi(tok); if (priority < 0 || priority > 65535) { snprintf(psr->errstr, ERR_STR_LEN, "invalid priority for SRV record"); goto error; } tok = RRParserNextToken(psr); int weight = atoi(tok); if (weight < 0 || weight > 65535) { snprintf(psr->errstr, ERR_STR_LEN, "invalid weight for SRV record"); goto error; } tok = RRParserNextToken(psr); int port = atoi(tok); if (port < 0 || port > 65535) { snprintf(psr->errstr, ERR_STR_LEN, "invalid port for SRV record."); goto error; } dump16be((uint16_t)priority, ptr); ptr += 2; dump16be((uint16_t)weight, ptr); ptr += 2; dump16be((uint16_t)port, ptr); ptr += 2; tok = RRParserNextToken(psr); size_t targetLen = strlen(tok)+1; dot2lenlabel(tok, NULL); memcpy(ptr, tok, targetLen); ptr += targetLen; break; case DNS_TYPE_PTR: break; default: snprintf(psr->errstr, ERR_STR_LEN, "unsupported dns record type(%d)", type); goto error; } rdlength = (uint16_t )(ptr-buf - 2); dump16be(rdlength, buf); *rs = RRSetCat(*rs, buf, ptr-buf); goto ok; error: err = ERR_CODE; psr->err = PARSER_ERR; ok: return err; }