-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmssql_info.py
106 lines (78 loc) · 3.32 KB
/
mssql_info.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""Retrieves Microsoft SQL Server instance information by querying the SQL Browser
service.
"""
import argparse
import sys
import socket
from collections import OrderedDict
SQL_BROWSER_DEFAULT_PORT = 1434
BUFFER_SIZE = 4096
TIMEOUT = 4
def get_instance_info(host, instance=None, sql_browser_port=SQL_BROWSER_DEFAULT_PORT,
buffer_size=BUFFER_SIZE, timeout=TIMEOUT):
"""Gets Microsoft SQL Server instance information by querying the SQL Browser service.
Args:
host (str): Hostname or IP address of the SQL Server to query for information.
instance (str): The name of the instance to query for information.
All instances are included if none.
sql_browser_port (int): SQL Browser port number to query.
buffer_size (int): Buffer size for the UDP request.
timeout (int): timeout for the query.
Returns:
dict: A dictionary with the server name as the key and a dictionary of the
server information as the value.
"""
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Set a timeout
sock.settimeout(timeout)
server_address = (host, sql_browser_port)
if instance:
# The message is a CLNT_UCAST_INST packet to get a single instance
# https://msdn.microsoft.com/en-us/library/cc219746.aspx
message = '\x04%s\x00' % instance
# Encode the message as a bytesarray
else:
# The message is a CLNT_UCAST_EX packet to get all instances
# https://msdn.microsoft.com/en-us/library/cc219745.aspx
message = '\x03'
# Encode the message as a bytesarray
message = message.encode()
# Send data
sock.sendto(message, server_address)
# Receive response
data, server = sock.recvfrom(buffer_size)
results = []
# Loop through the server data
for server in data[3:].decode().split(';;'):
server_info = OrderedDict()
chunk = server.split(';')
if len(chunk) > 1:
for i in range(1, len(chunk), 2):
server_info[chunk[i - 1]] = chunk[i]
results.append(server_info)
# Close socket
sock.close()
return results
def main():
"""Main program logic if called as a script."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('host',
help='hostname or IP address of the SQL Server to query for information')
parser.add_argument('-i', '--instance', default=None, required=False,
help='name of the instance to query for information')
parser.add_argument('-p', '--port', default=SQL_BROWSER_DEFAULT_PORT, required=False,
help='SQL Browser port')
arguments = parser.parse_args()
try:
instance_info = get_instance_info(arguments.host, instance=arguments.instance,
sql_browser_port=arguments.port)
except socket.error as error:
sys.stderr.write('Connection to %s failed: %s' % (arguments.host, error))
sys.exit(1)
for i in instance_info:
print('')
for key, value in i.items():
print('%s: %s' % (key, value))
if __name__ == '__main__':
main()