Created
October 18, 2014 01:45
-
-
Save uchan-nos/5c6f12fb1bebdecd983b 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 <cstring> | |
| #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]); | |
| } | |
| } | |
| void CapturePackets(int bpf, int buf_len) { | |
| 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=%x]\n", ntohs(eh->ether_type)); | |
| //printf(" caplen=%u, datalen=%u, hdrlen=%u\n", bh->bh_caplen, bh->bh_datalen, bh->bh_hdrlen); | |
| fflush(stdout); | |
| i += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); | |
| } | |
| } | |
| } | |
| void SendPacket(int bpf, int buf_len) { | |
| const int BPF_HDRLEN = /*18*/0; | |
| const int ETHERLEN = 60; | |
| vector<char> buf(BPF_HDRLEN + ETHERLEN); | |
| //struct bpf_hdr* bh = reinterpret_cast<struct bpf_hdr*>(buf.data()); | |
| struct ether_header* eh = reinterpret_cast<struct ether_header*>(buf.data() + BPF_HDRLEN); | |
| //bh->bh_hdrlen = BPF_HDRLEN; | |
| //bh->bh_caplen = bh->bh_datalen = ETHERLEN; | |
| memcpy(eh->ether_shost, "\x84\x38\x35\x4b\x41\xa2", 6); | |
| memcpy(eh->ether_dhost, "\x52\x54\x00\x81\x39\x00", 6); | |
| eh->ether_type = htons(0x0101); | |
| write(bpf, buf.data(), buf.size()); | |
| } | |
| 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); | |
| } | |
| #ifndef ETHER_SEND | |
| CapturePackets(bpf, buf_len); | |
| #else | |
| SendPacket(bpf, buf_len); | |
| #endif | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment