1 /* RIP offset-list
2  * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
3  *
4  * This file is part of GNU Zebra.
5  *
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
9  * later version.
10  *
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.
15  *
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
19  */
20 
21 #include <zebra.h>
22 
23 #include "if.h"
24 #include "prefix.h"
25 #include "filter.h"
26 #include "command.h"
27 #include "linklist.h"
28 #include "memory.h"
29 
30 #include "ripd/ripd.h"
31 
32 DEFINE_MTYPE_STATIC(RIPD, RIP_OFFSET_LIST, "RIP offset list")
33 
34 #define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
35 #define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_IN].metric)
36 
37 #define OFFSET_LIST_OUT_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
38 #define OFFSET_LIST_OUT_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
39 
rip_offset_list_new(struct rip * rip,const char * ifname)40 struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname)
41 {
42 	struct rip_offset_list *offset;
43 
44 	offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
45 	offset->rip = rip;
46 	offset->ifname = strdup(ifname);
47 	listnode_add_sort(rip->offset_list_master, offset);
48 
49 	return offset;
50 }
51 
offset_list_del(struct rip_offset_list * offset)52 void offset_list_del(struct rip_offset_list *offset)
53 {
54 	listnode_delete(offset->rip->offset_list_master, offset);
55 	offset_list_free(offset);
56 }
57 
offset_list_free(struct rip_offset_list * offset)58 void offset_list_free(struct rip_offset_list *offset)
59 {
60 	if (OFFSET_LIST_IN_NAME(offset))
61 		free(OFFSET_LIST_IN_NAME(offset));
62 	if (OFFSET_LIST_OUT_NAME(offset))
63 		free(OFFSET_LIST_OUT_NAME(offset));
64 	free(offset->ifname);
65 	XFREE(MTYPE_RIP_OFFSET_LIST, offset);
66 }
67 
rip_offset_list_lookup(struct rip * rip,const char * ifname)68 struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
69 					       const char *ifname)
70 {
71 	struct rip_offset_list *offset;
72 	struct listnode *node, *nnode;
73 
74 	for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) {
75 		if (strcmp(offset->ifname, ifname) == 0)
76 			return offset;
77 	}
78 	return NULL;
79 }
80 
81 /* If metric is modifed return 1. */
rip_offset_list_apply_in(struct prefix_ipv4 * p,struct interface * ifp,uint32_t * metric)82 int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
83 			     uint32_t *metric)
84 {
85 	struct rip_interface *ri = ifp->info;
86 	struct rip_offset_list *offset;
87 	struct access_list *alist;
88 
89 	/* Look up offset-list with interface name. */
90 	offset = rip_offset_list_lookup(ri->rip, ifp->name);
91 	if (offset && OFFSET_LIST_IN_NAME(offset)) {
92 		alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
93 
94 		if (alist
95 		    && access_list_apply(alist, (struct prefix *)p)
96 			       == FILTER_PERMIT) {
97 			*metric += OFFSET_LIST_IN_METRIC(offset);
98 			return 1;
99 		}
100 		return 0;
101 	}
102 	/* Look up offset-list without interface name. */
103 	offset = rip_offset_list_lookup(ri->rip, "*");
104 	if (offset && OFFSET_LIST_IN_NAME(offset)) {
105 		alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
106 
107 		if (alist
108 		    && access_list_apply(alist, (struct prefix *)p)
109 			       == FILTER_PERMIT) {
110 			*metric += OFFSET_LIST_IN_METRIC(offset);
111 			return 1;
112 		}
113 		return 0;
114 	}
115 	return 0;
116 }
117 
118 /* If metric is modifed return 1. */
rip_offset_list_apply_out(struct prefix_ipv4 * p,struct interface * ifp,uint32_t * metric)119 int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
120 			      uint32_t *metric)
121 {
122 	struct rip_interface *ri = ifp->info;
123 	struct rip_offset_list *offset;
124 	struct access_list *alist;
125 
126 	/* Look up offset-list with interface name. */
127 	offset = rip_offset_list_lookup(ri->rip, ifp->name);
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 
141 	/* Look up offset-list without interface name. */
142 	offset = rip_offset_list_lookup(ri->rip, "*");
143 	if (offset && OFFSET_LIST_OUT_NAME(offset)) {
144 		alist = access_list_lookup(AFI_IP,
145 					   OFFSET_LIST_OUT_NAME(offset));
146 
147 		if (alist
148 		    && access_list_apply(alist, (struct prefix *)p)
149 			       == FILTER_PERMIT) {
150 			*metric += OFFSET_LIST_OUT_METRIC(offset);
151 			return 1;
152 		}
153 		return 0;
154 	}
155 	return 0;
156 }
157 
offset_list_cmp(struct rip_offset_list * o1,struct rip_offset_list * o2)158 int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
159 {
160 	return strcmp(o1->ifname, o2->ifname);
161 }
162