examples/scripts: add smbXsrvdump
[samba.git] / examples / scripts / debugging / smbXsrvdump
1 #!/usr/bin/env python3
2
3 import sys
4
5 sys.path.insert(0, "bin/python")
6
7 import os
8 import argparse
9 import struct
10
11 from samba.ndr import ndr_unpack, ndr_print
12 from samba.dcerpc import smbXsrv
13 from samba.dcerpc import server_id
14 import tdb
15
16 def print_watchers(num_watched, blob):
17     for i in range(0,num_watched):
18         id = ndr_unpack(server_id.server_id, blob[:24])
19         print(ndr_print(id))
20         blob = blob[24:]
21
22 def print_record(data, ndr_type, watched, ctdb):
23     blob = data
24
25     if ctdb:
26         (rsn, dmaster, reserved1, flags) = struct.unpack('QIII', bytes(blob[:20]))
27         blob = blob[24:]
28         print("    ctdb record header: rsn=%lu, dmaster=%u, reserved1=0x%x, flags=0x%x len=%u" %
29               (rsn, dmaster, reserved1, flags, len(blob)))
30         if len(blob) == 0:
31             return
32
33     if watched:
34         (num_watched, ) = struct.unpack('I', bytes(blob[:4]))
35         blob = blob[4:]
36
37         deleted_bit = 1<<31
38         deleted = num_watched & deleted_bit
39
40         num_watched = num_watched & ~deleted_bit
41         if num_watched > 0:
42             if deleted:
43                 deleted_str = "yes"
44             else:
45                 deleted_str = "no"
46             print("    num_watched: %d, deleted: %s" % (num_watched, deleted_str))
47             print_watchers(num_watched, blob)
48             blob = blob[num_watched*4:]
49
50     unpacked = ndr_unpack(ndr_type, blob, allow_remaining=True)
51     print(ndr_print(unpacked))
52
53 if __name__ == "__main__":
54     parser = argparse.ArgumentParser()
55     parser.add_argument('path', help='Path to the TDB file')
56     parser.add_argument('-c', '--ctdb',
57                         default=False,
58                         action="store_true",
59                         help='The TDB database is from a ctdb cluster')
60     args = parser.parse_args()
61
62     watched = False
63     if 'smbXsrv_session' in args.path:
64         ndr_type = smbXsrv.session_globalB
65         watched = True
66     elif 'smbXsrv_open' in args.path:
67         ndr_type = smbXsrv.open_globalB
68     elif 'smbXsrv_client' in args.path:
69         ndr_type = smbXsrv.client_globalB
70         watched = True
71     elif 'smbXsrv_tcon' in args.path:
72         ndr_type = smbXsrv.tcon_globalB
73     elif 'smbXsrv_version' in args.path:
74         ndr_type = smbXsrv.version_globalB
75     else:
76         raise Exception("Failed to guess NDR type")
77
78     tdb = tdb.Tdb(args.path, 0, tdb.INCOMPATIBLE_HASH, os.O_RDONLY)
79
80     i = 1
81     for k in tdb.keys():
82         data = tdb.get(k)
83         print("Record: %d" % i)
84         print_record(data, ndr_type, watched, args.ctdb)
85         i = i + 1
86
87     tdb.close()