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