Revision 11cb6202

View differences:

filter/config.Y
39 39
%type <v> set_atom fprefix fprefix_s fipa
40 40
%type <s> decls declsn one_decl function_params 
41 41
%type <h> bgp_path
42
%type <i> bgp_one
43 42

  
44 43
CF_GRAMMAR
45 44

  
......
273 272

  
274 273
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
275 274

  
276
bgp_one:
277
   NUM { $$ = $1; }
278
 | '?' { $$ = PM_ANY; }
279
 ;
280 275

  
281 276
bgp_path: 
282
   bgp_one          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = $1; }
283
 | bgp_one bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = $1; }
277
   NUM          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = $1; $$->any = 0; }
278
 | '?'          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = 0;  $$->any = 1; }
279
 | NUM bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = $1; $$->any = 0; }
280
 | '?' bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = 0;  $$->any = 1; }
284 281
 ;
285 282

  
286 283
constant:
filter/filter.c
69 69
  }
70 70
}
71 71

  
72
static void
73
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
74
{
75
  byte *end = buf + size - 16;
76

  
77
  while (p)
78
    {
79
      if (buf > end)
80
	{
81
	  strcpy(buf, " ...");
82
	  return;
83
	}
84

  
85
      if (p->any)
86
	buf += bsprintf(buf, "? ");
87
      else
88
	buf += bsprintf(buf, "%u ", p->val);
89

  
90
      p = p->next;
91
    }
92

  
93
  *buf = 0;
94
}
95

  
72 96
/**
73 97
 * val_compare - compare two values
74 98
 * @v1: first value
......
224 248
  case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
225 249
  case T_PATH: as_path_format(v.val.ad, buf2, 1020); PRINTF( "(path %s)", buf2 ); break;
226 250
  case T_CLIST: int_set_format(v.val.ad, buf2, 1020); PRINTF( "(clist %s)", buf2 ); break;
227
  case T_PATH_MASK: debug( "(pathmask " ); { struct f_path_mask *p = v.val.path_mask; while (p) { debug("%d ", p->val); p=p->next; } debug(")" ); } break;
251
  case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1020); PRINTF( "(pathmask %s)", buf2 ); break;
228 252
  default: PRINTF( "[unknown type %x]", v.type );
229 253
#undef PRINTF
230 254
  }
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

  
nest/attrs.h
14 14
#define AS_PATH_SET		1	/* Types of path segments */
15 15
#define AS_PATH_SEQUENCE	2
16 16

  
17
struct adata *as_path_prepend(struct linpool *pool, struct adata *olda, int as);
17
#define AS_PATH_MAXLEN		10000
18

  
19
#define AS_TRANS		23456
20
/* AS_TRANS is used when we need to store 32bit ASN larger than 0xFFFF
21
 * to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details
22
 */
23

  
24
struct adata *as_path_prepend(struct linpool *pool, struct adata *olda, u32 as);
25
int as_path_convert_to_old(struct adata *path, byte *dst, int *new_used);
26
int as_path_convert_to_new(struct adata *path, byte *dst, int req_as);
18 27
void as_path_format(struct adata *path, byte *buf, unsigned int size);
19 28
int as_path_getlen(struct adata *path);
20
int as_path_get_first(struct adata *path);
29
int as_path_get_first(struct adata *path, u32 *orig_as);
30
int as_path_is_member(struct adata *path, u32 as);
31

  
21 32

  
22 33
struct f_path_mask {
23 34
  struct f_path_mask *next;
24
  int val;
35
  u32 val;
36
  int any;
25 37
};
26
#define PM_ANY -1
38

  
39
// #define PM_ANY -1
27 40

  
28 41
int as_path_match(struct adata *path, struct f_path_mask *mask);
29 42

  
proto/bgp/attrs.c
55 55
}
56 56

  
57 57
static int
58
bgp_check_path(struct bgp_proto *p UNUSED, byte *a, int len)
58
bgp_check_path(byte *a, int len, int bs, int errcode)
59 59
{
60 60
  while (len)
61 61
    {
62 62
      DBG("Path segment %02x %02x\n", a[0], a[1]);
63 63
      if (len < 2 ||
64
	  a[0] != AS_PATH_SET && a[0] != AS_PATH_SEQUENCE ||
65
	  2*a[1] + 2 > len)
66
	return 11;
67
      len -= 2*a[1] + 2;
68
      a += 2*a[1] + 2;
64
	  (a[0] != AS_PATH_SET && a[0] != AS_PATH_SEQUENCE) ||
65
	  bs * a[1] + 2 > len)
66
	return errcode;
67
      len -= bs * a[1] + 2;
68
      a += bs * a[1] + 2;
69 69
    }
70 70
  return 0;
71 71
}
72 72

  
73 73
static int
74
bgp_check_as_path(struct bgp_proto *p, byte *a, int len)
75
{
76
  return bgp_check_path(a, len, (bgp_as4_support && p->as4_support) ? 4 : 2, 11);
77
}
78

  
79
static int
80
bgp_check_as4_path(struct bgp_proto *p, byte *a, int len)
81
{
82
  if (bgp_as4_support && (! p->as4_support))
83
    return bgp_check_path(a, len, 4, 9);
84
  else 
85
    return 0;
86
}
87

  
88

  
89
static int
74 90
bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a, int len)
75 91
{
76 92
#ifdef IPV6
......
88 104
}
89 105

  
90 106
static int
107
bgp_check_aggregator(struct bgp_proto *p UNUSED, UNUSED byte *a, int len)
108
{
109
  int exp_len = (bgp_as4_support && p->as4_support) ? 8 : 6;
110
  
111
  return (len == exp_len) ? 0 : 5;
112
}
113

  
114
static int
91 115
bgp_check_reach_nlri(struct bgp_proto *p UNUSED, byte *a UNUSED, int len UNUSED)
92 116
{
93 117
#ifdef IPV6
......
113 137
  { "origin", 1, BAF_TRANSITIVE, EAF_TYPE_INT, 1,				/* BA_ORIGIN */
114 138
    bgp_check_origin, bgp_format_origin },
115 139
  { "as_path", -1, BAF_TRANSITIVE, EAF_TYPE_AS_PATH, 1,				/* BA_AS_PATH */
116
    bgp_check_path, NULL },
140
    bgp_check_as_path, NULL },
117 141
  { "next_hop", 4, BAF_TRANSITIVE, EAF_TYPE_IP_ADDRESS, 1,			/* BA_NEXT_HOP */
118 142
    bgp_check_next_hop, NULL },
119 143
  { "med", 4, BAF_OPTIONAL, EAF_TYPE_INT, 0,					/* BA_MULTI_EXIT_DISC */
......
122 146
    NULL, NULL },
123 147
  { "atomic_aggr", 0, BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,			/* BA_ATOMIC_AGGR */
124 148
    NULL, NULL },
125
  { "aggregator", 6, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,		/* BA_AGGREGATOR */
126
    NULL, NULL },
149
  { "aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,	/* BA_AGGREGATOR */
150
    bgp_check_aggregator, NULL },
127 151
  { "community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_INT_SET, 1,	/* BA_COMMUNITY */
128 152
    NULL, NULL },
129 153
  { NULL, },									/* BA_ORIGINATOR_ID */
......
135 159
    bgp_check_reach_nlri, NULL },
136 160
  { "mp_unreach_nlri", -1, BAF_OPTIONAL, EAF_TYPE_OPAQUE, 1,			/* BA_MP_UNREACH_NLRI */
137 161
    bgp_check_unreach_nlri, NULL },
162
  { NULL, },									/* BA_EXTENDED_COMM */
163
  { "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,		/* BA_AS4_PATH */
164
    bgp_check_as4_path, NULL },
165
  { "as4_aggregator", 8, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,	/* BA_AS4_PATH */
166
    NULL, NULL }
138 167
};
139 168

  
169
/* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH because
170
 * EAF_TYPE_AS_PATH is supposed to have different format (2 or 4 B for each ASN)
171
 * depending on bgp_as4_support variable.
172
 */
173

  
140 174
#define ATTR_KNOWN(code) ((code) < ARRAY_SIZE(bgp_attr_table) && bgp_attr_table[code].name)
141 175

  
142 176
static byte *
......
170 204
  return bgp_set_attr(a->attrs, pool, attr, val);
171 205
}
172 206

  
207
static int
208
bgp_encode_attr_hdr(byte *dst, unsigned int flags, unsigned code, int len)
209
{
210
  int wlen;
211

  
212
  DBG("\tAttribute %02x (%d bytes, flags %02x)\n", code, len, flags);
213

  
214
  if (len < 256)
215
    {
216
      *dst++ = flags;
217
      *dst++ = code;
218
      *dst++ = len;
219
      wlen = 3;
220
    }
221
  else
222
    {
223
      *dst++ = flags | BAF_EXT_LEN;
224
      *dst++ = code;
225
      put_u16(dst, len);
226
      wlen = 4;
227
    }
228

  
229
  return wlen;
230
}
231

  
232
static void
233
aggregator_convert_to_old(struct adata *aggr, byte *dst, int *new_used)
234
{
235
  byte *src = aggr->data;
236
  *new_used = 0;
237

  
238
  u32 as = get_u32(src);
239
  if (as > 0xFFFF) 
240
    {
241
      as = AS_TRANS;
242
      *new_used = 1;
243
    }
244
  put_u16(dst, as);
245

  
246
  /* Copy IPv4 address */
247
  memcpy(dst + 2, src + 4, 4);
248
}
249

  
250
static void
251
aggregator_convert_to_new(struct adata *aggr, byte *dst)
252
{
253
  byte *src = aggr->data;
254

  
255
  u32 as   = get_u16(src);
256
  put_u32(dst, as);
257

  
258
  /* Copy IPv4 address */
259
  memcpy(dst + 4, src + 2, 4);
260
}
261

  
262
static int
263
bgp_get_attr_len(eattr *a)
264
{
265
  int len;
266
  if (ATTR_KNOWN(EA_ID(a->id)))
267
    {
268
      int code = EA_ID(a->id);
269
      struct attr_desc *desc = &bgp_attr_table[code];
270
      len = desc->expected_length;
271
      if (len < 0)
272
	{
273
	  ASSERT(!(a->type & EAF_EMBEDDED));
274
	  len = a->u.ptr->length;
275
	}
276
    }
277
  else
278
    {
279
      ASSERT((a->type & EAF_TYPE_MASK) == EAF_TYPE_OPAQUE);
280
      len = a->u.ptr->length;
281
    }
282
  
283
  return len;
284
}
285

  
286
#define ADVANCE(w, r, l) do { r -= l; w += l; } while (0)
287

  
173 288
/**
174 289
 * bgp_encode_attrs - encode BGP attributes
290
 * @p: BGP instance
175 291
 * @w: buffer
176 292
 * @attrs: a list of extended attributes
177 293
 * @remains: remaining space in the buffer
......
182 298
 * Result: Length of the attribute block generated.
183 299
 */
184 300
unsigned int
185
bgp_encode_attrs(byte *w, ea_list *attrs, int remains)
301
bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
186 302
{
187 303
  unsigned int i, code, flags;
188 304
  byte *start = w;
189
  int len;
305
  int len, rv;
190 306

  
191 307
  for(i=0; i<attrs->count; i++)
192 308
    {
......
198 314
      if (code == BA_NEXT_HOP)
199 315
	continue;
200 316
#endif
201
      flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
202
      if (ATTR_KNOWN(code))
203
	{
204
	  struct attr_desc *desc = &bgp_attr_table[code];
205
	  len = desc->expected_length;
206
	  if (len < 0)
207
	    {
208
	      ASSERT(!(a->type & EAF_EMBEDDED));
209
	      len = a->u.ptr->length;
210
	    }
211
	}
212
      else
317

  
318
      /* When AS4-aware BGP speaker is talking to non-AS4-aware BGP speaker,
319
       * we have to convert our 4B AS_PATH to 2B AS_PATH and send our AS_PATH 
320
       * as optional AS4_PATH attribute.
321
       */
322
      if ((code == BA_AS_PATH) && bgp_as4_support && (! p->as4_support))
213 323
	{
214
	  ASSERT((a->type & EAF_TYPE_MASK) == EAF_TYPE_OPAQUE);
215 324
	  len = a->u.ptr->length;
325

  
326
	  if (remains < (len + 4))
327
	    goto err_no_buffer;
328

  
329
	  /* Using temporary buffer because don't know a length of created attr
330
	   * and therefore a length of a header. Perhaps i should better always
331
	   * use BAF_EXT_LEN. */
332
	  
333
	  byte buf[len];
334
	  int new_used;
335
	  int nl = as_path_convert_to_old(a->u.ptr, buf, &new_used);
336

  
337
	  rv = bgp_encode_attr_hdr(w, BAF_TRANSITIVE, BA_AS_PATH, nl);
338
	  ADVANCE(w, remains, rv);
339
	  memcpy(w, buf, nl);
340
	  ADVANCE(w, remains, nl);
341

  
342
	  if (! new_used)
343
	    continue;
344

  
345
	  if (remains < (len + 4))
346
	    goto err_no_buffer;
347

  
348
	  /* We should discard AS_CONFED_SEQUENCE or AS_CONFED_SET path segments 
349
	   * here but we don't support confederations and such paths we already
350
	   * discarded in bgp_check_as_path().
351
	   */
352

  
353
	  rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AS4_PATH, len);
354
	  ADVANCE(w, remains, rv);
355
	  memcpy(w, a->u.ptr->data, len);
356
	  ADVANCE(w, remains, len);
357

  
358
	  continue;
216 359
	}
217
      DBG("\tAttribute %02x (type %02x, %d bytes, flags %02x)\n", code, a->type, len, flags);
218
      if (remains < len + 4)
219
	{
220
	  log(L_ERR "BGP: attribute list too long, ignoring the remaining attributes");
221
	  break;
222
	}
223
      if (len < 256)
224
	{
225
	  *w++ = flags;
226
	  *w++ = code;
227
	  *w++ = len;
228
	  remains -= 3;
229
	}
230
      else
360

  
361
      /* The same issue with AGGREGATOR attribute */
362
      if ((code == BA_AGGREGATOR) && bgp_as4_support && (! p->as4_support))
231 363
	{
232
	  *w++ = flags | BAF_EXT_LEN;
233
	  *w++ = code;
234
	  put_u16(w, len);
235
	  w += 2;
236
	  remains -= 4;
364
	  int new_used;
365

  
366
	  len = 6;
367
	  if (remains < (len + 3))
368
	    goto err_no_buffer;
369

  
370
	  rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AGGREGATOR, len);
371
	  ADVANCE(w, remains, rv);
372
	  aggregator_convert_to_old(a->u.ptr, w, &new_used);
373
	  ADVANCE(w, remains, len);
374

  
375
	  if (! new_used)
376
	    continue;
377

  
378
	  len = 8;
379
	  if (remains < (len + 3))
380
	    goto err_no_buffer;
381

  
382
	  rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AS4_AGGREGATOR, len);
383
	  ADVANCE(w, remains, rv);
384
	  memcpy(w, a->u.ptr->data, len);
385
	  ADVANCE(w, remains, len);
386

  
387
	  continue;
237 388
	}
389

  
390
      /* Standard path continues here ... */
391

  
392
      flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
393
      len = bgp_get_attr_len(a);
394

  
395
      if (remains < len + 4)
396
	goto err_no_buffer;
397

  
398
      rv = bgp_encode_attr_hdr(w, flags, code, len);
399
      ADVANCE(w, remains, rv);
400

  
238 401
      switch (a->type & EAF_TYPE_MASK)
239 402
	{
240 403
	case EAF_TYPE_INT:
......
266 429
	default:
267 430
	  bug("bgp_encode_attrs: unknown attribute type %02x", a->type);
268 431
	}
269
      remains -= len;
270
      w += len;
432
      ADVANCE(w, remains, len);
271 433
    }
272 434
  return w - start;
435

  
436
 err_no_buffer:
437
  log(L_ERR "BGP: attribute list too long, ignoring the remaining attributes");
438
  return w - start;
273 439
}
274 440

  
275 441
static void
......
566 732
    bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, 0);
567 733
  else
568 734
    {
569
      z = bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, 4);
735
      z = bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, bgp_as4_support ? 6 : 4);
570 736
      z[0] = AS_PATH_SEQUENCE;
571 737
      z[1] = 1;				/* 1 AS */
572
      put_u16(z+2, p->local_as);
738

  
739
      if (bgp_as4_support)
740
	put_u32(z+2, p->local_as);
741
      else
742
	put_u16(z+2, p->local_as);
573 743
    }
574 744

  
575 745
  z = bgp_set_attr(ea->attrs+2, pool, BA_NEXT_HOP, sizeof(ip_addr));
......
670 840
    {
671 841
      x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
672 842
      y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
673
      n = x ? as_path_getlen(x->u.ptr) : 100000;
674
      o = y ? as_path_getlen(y->u.ptr) : 100000;
843
      n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
844
      o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
675 845
      if (n < o)
676 846
	return 1;
677 847
      if (n > o)
......
712 882
static int
713 883
bgp_path_loopy(struct bgp_proto *p, eattr *a)
714 884
{
715
  byte *path = a->u.ptr->data;
716
  int len = a->u.ptr->length;
717
  int i, n;
885
  return as_path_is_member(a->u.ptr, p->local_as);
886
}
887

  
888

  
889
static struct adata *
890
bgp_aggregator_convert_to_new(struct adata *old, struct linpool *pool)
891
{
892
  struct adata *newa = lp_alloc(pool, sizeof(struct adata) + 8);
893
  newa->length = 8;
894
  aggregator_convert_to_new(old, newa->data);
895
  return newa;
896
}
897

  
898

  
899
/* Take last req_as ASNs from path old2 (in 2B format), convert to 4B format
900
 * and append path old4 (in 4B format).
901
 */
902
static struct adata *
903
bgp_merge_as_paths(struct adata *old2, struct adata *old4, int req_as, struct linpool *pool)
904
{
905
  byte buf[old2->length * 2];
906

  
907
  int ol = as_path_convert_to_new(old2, buf, req_as);
908
  int nl = ol + (old4 ? old4->length : 0);
718 909

  
719
  while (len > 0)
910
  struct adata *newa = lp_alloc(pool, sizeof(struct adata) + nl);
911
  newa->length = nl;
912
  memcpy(newa->data, buf, ol);
913
  if (old4) memcpy(newa->data + ol, old4->data, old4->length);
914

  
915
  return newa;
916
}
917

  
918

  
919
/* Reconstruct 4B AS_PATH and AGGREGATOR according to RFC4893 4.2.3 */
920
static void
921
bgp_reconstruct_4b_atts(struct bgp_proto *p, rta *a, struct linpool *pool)
922
{
923
  eattr *p2 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
924
  eattr *p4 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS4_PATH));
925
  eattr *a2 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AGGREGATOR));
926
  eattr *a4 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS4_AGGREGATOR));
927

  
928
  if (a2)
720 929
    {
721
      n = path[1];
722
      len -= 2 + 2*n;
723
      path += 2;
724
      for(i=0; i<n; i++)
930
      u32 a2_as = get_u16(a2->u.ptr->data);
931

  
932
      if (a4)
725 933
	{
726
	  if (get_u16(path) == p->local_as)
727
	    return 1;
728
	  path += 2;
934
	  if (a2_as != AS_TRANS)
935
	    {
936
	      /* Routes were aggregated by old router and therefore AS4_PATH
937
	       * and AS4_AGGREGATOR is invalid
938
	       *
939
	       * Convert AS_PATH and AGGREGATOR to 4B format and finish.
940
	       */
941

  
942
	      a2->u.ptr = bgp_aggregator_convert_to_new(a2->u.ptr, pool);
943
	      p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, NULL, AS_PATH_MAXLEN, pool);
944

  
945
	      return;
946
	    }
947
	  else
948
	    {
949
	      /* Common case, use AS4_AGGREGATOR attribute */
950
	      a2->u.ptr = a4->u.ptr;
951
	    }
952
	}
953
      else
954
	{
955
	  /* Common case, use old AGGREGATOR attribute */
956
	  a2->u.ptr = bgp_aggregator_convert_to_new(a2->u.ptr, pool);
957

  
958
	  if (a2_as == AS_TRANS)
959
	    log(L_WARN "BGP: AGGREGATOR attribute contain AS_TRANS, but AS4_AGGREGATOR is missing");
729 960
	}
730 961
    }
731
  return 0;
962
  else
963
    if (a4)
964
      log(L_WARN "BGP: AS4_AGGREGATOR attribute received, but AGGREGATOR attribute is missing");
965

  
966
  int p2_len = as_path_getlen(p2->u.ptr);
967
  int p4_len = p4 ? as_path_getlen(p4->u.ptr) : AS_PATH_MAXLEN;
968

  
969
  if (p2_len < p4_len)
970
    p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, NULL, AS_PATH_MAXLEN, pool);
971
  else
972
    p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, p4->u.ptr, p2_len - p4_len, pool);
973

  
974
}
975

  
976
static void
977
bgp_remove_as4_attrs(struct bgp_proto *p, rta *a)
978
{
979
  unsigned id1 = EA_CODE(EAP_BGP, BA_AS4_PATH);
980
  unsigned id2 = EA_CODE(EAP_BGP, BA_AS4_AGGREGATOR);
981
  ea_list **el = &(a->eattrs);
982

  
983
  /* We know that ea_lists constructed in bgp_decode_attrs have one attribute per ea_list struct */
984
  while (*el != NULL)
985
    {
986
      unsigned fid = (*el)->attrs[0].id;
987

  
988
      if ((fid == id1) || (fid == id2))
989
	{
990
	  *el = (*el)->next;
991
	  if (p->as4_support)
992
	    log(L_WARN "BGP: Unexpected AS4_* attributes received");
993
	}
994
      else
995
	el = &((*el)->next);
996
    }
732 997
}
733 998

  
734 999
/**
......
883 1148
	    }
884 1149
	}
885 1150
    }
1151
  
1152
  /* When receiving attributes from non-AS4-aware BGP speaker,
1153
   * we have to reconstruct 4B AS_PATH and AGGREGATOR attributes
1154
   */
1155
  if (bgp_as4_support && (! bgp->as4_support))
1156
    bgp_reconstruct_4b_atts(bgp, a, pool);
1157

  
1158
  if (bgp_as4_support)
1159
    bgp_remove_as4_attrs(bgp, a);
886 1160

  
887 1161
  /* If the AS path attribute contains our AS, reject the routes */
888 1162
  e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
......
945 1219
{
946 1220
  eattr *p = ea_find(attrs, EA_CODE(EAP_BGP, BA_AS_PATH));
947 1221
  eattr *o = ea_find(attrs, EA_CODE(EAP_BGP, BA_ORIGIN));
948
  int origas;
1222
  u32 origas;
949 1223

  
950 1224
  buf += bsprintf(buf, " (%d) [", e->pref);
951
  if (p && (origas = as_path_get_first(p->u.ptr)) >= 0)
952
    buf += bsprintf(buf, "AS%d", origas);
1225
  if (p && as_path_get_first(p->u.ptr, &origas))
1226
    buf += bsprintf(buf, "AS%u", origas);
953 1227
  if (o)
954 1228
    buf += bsprintf(buf, "%c", "ie?"[o->u.data]);
955 1229
  strcpy(buf, "]");
proto/bgp/bgp.c
76 76
static void bgp_initiate(struct bgp_proto *p);
77 77
static void bgp_setup_listen_sk(void);
78 78

  
79

  
79 80
static void
80 81
bgp_close(struct bgp_proto *p UNUSED)
81 82
{
......
611 612
    cf_error("Local AS number must be set");
612 613
  if (!c->remote_as)
613 614
    cf_error("Neighbor must be configured");
615
  if (!bgp_as4_support && (c->local_as > 0xFFFF))
616
    cf_error("Local AS number out of range");
617
  if (!bgp_as4_support && (c->remote_as > 0xFFFF))
618
    cf_error("Neighbor AS number out of range");
614 619
}
615 620

  
616 621
static void
proto/bgp/bgp.h
16 16

  
17 17
struct bgp_config {
18 18
  struct proto_config c;
19
  unsigned int local_as, remote_as;
19
  u32 local_as, remote_as;
20 20
  ip_addr remote_ip;
21 21
  int multihop;				/* Number of hops if multihop */
22 22
  ip_addr multihop_via;			/* Multihop: address to route to */
......
47 47
  byte *notify_data;
48 48
  int error_flag;			/* Error state, ignore all input */
49 49
  int primary;				/* This connection is primary */
50
  u32 advertised_as;			/* Temporary value for AS number received */
50 51
  unsigned hold_time, keepalive_time;	/* Times calculated from my and neighbor's requirements */
51 52
};
52 53

  
53 54
struct bgp_proto {
54 55
  struct proto p;
55 56
  struct bgp_config *cf;		/* Shortcut to BGP configuration */
56
  unsigned local_as, remote_as;
57
  u32 local_as, remote_as;
57 58
  int is_internal;			/* Internal BGP connection (local_as == remote_as) */
59
  int as4_support;			/* Peer supports 4B AS numbers [RFC4893] */
58 60
  u32 local_id;				/* BGP identifier of this router */
59 61
  u32 remote_id;			/* BGP identifier of the neighbor */
60 62
  struct bgp_conn *conn;		/* Connection we have established */
......
100 102

  
101 103
extern struct linpool *bgp_linpool;
102 104

  
105
extern int bgp_as4_support;
106

  
107

  
103 108
void bgp_start_timer(struct timer *t, int value);
104 109
void bgp_check(struct bgp_config *c);
105 110
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
......
122 127
void bgp_rt_notify(struct proto *, struct network *, struct rte *, struct rte *, struct ea_list *);
123 128
int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *);
124 129
void bgp_attr_init(struct bgp_proto *);
125
unsigned int bgp_encode_attrs(byte *w, struct ea_list *attrs, int remains);
130
unsigned int bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains);
126 131
void bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck);
127 132
void bgp_get_route_info(struct rte *, byte *buf, struct ea_list *attrs);
128 133

  
......
165 170
#define BA_MP_REACH_NLRI	0x0e	/* [RFC2283] */
166 171
#define BA_MP_UNREACH_NLRI	0x0f
167 172
#define BA_EXTENDED_COMM	0x10	/* draft-ramachandra-bgp-ext-communities */
173
#define BA_AS4_PATH             0x11    /* [RFC4893] */
174
#define BA_AS4_AGGREGATOR       0x12
168 175

  
169 176
/* BGP states */
170 177

  
proto/bgp/config.Y
44 44
bgp_proto:
45 45
   bgp_proto_start proto_name '{'
46 46
 | bgp_proto proto_item ';'
47
 | bgp_proto LOCAL AS expr ';' {
48
     if ($4 < 0 || $4 > 65535) cf_error("AS number out of range");
49
     BGP_CFG->local_as = $4;
50
   }
47
 | bgp_proto LOCAL AS expr ';' { BGP_CFG->local_as = $4; }
51 48
 | bgp_proto NEIGHBOR ipa AS expr ';' {
52
     if ($5 < 0 || $5 > 65535) cf_error("AS number out of range");
49
     if (ipa_nonzero(BGP_CFG->remote_ip)) cf_error("Only one neighbor per BGP instance is allowed");
50

  
53 51
     BGP_CFG->remote_ip = $3;
54 52
     BGP_CFG->remote_as = $5;
55 53
   }
proto/bgp/packets.c
12 12
#include "nest/iface.h"
13 13
#include "nest/protocol.h"
14 14
#include "nest/route.h"
15
#include "nest/attrs.h"
15 16
#include "conf/conf.h"
16 17
#include "lib/unaligned.h"
17 18
#include "lib/socket.h"
......
30 31
  return buf + 2 + conn->notify_size;
31 32
}
32 33

  
34
#ifdef IPV6
35
static byte *
36
bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf)
37
{
38
  *buf++ = 1;		/* Capability 1: Multiprotocol extensions */
39
  *buf++ = 4;		/* Capability data length */
40
  *buf++ = 0;		/* We support AF IPv6 */
41
  *buf++ = BGP_AF_IPV6;
42
  *buf++ = 0;		/* RFU */
43
  *buf++ = 1;		/* and SAFI 1 */
44
  return buf;
45
}
46
#endif
47

  
48
static byte *
49
bgp_put_cap_as4(struct bgp_conn *conn, byte *buf)
50
{
51
  *buf++ = 65;		/* Capability 65: Support for 4-octet AS number */
52
  *buf++ = 4;		/* Capability data length */
53
  put_u32(buf, conn->bgp->local_as);
54
  return buf + 4;
55
}
56

  
33 57
static byte *
34 58
bgp_create_open(struct bgp_conn *conn, byte *buf)
35 59
{
36 60
  struct bgp_proto *p = conn->bgp;
61
  byte *cap;
62
  int cap_len;
37 63

  
38 64
  BGP_TRACE(D_PACKETS, "Sending OPEN(ver=%d,as=%d,hold=%d,id=%08x)",
39 65
	    BGP_VERSION, p->local_as, p->cf->hold_time, p->local_id);
40 66
  buf[0] = BGP_VERSION;
41
  put_u16(buf+1, p->local_as);
67
  put_u16(buf+1, (p->local_as < 0xFFFF) ? p->local_as : AS_TRANS);
42 68
  put_u16(buf+3, p->cf->hold_time);
43 69
  put_u32(buf+5, p->local_id);
44
#ifndef IPV6
45
  buf[9] = 0;				/* No optional parameters */
46
  return buf+10;
47
#else
48
  buf += 9;
49
  *buf++ = 8;		/* Optional params len */
50
  *buf++ = 2;		/* Option: Capability list */
51
  *buf++ = 6;		/* Option length */
52
  *buf++ = 1;		/* Capability 1: Multiprotocol extensions */
53
  *buf++ = 4;		/* Capability data length */
54
  *buf++ = 0;		/* We support AF IPv6 */
55
  *buf++ = BGP_AF_IPV6;
56
  *buf++ = 0;		/* RFU */
57
  *buf++ = 1;		/* and SAFI 1 */
58
  return buf;
70
  /* Skipped 3 B for length field and Capabilities parameter header */
71
  cap = buf + 12;
72

  
73
#ifdef IPV6
74
  cap = bgp_put_cap_ipv6(conn, cap);
59 75
#endif
76
  if (bgp_as4_support)
77
    cap = bgp_put_cap_as4(conn, cap);
78

  
79
  cap_len = cap - buf - 12;
80
  if (cap_len > 0)
81
    {
82
      buf[9]  = cap_len + 2;	/* Optional params len */
83
      buf[10] = 2;		/* Option: Capability list */
84
      buf[11] = cap_len;	/* Option length */
85
      return cap;
86
    }
87
  else
88
    {
89
      buf[9] = 0;		/* No optional parameters */
90
      return buf + 10;
91
    }
60 92
}
61 93

  
62 94
static unsigned int
......
118 150
	      continue;
119 151
	    }
120 152
	  DBG("Processing bucket %p\n", buck);
121
	  a_size = bgp_encode_attrs(w+2, buck->eattrs, 1024);
153
	  a_size = bgp_encode_attrs(p, w+2, buck->eattrs, 1024);
122 154
	  put_u16(w, a_size);
123 155
	  w += a_size + 2;
124 156
	  r_size = bgp_encode_prefixes(p, w, buck, remains - a_size);
......
166 198
      *tmp++ = BGP_AF_IPV6;
167 199
      *tmp++ = 1;
168 200
      ea->attrs[0].u.ptr->length = bgp_encode_prefixes(p, tmp, buck, remains-11);
169
      size = bgp_encode_attrs(w, ea, remains);
201
      size = bgp_encode_attrs(p, w, ea, remains);
170 202
      w += size;
171 203
      remains -= size;
172 204
    }
......
183 215
	      continue;
184 216
	    }
185 217
	  DBG("Processing bucket %p\n", buck);
186
	  size = bgp_encode_attrs(w, buck->eattrs, 1024);
218
	  size = bgp_encode_attrs(p, w, buck->eattrs, 1024);
187 219
	  w += size;
188 220
	  remains -= size;
189 221
	  tstart = tmp = bgp_attach_attr(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
......
230 262
	  *tmp++ = 0;			/* No SNPA information */
231 263
	  tmp += bgp_encode_prefixes(p, tmp, buck, remains - (8+3+32+1));
232 264
	  ea->attrs[0].u.ptr->length = tmp - tstart;
233
	  w += bgp_encode_attrs(w, ea, remains);
265
	  w += bgp_encode_attrs(p, w, ea, remains);
234 266
	  break;
235 267
	}
236 268
    }
......
353 385
    ;
354 386
}
355 387

  
388
/* Capatibility negotiation as per RFC 2842 */
389

  
390
void
391
bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
392
{
393
  struct bgp_proto *p = conn->bgp;
394
  int cl;
395
  u32 as;
396

  
397
  while (len > 0)
398
    {
399
      if (len < 2 || len < 2 + opt[1])
400
	goto err;
401
      
402
      cl = opt[1];
403

  
404
      switch (opt[0])
405
	{
406
	case 65:
407
	  if (cl != 4)
408
	    goto err;
409
	  p->as4_support = 1;
410
	  if (bgp_as4_support)
411
	    conn->advertised_as = get_u32(opt + 2);
412
	  break;
413

  
414
	  /* We can safely ignore all other capabilities */
415
	}
416
      len -= 2 + cl;
417
      opt += 2 + cl;
418
    }
419
  return;
420

  
421
    err:
422
  bgp_error(conn, 2, 0, NULL, 0);
423
  return;
424
}
425

  
356 426
static int
357 427
bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
358 428
{
429
  int ol;
430

  
359 431
  while (len > 0)
360 432
    {
361 433
      if (len < 2 || len < 2 + opt[1])
......
369 441
	DBG("\n");
370 442
      }
371 443
#endif
444

  
445
      ol = opt[1];
372 446
      switch (opt[0])
373 447
	{
374 448
	case 2:
375
	  /* Capatibility negotiation as per RFC 2842 */
376
	  /* We can safely ignore all capabilities announced */
449
	  bgp_parse_capabilities(conn, opt + 2, ol);
377 450
	  break;
451

  
378 452
	default:
379 453
	  /*
380 454
	   *  BGP specs don't tell us to send which option
......
382 456
	   *  to do so. Also, capability negotiation with
383 457
	   *  Cisco routers doesn't work without that.
384 458
	   */
385
	  bgp_error(conn, 2, 4, opt, opt[1]);
459
	  bgp_error(conn, 2, 4, opt, ol);
386 460
	  return 0;
387 461
	}
388
      len -= 2 + opt[1];
389
      opt += 2 + opt[1];
462
      len -= 2 + ol;
463
      opt += 2 + ol;
390 464
    }
391 465
  return 0;
392 466
}
......
397 471
  struct bgp_conn *other;
398 472
  struct bgp_proto *p = conn->bgp;
399 473
  struct bgp_config *cf = p->cf;
400
  unsigned as, hold;
474
  unsigned hold;
401 475
  u32 id;
402 476

  
403 477
  /* Check state */
......
409 483
    { bgp_error(conn, 1, 2, pkt+16, 2); return; }
410 484
  if (pkt[19] != BGP_VERSION)
411 485
    { bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
412
  as = get_u16(pkt+20);
486
  conn->advertised_as = get_u16(pkt+20);
413 487
  hold = get_u16(pkt+22);
414 488
  id = get_u32(pkt+24);
415
  BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", as, hold, id);
416
  if (cf->remote_as && as != p->remote_as)
417
    { bgp_error(conn, 2, 2, pkt+20, -2); return; }
418
  if (hold > 0 && hold < 3)
419
    { bgp_error(conn, 2, 6, pkt+22, 2); return; }
420
  p->remote_id = id;
489
  BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
490

  
491
  p->remote_id = id; // ???
421 492
  if (bgp_parse_options(conn, pkt+29, pkt[28]))
422 493
    return;
494

  
495
  if (hold > 0 && hold < 3)
496
    { bgp_error(conn, 2, 6, pkt+22, 2); return; }
497

  
423 498
  if (!id || id == 0xffffffff || id == p->local_id)
424 499
    { bgp_error(conn, 2, 3, pkt+24, -4); return; }
425 500

  
501

  
502
  if (conn->advertised_as != p->remote_as)
503
    {
504
      bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return;
505
    }
506

  
426 507
  /* Check the other connection */
427 508
  other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
428 509
  switch (other->state)
......
463 544
  else
464 545
    conn->hold_time = p->cf->hold_time;
465 546
  conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
466
  p->remote_as = as;
547
  // p->remote_as = conn->advertised_as;
467 548
  p->remote_id = id;
468 549
  DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x\n", conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id);
469 550

  
......
720 801
  { 2, 4, "Unsupported optional parameter" },
721 802
  { 2, 5, "Authentication failure" },
722 803
  { 2, 6, "Unacceptable hold time" },
723
  { 2, 7, "Required capability missing" }, /* capability negotiation draft */
804
  { 2, 7, "Required capability missing" }, /* [RFC3392] */
724 805
  { 3, 0, "Invalid UPDATE message" },
725 806
  { 3, 1, "Malformed attribute list" },
726 807
  { 3, 2, "Unrecognized well-known attribute" },

Also available in: Unified diff