Send a packet
(self, pkt)
| 494 | return r |
| 495 | |
| 496 | def send(self, pkt): |
| 497 | # type: (Packet) -> int |
| 498 | """Send a packet""" |
| 499 | from scapy.layers.l2 import Loopback |
| 500 | |
| 501 | # Use the routing table to find the output interface |
| 502 | iff = pkt.route()[0] |
| 503 | if iff is None: |
| 504 | iff = network_name(conf.iface) |
| 505 | |
| 506 | # Assign the network interface to the BPF handle |
| 507 | if iff not in self.send_socks: |
| 508 | self.send_socks[iff] = L3bpfSocket( |
| 509 | iface=iff, |
| 510 | type=self.type, |
| 511 | filter=self.filter, |
| 512 | promisc=self.promisc, |
| 513 | ) |
| 514 | fd = self.send_socks[iff] |
| 515 | |
| 516 | # Build the frame |
| 517 | # |
| 518 | # LINKTYPE_NULL / DLT_NULL (Loopback) is a special case. From the |
| 519 | # bpf(4) man page (from macOS/Darwin, but also for BSD): |
| 520 | # |
| 521 | # "A packet can be sent out on the network by writing to a bpf file |
| 522 | # descriptor. [...] Currently only writes to Ethernets and SLIP links |
| 523 | # are supported." |
| 524 | # |
| 525 | # Headers are only mentioned for reads, not writes, and it has the |
| 526 | # name "NULL" and id=0. |
| 527 | # |
| 528 | # The _correct_ behaviour appears to be that one should add a BSD |
| 529 | # Loopback header to every sent packet. This is needed by FreeBSD's |
| 530 | # if_lo, and Darwin's if_lo & if_utun. |
| 531 | # |
| 532 | # tuntaposx appears to have interpreted "NULL" as "no headers". |
| 533 | # Thankfully its interfaces have a different name (tunX) to Darwin's |
| 534 | # if_utun interfaces (utunX). |
| 535 | # |
| 536 | # There might be other drivers which make the same mistake as |
| 537 | # tuntaposx, but these are typically provided with VPN software, and |
| 538 | # Apple are breaking these kexts in a future version of macOS... so |
| 539 | # the problem will eventually go away. They already don't work on Macs |
| 540 | # with Apple Silicon (M1). |
| 541 | if DARWIN and iff.startswith('tun') and self.guessed_cls == Loopback: |
| 542 | frame = pkt |
| 543 | elif FREEBSD and (iff.startswith('tun') or iff.startswith('tap')): |
| 544 | # On FreeBSD, the bpf manpage states that it is only possible |
| 545 | # to write packets to Ethernet and SLIP network interfaces |
| 546 | # using /dev/bpf |
| 547 | # |
| 548 | # Note: `open("/dev/tun0", "wb").write(raw(pkt())) should be |
| 549 | # used |
| 550 | warning("Cannot write to %s according to the documentation!", iff) |
| 551 | return |
| 552 | else: |
| 553 | frame = fd.guessed_cls() / pkt |
nothing calls this directly
no test coverage detected