~ubuntu-branches/ubuntu/breezy/quagga/breezy-security

« back to all changes in this revision

Viewing changes to ripd/rip_offset.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-05-20 13:16:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050520131612-pr6paalox60o3x3n
Tags: upstream-0.99.1
ImportĀ upstreamĀ versionĀ 0.99.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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 "if.h"
 
25
#include "prefix.h"
 
26
#include "filter.h"
 
27
#include "command.h"
 
28
#include "linklist.h"
 
29
#include "memory.h"
 
30
 
 
31
#define RIP_OFFSET_LIST_IN  0
 
32
#define RIP_OFFSET_LIST_OUT 1
 
33
#define RIP_OFFSET_LIST_MAX 2
 
34
 
 
35
struct rip_offset_list
 
36
{
 
37
  char *ifname;
 
38
 
 
39
  struct 
 
40
  {
 
41
    char *alist_name;
 
42
    /* struct access_list *alist; */
 
43
    int metric;
 
44
  } direct[RIP_OFFSET_LIST_MAX];
 
45
};
 
46
 
 
47
static struct list *rip_offset_list_master;
 
48
 
 
49
int
 
50
strcmp_safe (const char *s1, const char *s2)
 
51
{
 
52
  if (s1 == NULL && s2 == NULL)
 
53
    return 0;
 
54
  if (s1 == NULL)
 
55
    return -1;
 
56
  if (s2 == NULL)
 
57
    return 1;
 
58
  return strcmp (s1, s2);
 
59
}
 
60
 
 
61
struct rip_offset_list *
 
62
rip_offset_list_new ()
 
63
{
 
64
  struct rip_offset_list *new;
 
65
 
 
66
  new = XMALLOC (MTYPE_RIP_OFFSET_LIST, sizeof (struct rip_offset_list));
 
67
  memset (new, 0, sizeof (struct rip_offset_list));
 
68
  return new;
 
69
}
 
70
 
 
71
void
 
72
rip_offset_list_free (struct rip_offset_list *offset)
 
73
{
 
74
  XFREE (MTYPE_RIP_OFFSET_LIST, offset);
 
75
}
 
76
 
 
77
struct rip_offset_list *
 
78
rip_offset_list_lookup (const char *ifname)
 
79
{
 
80
  struct rip_offset_list *offset;
 
81
  struct listnode *node, *nnode;
 
82
 
 
83
  for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset))
 
84
    {
 
85
      if (strcmp_safe (offset->ifname, ifname) == 0)
 
86
        return offset;
 
87
    }
 
88
  return NULL;
 
89
}
 
90
 
 
91
struct rip_offset_list *
 
92
rip_offset_list_get (const char *ifname)
 
93
{
 
94
  struct rip_offset_list *offset;
 
95
  
 
96
  offset = rip_offset_list_lookup (ifname);
 
97
  if (offset)
 
98
    return offset;
 
99
 
 
100
  offset = rip_offset_list_new ();
 
101
  if (ifname)
 
102
    offset->ifname = strdup (ifname);
 
103
  listnode_add_sort (rip_offset_list_master, offset);
 
104
 
 
105
  return offset;
 
106
}
 
107
 
 
108
int
 
109
rip_offset_list_set (struct vty *vty, const char *alist, const char *direct_str,
 
110
                     const char *metric_str, const char *ifname)
 
111
{
 
112
  int direct;
 
113
  int metric;
 
114
  struct rip_offset_list *offset;
 
115
 
 
116
  /* Check direction. */
 
117
  if (strncmp (direct_str, "i", 1) == 0)
 
118
    direct = RIP_OFFSET_LIST_IN;
 
119
  else if (strncmp (direct_str, "o", 1) == 0)
 
120
    direct = RIP_OFFSET_LIST_OUT;
 
121
  else
 
122
    {
 
123
      vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
 
124
      return CMD_WARNING;
 
125
    }
 
126
 
 
127
  /* Check metric. */
 
128
  metric = atoi (metric_str);
 
129
  if (metric < 0 || metric > 16)
 
130
    {
 
131
      vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
 
132
      return CMD_WARNING;
 
133
    }
 
134
 
 
135
  /* Get offset-list structure with interface name. */
 
136
  offset = rip_offset_list_get (ifname);
 
137
 
 
138
  if (offset->direct[direct].alist_name)
 
139
    free (offset->direct[direct].alist_name);
 
140
  offset->direct[direct].alist_name = strdup (alist);
 
141
  offset->direct[direct].metric = metric;
 
142
 
 
143
  return CMD_SUCCESS;
 
144
}
 
145
 
 
146
int
 
147
rip_offset_list_unset (struct vty *vty, const char *alist,
 
148
                       const char *direct_str, const char *metric_str,
 
149
                       const char *ifname)
 
150
{
 
151
  int direct;
 
152
  int metric;
 
153
  struct rip_offset_list *offset;
 
154
 
 
155
  /* Check direction. */
 
156
  if (strncmp (direct_str, "i", 1) == 0)
 
157
    direct = RIP_OFFSET_LIST_IN;
 
158
  else if (strncmp (direct_str, "o", 1) == 0)
 
159
    direct = RIP_OFFSET_LIST_OUT;
 
160
  else
 
161
    {
 
162
      vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
 
163
      return CMD_WARNING;
 
164
    }
 
165
 
 
166
  /* Check metric. */
 
167
  metric = atoi (metric_str);
 
168
  if (metric < 0 || metric > 16)
 
169
    {
 
170
      vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
 
171
      return CMD_WARNING;
 
172
    }
 
173
 
 
174
  /* Get offset-list structure with interface name. */
 
175
  offset = rip_offset_list_lookup (ifname);
 
176
 
 
177
  if (offset)
 
178
    {
 
179
      if (offset->direct[direct].alist_name)
 
180
        free (offset->direct[direct].alist_name);
 
181
      offset->direct[direct].alist_name = NULL;
 
182
 
 
183
      if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL &&
 
184
          offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL)
 
185
        {
 
186
          listnode_delete (rip_offset_list_master, offset);
 
187
          if (offset->ifname)
 
188
            free (offset->ifname);
 
189
          rip_offset_list_free (offset);
 
190
        }
 
191
    }
 
192
  else
 
193
    {
 
194
      vty_out (vty, "Can't find offset-list%s", VTY_NEWLINE);
 
195
      return CMD_WARNING;
 
196
    }
 
197
  return CMD_SUCCESS;
 
198
}
 
199
 
 
200
#define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
 
201
#define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_IN].metric)
 
202
 
 
203
#define OFFSET_LIST_OUT_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
 
204
#define OFFSET_LIST_OUT_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
 
205
 
 
206
/* If metric is modifed return 1. */
 
207
int
 
208
rip_offset_list_apply_in (struct prefix_ipv4 *p, struct interface *ifp,
 
209
                          u_int32_t *metric)
 
210
{
 
211
  struct rip_offset_list *offset;
 
212
  struct access_list *alist;
 
213
 
 
214
  /* Look up offset-list with interface name. */
 
215
  offset = rip_offset_list_lookup (ifp->name);
 
216
  if (offset && OFFSET_LIST_IN_NAME (offset))
 
217
    {
 
218
      alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset));
 
219
 
 
220
      if (alist 
 
221
          && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
 
222
        {
 
223
          *metric += OFFSET_LIST_IN_METRIC (offset);
 
224
          return 1;
 
225
        }
 
226
      return 0;
 
227
    }
 
228
  /* Look up offset-list without interface name. */
 
229
  offset = rip_offset_list_lookup (NULL);
 
230
  if (offset && OFFSET_LIST_IN_NAME (offset))
 
231
    {
 
232
      alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset));
 
233
 
 
234
      if (alist 
 
235
          && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
 
236
        {
 
237
          *metric += OFFSET_LIST_IN_METRIC (offset);
 
238
          return 1;
 
239
        }
 
240
      return 0;
 
241
    }
 
242
  return 0;
 
243
}
 
244
 
 
245
/* If metric is modifed return 1. */
 
246
int
 
247
rip_offset_list_apply_out (struct prefix_ipv4 *p, struct interface *ifp,
 
248
                          u_int32_t *metric)
 
249
{
 
250
  struct rip_offset_list *offset;
 
251
  struct access_list *alist;
 
252
 
 
253
  /* Look up offset-list with interface name. */
 
254
  offset = rip_offset_list_lookup (ifp->name);
 
255
  if (offset && OFFSET_LIST_OUT_NAME (offset))
 
256
    {
 
257
      alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset));
 
258
 
 
259
      if (alist 
 
260
          && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
 
261
        {
 
262
          *metric += OFFSET_LIST_OUT_METRIC (offset);
 
263
          return 1;
 
264
        }
 
265
      return 0;
 
266
    }
 
267
 
 
268
  /* Look up offset-list without interface name. */
 
269
  offset = rip_offset_list_lookup (NULL);
 
270
  if (offset && OFFSET_LIST_OUT_NAME (offset))
 
271
    {
 
272
      alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset));
 
273
 
 
274
      if (alist 
 
275
          && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
 
276
        {
 
277
          *metric += OFFSET_LIST_OUT_METRIC (offset);
 
278
          return 1;
 
279
        }
 
280
      return 0;
 
281
    }
 
282
  return 0;
 
283
}
 
284
 
 
285
DEFUN (rip_offset_list,
 
286
       rip_offset_list_cmd,
 
287
       "offset-list WORD (in|out) <0-16>",
 
288
       "Modify RIP metric\n"
 
289
       "Access-list name\n"
 
290
       "For incoming updates\n"
 
291
       "For outgoing updates\n"
 
292
       "Metric value\n")
 
293
{
 
294
  return rip_offset_list_set (vty, argv[0], argv[1], argv[2], NULL);
 
295
}
 
296
 
 
297
DEFUN (rip_offset_list_ifname,
 
298
       rip_offset_list_ifname_cmd,
 
299
       "offset-list WORD (in|out) <0-16> IFNAME",
 
300
       "Modify RIP metric\n"
 
301
       "Access-list name\n"
 
302
       "For incoming updates\n"
 
303
       "For outgoing updates\n"
 
304
       "Metric value\n"
 
305
       "Interface to match\n")
 
306
{
 
307
  return rip_offset_list_set (vty, argv[0], argv[1], argv[2], argv[3]);
 
308
}
 
309
 
 
310
DEFUN (no_rip_offset_list,
 
311
       no_rip_offset_list_cmd,
 
312
       "no offset-list WORD (in|out) <0-16>",
 
313
       NO_STR
 
314
       "Modify RIP metric\n"
 
315
       "Access-list name\n"
 
316
       "For incoming updates\n"
 
317
       "For outgoing updates\n"
 
318
       "Metric value\n")
 
319
{
 
320
  return rip_offset_list_unset (vty, argv[0], argv[1], argv[2], NULL);
 
321
}
 
322
 
 
323
DEFUN (no_rip_offset_list_ifname,
 
324
       no_rip_offset_list_ifname_cmd,
 
325
       "no offset-list WORD (in|out) <0-16> IFNAME",
 
326
       NO_STR
 
327
       "Modify RIP metric\n"
 
328
       "Access-list name\n"
 
329
       "For incoming updates\n"
 
330
       "For outgoing updates\n"
 
331
       "Metric value\n"
 
332
       "Interface to match\n")
 
333
{
 
334
  return rip_offset_list_unset (vty, argv[0], argv[1], argv[2], argv[3]);
 
335
}
 
336
 
 
337
int
 
338
offset_list_cmp (struct rip_offset_list *o1, struct rip_offset_list *o2)
 
339
{
 
340
  return strcmp_safe (o1->ifname, o2->ifname);
 
341
}
 
342
 
 
343
void
 
344
offset_list_del (struct rip_offset_list *offset)
 
345
{
 
346
  if (OFFSET_LIST_IN_NAME (offset))
 
347
    free (OFFSET_LIST_IN_NAME (offset));
 
348
  if (OFFSET_LIST_OUT_NAME (offset))
 
349
    free (OFFSET_LIST_OUT_NAME (offset));
 
350
  if (offset->ifname)
 
351
    free (offset->ifname);
 
352
  rip_offset_list_free (offset);
 
353
}
 
354
 
 
355
void
 
356
rip_offset_init ()
 
357
{
 
358
  rip_offset_list_master = list_new ();
 
359
  rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
 
360
  rip_offset_list_master->del = (void (*)(void *)) offset_list_del;
 
361
 
 
362
  install_element (RIP_NODE, &rip_offset_list_cmd);
 
363
  install_element (RIP_NODE, &rip_offset_list_ifname_cmd);
 
364
  install_element (RIP_NODE, &no_rip_offset_list_cmd);
 
365
  install_element (RIP_NODE, &no_rip_offset_list_ifname_cmd);
 
366
}
 
367
 
 
368
void
 
369
rip_offset_clean ()
 
370
{
 
371
  list_delete (rip_offset_list_master);
 
372
 
 
373
  rip_offset_list_master = list_new ();
 
374
  rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
 
375
  rip_offset_list_master->del = (void (*)(void *)) offset_list_del;
 
376
}
 
377
 
 
378
int
 
379
config_write_rip_offset_list (struct vty *vty)
 
380
{
 
381
  struct listnode *node, *nnode;
 
382
  struct rip_offset_list *offset;
 
383
 
 
384
  for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset))
 
385
    {
 
386
      if (! offset->ifname)
 
387
        {
 
388
          if (offset->direct[RIP_OFFSET_LIST_IN].alist_name)
 
389
            vty_out (vty, " offset-list %s in %d%s",
 
390
                     offset->direct[RIP_OFFSET_LIST_IN].alist_name,
 
391
                     offset->direct[RIP_OFFSET_LIST_IN].metric,
 
392
                     VTY_NEWLINE);
 
393
          if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name)
 
394
            vty_out (vty, " offset-list %s out %d%s",
 
395
                     offset->direct[RIP_OFFSET_LIST_OUT].alist_name,
 
396
                     offset->direct[RIP_OFFSET_LIST_OUT].metric,
 
397
                     VTY_NEWLINE);
 
398
        }
 
399
      else
 
400
        {
 
401
          if (offset->direct[RIP_OFFSET_LIST_IN].alist_name)
 
402
            vty_out (vty, " offset-list %s in %d %s%s",
 
403
                     offset->direct[RIP_OFFSET_LIST_IN].alist_name,
 
404
                     offset->direct[RIP_OFFSET_LIST_IN].metric,
 
405
                     offset->ifname, VTY_NEWLINE);
 
406
          if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name)
 
407
            vty_out (vty, " offset-list %s out %d %s%s",
 
408
                     offset->direct[RIP_OFFSET_LIST_OUT].alist_name,
 
409
                     offset->direct[RIP_OFFSET_LIST_OUT].metric,
 
410
                     offset->ifname, VTY_NEWLINE);
 
411
        }
 
412
    }
 
413
 
 
414
  return 0;
 
415
}