diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/bgp.c | 62 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 1 | ||||
-rw-r--r-- | proto/bgp/config.Y | 5 |
3 files changed, 52 insertions, 16 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 70c9b2f9..d26b4817 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -92,6 +92,8 @@ static int bgp_open(struct bgp_proto *p) { struct config *cfg = p->cf->c.global; + int errcode; + bgp_counter++; if (!bgp_listen_sk) @@ -100,10 +102,8 @@ bgp_open(struct bgp_proto *p) if (!bgp_listen_sk) { bgp_counter--; - p->p.disabled = 1; - bgp_store_error(p, NULL, BE_MISC, BEM_NO_SOCKET); - proto_notify_state(&p->p, PS_DOWN); - return -1; + errcode = BEM_NO_SOCKET; + goto err; } if (!bgp_linpool) @@ -115,14 +115,18 @@ bgp_open(struct bgp_proto *p) if (rv < 0) { bgp_close(p, 0); - p->p.disabled = 1; - bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_MD5); - proto_notify_state(&p->p, PS_DOWN); - return -1; + errcode = BEM_INVALID_MD5; + goto err; } } return 0; + +err: + p->p.disabled = 1; + bgp_store_error(p, NULL, BE_MISC, errcode); + proto_notify_state(&p->p, PS_DOWN); + return -1; } static void @@ -567,6 +571,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c { sock *s; struct bgp_conn *conn = &p->outgoing_conn; + int hops = p->cf->multihop ? : 1; DBG("BGP: Connecting\n"); s = sk_new(p->p.pool); @@ -574,7 +579,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c s->saddr = p->source_addr; s->daddr = p->cf->remote_ip; s->dport = BGP_PORT; - s->ttl = p->cf->multihop ? : 1; + s->ttl = p->cf->ttl_security ? 255 : hops; s->rbsize = BGP_RX_BUFFER_SIZE; s->tbsize = BGP_TX_BUFFER_SIZE; s->tos = IP_PREC_INTERNET_CONTROL; @@ -584,11 +589,25 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c bgp_setup_conn(p, conn); bgp_setup_sk(conn, s); bgp_conn_set_state(conn, BS_CONNECT); - if (sk_open(s)) + + if (sk_open(s) < 0) { bgp_sock_err(s, 0); return; } + + /* Set minimal receive TTL if needed */ + if (p->cf->ttl_security) + { + DBG("Setting minimum received TTL to %d", 256 - hops); + if (sk_set_min_ttl(s, 256 - hops) < 0) + { + log(L_ERR "TTL security configuration failed, closing session"); + bgp_sock_err(s, 0); + return; + } + } + DBG("BGP: Waiting for connect success\n"); bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time); } @@ -627,9 +646,22 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED) if (!acc) goto err; + int hops = p->cf->multihop ? : 1; + if (p->cf->ttl_security) + { + /* TTL security support */ + if ((sk_set_ttl(sk, 255) < 0) || + (sk_set_min_ttl(sk, 256 - hops) < 0)) + { + log(L_ERR "TTL security configuration failed, closing session"); + goto err; + } + } + else + sk_set_ttl(sk, hops); + bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); - sk_set_ttl(sk, p->cf->multihop ? : 1); bgp_send_open(&p->incoming_conn); return 0; } @@ -656,6 +688,7 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags) sock *s = sk_new(&root_pool); DBG("BGP: Creating listening socket\n"); s->type = SK_TCP_PASSIVE; + s->ttl = 255; s->saddr = addr; s->sport = port ? port : BGP_PORT; s->flags = flags ? 0 : SKF_V6ONLY; @@ -664,14 +697,15 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags) s->tbsize = BGP_TX_BUFFER_SIZE; s->rx_hook = bgp_incoming_connection; s->err_hook = bgp_listen_sock_err; - if (sk_open(s)) + + if (sk_open(s) < 0) { log(L_ERR "BGP: Unable to open listening socket"); rfree(s); return NULL; } - else - return s; + + return s; } static void diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 12478709..16e8ea89 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -20,6 +20,7 @@ struct bgp_config { u32 local_as, remote_as; ip_addr remote_ip; int multihop; /* Number of hops if multihop */ + int ttl_security; /* Enable TTL security [RFC5082] */ ip_addr source_addr; /* Source address to use */ int next_hop_self; /* Always set next hop to local IP address */ int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 93cc85f6..19d757a5 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, - TABLE, GATEWAY, DIRECT, RECURSIVE, MED) + TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY) CF_GRAMMAR @@ -71,7 +71,7 @@ bgp_proto: | bgp_proto CONNECT RETRY TIME expr ';' { BGP_CFG->connect_retry_time = $5; } | bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; } | bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; } - | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; } + | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); } | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; } | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; } | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; } @@ -98,6 +98,7 @@ bgp_proto: | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; } | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; } | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; } + | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; } ; CF_ADDTO(dynamic_attr, BGP_ORIGIN |