]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_community_alias.c
bgpd: Fix memory leak for community alias
[mirror_frr.git] / bgpd / bgp_community_alias.c
1 /* BGP community, large-community aliasing.
2 *
3 * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com>
4 *
5 * This file is part of FRRouting (FRR).
6 *
7 * FRR is free software; you can redistribute it and/or modify it under the
8 * terms of the GNU General Public License as published by the Free Software
9 * Foundation; either version 2, or (at your option) any later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "zebra.h"
22
23 #include "memory.h"
24 #include "lib/jhash.h"
25 #include "frrstr.h"
26
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_community_alias.h"
29
30 static struct hash *bgp_ca_alias_hash;
31 static struct hash *bgp_ca_community_hash;
32
33 static unsigned int bgp_ca_community_hash_key(const void *p)
34 {
35 const struct community_alias *ca = p;
36
37 return jhash(ca->community, sizeof(ca->community), 0);
38 }
39
40 static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
41 {
42 const struct community_alias *ca1 = p1;
43 const struct community_alias *ca2 = p2;
44
45 return (strcmp(ca1->community, ca2->community) == 0);
46 }
47
48 static unsigned int bgp_ca_alias_hash_key(const void *p)
49 {
50 const struct community_alias *ca = p;
51
52 return jhash(ca->alias, sizeof(ca->alias), 0);
53 }
54
55 static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
56 {
57 const struct community_alias *ca1 = p1;
58 const struct community_alias *ca2 = p2;
59
60 return (strcmp(ca1->alias, ca2->alias) == 0);
61 }
62
63 static void *bgp_community_alias_alloc(void *p)
64 {
65 const struct community_alias *ca = p;
66 struct communtiy_alias *new;
67
68 new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
69 memcpy(new, ca, sizeof(struct community_alias));
70
71 return new;
72 }
73
74 void bgp_community_alias_init(void)
75 {
76 bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
77 bgp_ca_community_hash_cmp,
78 "BGP community alias (community)");
79 bgp_ca_alias_hash =
80 hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
81 "BGP community alias (alias)");
82 }
83
84 static void bgp_ca_free(void *ca)
85 {
86 XFREE(MTYPE_COMMUNITY_ALIAS, ca);
87 }
88
89 void bgp_community_alias_finish(void)
90 {
91 hash_clean(bgp_ca_community_hash, bgp_ca_free);
92 hash_free(bgp_ca_community_hash);
93 hash_clean(bgp_ca_alias_hash, bgp_ca_free);
94 hash_free(bgp_ca_alias_hash);
95 }
96
97 static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
98 struct vty *vty)
99 {
100 struct community_alias *ca = hb->data;
101
102 vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
103 }
104
105 int bgp_community_alias_write(struct vty *vty)
106 {
107 hash_iterate(bgp_ca_community_hash,
108 (void (*)(struct hash_bucket *,
109 void *))bgp_community_alias_show_iterator,
110 vty);
111 return 1;
112 }
113
114 void bgp_ca_community_insert(struct community_alias *ca)
115 {
116 (void)hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
117 }
118
119 void bgp_ca_alias_insert(struct community_alias *ca)
120 {
121 (void)hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
122 }
123
124 void bgp_ca_community_delete(struct community_alias *ca)
125 {
126 struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
127
128 XFREE(MTYPE_COMMUNITY_ALIAS, data);
129 }
130
131 void bgp_ca_alias_delete(struct community_alias *ca)
132 {
133 struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
134
135 XFREE(MTYPE_COMMUNITY_ALIAS, data);
136 }
137
138 struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
139 {
140 return hash_lookup(bgp_ca_community_hash, ca);
141 }
142
143 struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
144 {
145 return hash_lookup(bgp_ca_alias_hash, ca);
146 }
147
148 const char *bgp_community2alias(char *community)
149 {
150 struct community_alias ca;
151 struct community_alias *find;
152
153 memset(&ca, 0, sizeof(ca));
154 strlcpy(ca.community, community, sizeof(ca.community));
155
156 find = bgp_ca_community_lookup(&ca);
157 if (find)
158 return find->alias;
159
160 return community;
161 }
162
163 const char *bgp_alias2community(char *alias)
164 {
165 struct community_alias ca;
166 struct community_alias *find;
167
168 memset(&ca, 0, sizeof(ca));
169 strlcpy(ca.alias, alias, sizeof(ca.alias));
170
171 find = bgp_ca_alias_lookup(&ca);
172 if (find)
173 return find->community;
174
175 return alias;
176 }
177
178 /* Communities structs have `->str` which is used
179 * for vty outputs and extended BGP community lists
180 * with regexp.
181 * This is a helper to convert already aliased version
182 * of communities into numerical-only format.
183 */
184 char *bgp_alias2community_str(const char *str)
185 {
186 char **aliases;
187 char *comstr;
188 int num, i;
189
190 frrstr_split(str, " ", &aliases, &num);
191 const char *communities[num];
192
193 for (i = 0; i < num; i++)
194 communities[i] = bgp_alias2community(aliases[i]);
195
196 comstr = frrstr_join(communities, num, " ");
197
198 for (i = 0; i < num; i++)
199 XFREE(MTYPE_TMP, aliases[i]);
200 XFREE(MTYPE_TMP, aliases);
201
202 return comstr;
203 }
204
205 static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
206 void *data)
207 {
208 vector *comps = data;
209 struct community_alias *alias = bucket->data;
210
211 vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
212
213 return 1;
214 }
215
216 static void bgp_community_alias_cmd_completion(vector comps,
217 struct cmd_token *token)
218 {
219 hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
220 }
221
222 static const struct cmd_variable_handler community_alias_handlers[] = {
223 {.varname = "alias_name",
224 .completions = bgp_community_alias_cmd_completion},
225 {.tokenname = "ALIAS_NAME",
226 .completions = bgp_community_alias_cmd_completion},
227 {.completions = NULL}};
228
229 void bgp_community_alias_command_completion_setup(void)
230 {
231 cmd_variable_handler_register(community_alias_handlers);
232 }