#include #include #include #include #include "dnsconf.h" #include "internal.h" #include PUBLIC RECORD_IN_SOA::RECORD_IN_SOA(const RECORD_PARSE &p) : RECORD_IN(p,RTYPE_SOA) { lastrequest = 0; domain.setfrom (p.f1); machine.setfrom (p.f2); admin.setfrom (p.f3); old_serial = new_serial = atol(p.f4); refresh.setfrom (p.f5); retry.setfrom (p.f6); expire.setfrom (p.f7); default_ttl.setfrom (p.f8); } /* Create a SOA record with default values */ PUBLIC RECORD_IN_SOA::RECORD_IN_SOA() : RECORD_IN(RTYPE_SOA) { lastrequest = 0; THISHOST th; const char *name = th.getname1(); domain.setfrom ("@"); machine.setfrom (name); dns_cnv2abs (machine); admin.setfrom ("hostmaster."); admin.append (name); dns_cnv2abs (admin); old_serial = new_serial = 0; update(NULL); /* #Specification: SOA / default values The following defaults are proposed the the user. We can bet that he will use those. If you think they are hazardous, please tell me. refresh = 60*60; retry = 15*60; expire = 14*24*60*60l; default_ttl = 12*60*60; */ refresh.setfrom (60*60); retry.setfrom (15*60); expire.setfrom (14*24*60*60l); default_ttl.setfrom (12*60*60); } PUBLIC void RECORD_IN_SOA::print (FILE_CFG *fout) const { char t_refresh[20],t_retry[20],t_expire[20],t_default[20]; record_formatttl (refresh.seconds,t_refresh); record_formatttl (retry.seconds,t_retry); record_formatttl (expire.seconds,t_expire); record_formatttl (default_ttl.seconds,t_default); fprintf (fout,"%s\t%s\tIN\tSOA\t%s\t%s (\n" "\t\t\t%ld ; serial\n" "\t\t\t%s ; refresh\n" "\t\t\t%s ; retry\n" "\t\t\t%s ; expire\n" "\t\t\t%s ; default_ttl\n" "\t\t\t)\n" ,domain.get(),ttlstr ,machine.get() ,admin.get() ,new_serial ,t_refresh,t_retry,t_expire,t_default); } /* Set the serial number to a new value (based on the current date) */ PUBLIC void RECORD_IN_SOA::update(const char *name) { long old = old_serial; if (name != NULL && context_isroot()){ time_t curtime = time(NULL); /* We have a copy of the original serial number, but this is not enough to compute a reliable serial (always greater). When we update the SOA, we request the serial of the running DNS for that zone and we use this as the basis to create the new serial. When doing batch update of the DNS (update from dhcp leases) we avoid talking to the DNS too much (slow). The lastrequest variable indicates the date of the last request and we assume the result is good for 5 seconds. */ if (curtime > lastrequest + 5){ long dns_serial = dns_getserial (name,"127.0.0.1",4); lastrequest = curtime; if (dns_serial > old) old = dns_serial; } } if (new_serial <= old){ /* #Specification: dnsconf / SOA / serial The serial number of a SOA record is the date it was modified and a revision number. This gives a ten digits number that always grows. The format is yyyymmddrr (where rr is a revision number). When updating a SOA serial, dnsconf use the current date to setup a new serial number. If the new number if smaller than the old, then the old one + 1 is used instead. This makes sure the serial is always growing. */ time_t tt = time(NULL); struct tm *t = localtime (&tt); new_serial = (1900+t->tm_year)*1000000 + (t->tm_mon+1)*10000 + t->tm_mday * 100 + 1; if (new_serial <= old){ new_serial = old+1; } } setmodified(); }