uint16_t qtype_getcode(const char *name, bool allow_qtype) { try { uint16_t ret = txt_to_int(name); if (!is_common_rr(ret)) throw PException(); return ret; } catch (PException p) { if (allow_qtype) { if (strcmpi(name, "maila") == 0) return QTYPE_MAILA; if (strcmpi(name, "mailb") == 0) return QTYPE_MAILB; if (strcmpi(name, "ixfr") == 0) return QTYPE_IXFR; if (strcmpi(name, "axfr") == 0) return QTYPE_AXFR; if (strcmpi(name, "any") == 0) return QTYPE_ANY; if (strcmpi(name, "all") == 0) return QTYPE_ANY; } rr_type *t = rrtype_getinfo(name); if (!t) throw PException(true, "Qtype %s not supported", name); return t->type; } }
void rr_read(u_int16 RRTYPE, unsigned char*& RDATA, uint16_t &RDLEN, message_buff &buff, int ix, int len) { rr_type *info = rrtype_getinfo(RRTYPE); char *ptr; stl_string res; _domain dom; if (ix + len > buff.len) throw PException("RR doesn't fit in DNS message"); if (info) { /* we support the RR type */ try { ptr = info->properties; while (*ptr) { int x; x = rr_len(*ptr, buff, ix, len); if (x > len) throw PException("RR item too long!"); if (*ptr == 'd' || *ptr == 'm') { /* domain name: needs to be decompressed */ dom = dom_uncompress(buff, ix); res.append((char*)dom, domlen(dom)); free(dom); } else { res.append((char*)buff.msg + ix, x); } ix += x; len -= x; ptr++; } if (len != 0) throw PException("extra data in RR"); } catch(PException p) { throw PException("Parsing RR failed: ", p); } if (len != 0) throw PException("RR length too long"); } else { /* we do not support the RR type: just copy it altogether */ res.append((char*)buff.msg + ix, len); } RDLEN = res.length(); RDATA = (unsigned char *)memdup((void *)res.c_str(), res.length()); }
char *rrtype_getname(u_int16 type) { rr_type *info = rrtype_getinfo(type); if (info) return info->name; else return NULL; }
} if (len != 0) throw PException("extra data in RR"); } catch(PException p) { throw PException("Parsing RR failed: ", p); } if (len != 0) throw PException("RR length too long"); } else { /* we do not support the RR type: just copy it altogether */ res.append((char*)buff.msg + ix, len); } RDLEN = res.length(); RDATA = (unsigned char *)memdup((void *)res.c_str(), res.length()); } void rr_write(u_int16 RRTYPE, unsigned char *RDATA, uint16_t RDLEN, stl_string &dnsmessage, stl_slist(dom_compr_info) *comprinfo) { rr_type *info = rrtype_getinfo(RRTYPE); char *ptr; int len, ix = 0; message_buff rrbuff(RDATA, RDLEN); if (!info || !(info->flags & R_COMPRESS) || !comprinfo) { dnsmessage.append((char*)RDATA, RDLEN); return; } ptr = info->properties; while (*ptr) { len = rr_len(*ptr, rrbuff, ix, RDLEN - ix); if ((*ptr == 'd' || *ptr == 'm') && comprinfo) { /* compress dname */ dom_write(dnsmessage, RDATA + ix, comprinfo);
void read_master_file(const char *file, domainname &znroot, void *userdat, error_callback err, rr_callback rr_cb, rr_literal_callback rrl_cb, comment_callback comm_cb, int flags) { bool has_znroot = !(flags&POSLIB_MF_AUTOPROBE), has_soa = false; char buff[1024]; char *ptr, *p2; int c; bool ttl_given = false; stl_string ttl = "3600"; domainname origin, nam; int linenum = 1, linenum2; stl_string str, tmp, t2, t3, nm; DnsRR rr; rr_type *type = NULL; FILE *f = try_fopen_r(file); if (!f) throw PException(true, "Could not open %s", file); c = fgetc(f); if (c != EOF) ungetc(c, f); if (has_znroot) origin = znroot; try { begin: while (!feof(f)) { /* since the poslib functions will filter out comments, let's do them ourselves */ if (comm_cb) { c = fgetc(f); if (c == ';') { fgets(buff, 1024, f); ptr = buff + strlen(buff) - 1; while (ptr >= buff && (*ptr == '\n' || *ptr == '\r')) *ptr = '\0'; comm_cb(userdat, buff); continue; } ungetc(c, f); } try { read_line(buff, f, &linenum, &linenum2); } catch (PException p) { break; } if (buff[0] == 0) goto begin; ptr = buff; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr == '\0') continue; if (buff[0] == '$') { if (strncmpi(buff, "$ttl ", 4) == 0) { ttl = buff + 5; ttl_given = true; } else if (strncmpi(buff, "$origin ", 8) == 0) { /* origin */ origin = domainname(buff + 8, znroot); if (!has_znroot) { /* first entry. this is the zone root */ znroot = origin; has_znroot = true; } } else err(userdat, file, linenum2, PException(true, "Unknown directive %s", buff).message); continue; } if (!has_znroot) { znroot = guess_zone_name(file); origin = znroot; has_znroot = true; } if (buff[0] != ' ' && buff[0] != '\t') { nam = domainname(read_entry(ptr).c_str(), origin); } else if (!has_soa) { err(userdat, file, linenum2, "First record in zone should have a domain name! Using origin instead."); nam = origin; } /* can be class or ttl or rrtype */ while (1) { str = read_entry(ptr); if (str == "IN" || str == "HS" || str == "CH" || str == "HS" || str == "in" || str == "hs" || str == "ch" || str == "hs") { /* class */ continue; } else if ((type = rrtype_getinfo(str.c_str())) != NULL) { break; } else { try { txt_to_int(str.c_str()); ttl_given = true; } catch (PException p) { err(userdat, file, linenum2, PException(true, "Invalid TTL/RR type %s!", str.c_str()).message); goto begin; } ttl = str.c_str(); } } if (!has_soa) { if (type->type != DNS_TYPE_SOA) { if (!(flags & POSLIB_MF_NOSOA)) { err(userdat, file, linenum2, "First record was no SOA record; using default SOA record instead."); if (rr_cb) { rr.NAME = znroot; rr.TYPE = DNS_TYPE_SOA; rr.TTL = 3600; tmp = rr_fromstring(DNS_TYPE_SOA, "ns1 hostmaster 1 2h 1h 1d 2h", znroot); rr.RDLENGTH = tmp.size(); rr.RDATA = (unsigned char *)memdup(tmp.c_str(), tmp.size()); rr_cb(userdat, &rr); } if (rrl_cb) rrl_cb(userdat, "@", "1h", "SOA", "ns1 hostmaster 1 2h 1h 1d 2h", znroot); } else if (!ttl_given) { err(userdat, file, linenum2, "First record should have TTL value; using 1h for now."); ttl = "3600"; ttl_given = true; } } else { if (!ttl_given) { p2 = ptr; read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); t3 = read_entry(p2); if (strlen(t3.c_str()) < 32) ttl = t3; } } has_soa = true; } else if (type->type == DNS_TYPE_SOA && !(flags & POSLIB_MF_NOSOA)) { err(userdat, file, linenum2, "Non-initial SOA record ignored"); continue; } if (!(nam >= znroot)) { err(userdat, file, linenum2, PException(true, "Ignoring domain name %s outside of zone %s!", nam.tocstr(), znroot.tocstr()).message); continue; } if (rr_cb) { try { rr.NAME = nam; rr.TYPE = type->type; rr.TTL = txt_to_int(ttl.c_str()); tmp = rr_fromstring(type->type, ptr, origin); rr.RDLENGTH = tmp.size(); rr.RDATA = (unsigned char *)memdup(tmp.c_str(), tmp.size()); rr_cb(userdat, &rr); } catch (PException p) { err(userdat, file, linenum2, p.message); } } if (rrl_cb) { try { t2 = ptr; nm = nam.torelstring(znroot); tmp = rr_fromstring(type->type, ptr, origin); if (origin != znroot) t2 = rrdata_convertdoms(type, znroot, origin, ptr); } catch (PException p) { err(userdat, file, linenum2, p.message); } rrl_cb(userdat, nm.c_str(), ttl.c_str(), type->name, t2.c_str(), znroot); } } } catch (PException p) { fclose(f); throw p; } fclose(f); }