2 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
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
22 /* RIPng support by Vincent Jardin <vincent.jardin@6wind.com>
23 * Copyright (C) 2002 6WIND
35 #include "ripngd/ripngd.h"
37 #define RIPNG_OFFSET_LIST_IN 0
38 #define RIPNG_OFFSET_LIST_OUT 1
39 #define RIPNG_OFFSET_LIST_MAX 2
41 struct ripng_offset_list
48 /* struct access_list *alist; */
50 } direct[RIPNG_OFFSET_LIST_MAX];
53 static struct list *ripng_offset_list_master;
56 strcmp_safe (const char *s1, const char *s2)
58 if (s1 == NULL && s2 == NULL)
64 return strcmp (s1, s2);
67 static struct ripng_offset_list *
68 ripng_offset_list_new ()
70 struct ripng_offset_list *new;
72 new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST, sizeof (struct ripng_offset_list));
77 ripng_offset_list_free (struct ripng_offset_list *offset)
79 XFREE (MTYPE_RIPNG_OFFSET_LIST, offset);
82 static struct ripng_offset_list *
83 ripng_offset_list_lookup (const char *ifname)
85 struct ripng_offset_list *offset;
86 struct listnode *node, *nnode;
88 for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset))
90 if (strcmp_safe (offset->ifname, ifname) == 0)
96 static struct ripng_offset_list *
97 ripng_offset_list_get (const char *ifname)
99 struct ripng_offset_list *offset;
101 offset = ripng_offset_list_lookup (ifname);
105 offset = ripng_offset_list_new ();
107 offset->ifname = strdup (ifname);
108 listnode_add_sort (ripng_offset_list_master, offset);
114 ripng_offset_list_set (struct vty *vty, const char *alist,
115 const char *direct_str, const char *metric_str,
120 struct ripng_offset_list *offset;
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;
129 vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
134 metric = atoi (metric_str);
135 if (metric < 0 || metric > 16)
137 vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
141 /* Get offset-list structure with interface name. */
142 offset = ripng_offset_list_get (ifname);
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;
153 ripng_offset_list_unset (struct vty *vty, const char *alist,
154 const char *direct_str, const char *metric_str,
159 struct ripng_offset_list *offset;
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;
168 vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
173 metric = atoi (metric_str);
174 if (metric < 0 || metric > 16)
176 vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
180 /* Get offset-list structure with interface name. */
181 offset = ripng_offset_list_lookup (ifname);
185 if (offset->direct[direct].alist_name)
186 free (offset->direct[direct].alist_name);
187 offset->direct[direct].alist_name = NULL;
189 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL &&
190 offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
192 listnode_delete (ripng_offset_list_master, offset);
194 free (offset->ifname);
195 ripng_offset_list_free (offset);
200 vty_out (vty, "Can't find offset-list%s", VTY_NEWLINE);
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)
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)
212 /* If metric is modifed return 1. */
214 ripng_offset_list_apply_in (struct prefix_ipv6 *p, struct interface *ifp,
217 struct ripng_offset_list *offset;
218 struct access_list *alist;
220 /* Look up offset-list with interface name. */
221 offset = ripng_offset_list_lookup (ifp->name);
222 if (offset && OFFSET_LIST_IN_NAME (offset))
224 alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
227 && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
229 *metric += OFFSET_LIST_IN_METRIC (offset);
234 /* Look up offset-list without interface name. */
235 offset = ripng_offset_list_lookup (NULL);
236 if (offset && OFFSET_LIST_IN_NAME (offset))
238 alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
241 && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
243 *metric += OFFSET_LIST_IN_METRIC (offset);
251 /* If metric is modifed return 1. */
253 ripng_offset_list_apply_out (struct prefix_ipv6 *p, struct interface *ifp,
256 struct ripng_offset_list *offset;
257 struct access_list *alist;
259 /* Look up offset-list with interface name. */
260 offset = ripng_offset_list_lookup (ifp->name);
261 if (offset && OFFSET_LIST_OUT_NAME (offset))
263 alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
266 && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
268 *metric += OFFSET_LIST_OUT_METRIC (offset);
274 /* Look up offset-list without interface name. */
275 offset = ripng_offset_list_lookup (NULL);
276 if (offset && OFFSET_LIST_OUT_NAME (offset))
278 alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
281 && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
283 *metric += OFFSET_LIST_OUT_METRIC (offset);
291 DEFUN (ripng_offset_list,
292 ripng_offset_list_cmd,
293 "offset-list WORD (in|out) <0-16>",
294 "Modify RIPng metric\n"
296 "For incoming updates\n"
297 "For outgoing updates\n"
300 return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], NULL);
303 DEFUN (ripng_offset_list_ifname,
304 ripng_offset_list_ifname_cmd,
305 "offset-list WORD (in|out) <0-16> IFNAME",
306 "Modify RIPng metric\n"
308 "For incoming updates\n"
309 "For outgoing updates\n"
311 "Interface to match\n")
313 return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], argv[3]);
316 DEFUN (no_ripng_offset_list,
317 no_ripng_offset_list_cmd,
318 "no offset-list WORD (in|out) <0-16>",
320 "Modify RIPng metric\n"
322 "For incoming updates\n"
323 "For outgoing updates\n"
326 return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], NULL);
329 DEFUN (no_ripng_offset_list_ifname,
330 no_ripng_offset_list_ifname_cmd,
331 "no offset-list WORD (in|out) <0-16> IFNAME",
333 "Modify RIPng metric\n"
335 "For incoming updates\n"
336 "For outgoing updates\n"
338 "Interface to match\n")
340 return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], argv[3]);
344 offset_list_cmp (struct ripng_offset_list *o1, struct ripng_offset_list *o2)
346 return strcmp_safe (o1->ifname, o2->ifname);
350 offset_list_del (struct ripng_offset_list *offset)
352 if (OFFSET_LIST_IN_NAME (offset))
353 free (OFFSET_LIST_IN_NAME (offset));
354 if (OFFSET_LIST_OUT_NAME (offset))
355 free (OFFSET_LIST_OUT_NAME (offset));
357 free (offset->ifname);
358 ripng_offset_list_free (offset);
362 ripng_offset_init (void)
364 ripng_offset_list_master = list_new ();
365 ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
366 ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
368 install_element (RIPNG_NODE, &ripng_offset_list_cmd);
369 install_element (RIPNG_NODE, &ripng_offset_list_ifname_cmd);
370 install_element (RIPNG_NODE, &no_ripng_offset_list_cmd);
371 install_element (RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
375 ripng_offset_clean (void)
377 list_delete (ripng_offset_list_master);
379 ripng_offset_list_master = list_new ();
380 ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
381 ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
385 config_write_ripng_offset_list (struct vty *vty)
387 struct listnode *node, *nnode;
388 struct ripng_offset_list *offset;
390 for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset))
392 if (! offset->ifname)
394 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
395 vty_out (vty, " offset-list %s in %d%s",
396 offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
397 offset->direct[RIPNG_OFFSET_LIST_IN].metric,
399 if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
400 vty_out (vty, " offset-list %s out %d%s",
401 offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
402 offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
407 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
408 vty_out (vty, " offset-list %s in %d %s%s",
409 offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
410 offset->direct[RIPNG_OFFSET_LIST_IN].metric,
411 offset->ifname, VTY_NEWLINE);
412 if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
413 vty_out (vty, " offset-list %s out %d %s%s",
414 offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
415 offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
416 offset->ifname, VTY_NEWLINE);