summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/attrs.c44
-rw-r--r--proto/bgp/bgp.c2
-rw-r--r--proto/bgp/bgp.h5
-rw-r--r--proto/bgp/config.Y4
-rw-r--r--proto/bgp/packets.c29
5 files changed, 62 insertions, 22 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index b8371f32..0309c1f7 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -191,7 +191,7 @@ validate_as4_path(struct bgp_proto *p, struct adata *path)
}
static int
-bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a, int len)
+bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a UNUSED6, int len UNUSED6)
{
#ifdef IPV6
return IGNORE;
@@ -289,6 +289,12 @@ bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
return ((len % 8) == 0) ? 0 : WITHDRAW;
}
+static int
+bgp_check_large_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
+{
+ return ((len % 12) == 0) ? 0 : WITHDRAW;
+}
+
static struct attr_desc bgp_attr_table[] = {
{ NULL, -1, 0, 0, 0, /* Undefined */
@@ -325,7 +331,10 @@ static struct attr_desc bgp_attr_table[] = {
{ "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
NULL, NULL },
{ "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
- NULL, NULL }
+ NULL, NULL },
+ [BA_LARGE_COMMUNITY] =
+ { "large_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_LC_SET, 1,
+ bgp_check_large_community, NULL }
};
/* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH.
@@ -575,7 +584,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
len = bgp_get_attr_len(a);
/* Skip empty sets */
- if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET)) && (len == 0))
+ if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET) || (type == EAF_TYPE_LC_SET)) && (len == 0))
continue;
if (remains < len + 4)
@@ -601,6 +610,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
break;
}
case EAF_TYPE_INT_SET:
+ case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET:
{
u32 *z = int_set_get_data(a->u.ptr);
@@ -683,6 +693,25 @@ bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal)
qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec);
}
+static int
+bgp_compare_lc(const u32 *x, const u32 *y)
+{
+ if (x[0] != y[0])
+ return (x[0] > y[0]) ? 1 : -1;
+ if (x[1] != y[1])
+ return (x[1] > y[1]) ? 1 : -1;
+ if (x[2] != y[2])
+ return (x[2] > y[2]) ? 1 : -1;
+ return 0;
+}
+
+static inline void
+bgp_normalize_lc_set(u32 *dest, u32 *src, unsigned cnt)
+{
+ memcpy(dest, src, LCOMM_LENGTH * cnt);
+ qsort(dest, cnt, LCOMM_LENGTH, (int(*)(const void *, const void *)) bgp_compare_lc);
+}
+
static void
bgp_rehash_buckets(struct bgp_proto *p)
{
@@ -827,6 +856,14 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
d->u.ptr = z;
break;
}
+ case EAF_TYPE_LC_SET:
+ {
+ struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
+ z->length = d->u.ptr->length;
+ bgp_normalize_lc_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / LCOMM_LENGTH);
+ d->u.ptr = z;
+ break;
+ }
default: ;
}
d++;
@@ -1797,6 +1834,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, uint len, struct linpool *po
ipa_ntoh(*(ip_addr *)ad->data);
break;
case EAF_TYPE_INT_SET:
+ case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET:
{
u32 *z = (u32 *) ad->data;
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 0ae3db7b..cac5d4c4 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -807,7 +807,7 @@ bgp_find_proto(sock *sk)
* closes the new connection by sending a Notification message.
*/
static int
-bgp_incoming_connection(sock *sk, int dummy UNUSED)
+bgp_incoming_connection(sock *sk, uint dummy UNUSED)
{
struct bgp_proto *p;
int acc, hops;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index b1cca2d9..b4067f3a 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -191,7 +191,7 @@ struct bgp_bucket {
#define BGP_RX_BUFFER_EXT_SIZE 65535
#define BGP_TX_BUFFER_EXT_SIZE 65535
-static inline int bgp_max_packet_length(struct bgp_proto *p)
+static inline uint bgp_max_packet_length(struct bgp_proto *p)
{ return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; }
extern struct linpool *bgp_linpool;
@@ -268,7 +268,7 @@ void mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new
void bgp_schedule_packet(struct bgp_conn *conn, int type);
void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk);
-int bgp_rx(struct birdsock *sk, int size);
+int bgp_rx(struct birdsock *sk, uint size);
const char * bgp_error_dsc(unsigned code, unsigned subcode);
void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
@@ -308,6 +308,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define BA_EXT_COMMUNITY 0x10 /* [RFC4360] */
#define BA_AS4_PATH 0x11 /* [RFC4893] */
#define BA_AS4_AGGREGATOR 0x12
+#define BA_LARGE_COMMUNITY 0x20 /* [draft-ietf-idr-large-community] */
/* BGP connection states */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 33561bff..bdbb6007 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
- CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY)
+ CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY)
CF_GRAMMAR
@@ -153,6 +153,8 @@ CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST
{ $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); })
CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY
{ $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); })
+CF_ADDTO(dynamic_attr, BGP_LARGE_COMMUNITY
+ { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(EAP_BGP, BA_LARGE_COMMUNITY)); })
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 0cf38edf..3e816839 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -191,7 +191,7 @@ bgp_put_cap_gr1(struct bgp_proto *p, byte *buf)
}
static byte *
-bgp_put_cap_gr2(struct bgp_proto *p, byte *buf)
+bgp_put_cap_gr2(struct bgp_proto *p UNUSED, byte *buf)
{
*buf++ = 64; /* Capability 64: Support for graceful restart */
*buf++ = 2; /* Capability data length */
@@ -931,7 +931,7 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
}
static void
-bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
+bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_conn *other;
struct bgp_proto *p = conn->bgp;
@@ -944,7 +944,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
{ bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
/* Check message contents */
- if (len < 29 || len != 29 + pkt[28])
+ if (len < 29 || len != 29U + pkt[28])
{ bgp_error(conn, 1, 2, pkt+16, 2); return; }
if (pkt[19] != BGP_VERSION)
{ bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
@@ -1256,16 +1256,15 @@ bgp_do_rx_update(struct bgp_conn *conn,
#else /* IPv6 version */
#define DO_NLRI(name) \
- start = x = p->name##_start; \
+ x = p->name##_start; \
len = len0 = p->name##_len; \
if (len) \
{ \
if (len < 3) { err=9; goto done; } \
af = get_u16(x); \
- sub = x[2]; \
x += 3; \
len -= 3; \
- DBG("\tNLRI AF=%d sub=%d len=%d\n", af, sub, len);\
+ DBG("\tNLRI AF=%d sub=%d len=%d\n", af, x[-1], len);\
} \
else \
af = 0; \
@@ -1291,15 +1290,15 @@ bgp_attach_next_hop(rta *a0, byte *x)
static void
bgp_do_rx_update(struct bgp_conn *conn,
- byte *withdrawn, int withdrawn_len,
- byte *nlri, int nlri_len,
+ byte *withdrawn UNUSED, int withdrawn_len,
+ byte *nlri UNUSED, int nlri_len,
byte *attrs, int attr_len)
{
struct bgp_proto *p = conn->bgp;
struct rte_src *src = p->p.main_source;
- byte *start, *x;
+ byte *x;
int len, len0;
- unsigned af, sub;
+ unsigned af;
rta *a0, *a = NULL;
ip_addr prefix;
int pxlen, err = 0;
@@ -1375,11 +1374,11 @@ bgp_do_rx_update(struct bgp_conn *conn,
#endif
static void
-bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
+bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_proto *p = conn->bgp;
byte *withdrawn, *attrs, *nlri;
- int withdrawn_len, attr_len, nlri_len;
+ uint withdrawn_len, attr_len, nlri_len;
BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE");
@@ -1525,7 +1524,7 @@ bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned
}
static void
-bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
+bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_proto *p = conn->bgp;
if (len < 21)
@@ -1591,7 +1590,7 @@ bgp_rx_keepalive(struct bgp_conn *conn)
}
static void
-bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
+bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_proto *p = conn->bgp;
@@ -1680,7 +1679,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
* bgp_rx_packet().
*/
int
-bgp_rx(sock *sk, int size)
+bgp_rx(sock *sk, uint size)
{
struct bgp_conn *conn = sk->data;
struct bgp_proto *p = conn->bgp;