Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: ISC |
2 | | /* |
3 | | * Copyright (c) 2017-20 David Lamparter, for NetDEF, Inc. |
4 | | */ |
5 | | |
6 | | #ifdef HAVE_CONFIG_H |
7 | | #include "config.h" |
8 | | #endif |
9 | | |
10 | | #include <stdlib.h> |
11 | | #include <stdarg.h> |
12 | | #include <string.h> |
13 | | #include <pthread.h> |
14 | | #include <signal.h> |
15 | | #include <inttypes.h> |
16 | | |
17 | | #include "xref.h" |
18 | | #include "vty.h" |
19 | | #include "jhash.h" |
20 | | #include "sha256.h" |
21 | | #include "memory.h" |
22 | | #include "hash.h" |
23 | | |
24 | | struct xref_block *xref_blocks; |
25 | | static struct xref_block **xref_block_last = &xref_blocks; |
26 | | |
27 | | struct xrefdata_uid_head xrefdata_uid = INIT_RBTREE_UNIQ(xrefdata_uid); |
28 | | |
29 | | static void base32(uint8_t **inpos, int *bitpos, |
30 | | char *out, size_t n_chars) |
31 | 0 | { |
32 | 0 | static const char base32ch[] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; |
33 | |
|
34 | 0 | char *opos = out; |
35 | 0 | uint8_t *in = *inpos; |
36 | 0 | int bp = *bitpos; |
37 | |
|
38 | 0 | while (opos < out + n_chars) { |
39 | 0 | uint32_t bits = in[0] | (in[1] << 8); |
40 | |
|
41 | 0 | if (bp == -1) |
42 | 0 | bits |= 0x10; |
43 | 0 | else |
44 | 0 | bits >>= bp; |
45 | |
|
46 | 0 | *opos++ = base32ch[bits & 0x1f]; |
47 | |
|
48 | 0 | bp += 5; |
49 | 0 | if (bp >= 8) |
50 | 0 | in++, bp -= 8; |
51 | 0 | } |
52 | 0 | *opos = '\0'; |
53 | 0 | *inpos = in; |
54 | 0 | *bitpos = bp; |
55 | 0 | } |
56 | | |
57 | | static void xref_add_one(const struct xref *xref) |
58 | 41.7k | { |
59 | 41.7k | SHA256_CTX sha; |
60 | 41.7k | struct xrefdata *xrefdata; |
61 | | |
62 | 41.7k | const char *filename, *p, *q; |
63 | 41.7k | uint8_t hash[32], *h = hash; |
64 | 41.7k | uint32_t be_val; |
65 | 41.7k | int bitpos; |
66 | | |
67 | 41.7k | if (!xref || !xref->xrefdata) |
68 | 41.7k | return; |
69 | | |
70 | 0 | xrefdata = xref->xrefdata; |
71 | 0 | xrefdata->xref = xref; |
72 | |
|
73 | 0 | if (!xrefdata->hashstr) |
74 | 0 | return; |
75 | | |
76 | | /* as far as the unique ID is concerned, only use the last |
77 | | * directory name + filename, e.g. "bgpd/bgp_route.c". This |
78 | | * gives a little leeway in moving things and avoids IDs being |
79 | | * screwed up by out of tree builds or absolute pathnames. |
80 | | */ |
81 | 0 | filename = xref->file; |
82 | 0 | p = strrchr(filename, '/'); |
83 | 0 | if (p) { |
84 | 0 | q = memrchr(filename, '/', p - filename); |
85 | 0 | if (q) |
86 | 0 | filename = q + 1; |
87 | 0 | } |
88 | |
|
89 | 0 | SHA256_Init(&sha); |
90 | 0 | SHA256_Update(&sha, filename, strlen(filename)); |
91 | 0 | SHA256_Update(&sha, xrefdata->hashstr, |
92 | 0 | strlen(xrefdata->hashstr)); |
93 | 0 | be_val = htonl(xrefdata->hashu32[0]); |
94 | 0 | SHA256_Update(&sha, &be_val, sizeof(be_val)); |
95 | 0 | be_val = htonl(xrefdata->hashu32[1]); |
96 | 0 | SHA256_Update(&sha, &be_val, sizeof(be_val)); |
97 | 0 | SHA256_Final(hash, &sha); |
98 | |
|
99 | 0 | bitpos = -1; |
100 | 0 | base32(&h, &bitpos, &xrefdata->uid[0], 5); |
101 | 0 | xrefdata->uid[5] = '-'; |
102 | 0 | base32(&h, &bitpos, &xrefdata->uid[6], 5); |
103 | |
|
104 | 0 | xrefdata_uid_add(&xrefdata_uid, xrefdata); |
105 | 0 | } |
106 | | |
107 | | void xref_gcc_workaround(const struct xref *xref) |
108 | 0 | { |
109 | 0 | xref_add_one(xref); |
110 | 0 | } |
111 | | |
112 | | void xref_block_add(struct xref_block *block) |
113 | 14 | { |
114 | 14 | const struct xref * const *xrefp; |
115 | | |
116 | 14 | *xref_block_last = block; |
117 | 14 | xref_block_last = &block->next; |
118 | | |
119 | 41.7k | for (xrefp = block->start; xrefp < block->stop; xrefp++) |
120 | 41.7k | xref_add_one(*xrefp); |
121 | 14 | } |