Created
October 18, 2014 00:53
-
-
Save uchan-nos/1c3b9da6c675412f1dd0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <cstdio> | |
| #include <cstdlib> | |
| #include <vector> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <sys/stat.h> | |
| #include <sys/socket.h> | |
| #include <sys/types.h> | |
| #include <sys/time.h> | |
| #include <sys/ioctl.h> | |
| #include <net/bpf.h> | |
| #include <net/if.h> | |
| #include <net/ethernet.h> | |
| using namespace std; | |
| int OpenBPF() { | |
| char buf[11]; | |
| for (int i = 0; i < 99; ++i) { | |
| sprintf(buf, "/dev/bpf%d", i); | |
| int bpf = open(buf, O_RDWR); | |
| if (bpf != -1) { | |
| return bpf; | |
| } | |
| } | |
| return -1; | |
| } | |
| void PrintMAC(unsigned char* mac) { | |
| printf("%02x", mac[0]); | |
| for (int i = 1; i < 6; ++i) { | |
| printf(":%02x", mac[i]); | |
| } | |
| } | |
| int main() { | |
| int bpf = OpenBPF(); | |
| if (bpf == -1) { | |
| perror("failed to open /dev/bpf*"); | |
| exit(-1); | |
| } | |
| const char* network_interface = "en0"; | |
| struct ifreq bound_if; | |
| // bound network interface to bpf | |
| strcpy(bound_if.ifr_name, network_interface); | |
| if (ioctl(bpf, BIOCSETIF, &bound_if) == -1) { | |
| perror("failed to associate bpf to network interface"); | |
| exit(-1); | |
| } | |
| int int_true = 1; | |
| int buf_len = 0; | |
| // activate immediate mode (no buffer) | |
| if (ioctl(bpf, BIOCIMMEDIATE, &int_true) == -1) { | |
| perror("failed to activate immediate mode"); | |
| exit(-1); | |
| } | |
| // request buffer length | |
| if (ioctl(bpf, BIOCGBLEN, &buf_len) == -1) { | |
| perror("failed to get buffer length"); | |
| exit(-1); | |
| } | |
| vector<char> bpf_buf(buf_len); | |
| size_t i; | |
| struct bpf_hdr* bh = nullptr; | |
| struct ether_header* eh = nullptr; | |
| // capture packets | |
| while (1) { | |
| int n = read(bpf, bpf_buf.data(), bpf_buf.size()); | |
| if (n == -1) { | |
| perror("failed to read"); | |
| exit(-1); | |
| } | |
| i = 0; | |
| while (i < n) { | |
| bh = reinterpret_cast<struct bpf_hdr*>(bpf_buf.data() + i); | |
| // ethernetフレームはBPFヘッダの直後から始まる | |
| eh = reinterpret_cast<struct ether_header*>(bpf_buf.data() + i + bh->bh_hdrlen); | |
| // print MAC address | |
| PrintMAC(eh->ether_shost); | |
| printf(" -> "); | |
| PrintMAC(eh->ether_dhost); | |
| printf(" [type=%u]\n", eh->ether_type); | |
| i += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment