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
{
45 /* struct access_list *alist; */
47 } direct
[RIPNG_OFFSET_LIST_MAX
];
50 static struct list
*ripng_offset_list_master
;
52 static int strcmp_safe(const char *s1
, const char *s2
)
54 if (s1
== NULL
&& s2
== NULL
)
60 return strcmp(s1
, s2
);
63 static struct ripng_offset_list
*ripng_offset_list_new(void)
65 struct ripng_offset_list
*new;
67 new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST
,
68 sizeof(struct ripng_offset_list
));
72 static void ripng_offset_list_free(struct ripng_offset_list
*offset
)
74 XFREE(MTYPE_RIPNG_OFFSET_LIST
, offset
);
77 static struct ripng_offset_list
*ripng_offset_list_lookup(const char *ifname
)
79 struct ripng_offset_list
*offset
;
80 struct listnode
*node
, *nnode
;
82 for (ALL_LIST_ELEMENTS(ripng_offset_list_master
, node
, nnode
, offset
)) {
83 if (strcmp_safe(offset
->ifname
, ifname
) == 0)
89 static struct ripng_offset_list
*ripng_offset_list_get(const char *ifname
)
91 struct ripng_offset_list
*offset
;
93 offset
= ripng_offset_list_lookup(ifname
);
97 offset
= ripng_offset_list_new();
99 offset
->ifname
= strdup(ifname
);
100 listnode_add_sort(ripng_offset_list_master
, offset
);
105 static int ripng_offset_list_set(struct vty
*vty
, const char *alist
,
106 const char *direct_str
, const char *metric_str
,
111 struct ripng_offset_list
*offset
;
113 /* Check direction. */
114 if (strncmp(direct_str
, "i", 1) == 0)
115 direct
= RIPNG_OFFSET_LIST_IN
;
116 else if (strncmp(direct_str
, "o", 1) == 0)
117 direct
= RIPNG_OFFSET_LIST_OUT
;
119 vty_out(vty
, "Invalid direction: %s\n", direct_str
);
120 return CMD_WARNING_CONFIG_FAILED
;
124 metric
= atoi(metric_str
);
125 if (metric
< 0 || metric
> 16) {
126 vty_out(vty
, "Invalid metric: %s\n", metric_str
);
127 return CMD_WARNING_CONFIG_FAILED
;
130 /* Get offset-list structure with interface name. */
131 offset
= ripng_offset_list_get(ifname
);
133 if (offset
->direct
[direct
].alist_name
)
134 free(offset
->direct
[direct
].alist_name
);
135 offset
->direct
[direct
].alist_name
= strdup(alist
);
136 offset
->direct
[direct
].metric
= metric
;
141 static int ripng_offset_list_unset(struct vty
*vty
, const char *alist
,
142 const char *direct_str
,
143 const char *metric_str
, const char *ifname
)
147 struct ripng_offset_list
*offset
;
149 /* Check direction. */
150 if (strncmp(direct_str
, "i", 1) == 0)
151 direct
= RIPNG_OFFSET_LIST_IN
;
152 else if (strncmp(direct_str
, "o", 1) == 0)
153 direct
= RIPNG_OFFSET_LIST_OUT
;
155 vty_out(vty
, "Invalid direction: %s\n", direct_str
);
156 return CMD_WARNING_CONFIG_FAILED
;
160 metric
= atoi(metric_str
);
161 if (metric
< 0 || metric
> 16) {
162 vty_out(vty
, "Invalid metric: %s\n", metric_str
);
163 return CMD_WARNING_CONFIG_FAILED
;
166 /* Get offset-list structure with interface name. */
167 offset
= ripng_offset_list_lookup(ifname
);
170 if (offset
->direct
[direct
].alist_name
)
171 free(offset
->direct
[direct
].alist_name
);
172 offset
->direct
[direct
].alist_name
= NULL
;
174 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
== NULL
175 && offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
177 listnode_delete(ripng_offset_list_master
, offset
);
179 free(offset
->ifname
);
180 ripng_offset_list_free(offset
);
183 vty_out(vty
, "Can't find offset-list\n");
184 return CMD_WARNING_CONFIG_FAILED
;
189 #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
190 #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
192 #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
193 #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
195 /* If metric is modifed return 1. */
196 int ripng_offset_list_apply_in(struct prefix_ipv6
*p
, struct interface
*ifp
,
199 struct ripng_offset_list
*offset
;
200 struct access_list
*alist
;
202 /* Look up offset-list with interface name. */
203 offset
= ripng_offset_list_lookup(ifp
->name
);
204 if (offset
&& OFFSET_LIST_IN_NAME(offset
)) {
205 alist
= access_list_lookup(AFI_IP6
,
206 OFFSET_LIST_IN_NAME(offset
));
209 && access_list_apply(alist
, (struct prefix
*)p
)
211 *metric
+= OFFSET_LIST_IN_METRIC(offset
);
216 /* Look up offset-list without interface name. */
217 offset
= ripng_offset_list_lookup(NULL
);
218 if (offset
&& OFFSET_LIST_IN_NAME(offset
)) {
219 alist
= access_list_lookup(AFI_IP6
,
220 OFFSET_LIST_IN_NAME(offset
));
223 && access_list_apply(alist
, (struct prefix
*)p
)
225 *metric
+= OFFSET_LIST_IN_METRIC(offset
);
233 /* If metric is modifed return 1. */
234 int ripng_offset_list_apply_out(struct prefix_ipv6
*p
, struct interface
*ifp
,
237 struct ripng_offset_list
*offset
;
238 struct access_list
*alist
;
240 /* Look up offset-list with interface name. */
241 offset
= ripng_offset_list_lookup(ifp
->name
);
242 if (offset
&& OFFSET_LIST_OUT_NAME(offset
)) {
243 alist
= access_list_lookup(AFI_IP6
,
244 OFFSET_LIST_OUT_NAME(offset
));
247 && access_list_apply(alist
, (struct prefix
*)p
)
249 *metric
+= OFFSET_LIST_OUT_METRIC(offset
);
255 /* Look up offset-list without interface name. */
256 offset
= ripng_offset_list_lookup(NULL
);
257 if (offset
&& OFFSET_LIST_OUT_NAME(offset
)) {
258 alist
= access_list_lookup(AFI_IP6
,
259 OFFSET_LIST_OUT_NAME(offset
));
262 && access_list_apply(alist
, (struct prefix
*)p
)
264 *metric
+= OFFSET_LIST_OUT_METRIC(offset
);
272 DEFUN (ripng_offset_list
,
273 ripng_offset_list_cmd
,
274 "offset-list WORD <in|out> (0-16)",
275 "Modify RIPng metric\n"
277 "For incoming updates\n"
278 "For outgoing updates\n"
284 return ripng_offset_list_set(vty
, argv
[idx_word
]->arg
,
285 argv
[idx_in_out
]->arg
,
286 argv
[idx_number
]->arg
, NULL
);
289 DEFUN (ripng_offset_list_ifname
,
290 ripng_offset_list_ifname_cmd
,
291 "offset-list WORD <in|out> (0-16) IFNAME",
292 "Modify RIPng metric\n"
294 "For incoming updates\n"
295 "For outgoing updates\n"
297 "Interface to match\n")
303 return ripng_offset_list_set(
304 vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
,
305 argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
308 DEFUN (no_ripng_offset_list
,
309 no_ripng_offset_list_cmd
,
310 "no offset-list WORD <in|out> (0-16)",
312 "Modify RIPng metric\n"
314 "For incoming updates\n"
315 "For outgoing updates\n"
321 return ripng_offset_list_unset(vty
, argv
[idx_word
]->arg
,
322 argv
[idx_in_out
]->arg
,
323 argv
[idx_number
]->arg
, NULL
);
326 DEFUN (no_ripng_offset_list_ifname
,
327 no_ripng_offset_list_ifname_cmd
,
328 "no offset-list WORD <in|out> (0-16) IFNAME",
330 "Modify RIPng metric\n"
332 "For incoming updates\n"
333 "For outgoing updates\n"
335 "Interface to match\n")
341 return ripng_offset_list_unset(
342 vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
,
343 argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
346 static int offset_list_cmp(struct ripng_offset_list
*o1
,
347 struct ripng_offset_list
*o2
)
349 return strcmp_safe(o1
->ifname
, o2
->ifname
);
352 static void offset_list_del(struct ripng_offset_list
*offset
)
354 if (OFFSET_LIST_IN_NAME(offset
))
355 free(OFFSET_LIST_IN_NAME(offset
));
356 if (OFFSET_LIST_OUT_NAME(offset
))
357 free(OFFSET_LIST_OUT_NAME(offset
));
359 free(offset
->ifname
);
360 ripng_offset_list_free(offset
);
363 void ripng_offset_init(void)
365 ripng_offset_list_master
= list_new();
366 ripng_offset_list_master
->cmp
=
367 (int (*)(void *, void *))offset_list_cmp
;
368 ripng_offset_list_master
->del
= (void (*)(void *))offset_list_del
;
370 install_element(RIPNG_NODE
, &ripng_offset_list_cmd
);
371 install_element(RIPNG_NODE
, &ripng_offset_list_ifname_cmd
);
372 install_element(RIPNG_NODE
, &no_ripng_offset_list_cmd
);
373 install_element(RIPNG_NODE
, &no_ripng_offset_list_ifname_cmd
);
376 void ripng_offset_clean(void)
378 list_delete_and_null(&ripng_offset_list_master
);
380 ripng_offset_list_master
= list_new();
381 ripng_offset_list_master
->cmp
=
382 (int (*)(void *, void *))offset_list_cmp
;
383 ripng_offset_list_master
->del
= (void (*)(void *))offset_list_del
;
386 int config_write_ripng_offset_list(struct vty
*vty
)
388 struct listnode
*node
, *nnode
;
389 struct ripng_offset_list
*offset
;
391 for (ALL_LIST_ELEMENTS(ripng_offset_list_master
, node
, nnode
, offset
)) {
392 if (!offset
->ifname
) {
393 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
394 vty_out(vty
, " offset-list %s in %d\n",
395 offset
->direct
[RIPNG_OFFSET_LIST_IN
]
397 offset
->direct
[RIPNG_OFFSET_LIST_IN
]
399 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
400 vty_out(vty
, " offset-list %s out %d\n",
401 offset
->direct
[RIPNG_OFFSET_LIST_OUT
]
403 offset
->direct
[RIPNG_OFFSET_LIST_OUT
]
406 if (offset
->direct
[RIPNG_OFFSET_LIST_IN
].alist_name
)
407 vty_out(vty
, " offset-list %s in %d %s\n",
408 offset
->direct
[RIPNG_OFFSET_LIST_IN
]
410 offset
->direct
[RIPNG_OFFSET_LIST_IN
]
413 if (offset
->direct
[RIPNG_OFFSET_LIST_OUT
].alist_name
)
414 vty_out(vty
, " offset-list %s out %d %s\n",
415 offset
->direct
[RIPNG_OFFSET_LIST_OUT
]
417 offset
->direct
[RIPNG_OFFSET_LIST_OUT
]