Statistics
| Branch: | Revision:

iof-bird-daemon / nest / a-path.c @ 98347659

History | View | Annotate | Download (3.36 KB)

1
/*
2
 *        BIRD -- Path Operations
3
 *
4
 *        (c) 2000 Martin Mares <mj@ucw.cz>
5
 *        (c) 2000 Pavel Machek <pavel@ucw.cz>
6
 *
7
 *        Can be freely distributed and used under the terms of the GNU GPL.
8
 */
9

    
10
#include "nest/bird.h"
11
#include "nest/route.h"
12
#include "nest/attrs.h"
13
#include "lib/resource.h"
14
#include "lib/unaligned.h"
15
#include "lib/string.h"
16

    
17
struct adata *
18
as_path_prepend(struct linpool *pool, struct adata *olda, int as)
19
{
20
  struct adata *newa;
21

    
22
  if (olda->length && olda->data[0] == AS_PATH_SEQUENCE &&
23
      olda->data[1] < 255) /* Starting with sequence => just prepend the AS number */
24
    {
25
      newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 2);
26
      newa->length = olda->length + 2;
27
      newa->data[0] = 2;
28
      newa->data[1] = olda->data[1] + 1;
29
      memcpy(newa->data+4, olda->data+2, olda->length-2);
30
    }
31
  else                                        /* Create new path segment */
32
    {
33
      newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 4);
34
      newa->length = olda->length + 4;
35
      newa->data[0] = 2;
36
      newa->data[1] = 1;
37
      memcpy(newa->data+4, olda->data, olda->length);
38
    }
39
  put_u16(newa->data+2, as);
40
  return newa;
41
}
42

    
43
void
44
as_path_format(struct adata *path, byte *buf, unsigned int size)
45
{
46
  byte *p = path->data;
47
  byte *e = p + path->length - 8;
48
  byte *end = buf + size;
49
  int sp = 1;
50
  int l, type, isset, as;
51

    
52
  while (p < e)
53
    {
54
      if (buf > end)
55
        {
56
          strcpy(buf, " ...");
57
          return;
58
        }
59
      isset = (*p++ == AS_PATH_SET);
60
      l = *p++;
61
      if (isset)
62
        {
63
          if (!sp)
64
            *buf++ = ' ';
65
          *buf++ = '{';
66
          sp = 0;
67
        }
68
      while (l-- && buf <= end)
69
        {
70
          if (!sp)
71
            *buf++ = ' ';
72
          buf += bsprintf(buf, "%d", get_u16(p));
73
          p += 2;
74
          sp = 0;
75
        }
76
      if (isset)
77
        {
78
          *buf++ = ' ';
79
          *buf++ = '}';
80
          sp = 0;
81
        }
82
    }
83
  *buf = 0;
84
}
85

    
86
int
87
as_path_getlen(struct adata *path)
88
{
89
  int res = 0;
90
  u8 *p = path->data;
91
  u8 *q = p+path->length;
92
  int len;
93

    
94
  while (p<q)
95
    {
96
      switch (*p++)
97
        {
98
        case AS_PATH_SET:      len = *p++; res++;    p += 2*len; break;
99
        case AS_PATH_SEQUENCE: len = *p++; res+=len; p += 2*len; break;
100
        default: bug("as_path_getlen: Invalid path segment");
101
        }
102
    }
103
  return res;
104
}
105

    
106
#define MASK_PLUS do { mask = mask->next; if (!mask) return next == q; \
107
                       asterisk = (mask->val == PM_ANY); \
108
                       if (asterisk) { mask = mask->next; if (!mask) { return 1; } } \
109
                       } while(0)
110

    
111
int
112
as_path_match(struct adata *path, struct f_path_mask *mask)
113
{
114
  int i;
115
  int asterisk = 0;
116
  u8 *p = path->data;
117
  u8 *q = p+path->length;
118
  int len;
119
  u8 *next;
120

    
121
  asterisk = (mask->val == PM_ANY);
122
  if (asterisk)
123
    { mask = mask->next; if (!mask) return 1; }
124

    
125
  while (p<q) {
126
    switch (*p++) {
127
    case AS_PATH_SET:
128
      len = *p++;
129
      {
130
        u8 *p_save = p;
131
        next = p_save + 2*len;
132
      retry:
133
        p = p_save;
134
        for (i=0; i<len; i++) {
135
          if (asterisk && (get_u16(p) == mask->val)) {
136
            MASK_PLUS;
137
            goto retry;
138
          }
139
          if (!asterisk && (get_u16(p) == mask->val)) {
140
            p = next;
141
            MASK_PLUS;
142
            goto okay;
143
          }
144
          p+=2;
145
        }
146
        if (!asterisk)
147
          return 0;
148
      okay:
149
      }
150
      break;
151

    
152
    case AS_PATH_SEQUENCE:
153
      len = *p++;
154
      for (i=0; i<len; i++) {
155
        next = p+2;
156
        if (asterisk && (get_u16(p) == mask->val))
157
          MASK_PLUS;
158
        else if (!asterisk) {
159
          if (get_u16(p) != mask->val)
160
            return 0;
161
          MASK_PLUS;
162
        }
163
        p+=2;
164
      }
165
      break;
166

    
167
    default:
168
      bug("as_path_match: Invalid path component");
169
    }
170
  }
171
  return 0;
172
}
173