Revision 11cb6202 nest/a-path.c

View differences:

nest/a-path.c
14 14
#include "lib/unaligned.h"
15 15
#include "lib/string.h"
16 16

  
17

  
18
/* Global AS4 support, shared by all BGP instances.
19
 * This specifies whether BA_AS_PATH attributes contain 2 or 4 B per ASN
20
 */
21

  
22
int bgp_as4_support = 1;
23

  
24
static void
25
put_as(byte *data, u32 as)
26
{
27
  if (bgp_as4_support)
28
    put_u32(data, as);
29
  else if (as <= 0xFFFF)
30
    put_u16(data, as);
31
  else
32
    bug("put_as: Try to put 32bit AS to 16bit AS Path");
33
}
34

  
35
static inline u32
36
get_as(byte *data)
37
{
38
  return bgp_as4_support ? get_u32(data) : get_u16(data);
39
}
40

  
17 41
struct adata *
18
as_path_prepend(struct linpool *pool, struct adata *olda, int as)
42
as_path_prepend(struct linpool *pool, struct adata *olda, u32 as)
19 43
{
44
  int bs = bgp_as4_support ? 4 : 2;
20 45
  struct adata *newa;
21 46

  
22
  if (olda->length && olda->data[0] == AS_PATH_SEQUENCE &&
23
      olda->data[1] < 255) /* Starting with sequence => just prepend the AS number */
47
  if (olda->length && olda->data[0] == AS_PATH_SEQUENCE && olda->data[1] < 255)
48
    /* Starting with sequence => just prepend the AS number */
24 49
    {
25
      newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 2);
26
      newa->length = olda->length + 2;
27
      newa->data[0] = 2;
50
      int nl = olda->length + bs;
51
      newa = lp_alloc(pool, sizeof(struct adata) + nl);
52
      newa->length = nl;
53
      newa->data[0] = AS_PATH_SEQUENCE;
28 54
      newa->data[1] = olda->data[1] + 1;
29
      memcpy(newa->data+4, olda->data+2, olda->length-2);
55
      memcpy(newa->data + bs + 2, olda->data + 2, olda->length - 2);
30 56
    }
31
  else					/* Create new path segment */
57
  else /* Create new path segment */
32 58
    {
33
      newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 4);
34
      newa->length = olda->length + 4;
35
      newa->data[0] = 2;
59
      int nl = olda->length + bs + 2;
60
      newa = lp_alloc(pool, sizeof(struct adata) + nl);
61
      newa->length = nl;
62
      newa->data[0] = AS_PATH_SEQUENCE;
36 63
      newa->data[1] = 1;
37
      memcpy(newa->data+4, olda->data, olda->length);
64
      memcpy(newa->data + bs + 2, olda->data, olda->length);
38 65
    }
39
  put_u16(newa->data+2, as);
66
  put_as(newa->data + 2, as);
40 67
  return newa;
41 68
}
42 69

  
70
int
71
as_path_convert_to_old(struct adata *path, byte *dst, int *new_used)
72
{
73
  byte *src = path->data;
74
  byte *src_end = src + path->length;
75
  byte *dst_start = dst;
76
  u32 as;
77
  int i, n;
78
  *new_used = 0;
79

  
80
  while (src < src_end)
81
    {
82
      n = src[1];
83
      *dst++ = *src++;
84
      *dst++ = *src++;
85

  
86
      for(i=0; i<n; i++)
87
	{
88
	  as = get_u32(src);
89
	  if (as > 0xFFFF) 
90
	    {
91
	      as = AS_TRANS;
92
	      *new_used = 1;
93
	    }
94
	  put_u16(dst, as);
95
	  src += 4;
96
	  dst += 2;
97
	}
98
    }
99

  
100
  return dst - dst_start;
101
}
102

  
103
int
104
as_path_convert_to_new(struct adata *path, byte *dst, int req_as)
105
{
106
  byte *src = path->data;
107
  byte *src_end = src + path->length;
108
  byte *dst_start = dst;
109
  u32 as;
110
  int i, t, n;
111

  
112

  
113
  while ((src < src_end) && (req_as > 0))
114
    {
115
      t = *src++;
116
      n = *src++;
117

  
118
      if (t == AS_PATH_SEQUENCE)
119
	{
120
	  if (n > req_as)
121
	    n = req_as;
122

  
123
	  req_as -= n;
124
	}
125
      else // t == AS_PATH_SET
126
	req_as--;
127

  
128
      *dst++ = t;
129
      *dst++ = n;
130

  
131
      for(i=0; i<n; i++)
132
	{
133
	  as = get_u16(src);
134
	  put_u32(dst, as);
135
	  src += 2;
136
	  dst += 4;
137
	}
138
    }
139

  
140
  return dst - dst_start;
141
}
142

  
43 143
void
44 144
as_path_format(struct adata *path, byte *buf, unsigned int size)
45 145
{
146
  int bs = bgp_as4_support ? 4 : 2;
46 147
  byte *p = path->data;
47 148
  byte *e = p + path->length;
48
  byte *end = buf + size - 8;
149
  byte *end = buf + size - 16;
49 150
  int sp = 1;
50 151
  int l, isset;
51 152

  
......
69 170
	{
70 171
	  if (!sp)
71 172
	    *buf++ = ' ';
72
	  buf += bsprintf(buf, "%d", get_u16(p));
73
	  p += 2;
173
	  buf += bsprintf(buf, "%u", get_as(p));
174
	  p += bs;
74 175
	  sp = 0;
75 176
	}
76 177
      if (isset)
......
86 187
int
87 188
as_path_getlen(struct adata *path)
88 189
{
190
  int bs = bgp_as4_support ? 4 : 2;
89 191
  int res = 0;
90 192
  u8 *p = path->data;
91 193
  u8 *q = p+path->length;
......
95 197
    {
96 198
      switch (*p++)
97 199
	{
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;
200
	case AS_PATH_SET:      len = *p++; res++;      p += bs * len; break;
201
	case AS_PATH_SEQUENCE: len = *p++; res += len; p += bs * len; break;
100 202
	default: bug("as_path_getlen: Invalid path segment");
101 203
	}
102 204
    }
......
104 206
}
105 207

  
106 208
int
107
as_path_get_first(struct adata *path)
209
as_path_get_first(struct adata *path, u32 *orig_as)
108 210
{
109
  int res = -1;
211
  int bs = bgp_as4_support ? 4 : 2;
212
  int found = 0;
213
  u32 res = 0;
110 214
  u8 *p = path->data;
111 215
  u8 *q = p+path->length;
112 216
  int len;
......
117 221
	{
118 222
	case AS_PATH_SET:
119 223
	  if (len = *p++)
120
	    res = get_u16(p);
121
	  p += 2*len;
224
	    {
225
	      found = 1;
226
	      res = get_as(p);
227
	      p += bs * len;
228
	    }
122 229
	  break;
123 230
	case AS_PATH_SEQUENCE:
124 231
	  if (len = *p++)
125
	    res = get_u16(p+2*(len-1));
126
	  p += 2*len;
232
	    {
233
	      found = 1;
234
	      res = get_as(p + bs * (len - 1));
235
	      p += bs * len;
236
	    }
127 237
	  break;
128 238
	default: bug("as_path_get_first: Invalid path segment");
129 239
	}
130 240
    }
131
  return res;
241

  
242
  *orig_as = res;
243
  return found;
132 244
}
133 245

  
246
int
247
as_path_is_member(struct adata *path, u32 as)
248
{
249
  int bs = bgp_as4_support ? 4 : 2;
250
  u8 *p = path->data;
251
  u8 *q = p+path->length;
252
  int i, n;
253

  
254
  while (p<q)
255
    {
256
      n = p[1];
257
      p += 2;
258
      for(i=0; i<n; i++)
259
	{
260
	  if (get_as(p) == as)
261
	    return 1;
262
	  p += bs;
263
	}
264
    }
265
  return 0;
266
}
267

  
268

  
269

  
134 270
#define MASK_PLUS do { mask = mask->next; if (!mask) return next == q; \
135
		       asterisk = (mask->val == PM_ANY); \
271
		       asterisk = mask->any; \
136 272
                       if (asterisk) { mask = mask->next; if (!mask) { return 1; } } \
137 273
		       } while(0)
138 274

  
139 275
int
140 276
as_path_match(struct adata *path, struct f_path_mask *mask)
141 277
{
278
  int bs = bgp_as4_support ? 4 : 2;
142 279
  int i;
143 280
  int asterisk = 0;
144 281
  u8 *p = path->data;
145 282
  u8 *q = p+path->length;
146 283
  int len;
147 284
  u8 *next;
285
  u32 as;
148 286

  
149
  asterisk = (mask->val == PM_ANY);
287
  asterisk = mask->any;
150 288
  if (asterisk)
151 289
    { mask = mask->next; if (!mask) return 1; }
152 290

  
......
156 294
      len = *p++;
157 295
      {
158 296
	u8 *p_save = p;
159
	next = p_save + 2*len;
297
	next = p_save + bs * len;
160 298
      retry:
161 299
	p = p_save;
162 300
	for (i=0; i<len; i++) {
163
	  if (asterisk && (get_u16(p) == mask->val)) {
301
	  as = get_as(p);
302
	  if (asterisk && (as == mask->val)) {
164 303
	    MASK_PLUS;
165 304
	    goto retry;
166 305
	  }
167
	  if (!asterisk && (get_u16(p) == mask->val)) {
306
	  if (!asterisk && (as == mask->val)) {
168 307
	    p = next;
169 308
	    MASK_PLUS;
170 309
	    goto okay;
171 310
	  }
172
	  p+=2;
311
	  p += bs;
173 312
	}
174 313
	if (!asterisk)
175 314
	  return 0;
......
180 319
    case AS_PATH_SEQUENCE:
181 320
      len = *p++;
182 321
      for (i=0; i<len; i++) {
183
	next = p+2;
184
	if (asterisk && (get_u16(p) == mask->val))
322
	as = get_as(p);
323
	if (asterisk && (as == mask->val))
185 324
	  MASK_PLUS;
186 325
	else if (!asterisk) {
187
	  if (get_u16(p) != mask->val)
326
	  if (as != mask->val)
188 327
	    return 0;
189 328
	  MASK_PLUS;
190 329
	}
191
	p+=2;
330
	p += bs;
192 331
      }
193 332
      break;
194 333

  

Also available in: Unified diff