Line data Source code
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 0 : static unsigned int bgp_ca_community_hash_key(const void *p)
34 : {
35 0 : const struct community_alias *ca = p;
36 :
37 0 : return jhash(ca->community, sizeof(ca->community), 0);
38 : }
39 :
40 0 : static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
41 : {
42 0 : const struct community_alias *ca1 = p1;
43 0 : const struct community_alias *ca2 = p2;
44 :
45 0 : return (strcmp(ca1->community, ca2->community) == 0);
46 : }
47 :
48 0 : static unsigned int bgp_ca_alias_hash_key(const void *p)
49 : {
50 0 : const struct community_alias *ca = p;
51 :
52 0 : return jhash(ca->alias, sizeof(ca->alias), 0);
53 : }
54 :
55 0 : static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
56 : {
57 0 : const struct community_alias *ca1 = p1;
58 0 : const struct community_alias *ca2 = p2;
59 :
60 0 : return (strcmp(ca1->alias, ca2->alias) == 0);
61 : }
62 :
63 0 : static void *bgp_community_alias_alloc(void *p)
64 : {
65 0 : const struct community_alias *ca = p;
66 0 : struct communtiy_alias *new;
67 :
68 0 : new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
69 0 : memcpy(new, ca, sizeof(struct community_alias));
70 :
71 0 : return new;
72 : }
73 :
74 34 : void bgp_community_alias_init(void)
75 : {
76 34 : bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
77 : bgp_ca_community_hash_cmp,
78 : "BGP community alias (community)");
79 68 : bgp_ca_alias_hash =
80 34 : hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
81 : "BGP community alias (alias)");
82 34 : }
83 :
84 0 : static void bgp_ca_free(void *ca)
85 : {
86 0 : XFREE(MTYPE_COMMUNITY_ALIAS, ca);
87 0 : }
88 :
89 34 : void bgp_community_alias_finish(void)
90 : {
91 34 : hash_clean(bgp_ca_community_hash, bgp_ca_free);
92 34 : hash_free(bgp_ca_community_hash);
93 34 : hash_clean(bgp_ca_alias_hash, bgp_ca_free);
94 34 : hash_free(bgp_ca_alias_hash);
95 34 : }
96 :
97 0 : static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
98 : struct vty *vty)
99 : {
100 0 : struct community_alias *ca = hb->data;
101 :
102 0 : vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
103 0 : }
104 :
105 0 : int bgp_community_alias_write(struct vty *vty)
106 : {
107 0 : hash_iterate(bgp_ca_community_hash,
108 : (void (*)(struct hash_bucket *,
109 : void *))bgp_community_alias_show_iterator,
110 : vty);
111 0 : return 1;
112 : }
113 :
114 0 : void bgp_ca_community_insert(struct community_alias *ca)
115 : {
116 0 : (void)hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
117 0 : }
118 :
119 0 : void bgp_ca_alias_insert(struct community_alias *ca)
120 : {
121 0 : (void)hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
122 0 : }
123 :
124 0 : void bgp_ca_community_delete(struct community_alias *ca)
125 : {
126 0 : struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
127 :
128 0 : XFREE(MTYPE_COMMUNITY_ALIAS, data);
129 0 : }
130 :
131 0 : void bgp_ca_alias_delete(struct community_alias *ca)
132 : {
133 0 : struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
134 :
135 0 : XFREE(MTYPE_COMMUNITY_ALIAS, data);
136 0 : }
137 :
138 49 : struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
139 : {
140 0 : return hash_lookup(bgp_ca_community_hash, ca);
141 : }
142 :
143 0 : struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
144 : {
145 0 : return hash_lookup(bgp_ca_alias_hash, ca);
146 : }
147 :
148 49 : const char *bgp_community2alias(char *community)
149 : {
150 49 : struct community_alias ca;
151 49 : struct community_alias *find;
152 :
153 49 : memset(&ca, 0, sizeof(ca));
154 49 : strlcpy(ca.community, community, sizeof(ca.community));
155 :
156 49 : find = bgp_ca_community_lookup(&ca);
157 49 : if (find)
158 0 : return find->alias;
159 :
160 : return community;
161 : }
162 :
163 0 : const char *bgp_alias2community(char *alias)
164 : {
165 0 : struct community_alias ca;
166 0 : struct community_alias *find;
167 :
168 0 : memset(&ca, 0, sizeof(ca));
169 0 : strlcpy(ca.alias, alias, sizeof(ca.alias));
170 :
171 0 : find = bgp_ca_alias_lookup(&ca);
172 0 : if (find)
173 0 : 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 0 : char *bgp_alias2community_str(const char *str)
185 0 : {
186 0 : char **aliases;
187 0 : char *comstr;
188 0 : int num, i;
189 :
190 0 : frrstr_split(str, " ", &aliases, &num);
191 0 : const char *communities[num];
192 :
193 0 : for (i = 0; i < num; i++)
194 0 : communities[i] = bgp_alias2community(aliases[i]);
195 :
196 0 : comstr = frrstr_join(communities, num, " ");
197 :
198 0 : for (i = 0; i < num; i++)
199 0 : XFREE(MTYPE_TMP, aliases[i]);
200 0 : XFREE(MTYPE_TMP, aliases);
201 :
202 0 : return comstr;
203 : }
204 :
205 0 : static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
206 : void *data)
207 : {
208 0 : vector *comps = data;
209 0 : struct community_alias *alias = bucket->data;
210 :
211 0 : vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
212 :
213 0 : return 1;
214 : }
215 :
216 0 : static void bgp_community_alias_cmd_completion(vector comps,
217 : struct cmd_token *token)
218 : {
219 0 : hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
220 0 : }
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 34 : void bgp_community_alias_command_completion_setup(void)
230 : {
231 34 : cmd_variable_handler_register(community_alias_handlers);
232 34 : }
|