Is there any interest in allowing "local-address $ip $ip6" and having the parser choose whichever of these addresses has the relevant af for a peer?
Mostly it allows prettier/shorter configs and slightly less complex templates if you generate them programmatically. For example if you have ibgp connections from loopbacks you might have either set local-address in each "neighbor" block or used something like: group "internal" { remote-as $foo local-address $LOOPBACK neighbor 10.0.0.1 { descr "r1-v4" } neighbor 10.0.0.2 { descr "r2-v4" } } group "internal-v6" { remote-as $foo local-address $LOOPBACK6 neighbor aaaa::1 { descr "r1-v6" } neighbor aaaa::2 { descr "r2-v6" } } With the diff below that can be collapsed to: group "internal" { remote-as $foo local-address $LOOPBACK $LOOPBACK6 neighbor 10.0.0.1 { descr "r1-v4" } neighbor aaaa::1 { descr "r1-v6" } neighbor 10.0.0.2 { descr "r2-v4" } neighbor aaaa::2 { descr "r2-v6" } } Earlier versions before I added memsets didn't work correctly with some combinations of overrides, I think I've covered all the possibilities now but might have missed something.. Index: bgpd.conf.5 =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v retrieving revision 1.169 diff -u -p -r1.169 bgpd.conf.5 --- bgpd.conf.5 18 Jun 2018 06:04:25 -0000 1.169 +++ bgpd.conf.5 29 Jun 2018 14:59:16 -0000 @@ -923,7 +923,7 @@ and .Xr bgpd 8 daemons on both sides, the session should be established. .Pp -.It Ic local-address Ar address +.It Ic local-address Ar address Op address When .Xr bgpd 8 initiates the TCP connection to the neighbor system, it normally does not @@ -933,6 +933,8 @@ If a is given, .Xr bgpd 8 binds to this address first. +If two addresses are given, one is used for IPv4 neighbors, +the other for IPv6 neighbors. .Pp .It Ic local-as Ar as-number Op Ar as-number Set the AS number sent to the remote system. Index: bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.320 diff -u -p -r1.320 bgpd.h --- bgpd.h 29 Jun 2018 11:45:50 -0000 1.320 +++ bgpd.h 29 Jun 2018 14:59:16 -0000 @@ -303,6 +303,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.323 diff -u -p -r1.323 parse.y --- parse.y 13 Jun 2018 09:44:59 -0000 1.323 +++ parse.y 29 Jun 2018 14:59:16 -0000 @@ -1045,7 +1045,18 @@ neighbor : { curpeer = new_peer(); } curpeer_filter[1], entry); curpeer_filter[0] = NULL; curpeer_filter[1] = NULL; - + if (!curpeer->conf.local_addr.aid) { + if (curpeer->conf.local_addr_v4.aid == + curpeer->conf.remote_addr.aid) { + memcpy(&curpeer->conf.local_addr, + &curpeer->conf.local_addr_v4, + sizeof(curpeer->conf.local_addr)); + } else { + memcpy(&curpeer->conf.local_addr, + &curpeer->conf.local_addr_v6, + sizeof(curpeer->conf.local_addr)); + } + } if (neighbor_consistent(curpeer) == -1) YYERROR; curpeer->next = peer_l; @@ -1133,6 +1144,30 @@ peeropts : REMOTEAS as4number { | LOCALADDR address { memcpy(&curpeer->conf.local_addr, &$2, sizeof(curpeer->conf.local_addr)); + 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)); + } + | LOCALADDR address address { + if($2.aid == $3.aid) { + yyerror("\"local-address addr addr\" requires " + "different address families"); + YYERROR; + } + memset(&curpeer->conf.local_addr, 0, + sizeof(curpeer->conf.local_addr)); + if($2.aid == AF_INET && $3.aid == AF_INET6) { + memcpy(&curpeer->conf.local_addr_v4, &$2, + sizeof(curpeer->conf.local_addr_v4)); + memcpy(&curpeer->conf.local_addr_v6, &$3, + sizeof(curpeer->conf.local_addr_v6)); + } else { + memcpy(&curpeer->conf.local_addr_v4, &$3, + sizeof(curpeer->conf.local_addr_v4)); + memcpy(&curpeer->conf.local_addr_v6, &$2, + sizeof(curpeer->conf.local_addr_v6)); + } } | MULTIHOP NUMBER { if ($2 < 2 || $2 > 255) {