1# This file is part of Scapy
2# See http://www.secdev.org/projects/scapy for more information
3# Copyright (C) Lucas Preston <lucas.preston@infinite.io>
4# This program is published under a GPLv2 license
5
6# scapy.contrib.description = Network Lock Manager (NLM) v4
7# scapy.contrib.status = loads
8
9from scapy.contrib.oncrpc import RPC, RPC_Call, Object_Name
10from scapy.packet import Packet, bind_layers
11from scapy.fields import IntField, StrLenField, LongField, PacketField, \
12    IntEnumField
13from scapy.contrib.nfs import File_Object
14
15nlm4_stats = {
16    0: 'NLM4_GRANTED',
17    1: 'NLM4_DENIED',
18    2: 'NLM4_DENIED_NOLOCKS',
19    3: 'NLM4_BLOCKED',
20    4: 'NLM4_DENIED_GRACE_PERIOD',
21    5: 'NLM4_DEADLCK',
22    6: 'NLM4_ROFS',
23    7: 'NLM4_STALE_FH',
24    8: 'NLM4_FBIG',
25    9: 'NLM4_FAILED'
26}
27
28
29class NLM4_Cookie(Packet):
30    name = 'Cookie'
31    fields_desc = [
32        IntField('length', 0),
33        StrLenField('contents', '', length_from=lambda pkt: pkt.length),
34        StrLenField('fill', b'', length_from=lambda pkt: (4 - pkt.length) % 4)
35    ]
36
37    def set(self, c, length=None, fill=None):
38        if length is None:
39            length = len(c)
40        if fill is None:
41            fill = b'\x00' * ((4 - len(c)) % 4)
42        self.length = length
43        self.contents = c
44        self.fill = fill
45
46    def extract_padding(self, s):
47        return '', s
48
49
50class SHARE_Call(Packet):
51    name = 'SHARE Call'
52    fields_desc = [
53        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
54        PacketField('caller', Object_Name(), Object_Name),
55        PacketField('filehandle', File_Object(), File_Object),
56        PacketField('owner', Object_Name(), Object_Name),
57        IntField('mode', 0),
58        IntField('access', 0),
59        IntEnumField('reclaim', 0, {0: 'NO', 1: 'YES'})
60    ]
61
62
63class SHARE_Reply(Packet):
64    name = 'SHARE Reply'
65    fields_desc = [
66        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
67        IntEnumField('status', 0, nlm4_stats),
68        IntField('sequence', 0)
69    ]
70
71
72bind_layers(RPC_Call, SHARE_Call, program=100021, pversion=4, procedure=20)
73bind_layers(RPC, SHARE_Call, mtype=0)
74bind_layers(RPC, SHARE_Reply, mtype=1)
75
76
77class UNSHARE_Call(Packet):
78    name = 'UNSHARE Reply'
79    fields_desc = [
80        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
81        PacketField('caller', Object_Name(), Object_Name),
82        PacketField('filehandle', File_Object(), File_Object),
83        PacketField('owner', Object_Name(), Object_Name),
84        IntField('mode', 0),
85        IntField('access', 0),
86        IntEnumField('reclaim', 0, {0: 'NO', 1: 'YES'})
87    ]
88
89
90class UNSHARE_Reply(Packet):
91    name = 'UNSHARE Reply'
92    fields_desc = [
93        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
94        IntEnumField('status', 0, nlm4_stats),
95        IntField('sequence', 0)
96    ]
97
98
99bind_layers(
100    RPC_Call, UNSHARE_Call, program=100021, pversion=4, procedure=21
101)
102bind_layers(RPC, UNSHARE_Call, mtype=0)
103bind_layers(RPC, UNSHARE_Reply, mtype=1)
104
105
106class LOCK_Call(Packet):
107    name = 'LOCK Call'
108    fields_desc = [
109        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
110        IntEnumField('block', 0, {0: 'NO', 1: 'YES'}),
111        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),
112        PacketField('caller', Object_Name(), Object_Name),
113        PacketField('filehandle', File_Object(), File_Object),
114        PacketField('owner', Object_Name(), Object_Name),
115        IntField('svid', 0),
116        LongField('l_offset', 0),
117        LongField('l_len', 0),
118        IntField('reclaim', 0),
119        IntField('state', 0)
120    ]
121
122
123class LOCK_Reply(Packet):
124    name = 'LOCK Reply'
125    fields_desc = [
126        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
127        IntEnumField('status', 0, nlm4_stats)
128    ]
129
130
131bind_layers(RPC_Call, LOCK_Call, program=100021, pversion=4, procedure=2)
132bind_layers(RPC, LOCK_Call, mtype=0)
133bind_layers(RPC, LOCK_Reply, mtype=1)
134
135
136class UNLOCK_Call(Packet):
137    name = 'UNLOCK Call'
138    fields_desc = [
139        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
140        PacketField('caller', Object_Name(), Object_Name),
141        PacketField('filehandle', File_Object(), File_Object),
142        PacketField('owner', Object_Name(), Object_Name),
143        IntField('svid', 0),
144        LongField('l_offset', 0),
145        LongField('l_len', 0)
146    ]
147
148
149class UNLOCK_Reply(Packet):
150    name = 'UNLOCK Reply'
151    fields_desc = [
152        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
153        IntEnumField('status', 0, nlm4_stats)
154    ]
155
156
157bind_layers(RPC_Call, UNLOCK_Call, program=100021, pversion=4, procedure=4)
158bind_layers(RPC, UNLOCK_Call, mtype=0)
159bind_layers(RPC, UNLOCK_Reply, mtype=1)
160
161
162class GRANTED_MSG_Call(Packet):
163    name = 'GRANTED_MSG Call'
164    fields_desc = [
165        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
166        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),
167        PacketField('caller', Object_Name(), Object_Name),
168        PacketField('filehandle', File_Object(), File_Object),
169        PacketField('owner', Object_Name(), Object_Name),
170        IntField('svid', 0),
171        LongField('l_offset', 0),
172        LongField('l_len', 0)
173    ]
174
175
176class GRANTED_MSG_Reply(Packet):
177    name = 'GRANTED_MSG Reply'
178    fields_desc = []
179
180
181bind_layers(
182    RPC_Call, GRANTED_MSG_Call, program=100021, pversion=4, procedure=10
183)
184bind_layers(RPC, GRANTED_MSG_Call, mtype=0)
185bind_layers(RPC, GRANTED_MSG_Reply, mtype=1)
186
187
188class GRANTED_RES_Call(Packet):
189    name = 'GRANTED_RES Call'
190    fields_desc = [
191        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
192        IntEnumField('status', 0, nlm4_stats)
193    ]
194
195
196class GRANTED_RES_Reply(Packet):
197    name = 'GRANTED_RES Reply'
198    fields_desc = []
199
200
201bind_layers(
202    RPC_Call, GRANTED_RES_Call, program=100021, pversion=4, procedure=15
203)
204bind_layers(RPC, GRANTED_RES_Call, mtype=0)
205bind_layers(RPC, GRANTED_RES_Reply, mtype=1)
206
207
208class CANCEL_Call(Packet):
209    name = 'CANCEL Call'
210    fields_desc = [
211        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
212        IntEnumField('block', 0, {0: 'NO', 1: 'YES'}),
213        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),
214        PacketField('caller', Object_Name(), Object_Name),
215        PacketField('filehandle', File_Object(), File_Object),
216        PacketField('owner', Object_Name(), Object_Name),
217        IntField('svid', 0),
218        LongField('l_offset', 0),
219        LongField('l_len', 0)
220    ]
221
222
223class CANCEL_Reply(Packet):
224    name = 'CANCEL Reply'
225    fields_desc = [
226        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
227        IntEnumField('status', 0, nlm4_stats)
228    ]
229
230
231bind_layers(RPC_Call, CANCEL_Call, program=100021, pversion=4, procedure=3)
232bind_layers(RPC, CANCEL_Call, mtype=0)
233bind_layers(RPC, CANCEL_Reply, mtype=1)
234
235
236class TEST_Call(Packet):
237    name = 'TEST Call'
238    fields_desc = [
239        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
240        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),
241        PacketField('caller', Object_Name(), Object_Name),
242        PacketField('filehandle', File_Object(), File_Object),
243        PacketField('owner', Object_Name(), Object_Name),
244        IntField('svid', 0),
245        LongField('l_offset', 0),
246        LongField('l_len', 0)
247    ]
248
249
250class TEST_Reply(Packet):
251    name = 'TEST Reply'
252    fields_desc = [
253        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),
254        IntEnumField('status', 0, nlm4_stats)
255    ]
256
257
258bind_layers(RPC_Call, TEST_Call, program=100021, pversion=4, procedure=1)
259bind_layers(RPC, TEST_Call, mtype=0)
260bind_layers(RPC, TEST_Reply, mtype=1)
261