Index: proto/bgp/bgp.c =================================================================== --- proto/bgp/bgp.c (revision 4980) +++ proto/bgp/bgp.c (working copy) @@ -574,7 +574,11 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect s->saddr = p->source_addr; s->daddr = p->cf->remote_ip; s->dport = BGP_PORT; - s->ttl = p->cf->multihop ? : 1; + /* TTL security support */ + if (p->cf->min_ttl > 0) + s->ttl = 255; + else + s->ttl = p->cf->multihop ? : 1; s->rbsize = BGP_RX_BUFFER_SIZE; s->tbsize = BGP_TX_BUFFER_SIZE; s->tos = IP_PREC_INTERNET_CONTROL; @@ -589,6 +593,17 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect bgp_sock_err(s, 0); return; } + /* Set minimal receive TTL if needed */ + if (p->cf->min_ttl > 0) + { + log(L_ERR "Setting minimum received TTL to %d", p->cf->min_ttl); + if (sk_set_min_ttl(s, p->cf->min_ttl) != 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); } @@ -629,7 +644,17 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); - sk_set_ttl(sk, p->cf->multihop ? : 1); + /* TTL security support */ + if (p->cf->min_ttl > 0) + { + if ((sk_set_ttl(sk, 255) != 0) || (sk_set_min_ttl(sk, p->cf->min_ttl) != 0)) + { + log(L_ERR "TTL security configuration failed, closing session"); + goto err; + } + } + else + sk_set_ttl(sk, p->cf->multihop ? : 1); bgp_send_open(&p->incoming_conn); return 0; } Index: proto/bgp/config.Y =================================================================== --- proto/bgp/config.Y (revision 4980) +++ proto/bgp/config.Y (working copy) @@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, 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) + GATEWAY, DIRECT, RECURSIVE, MED, TTL_SECURITY, HOPS) CF_GRAMMAR @@ -49,6 +49,7 @@ bgp_proto_start: proto_start BGP { BGP_CFG->advertise_ipv4 = 1; BGP_CFG->interpret_communities = 1; BGP_CFG->default_local_pref = 100; + BGP_CFG->min_ttl = 0; } ; @@ -98,6 +99,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 HOPS expr ';' { BGP_CFG->min_ttl = $4; } ; CF_ADDTO(dynamic_attr, BGP_ORIGIN Index: proto/bgp/bgp.h =================================================================== --- proto/bgp/bgp.h (revision 4980) +++ proto/bgp/bgp.h (working copy) @@ -20,6 +20,7 @@ struct bgp_config { u32 local_as, remote_as; ip_addr remote_ip; int multihop; /* Number of hops if multihop */ + int min_ttl; /* minimum TTL for TTL security */ 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_* */ Index: lib/socket.h =================================================================== --- lib/socket.h (revision 4980) +++ lib/socket.h (working copy) @@ -54,7 +54,8 @@ int sk_send(sock *, unsigned len); /* Send data, < int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */ void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */ void sk_dump_all(void); -int sk_set_ttl(sock *s, int ttl); /* Set TTL for given socket */ +int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */ +int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */ /* Add or remove security associations for given passive socket */ int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); Index: sysdep/linux/sysio.h =================================================================== --- sysdep/linux/sysio.h (revision 4980) +++ sysdep/linux/sysio.h (working copy) @@ -309,3 +309,37 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg */ #endif + +static int +sk_set_min_ttl4(sock *s, int ttl) +{ +#ifdef IP_MINTTL + if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) == -1) + { + log(L_ERR "sk_set_min_ttl4: setsockopt: %m"); + return -1; + } + + return 0; +#else + log(L_ERR "IP_MINTTL options is not supported by your kernel"); + return -1; +#endif +} + +static int +sk_set_min_ttl6(sock *s, int ttl) +{ +#ifdef IPV6_MINHOPCNT + if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCNT, &ttl, sizeof(ttl)) == -1) + { + log(L_ERR "sk_set_min_ttl6: setsockopt: %m"); + return -1; + } + + return 0; +#else + log(L_ERR "IPV6_MINHOPCNT options is not supported by your kernel"); + return -1; +#endif +} Index: sysdep/unix/io.c =================================================================== --- sysdep/unix/io.c (revision 4980) +++ sysdep/unix/io.c (working copy) @@ -805,7 +805,7 @@ bad: } /** - * sk_set_ttl - set TTL for given socket. + * sk_set_ttl - set transmit TTL for given socket. * @s: socket * @ttl: TTL value * @@ -828,7 +828,29 @@ sk_set_ttl(sock *s, int ttl) return (err ? -1 : 0); } +/** + * sk_set_min_ttl - set minimal accepted TTL for given socket. + * @s: socket + * @ttl: TTL value + * + * Can be used in TTL security implementation + * + * Result: 0 for success, -1 for an error. + */ +int +sk_set_min_ttl(sock *s, int ttl) +{ + int err; +#ifdef IPV6 + err = sk_set_min_ttl6(s, ttl); +#else + err = sk_set_min_ttl4(s, ttl); +#endif + + return err; +} + /** * sk_set_md5_auth - add / remove MD5 security association for given socket. * @s: socket Index: sysdep/bsd/sysio.h =================================================================== --- sysdep/bsd/sysio.h (revision 4980) +++ sysdep/bsd/sysio.h (working copy) @@ -237,3 +237,23 @@ sk_set_md5_auth_int(sock *s, sockaddr *sa, char *p return rv; } + +static int +sk_set_min_ttl4(sock *s, int ttl) +{ + if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) == -1) + { + log(L_ERR "sk_set_min_ttl4: setsockopt: %m"); + return -1; + } + + return 0; +} + +static int +sk_set_min_ttl6(sock *s, int ttl) +{ + log(L_ERR "sk_set_min_ttl6: not supported"); + return -1; +} +