dnscontrol/providers/bind/serial.go
2023-05-20 13:21:45 -04:00

64 lines
1.9 KiB
Go

package bind
import (
"log"
"strconv"
"time"
"github.com/StackExchange/dnscontrol/v4/pkg/bindserial"
)
var nowFunc = time.Now
// generateSerial takes an old SOA serial number and increments it.
func generateSerial(oldSerial uint32) uint32 {
// Serial numbers are in the format yyyymmddvv
// where vv is a version count that starts at 01 each day.
// Multiple serial numbers generated on the same day increase vv.
// If the old serial number is not in this format, it gets replaced
// with the new format. However if that would mean a new serial number
// that is smaller than the old one, we punt and increment the old number.
// At no time will a serial number == 0 be returned.
if bindserial.ForcedValue != 0 {
// https://github.com/StackExchange/dnscontrol/issues/1859
// User needs to have reproducible builds and BIND generates
return uint32(bindserial.ForcedValue & 0xFFFF)
}
original := oldSerial
var newSerial uint32
// Make draft new serial number:
today := nowFunc().UTC()
todayStr := today.Format("20060102")
todayNum, err := strconv.ParseUint(todayStr, 10, 32)
if err != nil {
log.Fatalf("new serial won't fit in 32 bits: %v", err)
}
draft := uint32(todayNum * 100)
// First serial number to be requested today:
method := "default"
newSerial = draft
if oldSerial >= newSerial {
// If that would be going backwards, just increment the old one.
method = "o>=d"
newSerial = oldSerial + 1
}
if newSerial == 0 {
// We never return 0 as the serial number.
newSerial = 1
}
// Assertions that should never happen.
if oldSerial == newSerial {
log.Fatalf("%v: old_serial == new_serial (%v == %v) draft=%v method=%v", original, oldSerial, newSerial, draft, method)
}
if oldSerial > newSerial {
log.Fatalf("%v: old_serial > new_serial (%v > %v) draft=%v method=%v", original, oldSerial, newSerial, draft, method)
}
return newSerial
}