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