Permalink
Browse files

IPv6/AAAA record support

  • Loading branch information...
1 parent af48979 commit 309d8ee0ae77e617e8cd6cf2c30b0378b66498d3 @sipa committed May 25, 2012
Showing with 859 additions and 324 deletions.
  1. +3 −3 Makefile
  2. +5 −7 bitcoin.cpp
  3. +1 −1 bitcoin.h
  4. +9 −9 db.cpp
  5. +17 −18 db.h
  6. +17 −11 dns.c
  7. +9 −1 dns.h
  8. +46 −16 main.cpp
  9. +650 −177 netbase.cpp
  10. +69 −54 netbase.h
  11. +2 −2 protocol.cpp
  12. +3 −3 protocol.h
  13. +3 −3 test.pl
  14. +25 −19 util.h
View
@@ -1,8 +1,8 @@
-dnsseed: dns.o bitcoin.o netbase.o protocol.o db.o main.o
- g++ -pthread -lcrypto -o dnsseed dns.o bitcoin.o netbase.o protocol.o db.o main.o
+dnsseed: dns.o bitcoin.o netbase.o protocol.o db.o main.o util.o
+ g++ -pthread -o dnsseed dns.o bitcoin.o netbase.o protocol.o db.o main.o util.o -lcrypto
%.o: %.cpp bitcoin.h netbase.h protocol.h db.h serialize.h uint256.h util.h
- g++ -pthread -O2 -ggdb3 -march=nocona -Wno-invalid-offsetof -c -o $@ $<
+ g++ -DUSE_IPV6 -pthread -O2 -ggdb3 -march=nocona -Wno-invalid-offsetof -c -o $@ $<
dns.o: dns.c
gcc -pthread -std=c99 -O2 -ggdb3 -march=nocona dns.c -c -o dns.o
View
@@ -72,7 +72,7 @@ class CNode {
int64 nTime = time(NULL);
uint64 nLocalNonce = BITCOIN_SEED_NONCE;
int64 nLocalServices = 0;
- CAddress me(CIPPort("0.0.0.0"));
+ CAddress me(CService("0.0.0.0"));
BeginMessage("version");
int nBestHeight = REQUIRE_HEIGHT;
string ver = "/bitcoin-seeder:0.01/";
@@ -132,8 +132,6 @@ class CNode {
CAddress &addr = *it;
// printf("%s: got address %s\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
it++;
- if (!addr.IsIPv4())
- continue;
if (addr.nTime <= 100000000 || addr.nTime > now + 600)
addr.nTime = now - 5 * 86400;
vAddr->push_back(addr);
@@ -192,7 +190,7 @@ class CNode {
}
public:
- CNode(const CIPPort& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) {
+ CNode(const CService& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) {
vSend.SetType(SER_NETWORK);
vSend.SetVersion(0);
vRecv.SetType(SER_NETWORK);
@@ -204,7 +202,7 @@ class CNode {
}
bool Run() {
bool res = true;
- if (!you.ConnectSocket(sock)) return false;
+ if (!ConnectSocket(you, sock)) return false;
PushVersion();
Send();
int64 now;
@@ -262,7 +260,7 @@ class CNode {
}
};
-bool TestNode(const CIPPort &cip, int &ban, int &clientV, std::string &clientSV, vector<CAddress>& vAddr) {
+bool TestNode(const CService &cip, int &ban, int &clientV, std::string &clientSV, vector<CAddress>& vAddr) {
try {
CNode node(cip, vAddr);
bool ret = node.Run();
@@ -283,7 +281,7 @@ bool TestNode(const CIPPort &cip, int &ban, int &clientV, std::string &clientSV,
/*
int main(void) {
- CIPPort ip("bitcoin.sipa.be", 8333, true);
+ CService ip("bitcoin.sipa.be", 8333, true);
vector<CAddress> vAddr;
vAddr.clear();
int ban = 0;
View
@@ -3,6 +3,6 @@
#include "protocol.h"
-bool TestNode(const CIPPort &cip, int &ban, int &client, std::string &clientSV, std::vector<CAddress>& vAddr);
+bool TestNode(const CService &cip, int &ban, int &client, std::string &clientSV, std::vector<CAddress>& vAddr);
#endif
View
18 db.cpp
@@ -26,7 +26,7 @@ void CAddrInfo::Update(bool good) {
// 100.0 * stat1W.reliability, 100.0 * (stat1W.reliability + 1.0 - stat1W.weight), stat1W.count);
}
-bool CAddrDb::Get_(CIPPort &ip, int &wait) {
+bool CAddrDb::Get_(CService &ip, int &wait) {
int64 now = time(NULL);
int cont = 0;
int tot = unkId.size();
@@ -78,13 +78,13 @@ bool CAddrDb::Get_(CIPPort &ip, int &wait) {
return true;
}
-int CAddrDb::Lookup_(const CIPPort &ip) {
+int CAddrDb::Lookup_(const CService &ip) {
if (ipToId.count(ip))
return ipToId[ip];
return -1;
}
-void CAddrDb::Good_(const CIPPort &addr, int clientV, std::string clientSV) {
+void CAddrDb::Good_(const CService &addr, int clientV, std::string clientSV) {
int id = Lookup_(addr);
if (id == -1) return;
unkId.erase(id);
@@ -101,7 +101,7 @@ void CAddrDb::Good_(const CIPPort &addr, int clientV, std::string clientSV) {
ourId.push_back(id);
}
-void CAddrDb::Bad_(const CIPPort &addr, int ban)
+void CAddrDb::Bad_(const CService &addr, int ban)
{
int id = Lookup_(addr);
if (id == -1) return;
@@ -130,7 +130,7 @@ void CAddrDb::Bad_(const CIPPort &addr, int ban)
nDirty++;
}
-void CAddrDb::Skipped_(const CIPPort &addr)
+void CAddrDb::Skipped_(const CService &addr)
{
int id = Lookup_(addr);
if (id == -1) return;
@@ -144,7 +144,7 @@ void CAddrDb::Skipped_(const CIPPort &addr)
void CAddrDb::Add_(const CAddress &addr, bool force) {
if (!force && !addr.IsRoutable())
return;
- CIPPort ipp(addr);
+ CService ipp(addr);
if (banned.count(ipp)) {
time_t bantime = banned[ipp];
if (force || (bantime < time(NULL) && addr.nTime > bantime))
@@ -180,7 +180,7 @@ void CAddrDb::Add_(const CAddress &addr, bool force) {
nDirty++;
}
-void CAddrDb::GetIPs_(set<CIP>& ips, int max, bool fOnlyIPv4) {
+void CAddrDb::GetIPs_(set<CNetAddr>& ips, int max, const bool* nets) {
if (goodId.size() == 0) {
int id = -1;
if (ourId.size() == 0) {
@@ -208,8 +208,8 @@ void CAddrDb::GetIPs_(set<CIP>& ips, int max, bool fOnlyIPv4) {
ids.insert(id);
}
for (set<int>::const_iterator it = ids.begin(); it != ids.end(); it++) {
- CIPPort &ip = idToInfo[*it].ip;
- if (ip.IsValid() && (!fOnlyIPv4 || ip.IsIPv4()))
+ CService &ip = idToInfo[*it].ip;
+ if (nets[ip.GetNetwork()])
ips.insert(ip);
}
}
View
35 db.h
@@ -12,7 +12,7 @@
#define MIN_RETRY 1000
-std::string static inline ToString(const CIPPort &ip) {
+std::string static inline ToString(const CService &ip) {
std::string str = ip.ToString();
while (str.size() < 22) str += ' ';
return str;
@@ -44,7 +44,7 @@ class CAddrStat {
class CAddrReport {
public:
- CIPPort ip;
+ CService ip;
int clientVersion;
double uptime[5];
std::string clientSubVersion;
@@ -53,7 +53,7 @@ class CAddrReport {
class CAddrInfo {
private:
- CIPPort ip;
+ CService ip;
uint64_t services;
int64 lastTry;
int64 ourLastTry;
@@ -87,7 +87,6 @@ class CAddrInfo {
if (ip.GetPort() != 8333) return false;
if (!(services & NODE_NETWORK)) return false;
if (!ip.IsRoutable()) return false;
- if (!ip.IsIPv4()) return false;
if (clientVersion && clientVersion < 32400) return false;
if (total <= 3 && success * 2 >= total) return true;
@@ -170,7 +169,7 @@ class CAddrDb {
mutable CCriticalSection cs;
int nId; // number of address id's
std::map<int, CAddrInfo> idToInfo; // map address id to address info (b,c,d,e)
- std::map<CIPPort, int> ipToId; // map ip to id (b,c,d,e)
+ std::map<CService, int> ipToId; // map ip to id (b,c,d,e)
std::deque<int> ourId; // sequence of tried nodes, in order we have tried connecting to them (c,d)
std::set<int> unkId; // set of nodes not yet tried (b)
std::set<int> goodId; // set of good nodes (d, good e)
@@ -179,15 +178,15 @@ class CAddrDb {
protected:
// internal routines that assume proper locks are acquired
void Add_(const CAddress &addr, bool force); // add an address
- bool Get_(CIPPort &ip, int& wait); // get an IP to test (must call Good_, Bad_, or Skipped_ on result afterwards)
- void Good_(const CIPPort &ip, int clientV, std::string clientSV); // mark an IP as good (must have been returned by Get_)
- void Bad_(const CIPPort &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_)
- void Skipped_(const CIPPort &ip); // mark an IP as skipped (must have been returned by Get_)
- int Lookup_(const CIPPort &ip); // look up id of an IP
- void GetIPs_(std::set<CIP>& ips, int max, bool fOnlyIPv4); // get a random set of IPs (shared lock only)
+ bool Get_(CService &ip, int& wait); // get an IP to test (must call Good_, Bad_, or Skipped_ on result afterwards)
+ void Good_(const CService &ip, int clientV, std::string clientSV); // mark an IP as good (must have been returned by Get_)
+ void Bad_(const CService &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_)
+ void Skipped_(const CService &ip); // mark an IP as skipped (must have been returned by Get_)
+ int Lookup_(const CService &ip); // look up id of an IP
+ void GetIPs_(std::set<CNetAddr>& ips, int max, const bool* nets); // get a random set of IPs (shared lock only)
public:
- std::map<CIPPort, time_t> banned; // nodes that are banned, with their unban time (a)
+ std::map<CService, time_t> banned; // nodes that are banned, with their unban time (a)
void GetStats(CAddrDbStats &stats) {
SHARED_CRITICAL_BLOCK(cs) {
@@ -272,24 +271,24 @@ class CAddrDb {
for (int i=0; i<vAddr.size(); i++)
Add_(vAddr[i], fForce);
}
- void Good(const CIPPort &addr, int clientVersion, std::string clientSubVersion) {
+ void Good(const CService &addr, int clientVersion, std::string clientSubVersion) {
CRITICAL_BLOCK(cs)
Good_(addr, clientVersion, clientSubVersion);
}
- void Skipped(const CIPPort &addr) {
+ void Skipped(const CService &addr) {
CRITICAL_BLOCK(cs)
Skipped_(addr);
}
- void Bad(const CIPPort &addr, int ban = 0) {
+ void Bad(const CService &addr, int ban = 0) {
CRITICAL_BLOCK(cs)
Bad_(addr, ban);
}
- bool Get(CIPPort &ip, int& wait) {
+ bool Get(CService &ip, int& wait) {
CRITICAL_BLOCK(cs)
return Get_(ip, wait);
}
- void GetIPs(std::set<CIP>& ips, int max, bool fOnlyIPv4 = true) {
+ void GetIPs(std::set<CNetAddr>& ips, int max, const bool *nets) {
SHARED_CRITICAL_BLOCK(cs)
- GetIPs_(ips, max, fOnlyIPv4);
+ GetIPs_(ips, max, nets);
}
};
View
28 dns.c
@@ -127,7 +127,9 @@ int static write_record(unsigned char** outpos, const unsigned char *outend, con
}
-int static write_record_a(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const struct in_addr *ip) {
+int static write_record_a(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const addr_t *ip) {
+ if (ip->v != 4)
+ return -6;
unsigned char *oldpos = *outpos;
int error = 0;
int ret = write_record(outpos, outend, name, offset, TYPE_A, cls, ttl);
@@ -136,16 +138,17 @@ int static write_record_a(unsigned char** outpos, const unsigned char *outend, c
// rdlength
*((*outpos)++) = 0; *((*outpos)++) = 4;
// rdata
- const unsigned char *pd = (const unsigned char*)ip;
for (int i=0; i<4; i++)
- *((*outpos)++) = pd[i];
+ *((*outpos)++) = ip->data.v4[i];
return 0;
error:
*outpos = oldpos;
return error;
}
-int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const struct in6_addr *ip) {
+int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const addr_t *ip) {
+ if (ip->v != 6)
+ return -6;
unsigned char *oldpos = *outpos;
int error = 0;
int ret = write_record(outpos, outend, name, offset, TYPE_AAAA, cls, ttl);
@@ -154,9 +157,8 @@ int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend
// rdlength
*((*outpos)++) = 0; *((*outpos)++) = 16;
// rdata
- const unsigned char *pd = (const unsigned char*)ip;
for (int i=0; i<16; i++)
- *((*outpos)++) = pd[i];
+ *((*outpos)++) = ip->data.v6[i];
return 0;
error:
*outpos = oldpos;
@@ -293,13 +295,17 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
if (!ret2) { outbuf[7]++; }
}
- // A records
- if ((typ == TYPE_A || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
- struct in_addr addr[32];
- int naddr = opt->cb((void*)opt, addr, 32, 1);
+ // A/AAAA records
+ if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
+ addr_t addr[32];
+ int naddr = opt->cb((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY);
int n = 0;
while (n < naddr) {
- int ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
+ int ret = 1;
+ if (addr->v == 4)
+ ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
+ else if (addr->v == 6)
+ ret = write_record_aaaa(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
// printf("wrote A record: %i\n", ret);
if (!ret) {
n++;
View
10 dns.h
@@ -3,14 +3,22 @@
#include <stdint.h>
+typedef struct {
+ int v;
+ union {
+ unsigned char v4[4];
+ unsigned char v6[16];
+ } data;
+} addr_t;
+
typedef struct {
int port;
int datattl;
int nsttl;
const char *host;
const char *ns;
const char *mbox;
- int (*cb)(void *opt, struct in_addr *addr, int max, int ipv4only);
+ int (*cb)(void *opt, addr_t *addr, int max, int ipv4, int ipv6);
// stats
uint64_t nRequests;
} dns_opt_t;
Oops, something went wrong.

0 comments on commit 309d8ee

Please sign in to comment.