@@ -6,8 +6,8 @@ use crate::{
66 IO_TIMEOUT ,
77 clock:: ConnectionClock ,
88 connection:: {
9- BgpConnection , BgpConnector , BgpListener , ConnectionDirection ,
10- ConnectionId , ThreadState ,
9+ BgpConnection , BgpConnector , BgpListener , ConnectTarget ,
10+ ConnectionDirection , ConnectionId , ThreadState ,
1111 } ,
1212 error:: Error ,
1313 log:: { connection_log, connection_log_lite} ,
@@ -207,6 +207,7 @@ impl BgpListener<BgpConnectionTcp> for BgpListenerTcp {
207207 conn : & BgpConnectionTcp ,
208208 min_ttl : Option < u8 > ,
209209 md5_key : Option < String > ,
210+ _listen_port : std:: num:: NonZeroU16 ,
210211 ) -> Result < ( ) , Error > {
211212 let tcp_stream = lock ! ( conn. conn) ;
212213
@@ -230,7 +231,8 @@ impl BgpListener<BgpConnectionTcp> for BgpListenerTcp {
230231
231232 #[ cfg( target_os = "illumos" ) ]
232233 {
233- let local = get_md5_source_addrs ( conn. peer . ip ( ) ) ?;
234+ let local =
235+ get_md5_source_addrs ( conn. peer . ip ( ) , _listen_port. get ( ) ) ?;
234236 conn. manage_md5_associations (
235237 tcp_stream. as_raw_fd ( ) ,
236238 key,
@@ -258,12 +260,13 @@ pub struct BgpConnectorTcp;
258260
259261impl BgpConnector < BgpConnectionTcp > for BgpConnectorTcp {
260262 fn connect (
261- peer : SocketAddr ,
263+ addrs : ConnectTarget ,
262264 timeout : Duration ,
263265 log : Logger ,
264266 event_tx : Sender < FsmEvent < BgpConnectionTcp > > ,
265267 config : SessionInfo ,
266268 ) -> Result < JoinHandle < ( ) > , Error > {
269+ let peer = addrs. destination ;
267270 let s = create_outbound_socket ( peer, & log) ?;
268271
269272 // Apply MD5 authentication before connecting (Linux)
@@ -290,8 +293,15 @@ impl BgpConnector<BgpConnectionTcp> for BgpConnectorTcp {
290293 #[ cfg( target_os = "illumos" ) ]
291294 let md5_locals = if let Some ( key) = & config. md5_auth_key {
292295 Some (
293- setup_outbound_md5 ( s. as_raw_fd ( ) , key, peer. ip ( ) , peer, & log)
294- . map_err ( |e| {
296+ setup_outbound_md5 (
297+ s. as_raw_fd ( ) ,
298+ key,
299+ peer. ip ( ) ,
300+ peer,
301+ config. addr . listen_port . get ( ) ,
302+ & log,
303+ )
304+ . map_err ( |e| {
295305 connection_log_lite ! ( log,
296306 warn,
297307 "failed to apply MD5 auth for {peer}: {e}" ;
@@ -334,7 +344,7 @@ impl BgpConnector<BgpConnectionTcp> for BgpConnectorTcp {
334344 }
335345
336346 // Bind to source address/port if specified
337- if let Some ( src) = config . bind_addr {
347+ if let Some ( src) = addrs . source {
338348 let ba: socket2:: SockAddr = src. into ( ) ;
339349 if let Err ( e) = s. bind ( & ba) {
340350 connection_log_lite ! ( log,
@@ -1387,7 +1397,10 @@ fn source_address_select(dst: IpAddr) -> anyhow::Result<Vec<IpAddr>> {
13871397/// Helper function to select and validate MD5 source addresses.
13881398/// Eliminates duplication between inbound and outbound paths
13891399#[ cfg( target_os = "illumos" ) ]
1390- fn get_md5_source_addrs ( peer_ip : IpAddr ) -> Result < Vec < SocketAddr > , Error > {
1400+ fn get_md5_source_addrs (
1401+ peer_ip : IpAddr ,
1402+ local_port : u16 ,
1403+ ) -> Result < Vec < SocketAddr > , Error > {
13911404 let sources = source_address_select ( peer_ip)
13921405 . map_err ( |e| Error :: InvalidAddress ( e. to_string ( ) ) ) ?;
13931406
@@ -1399,7 +1412,7 @@ fn get_md5_source_addrs(peer_ip: IpAddr) -> Result<Vec<SocketAddr>, Error> {
13991412
14001413 Ok ( sources
14011414 . iter ( )
1402- . map ( |x| SocketAddr :: new ( * x, crate :: BGP_PORT . get ( ) ) )
1415+ . map ( |x| SocketAddr :: new ( * x, local_port ) )
14031416 . collect ( ) )
14041417}
14051418
@@ -1410,8 +1423,17 @@ fn any_port(mut s: SocketAddr) -> SocketAddr {
14101423 s
14111424}
14121425
1413- /// Generate all four bidirectional SA pairs for MD5 protection.
1414- /// Covers both directions of traffic with both port configurations
1426+ /// Generate PF_KEY TCP-MD5 selectors for both possible BGP TCP 4-tuples.
1427+ ///
1428+ /// `src` should use our BGP listening port. During outbound pre-connect setup
1429+ /// this comes from session configuration because the socket is not connected
1430+ /// yet; during inbound setup the dispatcher passes the same shared listen port
1431+ /// used by every session.
1432+ /// `dst` uses the peer's configured/listening port for outbound connections and
1433+ /// the peer's observed client endpoint for inbound connections.
1434+ ///
1435+ /// Port 0 is used as the PF_KEY wildcard for the side whose ephemeral client
1436+ /// port is not known.
14151437#[ cfg( target_os = "illumos" ) ]
14161438fn sa_set ( src : SocketAddr , dst : SocketAddr ) -> [ ( SocketAddr , SocketAddr ) ; 4 ] {
14171439 // There are two directions of traffic we have to cover with two port
@@ -1510,6 +1532,7 @@ fn setup_outbound_md5(
15101532 key : & str ,
15111533 peer_ip : IpAddr ,
15121534 peer : SocketAddr ,
1535+ local_port : u16 ,
15131536 logger : & Logger ,
15141537) -> Result < ( String , Vec < SocketAddr > ) , Error > {
15151538 let sources = source_address_select ( peer_ip) . map_err ( |e| {
@@ -1537,7 +1560,7 @@ fn setup_outbound_md5(
15371560
15381561 let local: Vec < SocketAddr > = sources
15391562 . iter ( )
1540- . map ( |x| SocketAddr :: new ( * x, crate :: BGP_PORT . get ( ) ) )
1563+ . map ( |x| SocketAddr :: new ( * x, local_port ) )
15411564 . collect ( ) ;
15421565
15431566 init_md5_associations ( fd, key, local. clone ( ) , peer) ?;
0 commit comments