}
+static inline int
+bgp_as_path_first_as_equal(const byte *data, uint len, u32 asn)
+{
+ return (len >= 6) &&
+ ((data[0] == AS_PATH_SEQUENCE) || (data[0] == AS_PATH_CONFED_SEQUENCE)) &&
+ (data[1] > 0) &&
+ (get_u32(data+2) == asn);
+}
+
static int
bgp_encode_as_path(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
{
{
struct bgp_proto *p = s->proto;
int as_length = s->as4_session ? 4 : 2;
+ int as_sets = p->cf->allow_as_sets;
int as_confed = p->cf->confederation && p->is_interior;
char err[128];
- if (!as_path_valid(data, len, as_length, as_confed, err, sizeof(err)))
+ if (!as_path_valid(data, len, as_length, as_sets, as_confed, err, sizeof(err)))
WITHDRAW("Malformed AS_PATH attribute - %s", err);
- /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
- if (p->is_interior && !p->is_internal &&
- ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
- WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
-
if (!s->as4_session)
{
/* Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer */
len = as_path_16to32(data, src, len);
}
+ /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
+ if (p->is_interior && !p->is_internal &&
+ ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
+ WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
+
+ /* Reject routes with first AS in AS_PATH not matching neighbor AS; RFC 4271 6.3 */
+ if (!p->is_internal && p->cf->enforce_first_as &&
+ !bgp_as_path_first_as_equal(data, len, p->remote_as))
+ WITHDRAW("Malformed AS_PATH attribute - %s", "First AS differs from neigbor AS");
+
bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len);
}
static void
bgp_export_ext_community(struct bgp_export_state *s, eattr *a)
{
- struct adata *ad = ec_set_del_nontrans(s->pool, a->u.ptr);
+ if (!s->proto->is_interior)
+ {
+ struct adata *ad = ec_set_del_nontrans(s->pool, a->u.ptr);
- if (ad->length == 0)
- UNSET(a);
+ if (ad->length == 0)
+ UNSET(a);
+
+ ec_set_sort_x(ad);
+ a->u.ptr = ad;
+ }
+ else
+ {
+ if (a->u.ptr->length == 0)
+ UNSET(a);
- ec_set_sort_x(ad);
- a->u.ptr = ad;
+ a->u.ptr = ec_set_sort(s->pool, a->u.ptr);
+ }
}
static void
static void
bgp_decode_as4_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
{
+ struct bgp_proto *p = s->proto;
+ int sets = p->cf->allow_as_sets;
+
char err[128];
if (s->as4_session)
if (len < 6)
DISCARD(BAD_LENGTH, "AS4_PATH", len);
- if (!as_path_valid(data, len, 4, 1, err, sizeof(err)))
+ if (!as_path_valid(data, len, 4, sets, 1, err, sizeof(err)))
DISCARD("Malformed AS4_PATH attribute - %s", err);
struct adata *a = lp_alloc_adata(s->pool, len);