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));
> 

Reply via email to