#include "tdns-c.h" #include "comboaddress.hh" #include "record-types.hh" #include "swrappers.hh" #include "sclasses.hh" #include using namespace std; namespace { template struct TDNSCleanUp { void operator()(vector* vec) { for(auto& p : *vec) { delete p; } delete vec; } }; DNSMessageReader getDNSResponse(Socket& sock, const DNSName& dn, const DNSType& dt) { DNSMessageWriter dmw(dn, dt); dmw.dh.rd = true; dmw.randomizeID(); SWrite(sock, dmw.serialize()); ComboAddress server; string resp =SRecvfrom(sock, 65535, server); return DNSMessageReader(resp); } Socket makeResolverSocket() { ComboAddress server("192.168.1.91", 53); Socket sock(server.sin4.sin_family, SOCK_DGRAM); SConnect(sock, server); return sock; } } extern "C" { const char* TDNSErrorMessage(int err) { static const char *errors[]={"No error", "Timeout", "Server failure", "No such domain", "Unknown error"}; static constexpr int size = sizeof(errors)/sizeof(errors[0]); if(err >= size) err = size-1; return errors[err]; }; void freeTDNSIPAddresses(struct TDNSIPAddresses*vec) { auto ptr = (vector*) vec->__handle; TDNSCleanUp()(ptr); delete vec; } int TDNSLookupIPs(const char* name, int timeoutMsec, int lookupIPv4, int lookupIPv6, struct TDNSIPAddresses** ret) { Socket sock = makeResolverSocket(); vector dtypes; if(lookupIPv4) dtypes.push_back(DNSType::A); if(lookupIPv6) dtypes.push_back(DNSType::AAAA); DNSName dn = makeDNSName(name); std::unique_ptr, TDNSCleanUp> sas(new vector()); uint32_t resttl = std::numeric_limits::max(); for(const auto& dt : dtypes) { DNSMessageReader dmr = getDNSResponse(sock, dn, dt); DNSName rrdn; DNSType rrdt; dmr.getQuestion(rrdn, rrdt); if(dmr.dh.rcode) { return 3; } // cout<<"Received response with RCode "<<(RCode)dmr.dh.rcode<<", qname " < rr; DNSSection rrsection; uint32_t rrttl; while(dmr.getRR(rrsection, rrdn, rrdt, rrttl, rr)) { if(rrttl < resttl) resttl = rrttl; // cout << rrsection << " " << rrdn<< " IN " << rrdt << " " << rrttl << " " <toString()<(rr.get()); ca = agen->getIP(); } else { auto agen =dynamic_cast(rr.get()); ca = agen->getIP(); } auto sa = new struct sockaddr_storage(); memcpy(sa, &ca, sizeof(ca)); sas->push_back(sa); } } sas->push_back(0); *ret = new struct TDNSIPAddresses(); (*ret)->ttl = resttl; (*ret)->addresses = (struct sockaddr_storage**)(&(*sas)[0]); (*ret)->__handle = sas.get(); sas.release(); return 0; } int TDNSLookupMXs(const char* name, int timeoutMsec, struct TDNSMXs** ret) { Socket sock = makeResolverSocket(); std::unique_ptr, TDNSCleanUp> sas(new vector()); uint32_t resttl = std::numeric_limits::max(); DNSName dn = makeDNSName(name); DNSMessageReader dmr = getDNSResponse(sock, dn, DNSType::MX); DNSName rrdn; DNSType rrdt; dmr.getQuestion(rrdn, rrdt); // cout<<"Received response with RCode "<<(RCode)dmr.dh.rcode<<", qname " < rr; DNSSection rrsection; uint32_t rrttl; while(dmr.getRR(rrsection, rrdn, rrdt, rrttl, rr)) { if(rrttl < resttl) resttl = rrttl; // cout << rrsection << " " << rrdn<< " IN " << rrdt << " " << rrttl << " " <toString()<(rr.get()); auto sa = new struct TDNSMX(); sa->priority = mxgen->d_prio; sa->name = strdup(mxgen->d_name.toString().c_str()); sas->push_back(sa); } } sas->push_back(0); *ret = new struct TDNSMXs(); (*ret)->ttl = resttl; (*ret)->mxs = (struct TDNSMX**)(&(*sas)[0]); (*ret)->__handle = sas.get(); sas.release(); return 0; } void freeTDNSMXs(struct TDNSMXs* vec) { auto ptr = (vector*) vec->__handle; for(auto& p : *ptr) { if(!p) break; free((void*)p->name); delete p; } delete ptr; delete vec; } int TDNSLookupTXTs(const char* name, int timeoutMsec, struct TDNSTXTs** ret) { Socket sock = makeResolverSocket(); std::unique_ptr, TDNSCleanUp> sas(new vector()); uint32_t resttl = std::numeric_limits::max(); DNSName dn = makeDNSName(name); DNSMessageReader dmr = getDNSResponse(sock, dn, DNSType::TXT); DNSName rrdn; DNSType rrdt; dmr.getQuestion(rrdn, rrdt); // cout<<"Received response with RCode "<<(RCode)dmr.dh.rcode<<", qname " < rr; DNSSection rrsection; uint32_t rrttl; while(dmr.getRR(rrsection, rrdn, rrdt, rrttl, rr)) { if(rrttl < resttl) resttl = rrttl; // cout << rrsection << " " << rrdn<< " IN " << rrdt << " " << rrttl << " " <toString()<(rr.get()); auto sa = new struct TDNSTXT(); sa->content = strdup(txtgen->toString().c_str()); sas->push_back(sa); } } sas->push_back(0); *ret = new struct TDNSTXTs(); (*ret)->ttl = resttl; (*ret)->txts = (struct TDNSTXT**)(&(*sas)[0]); (*ret)->__handle = sas.get(); sas.release(); return 0; } void freeTDNSTXTs(struct TDNSTXTs* vec) { auto ptr = (vector*) vec->__handle; for(auto& p : *ptr) { if(!p) break; free((void*)p->content); delete p; } delete ptr; delete vec; } }