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