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