How to write cross-platform packet capture from scratch in 1000 LOC.

How supports the both of Linux and macOS

RAW Socket

struct timeval timeout;
fd_set mask;
int width, len, ready;
while (g_gotsig == 0) {
FD_ZERO(&mask);
FD_SET(soc, &mask);
width = doc + 1;
timeout.tv_sec = 8;
timeout.tv_usec = 0;
ready = select(width, &mask, NULL, NULL, &timeout);
if (ready == -1) {
perror("select");
break;
} else if (ready == 0) {
fprintf(stderr, "select timeout");
break;
}
if (FD_ISSET(sniffer->fd, &mask)){
if ((len = recv(soc, buffer, >buf_len, 0)) == -1){
perror("recv:");
return -1;
}
}
}

Berkeley Packet Filters

$ ls /dev/bpf?
/dev/bpf0 /dev/bpf1 /dev/bpf2 /dev/bpf3 /dev/bpf4 /dev/bpf5 /dev/bpf6 /dev/bpf7 /dev/bpf8 /dev/bpf9
typedef struct {
int fd;
char device[11];
unsigned int buf_len;
char *buffer;
unsigned int last_read_len;
unsigned int read_bytes_consumed;
} Sniffer;
int
parse_bpf_packets(Sniffer *sniffer, CapturedInfo *info)
{
if (sniffer->read_bytes_consumed + sizeof(sniffer->buffer)
>= sniffer->last_read_len) {
return 0;
}
info->bpf_hdr = (struct bpf_hdr*)((long)sniffer->buffer +
(long)sniffer->read_bytes_consumed);
info->data = sniffer->buffer + \
(long)sniffer->read_bytes_consumed + \
info->bpf_hdr->bh_hdrlen;
sniffer->read_bytes_consumed += BPF_WORDALIGN(
info->bpf_hdr->bh_hdrlen + info->bpf_hdr->bh_caplen);
return info->bpf_hdr->bh_datalen;
}

References

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store