]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: ISC |
8e427c29 DL |
2 | /* |
3 | * Copyright (c) 2017-20 David Lamparter, for NetDEF, Inc. | |
8e427c29 DL |
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 | ||
4894e9c1 DL |
27 | struct xrefdata_uid_head xrefdata_uid = INIT_RBTREE_UNIQ(xrefdata_uid); |
28 | ||
8e427c29 DL |
29 | static void base32(uint8_t **inpos, int *bitpos, |
30 | char *out, size_t n_chars) | |
31 | { | |
32 | static const char base32ch[] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; | |
33 | ||
34 | char *opos = out; | |
35 | uint8_t *in = *inpos; | |
36 | int bp = *bitpos; | |
37 | ||
38 | while (opos < out + n_chars) { | |
39 | uint32_t bits = in[0] | (in[1] << 8); | |
40 | ||
41 | if (bp == -1) | |
42 | bits |= 0x10; | |
43 | else | |
44 | bits >>= bp; | |
45 | ||
46 | *opos++ = base32ch[bits & 0x1f]; | |
47 | ||
48 | bp += 5; | |
49 | if (bp >= 8) | |
50 | in++, bp -= 8; | |
51 | } | |
52 | *opos = '\0'; | |
53 | *inpos = in; | |
54 | *bitpos = bp; | |
55 | } | |
56 | ||
08a73c42 DL |
57 | static void xref_add_one(const struct xref *xref) |
58 | { | |
59 | SHA256_CTX sha; | |
60 | struct xrefdata *xrefdata; | |
61 | ||
62 | const char *filename, *p, *q; | |
63 | uint8_t hash[32], *h = hash; | |
64 | uint32_t be_val; | |
65 | int bitpos; | |
66 | ||
67 | if (!xref || !xref->xrefdata) | |
68 | return; | |
69 | ||
70 | xrefdata = xref->xrefdata; | |
71 | xrefdata->xref = xref; | |
72 | ||
73 | if (!xrefdata->hashstr) | |
74 | 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 | filename = xref->file; | |
82 | p = strrchr(filename, '/'); | |
83 | if (p) { | |
84 | q = memrchr(filename, '/', p - filename); | |
85 | if (q) | |
86 | filename = q + 1; | |
08a73c42 DL |
87 | } |
88 | ||
89 | SHA256_Init(&sha); | |
90 | SHA256_Update(&sha, filename, strlen(filename)); | |
91 | SHA256_Update(&sha, xrefdata->hashstr, | |
92 | strlen(xrefdata->hashstr)); | |
93 | be_val = htonl(xrefdata->hashu32[0]); | |
94 | SHA256_Update(&sha, &be_val, sizeof(be_val)); | |
95 | be_val = htonl(xrefdata->hashu32[1]); | |
96 | SHA256_Update(&sha, &be_val, sizeof(be_val)); | |
97 | SHA256_Final(hash, &sha); | |
98 | ||
99 | bitpos = -1; | |
100 | base32(&h, &bitpos, &xrefdata->uid[0], 5); | |
101 | xrefdata->uid[5] = '-'; | |
102 | base32(&h, &bitpos, &xrefdata->uid[6], 5); | |
4894e9c1 DL |
103 | |
104 | xrefdata_uid_add(&xrefdata_uid, xrefdata); | |
08a73c42 DL |
105 | } |
106 | ||
107 | void xref_gcc_workaround(const struct xref *xref) | |
108 | { | |
109 | xref_add_one(xref); | |
110 | } | |
111 | ||
8e427c29 DL |
112 | void xref_block_add(struct xref_block *block) |
113 | { | |
114 | const struct xref * const *xrefp; | |
8e427c29 DL |
115 | |
116 | *xref_block_last = block; | |
117 | xref_block_last = &block->next; | |
118 | ||
08a73c42 DL |
119 | for (xrefp = block->start; xrefp < block->stop; xrefp++) |
120 | xref_add_one(*xrefp); | |
8e427c29 | 121 | } |