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 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
21 /* RIPng support by Vincent Jardin <vincent.jardin@6wind.com>
22 * Copyright (C) 2002 6WIND
34 #include "ripngd/ripngd.h"
36 #define RIPNG_OFFSET_LIST_IN 0
37 #define RIPNG_OFFSET_LIST_OUT 1
38 #define RIPNG_OFFSET_LIST_MAX 2
40 struct ripng_offset_list
47 /* struct access_list *alist; */
49 } direct
[RIPNG_OFFSET_LIST_MAX
];
52 static struct list
*ripng_offset_list_master
;
55 strcmp_safe (const char *s1
, const char *s2
)
57 if (s1
== NULL
&& s2
== NULL
)
63 return strcmp (s1
, s2
);
66 static struct ripng_offset_list
*
67 ripng_offset_list_new (void)
69 struct ripng_offset_list
*new;
71 new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST
, sizeof (struct ripng_offset_list
));
76 ripng_offset_list_free (struct ripng_offset_list
*offset
)
78 XFREE (MTYPE_RIPNG_OFFSET_LIST
, offset
);
81 static struct ripng_offset_list
*
82 ripng_offset_list_lookup (const char *ifname
)
84 struct ripng_offset_list
*offset
;
85 struct listnode
*node
, *nnode
;
87 for (ALL_LIST_ELEMENTS (ripng_offset_list_master
, node
, nnode
, offset
))
89 if (strcmp_safe (offset
->ifname
, ifname
) == 0)
95 static struct ripng_offset_list
*
96 ripng_offset_list_get (const char *ifname
)
98 struct ripng_offset_list
*offset
;
100 offset
= ripng_offset_list_lookup (ifname
);
104 offset
= ripng_offset_list_new ();
106 offset
->ifname
= strdup (ifname
);
107 listnode_add_sort (ripng_offset_list_master
, offset
);
113 ripng_offset_list_set (struct vty
*vty
, const char *alist
,
114 const char *direct_str
, const char *metric_str
,
119 struct ripng_offset_list
*offset
;
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
;
128 vty_out (vty
, "Invalid direction: %s%s", direct_str
, VTY_NEWLINE
);
133 metric
= atoi (metric_str
);
134 if (metric
< 0 || metric
> 16)
136 vty_out (vty
, "Invalid metric: %s%s", metric_str
, VTY_NEWLINE
);
140 /* Get offset-list structure with interface name. */
141 offset
= ripng_offset_list_get (ifname
);
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
;
152 ripng_offset_list_unset (struct vty
*vty
, const char *alist
,
153 const char *direct_str
, const char *metric_str
,
158 struct ripng_offset_list
*offset
;
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
;
167 vty_out (vty
, "Invalid direction: %s%s", direct_str
, VTY_NEWLINE
);
172 metric
= atoi (metric_str
);
173 if (metric
< 0 || metric
> 16)
175 vty_out (vty
, "Invalid metric: %s%s", metric_str
, VTY_NEWLINE
);
179 /* Get offset-list structure with interface name. */
180 offset
= ripng_offset_list_lookup (ifname
);
184 if (offset
->direct
[direct
].alist_name
)
185 free (offset
->direct
[direct
].alist_name
);
186 offset
->direct
[direct
].alist_name
= NULL
;
188 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
== NULL
&&
189 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
== NULL
)
191 listnode_delete (ripng_offset_list_master
, offset
);
193 free (offset
->ifname
);
194 ripng_offset_list_free (offset
);
199 vty_out (vty
, "Can't find offset-list%s", VTY_NEWLINE
);
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)
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)
211 /* If metric is modifed return 1. */
213 ripng_offset_list_apply_in (struct prefix_ipv6
*p
, struct interface
*ifp
,
216 struct ripng_offset_list
*offset
;
217 struct access_list
*alist
;
219 /* Look up offset-list with interface name. */
220 offset
= ripng_offset_list_lookup (ifp
->name
);
221 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
223 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_IN_NAME (offset
));
226 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
228 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
233 /* Look up offset-list without interface name. */
234 offset
= ripng_offset_list_lookup (NULL
);
235 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
237 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_IN_NAME (offset
));
240 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
242 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
250 /* If metric is modifed return 1. */
252 ripng_offset_list_apply_out (struct prefix_ipv6
*p
, struct interface
*ifp
,
255 struct ripng_offset_list
*offset
;
256 struct access_list
*alist
;
258 /* Look up offset-list with interface name. */
259 offset
= ripng_offset_list_lookup (ifp
->name
);
260 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
262 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_OUT_NAME (offset
));
265 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
267 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
273 /* Look up offset-list without interface name. */
274 offset
= ripng_offset_list_lookup (NULL
);
275 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
277 alist
= access_list_lookup (AFI_IP6
, OFFSET_LIST_OUT_NAME (offset
));
280 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
282 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
290 DEFUN (ripng_offset_list
,
291 ripng_offset_list_cmd
,
292 "offset-list WORD <in|out> (0-16)",
293 "Modify RIPng metric\n"
295 "For incoming updates\n"
296 "For outgoing updates\n"
302 return ripng_offset_list_set (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, NULL
);
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"
310 "For incoming updates\n"
311 "For outgoing updates\n"
313 "Interface to match\n")
319 return ripng_offset_list_set (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
322 DEFUN (no_ripng_offset_list
,
323 no_ripng_offset_list_cmd
,
324 "no offset-list WORD <in|out> (0-16)",
326 "Modify RIPng metric\n"
328 "For incoming updates\n"
329 "For outgoing updates\n"
335 return ripng_offset_list_unset (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, NULL
);
338 DEFUN (no_ripng_offset_list_ifname
,
339 no_ripng_offset_list_ifname_cmd
,
340 "no offset-list WORD <in|out> (0-16) IFNAME",
342 "Modify RIPng metric\n"
344 "For incoming updates\n"
345 "For outgoing updates\n"
347 "Interface to match\n")
353 return ripng_offset_list_unset (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
357 offset_list_cmp (struct ripng_offset_list
*o1
, struct ripng_offset_list
*o2
)
359 return strcmp_safe (o1
->ifname
, o2
->ifname
);
363 offset_list_del (struct ripng_offset_list
*offset
)
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
));
370 free (offset
->ifname
);
371 ripng_offset_list_free (offset
);
375 ripng_offset_init (void)
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
;
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
);
388 ripng_offset_clean (void)
390 list_delete (ripng_offset_list_master
);
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
;
398 config_write_ripng_offset_list (struct vty
*vty
)
400 struct listnode
*node
, *nnode
;
401 struct ripng_offset_list
*offset
;
403 for (ALL_LIST_ELEMENTS (ripng_offset_list_master
, node
, nnode
, offset
))
405 if (! offset
->ifname
)
407 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
408 vty_out (vty
, " offset-list %s in %d%s",
409 offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
,
410 offset
->direct
[RIPNG_OFFSET_LIST_IN
].metric
,
412 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
413 vty_out (vty
, " offset-list %s out %d%s",
414 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
,
415 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].metric
,
420 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
421 vty_out (vty
, " offset-list %s in %d %s%s",
422 offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
,
423 offset
->direct
[RIPNG_OFFSET_LIST_IN
].metric
,
424 offset
->ifname
, VTY_NEWLINE
);
425 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
426 vty_out (vty
, " offset-list %s out %d %s%s",
427 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
,
428 offset
->direct
[RIPNG_OFFSET_LIST_OUT
].metric
,
429 offset
->ifname
, VTY_NEWLINE
);