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