1/* route-map for interface.
2 * Copyright (C) 1999 Kunihiro Ishiguro
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
17 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#ifdef FOX_LIST_SUPPORT
23
24#include <zebra.h>
25
26#include "hash.h"
27#include "command.h"
28#include "memory.h"
29#include "if.h"
30#include "if_rmap.h"
31
32struct hash *ifrmaphash;
33
34/* Hook functions. */
35void (*if_rmap_add_hook) (struct if_rmap *) = NULL;
36void (*if_rmap_delete_hook) (struct if_rmap *) = NULL;
37
38struct if_rmap *
39if_rmap_new ()
40{
41  struct if_rmap *new;
42
43  new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap));
44
45  return new;
46}
47
48void
49if_rmap_free (struct if_rmap *if_rmap)
50{
51  if (if_rmap->ifname)
52    free (if_rmap->ifname);
53
54  if (if_rmap->routemap[IF_RMAP_IN])
55    free (if_rmap->routemap[IF_RMAP_IN]);
56  if (if_rmap->routemap[IF_RMAP_OUT])
57    free (if_rmap->routemap[IF_RMAP_OUT]);
58
59  XFREE (MTYPE_IF_RMAP, if_rmap);
60}
61
62struct if_rmap *
63if_rmap_lookup (char *ifname)
64{
65  struct if_rmap key;
66  struct if_rmap *if_rmap;
67
68  key.ifname = ifname;
69
70  if_rmap = hash_lookup (ifrmaphash, &key);
71
72  return if_rmap;
73}
74
75void
76if_rmap_hook_add (void (*func) (struct if_rmap *))
77{
78  if_rmap_add_hook = func;
79}
80
81void
82if_rmap_hook_delete (void (*func) (struct if_rmap *))
83{
84  if_rmap_delete_hook = func;
85}
86
87void *
88if_rmap_hash_alloc (struct if_rmap *arg)
89{
90  struct if_rmap *if_rmap;
91
92  if_rmap = if_rmap_new ();
93  if_rmap->ifname = strdup (arg->ifname);
94
95  return if_rmap;
96}
97
98struct if_rmap *
99if_rmap_get (char *ifname)
100{
101  struct if_rmap key;
102
103  key.ifname = ifname;
104
105  return (struct if_rmap *) hash_get (ifrmaphash, &key, if_rmap_hash_alloc);
106}
107
108unsigned int
109if_rmap_hash_make (struct if_rmap *if_rmap)
110{
111  unsigned int key;
112  int i;
113
114  key = 0;
115  for (i = 0; i < strlen (if_rmap->ifname); i++)
116    key += if_rmap->ifname[i];
117
118  return key;
119}
120
121int
122if_rmap_hash_cmp (struct if_rmap *if_rmap1, struct if_rmap *if_rmap2)
123{
124  if (strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0)
125    return 1;
126  return 0;
127}
128
129struct if_rmap *
130if_rmap_set (char *ifname, enum if_rmap_type type, char *routemap_name)
131{
132  struct if_rmap *if_rmap;
133
134  if_rmap = if_rmap_get (ifname);
135
136  if (type == IF_RMAP_IN)
137    {
138      if (if_rmap->routemap[IF_RMAP_IN])
139	free (if_rmap->routemap[IF_RMAP_IN]);
140      if_rmap->routemap[IF_RMAP_IN] = strdup (routemap_name);
141    }
142  if (type == IF_RMAP_OUT)
143    {
144      if (if_rmap->routemap[IF_RMAP_OUT])
145	free (if_rmap->routemap[IF_RMAP_OUT]);
146      if_rmap->routemap[IF_RMAP_OUT] = strdup (routemap_name);
147    }
148
149  if (if_rmap_add_hook)
150    (*if_rmap_add_hook) (if_rmap);
151
152  return if_rmap;
153}
154
155int
156if_rmap_unset (char *ifname, enum if_rmap_type type, char *routemap_name)
157{
158  struct if_rmap *if_rmap;
159
160  if_rmap = if_rmap_lookup (ifname);
161  if (!if_rmap)
162    return 0;
163
164  if (type == IF_RMAP_IN)
165    {
166      if (!if_rmap->routemap[IF_RMAP_IN])
167	return 0;
168      if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0)
169	return 0;
170
171      free (if_rmap->routemap[IF_RMAP_IN]);
172      if_rmap->routemap[IF_RMAP_IN] = NULL;
173    }
174
175  if (type == IF_RMAP_OUT)
176    {
177      if (!if_rmap->routemap[IF_RMAP_OUT])
178	return 0;
179      if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0)
180	return 0;
181
182      free (if_rmap->routemap[IF_RMAP_OUT]);
183      if_rmap->routemap[IF_RMAP_OUT] = NULL;
184    }
185
186  if (if_rmap_delete_hook)
187    (*if_rmap_delete_hook) (if_rmap);
188
189  if (if_rmap->routemap[IF_RMAP_IN] == NULL &&
190      if_rmap->routemap[IF_RMAP_OUT] == NULL)
191    {
192      hash_release (ifrmaphash, if_rmap);
193      if_rmap_free (if_rmap);
194    }
195
196  return 1;
197}
198
199DEFUN (if_rmap,
200       if_rmap_cmd,
201       "route-map RMAP_NAME (in|out) IFNAME",
202       "Route map set\n"
203       "Route map name\n"
204       "Route map set for input filtering\n"
205       "Route map set for output filtering\n"
206       "Route map interface name\n")
207{
208  enum if_rmap_type type;
209  struct if_rmap *if_rmap;
210
211  if (strncmp (argv[1], "i", 1) == 0)
212    type = IF_RMAP_IN;
213  else if (strncmp (argv[1], "o", 1) == 0)
214    type = IF_RMAP_OUT;
215  else
216    {
217      vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE);
218      return CMD_WARNING;
219    }
220
221  if_rmap = if_rmap_set (argv[2], type, argv[0]);
222
223  return CMD_SUCCESS;
224}
225
226DEFUN (no_if_rmap,
227       no_if_rmap_cmd,
228       "no route-map ROUTEMAP_NAME (in|out) IFNAME",
229       NO_STR
230       "Route map unset\n"
231       "Route map name\n"
232       "Route map for input filtering\n"
233       "Route map for output filtering\n"
234       "Route map interface name\n")
235{
236  int ret;
237  enum if_rmap_type type;
238
239  if (strncmp (argv[1], "i", 1) == 0)
240    type = IF_RMAP_IN;
241  else if (strncmp (argv[1], "o", 1) == 0)
242    type = IF_RMAP_OUT;
243  else
244    {
245      vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE);
246      return CMD_WARNING;
247    }
248
249  ret = if_rmap_unset (argv[2], type, argv[0]);
250  if (! ret)
251    {
252      vty_out (vty, "route-map doesn't exist%s", VTY_NEWLINE);
253      return CMD_WARNING;
254    }
255  return CMD_SUCCESS;
256}
257
258/* Configuration write function. */
259int
260config_write_if_rmap (struct vty *vty)
261{
262  int i;
263  struct hash_backet *mp;
264  int write = 0;
265
266  for (i = 0; i < ifrmaphash->size; i++)
267    for (mp = ifrmaphash->index[i]; mp; mp = mp->next)
268      {
269	struct if_rmap *if_rmap;
270
271	if_rmap = mp->data;
272
273	if (if_rmap->routemap[IF_RMAP_IN])
274	  {
275	    vty_out (vty, " route-map %s in %s%s",
276		     if_rmap->routemap[IF_RMAP_IN],
277		     if_rmap->ifname,
278		     VTY_NEWLINE);
279	    write++;
280	  }
281
282	if (if_rmap->routemap[IF_RMAP_OUT])
283	  {
284	    vty_out (vty, " route-map %s out %s%s",
285		     if_rmap->routemap[IF_RMAP_OUT],
286		     if_rmap->ifname,
287		     VTY_NEWLINE);
288	    write++;
289	  }
290      }
291  return write;
292}
293
294void
295if_rmap_reset ()
296{
297  hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free);
298}
299
300void
301if_rmap_init (int node)
302{
303  ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp);
304
305  install_element (node, &if_rmap_cmd);
306  install_element (node, &no_if_rmap_cmd);
307}
308#endif /* FOX_LIST_SUPPORT */
309