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
30 #include "ripd/ripd.h"
32 #define RIP_OFFSET_LIST_IN 0
33 #define RIP_OFFSET_LIST_OUT 1
34 #define RIP_OFFSET_LIST_MAX 2
36 struct rip_offset_list
43 /* struct access_list *alist; */
45 } direct
[RIP_OFFSET_LIST_MAX
];
48 static struct list
*rip_offset_list_master
;
51 strcmp_safe (const char *s1
, const char *s2
)
53 if (s1
== NULL
&& s2
== NULL
)
59 return strcmp (s1
, s2
);
62 static struct rip_offset_list
*
63 rip_offset_list_new (void)
65 return XCALLOC (MTYPE_RIP_OFFSET_LIST
, sizeof (struct rip_offset_list
));
69 rip_offset_list_free (struct rip_offset_list
*offset
)
71 XFREE (MTYPE_RIP_OFFSET_LIST
, offset
);
74 static struct rip_offset_list
*
75 rip_offset_list_lookup (const char *ifname
)
77 struct rip_offset_list
*offset
;
78 struct listnode
*node
, *nnode
;
80 for (ALL_LIST_ELEMENTS (rip_offset_list_master
, node
, nnode
, offset
))
82 if (strcmp_safe (offset
->ifname
, ifname
) == 0)
88 static struct rip_offset_list
*
89 rip_offset_list_get (const char *ifname
)
91 struct rip_offset_list
*offset
;
93 offset
= rip_offset_list_lookup (ifname
);
97 offset
= rip_offset_list_new ();
99 offset
->ifname
= strdup (ifname
);
100 listnode_add_sort (rip_offset_list_master
, offset
);
106 rip_offset_list_set (struct vty
*vty
, const char *alist
, const char *direct_str
,
107 const char *metric_str
, const char *ifname
)
111 struct rip_offset_list
*offset
;
113 /* Check direction. */
114 if (strncmp (direct_str
, "i", 1) == 0)
115 direct
= RIP_OFFSET_LIST_IN
;
116 else if (strncmp (direct_str
, "o", 1) == 0)
117 direct
= RIP_OFFSET_LIST_OUT
;
120 vty_outln (vty
, "Invalid direction: %s", direct_str
);
125 metric
= atoi (metric_str
);
126 if (metric
< 0 || metric
> 16)
128 vty_outln (vty
, "Invalid metric: %s", metric_str
);
132 /* Get offset-list structure with interface name. */
133 offset
= rip_offset_list_get (ifname
);
135 if (offset
->direct
[direct
].alist_name
)
136 free (offset
->direct
[direct
].alist_name
);
137 offset
->direct
[direct
].alist_name
= strdup (alist
);
138 offset
->direct
[direct
].metric
= metric
;
144 rip_offset_list_unset (struct vty
*vty
, const char *alist
,
145 const char *direct_str
, const char *metric_str
,
150 struct rip_offset_list
*offset
;
152 /* Check direction. */
153 if (strncmp (direct_str
, "i", 1) == 0)
154 direct
= RIP_OFFSET_LIST_IN
;
155 else if (strncmp (direct_str
, "o", 1) == 0)
156 direct
= RIP_OFFSET_LIST_OUT
;
159 vty_outln (vty
, "Invalid direction: %s", direct_str
);
164 metric
= atoi (metric_str
);
165 if (metric
< 0 || metric
> 16)
167 vty_outln (vty
, "Invalid metric: %s", metric_str
);
171 /* Get offset-list structure with interface name. */
172 offset
= rip_offset_list_lookup (ifname
);
176 if (offset
->direct
[direct
].alist_name
)
177 free (offset
->direct
[direct
].alist_name
);
178 offset
->direct
[direct
].alist_name
= NULL
;
180 if (offset
->direct
[RIP_OFFSET_LIST_IN
].alist_name
== NULL
&&
181 offset
->direct
[RIP_OFFSET_LIST_OUT
].alist_name
== NULL
)
183 listnode_delete (rip_offset_list_master
, offset
);
185 free (offset
->ifname
);
186 rip_offset_list_free (offset
);
191 vty_outln (vty
, "Can't find offset-list");
197 #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
198 #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric)
200 #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
201 #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
203 /* If metric is modifed return 1. */
205 rip_offset_list_apply_in (struct prefix_ipv4
*p
, struct interface
*ifp
,
208 struct rip_offset_list
*offset
;
209 struct access_list
*alist
;
211 /* Look up offset-list with interface name. */
212 offset
= rip_offset_list_lookup (ifp
->name
);
213 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
215 alist
= access_list_lookup (AFI_IP
, OFFSET_LIST_IN_NAME (offset
));
218 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
220 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
225 /* Look up offset-list without interface name. */
226 offset
= rip_offset_list_lookup (NULL
);
227 if (offset
&& OFFSET_LIST_IN_NAME (offset
))
229 alist
= access_list_lookup (AFI_IP
, OFFSET_LIST_IN_NAME (offset
));
232 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
234 *metric
+= OFFSET_LIST_IN_METRIC (offset
);
242 /* If metric is modifed return 1. */
244 rip_offset_list_apply_out (struct prefix_ipv4
*p
, struct interface
*ifp
,
247 struct rip_offset_list
*offset
;
248 struct access_list
*alist
;
250 /* Look up offset-list with interface name. */
251 offset
= rip_offset_list_lookup (ifp
->name
);
252 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
254 alist
= access_list_lookup (AFI_IP
, OFFSET_LIST_OUT_NAME (offset
));
257 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
259 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
265 /* Look up offset-list without interface name. */
266 offset
= rip_offset_list_lookup (NULL
);
267 if (offset
&& OFFSET_LIST_OUT_NAME (offset
))
269 alist
= access_list_lookup (AFI_IP
, OFFSET_LIST_OUT_NAME (offset
));
272 && access_list_apply (alist
, (struct prefix
*)p
) == FILTER_PERMIT
)
274 *metric
+= OFFSET_LIST_OUT_METRIC (offset
);
282 DEFUN (rip_offset_list
,
284 "offset-list WORD <in|out> (0-16)",
285 "Modify RIP metric\n"
287 "For incoming updates\n"
288 "For outgoing updates\n"
294 return rip_offset_list_set (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, NULL
);
297 DEFUN (rip_offset_list_ifname
,
298 rip_offset_list_ifname_cmd
,
299 "offset-list WORD <in|out> (0-16) IFNAME",
300 "Modify RIP metric\n"
302 "For incoming updates\n"
303 "For outgoing updates\n"
305 "Interface to match\n")
311 return rip_offset_list_set (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
314 DEFUN (no_rip_offset_list
,
315 no_rip_offset_list_cmd
,
316 "no offset-list WORD <in|out> (0-16)",
318 "Modify RIP metric\n"
320 "For incoming updates\n"
321 "For outgoing updates\n"
327 return rip_offset_list_unset (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, NULL
);
330 DEFUN (no_rip_offset_list_ifname
,
331 no_rip_offset_list_ifname_cmd
,
332 "no offset-list WORD <in|out> (0-16) IFNAME",
334 "Modify RIP metric\n"
336 "For incoming updates\n"
337 "For outgoing updates\n"
339 "Interface to match\n")
345 return rip_offset_list_unset (vty
, argv
[idx_word
]->arg
, argv
[idx_in_out
]->arg
, argv
[idx_number
]->arg
, argv
[idx_ifname
]->arg
);
349 offset_list_cmp (struct rip_offset_list
*o1
, struct rip_offset_list
*o2
)
351 return strcmp_safe (o1
->ifname
, o2
->ifname
);
355 offset_list_del (struct rip_offset_list
*offset
)
357 if (OFFSET_LIST_IN_NAME (offset
))
358 free (OFFSET_LIST_IN_NAME (offset
));
359 if (OFFSET_LIST_OUT_NAME (offset
))
360 free (OFFSET_LIST_OUT_NAME (offset
));
362 free (offset
->ifname
);
363 rip_offset_list_free (offset
);
369 rip_offset_list_master
= list_new ();
370 rip_offset_list_master
->cmp
= (int (*)(void *, void *)) offset_list_cmp
;
371 rip_offset_list_master
->del
= (void (*)(void *)) offset_list_del
;
373 install_element (RIP_NODE
, &rip_offset_list_cmd
);
374 install_element (RIP_NODE
, &rip_offset_list_ifname_cmd
);
375 install_element (RIP_NODE
, &no_rip_offset_list_cmd
);
376 install_element (RIP_NODE
, &no_rip_offset_list_ifname_cmd
);
382 list_delete (rip_offset_list_master
);
384 rip_offset_list_master
= list_new ();
385 rip_offset_list_master
->cmp
= (int (*)(void *, void *)) offset_list_cmp
;
386 rip_offset_list_master
->del
= (void (*)(void *)) offset_list_del
;
390 config_write_rip_offset_list (struct vty
*vty
)
392 struct listnode
*node
, *nnode
;
393 struct rip_offset_list
*offset
;
395 for (ALL_LIST_ELEMENTS (rip_offset_list_master
, node
, nnode
, offset
))
397 if (! offset
->ifname
)
399 if (offset
->direct
[RIP_OFFSET_LIST_IN
].alist_name
)
400 vty_outln (vty
, " offset-list %s in %d",
401 offset
->direct
[RIP_OFFSET_LIST_IN
].alist_name
,
402 offset
->direct
[RIP_OFFSET_LIST_IN
].metric
);
403 if (offset
->direct
[RIP_OFFSET_LIST_OUT
].alist_name
)
404 vty_outln (vty
, " offset-list %s out %d",
405 offset
->direct
[RIP_OFFSET_LIST_OUT
].alist_name
,
406 offset
->direct
[RIP_OFFSET_LIST_OUT
].metric
);
410 if (offset
->direct
[RIP_OFFSET_LIST_IN
].alist_name
)
411 vty_outln (vty
, " offset-list %s in %d %s",
412 offset
->direct
[RIP_OFFSET_LIST_IN
].alist_name
,
413 offset
->direct
[RIP_OFFSET_LIST_IN
].metric
,
415 if (offset
->direct
[RIP_OFFSET_LIST_OUT
].alist_name
)
416 vty_outln (vty
, " offset-list %s out %d %s",
417 offset
->direct
[RIP_OFFSET_LIST_OUT
].alist_name
,
418 offset
->direct
[RIP_OFFSET_LIST_OUT
].metric
,