| 540 | |
| 541 | |
| 542 | class IP(Packet, IPTools): |
| 543 | name = "IP" |
| 544 | fields_desc = [BitField("version", 4, 4), |
| 545 | BitField("ihl", None, 4), |
| 546 | XByteField("tos", 0), |
| 547 | ShortField("len", None), |
| 548 | ShortField("id", 1), |
| 549 | FlagsField("flags", 0, 3, ["MF", "DF", "evil"]), |
| 550 | BitField("frag", 0, 13), |
| 551 | ByteField("ttl", 64), |
| 552 | ByteEnumField("proto", 0, IP_PROTOS), |
| 553 | XShortField("chksum", None), |
| 554 | # IPField("src", "127.0.0.1"), |
| 555 | Emph(SourceIPField("src")), |
| 556 | Emph(DestIPField("dst", "127.0.0.1")), |
| 557 | PacketListField("options", [], IPOption, length_from=lambda p:p.ihl * 4 - 20)] # noqa: E501 |
| 558 | |
| 559 | def post_build(self, p, pay): |
| 560 | ihl = self.ihl |
| 561 | p += b"\0" * ((-len(p)) % 4) # pad IP options if needed |
| 562 | if ihl is None: |
| 563 | ihl = len(p) // 4 |
| 564 | p = chb(((self.version & 0xf) << 4) | ihl & 0x0f) + p[1:] |
| 565 | if self.len is None: |
| 566 | tmp_len = len(p) + len(pay) |
| 567 | p = p[:2] + struct.pack("!H", tmp_len) + p[4:] |
| 568 | if self.chksum is None: |
| 569 | ck = checksum(p) |
| 570 | p = p[:10] + chb(ck >> 8) + chb(ck & 0xff) + p[12:] |
| 571 | return p + pay |
| 572 | |
| 573 | def extract_padding(self, s): |
| 574 | tmp_len = self.len - (self.ihl << 2) |
| 575 | if tmp_len < 0: |
| 576 | return s, b"" |
| 577 | return s[:tmp_len], s[tmp_len:] |
| 578 | |
| 579 | def route(self): |
| 580 | dst = self.dst |
| 581 | scope = None |
| 582 | if isinstance(dst, (Net, _ScopedIP)): |
| 583 | scope = dst.scope |
| 584 | if isinstance(dst, (Gen, list)): |
| 585 | dst = next(iter(dst)) |
| 586 | if conf.route is None: |
| 587 | # unused import, only to initialize conf.route |
| 588 | import scapy.route # noqa: F401 |
| 589 | return conf.route.route(dst, dev=scope) |
| 590 | |
| 591 | def hashret(self): |
| 592 | if ((self.proto == socket.IPPROTO_ICMP) and |
| 593 | (isinstance(self.payload, ICMP)) and |
| 594 | (self.payload.type in [3, 4, 5, 11, 12])): |
| 595 | return self.payload.payload.hashret() |
| 596 | if not conf.checkIPinIP and self.proto in [4, 41]: # IP, IPv6 |
| 597 | return self.payload.hashret() |
| 598 | if self.dst == "224.0.0.251": # mDNS |
| 599 | return struct.pack("B", self.proto) + self.payload.hashret() |
no test coverage detected