]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_routemap.c
Merge pull request #13149 from pushpasis/mgmt_cleanup_zlog
[mirror_frr.git] / ripngd / ripng_routemap.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* RIPng routemap.
3 * Copyright (C) 1999 Kunihiro Ishiguro
4 */
5
6 #include <zebra.h>
7
8 #include "if.h"
9 #include "memory.h"
10 #include "prefix.h"
11 #include "vty.h"
12 #include "routemap.h"
13 #include "command.h"
14 #include "sockunion.h"
15
16 #include "ripngd/ripngd.h"
17
18 struct rip_metric_modifier {
19 enum { metric_increment, metric_decrement, metric_absolute } type;
20 bool used;
21 uint8_t metric;
22 };
23
24 /* `match metric METRIC' */
25 /* Match function return 1 if match is success else return zero. */
26 static enum route_map_cmd_result_t
27 route_match_metric(void *rule, const struct prefix *prefix, void *object)
28 {
29 uint32_t *metric;
30 struct ripng_info *rinfo;
31
32 metric = rule;
33 rinfo = object;
34
35 if (rinfo->metric == *metric)
36 return RMAP_MATCH;
37 else
38 return RMAP_NOMATCH;
39
40 return RMAP_NOMATCH;
41 }
42
43 /* Route map `match metric' match statement. `arg' is METRIC value */
44 static void *route_match_metric_compile(const char *arg)
45 {
46 uint32_t *metric;
47
48 metric = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
49 *metric = atoi(arg);
50
51 if (*metric > 0)
52 return metric;
53
54 XFREE(MTYPE_ROUTE_MAP_COMPILED, metric);
55 return NULL;
56 }
57
58 /* Free route map's compiled `match metric' value. */
59 static void route_match_metric_free(void *rule)
60 {
61 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
62 }
63
64 /* Route map commands for metric matching. */
65 static const struct route_map_rule_cmd route_match_metric_cmd = {
66 "metric",
67 route_match_metric,
68 route_match_metric_compile,
69 route_match_metric_free
70 };
71
72 /* `match interface IFNAME' */
73 /* Match function return 1 if match is success else return zero. */
74 static enum route_map_cmd_result_t
75 route_match_interface(void *rule, const struct prefix *prefix, void *object)
76 {
77 struct ripng_info *rinfo;
78 struct interface *ifp;
79 char *ifname;
80
81 ifname = rule;
82 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
83
84 if (!ifp)
85 return RMAP_NOMATCH;
86
87 rinfo = object;
88
89 if (rinfo->ifindex == ifp->ifindex)
90 return RMAP_MATCH;
91 else
92 return RMAP_NOMATCH;
93
94 return RMAP_NOMATCH;
95 }
96
97 /* Route map `match interface' match statement. `arg' is IFNAME value */
98 static void *route_match_interface_compile(const char *arg)
99 {
100 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
101 }
102
103 static void route_match_interface_free(void *rule)
104 {
105 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
106 }
107
108 static const struct route_map_rule_cmd route_match_interface_cmd = {
109 "interface",
110 route_match_interface,
111 route_match_interface_compile,
112 route_match_interface_free
113 };
114
115 /* `match tag TAG' */
116 /* Match function return 1 if match is success else return zero. */
117 static enum route_map_cmd_result_t route_match_tag(void *rule,
118 const struct prefix *prefix,
119 void *object)
120 {
121 route_tag_t *tag;
122 struct ripng_info *rinfo;
123 route_tag_t rinfo_tag;
124
125 tag = rule;
126 rinfo = object;
127
128 /* The information stored by rinfo is host ordered. */
129 rinfo_tag = rinfo->tag;
130 if (rinfo_tag == *tag)
131 return RMAP_MATCH;
132 else
133 return RMAP_NOMATCH;
134 }
135
136
137 static const struct route_map_rule_cmd route_match_tag_cmd = {
138 "tag",
139 route_match_tag,
140 route_map_rule_tag_compile,
141 route_map_rule_tag_free,
142 };
143
144 /* `set metric METRIC' */
145
146 /* Set metric to attribute. */
147 static enum route_map_cmd_result_t
148 route_set_metric(void *rule, const struct prefix *prefix, void *object)
149 {
150 struct rip_metric_modifier *mod;
151 struct ripng_info *rinfo;
152
153 mod = rule;
154 rinfo = object;
155
156 if (!mod->used)
157 return RMAP_OKAY;
158
159 if (mod->type == metric_increment)
160 rinfo->metric_out += mod->metric;
161 else if (mod->type == metric_decrement)
162 rinfo->metric_out -= mod->metric;
163 else if (mod->type == metric_absolute)
164 rinfo->metric_out = mod->metric;
165
166 if (rinfo->metric_out < 1)
167 rinfo->metric_out = 1;
168 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
169 rinfo->metric_out = RIPNG_METRIC_INFINITY;
170
171 rinfo->metric_set = 1;
172
173 return RMAP_OKAY;
174 }
175
176 /* set metric compilation. */
177 static void *route_set_metric_compile(const char *arg)
178 {
179 int len;
180 const char *pnt;
181 long metric;
182 char *endptr = NULL;
183 struct rip_metric_modifier *mod;
184
185 len = strlen(arg);
186 pnt = arg;
187
188 mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
189 sizeof(struct rip_metric_modifier));
190 mod->used = false;
191
192 if (len == 0)
193 return mod;
194
195 /* Examine first character. */
196 if (arg[0] == '+') {
197 mod->type = metric_increment;
198 pnt++;
199 } else if (arg[0] == '-') {
200 mod->type = metric_decrement;
201 pnt++;
202 } else
203 mod->type = metric_absolute;
204
205 /* Check beginning with digit string. */
206 if (*pnt < '0' || *pnt > '9')
207 return mod;
208
209 /* Convert string to integer. */
210 metric = strtol(pnt, &endptr, 10);
211
212 if (*endptr != '\0' || metric < 0)
213 return mod;
214
215 if (metric > RIPNG_METRIC_INFINITY) {
216 zlog_info(
217 "%s: Metric specified: %ld is being converted into METRIC_INFINITY",
218 __func__, metric);
219 mod->metric = RIPNG_METRIC_INFINITY;
220 } else
221 mod->metric = metric;
222
223 mod->used = true;
224 return mod;
225 }
226
227 /* Free route map's compiled `set metric' value. */
228 static void route_set_metric_free(void *rule)
229 {
230 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
231 }
232
233 static const struct route_map_rule_cmd route_set_metric_cmd = {
234 "metric",
235 route_set_metric,
236 route_set_metric_compile,
237 route_set_metric_free,
238 };
239
240 /* `set ipv6 next-hop local IP_ADDRESS' */
241
242 /* Set nexthop to object. object must be pointer to struct attr. */
243 static enum route_map_cmd_result_t
244 route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
245 {
246 struct in6_addr *address;
247 struct ripng_info *rinfo;
248
249 /* Fetch routemap's rule information. */
250 address = rule;
251 rinfo = object;
252
253 /* Set next hop value. */
254 rinfo->nexthop_out = *address;
255
256 return RMAP_OKAY;
257 }
258
259 /* Route map `ipv6 nexthop local' compile function. Given string is converted
260 to struct in6_addr structure. */
261 static void *route_set_ipv6_nexthop_local_compile(const char *arg)
262 {
263 int ret;
264 struct in6_addr *address;
265
266 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
267
268 ret = inet_pton(AF_INET6, arg, address);
269
270 if (ret == 0) {
271 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
272 return NULL;
273 }
274
275 return address;
276 }
277
278 /* Free route map's compiled `ipv6 nexthop local' value. */
279 static void route_set_ipv6_nexthop_local_free(void *rule)
280 {
281 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
282 }
283
284 /* Route map commands for ipv6 nexthop local set. */
285 static const struct route_map_rule_cmd
286 route_set_ipv6_nexthop_local_cmd = {
287 "ipv6 next-hop local",
288 route_set_ipv6_nexthop_local,
289 route_set_ipv6_nexthop_local_compile,
290 route_set_ipv6_nexthop_local_free
291 };
292
293 /* `set tag TAG' */
294
295 /* Set tag to object. object must be pointer to struct attr. */
296 static enum route_map_cmd_result_t
297 route_set_tag(void *rule, const struct prefix *prefix, void *object)
298 {
299 route_tag_t *tag;
300 struct ripng_info *rinfo;
301
302 /* Fetch routemap's rule information. */
303 tag = rule;
304 rinfo = object;
305
306 /* Set next hop value. */
307 rinfo->tag_out = *tag;
308
309 return RMAP_OKAY;
310 }
311
312 /* Route map commands for tag set. */
313 static const struct route_map_rule_cmd route_set_tag_cmd = {
314 "tag",
315 route_set_tag,
316 route_map_rule_tag_compile,
317 route_map_rule_tag_free
318 };
319
320 #define MATCH_STR "Match values from routing table\n"
321 #define SET_STR "Set values in destination routing protocol\n"
322
323 void ripng_route_map_init(void)
324 {
325 route_map_init();
326
327 route_map_match_interface_hook(generic_match_add);
328 route_map_no_match_interface_hook(generic_match_delete);
329
330 route_map_match_metric_hook(generic_match_add);
331 route_map_no_match_metric_hook(generic_match_delete);
332
333 route_map_match_tag_hook(generic_match_add);
334 route_map_no_match_tag_hook(generic_match_delete);
335
336 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
337 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
338
339 route_map_set_metric_hook(generic_set_add);
340 route_map_no_set_metric_hook(generic_set_delete);
341
342 route_map_set_tag_hook(generic_set_add);
343 route_map_no_set_tag_hook(generic_set_delete);
344
345 route_map_install_match(&route_match_metric_cmd);
346 route_map_install_match(&route_match_interface_cmd);
347 route_map_install_match(&route_match_tag_cmd);
348 route_map_install_set(&route_set_metric_cmd);
349 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
350 route_map_install_set(&route_set_tag_cmd);
351 }