Bug Summary

File:src/usr.sbin/rpki-client/rrdp_notification.c
Warning:line 101, column 9
Potential leak of memory pointed to by 'd'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rrdp_notification.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/rpki-client/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/rpki-client -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/rpki-client/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/rpki-client/rrdp_notification.c
1/* $OpenBSD: rrdp_notification.c,v 1.12 2021/11/24 15:24:16 claudio Exp $ */
2/*
3 * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
4 * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/stat.h>
20
21#include <assert.h>
22#include <err.h>
23#include <errno(*__errno()).h>
24#include <limits.h>
25#include <fcntl.h>
26#include <string.h>
27#include <unistd.h>
28
29#include <expat.h>
30#include <openssl/sha.h>
31
32#include "extern.h"
33#include "rrdp.h"
34
35enum notification_scope {
36 NOTIFICATION_SCOPE_START,
37 NOTIFICATION_SCOPE_NOTIFICATION,
38 NOTIFICATION_SCOPE_SNAPSHOT,
39 NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT,
40 NOTIFICATION_SCOPE_DELTA,
41 NOTIFICATION_SCOPE_END
42};
43
44struct delta_item {
45 char *uri;
46 char hash[SHA256_DIGEST_LENGTH32];
47 long long serial;
48 TAILQ_ENTRY(delta_item)struct { struct delta_item *tqe_next; struct delta_item **tqe_prev
; }
q;
49};
50
51TAILQ_HEAD(delta_q, delta_item)struct delta_q { struct delta_item *tqh_first; struct delta_item
**tqh_last; }
;
52
53struct notification_xml {
54 XML_Parser parser;
55 struct rrdp_session *repository;
56 struct rrdp_session *current;
57 const char *notifyuri;
58 char *session_id;
59 char *snapshot_uri;
60 char snapshot_hash[SHA256_DIGEST_LENGTH32];
61 struct delta_q delta_q;
62 long long serial;
63 int version;
64 enum notification_scope scope;
65};
66
67static void free_delta(struct delta_item *);
68
69static int
70add_delta(struct notification_xml *nxml, const char *uri,
71 const char hash[SHA256_DIGEST_LENGTH32], long long serial)
72{
73 struct delta_item *d, *n;
74
75 if ((d = calloc(1, sizeof(struct delta_item))) == NULL((void*)0))
27
Memory is allocated
28
Assuming the condition is false
29
Taking false branch
76 err(1, "%s - calloc", __func__);
77
78 d->serial = serial;
79 d->uri = xstrdup(uri);
80 memcpy(d->hash, hash, sizeof(d->hash));
81
82 /* optimise for a sorted input */
83 n = TAILQ_LAST(&nxml->delta_q, delta_q)(*(((struct delta_q *)((&nxml->delta_q)->tqh_last))
->tqh_last))
;
84 if (n == NULL((void*)0))
30
Assuming 'n' is not equal to NULL
31
Taking false branch
85 TAILQ_INSERT_HEAD(&nxml->delta_q, d, q)do { if (((d)->q.tqe_next = (&nxml->delta_q)->tqh_first
) != ((void*)0)) (&nxml->delta_q)->tqh_first->q.
tqe_prev = &(d)->q.tqe_next; else (&nxml->delta_q
)->tqh_last = &(d)->q.tqe_next; (&nxml->delta_q
)->tqh_first = (d); (d)->q.tqe_prev = &(&nxml->
delta_q)->tqh_first; } while (0)
;
86 else if (n->serial < serial)
32
Assuming 'serial' is <= field 'serial'
33
Taking false branch
87 TAILQ_INSERT_TAIL(&nxml->delta_q, d, q)do { (d)->q.tqe_next = ((void*)0); (d)->q.tqe_prev = (&
nxml->delta_q)->tqh_last; *(&nxml->delta_q)->
tqh_last = (d); (&nxml->delta_q)->tqh_last = &(
d)->q.tqe_next; } while (0)
;
88 else
89 TAILQ_FOREACH(n, &nxml->delta_q, q)for((n) = ((&nxml->delta_q)->tqh_first); (n) != ((void
*)0); (n) = ((n)->q.tqe_next))
{
34
Assuming 'n' is equal to null
35
Loop condition is false. Execution continues on line 101
90 if (n->serial == serial) {
91 warnx("duplicate delta serial %lld ", serial);
92 free_delta(d);
93 return 0;
94 }
95 if (n->serial > serial) {
96 TAILQ_INSERT_BEFORE(n, d, q)do { (d)->q.tqe_prev = (n)->q.tqe_prev; (d)->q.tqe_next
= (n); *(n)->q.tqe_prev = (d); (n)->q.tqe_prev = &
(d)->q.tqe_next; } while (0)
;
97 break;
98 }
99 }
100
101 return 1;
36
Potential leak of memory pointed to by 'd'
102}
103
104static void
105free_delta(struct delta_item *d)
106{
107 free(d->uri);
108 free(d);
109}
110
111static void
112start_notification_elem(struct notification_xml *nxml, const char **attr)
113{
114 XML_Parser p = nxml->parser;
115 int has_xmlns = 0;
116 size_t i;
117
118 if (nxml->scope != NOTIFICATION_SCOPE_START)
119 PARSE_FAIL(p,do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered notification elem unexpectedely"
); return; } while (0)
120 "parse failed - entered notification elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered notification elem unexpectedely"
); return; } while (0)
;
121 for (i = 0; attr[i]; i += 2) {
122 const char *errstr;
123 if (strcmp("xmlns", attr[i]) == 0) {
124 has_xmlns = 1;
125 continue;
126 }
127 if (strcmp("session_id", attr[i]) == 0) {
128 nxml->session_id = xstrdup(attr[i + 1]);
129 continue;
130 }
131 if (strcmp("version", attr[i]) == 0) {
132 nxml->version = strtonum(attr[i + 1],
133 1, MAX_VERSION1, &errstr);
134 if (errstr == NULL((void*)0))
135 continue;
136 }
137 if (strcmp("serial", attr[i]) == 0) {
138 nxml->serial = strtonum(attr[i + 1],
139 1, LLONG_MAX9223372036854775807LL, &errstr);
140 if (errstr == NULL((void*)0))
141 continue;
142 }
143 PARSE_FAIL(p, "parse failed - non conforming "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in notification elem", attr[i]); return
; } while (0)
144 "attribute '%s' found in notification elem", attr[i])do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in notification elem", attr[i]); return
; } while (0)
;
145 }
146 if (!(has_xmlns && nxml->version && nxml->session_id && nxml->serial))
147 PARSE_FAIL(p, "parse failed - incomplete "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - incomplete "
"notification attributes"); return; } while (0)
148 "notification attributes")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - incomplete "
"notification attributes"); return; } while (0)
;
149
150 nxml->scope = NOTIFICATION_SCOPE_NOTIFICATION;
151}
152
153static void
154end_notification_elem(struct notification_xml *nxml)
155{
156 XML_Parser p = nxml->parser;
157
158 if (nxml->scope != NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT)
159 PARSE_FAIL(p, "parse failed - exited notification "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - exited notification "
"elem unexpectedely"); return; } while (0)
160 "elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - exited notification "
"elem unexpectedely"); return; } while (0)
;
161 nxml->scope = NOTIFICATION_SCOPE_END;
162}
163
164static void
165start_snapshot_elem(struct notification_xml *nxml, const char **attr)
166{
167 XML_Parser p = nxml->parser;
168 int i, hasUri = 0, hasHash = 0;
169
170 if (nxml->scope != NOTIFICATION_SCOPE_NOTIFICATION)
171 PARSE_FAIL(p,do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered snapshot elem unexpectedely"
); return; } while (0)
172 "parse failed - entered snapshot elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered snapshot elem unexpectedely"
); return; } while (0)
;
173 for (i = 0; attr[i]; i += 2) {
174 if (strcmp("uri", attr[i]) == 0 && hasUri++ == 0) {
175 if (valid_uri(attr[i + 1], strlen(attr[i + 1]),
176 "https://") &&
177 valid_origin(attr[i + 1], nxml->notifyuri)) {
178 nxml->snapshot_uri = xstrdup(attr[i + 1]);
179 continue;
180 }
181 }
182 if (strcmp("hash", attr[i]) == 0 && hasHash++ == 0) {
183 if (hex_decode(attr[i + 1], nxml->snapshot_hash,
184 sizeof(nxml->snapshot_hash)) == 0)
185 continue;
186 }
187 PARSE_FAIL(p, "parse failed - non conforming "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in snapshot elem", attr[i]); return; }
while (0)
188 "attribute '%s' found in snapshot elem", attr[i])do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in snapshot elem", attr[i]); return; }
while (0)
;
189 }
190 if (hasUri != 1 || hasHash != 1)
191 PARSE_FAIL(p, "parse failed - incomplete snapshot attributes")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - incomplete snapshot attributes"
); return; } while (0)
;
192
193 nxml->scope = NOTIFICATION_SCOPE_SNAPSHOT;
194}
195
196static void
197end_snapshot_elem(struct notification_xml *nxml)
198{
199 XML_Parser p = nxml->parser;
200
201 if (nxml->scope != NOTIFICATION_SCOPE_SNAPSHOT)
202 PARSE_FAIL(p, "parse failed - exited snapshot "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - exited snapshot "
"elem unexpectedely"); return; } while (0)
203 "elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - exited snapshot "
"elem unexpectedely"); return; } while (0)
;
204 nxml->scope = NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT;
205}
206
207static void
208start_delta_elem(struct notification_xml *nxml, const char **attr)
209{
210 XML_Parser p = nxml->parser;
211 int i, hasUri = 0, hasHash = 0;
212 const char *delta_uri = NULL((void*)0);
213 char delta_hash[SHA256_DIGEST_LENGTH32];
214 long long delta_serial = 0;
215
216 if (nxml->scope != NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT)
7
Assuming field 'scope' is equal to NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT
8
Taking false branch
217 PARSE_FAIL(p, "parse failed - entered delta "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered delta "
"elem unexpectedely"); return; } while (0)
218 "elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - entered delta "
"elem unexpectedely"); return; } while (0)
;
219 for (i = 0; attr[i]; i += 2) {
9
Loop condition is true. Entering loop body
19
Loop condition is false. Execution continues on line 245
220 if (strcmp("uri", attr[i]) == 0 && hasUri++ == 0) {
10
Taking true branch
221 if (valid_uri(attr[i + 1], strlen(attr[i + 1]),
11
Assuming the condition is false
222 "https://") &&
223 valid_origin(attr[i + 1], nxml->notifyuri)) {
224 delta_uri = attr[i + 1];
225 continue;
226 }
227 }
228 if (strcmp("hash", attr[i]) == 0 && hasHash++ == 0) {
12
Taking true branch
229 if (hex_decode(attr[i + 1], delta_hash,
13
Assuming the condition is false
14
Taking false branch
230 sizeof(delta_hash)) == 0)
231 continue;
232 }
233 if (strcmp("serial", attr[i]) == 0 && delta_serial
14.1
'delta_serial' is equal to 0
== 0) {
15
Taking true branch
234 const char *errstr;
235
236 delta_serial = strtonum(attr[i + 1],
237 1, LLONG_MAX9223372036854775807LL, &errstr);
238 if (errstr == NULL((void*)0))
16
Assuming 'errstr' is equal to NULL
17
Taking true branch
239 continue;
18
Execution continues on line 219
240 }
241 PARSE_FAIL(p, "parse failed - non conforming "do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in snapshot elem", attr[i]); return; }
while (0)
242 "attribute '%s' found in snapshot elem", attr[i])do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - non conforming "
"attribute '%s' found in snapshot elem", attr[i]); return; }
while (0)
;
243 }
244 /* Only add to the list if we are relevant */
245 if (hasUri
19.1
'hasUri' is equal to 1
!= 1 || hasHash
19.2
'hasHash' is equal to 1
!= 1 || delta_serial == 0)
20
Assuming 'delta_serial' is not equal to 0
21
Taking false branch
246 PARSE_FAIL(p, "parse failed - incomplete delta attributes")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - incomplete delta attributes"
); return; } while (0)
;
247
248 /* optimisation, add only deltas that could be interesting */
249 if (nxml->repository->serial != 0 &&
22
Assuming field 'serial' is not equal to 0
25
Taking true branch
250 nxml->repository->serial < delta_serial &&
23
Assuming 'delta_serial' is > field 'serial'
251 nxml->repository->session_id != NULL((void*)0) &&
24
Assuming field 'session_id' is not equal to NULL
252 strcmp(nxml->session_id, nxml->repository->session_id) == 0) {
253 if (add_delta(nxml, delta_uri, delta_hash, delta_serial) == 0)
26
Calling 'add_delta'
254 PARSE_FAIL(p, "parse failed - adding delta failed")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - adding delta failed"
); return; } while (0)
;
255 }
256
257 nxml->scope = NOTIFICATION_SCOPE_DELTA;
258}
259
260static void
261end_delta_elem(struct notification_xml *nxml)
262{
263 XML_Parser p = nxml->parser;
264
265 if (nxml->scope != NOTIFICATION_SCOPE_DELTA)
266 PARSE_FAIL(p, "parse failed - exited delta elem unexpectedely")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - exited delta elem unexpectedely"
); return; } while (0)
;
267 nxml->scope = NOTIFICATION_SCOPE_NOTIFICATION_POST_SNAPSHOT;
268}
269
270static void
271notification_xml_elem_start(void *data, const char *el, const char **attr)
272{
273 struct notification_xml *nxml = data;
274 XML_Parser p = nxml->parser;
275
276 /*
277 * Can only enter here once as we should have no ways to get back to
278 * START scope
279 */
280 if (strcmp("notification", el) == 0)
1
Assuming the condition is false
2
Taking false branch
281 start_notification_elem(nxml, attr);
282 /*
283 * Will enter here multiple times, BUT never nested. will start
284 * collecting character data in that handler
285 * mem is cleared in end block, (TODO or on parse failure)
286 */
287 else if (strcmp("snapshot", el) == 0)
3
Assuming the condition is false
4
Taking false branch
288 start_snapshot_elem(nxml, attr);
289 else if (strcmp("delta", el) == 0)
5
Taking true branch
290 start_delta_elem(nxml, attr);
6
Calling 'start_delta_elem'
291 else
292 PARSE_FAIL(p, "parse failed - unexpected elem exit found")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - unexpected elem exit found"
); return; } while (0)
;
293}
294
295static void
296notification_xml_elem_end(void *data, const char *el)
297{
298 struct notification_xml *nxml = data;
299 XML_Parser p = nxml->parser;
300
301 if (strcmp("notification", el) == 0)
302 end_notification_elem(nxml);
303 else if (strcmp("snapshot", el) == 0)
304 end_snapshot_elem(nxml);
305 else if (strcmp("delta", el) == 0)
306 end_delta_elem(nxml);
307 else
308 PARSE_FAIL(p, "parse failed - unexpected elem exit found")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - unexpected elem exit found"
); return; } while (0)
;
309}
310
311static void
312notification_doctype_handler(void *data, const char *doctypeName,
313 const char *sysid, const char *pubid, int subset)
314{
315 struct notification_xml *nxml = data;
316 XML_Parser p = nxml->parser;
317
318 PARSE_FAIL(p, "parse failed - DOCTYPE not allowed")do { XML_StopParser(p, ((XML_Bool)0)); warnx("parse failed - DOCTYPE not allowed"
); return; } while (0)
;
319}
320
321struct notification_xml *
322new_notification_xml(XML_Parser p, struct rrdp_session *repository,
323 struct rrdp_session *current, const char *notifyuri)
324{
325 struct notification_xml *nxml;
326
327 if ((nxml = calloc(1, sizeof(*nxml))) == NULL((void*)0))
328 err(1, "%s", __func__);
329 TAILQ_INIT(&(nxml->delta_q))do { (&(nxml->delta_q))->tqh_first = ((void*)0); (&
(nxml->delta_q))->tqh_last = &(&(nxml->delta_q
))->tqh_first; } while (0)
;
330 nxml->parser = p;
331 nxml->repository = repository;
332 nxml->current = current;
333 nxml->notifyuri = notifyuri;
334
335 XML_SetElementHandler(nxml->parser, notification_xml_elem_start,
336 notification_xml_elem_end);
337 XML_SetUserData(nxml->parser, nxml);
338 XML_SetDoctypeDeclHandler(nxml->parser, notification_doctype_handler,
339 NULL((void*)0));
340
341 return nxml;
342}
343
344void
345free_notification_xml(struct notification_xml *nxml)
346{
347 if (nxml == NULL((void*)0))
348 return;
349
350 free(nxml->session_id);
351 free(nxml->snapshot_uri);
352 while (!TAILQ_EMPTY(&nxml->delta_q)(((&nxml->delta_q)->tqh_first) == ((void*)0))) {
353 struct delta_item *d = TAILQ_FIRST(&nxml->delta_q)((&nxml->delta_q)->tqh_first);
354 TAILQ_REMOVE(&nxml->delta_q, d, q)do { if (((d)->q.tqe_next) != ((void*)0)) (d)->q.tqe_next
->q.tqe_prev = (d)->q.tqe_prev; else (&nxml->delta_q
)->tqh_last = (d)->q.tqe_prev; *(d)->q.tqe_prev = (d
)->q.tqe_next; ; ; } while (0)
;
355 free_delta(d);
356 }
357 free(nxml);
358}
359
360/*
361 * Finalize notification step, decide if a delta update is possible
362 * if either the session_id changed or the delta files fail to cover
363 * all the steps up to the new serial fall back to a snapshot.
364 * Return SNAPSHOT or DELTA for snapshot or delta processing.
365 * Return NOTIFICATION if repository is up to date.
366 */
367enum rrdp_task
368notification_done(struct notification_xml *nxml, char *last_mod)
369{
370 struct delta_item *d;
371 long long s, last_s = 0;
372
373 nxml->current->last_mod = last_mod;
374 nxml->current->session_id = xstrdup(nxml->session_id);
375
376 /* check the that the session_id was valid and still the same */
377 if (nxml->repository->session_id == NULL((void*)0) ||
378 strcmp(nxml->session_id, nxml->repository->session_id) != 0)
379 goto snapshot;
380
381 /* if repository serial is 0 fall back to snapshot */
382 if (nxml->repository->serial == 0)
383 goto snapshot;
384
385 /* if our serial is equal or bigger, the repo is up to date */
386 if (nxml->repository->serial >= nxml->serial) {
387 nxml->current->serial = nxml->repository->serial;
388 return NOTIFICATION;
389 }
390
391 /* it makes no sense to process too many deltas */
392 if (nxml->serial - nxml->repository->serial > 300)
393 goto snapshot;
394
395 /* check that all needed deltas are available */
396 s = nxml->repository->serial + 1;
397 TAILQ_FOREACH(d, &nxml->delta_q, q)for((d) = ((&nxml->delta_q)->tqh_first); (d) != ((void
*)0); (d) = ((d)->q.tqe_next))
{
398 if (d->serial != s++)
399 goto snapshot;
400 last_s = d->serial;
401 }
402 if (last_s != nxml->serial)
403 goto snapshot;
404
405 /* update via delta possible */
406 nxml->current->serial = nxml->repository->serial;
407 nxml->repository->serial = nxml->serial;
408 return DELTA;
409
410snapshot:
411 /* update via snapshot download */
412 nxml->current->serial = nxml->serial;
413 return SNAPSHOT;
414}
415
416const char *
417notification_get_next(struct notification_xml *nxml, char *hash, size_t hlen,
418 enum rrdp_task task)
419{
420 struct delta_item *d;
421
422 switch (task) {
423 case SNAPSHOT:
424 assert(hlen == sizeof(nxml->snapshot_hash))((hlen == sizeof(nxml->snapshot_hash)) ? (void)0 : __assert2
("/usr/src/usr.sbin/rpki-client/rrdp_notification.c", 424, __func__
, "hlen == sizeof(nxml->snapshot_hash)"))
;
425 memcpy(hash, nxml->snapshot_hash, hlen);
426 /*
427 * Ensure that the serial is correct in case a previous
428 * delta request failed.
429 */
430 nxml->current->serial = nxml->serial;
431 return nxml->snapshot_uri;
432 case DELTA:
433 /* first bump serial, then use first delta */
434 nxml->current->serial += 1;
435 d = TAILQ_FIRST(&nxml->delta_q)((&nxml->delta_q)->tqh_first);
436 assert(d->serial == nxml->current->serial)((d->serial == nxml->current->serial) ? (void)0 : __assert2
("/usr/src/usr.sbin/rpki-client/rrdp_notification.c", 436, __func__
, "d->serial == nxml->current->serial"))
;
437 assert(hlen == sizeof(d->hash))((hlen == sizeof(d->hash)) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/rrdp_notification.c"
, 437, __func__, "hlen == sizeof(d->hash)"))
;
438 memcpy(hash, d->hash, hlen);
439 return d->uri;
440 default:
441 errx(1, "%s: bad task", __func__);
442 }
443}
444
445/*
446 * Pop first element from the delta queue. Return non-0 if this was the last
447 * delta to fetch.
448 */
449int
450notification_delta_done(struct notification_xml *nxml)
451{
452 struct delta_item *d;
453
454 d = TAILQ_FIRST(&nxml->delta_q)((&nxml->delta_q)->tqh_first);
455 assert(d->serial == nxml->current->serial)((d->serial == nxml->current->serial) ? (void)0 : __assert2
("/usr/src/usr.sbin/rpki-client/rrdp_notification.c", 455, __func__
, "d->serial == nxml->current->serial"))
;
456 TAILQ_REMOVE(&nxml->delta_q, d, q)do { if (((d)->q.tqe_next) != ((void*)0)) (d)->q.tqe_next
->q.tqe_prev = (d)->q.tqe_prev; else (&nxml->delta_q
)->tqh_last = (d)->q.tqe_prev; *(d)->q.tqe_prev = (d
)->q.tqe_next; ; ; } while (0)
;
457 free_delta(d);
458
459 assert(!TAILQ_EMPTY(&nxml->delta_q) ||((!(((&nxml->delta_q)->tqh_first) == ((void*)0)) ||
nxml->serial == nxml->current->serial) ? (void)0 : __assert2
("/usr/src/usr.sbin/rpki-client/rrdp_notification.c", 460, __func__
, "!TAILQ_EMPTY(&nxml->delta_q) || nxml->serial == nxml->current->serial"
))
460 nxml->serial == nxml->current->serial)((!(((&nxml->delta_q)->tqh_first) == ((void*)0)) ||
nxml->serial == nxml->current->serial) ? (void)0 : __assert2
("/usr/src/usr.sbin/rpki-client/rrdp_notification.c", 460, __func__
, "!TAILQ_EMPTY(&nxml->delta_q) || nxml->serial == nxml->current->serial"
))
;
461 return TAILQ_EMPTY(&nxml->delta_q)(((&nxml->delta_q)->tqh_first) == ((void*)0));
462}
463
464void
465log_notification_xml(struct notification_xml *nxml)
466{
467 struct delta_item *d;
468 char *hash;
469
470 logx("session_id: %s, serial: %lld", nxml->session_id, nxml->serial);
471 logx("snapshot_uri: %s", nxml->snapshot_uri);
472 hash = hex_encode(nxml->snapshot_hash, sizeof(nxml->snapshot_hash));
473 logx("snapshot hash: %s", hash);
474 free(hash);
475
476 TAILQ_FOREACH(d, &nxml->delta_q, q)for((d) = ((&nxml->delta_q)->tqh_first); (d) != ((void
*)0); (d) = ((d)->q.tqe_next))
{
477 logx("delta serial %lld uri: %s", d->serial, d->uri);
478 hash = hex_encode(d->hash, sizeof(d->hash));
479 logx("delta hash: %s", hash);
480 free(hash);
481 }
482}