저는 네트워크 패킷에 대한 저수준 인터페이스에 관심이 있습니다. 내가 이해한 바에 따르면 tcpdump 및 libpcap과 같은 도구는 BPF 패킷 필터링 장치 /dev/bpf*를 사용하여 링크 계층 네트워크 패킷(Mac OS X 및 FreeBSD에서)을 읽습니다.
그런데 /dev/bpf*의 데이터는 어디서 오는 걸까요? 아래에서 위로 시작하면 먼저 하드웨어 네트워크 카드(Wi-Fi의 전파)에서 데이터를 읽습니다. 그런 다음 네트워크 카드 드라이버는 이러한 패킷을 읽고 이를 커널에 제공합니다. 예를 들어, 내 컴퓨터에서 네트워크 카드는 Airport Brcm_4331이고 해당 드라이버는 IOReg에 "com.apple.driver.AirPort.Brcm4331"로 나열되어 있습니다. 하지만 소켓 계층에서 보거나 ifconfig를 사용하여 보면 네트워크 인터페이스가 "en0"이라고 합니다. 이는 bpf 패킷 캡처 API를 사용할 때 제공하는 인터페이스 이름이기도 합니다.
그렇다면 Airport Brcm_4331 카드의 실제 드라이버와 일반 "en0" 인터페이스 사이의 차이점은 무엇입니까?
내 생각에는 네트워크 카드 드라이버 자체가 원시 패킷을 읽을 수 있는 일반 인터페이스를 제공하는 것 같습니다. 따라서 하드웨어(물리적 계층, Wi-Fi)에서 패킷을 읽은 다음 장치 독립적인 방식으로 데이터 링크 계층(이더넷)에 대한 패킷을 읽는 몇 가지 표준 기능을 제공합니다. 이것이 소위 "en0" 인터페이스입니다. 그런 다음 bpf는 "en0" 인터페이스에서 데이터를 읽고 해당 데이터를 /dev/bpf 파일에 기록하여 Unix 파일과 유사한 인터페이스를 제공합니다.
그렇죠? 그렇다면 bpf API를 사용하지 않고 드라이버와 직접 상호 작용하는 코드를 작성할 수 있습니까? 이 항목에 대한 문서를 찾기가 어렵기 때문에 이 수준에서 정말 혼란스럽습니다. 실제 드라이버와 상호 작용하는 방식을 설명하지 않고 고급 Unix API(원시 소켓, libpcap 및 bpf)만 논의하는 경우가 많습니다.