]> git.proxmox.com Git - mirror_frr.git/blob - babeld/source.c
Merge pull request #13376 from louis-6wind/fix-flex-algo-mem-leak
[mirror_frr.git] / babeld / source.c
1 // SPDX-License-Identifier: MIT
2 /*
3 Copyright (c) 2007, 2008 by Juliusz Chroboczek
4 */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/time.h>
14
15 #include "babel_main.h"
16 #include "babeld.h"
17 #include "util.h"
18 #include "source.h"
19 #include "babel_interface.h"
20 #include "route.h"
21 #include "babel_errors.h"
22
23 struct source *srcs = NULL;
24
25 struct source*
26 find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
27 int create, unsigned short seqno)
28 {
29 struct source *src;
30
31 for(src = srcs; src; src = src->next) {
32 /* This should really be a hash table. For now, check the
33 last byte first. */
34 if(src->id[7] != id[7])
35 continue;
36 if(memcmp(src->id, id, 8) != 0)
37 continue;
38 if(src->plen != plen)
39 continue;
40 if(memcmp(src->prefix, p, 16) == 0)
41 return src;
42 }
43
44 if(!create)
45 return NULL;
46
47 src = malloc(sizeof(struct source));
48 if(src == NULL) {
49 flog_err(EC_BABEL_MEMORY, "malloc(source): %s", safe_strerror(errno));
50 return NULL;
51 }
52
53 memcpy(src->id, id, 8);
54 memcpy(src->prefix, p, 16);
55 src->plen = plen;
56 src->seqno = seqno;
57 src->metric = INFINITY;
58 src->time = babel_now.tv_sec;
59 src->route_count = 0;
60 src->next = srcs;
61 srcs = src;
62 return src;
63 }
64
65 struct source *
66 retain_source(struct source *src)
67 {
68 assert(src->route_count < 0xffff);
69 src->route_count++;
70 return src;
71 }
72
73 void
74 release_source(struct source *src)
75 {
76 assert(src->route_count > 0);
77 src->route_count--;
78 }
79
80 int
81 flush_source(struct source *src)
82 {
83 if(src->route_count > 0)
84 /* The source is in use by a route. */
85 return 0;
86
87 if(srcs == src) {
88 srcs = src->next;
89 } else {
90 struct source *previous = srcs;
91 while(previous->next != src)
92 previous = previous->next;
93 previous->next = src->next;
94 }
95
96 free(src);
97 return 1;
98 }
99
100 void
101 update_source(struct source *src,
102 unsigned short seqno, unsigned short metric)
103 {
104 if(metric >= INFINITY)
105 return;
106
107 /* If a source is expired, pretend that it doesn't exist and update
108 it unconditionally. This makes ensures that old data will
109 eventually be overridden, and prevents us from getting stuck if
110 a router loses its sequence number. */
111 if(src->time < babel_now.tv_sec - SOURCE_GC_TIME ||
112 seqno_compare(src->seqno, seqno) < 0 ||
113 (src->seqno == seqno && src->metric > metric)) {
114 src->seqno = seqno;
115 src->metric = metric;
116 }
117 src->time = babel_now.tv_sec;
118 }
119
120 void
121 expire_sources(void)
122 {
123 struct source *src;
124
125 src = srcs;
126 while(src) {
127 if(src->time > babel_now.tv_sec)
128 /* clock stepped */
129 src->time = babel_now.tv_sec;
130 if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) {
131 struct source *old = src;
132 src = src->next;
133 flush_source(old);
134 continue;
135 }
136 src = src->next;
137 }
138 }
139
140 void
141 check_sources_released(void)
142 {
143 struct source *src;
144
145 for(src = srcs; src; src = src->next) {
146 if(src->route_count != 0)
147 fprintf(stderr, "Warning: source %s %s has refcount %d.\n",
148 format_eui64(src->id),
149 format_prefix(src->prefix, src->plen),
150 (int)src->route_count);
151 }
152 }