| 398 | |
| 399 | |
| 400 | class TCPOptionsField(StrField): |
| 401 | islist = 1 |
| 402 | |
| 403 | def getfield(self, pkt, s): |
| 404 | opsz = (pkt.dataofs - 5) * 4 |
| 405 | if opsz < 0: |
| 406 | log_runtime.info( |
| 407 | "bad dataofs (%i). Assuming dataofs=5", pkt.dataofs |
| 408 | ) |
| 409 | opsz = 0 |
| 410 | return s[opsz:], self.m2i(pkt, s[:opsz]) |
| 411 | |
| 412 | def m2i(self, pkt, x): |
| 413 | opt = [] |
| 414 | while x: |
| 415 | onum = orb(x[0]) |
| 416 | if onum == 0: |
| 417 | opt.append(("EOL", None)) |
| 418 | break |
| 419 | if onum == 1: |
| 420 | opt.append(("NOP", None)) |
| 421 | x = x[1:] |
| 422 | continue |
| 423 | try: |
| 424 | olen = orb(x[1]) |
| 425 | except IndexError: |
| 426 | olen = 0 |
| 427 | if olen < 2: |
| 428 | log_runtime.info( |
| 429 | "Malformed TCP option (announced length is %i)", olen |
| 430 | ) |
| 431 | olen = 2 |
| 432 | oval = x[2:olen] |
| 433 | if onum in TCPOptions[0]: |
| 434 | oname, ofmt = TCPOptions[0][onum] |
| 435 | if onum == 5: # SAck |
| 436 | ofmt += "%iI" % (len(oval) // 4) |
| 437 | if onum == 29: # AO |
| 438 | oval = TCPAOValue(oval) |
| 439 | if ofmt and struct.calcsize(ofmt) == len(oval): |
| 440 | oval = struct.unpack(ofmt, oval) |
| 441 | if len(oval) == 1: |
| 442 | oval = oval[0] |
| 443 | opt.append((oname, oval)) |
| 444 | else: |
| 445 | opt.append((onum, oval)) |
| 446 | x = x[olen:] |
| 447 | return opt |
| 448 | |
| 449 | def i2h(self, pkt, x): |
| 450 | if not x: |
| 451 | return [] |
| 452 | return x |
| 453 | |
| 454 | def i2m(self, pkt, x): |
| 455 | opt = b"" |
| 456 | for oname, oval in x: |
| 457 | # We check for a (0, b'') or (1, b'') option first |