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