Skip to content

Support IP layer mode on macOS#776

Merged
zakird merged 4 commits intozmap:mainfrom
droe:droe/iplayer-macos
Feb 11, 2024
Merged

Support IP layer mode on macOS#776
zakird merged 4 commits intozmap:mainfrom
droe:droe/iplayer-macos

Conversation

@droe
Copy link
Contributor

@droe droe commented Feb 10, 2024

  • Implement IP layer mode on macOS using socket(PF_INET, SOCK_RAW, IPPROTO_RAW) and setsockopt(IP_HDRINCL)
  • Teach recv-pcap to handle BSD loopback encapsulation as used by macOS utun interfaces
  • While here fix file descriptor leaks in bpf failure paths

Deliberately ifdef'ed macOS-specific code with __APPLE__ such that in the future, the code can be shared amongst macOS and BSDs lacking sendmmsg. If/when I get around to implement sendmmsg for BSD, I'll likely propose to split send code into bsd-legacy and bsd-sendmmsg, instead of send-bsd and send-mac with largely duplicate code for the "no sendmmsg available" case.

@zakird
Copy link
Member

zakird commented Feb 10, 2024

Overall makes sense. One question:

Deliberately ifdef'ed macOS-specific code with APPLE such that in the future, the code can be shared amongst macOS and BSDs lacking sendmmsg.

This makes sense, but I'm not sure if the code in that block is actually Apple-specific. It seems that the host-order part:

	 BSD loopback encapsulation; the link layer header is a	4-byte
	 field,	 in  host  byte	 order,	 containing  a	PF_ value from
	 socket.h for the network-layer	protocol of the	packet

Is for BSD more broadly.

@droe
Copy link
Contributor Author

droe commented Feb 10, 2024

The ifdef __APPLE__ is on the send path, the byte order comment there applies only to IP header fields when sending through a raw IP socket (as opposed to BPF device, used by zmap when -X is not given), and is independent of the link layer type of the interface. The packet sent to the socket begins with the IP header and has no link layer header. macOS requires the off and len fields of the IP header in host byte order when sending via raw IP sockets. FreeBSD used to require them in host byte order too, back when Apple forked the BSD portion of XNU from FreeBSD 4, but since FreeBSD 11, FreeBSD takes those fields in network byte order. When sending with those fields in host byte order on FreeBSD 14, or when sending with those fields in network byte order on macOS Sonoma, you get EINVAL from the sendto() calls. This can also be verified by comparing the «Raw IP Sockets» and «BUGS» sections of ip(4) for macOS and different versions of FreeBSD. We could cater for old FreeBSD too by checking for __FreeBSD_version < 1100030.

The BSD loopback encapsulation change on the other hand is on the libpcap receive path, and is only relevant to certain types of interfaces, including utun on macOS, which is used by at least some VPN software on macOS. I have not ifdef'ed that to __APPLE__, as it seems to compile fine on Linux etc too. The commit adding recv support for BSD loopback encapsulation is orthogonal to the rest of the changeset; sending in IP layer mode works without it. Zmap would not be able to receive packets over utun interfaces tho. Byte order of the protocol field in the BSD loopback encapsulation header is currently irrelevant, as zmap never interprets it.

@zakird zakird merged commit 45d7ab5 into zmap:main Feb 11, 2024
@droe droe deleted the droe/iplayer-macos branch March 11, 2024 08:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants