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 #define RIPNG_OFFSET_LIST_IN 0
36 #define RIPNG_OFFSET_LIST_OUT 1
37 #define RIPNG_OFFSET_LIST_MAX 2
39 struct ripng_offset_list
46 /* struct access_list *alist; */
48 } direct
[RIPNG_OFFSET_LIST_MAX
];
51 static struct list
*ripng_offset_list_master
;
54 strcmp_safe (const char *s1
, const char *s2
)
56 if (s1
== NULL
&& s2
== NULL
)
62 return strcmp (s1
, s2
);
65 struct ripng_offset_list
*
66 ripng_offset_list_new ()
68 struct ripng_offset_list
*new;
70 new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST
, sizeof (struct ripng_offset_list
));
75 ripng_offset_list_free (struct ripng_offset_list
*offset
)
77 XFREE (MTYPE_RIPNG_OFFSET_LIST
, offset
);
80 struct ripng_offset_list
*
81 ripng_offset_list_lookup (const char *ifname
)
83 struct ripng_offset_list
*offset
;
84 struct listnode
*node
, *nnode
;
86 for (ALL_LIST_ELEMENTS (ripng_offset_list_master
, node
, nnode
, offset
))
88 if (strcmp_safe (offset
->ifname
, ifname
) == 0)
94 struct ripng_offset_list
*
95 ripng_offset_list_get (const char *ifname
)
97 struct ripng_offset_list
*offset
;
99 offset
= ripng_offset_list_lookup (ifname
);
103 offset
= ripng_offset_list_new ();
105 offset
->ifname
= strdup (ifname
);
106 listnode_add_sort (ripng_offset_list_master
, offset
);
112 ripng_offset_list_set (struct vty
*vty
, const char *alist
,
113 const char *direct_str
, const char *metric_str
,
118 struct ripng_offset_list
*offset
;
120 /* Check direction. */
121 if (strncmp (direct_str
, "i", 1) == 0)
122 direct
= RIPNG_OFFSET_LIST_IN
;
123 else if (strncmp (direct_str
, "o", 1) == 0)
124 direct
= RIPNG_OFFSET_LIST_OUT
;
127 vty_out (vty
, "Invalid direction: %s%s", direct_str
, VTY_NEWLINE
);
132 metric
= atoi (metric_str
);
133 if (metric
< 0 || metric
> 16)
135 vty_out (vty
, "Invalid metric: %s%s", metric_str
, VTY_NEWLINE
);
139 /* Get offset-list structure with interface name. */
140 offset
= ripng_offset_list_get (ifname
);
142 if (offset
->direct
[direct
].alist_name
)
143 free (offset
->direct
[direct
].alist_name
);
144 offset
->direct
[direct
].alist_name
= strdup (alist
);
145 offset
->direct
[direct
].metric
= metric
;
151 ripng_offset_list_unset (struct vty
*vty
, const char *alist
,
152 const char *direct_str
, const char *metric_str
,
157 struct ripng_offset_list
*offset
;
159 /* Check direction. */
160 if (strncmp (direct_str
, "i", 1) == 0)
161 direct
= RIPNG_OFFSET_LIST_IN
;
162 else if (strncmp (direct_str
, "o", 1) == 0)
163 direct
= RIPNG_OFFSET_LIST_OUT
;
166 vty_out (vty
, "Invalid direction: %s%s", direct_str
, VTY_NEWLINE
);
171 metric
= atoi (metric_str
);
172 if (metric
< 0 || metric
> 16)
174 vty_out (vty
, "Invalid metric: %s%s", metric_str
, VTY_NEWLINE
);
178 /* Get offset-list structure with interface name. */
179 offset
= ripng_offset_list_lookup (ifname
);
183 if (offset
->direct
[direct
].alist_name
)
184 free (offset
->direct
[direct
].alist_name
);
185 offset
->direct
[direct
].alist_name
= NULL
;
187 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
== NULL
&&
188 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
== NULL
)
190 listnode_delete (ripng_offset_list_master
, offset
);
192 free (offset
->ifname
);
193 ripng_offset_list_free (offset
);
198 vty_out (vty
, "Can't find offset-list%s", VTY_NEWLINE
);
204 #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
205 #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
207 #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
208 #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
210 /* If metric is modifed return 1. */
212 ripng_offset_list_apply_in (struct prefix_ipv6
*p
, struct interface
*ifp
,
215 struct ripng_offset_list
*offset
;
216 struct access_list
*alist
;
218 /* Look up offset-list with interface name. */
219 offset
= ripng_offset_list_lookup (ifp
->name
);
220 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
222 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_IN_NAME (offset
));
225 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
227 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
232 /* Look up offset-list without interface name. */
233 offset
= ripng_offset_list_lookup (NULL
);
234 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
236 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_IN_NAME (offset
));
239 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
241 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
249 /* If metric is modifed return 1. */
251 ripng_offset_list_apply_out (struct prefix_ipv6
*p
, struct interface
*ifp
,
254 struct ripng_offset_list
*offset
;
255 struct access_list
*alist
;
257 /* Look up offset-list with interface name. */
258 offset
= ripng_offset_list_lookup (ifp
->name
);
259 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
261 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_OUT_NAME (offset
));
264 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
266 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
272 /* Look up offset-list without interface name. */
273 offset
= ripng_offset_list_lookup (NULL
);
274 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
276 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_OUT_NAME (offset
));
279 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
281 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
289 DEFUN (ripng_offset_list
,
290 ripng_offset_list_cmd
,
291 "offset-list WORD (in|out) <0-16>",
292 "Modify RIPng metric\n"
294 "For incoming updates\n"
295 "For outgoing updates\n"
298 return ripng_offset_list_set (vty
, argv
[0], argv
[1], argv
[2], NULL
);
301 DEFUN (ripng_offset_list_ifname
,
302 ripng_offset_list_ifname_cmd
,
303 "offset-list WORD (in|out) <0-16> IFNAME",
304 "Modify RIPng metric\n"
306 "For incoming updates\n"
307 "For outgoing updates\n"
309 "Interface to match\n")
311 return ripng_offset_list_set (vty
, argv
[0], argv
[1], argv
[2], argv
[3]);
314 DEFUN (no_ripng_offset_list
,
315 no_ripng_offset_list_cmd
,
316 "no offset-list WORD (in|out) <0-16>",
318 "Modify RIPng metric\n"
320 "For incoming updates\n"
321 "For outgoing updates\n"
324 return ripng_offset_list_unset (vty
, argv
[0], argv
[1], argv
[2], NULL
);
327 DEFUN (no_ripng_offset_list_ifname
,
328 no_ripng_offset_list_ifname_cmd
,
329 "no offset-list WORD (in|out) <0-16> IFNAME",
331 "Modify RIPng metric\n"
333 "For incoming updates\n"
334 "For outgoing updates\n"
336 "Interface to match\n")
338 return ripng_offset_list_unset (vty
, argv
[0], argv
[1], argv
[2], argv
[3]);
342 offset_list_cmp (struct ripng_offset_list
*o1
, struct ripng_offset_list
*o2
)
344 return strcmp_safe (o1
->ifname
, o2
->ifname
);
348 offset_list_del (struct ripng_offset_list
*offset
)
350 if (OFFSET_LIST_IN_NAME (offset
))
351 free (OFFSET_LIST_IN_NAME (offset
));
352 if (OFFSET_LIST_OUT_NAME (offset
))
353 free (OFFSET_LIST_OUT_NAME (offset
));
355 free (offset
->ifname
);
356 ripng_offset_list_free (offset
);
362 ripng_offset_list_master
= list_new ();
363 ripng_offset_list_master
->cmp
= (int (*)(void *, void *)) offset_list_cmp
;
364 ripng_offset_list_master
->del
= (void (*)(void *)) offset_list_del
;
366 install_element (RIPNG_NODE
, &ripng_offset_list_cmd
);
367 install_element (RIPNG_NODE
, &ripng_offset_list_ifname_cmd
);
368 install_element (RIPNG_NODE
, &no_ripng_offset_list_cmd
);
369 install_element (RIPNG_NODE
, &no_ripng_offset_list_ifname_cmd
);
373 ripng_offset_clean ()
375 list_delete (ripng_offset_list_master
);
377 ripng_offset_list_master
= list_new ();
378 ripng_offset_list_master
->cmp
= (int (*)(void *, void *)) offset_list_cmp
;
379 ripng_offset_list_master
->del
= (void (*)(void *)) offset_list_del
;
383 config_write_ripng_offset_list (struct vty
*vty
)
385 struct listnode
*node
, *nnode
;
386 struct ripng_offset_list
*offset
;
388 for (ALL_LIST_ELEMENTS (ripng_offset_list_master
, node
, nnode
, offset
))
390 if (! offset
->ifname
)
392 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
393 vty_out (vty
, " offset-list %s in %d%s",
394 offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
,
395 offset
->direct
[RIPNG_OFFSET_LIST_IN
].metric
,
397 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
398 vty_out (vty
, " offset-list %s out %d%s",
399 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
,
400 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].metric
,
405 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
406 vty_out (vty
, " offset-list %s in %d %s%s",
407 offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
,
408 offset
->direct
[RIPNG_OFFSET_LIST_IN
].metric
,
409 offset
->ifname
, VTY_NEWLINE
);
410 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
411 vty_out (vty
, " offset-list %s out %d %s%s",
412 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
,
413 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].metric
,
414 offset
->ifname
, VTY_NEWLINE
);