We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
mistaken msglen in MQTTPublish message
### Brief description

I noticed that the StrLenField of value in MQTTPublish packets is defined as
```python
StrLenField("value", "",
                    length_from=lambda pkt: (pkt.underlayer.len -
                                             pkt.length - 2)),
```
However, if the QoS of the publish message is 1 or 2, because of the field of msgid,  I guess it should be pkt.underlayer.len - pkt.length - 4, as I met this problem when I was trying to parse a packet that contains two MQTT Publish messages. 
![image](https://user-images.githubusercontent.com/79267237/161885502-3e24b59c-95a7-4761-a642-1e1aa135bb45.png)
I tried to fix it with codes as followed. Perhaps it could help. 
```python
StrLenField("value", "",
                    length_from=lambda pkt: pkt.underlayer.len -pkt.length - 2 if pkt.underlayer.QOS == 0 
                                            else pkt.underlayer.len -pkt.length - 4)
```



### Scapy version

2.4.5

### Python version

3.8

### Operating system

Win11

### Additional environment information

_No response_

### How to reproduce

Sniff a packet with two MQTT Publish messages......

### Actual result

_No response_

### Expected result

_No response_

### Related resources

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scapy/contrib/mqtt.py`
Content:
```
1 # This file is part of Scapy
2 # See http://www.secdev.org/projects/scapy for more information
3 # Copyright (C) Santiago Hernandez Ramos <shramos@protonmail.com>
4 # This program is published under GPLv2 license
5 
6 # scapy.contrib.description = Message Queuing Telemetry Transport (MQTT)
7 # scapy.contrib.status = loads
8 
9 from scapy.packet import Packet, bind_layers
10 from scapy.fields import FieldLenField, BitEnumField, StrLenField, \
11     ShortField, ConditionalField, ByteEnumField, ByteField, PacketListField
12 from scapy.layers.inet import TCP
13 from scapy.error import Scapy_Exception
14 from scapy.compat import orb, chb
15 from scapy.volatile import RandNum
16 from scapy.config import conf
17 
18 
19 # CUSTOM FIELDS
20 # source: http://stackoverflow.com/a/43717630
21 class VariableFieldLenField(FieldLenField):
22     def addfield(self, pkt, s, val):
23         val = self.i2m(pkt, val)
24         data = []
25         while val:
26             if val > 127:
27                 data.append(val & 127)
28                 val //= 128
29             else:
30                 data.append(val)
31                 lastoffset = len(data) - 1
32                 data = b"".join(chb(val | (0 if i == lastoffset else 128))
33                                 for i, val in enumerate(data))
34                 return s + data
35             if len(data) > 3:
36                 raise Scapy_Exception("%s: malformed length field" %
37                                       self.__class__.__name__)
38         # If val is None / 0
39         return s + b"\x00"
40 
41     def getfield(self, pkt, s):
42         value = 0
43         for offset, curbyte in enumerate(s):
44             curbyte = orb(curbyte)
45             value += (curbyte & 127) * (128 ** offset)
46             if curbyte & 128 == 0:
47                 return s[offset + 1:], value
48             if offset > 2:
49                 raise Scapy_Exception("%s: malformed length field" %
50                                       self.__class__.__name__)
51 
52     def randval(self):
53         return RandVariableFieldLen()
54 
55 
56 class RandVariableFieldLen(RandNum):
57     def __init__(self):
58         RandNum.__init__(self, 0, 268435455)
59 
60 
61 # LAYERS
62 CONTROL_PACKET_TYPE = {
63     1: 'CONNECT',
64     2: 'CONNACK',
65     3: 'PUBLISH',
66     4: 'PUBACK',
67     5: 'PUBREC',
68     6: 'PUBREL',
69     7: 'PUBCOMP',
70     8: 'SUBSCRIBE',
71     9: 'SUBACK',
72     10: 'UNSUBSCRIBE',
73     11: 'UNSUBACK',
74     12: 'PINGREQ',
75     13: 'PINGRESP',
76     14: 'DISCONNECT',
77     15: 'AUTH'  # Added in v5.0
78 }
79 
80 
81 QOS_LEVEL = {
82     0: 'At most once delivery',
83     1: 'At least once delivery',
84     2: 'Exactly once delivery'
85 }
86 
87 
88 # source: http://stackoverflow.com/a/43722441
89 class MQTT(Packet):
90     name = "MQTT fixed header"
91     fields_desc = [
92         BitEnumField("type", 1, 4, CONTROL_PACKET_TYPE),
93         BitEnumField("DUP", 0, 1, {0: 'Disabled',
94                                    1: 'Enabled'}),
95         BitEnumField("QOS", 0, 2, QOS_LEVEL),
96         BitEnumField("RETAIN", 0, 1, {0: 'Disabled',
97                                       1: 'Enabled'}),
98         # Since the size of the len field depends on the next layer, we need
99         # to "cheat" with the length_of parameter and use adjust parameter to
100         # calculate the value.
101         VariableFieldLenField("len", None, length_of="len",
102                               adjust=lambda pkt, x: len(pkt.payload),),
103     ]
104 
105 
106 PROTOCOL_LEVEL = {
107     3: 'v3.1',
108     4: 'v3.1.1',
109     5: 'v5.0'
110 }
111 
112 
113 class MQTTConnect(Packet):
114     name = "MQTT connect"
115     fields_desc = [
116         FieldLenField("length", None, length_of="protoname"),
117         StrLenField("protoname", "",
118                     length_from=lambda pkt: pkt.length),
119         ByteEnumField("protolevel", 5, PROTOCOL_LEVEL),
120         BitEnumField("usernameflag", 0, 1, {0: 'Disabled',
121                                             1: 'Enabled'}),
122         BitEnumField("passwordflag", 0, 1, {0: 'Disabled',
123                                             1: 'Enabled'}),
124         BitEnumField("willretainflag", 0, 1, {0: 'Disabled',
125                                               1: 'Enabled'}),
126         BitEnumField("willQOSflag", 0, 2, QOS_LEVEL),
127         BitEnumField("willflag", 0, 1, {0: 'Disabled',
128                                         1: 'Enabled'}),
129         BitEnumField("cleansess", 0, 1, {0: 'Disabled',
130                                          1: 'Enabled'}),
131         BitEnumField("reserved", 0, 1, {0: 'Disabled',
132                                         1: 'Enabled'}),
133         ShortField("klive", 0),
134         FieldLenField("clientIdlen", None, length_of="clientId"),
135         StrLenField("clientId", "",
136                     length_from=lambda pkt: pkt.clientIdlen),
137         # Payload with optional fields depending on the flags
138         ConditionalField(FieldLenField("wtoplen", None, length_of="willtopic"),
139                          lambda pkt: pkt.willflag == 1),
140         ConditionalField(StrLenField("willtopic", "",
141                                      length_from=lambda pkt: pkt.wtoplen),
142                          lambda pkt: pkt.willflag == 1),
143         ConditionalField(FieldLenField("wmsglen", None, length_of="willmsg"),
144                          lambda pkt: pkt.willflag == 1),
145         ConditionalField(StrLenField("willmsg", "",
146                                      length_from=lambda pkt: pkt.wmsglen),
147                          lambda pkt: pkt.willflag == 1),
148         ConditionalField(FieldLenField("userlen", None, length_of="username"),
149                          lambda pkt: pkt.usernameflag == 1),
150         ConditionalField(StrLenField("username", "",
151                                      length_from=lambda pkt: pkt.userlen),
152                          lambda pkt: pkt.usernameflag == 1),
153         ConditionalField(FieldLenField("passlen", None, length_of="password"),
154                          lambda pkt: pkt.passwordflag == 1),
155         ConditionalField(StrLenField("password", "",
156                                      length_from=lambda pkt: pkt.passlen),
157                          lambda pkt: pkt.passwordflag == 1),
158     ]
159 
160 
161 class MQTTDisconnect(Packet):
162     name = "MQTT disconnect"
163     fields_desc = []
164 
165 
166 RETURN_CODE = {
167     0: 'Connection Accepted',
168     1: 'Unacceptable protocol version',
169     2: 'Identifier rejected',
170     3: 'Server unavailable',
171     4: 'Bad username/password',
172     5: 'Not authorized'
173 }
174 
175 
176 class MQTTConnack(Packet):
177     name = "MQTT connack"
178     fields_desc = [
179         ByteField("sessPresentFlag", 0),
180         ByteEnumField("retcode", 0, RETURN_CODE),
181         # this package has not payload
182     ]
183 
184 
185 class MQTTPublish(Packet):
186     name = "MQTT publish"
187     fields_desc = [
188         FieldLenField("length", None, length_of="topic"),
189         StrLenField("topic", "",
190                     length_from=lambda pkt: pkt.length),
191         ConditionalField(ShortField("msgid", None),
192                          lambda pkt: (pkt.underlayer.QOS == 1 or
193                                       pkt.underlayer.QOS == 2)),
194         StrLenField("value", "",
195                     length_from=lambda pkt: (pkt.underlayer.len -
196                                              pkt.length - 2)),
197     ]
198 
199 
200 class MQTTPuback(Packet):
201     name = "MQTT puback"
202     fields_desc = [
203         ShortField("msgid", None),
204     ]
205 
206 
207 class MQTTPubrec(Packet):
208     name = "MQTT pubrec"
209     fields_desc = [
210         ShortField("msgid", None),
211     ]
212 
213 
214 class MQTTPubrel(Packet):
215     name = "MQTT pubrel"
216     fields_desc = [
217         ShortField("msgid", None),
218     ]
219 
220 
221 class MQTTPubcomp(Packet):
222     name = "MQTT pubcomp"
223     fields_desc = [
224         ShortField("msgid", None),
225     ]
226 
227 
228 class MQTTTopic(Packet):
229     name = "MQTT topic"
230     fields_desc = [
231         FieldLenField("length", None, length_of="topic"),
232         StrLenField("topic", "", length_from=lambda pkt:pkt.length)
233     ]
234 
235     def guess_payload_class(self, payload):
236         return conf.padding_layer
237 
238 
239 class MQTTTopicQOS(MQTTTopic):
240     fields_desc = MQTTTopic.fields_desc + [ByteEnumField("QOS", 0, QOS_LEVEL)]
241 
242 
243 class MQTTSubscribe(Packet):
244     name = "MQTT subscribe"
245     fields_desc = [
246         ShortField("msgid", None),
247         PacketListField("topics", [], pkt_cls=MQTTTopicQOS)
248     ]
249 
250 
251 ALLOWED_RETURN_CODE = {
252     0: 'Success',
253     1: 'Success',
254     2: 'Success',
255     128: 'Failure'
256 }
257 
258 
259 class MQTTSuback(Packet):
260     name = "MQTT suback"
261     fields_desc = [
262         ShortField("msgid", None),
263         ByteEnumField("retcode", None, ALLOWED_RETURN_CODE)
264     ]
265 
266 
267 class MQTTUnsubscribe(Packet):
268     name = "MQTT unsubscribe"
269     fields_desc = [
270         ShortField("msgid", None),
271         PacketListField("topics", [], pkt_cls=MQTTTopic)
272     ]
273 
274 
275 class MQTTUnsuback(Packet):
276     name = "MQTT unsuback"
277     fields_desc = [
278         ShortField("msgid", None)
279     ]
280 
281 
282 # LAYERS BINDINGS
283 
284 bind_layers(TCP, MQTT, sport=1883)
285 bind_layers(TCP, MQTT, dport=1883)
286 bind_layers(MQTT, MQTTConnect, type=1)
287 bind_layers(MQTT, MQTTConnack, type=2)
288 bind_layers(MQTT, MQTTPublish, type=3)
289 bind_layers(MQTT, MQTTPuback, type=4)
290 bind_layers(MQTT, MQTTPubrec, type=5)
291 bind_layers(MQTT, MQTTPubrel, type=6)
292 bind_layers(MQTT, MQTTPubcomp, type=7)
293 bind_layers(MQTT, MQTTSubscribe, type=8)
294 bind_layers(MQTT, MQTTSuback, type=9)
295 bind_layers(MQTT, MQTTUnsubscribe, type=10)
296 bind_layers(MQTT, MQTTUnsuback, type=11)
297 bind_layers(MQTT, MQTTDisconnect, type=14)
298 bind_layers(MQTTConnect, MQTT)
299 bind_layers(MQTTConnack, MQTT)
300 bind_layers(MQTTPublish, MQTT)
301 bind_layers(MQTTPuback, MQTT)
302 bind_layers(MQTTPubrec, MQTT)
303 bind_layers(MQTTPubrel, MQTT)
304 bind_layers(MQTTPubcomp, MQTT)
305 bind_layers(MQTTSubscribe, MQTT)
306 bind_layers(MQTTSuback, MQTT)
307 bind_layers(MQTTUnsubscribe, MQTT)
308 bind_layers(MQTTUnsuback, MQTT)
309 bind_layers(MQTTDisconnect, MQTT)
310
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scapy/contrib/mqtt.py b/scapy/contrib/mqtt.py
--- a/scapy/contrib/mqtt.py
+++ b/scapy/contrib/mqtt.py
@@ -192,8 +192,9 @@
                          lambda pkt: (pkt.underlayer.QOS == 1 or
                                       pkt.underlayer.QOS == 2)),
         StrLenField("value", "",
-                    length_from=lambda pkt: (pkt.underlayer.len -
-                                             pkt.length - 2)),
+                    length_from=lambda pkt: pkt.underlayer.len - pkt.length - 2
+                    if pkt.underlayer.QOS == 0 else
+                    pkt.underlayer.len - pkt.length - 4)
     ]

{"golden_diff": "diff --git a/scapy/contrib/mqtt.py b/scapy/contrib/mqtt.py\n--- a/scapy/contrib/mqtt.py\n+++ b/scapy/contrib/mqtt.py\n@@ -192,8 +192,9 @@\n                          lambda pkt: (pkt.underlayer.QOS == 1 or\n                                       pkt.underlayer.QOS == 2)),\n         StrLenField(\"value\", \"\",\n-                    length_from=lambda pkt: (pkt.underlayer.len -\n-                                             pkt.length - 2)),\n+                    length_from=lambda pkt: pkt.underlayer.len - pkt.length - 2\n+                    if pkt.underlayer.QOS == 0 else\n+                    pkt.underlayer.len - pkt.length - 4)\n     ]\n", "issue": "mistaken msglen in MQTTPublish message\n### Brief description\n\nI noticed that the StrLenField of value in MQTTPublish packets is defined as\r\n```python\r\nStrLenField(\"value\", \"\",\r\n                    length_from=lambda pkt: (pkt.underlayer.len -\r\n                                             pkt.length - 2)),\r\n```\r\nHowever, if the QoS of the publish message is 1 or 2, because of the field of msgid,  I guess it should be pkt.underlayer.len - pkt.length - 4, as I met this problem when I was trying to parse a packet that contains two MQTT Publish messages. \r\n![image](https://user-images.githubusercontent.com/79267237/161885502-3e24b59c-95a7-4761-a642-1e1aa135bb45.png)\r\nI tried to fix it with codes as followed. Perhaps it could help. \r\n```python\r\nStrLenField(\"value\", \"\",\r\n                    length_from=lambda pkt: pkt.underlayer.len -pkt.length - 2 if pkt.underlayer.QOS == 0 \r\n                                            else pkt.underlayer.len -pkt.length - 4)\r\n```\r\n\r\n\n\n### Scapy version\n\n2.4.5\n\n### Python version\n\n3.8\n\n### Operating system\n\nWin11\n\n### Additional environment information\n\n_No response_\n\n### How to reproduce\n\nSniff a packet with two MQTT Publish messages......\n\n### Actual result\n\n_No response_\n\n### Expected result\n\n_No response_\n\n### Related resources\n\n_No response_\n", "before_files": [{"content": "# This file is part of Scapy\n# See http://www.secdev.org/projects/scapy for more information\n# Copyright (C) Santiago Hernandez Ramos <shramos@protonmail.com>\n# This program is published under GPLv2 license\n\n# scapy.contrib.description = Message Queuing Telemetry Transport (MQTT)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FieldLenField, BitEnumField, StrLenField, \\\n    ShortField, ConditionalField, ByteEnumField, ByteField, PacketListField\nfrom scapy.layers.inet import TCP\nfrom scapy.error import Scapy_Exception\nfrom scapy.compat import orb, chb\nfrom scapy.volatile import RandNum\nfrom scapy.config import conf\n\n\n# CUSTOM FIELDS\n# source: http://stackoverflow.com/a/43717630\nclass VariableFieldLenField(FieldLenField):\n    def addfield(self, pkt, s, val):\n        val = self.i2m(pkt, val)\n        data = []\n        while val:\n            if val > 127:\n                data.append(val & 127)\n                val //= 128\n            else:\n                data.append(val)\n                lastoffset = len(data) - 1\n                data = b\"\".join(chb(val | (0 if i == lastoffset else 128))\n                                for i, val in enumerate(data))\n                return s + data\n            if len(data) > 3:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n        # If val is None / 0\n        return s + b\"\\x00\"\n\n    def getfield(self, pkt, s):\n        value = 0\n        for offset, curbyte in enumerate(s):\n            curbyte = orb(curbyte)\n            value += (curbyte & 127) * (128 ** offset)\n            if curbyte & 128 == 0:\n                return s[offset + 1:], value\n            if offset > 2:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n\n    def randval(self):\n        return RandVariableFieldLen()\n\n\nclass RandVariableFieldLen(RandNum):\n    def __init__(self):\n        RandNum.__init__(self, 0, 268435455)\n\n\n# LAYERS\nCONTROL_PACKET_TYPE = {\n    1: 'CONNECT',\n    2: 'CONNACK',\n    3: 'PUBLISH',\n    4: 'PUBACK',\n    5: 'PUBREC',\n    6: 'PUBREL',\n    7: 'PUBCOMP',\n    8: 'SUBSCRIBE',\n    9: 'SUBACK',\n    10: 'UNSUBSCRIBE',\n    11: 'UNSUBACK',\n    12: 'PINGREQ',\n    13: 'PINGRESP',\n    14: 'DISCONNECT',\n    15: 'AUTH'  # Added in v5.0\n}\n\n\nQOS_LEVEL = {\n    0: 'At most once delivery',\n    1: 'At least once delivery',\n    2: 'Exactly once delivery'\n}\n\n\n# source: http://stackoverflow.com/a/43722441\nclass MQTT(Packet):\n    name = \"MQTT fixed header\"\n    fields_desc = [\n        BitEnumField(\"type\", 1, 4, CONTROL_PACKET_TYPE),\n        BitEnumField(\"DUP\", 0, 1, {0: 'Disabled',\n                                   1: 'Enabled'}),\n        BitEnumField(\"QOS\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"RETAIN\", 0, 1, {0: 'Disabled',\n                                      1: 'Enabled'}),\n        # Since the size of the len field depends on the next layer, we need\n        # to \"cheat\" with the length_of parameter and use adjust parameter to\n        # calculate the value.\n        VariableFieldLenField(\"len\", None, length_of=\"len\",\n                              adjust=lambda pkt, x: len(pkt.payload),),\n    ]\n\n\nPROTOCOL_LEVEL = {\n    3: 'v3.1',\n    4: 'v3.1.1',\n    5: 'v5.0'\n}\n\n\nclass MQTTConnect(Packet):\n    name = \"MQTT connect\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"protoname\"),\n        StrLenField(\"protoname\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ByteEnumField(\"protolevel\", 5, PROTOCOL_LEVEL),\n        BitEnumField(\"usernameflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"passwordflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"willretainflag\", 0, 1, {0: 'Disabled',\n                                              1: 'Enabled'}),\n        BitEnumField(\"willQOSflag\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"willflag\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        BitEnumField(\"cleansess\", 0, 1, {0: 'Disabled',\n                                         1: 'Enabled'}),\n        BitEnumField(\"reserved\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        ShortField(\"klive\", 0),\n        FieldLenField(\"clientIdlen\", None, length_of=\"clientId\"),\n        StrLenField(\"clientId\", \"\",\n                    length_from=lambda pkt: pkt.clientIdlen),\n        # Payload with optional fields depending on the flags\n        ConditionalField(FieldLenField(\"wtoplen\", None, length_of=\"willtopic\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willtopic\", \"\",\n                                     length_from=lambda pkt: pkt.wtoplen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"wmsglen\", None, length_of=\"willmsg\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willmsg\", \"\",\n                                     length_from=lambda pkt: pkt.wmsglen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"userlen\", None, length_of=\"username\"),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(StrLenField(\"username\", \"\",\n                                     length_from=lambda pkt: pkt.userlen),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(FieldLenField(\"passlen\", None, length_of=\"password\"),\n                         lambda pkt: pkt.passwordflag == 1),\n        ConditionalField(StrLenField(\"password\", \"\",\n                                     length_from=lambda pkt: pkt.passlen),\n                         lambda pkt: pkt.passwordflag == 1),\n    ]\n\n\nclass MQTTDisconnect(Packet):\n    name = \"MQTT disconnect\"\n    fields_desc = []\n\n\nRETURN_CODE = {\n    0: 'Connection Accepted',\n    1: 'Unacceptable protocol version',\n    2: 'Identifier rejected',\n    3: 'Server unavailable',\n    4: 'Bad username/password',\n    5: 'Not authorized'\n}\n\n\nclass MQTTConnack(Packet):\n    name = \"MQTT connack\"\n    fields_desc = [\n        ByteField(\"sessPresentFlag\", 0),\n        ByteEnumField(\"retcode\", 0, RETURN_CODE),\n        # this package has not payload\n    ]\n\n\nclass MQTTPublish(Packet):\n    name = \"MQTT publish\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ConditionalField(ShortField(\"msgid\", None),\n                         lambda pkt: (pkt.underlayer.QOS == 1 or\n                                      pkt.underlayer.QOS == 2)),\n        StrLenField(\"value\", \"\",\n                    length_from=lambda pkt: (pkt.underlayer.len -\n                                             pkt.length - 2)),\n    ]\n\n\nclass MQTTPuback(Packet):\n    name = \"MQTT puback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrec(Packet):\n    name = \"MQTT pubrec\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrel(Packet):\n    name = \"MQTT pubrel\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubcomp(Packet):\n    name = \"MQTT pubcomp\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTTopic(Packet):\n    name = \"MQTT topic\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\", length_from=lambda pkt:pkt.length)\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass MQTTTopicQOS(MQTTTopic):\n    fields_desc = MQTTTopic.fields_desc + [ByteEnumField(\"QOS\", 0, QOS_LEVEL)]\n\n\nclass MQTTSubscribe(Packet):\n    name = \"MQTT subscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopicQOS)\n    ]\n\n\nALLOWED_RETURN_CODE = {\n    0: 'Success',\n    1: 'Success',\n    2: 'Success',\n    128: 'Failure'\n}\n\n\nclass MQTTSuback(Packet):\n    name = \"MQTT suback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        ByteEnumField(\"retcode\", None, ALLOWED_RETURN_CODE)\n    ]\n\n\nclass MQTTUnsubscribe(Packet):\n    name = \"MQTT unsubscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopic)\n    ]\n\n\nclass MQTTUnsuback(Packet):\n    name = \"MQTT unsuback\"\n    fields_desc = [\n        ShortField(\"msgid\", None)\n    ]\n\n\n# LAYERS BINDINGS\n\nbind_layers(TCP, MQTT, sport=1883)\nbind_layers(TCP, MQTT, dport=1883)\nbind_layers(MQTT, MQTTConnect, type=1)\nbind_layers(MQTT, MQTTConnack, type=2)\nbind_layers(MQTT, MQTTPublish, type=3)\nbind_layers(MQTT, MQTTPuback, type=4)\nbind_layers(MQTT, MQTTPubrec, type=5)\nbind_layers(MQTT, MQTTPubrel, type=6)\nbind_layers(MQTT, MQTTPubcomp, type=7)\nbind_layers(MQTT, MQTTSubscribe, type=8)\nbind_layers(MQTT, MQTTSuback, type=9)\nbind_layers(MQTT, MQTTUnsubscribe, type=10)\nbind_layers(MQTT, MQTTUnsuback, type=11)\nbind_layers(MQTT, MQTTDisconnect, type=14)\nbind_layers(MQTTConnect, MQTT)\nbind_layers(MQTTConnack, MQTT)\nbind_layers(MQTTPublish, MQTT)\nbind_layers(MQTTPuback, MQTT)\nbind_layers(MQTTPubrec, MQTT)\nbind_layers(MQTTPubrel, MQTT)\nbind_layers(MQTTPubcomp, MQTT)\nbind_layers(MQTTSubscribe, MQTT)\nbind_layers(MQTTSuback, MQTT)\nbind_layers(MQTTUnsubscribe, MQTT)\nbind_layers(MQTTUnsuback, MQTT)\nbind_layers(MQTTDisconnect, MQTT)\n", "path": "scapy/contrib/mqtt.py"}], "after_files": [{"content": "# This file is part of Scapy\n# See http://www.secdev.org/projects/scapy for more information\n# Copyright (C) Santiago Hernandez Ramos <shramos@protonmail.com>\n# This program is published under GPLv2 license\n\n# scapy.contrib.description = Message Queuing Telemetry Transport (MQTT)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FieldLenField, BitEnumField, StrLenField, \\\n    ShortField, ConditionalField, ByteEnumField, ByteField, PacketListField\nfrom scapy.layers.inet import TCP\nfrom scapy.error import Scapy_Exception\nfrom scapy.compat import orb, chb\nfrom scapy.volatile import RandNum\nfrom scapy.config import conf\n\n\n# CUSTOM FIELDS\n# source: http://stackoverflow.com/a/43717630\nclass VariableFieldLenField(FieldLenField):\n    def addfield(self, pkt, s, val):\n        val = self.i2m(pkt, val)\n        data = []\n        while val:\n            if val > 127:\n                data.append(val & 127)\n                val //= 128\n            else:\n                data.append(val)\n                lastoffset = len(data) - 1\n                data = b\"\".join(chb(val | (0 if i == lastoffset else 128))\n                                for i, val in enumerate(data))\n                return s + data\n            if len(data) > 3:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n        # If val is None / 0\n        return s + b\"\\x00\"\n\n    def getfield(self, pkt, s):\n        value = 0\n        for offset, curbyte in enumerate(s):\n            curbyte = orb(curbyte)\n            value += (curbyte & 127) * (128 ** offset)\n            if curbyte & 128 == 0:\n                return s[offset + 1:], value\n            if offset > 2:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n\n    def randval(self):\n        return RandVariableFieldLen()\n\n\nclass RandVariableFieldLen(RandNum):\n    def __init__(self):\n        RandNum.__init__(self, 0, 268435455)\n\n\n# LAYERS\nCONTROL_PACKET_TYPE = {\n    1: 'CONNECT',\n    2: 'CONNACK',\n    3: 'PUBLISH',\n    4: 'PUBACK',\n    5: 'PUBREC',\n    6: 'PUBREL',\n    7: 'PUBCOMP',\n    8: 'SUBSCRIBE',\n    9: 'SUBACK',\n    10: 'UNSUBSCRIBE',\n    11: 'UNSUBACK',\n    12: 'PINGREQ',\n    13: 'PINGRESP',\n    14: 'DISCONNECT',\n    15: 'AUTH'  # Added in v5.0\n}\n\n\nQOS_LEVEL = {\n    0: 'At most once delivery',\n    1: 'At least once delivery',\n    2: 'Exactly once delivery'\n}\n\n\n# source: http://stackoverflow.com/a/43722441\nclass MQTT(Packet):\n    name = \"MQTT fixed header\"\n    fields_desc = [\n        BitEnumField(\"type\", 1, 4, CONTROL_PACKET_TYPE),\n        BitEnumField(\"DUP\", 0, 1, {0: 'Disabled',\n                                   1: 'Enabled'}),\n        BitEnumField(\"QOS\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"RETAIN\", 0, 1, {0: 'Disabled',\n                                      1: 'Enabled'}),\n        # Since the size of the len field depends on the next layer, we need\n        # to \"cheat\" with the length_of parameter and use adjust parameter to\n        # calculate the value.\n        VariableFieldLenField(\"len\", None, length_of=\"len\",\n                              adjust=lambda pkt, x: len(pkt.payload),),\n    ]\n\n\nPROTOCOL_LEVEL = {\n    3: 'v3.1',\n    4: 'v3.1.1',\n    5: 'v5.0'\n}\n\n\nclass MQTTConnect(Packet):\n    name = \"MQTT connect\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"protoname\"),\n        StrLenField(\"protoname\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ByteEnumField(\"protolevel\", 5, PROTOCOL_LEVEL),\n        BitEnumField(\"usernameflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"passwordflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"willretainflag\", 0, 1, {0: 'Disabled',\n                                              1: 'Enabled'}),\n        BitEnumField(\"willQOSflag\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"willflag\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        BitEnumField(\"cleansess\", 0, 1, {0: 'Disabled',\n                                         1: 'Enabled'}),\n        BitEnumField(\"reserved\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        ShortField(\"klive\", 0),\n        FieldLenField(\"clientIdlen\", None, length_of=\"clientId\"),\n        StrLenField(\"clientId\", \"\",\n                    length_from=lambda pkt: pkt.clientIdlen),\n        # Payload with optional fields depending on the flags\n        ConditionalField(FieldLenField(\"wtoplen\", None, length_of=\"willtopic\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willtopic\", \"\",\n                                     length_from=lambda pkt: pkt.wtoplen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"wmsglen\", None, length_of=\"willmsg\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willmsg\", \"\",\n                                     length_from=lambda pkt: pkt.wmsglen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"userlen\", None, length_of=\"username\"),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(StrLenField(\"username\", \"\",\n                                     length_from=lambda pkt: pkt.userlen),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(FieldLenField(\"passlen\", None, length_of=\"password\"),\n                         lambda pkt: pkt.passwordflag == 1),\n        ConditionalField(StrLenField(\"password\", \"\",\n                                     length_from=lambda pkt: pkt.passlen),\n                         lambda pkt: pkt.passwordflag == 1),\n    ]\n\n\nclass MQTTDisconnect(Packet):\n    name = \"MQTT disconnect\"\n    fields_desc = []\n\n\nRETURN_CODE = {\n    0: 'Connection Accepted',\n    1: 'Unacceptable protocol version',\n    2: 'Identifier rejected',\n    3: 'Server unavailable',\n    4: 'Bad username/password',\n    5: 'Not authorized'\n}\n\n\nclass MQTTConnack(Packet):\n    name = \"MQTT connack\"\n    fields_desc = [\n        ByteField(\"sessPresentFlag\", 0),\n        ByteEnumField(\"retcode\", 0, RETURN_CODE),\n        # this package has not payload\n    ]\n\n\nclass MQTTPublish(Packet):\n    name = \"MQTT publish\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ConditionalField(ShortField(\"msgid\", None),\n                         lambda pkt: (pkt.underlayer.QOS == 1 or\n                                      pkt.underlayer.QOS == 2)),\n        StrLenField(\"value\", \"\",\n                    length_from=lambda pkt: pkt.underlayer.len - pkt.length - 2\n                    if pkt.underlayer.QOS == 0 else\n                    pkt.underlayer.len - pkt.length - 4)\n    ]\n\n\nclass MQTTPuback(Packet):\n    name = \"MQTT puback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrec(Packet):\n    name = \"MQTT pubrec\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrel(Packet):\n    name = \"MQTT pubrel\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubcomp(Packet):\n    name = \"MQTT pubcomp\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTTopic(Packet):\n    name = \"MQTT topic\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\", length_from=lambda pkt:pkt.length)\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass MQTTTopicQOS(MQTTTopic):\n    fields_desc = MQTTTopic.fields_desc + [ByteEnumField(\"QOS\", 0, QOS_LEVEL)]\n\n\nclass MQTTSubscribe(Packet):\n    name = \"MQTT subscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopicQOS)\n    ]\n\n\nALLOWED_RETURN_CODE = {\n    0: 'Success',\n    1: 'Success',\n    2: 'Success',\n    128: 'Failure'\n}\n\n\nclass MQTTSuback(Packet):\n    name = \"MQTT suback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        ByteEnumField(\"retcode\", None, ALLOWED_RETURN_CODE)\n    ]\n\n\nclass MQTTUnsubscribe(Packet):\n    name = \"MQTT unsubscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopic)\n    ]\n\n\nclass MQTTUnsuback(Packet):\n    name = \"MQTT unsuback\"\n    fields_desc = [\n        ShortField(\"msgid\", None)\n    ]\n\n\n# LAYERS BINDINGS\n\nbind_layers(TCP, MQTT, sport=1883)\nbind_layers(TCP, MQTT, dport=1883)\nbind_layers(MQTT, MQTTConnect, type=1)\nbind_layers(MQTT, MQTTConnack, type=2)\nbind_layers(MQTT, MQTTPublish, type=3)\nbind_layers(MQTT, MQTTPuback, type=4)\nbind_layers(MQTT, MQTTPubrec, type=5)\nbind_layers(MQTT, MQTTPubrel, type=6)\nbind_layers(MQTT, MQTTPubcomp, type=7)\nbind_layers(MQTT, MQTTSubscribe, type=8)\nbind_layers(MQTT, MQTTSuback, type=9)\nbind_layers(MQTT, MQTTUnsubscribe, type=10)\nbind_layers(MQTT, MQTTUnsuback, type=11)\nbind_layers(MQTT, MQTTDisconnect, type=14)\nbind_layers(MQTTConnect, MQTT)\nbind_layers(MQTTConnack, MQTT)\nbind_layers(MQTTPublish, MQTT)\nbind_layers(MQTTPuback, MQTT)\nbind_layers(MQTTPubrec, MQTT)\nbind_layers(MQTTPubrel, MQTT)\nbind_layers(MQTTPubcomp, MQTT)\nbind_layers(MQTTSubscribe, MQTT)\nbind_layers(MQTTSuback, MQTT)\nbind_layers(MQTTUnsubscribe, MQTT)\nbind_layers(MQTTUnsuback, MQTT)\nbind_layers(MQTTDisconnect, MQTT)\n", "path": "scapy/contrib/mqtt.py"}]}