TRIP Routing Daemon
TRIP (RFC 3219) Location Server Implementation
Loading...
Searching...
No Matches
pib.c
Go to the documentation of this file.
1/*
2
3 trip: Modern TRIP LS implementation
4 Copyright (C) 2025 arf20 (Ángel Ruiz Fernandez)
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19 pib.c: Policy Information Base
20
21*/
22
27
28#include "pib.h"
29
30#define _COMPONENT_ "db"
31
32#include <logging/logging.h>
33
34#include <stdlib.h>
35#include <string.h>
36#include <ctype.h>
37
38#define INIT_VEC_CAPACITY 16
39
41#define VEC_ENSURE_CAPACITY(vec, size, capacity, type) \
42 if ((capacity) < (size) + 1) { \
43 (capacity) *= 2; \
44 (vec) = realloc((vec), (capacity) * sizeof(type)); \
45 }
46
47static pib_t g_pib = { 0 };
48
49pib_t *
51{
52 pib_t *p = &g_pib;
53
54 memset(p, 0, sizeof(pib_t));
55
56 p->acls_capacity = INIT_VEC_CAPACITY;
57 p->acls_size = 0;
58 p->acls = malloc(p->acls_capacity * sizeof(acl_t));
59
60 p->routemaps_capacity = INIT_VEC_CAPACITY;
61 p->routemaps_size = 0;
62 p->routemaps = malloc(p->routemaps_capacity * sizeof(routemap_t));
63
64 return p;
65}
66
67void
69{
70 for (size_t i = 0; i < pib->acls_size; i++) {
71 for (size_t j = 0; j < pib->acls[i].entries_size; j++)
72 free(pib->acls[i].entries[j].expression);
73 free(pib->acls[i].entries);
74 free(pib->acls[i].name);
75 }
76 free(pib->acls);
77
78 for (size_t i = 0; i < pib->routemaps_size; i++) {
79 for (size_t j = 0; j < pib->routemaps[i].size; j++) {
80 for (size_t k = 0; k < pib->routemaps[i].statements[j].matchers_size; k++)
81 free(pib->routemaps[i].statements[j].matchers[k].acls);
82
83 for (size_t k = 0; k < pib->routemaps[i].statements[j].actions_size; k++)
85 &pib->routemaps[i].statements[j].actions[k]);
86 free(pib->routemaps[i].statements[j].matchers);
87 free(pib->routemaps[i].statements[j].actions);
88 }
89 free(pib->routemaps[i].name);
90 free(pib->routemaps[i].statements);
91 }
92 free(pib->routemaps);
93}
94
95acl_t *
96pib_acl_new(pib_t *pib, const char *name)
97{
98 VEC_ENSURE_CAPACITY(pib->acls, pib->acls_size, pib->acls_capacity, acl_t);
99
100 acl_t *a = &pib->acls[pib->acls_size++];
101
102 a->name = strdup(name);
103
104 a->entries_capacity = INIT_VEC_CAPACITY;
105 a->entries_size = 0;
106 a->entries = malloc(a->entries_capacity * sizeof(acl_entry_t));
107
108 return a;
109}
110
112pib_routemap_new(pib_t *pib, const char *name, int deny)
113{
114 VEC_ENSURE_CAPACITY(pib->routemaps, pib->routemaps_size,
115 pib->routemaps_capacity, routemap_t);
116
117 routemap_t *r = &pib->routemaps[pib->routemaps_size++];
118
119 r->name = strdup(name);
120
121 r->size = 0;
122 r->capacity = INIT_VEC_CAPACITY;
123 r->statements = malloc(r->capacity * sizeof(routemap_statement_t));
124
125 return r;
126}
127
128acl_t *
129pib_acl_find(const pib_t *pib, const char *name)
130{
131 for (size_t i = 0; i < pib->acls_size; i++)
132 if (strcmp(pib->acls[i].name, name) == 0)
133 return &pib->acls[i];
134 return NULL;
135}
136
138pib_routemap_find(const pib_t *pib, const char *name)
139{
140 for (size_t i = 0; i < pib->routemaps_size; i++)
141 if (strcmp(pib->routemaps[i].name, name) == 0)
142 return &pib->routemaps[i];
143 return NULL;
144}
145
146
147void
148acl_insert(acl_t *acl, int deny, const char *expression)
149{
150 VEC_ENSURE_CAPACITY(acl->entries, acl->entries_size,
151 acl->entries_capacity, acl_entry_t);
152
153 acl_entry_t *e = &acl->entries[acl->entries_size++];
154
155 e->deny = deny;
156 e->expression = strdup(expression);
157}
158
160acl_find(const acl_t *acl, const char *expression)
161{
162 for (size_t i = 0; i < acl->entries_size; i++)
163 if (strcmp(acl->entries[i].expression, expression) == 0)
164 return &acl->entries[i];
165 return NULL;
166}
167
168static int
169ispfxdigit(char c)
170{
171 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'E');
172}
173
187static int
188pattern_check(const char *pat, const char *target)
189{
190 pat++; /* strip initiating _ */
191 while (1) {
192 /* both consumed - pattern matched */
193 if (!*pat && !*target)
194 return 1;
195
196 /* wildcard matches end */
197 if (*pat == '.' && !*target)
198 return 1;
199
200 /* consumed with leftover */
201 if (!*pat || !*target)
202 return 0;
203
204 /* wildcard */
205 if (*pat == '.') {
206 if (ispfxdigit(*target)) {
207 target++;
208 continue;
209 } else {
210 return 0;
211 }
212 }
213
214 /* digit check */
215 if (ispfxdigit(*pat) && *pat != *target)
216 return 0;
217 if (*pat == 'X' && !isdigit(*target))
218 return 0;
219 if (*pat == 'Z' && !(*target >= '1' && *target <= '9'))
220 return 0;
221 if (*pat == 'N' && !(*target >= '2' && *target <= '9'))
222 return 0;
223
224 /* matched digit */
225 target++;
226 pat++;
227 }
228}
229
237int
238acl_entry_match(const char *expr, const char *target)
239{
240 return
241 /* is prefix */
242 (ispfxdigit(expr[0])
243 /* target is under prefix (prefix shorter than target
244 * and prefix digits match) */
245 && (strlen(expr) <= strlen(target))
246 && (strncmp(expr, target, strlen(expr)) == 0)) ||
247 /* or must be pattern, check */
248 (pattern_check(expr, target));
249}
250
256int
257acl_check(const acl_t *acl, const char *target)
258{
259 for (size_t i = 0; i < acl->entries_size; i++) {
260 const char *expr = acl->entries[i].expression;
261 if (acl_entry_match(expr, target))
262 return !acl->entries[i].deny;
263 }
264 return 0; /* default deny */
265}
266
269{
270 VEC_ENSURE_CAPACITY(statement->matchers, statement->matchers_size,
271 statement->matchers_capacity, routemap_matcher_t);
272
273 routemap_matcher_t *m = &statement->matchers[statement->matchers_size++];
274
275 m->af = af;
276 m->size = 0;
277 m->capacity = INIT_VEC_CAPACITY;
278 m->acls = malloc(m->capacity * sizeof(acl_t*));
279
280 return m;
281}
282
283void
285 const routemap_action_t *action)
286{
287 VEC_ENSURE_CAPACITY(statement->actions, statement->actions_size,
288 statement->actions_capacity, routemap_action_t);
289
290 routemap_action_t *stmt = &statement->actions[statement->actions_size++];
291 memcpy(stmt, action, sizeof(routemap_action_t));
292}
293
294void
296{
297 if (action->valstr1)
298 free(action->valstr1);
299 if (action->valstr2)
300 free(action->valstr2);
301}
302
303void
305{
306 VEC_ENSURE_CAPACITY(matcher->acls, matcher->size,
307 matcher->capacity, acl_t*);
308
309 matcher->acls[matcher->size++] = (acl_t *)acl;
310}
311
312void
314{
315 free(matcher->acls);
316}
317
318
321 routemap_set_attr_t attribute)
322{
323 for (size_t i = 0; i < statement->actions_size; i++)
324 if (statement->actions[i].attribute == attribute)
325 return &statement->actions[i];
326 return NULL;
327}
328
329
331routemap_statement_new(routemap_t *routemap, uint32_t seq, int deny)
332{
333 VEC_ENSURE_CAPACITY(routemap->statements, routemap->size,
334 routemap->capacity, routemap_statement_t);
335
336 /* ordered insert by seq */
337 size_t i = 0;
338 for (; i < routemap->size && routemap->statements[i].seq < seq; i++);
339
340 memmove(&routemap->statements[i + 1], &routemap->statements[i],
341 (routemap->size - i) * sizeof(routemap_statement_t));
342 routemap->size++;
343
344
345 routemap_statement_t *s = &routemap->statements[i];
346 s->seq = seq;
347 s->deny = deny;
348
349 s->matchers_size = s->actions_size = 0;
350 s->matchers_capacity = s->actions_capacity = INIT_VEC_CAPACITY;
351 s->matchers = malloc(s->matchers_capacity * sizeof(routemap_matcher_t));
352 s->actions = malloc(s->actions_capacity * sizeof(routemap_action_t));
353
354 return s;
355}
356
358routemap_statement_find(routemap_t *routemap, uint32_t seq)
359{
360 for (size_t i = 0; i < routemap->size; i++)
361 if (routemap->statements[i].seq == seq)
362 return &routemap->statements[i];
363 return NULL;
364}
365
367routemap_match(const routemap_t *routemap, const char *route)
368{
369 for (size_t i = 0; i < routemap->size; i++) {
370 for (size_t j = 0; j < routemap->statements[i].matchers_size; j++) {
371 int t = 1;
372 for (size_t k = 0; t && k < routemap->statements[i].matchers[j].size; k++)
373 t &= acl_check(routemap->statements[i].matchers[j].acls[k], route);
374 if (t)
375 return &routemap->statements[i];
376 }
377 }
378
379 return NULL;
380}
381
logging utilities
pib_t * pib_new()
Initialize PIB.
Definition pib.c:50
int acl_entry_match(const char *expr, const char *target)
Match target against ACL expression.
Definition pib.c:238
routemap_t * pib_routemap_find(const pib_t *pib, const char *name)
Find a route map by name.
Definition pib.c:138
routemap_t * pib_routemap_new(pib_t *pib, const char *name, int deny)
Create and insert route map into PIB.
Definition pib.c:112
void routemap_statement_insert_action(routemap_statement_t *statement, const routemap_action_t *action)
Insert action (copy) into route map.
Definition pib.c:284
void routemap_statement_action_deinit(routemap_action_t *action)
Deinit route map action.
Definition pib.c:295
acl_entry_t * acl_find(const acl_t *acl, const char *expression)
Find entry in ACL.
Definition pib.c:160
#define VEC_ENSURE_CAPACITY(vec, size, capacity, type)
Ensure vector has at least 1 free slot for new element.
Definition pib.c:41
acl_t * pib_acl_new(pib_t *pib, const char *name)
Create and insert ACL into PIB.
Definition pib.c:96
int acl_check(const acl_t *acl, const char *target)
Check target against ACL.
Definition pib.c:257
void pib_destroy(pib_t *pib)
Deinitialize PIB.
Definition pib.c:68
routemap_statement_t * routemap_statement_new(routemap_t *routemap, uint32_t seq, int deny)
Allocate statement in route map.
Definition pib.c:331
const routemap_statement_t * routemap_match(const routemap_t *routemap, const char *route)
Match route against route map matchers.
Definition pib.c:367
routemap_statement_t * routemap_statement_find(routemap_t *routemap, uint32_t seq)
Find statement in route map by sequence number.
Definition pib.c:358
routemap_action_t * routemap_statement_action_find(const routemap_statement_t *statement, routemap_set_attr_t attribute)
Find action by attribute.
Definition pib.c:320
void routemap_matcher_insert(routemap_matcher_t *matcher, const acl_t *acl)
Insert ACL into route map matcher.
Definition pib.c:304
routemap_matcher_t * routemap_statement_matcher_new(routemap_statement_t *statement, int af)
Allocate a matcher in a route map statement.
Definition pib.c:268
void acl_insert(acl_t *acl, int deny, const char *expression)
Create and insert entry into ACL.
Definition pib.c:148
void routemap_matcher_deinit(routemap_matcher_t *matcher)
Deinitialize a route map matcher.
Definition pib.c:313
acl_t * pib_acl_find(const pib_t *pib, const char *name)
Find an ACL by name.
Definition pib.c:129
Policy Information Base.
routemap_set_attr_t
Attributes that can be set.
Definition pib.h:47
af
Address families.
Definition protocol.h:206
Access Control List entry.
Definition pib.h:33
int deny
Definition pib.h:34
Access Control List.
Definition pib.h:39
Policy Information Base.
Definition pib.h:87
Route map Action.
Definition pib.h:62
Route map ACL matcher.
Definition pib.h:55
size_t capacity
Definition pib.h:58
Route map statement.
Definition pib.h:69
Route map.
Definition pib.h:79
size_t capacity
Definition pib.h:82