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