]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_offset.c
Merge branch 'stable/3.0' into tmp-3.0-master-merge
[mirror_frr.git] / ripngd / ripng_offset.c
CommitLineData
a94434b6 1/* RIPng offset-list
2 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
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
a94434b6 19 */
20
d62a17ae 21/* RIPng support by Vincent Jardin <vincent.jardin@6wind.com>
22 * Copyright (C) 2002 6WIND
23 */
a94434b6 24
25#include <zebra.h>
26
27#include "if.h"
28#include "prefix.h"
29#include "filter.h"
30#include "command.h"
31#include "linklist.h"
32#include "memory.h"
33
6ac29a51
PJ
34#include "ripngd/ripngd.h"
35
a94434b6 36#define RIPNG_OFFSET_LIST_IN 0
37#define RIPNG_OFFSET_LIST_OUT 1
38#define RIPNG_OFFSET_LIST_MAX 2
39
d62a17ae 40struct ripng_offset_list {
41 char *ifname;
42
43 struct {
44 char *alist_name;
45 /* struct access_list *alist; */
46 int metric;
47 } direct[RIPNG_OFFSET_LIST_MAX];
a94434b6 48};
49
50static struct list *ripng_offset_list_master;
51
d62a17ae 52static int strcmp_safe(const char *s1, const char *s2)
a94434b6 53{
d62a17ae 54 if (s1 == NULL && s2 == NULL)
55 return 0;
56 if (s1 == NULL)
57 return -1;
58 if (s2 == NULL)
59 return 1;
60 return strcmp(s1, s2);
a94434b6 61}
62
d62a17ae 63static struct ripng_offset_list *ripng_offset_list_new(void)
a94434b6 64{
d62a17ae 65 struct ripng_offset_list *new;
a94434b6 66
d62a17ae 67 new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
68 sizeof(struct ripng_offset_list));
69 return new;
a94434b6 70}
71
d62a17ae 72static void ripng_offset_list_free(struct ripng_offset_list *offset)
a94434b6 73{
d62a17ae 74 XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
a94434b6 75}
76
d62a17ae 77static struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
a94434b6 78{
d62a17ae 79 struct ripng_offset_list *offset;
80 struct listnode *node, *nnode;
a94434b6 81
d62a17ae 82 for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
83 if (strcmp_safe(offset->ifname, ifname) == 0)
84 return offset;
85 }
86 return NULL;
a94434b6 87}
88
d62a17ae 89static struct ripng_offset_list *ripng_offset_list_get(const char *ifname)
a94434b6 90{
d62a17ae 91 struct ripng_offset_list *offset;
92
93 offset = ripng_offset_list_lookup(ifname);
94 if (offset)
95 return offset;
96
97 offset = ripng_offset_list_new();
98 if (ifname)
99 offset->ifname = strdup(ifname);
100 listnode_add_sort(ripng_offset_list_master, offset);
101
102 return offset;
a94434b6 103}
104
d62a17ae 105static int ripng_offset_list_set(struct vty *vty, const char *alist,
106 const char *direct_str, const char *metric_str,
107 const char *ifname)
a94434b6 108{
d62a17ae 109 int direct;
110 int metric;
111 struct ripng_offset_list *offset;
112
113 /* Check direction. */
114 if (strncmp(direct_str, "i", 1) == 0)
115 direct = RIPNG_OFFSET_LIST_IN;
116 else if (strncmp(direct_str, "o", 1) == 0)
117 direct = RIPNG_OFFSET_LIST_OUT;
118 else {
119 vty_out(vty, "Invalid direction: %s\n", direct_str);
120 return CMD_WARNING_CONFIG_FAILED;
121 }
122
123 /* Check metric. */
124 metric = atoi(metric_str);
125 if (metric < 0 || metric > 16) {
126 vty_out(vty, "Invalid metric: %s\n", metric_str);
127 return CMD_WARNING_CONFIG_FAILED;
128 }
129
130 /* Get offset-list structure with interface name. */
131 offset = ripng_offset_list_get(ifname);
132
133 if (offset->direct[direct].alist_name)
134 free(offset->direct[direct].alist_name);
135 offset->direct[direct].alist_name = strdup(alist);
136 offset->direct[direct].metric = metric;
137
138 return CMD_SUCCESS;
a94434b6 139}
140
d62a17ae 141static int ripng_offset_list_unset(struct vty *vty, const char *alist,
142 const char *direct_str,
143 const char *metric_str, const char *ifname)
a94434b6 144{
d62a17ae 145 int direct;
146 int metric;
147 struct ripng_offset_list *offset;
148
149 /* Check direction. */
150 if (strncmp(direct_str, "i", 1) == 0)
151 direct = RIPNG_OFFSET_LIST_IN;
152 else if (strncmp(direct_str, "o", 1) == 0)
153 direct = RIPNG_OFFSET_LIST_OUT;
154 else {
155 vty_out(vty, "Invalid direction: %s\n", direct_str);
156 return CMD_WARNING_CONFIG_FAILED;
157 }
158
159 /* Check metric. */
160 metric = atoi(metric_str);
161 if (metric < 0 || metric > 16) {
162 vty_out(vty, "Invalid metric: %s\n", metric_str);
163 return CMD_WARNING_CONFIG_FAILED;
164 }
165
166 /* Get offset-list structure with interface name. */
167 offset = ripng_offset_list_lookup(ifname);
168
169 if (offset) {
170 if (offset->direct[direct].alist_name)
171 free(offset->direct[direct].alist_name);
172 offset->direct[direct].alist_name = NULL;
173
174 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
175 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name
176 == NULL) {
177 listnode_delete(ripng_offset_list_master, offset);
178 if (offset->ifname)
179 free(offset->ifname);
180 ripng_offset_list_free(offset);
181 }
182 } else {
183 vty_out(vty, "Can't find offset-list\n");
184 return CMD_WARNING_CONFIG_FAILED;
a94434b6 185 }
d62a17ae 186 return CMD_SUCCESS;
a94434b6 187}
188
189#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
190#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
191
192#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
193#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
194
195/* If metric is modifed return 1. */
d62a17ae 196int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
197 u_char *metric)
a94434b6 198{
d62a17ae 199 struct ripng_offset_list *offset;
200 struct access_list *alist;
201
202 /* Look up offset-list with interface name. */
203 offset = ripng_offset_list_lookup(ifp->name);
204 if (offset && OFFSET_LIST_IN_NAME(offset)) {
205 alist = access_list_lookup(AFI_IP6,
206 OFFSET_LIST_IN_NAME(offset));
207
208 if (alist
209 && access_list_apply(alist, (struct prefix *)p)
210 == FILTER_PERMIT) {
211 *metric += OFFSET_LIST_IN_METRIC(offset);
212 return 1;
213 }
214 return 0;
a94434b6 215 }
d62a17ae 216 /* Look up offset-list without interface name. */
217 offset = ripng_offset_list_lookup(NULL);
218 if (offset && OFFSET_LIST_IN_NAME(offset)) {
219 alist = access_list_lookup(AFI_IP6,
220 OFFSET_LIST_IN_NAME(offset));
221
222 if (alist
223 && access_list_apply(alist, (struct prefix *)p)
224 == FILTER_PERMIT) {
225 *metric += OFFSET_LIST_IN_METRIC(offset);
226 return 1;
227 }
228 return 0;
a94434b6 229 }
d62a17ae 230 return 0;
a94434b6 231}
232
233/* If metric is modifed return 1. */
d62a17ae 234int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
235 u_char *metric)
a94434b6 236{
d62a17ae 237 struct ripng_offset_list *offset;
238 struct access_list *alist;
239
240 /* Look up offset-list with interface name. */
241 offset = ripng_offset_list_lookup(ifp->name);
242 if (offset && OFFSET_LIST_OUT_NAME(offset)) {
243 alist = access_list_lookup(AFI_IP6,
244 OFFSET_LIST_OUT_NAME(offset));
245
246 if (alist
247 && access_list_apply(alist, (struct prefix *)p)
248 == FILTER_PERMIT) {
249 *metric += OFFSET_LIST_OUT_METRIC(offset);
250 return 1;
251 }
252 return 0;
a94434b6 253 }
d62a17ae 254
255 /* Look up offset-list without interface name. */
256 offset = ripng_offset_list_lookup(NULL);
257 if (offset && OFFSET_LIST_OUT_NAME(offset)) {
258 alist = access_list_lookup(AFI_IP6,
259 OFFSET_LIST_OUT_NAME(offset));
260
261 if (alist
262 && access_list_apply(alist, (struct prefix *)p)
263 == FILTER_PERMIT) {
264 *metric += OFFSET_LIST_OUT_METRIC(offset);
265 return 1;
266 }
267 return 0;
a94434b6 268 }
d62a17ae 269 return 0;
a94434b6 270}
271
272DEFUN (ripng_offset_list,
273 ripng_offset_list_cmd,
6147e2c6 274 "offset-list WORD <in|out> (0-16)",
a94434b6 275 "Modify RIPng metric\n"
276 "Access-list name\n"
277 "For incoming updates\n"
278 "For outgoing updates\n"
279 "Metric value\n")
280{
d62a17ae 281 int idx_word = 1;
282 int idx_in_out = 2;
283 int idx_number = 3;
284 return ripng_offset_list_set(vty, argv[idx_word]->arg,
285 argv[idx_in_out]->arg,
286 argv[idx_number]->arg, NULL);
a94434b6 287}
288
289DEFUN (ripng_offset_list_ifname,
290 ripng_offset_list_ifname_cmd,
6147e2c6 291 "offset-list WORD <in|out> (0-16) IFNAME",
a94434b6 292 "Modify RIPng metric\n"
293 "Access-list name\n"
294 "For incoming updates\n"
295 "For outgoing updates\n"
296 "Metric value\n"
297 "Interface to match\n")
298{
d62a17ae 299 int idx_word = 1;
300 int idx_in_out = 2;
301 int idx_number = 3;
302 int idx_ifname = 4;
303 return ripng_offset_list_set(
304 vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
305 argv[idx_number]->arg, argv[idx_ifname]->arg);
a94434b6 306}
307
308DEFUN (no_ripng_offset_list,
309 no_ripng_offset_list_cmd,
6147e2c6 310 "no offset-list WORD <in|out> (0-16)",
a94434b6 311 NO_STR
312 "Modify RIPng metric\n"
313 "Access-list name\n"
314 "For incoming updates\n"
315 "For outgoing updates\n"
316 "Metric value\n")
317{
d62a17ae 318 int idx_word = 2;
319 int idx_in_out = 3;
320 int idx_number = 4;
321 return ripng_offset_list_unset(vty, argv[idx_word]->arg,
322 argv[idx_in_out]->arg,
323 argv[idx_number]->arg, NULL);
a94434b6 324}
325
326DEFUN (no_ripng_offset_list_ifname,
327 no_ripng_offset_list_ifname_cmd,
6147e2c6 328 "no offset-list WORD <in|out> (0-16) IFNAME",
a94434b6 329 NO_STR
330 "Modify RIPng metric\n"
331 "Access-list name\n"
332 "For incoming updates\n"
333 "For outgoing updates\n"
334 "Metric value\n"
335 "Interface to match\n")
336{
d62a17ae 337 int idx_word = 2;
338 int idx_in_out = 3;
339 int idx_number = 4;
340 int idx_ifname = 5;
341 return ripng_offset_list_unset(
342 vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
343 argv[idx_number]->arg, argv[idx_ifname]->arg);
a94434b6 344}
345
d62a17ae 346static int offset_list_cmp(struct ripng_offset_list *o1,
347 struct ripng_offset_list *o2)
a94434b6 348{
d62a17ae 349 return strcmp_safe(o1->ifname, o2->ifname);
a94434b6 350}
351
d62a17ae 352static void offset_list_del(struct ripng_offset_list *offset)
a94434b6 353{
d62a17ae 354 if (OFFSET_LIST_IN_NAME(offset))
355 free(OFFSET_LIST_IN_NAME(offset));
356 if (OFFSET_LIST_OUT_NAME(offset))
357 free(OFFSET_LIST_OUT_NAME(offset));
358 if (offset->ifname)
359 free(offset->ifname);
360 ripng_offset_list_free(offset);
a94434b6 361}
362
d62a17ae 363void ripng_offset_init(void)
a94434b6 364{
d62a17ae 365 ripng_offset_list_master = list_new();
366 ripng_offset_list_master->cmp =
367 (int (*)(void *, void *))offset_list_cmp;
368 ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
369
370 install_element(RIPNG_NODE, &ripng_offset_list_cmd);
371 install_element(RIPNG_NODE, &ripng_offset_list_ifname_cmd);
372 install_element(RIPNG_NODE, &no_ripng_offset_list_cmd);
373 install_element(RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
a94434b6 374}
375
d62a17ae 376void ripng_offset_clean(void)
a94434b6 377{
d62a17ae 378 list_delete(ripng_offset_list_master);
a94434b6 379
d62a17ae 380 ripng_offset_list_master = list_new();
381 ripng_offset_list_master->cmp =
382 (int (*)(void *, void *))offset_list_cmp;
383 ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
a94434b6 384}
385
d62a17ae 386int config_write_ripng_offset_list(struct vty *vty)
a94434b6 387{
d62a17ae 388 struct listnode *node, *nnode;
389 struct ripng_offset_list *offset;
390
391 for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
392 if (!offset->ifname) {
393 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
394 vty_out(vty, " offset-list %s in %d\n",
395 offset->direct[RIPNG_OFFSET_LIST_IN]
396 .alist_name,
397 offset->direct[RIPNG_OFFSET_LIST_IN]
398 .metric);
399 if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
400 vty_out(vty, " offset-list %s out %d\n",
401 offset->direct[RIPNG_OFFSET_LIST_OUT]
402 .alist_name,
403 offset->direct[RIPNG_OFFSET_LIST_OUT]
404 .metric);
405 } else {
406 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
407 vty_out(vty, " offset-list %s in %d %s\n",
408 offset->direct[RIPNG_OFFSET_LIST_IN]
409 .alist_name,
410 offset->direct[RIPNG_OFFSET_LIST_IN]
411 .metric,
412 offset->ifname);
413 if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
414 vty_out(vty, " offset-list %s out %d %s\n",
415 offset->direct[RIPNG_OFFSET_LIST_OUT]
416 .alist_name,
417 offset->direct[RIPNG_OFFSET_LIST_OUT]
418 .metric,
419 offset->ifname);
420 }
a94434b6 421 }
a94434b6 422
d62a17ae 423 return 0;
a94434b6 424}