]>
Commit | Line | Data |
---|---|---|
1 | // SPDX-License-Identifier: GPL-2.0-or-later | |
2 | /* RIP offset-list | |
3 | * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> | |
4 | */ | |
5 | ||
6 | #include <zebra.h> | |
7 | ||
8 | #include "if.h" | |
9 | #include "prefix.h" | |
10 | #include "filter.h" | |
11 | #include "command.h" | |
12 | #include "linklist.h" | |
13 | #include "memory.h" | |
14 | ||
15 | #include "ripd/ripd.h" | |
16 | ||
17 | DEFINE_MTYPE_STATIC(RIPD, RIP_OFFSET_LIST, "RIP offset list"); | |
18 | ||
19 | #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) | |
20 | #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric) | |
21 | ||
22 | #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name) | |
23 | #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) | |
24 | ||
25 | struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname) | |
26 | { | |
27 | struct rip_offset_list *offset; | |
28 | ||
29 | offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); | |
30 | offset->rip = rip; | |
31 | offset->ifname = strdup(ifname); | |
32 | listnode_add_sort(rip->offset_list_master, offset); | |
33 | ||
34 | return offset; | |
35 | } | |
36 | ||
37 | void offset_list_del(struct rip_offset_list *offset) | |
38 | { | |
39 | listnode_delete(offset->rip->offset_list_master, offset); | |
40 | offset_list_free(offset); | |
41 | } | |
42 | ||
43 | void offset_list_free(struct rip_offset_list *offset) | |
44 | { | |
45 | if (OFFSET_LIST_IN_NAME(offset)) | |
46 | free(OFFSET_LIST_IN_NAME(offset)); | |
47 | if (OFFSET_LIST_OUT_NAME(offset)) | |
48 | free(OFFSET_LIST_OUT_NAME(offset)); | |
49 | free(offset->ifname); | |
50 | XFREE(MTYPE_RIP_OFFSET_LIST, offset); | |
51 | } | |
52 | ||
53 | struct rip_offset_list *rip_offset_list_lookup(struct rip *rip, | |
54 | const char *ifname) | |
55 | { | |
56 | struct rip_offset_list *offset; | |
57 | struct listnode *node, *nnode; | |
58 | ||
59 | for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) { | |
60 | if (strcmp(offset->ifname, ifname) == 0) | |
61 | return offset; | |
62 | } | |
63 | return NULL; | |
64 | } | |
65 | ||
66 | /* If metric is modified return 1. */ | |
67 | int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, | |
68 | uint32_t *metric) | |
69 | { | |
70 | struct rip_interface *ri = ifp->info; | |
71 | struct rip_offset_list *offset; | |
72 | struct access_list *alist; | |
73 | ||
74 | /* Look up offset-list with interface name. */ | |
75 | offset = rip_offset_list_lookup(ri->rip, ifp->name); | |
76 | if (offset && OFFSET_LIST_IN_NAME(offset)) { | |
77 | alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); | |
78 | ||
79 | if (alist | |
80 | && access_list_apply(alist, (struct prefix *)p) | |
81 | == FILTER_PERMIT) { | |
82 | *metric += OFFSET_LIST_IN_METRIC(offset); | |
83 | return 1; | |
84 | } | |
85 | return 0; | |
86 | } | |
87 | /* Look up offset-list without interface name. */ | |
88 | offset = rip_offset_list_lookup(ri->rip, "*"); | |
89 | if (offset && OFFSET_LIST_IN_NAME(offset)) { | |
90 | alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); | |
91 | ||
92 | if (alist | |
93 | && access_list_apply(alist, (struct prefix *)p) | |
94 | == FILTER_PERMIT) { | |
95 | *metric += OFFSET_LIST_IN_METRIC(offset); | |
96 | return 1; | |
97 | } | |
98 | return 0; | |
99 | } | |
100 | return 0; | |
101 | } | |
102 | ||
103 | /* If metric is modified return 1. */ | |
104 | int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, | |
105 | uint32_t *metric) | |
106 | { | |
107 | struct rip_interface *ri = ifp->info; | |
108 | struct rip_offset_list *offset; | |
109 | struct access_list *alist; | |
110 | ||
111 | /* Look up offset-list with interface name. */ | |
112 | offset = rip_offset_list_lookup(ri->rip, ifp->name); | |
113 | if (offset && OFFSET_LIST_OUT_NAME(offset)) { | |
114 | alist = access_list_lookup(AFI_IP, | |
115 | OFFSET_LIST_OUT_NAME(offset)); | |
116 | ||
117 | if (alist | |
118 | && access_list_apply(alist, (struct prefix *)p) | |
119 | == FILTER_PERMIT) { | |
120 | *metric += OFFSET_LIST_OUT_METRIC(offset); | |
121 | return 1; | |
122 | } | |
123 | return 0; | |
124 | } | |
125 | ||
126 | /* Look up offset-list without interface name. */ | |
127 | offset = rip_offset_list_lookup(ri->rip, "*"); | |
128 | if (offset && OFFSET_LIST_OUT_NAME(offset)) { | |
129 | alist = access_list_lookup(AFI_IP, | |
130 | OFFSET_LIST_OUT_NAME(offset)); | |
131 | ||
132 | if (alist | |
133 | && access_list_apply(alist, (struct prefix *)p) | |
134 | == FILTER_PERMIT) { | |
135 | *metric += OFFSET_LIST_OUT_METRIC(offset); | |
136 | return 1; | |
137 | } | |
138 | return 0; | |
139 | } | |
140 | return 0; | |
141 | } | |
142 | ||
143 | int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2) | |
144 | { | |
145 | return strcmp(o1->ifname, o2->ifname); | |
146 | } |