diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:24:08 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:24:08 +0000 |
commit | f449f278dd3c70e479a035f50a9bb817a9b433ba (patch) | |
tree | 8ca2bfb785dda9bb4d573acdf9b42aea9cd51383 /src/knot/zone/serial.c | |
parent | Initial commit. (diff) | |
download | knot-f449f278dd3c70e479a035f50a9bb817a9b433ba.tar.xz knot-f449f278dd3c70e479a035f50a9bb817a9b433ba.zip |
Adding upstream version 3.2.6.upstream/3.2.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/knot/zone/serial.c')
-rw-r--r-- | src/knot/zone/serial.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/knot/zone/serial.c b/src/knot/zone/serial.c new file mode 100644 index 0000000..0be5cbe --- /dev/null +++ b/src/knot/zone/serial.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <time.h> + +#include "knot/conf/conf.h" +#include "knot/zone/serial.h" + +static const serial_cmp_result_t diffbrief2result[4] = { + [0] = SERIAL_EQUAL, + [1] = SERIAL_GREATER, + [2] = SERIAL_INCOMPARABLE, + [3] = SERIAL_LOWER, +}; + +serial_cmp_result_t serial_compare(uint32_t s1, uint32_t s2) +{ + uint64_t diff = ((uint64_t)s1 + ((uint64_t)1 << 32) - s2) & 0xffffffff; + int diffbrief = (diff >> 31 << 1) | ((diff & 0x7fffffff) ? 1 : 0); + assert(diffbrief > -1 && diffbrief < 4); + return diffbrief2result[diffbrief]; +} + +static uint32_t serial_dateserial(uint32_t current) +{ + struct tm now; + time_t current_time = time(NULL); + struct tm *gmtime_result = gmtime_r(¤t_time, &now); + if (gmtime_result == NULL) { + return current; + } + return (1900 + now.tm_year) * 1000000 + + ( 1 + now.tm_mon ) * 10000 + + ( now.tm_mday) * 100; +} + +uint32_t serial_next(uint32_t current, int policy, uint32_t must_increment) +{ + uint32_t minimum; + switch (policy) { + case SERIAL_POLICY_INCREMENT: + minimum = current; + break; + case SERIAL_POLICY_UNIXTIME: + minimum = time(NULL); + break; + case SERIAL_POLICY_DATESERIAL: + minimum = serial_dateserial(current); + break; + default: + assert(0); + return 0; + } + if (serial_compare(minimum, current) != SERIAL_GREATER) { + return current + must_increment; + } else { + return minimum; + } +} + +serial_cmp_result_t kserial_cmp(kserial_t a, kserial_t b) +{ + return ((a.valid && b.valid) ? serial_compare(a.serial, b.serial) : SERIAL_INCOMPARABLE); +} |