summaryrefslogtreecommitdiffstats
path: root/ripd/rip_offset.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /ripd/rip_offset.c
parentInitial commit. (diff)
downloadfrr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz
frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ripd/rip_offset.c')
-rw-r--r--ripd/rip_offset.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c
new file mode 100644
index 0000000..4c93f71
--- /dev/null
+++ b/ripd/rip_offset.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* RIP offset-list
+ * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "prefix.h"
+#include "filter.h"
+#include "command.h"
+#include "linklist.h"
+#include "memory.h"
+
+#include "ripd/ripd.h"
+
+DEFINE_MTYPE_STATIC(RIPD, RIP_OFFSET_LIST, "RIP offset list");
+
+#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
+#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric)
+
+#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
+#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
+
+struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname)
+{
+ struct rip_offset_list *offset;
+
+ offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
+ offset->rip = rip;
+ offset->ifname = strdup(ifname);
+ listnode_add_sort(rip->offset_list_master, offset);
+
+ return offset;
+}
+
+void offset_list_del(struct rip_offset_list *offset)
+{
+ listnode_delete(offset->rip->offset_list_master, offset);
+ offset_list_free(offset);
+}
+
+void offset_list_free(struct rip_offset_list *offset)
+{
+ if (OFFSET_LIST_IN_NAME(offset))
+ free(OFFSET_LIST_IN_NAME(offset));
+ if (OFFSET_LIST_OUT_NAME(offset))
+ free(OFFSET_LIST_OUT_NAME(offset));
+ free(offset->ifname);
+ XFREE(MTYPE_RIP_OFFSET_LIST, offset);
+}
+
+struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
+ const char *ifname)
+{
+ struct rip_offset_list *offset;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) {
+ if (strcmp(offset->ifname, ifname) == 0)
+ return offset;
+ }
+ return NULL;
+}
+
+/* If metric is modified return 1. */
+int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
+ uint32_t *metric)
+{
+ struct rip_interface *ri = ifp->info;
+ struct rip_offset_list *offset;
+ struct access_list *alist;
+
+ /* Look up offset-list with interface name. */
+ offset = rip_offset_list_lookup(ri->rip, ifp->name);
+ if (offset && OFFSET_LIST_IN_NAME(offset)) {
+ alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
+
+ if (alist
+ && access_list_apply(alist, (struct prefix *)p)
+ == FILTER_PERMIT) {
+ *metric += OFFSET_LIST_IN_METRIC(offset);
+ return 1;
+ }
+ return 0;
+ }
+ /* Look up offset-list without interface name. */
+ offset = rip_offset_list_lookup(ri->rip, "*");
+ if (offset && OFFSET_LIST_IN_NAME(offset)) {
+ alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
+
+ if (alist
+ && access_list_apply(alist, (struct prefix *)p)
+ == FILTER_PERMIT) {
+ *metric += OFFSET_LIST_IN_METRIC(offset);
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/* If metric is modified return 1. */
+int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
+ uint32_t *metric)
+{
+ struct rip_interface *ri = ifp->info;
+ struct rip_offset_list *offset;
+ struct access_list *alist;
+
+ /* Look up offset-list with interface name. */
+ offset = rip_offset_list_lookup(ri->rip, ifp->name);
+ if (offset && OFFSET_LIST_OUT_NAME(offset)) {
+ alist = access_list_lookup(AFI_IP,
+ OFFSET_LIST_OUT_NAME(offset));
+
+ if (alist
+ && access_list_apply(alist, (struct prefix *)p)
+ == FILTER_PERMIT) {
+ *metric += OFFSET_LIST_OUT_METRIC(offset);
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Look up offset-list without interface name. */
+ offset = rip_offset_list_lookup(ri->rip, "*");
+ if (offset && OFFSET_LIST_OUT_NAME(offset)) {
+ alist = access_list_lookup(AFI_IP,
+ OFFSET_LIST_OUT_NAME(offset));
+
+ if (alist
+ && access_list_apply(alist, (struct prefix *)p)
+ == FILTER_PERMIT) {
+ *metric += OFFSET_LIST_OUT_METRIC(offset);
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
+{
+ return strcmp(o1->ifname, o2->ifname);
+}