1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 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);
}
|