github.com/pmoroney/dnscontrol@v0.2.4-0.20171024134423-fad98f73f44a/providers/bind/serial.go (about)

     1  package bind
     2  
     3  import (
     4  	"log"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  var nowFunc func() time.Time = time.Now
    11  
    12  // generate_serial takes an old SOA serial number and increments it.
    13  func generate_serial(old_serial uint32) uint32 {
    14  	// Serial numbers are in the format yyyymmddvv
    15  	// where vv is a version count that starts at 01 each day.
    16  	// Multiple serial numbers generated on the same day increase vv.
    17  	// If the old serial number is not in this format, it gets replaced
    18  	// with the new format. However if that would mean a new serial number
    19  	// that is smaller than the old one, we punt and increment the old number.
    20  	// At no time will a serial number == 0 be returned.
    21  
    22  	original := old_serial
    23  	old_serialStr := strconv.FormatUint(uint64(old_serial), 10)
    24  	var new_serial uint32
    25  
    26  	// Make draft new serial number:
    27  	today := nowFunc().UTC()
    28  	todayStr := today.Format("20060102")
    29  	version := uint32(1)
    30  	todayNum, err := strconv.ParseUint(todayStr, 10, 32)
    31  	if err != nil {
    32  		log.Fatalf("new serial won't fit in 32 bits: %v", err)
    33  	}
    34  	draft := uint32(todayNum)*100 + version
    35  
    36  	method := "none" // Used only in debugging.
    37  	if old_serial > draft {
    38  		// If old_serial was really slow, upgrade to new yyyymmddvv standard:
    39  		method = "o>d"
    40  		new_serial = old_serial + 1
    41  		new_serial = old_serial + 1
    42  	} else if old_serial == draft {
    43  		// Edge case: increment old serial:
    44  		method = "o=d"
    45  		new_serial = draft + 1
    46  	} else if len(old_serialStr) != 10 {
    47  		// If old_serial is wrong number of digits, upgrade to yyyymmddvv standard:
    48  		method = "len!=10"
    49  		new_serial = draft
    50  	} else if strings.HasPrefix(old_serialStr, todayStr) {
    51  		// If old_serial just needs to be incremented:
    52  		method = "prefix"
    53  		new_serial = old_serial + 1
    54  	} else {
    55  		// First serial number to be requested today:
    56  		method = "default"
    57  		new_serial = draft
    58  	}
    59  
    60  	if new_serial == 0 {
    61  		// We never return 0 as the serial number.
    62  		new_serial = 1
    63  	}
    64  	if old_serial == new_serial {
    65  		log.Fatalf("%v: old_serial == new_serial (%v == %v) draft=%v method=%v", original, old_serial, new_serial, draft, method)
    66  	}
    67  	if old_serial > new_serial {
    68  		log.Fatalf("%v: old_serial > new_serial (%v > %v) draft=%v method=%v", original, old_serial, new_serial, draft, method)
    69  	}
    70  	return new_serial
    71  }