]>
Commit | Line | Data |
---|---|---|
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 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "if.h" | |
25 | #include "memory.h" | |
26 | #include "prefix.h" | |
82f97584 | 27 | #include "vty.h" |
718e3744 | 28 | #include "routemap.h" |
29 | #include "command.h" | |
a94434b6 | 30 | #include "sockunion.h" |
718e3744 | 31 | |
32 | #include "ripngd/ripngd.h" | |
6b0655a2 | 33 | |
a94434b6 | 34 | struct rip_metric_modifier |
35 | { | |
36 | enum | |
37 | { | |
38 | metric_increment, | |
39 | metric_decrement, | |
40 | metric_absolute | |
41 | } type; | |
42 | ||
43 | u_char metric; | |
44 | }; | |
45 | ||
a94434b6 | 46 | /* `match metric METRIC' */ |
47 | /* Match function return 1 if match is success else return zero. */ | |
6ac29a51 | 48 | static route_map_result_t |
a94434b6 | 49 | route_match_metric (void *rule, struct prefix *prefix, |
50 | route_map_object_t type, void *object) | |
51 | { | |
52 | u_int32_t *metric; | |
53 | struct ripng_info *rinfo; | |
54 | ||
55 | if (type == RMAP_RIPNG) | |
56 | { | |
57 | metric = rule; | |
58 | rinfo = object; | |
59 | ||
60 | if (rinfo->metric == *metric) | |
61 | return RMAP_MATCH; | |
62 | else | |
63 | return RMAP_NOMATCH; | |
64 | } | |
65 | return RMAP_NOMATCH; | |
66 | } | |
67 | ||
68 | /* Route map `match metric' match statement. `arg' is METRIC value */ | |
6ac29a51 | 69 | static void * |
98b718a9 | 70 | route_match_metric_compile (const char *arg) |
a94434b6 | 71 | { |
72 | u_int32_t *metric; | |
73 | ||
74 | metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); | |
75 | *metric = atoi (arg); | |
76 | ||
77 | if(*metric > 0) | |
78 | return metric; | |
79 | ||
80 | XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); | |
81 | return NULL; | |
82 | } | |
83 | ||
84 | /* Free route map's compiled `match metric' value. */ | |
6ac29a51 | 85 | static void |
a94434b6 | 86 | route_match_metric_free (void *rule) |
87 | { | |
88 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
89 | } | |
90 | ||
91 | /* Route map commands for metric matching. */ | |
6ac29a51 | 92 | static struct route_map_rule_cmd route_match_metric_cmd = |
a94434b6 | 93 | { |
94 | "metric", | |
95 | route_match_metric, | |
96 | route_match_metric_compile, | |
97 | route_match_metric_free | |
98 | }; | |
6b0655a2 | 99 | |
718e3744 | 100 | /* `match interface IFNAME' */ |
a94434b6 | 101 | /* Match function return 1 if match is success else return zero. */ |
6ac29a51 | 102 | static route_map_result_t |
718e3744 | 103 | route_match_interface (void *rule, struct prefix *prefix, |
104 | route_map_object_t type, void *object) | |
105 | { | |
106 | struct ripng_info *rinfo; | |
107 | struct interface *ifp; | |
108 | char *ifname; | |
109 | ||
a94434b6 | 110 | if (type == RMAP_RIPNG) |
718e3744 | 111 | { |
112 | ifname = rule; | |
113 | ifp = if_lookup_by_name(ifname); | |
114 | ||
115 | if (!ifp) | |
a94434b6 | 116 | return RMAP_NOMATCH; |
718e3744 | 117 | |
118 | rinfo = object; | |
119 | ||
120 | if (rinfo->ifindex == ifp->ifindex) | |
a94434b6 | 121 | return RMAP_MATCH; |
718e3744 | 122 | else |
a94434b6 | 123 | return RMAP_NOMATCH; |
718e3744 | 124 | } |
a94434b6 | 125 | return RMAP_NOMATCH; |
718e3744 | 126 | } |
127 | ||
a94434b6 | 128 | /* Route map `match interface' match statement. `arg' is IFNAME value */ |
6ac29a51 | 129 | static void * |
98b718a9 | 130 | route_match_interface_compile (const char *arg) |
718e3744 | 131 | { |
132 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
133 | } | |
134 | ||
6ac29a51 | 135 | static void |
718e3744 | 136 | route_match_interface_free (void *rule) |
137 | { | |
138 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
139 | } | |
140 | ||
6ac29a51 | 141 | static struct route_map_rule_cmd route_match_interface_cmd = |
718e3744 | 142 | { |
143 | "interface", | |
144 | route_match_interface, | |
145 | route_match_interface_compile, | |
146 | route_match_interface_free | |
147 | }; | |
a94434b6 | 148 | |
149 | /* `match tag TAG' */ | |
150 | /* Match function return 1 if match is success else return zero. */ | |
6ac29a51 | 151 | static route_map_result_t |
a94434b6 | 152 | route_match_tag (void *rule, struct prefix *prefix, |
153 | route_map_object_t type, void *object) | |
718e3744 | 154 | { |
a94434b6 | 155 | u_short *tag; |
156 | struct ripng_info *rinfo; | |
718e3744 | 157 | |
a94434b6 | 158 | if (type == RMAP_RIPNG) |
159 | { | |
160 | tag = rule; | |
161 | rinfo = object; | |
162 | ||
163 | /* The information stored by rinfo is host ordered. */ | |
164 | if (rinfo->tag == *tag) | |
165 | return RMAP_MATCH; | |
166 | else | |
167 | return RMAP_NOMATCH; | |
168 | } | |
169 | return RMAP_NOMATCH; | |
170 | } | |
171 | ||
172 | /* Route map `match tag' match statement. `arg' is TAG value */ | |
6ac29a51 | 173 | static void * |
98b718a9 | 174 | route_match_tag_compile (const char *arg) |
a94434b6 | 175 | { |
176 | u_short *tag; | |
177 | ||
178 | tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); | |
179 | *tag = atoi (arg); | |
180 | ||
181 | return tag; | |
182 | } | |
183 | ||
184 | /* Free route map's compiled `match tag' value. */ | |
6ac29a51 | 185 | static void |
a94434b6 | 186 | route_match_tag_free (void *rule) |
187 | { | |
188 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
189 | } | |
190 | ||
191 | /* Route map commands for tag matching. */ | |
6ac29a51 | 192 | static struct route_map_rule_cmd route_match_tag_cmd = |
a94434b6 | 193 | { |
194 | "tag", | |
195 | route_match_tag, | |
196 | route_match_tag_compile, | |
197 | route_match_tag_free | |
718e3744 | 198 | }; |
6b0655a2 | 199 | |
a94434b6 | 200 | /* `set metric METRIC' */ |
718e3744 | 201 | |
a94434b6 | 202 | /* Set metric to attribute. */ |
6ac29a51 | 203 | static route_map_result_t |
718e3744 | 204 | route_set_metric (void *rule, struct prefix *prefix, |
205 | route_map_object_t type, void *object) | |
206 | { | |
207 | if (type == RMAP_RIPNG) | |
208 | { | |
209 | struct rip_metric_modifier *mod; | |
210 | struct ripng_info *rinfo; | |
211 | ||
212 | mod = rule; | |
213 | rinfo = object; | |
214 | ||
215 | if (mod->type == metric_increment) | |
a94434b6 | 216 | rinfo->metric_out += mod->metric; |
718e3744 | 217 | else if (mod->type == metric_decrement) |
a94434b6 | 218 | rinfo->metric_out-= mod->metric; |
718e3744 | 219 | else if (mod->type == metric_absolute) |
a94434b6 | 220 | rinfo->metric_out = mod->metric; |
718e3744 | 221 | |
a94434b6 | 222 | if (rinfo->metric_out < 1) |
223 | rinfo->metric_out = 1; | |
224 | if (rinfo->metric_out > RIPNG_METRIC_INFINITY) | |
225 | rinfo->metric_out = RIPNG_METRIC_INFINITY; | |
718e3744 | 226 | |
227 | rinfo->metric_set = 1; | |
228 | } | |
229 | return RMAP_OKAY; | |
230 | } | |
231 | ||
a94434b6 | 232 | /* set metric compilation. */ |
6ac29a51 | 233 | static void * |
98b718a9 | 234 | route_set_metric_compile (const char *arg) |
718e3744 | 235 | { |
236 | int len; | |
98b718a9 | 237 | const char *pnt; |
718e3744 | 238 | int type; |
239 | long metric; | |
240 | char *endptr = NULL; | |
241 | struct rip_metric_modifier *mod; | |
242 | ||
243 | len = strlen (arg); | |
244 | pnt = arg; | |
245 | ||
246 | if (len == 0) | |
247 | return NULL; | |
248 | ||
249 | /* Examine first character. */ | |
250 | if (arg[0] == '+') | |
251 | { | |
252 | type = metric_increment; | |
253 | pnt++; | |
254 | } | |
255 | else if (arg[0] == '-') | |
256 | { | |
257 | type = metric_decrement; | |
258 | pnt++; | |
259 | } | |
260 | else | |
261 | type = metric_absolute; | |
262 | ||
263 | /* Check beginning with digit string. */ | |
264 | if (*pnt < '0' || *pnt > '9') | |
265 | return NULL; | |
266 | ||
267 | /* Convert string to integer. */ | |
268 | metric = strtol (pnt, &endptr, 10); | |
269 | ||
270 | if (metric == LONG_MAX || *endptr != '\0') | |
271 | return NULL; | |
73ffb25b | 272 | /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ |
273 | /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ | |
274 | if (metric < 0) | |
718e3744 | 275 | return NULL; |
276 | ||
277 | mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, | |
278 | sizeof (struct rip_metric_modifier)); | |
279 | mod->type = type; | |
280 | mod->metric = metric; | |
281 | ||
282 | return mod; | |
283 | } | |
284 | ||
a94434b6 | 285 | /* Free route map's compiled `set metric' value. */ |
6ac29a51 | 286 | static void |
718e3744 | 287 | route_set_metric_free (void *rule) |
288 | { | |
289 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
290 | } | |
291 | ||
6ac29a51 | 292 | static struct route_map_rule_cmd route_set_metric_cmd = |
718e3744 | 293 | { |
294 | "metric", | |
295 | route_set_metric, | |
296 | route_set_metric_compile, | |
297 | route_set_metric_free, | |
298 | }; | |
a94434b6 | 299 | |
300 | /* `set ipv6 next-hop local IP_ADDRESS' */ | |
301 | ||
302 | /* Set nexthop to object. ojbect must be pointer to struct attr. */ | |
6ac29a51 | 303 | static route_map_result_t |
a94434b6 | 304 | route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, |
305 | route_map_object_t type, void *object) | |
718e3744 | 306 | { |
a94434b6 | 307 | struct in6_addr *address; |
308 | struct ripng_info *rinfo; | |
718e3744 | 309 | |
a94434b6 | 310 | if(type == RMAP_RIPNG) |
718e3744 | 311 | { |
a94434b6 | 312 | /* Fetch routemap's rule information. */ |
313 | address = rule; | |
314 | rinfo = object; | |
315 | ||
316 | /* Set next hop value. */ | |
317 | rinfo->nexthop_out = *address; | |
718e3744 | 318 | } |
a94434b6 | 319 | |
320 | return RMAP_OKAY; | |
718e3744 | 321 | } |
322 | ||
a94434b6 | 323 | /* Route map `ipv6 nexthop local' compile function. Given string is converted |
324 | to struct in6_addr structure. */ | |
6ac29a51 | 325 | static void * |
98b718a9 | 326 | route_set_ipv6_nexthop_local_compile (const char *arg) |
718e3744 | 327 | { |
328 | int ret; | |
a94434b6 | 329 | struct in6_addr *address; |
718e3744 | 330 | |
7a559cbe | 331 | address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); |
a94434b6 | 332 | |
333 | ret = inet_pton (AF_INET6, arg, address); | |
334 | ||
335 | if (ret == 0) | |
718e3744 | 336 | { |
a94434b6 | 337 | XFREE (MTYPE_ROUTE_MAP_COMPILED, address); |
338 | return NULL; | |
718e3744 | 339 | } |
a94434b6 | 340 | |
341 | return address; | |
718e3744 | 342 | } |
343 | ||
a94434b6 | 344 | /* Free route map's compiled `ipv6 nexthop local' value. */ |
6ac29a51 | 345 | static void |
a94434b6 | 346 | route_set_ipv6_nexthop_local_free (void *rule) |
718e3744 | 347 | { |
a94434b6 | 348 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); |
349 | } | |
718e3744 | 350 | |
a94434b6 | 351 | /* Route map commands for ipv6 nexthop local set. */ |
6ac29a51 | 352 | static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = |
a94434b6 | 353 | { |
354 | "ipv6 next-hop local", | |
355 | route_set_ipv6_nexthop_local, | |
356 | route_set_ipv6_nexthop_local_compile, | |
357 | route_set_ipv6_nexthop_local_free | |
358 | }; | |
359 | ||
360 | /* `set tag TAG' */ | |
361 | ||
362 | /* Set tag to object. ojbect must be pointer to struct attr. */ | |
6ac29a51 | 363 | static route_map_result_t |
a94434b6 | 364 | route_set_tag (void *rule, struct prefix *prefix, |
365 | route_map_object_t type, void *object) | |
366 | { | |
367 | u_short *tag; | |
368 | struct ripng_info *rinfo; | |
369 | ||
370 | if(type == RMAP_RIPNG) | |
718e3744 | 371 | { |
a94434b6 | 372 | /* Fetch routemap's rule information. */ |
373 | tag = rule; | |
374 | rinfo = object; | |
375 | ||
376 | /* Set next hop value. */ | |
377 | rinfo->tag_out = *tag; | |
718e3744 | 378 | } |
a94434b6 | 379 | |
380 | return RMAP_OKAY; | |
718e3744 | 381 | } |
382 | ||
a94434b6 | 383 | /* Route map `tag' compile function. Given string is converted |
384 | to u_short. */ | |
6ac29a51 | 385 | static void * |
98b718a9 | 386 | route_set_tag_compile (const char *arg) |
718e3744 | 387 | { |
a94434b6 | 388 | u_short *tag; |
718e3744 | 389 | |
a94434b6 | 390 | tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); |
391 | *tag = atoi (arg); | |
392 | ||
393 | return tag; | |
394 | } | |
395 | ||
396 | /* Free route map's compiled `ip nexthop' value. */ | |
6ac29a51 | 397 | static void |
a94434b6 | 398 | route_set_tag_free (void *rule) |
399 | { | |
400 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
718e3744 | 401 | } |
a94434b6 | 402 | |
403 | /* Route map commands for tag set. */ | |
6ac29a51 | 404 | static struct route_map_rule_cmd route_set_tag_cmd = |
a94434b6 | 405 | { |
406 | "tag", | |
407 | route_set_tag, | |
408 | route_set_tag_compile, | |
409 | route_set_tag_free | |
410 | }; | |
6b0655a2 | 411 | |
a94434b6 | 412 | #define MATCH_STR "Match values from routing table\n" |
413 | #define SET_STR "Set values in destination routing protocol\n" | |
414 | ||
a94434b6 | 415 | void |
416 | ripng_route_map_reset () | |
417 | { | |
418 | /* XXX ??? */ | |
419 | ; | |
420 | } | |
421 | ||
718e3744 | 422 | void |
423 | ripng_route_map_init () | |
424 | { | |
425 | route_map_init (); | |
426 | route_map_init_vty (); | |
427 | ||
82f97584 DW |
428 | route_map_match_interface_hook (generic_match_add); |
429 | route_map_no_match_interface_hook (generic_match_delete); | |
430 | ||
431 | route_map_match_metric_hook (generic_match_add); | |
432 | route_map_no_match_metric_hook (generic_match_delete); | |
433 | ||
434 | route_map_match_tag_hook (generic_match_add); | |
435 | route_map_no_match_tag_hook (generic_match_delete); | |
436 | ||
437 | route_map_set_ipv6_nexthop_local_hook (generic_set_add); | |
438 | route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete); | |
439 | ||
440 | route_map_set_metric_hook (generic_set_add); | |
441 | route_map_no_set_metric_hook (generic_set_delete); | |
442 | ||
443 | route_map_set_tag_hook (generic_set_add); | |
444 | route_map_no_set_tag_hook (generic_set_delete); | |
445 | ||
a94434b6 | 446 | route_map_install_match (&route_match_metric_cmd); |
447 | route_map_install_match (&route_match_interface_cmd); | |
448 | route_map_install_match (&route_match_tag_cmd); | |
718e3744 | 449 | route_map_install_set (&route_set_metric_cmd); |
a94434b6 | 450 | route_map_install_set (&route_set_ipv6_nexthop_local_cmd); |
451 | route_map_install_set (&route_set_tag_cmd); | |
718e3744 | 452 | } |