]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_community_alias.c
Revert "bgpd: Free only subattributes, not the whole attr_extra pointer"
[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 "memory.h"
22 #include "lib/jhash.h"
23 #include "frrstr.h"
24
25 #include "bgpd/bgpd.h"
26 #include "bgpd/bgp_community_alias.h"
27
28 static struct hash *bgp_ca_alias_hash;
29 static struct hash *bgp_ca_community_hash;
30
31 static unsigned int bgp_ca_community_hash_key(const void *p)
32 {
33 const struct community_alias *ca = p;
34
35 return jhash(ca->community, sizeof(ca->community), 0);
36 }
37
38 static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
39 {
40 const struct community_alias *ca1 = p1;
41 const struct community_alias *ca2 = p2;
42
43 return (strcmp(ca1->community, ca2->community) == 0);
44 }
45
46 static unsigned int bgp_ca_alias_hash_key(const void *p)
47 {
48 const struct community_alias *ca = p;
49
50 return jhash(ca->alias, sizeof(ca->alias), 0);
51 }
52
53 static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
54 {
55 const struct community_alias *ca1 = p1;
56 const struct community_alias *ca2 = p2;
57
58 return (strcmp(ca1->alias, ca2->alias) == 0);
59 }
60
61 static void *bgp_community_alias_alloc(void *p)
62 {
63 const struct community_alias *ca = p;
64 struct communtiy_alias *new;
65
66 new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
67 memcpy(new, ca, sizeof(struct community_alias));
68
69 return new;
70 }
71
72 void bgp_community_alias_init(void)
73 {
74 bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
75 bgp_ca_community_hash_cmp,
76 "BGP community alias (community)");
77 bgp_ca_alias_hash =
78 hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
79 "BGP community alias (alias)");
80 }
81
82 void bgp_community_alias_finish(void)
83 {
84 hash_free(bgp_ca_community_hash);
85 hash_free(bgp_ca_alias_hash);
86 }
87
88 static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
89 struct vty *vty)
90 {
91 struct community_alias *ca = hb->data;
92
93 vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
94 }
95
96 int bgp_community_alias_write(struct vty *vty)
97 {
98 hash_iterate(bgp_ca_community_hash,
99 (void (*)(struct hash_bucket *,
100 void *))bgp_community_alias_show_iterator,
101 vty);
102 return 1;
103 }
104
105 void bgp_ca_community_insert(struct community_alias *ca)
106 {
107 hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
108 }
109
110 void bgp_ca_alias_insert(struct community_alias *ca)
111 {
112 hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
113 }
114
115 void bgp_ca_community_delete(struct community_alias *ca)
116 {
117 struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
118
119 XFREE(MTYPE_COMMUNITY_ALIAS, data);
120 }
121
122 void bgp_ca_alias_delete(struct community_alias *ca)
123 {
124 struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
125
126 XFREE(MTYPE_COMMUNITY_ALIAS, data);
127 }
128
129 struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
130 {
131 return hash_lookup(bgp_ca_community_hash, ca);
132 }
133
134 struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
135 {
136 return hash_lookup(bgp_ca_alias_hash, ca);
137 }
138
139 const char *bgp_community2alias(char *community)
140 {
141 struct community_alias ca;
142 struct community_alias *find;
143
144 memset(&ca, 0, sizeof(ca));
145 strlcpy(ca.community, community, sizeof(ca.community));
146
147 find = bgp_ca_community_lookup(&ca);
148 if (find)
149 return find->alias;
150
151 return community;
152 }
153
154 const char *bgp_alias2community(char *alias)
155 {
156 struct community_alias ca;
157 struct community_alias *find;
158
159 memset(&ca, 0, sizeof(ca));
160 strlcpy(ca.alias, alias, sizeof(ca.alias));
161
162 find = bgp_ca_alias_lookup(&ca);
163 if (find)
164 return find->community;
165
166 return alias;
167 }
168
169 /* Communities structs have `->str` which is used
170 * for vty outputs and extended BGP community lists
171 * with regexp.
172 * This is a helper to convert already aliased version
173 * of communities into numerical-only format.
174 */
175 char *bgp_alias2community_str(const char *str)
176 {
177 char **aliases;
178 char *comstr;
179 int num, i;
180
181 frrstr_split(str, " ", &aliases, &num);
182 const char *communities[num];
183
184 for (i = 0; i < num; i++)
185 communities[i] = bgp_alias2community(aliases[i]);
186
187 comstr = frrstr_join(communities, num, " ");
188
189 for (i = 0; i < num; i++)
190 XFREE(MTYPE_TMP, aliases[i]);
191 XFREE(MTYPE_TMP, aliases);
192
193 return comstr;
194 }
195
196 static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
197 void *data)
198 {
199 vector *comps = data;
200 struct community_alias *alias = bucket->data;
201
202 vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
203
204 return 1;
205 }
206
207 static void bgp_community_alias_cmd_completion(vector comps,
208 struct cmd_token *token)
209 {
210 hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
211 }
212
213 static const struct cmd_variable_handler community_alias_handlers[] = {
214 {.varname = "alias_name",
215 .completions = bgp_community_alias_cmd_completion},
216 {.tokenname = "ALIAS_NAME",
217 .completions = bgp_community_alias_cmd_completion},
218 {.completions = NULL}};
219
220 void bgp_community_alias_command_completion_setup(void)
221 {
222 cmd_variable_handler_register(community_alias_handlers);
223 }