mssql_browser/
browse_instance_dac.rs

1use super::error::*;
2use super::info::*;
3use super::socket::{UdpSocket, UdpSocketFactory};
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
5
6/// The CLNT_UCAST_DAC packet request is used to determine the TCP [RFC793] port on which the
7/// Microsoft SQL Server dedicated administrator connection (DAC) endpoint is listening.
8const CLNT_UCAST_DAC: u8 = 0x0F;
9
10/// The server responds to all client requests with an SVR_RESP.
11const SVR_RESP: u8 = 0x05;
12
13/// Gets DAC information about the given instance
14///
15/// # Arguments
16/// * `remote_addr` - The address of the remote host on which the instance is running.
17/// * `instance_name` - The name of the instance, must be less than `MAX_INSTANCE_NAME_LEN` characters.
18#[cfg(any(feature = "tokio", feature = "async-std"))]
19pub async fn browse_instance_dac(
20    remote_addr: IpAddr,
21    instance_name: &str,
22) -> Result<
23    DacInfo,
24    BrowserError<
25        <super::socket::DefaultSocketFactory as UdpSocketFactory>::Error,
26        <<super::socket::DefaultSocketFactory as UdpSocketFactory>::Socket as UdpSocket>::Error,
27    >,
28> {
29    let mut factory = super::socket::DefaultSocketFactory::new();
30    browse_instance_dac_inner(remote_addr, instance_name, &mut factory).await
31}
32
33/// Gets DAC information about the given instance
34///
35/// # Arguments
36/// * `remote_addr` - The address of the remote host on which the instance is running.
37/// * `instance_name` - The name of the instance, must be less than `MAX_INSTANCE_NAME_LEN` characters.
38pub async fn browse_instance_dac_inner<SF: UdpSocketFactory>(
39    remote_addr: IpAddr,
40    instance_name: &str,
41    socket_factory: &mut SF,
42) -> Result<DacInfo, BrowserError<SF::Error, <SF::Socket as UdpSocket>::Error>> {
43    const VERSION: u8 = 0x01;
44
45    if instance_name.len() > super::MAX_INSTANCE_NAME_LEN {
46        return Err(BrowserError::InstanceNameTooLong);
47    }
48
49    let local_addr = if remote_addr.is_ipv4() {
50        IpAddr::V4(Ipv4Addr::UNSPECIFIED)
51    } else {
52        IpAddr::V6(Ipv6Addr::UNSPECIFIED)
53    };
54
55    let bind_to = SocketAddr::new(local_addr, 0);
56    let mut socket = socket_factory
57        .bind(&bind_to)
58        .await
59        .map_err(BrowserError::BindFailed)?;
60
61    let remote = SocketAddr::new(remote_addr, 1434);
62    socket
63        .connect(&remote)
64        .await
65        .map_err(|e| BrowserError::ConnectFailed(remote, e))?;
66
67    let mut buffer = [0u8; 2 + super::MAX_INSTANCE_NAME_LEN + 1];
68    buffer[0] = CLNT_UCAST_DAC;
69    buffer[1] = VERSION;
70    buffer[2..(2 + instance_name.len())].copy_from_slice(instance_name.as_bytes()); // TODO: Encode as mbcs string
71    let buffer_len = 3 + instance_name.len();
72    socket
73        .send(&buffer[0..buffer_len])
74        .await
75        .map_err(|e| BrowserError::SendFailed(remote, e))?;
76
77    let mut buffer = [0u8; 6];
78
79    let bytes_received = socket
80        .recv(&mut buffer)
81        .await
82        .map_err(BrowserError::ReceiveFailed)?;
83
84    if bytes_received < 1 {
85        return Err(BrowserError::ProtocolError(
86            BrowserProtocolError::UnexpectedToken {
87                expected: BrowserProtocolToken::MessageIdentifier(SVR_RESP),
88                found: BrowserProtocolToken::EndOfMessage,
89            },
90        ));
91    }
92
93    if buffer[0] != SVR_RESP {
94        return Err(BrowserError::ProtocolError(
95            BrowserProtocolError::UnexpectedToken {
96                expected: BrowserProtocolToken::MessageIdentifier(SVR_RESP),
97                found: BrowserProtocolToken::MessageIdentifier(buffer[0]),
98            },
99        ));
100    }
101
102    if bytes_received < 3 {
103        return Err(BrowserError::ProtocolError(
104            BrowserProtocolError::UnexpectedToken {
105                expected: BrowserProtocolToken::MessageLength,
106                found: BrowserProtocolToken::EndOfMessage,
107            },
108        ));
109    }
110
111    let packet_size = u16::from_le_bytes([buffer[1], buffer[2]]) as usize;
112    if packet_size != buffer.len() {
113        return Err(BrowserError::ProtocolError(
114            BrowserProtocolError::LengthMismatch {
115                datagram: bytes_received,
116                header: packet_size,
117            },
118        ));
119    }
120
121    if bytes_received < 4 {
122        return Err(BrowserError::ProtocolError(
123            BrowserProtocolError::UnexpectedToken {
124                expected: BrowserProtocolToken::DacVersion(VERSION),
125                found: BrowserProtocolToken::EndOfMessage,
126            },
127        ));
128    }
129
130    if buffer[3] != VERSION {
131        return Err(BrowserError::ProtocolError(
132            BrowserProtocolError::UnexpectedToken {
133                expected: BrowserProtocolToken::DacVersion(VERSION),
134                found: BrowserProtocolToken::DacVersion(buffer[3]),
135            },
136        ));
137    }
138
139    if bytes_received < 6 {
140        return Err(BrowserError::ProtocolError(
141            BrowserProtocolError::UnexpectedToken {
142                expected: BrowserProtocolToken::DacPort,
143                found: BrowserProtocolToken::EndOfMessage,
144            },
145        ));
146    }
147
148    let port = u16::from_le_bytes([buffer[4], buffer[5]]);
149    return Ok(DacInfo { port });
150}