| 629 | return self.pcap_fd.send(sx) |
| 630 | |
| 631 | class L3pcapSocket(L2pcapSocket): |
| 632 | desc = "read/write packets at layer 3 using only libpcap" |
| 633 | |
| 634 | def __init__(self, *args, **kwargs): |
| 635 | # type: (*Any, **Any) -> None |
| 636 | super(L3pcapSocket, self).__init__(*args, **kwargs) |
| 637 | self.send_socks = {network_name(self.iface): self} |
| 638 | |
| 639 | def recv(self, x=MTU, **kwargs): |
| 640 | # type: (int, **Any) -> Optional[Packet] |
| 641 | r = L2pcapSocket.recv(self, x, **kwargs) |
| 642 | if r and self.lvl == 2: |
| 643 | r.payload.time = r.time |
| 644 | return r.payload |
| 645 | return r |
| 646 | |
| 647 | def send(self, x): |
| 648 | # type: (Packet) -> int |
| 649 | # Select the file descriptor to send the packet on. |
| 650 | iff = x.route()[0] |
| 651 | if iff is None: |
| 652 | iff = network_name(conf.iface) |
| 653 | type_x = type(x) |
| 654 | if iff not in self.send_socks: |
| 655 | self.send_socks[iff] = L3pcapSocket( |
| 656 | iface=iff, |
| 657 | type=self.type, |
| 658 | filter=self.filter, |
| 659 | promisc=self.promisc, |
| 660 | monitor=self.monitor, |
| 661 | ) |
| 662 | sock = self.send_socks[iff] |
| 663 | fd = sock.pcap_fd |
| 664 | if sock.lvl == 3: |
| 665 | if not issubclass(sock.LL, type_x): |
| 666 | warning("Incompatible L3 types detected using %s instead of %s !", |
| 667 | type_x, sock.LL) |
| 668 | sock.LL = type_x |
| 669 | if sock.lvl == 2: |
| 670 | sx = bytes(sock.LL() / x) |
| 671 | else: |
| 672 | sx = bytes(x) |
| 673 | # Now send. |
| 674 | try: |
| 675 | x.sent_time = time.time() |
| 676 | except AttributeError: |
| 677 | pass |
| 678 | return fd.send(sx) |
| 679 | |
| 680 | @staticmethod |
| 681 | def select(sockets, remain=None): |
| 682 | # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket] |
| 683 | socks = [] # type: List[SuperSocket] |
| 684 | for sock in sockets: |
| 685 | if isinstance(sock, L3pcapSocket): |
| 686 | socks += sock.send_socks.values() |
| 687 | else: |
| 688 | socks.append(sock) |