reads ok
Claudio Jeker(cje...@diehard.n-r-g.com) on 2020.04.23 10:04:15 +0200:
> local-address is one of those values that need to be set in some cases but
> is not very flexible to use. This diff tries to change this a bit.
>
> It allows to set the local-address for both IPv4 and IPv6 at the same time
> and also allows to unset a previously set local-address. For example:
>
> group IBGP {
> local-address 192.0.2.1
> local-address 2001:db8:abcd::1
>
> neighbor 192.0.2.2 { remote-as $AS }
> neighbor 2001:db8:abcd::2 { remote-as $AS }
>
> # reset the local-address for whatever reason
> neighbor 192.0.2.3 {
> no local-address
> remote-as $AS
> }
> }
>
> As usual setting a local-address on the neighbor will override the group
> config. I think for IBGP and multihop sessions this can simplify the
> config a fair bit. In my case this will collaps IPv4 and IPv6 specific
> groups back together since the only reason they are split is because of
> local-address.
>
> What do other bgpd user think?
> --
> :wq Claudio
>
> Index: bgpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
> retrieving revision 1.401
> diff -u -p -r1.401 bgpd.h
> --- bgpd.h 14 Feb 2020 13:54:31 -0000 1.401
> +++ bgpd.h 22 Apr 2020 15:50:46 -0000
> @@ -365,7 +365,8 @@ struct capabilities {
>
> struct peer_config {
> struct bgpd_addr remote_addr;
> - struct bgpd_addr local_addr;
> + struct bgpd_addr local_addr_v4;
> + struct bgpd_addr local_addr_v6;
> struct peer_auth auth;
> struct capabilities capabilities;
> char group[PEER_DESCR_LEN];
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
> retrieving revision 1.405
> diff -u -p -r1.405 parse.y
> --- parse.y 16 Mar 2020 14:47:30 -0000 1.405
> +++ parse.y 23 Apr 2020 07:51:25 -0000
> @@ -1260,8 +1260,27 @@ peeropts : REMOTEAS as4number {
> free($2);
> }
> | LOCALADDR address {
> - memcpy(&curpeer->conf.local_addr, &$2,
> - sizeof(curpeer->conf.local_addr));
> + if ($2.aid == AID_INET)
> + memcpy(&curpeer->conf.local_addr_v4, &$2,
> + sizeof(curpeer->conf.local_addr_v4));
> + else if ($2.aid == AID_INET6)
> + memcpy(&curpeer->conf.local_addr_v6, &$2,
> + sizeof(curpeer->conf.local_addr_v6));
> + else {
> + yyerror("Unsupported address family %s for "
> + "local-addr", aid2str($2.aid));
> + YYERROR;
> + }
> + }
> + | yesno LOCALADDR {
> + if ($1) {
> + yyerror("bad local-address definition");
> + YYERROR;
> + }
> + memset(&curpeer->conf.local_addr_v4, 0,
> + sizeof(curpeer->conf.local_addr_v4));
> + memset(&curpeer->conf.local_addr_v6, 0,
> + sizeof(curpeer->conf.local_addr_v6));
> }
> | MULTIHOP NUMBER {
> if ($2 < 2 || $2 > 255) {
> @@ -4176,11 +4195,17 @@ str2key(char *s, char *dest, size_t max_
> int
> neighbor_consistent(struct peer *p)
> {
> - /* local-address and peer's address: same address family */
> - if (p->conf.local_addr.aid &&
> - p->conf.local_addr.aid != p->conf.remote_addr.aid) {
> - yyerror("local-address and neighbor address "
> - "must be of the same address family");
> + struct bgpd_addr *local_addr;
> +
> + switch (p->conf.remote_addr.aid) {
> + case AID_INET:
> + local_addr = &p->conf.local_addr_v4;
> + break;
> + case AID_INET6:
> + local_addr = &p->conf.local_addr_v6;
> + break;
> + default:
> + yyerror("Bad address family for remote-addr");
> return (-1);
> }
>
> @@ -4189,7 +4214,7 @@ neighbor_consistent(struct peer *p)
> p->conf.auth.method == AUTH_IPSEC_IKE_AH ||
> p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
> p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
> - !p->conf.local_addr.aid) {
> + local_addr->aid == AID_UNSPEC) {
> yyerror("neighbors with any form of IPsec configured "
> "need local-address to be specified");
> return (-1);
> Index: pfkey.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/pfkey.c,v
> retrieving revision 1.60
> diff -u -p -r1.60 pfkey.c
> --- pfkey.c 1 Oct 2019 11:05:30 -0000 1.60
> +++ pfkey.c 22 Apr 2020 16:08:33 -0000
> @@ -55,6 +55,18 @@ int pfkey_send(int, uint8_t, uint8_t, ui
> pfkey_send(fd, satype, cmd, dir, from, to, \
> 0, 0, 0, NULL, 0, 0, NULL, sport, dport)
>
> +static struct bgpd_addr *
> +pfkey_localaddr(struct peer *p)
> +{
> + switch (p->conf.remote_addr.aid) {
> + case AID_INET:
> + return &p->conf.local_addr_v4;
> + case AID_INET6:
> + return &p->conf.local_addr_v6;
> + }
> + fatalx("Unknown AID in pfkey_localaddr");
> +}
> +
> int
> pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
> struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t spi,
> @@ -530,12 +542,12 @@ pfkey_md5sig_establish(struct peer *p)
> u_int32_t spi_out = 0;
> u_int32_t spi_in = 0;
>
> - if (pfkey_sa_add(&p->conf.local_addr, &p->conf.remote_addr,
> + if (pfkey_sa_add(pfkey_localaddr(p), &p->conf.remote_addr,
> p->conf.auth.md5key_len, p->conf.auth.md5key,
> &spi_out) == -1)
> goto fail;
>
> - if (pfkey_sa_add(&p->conf.remote_addr, &p->conf.local_addr,
> + if (pfkey_sa_add(&p->conf.remote_addr, pfkey_localaddr(p),
> p->conf.auth.md5key_len, p->conf.auth.md5key,
> &spi_in) == -1)
> goto fail;
> @@ -582,6 +594,7 @@ static int
> pfkey_ipsec_establish(struct peer *p)
> {
> uint8_t satype = SADB_SATYPE_ESP;
> + struct bgpd_addr *local_addr = pfkey_localaddr(p);
>
> /* cleanup first, unlike in the TCP MD5 case */
> if (p->auth.established) {
> @@ -601,7 +614,7 @@ pfkey_ipsec_establish(struct peer *p)
> satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
> SADB_SATYPE_ESP : SADB_SATYPE_AH;
> if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
> - &p->conf.local_addr, &p->conf.remote_addr,
> + local_addr, &p->conf.remote_addr,
> p->conf.auth.spi_out,
> p->conf.auth.auth_alg_out,
> p->conf.auth.auth_keylen_out,
> @@ -614,7 +627,7 @@ pfkey_ipsec_establish(struct peer *p)
> if (pfkey_reply(pfkey_fd, NULL) == -1)
> goto fail_key;
> if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
> - &p->conf.remote_addr, &p->conf.local_addr,
> + &p->conf.remote_addr, local_addr,
> p->conf.auth.spi_in,
> p->conf.auth.auth_alg_in,
> p->conf.auth.auth_keylen_in,
> @@ -632,25 +645,25 @@ pfkey_ipsec_establish(struct peer *p)
> }
>
> if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
> - &p->conf.local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
> + local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
> goto fail_flow;
> if (pfkey_reply(pfkey_fd, NULL) == -1)
> goto fail_flow;
>
> if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
> - &p->conf.local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
> + local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
> goto fail_flow;
> if (pfkey_reply(pfkey_fd, NULL) == -1)
> goto fail_flow;
>
> if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
> - &p->conf.remote_addr, &p->conf.local_addr, 0, BGP_PORT) == -1)
> + &p->conf.remote_addr, local_addr, 0, BGP_PORT) == -1)
> goto fail_flow;
> if (pfkey_reply(pfkey_fd, NULL) == -1)
> goto fail_flow;
>
> if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
> - &p->conf.remote_addr, &p->conf.local_addr, BGP_PORT, 0) == -1)
> + &p->conf.remote_addr, local_addr, BGP_PORT, 0) == -1)
> goto fail_flow;
> if (pfkey_reply(pfkey_fd, NULL) == -1)
> goto fail_flow;
> @@ -768,7 +781,7 @@ pfkey_establish(struct peer *p)
> * remote_addr cannot change, so no copy, SPI are
> * handled by the method specific functions.
> */
> - memcpy(&p->auth.local_addr, &p->conf.local_addr,
> + memcpy(&p->auth.local_addr, pfkey_localaddr(p),
> sizeof(p->auth.local_addr));
> p->auth.method = p->conf.auth.method;
>
> Index: printconf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
> retrieving revision 1.141
> diff -u -p -r1.141 printconf.c
> --- printconf.c 24 Jan 2020 05:44:05 -0000 1.141
> +++ printconf.c 22 Apr 2020 16:09:18 -0000
> @@ -608,8 +608,12 @@ print_peer(struct peer_config *p, struct
> printf("%s\tmultihop %u\n", c, p->distance);
> if (p->passive)
> printf("%s\tpassive\n", c);
> - if (p->local_addr.aid)
> - printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr));
> + if (p->local_addr_v4.aid)
> + printf("%s\tlocal-address %s\n", c,
> + log_addr(&p->local_addr_v4));
> + if (p->local_addr_v6.aid)
> + printf("%s\tlocal-address %s\n", c,
> + log_addr(&p->local_addr_v6));
> if (p->max_prefix) {
> printf("%s\tmax-prefix %u", c, p->max_prefix);
> if (p->max_prefix_restart)
> Index: session.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
> retrieving revision 1.399
> diff -u -p -r1.399 session.c
> --- session.c 12 Feb 2020 10:33:56 -0000 1.399
> +++ session.c 22 Apr 2020 15:54:22 -0000
> @@ -1039,6 +1039,7 @@ int
> session_connect(struct peer *peer)
> {
> struct sockaddr *sa;
> + struct bgpd_addr *bind_addr = NULL;
> socklen_t sa_len;
>
> /*
> @@ -1066,8 +1067,16 @@ session_connect(struct peer *peer)
> tcp_md5_set(peer->fd, peer);
> peer->wbuf.fd = peer->fd;
>
> - /* if update source is set we need to bind() */
> - if ((sa = addr2sa(&peer->conf.local_addr, 0, &sa_len)) != NULL) {
> + /* if local-address is set we need to bind() */
> + switch (peer->conf.remote_addr.aid) {
> + case AID_INET:
> + bind_addr = &peer->conf.local_addr_v4;
> + break;
> + case AID_INET6:
> + bind_addr = &peer->conf.local_addr_v6;
> + break;
> + }
> + if (bind_addr && (sa = addr2sa(bind_addr, 0, &sa_len)) != NULL) {
> if (bind(peer->fd, sa, sa_len) == -1) {
> log_peer_warn(&peer->conf, "session_connect bind");
> bgp_fsm(peer, EVNT_CON_OPENFAIL);
> Index: util.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
> retrieving revision 1.52
> diff -u -p -r1.52 util.c
> --- util.c 12 Feb 2020 10:33:56 -0000 1.52
> +++ util.c 22 Apr 2020 15:54:02 -0000
> @@ -844,7 +844,7 @@ addr2sa(struct bgpd_addr *addr, u_int16_
> struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
> struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
>
> - if (addr->aid == AID_UNSPEC)
> + if (addr == NULL || addr->aid == AID_UNSPEC)
> return (NULL);
>
> bzero(&ss, sizeof(ss));
>