-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
148 lines (132 loc) · 5.27 KB
/
main.cpp
File metadata and controls
148 lines (132 loc) · 5.27 KB
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
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <cstring>
#include <net/ethernet.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <iomanip>
#pragma pack(1)
typedef struct {
uint8_t dst_mac[6]; // Destination MAC address [x]
uint8_t src_mac[6]; // Source MAC address [x]
uint16_t ether_type; // Ethernet type [x]
uint16_t hw_type; // Hardware type [x]
uint16_t proto_type; // Protocol type [x]
uint8_t hw_size; // Hardware address length [x]
uint8_t proto_size; // Protocol address length [x]
uint16_t opcode; // Operation code (request or reply) [x]
uint8_t sender_mac[6]; // Sender MAC address [x]
uint32_t sender_ip; // Sender IP [x]
uint8_t target_mac[6]; // Target MAC [x]
uint32_t target_ip; // Target IP [x]
} arp_packet;
int createSocket() {
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
return sockfd;
}
int obtainSubnetMask(const std::string& interface) {
struct ifreq ifr;
strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
int tmp = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(tmp, SIOCGIFNETMASK, &ifr);
struct sockaddr_in* mask = (struct sockaddr_in*)&ifr.ifr_netmask;
close(tmp);
return mask->sin_addr.s_addr;
}
int obtainIPAddress(const std::string& interface) {
struct ifreq ifr;
strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
int tmp = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(tmp, SIOCGIFADDR, &ifr);
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
close(tmp);
return addr->sin_addr.s_addr;
}
int sendTo(int sockfd, const std::string& ip_address, const std::string& interface) {
struct sockaddr_ll dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sll_family = AF_PACKET;
dest_addr.sll_protocol = htons(ETH_P_ARP);
struct ifreq ifr;
strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
ioctl(sockfd, SIOCGIFINDEX, &ifr);
dest_addr.sll_ifindex = ifr.ifr_ifindex;
arp_packet pkt;
memset(&pkt, 0, sizeof(pkt));
pkt.proto_type = htons(0x0800); // IPv4
pkt.proto_size = 4; // IPv4 address length
pkt.hw_type = htons(1); // Ethernet
pkt.hw_size = 6; // MAC address length
pkt.opcode = htons(1); // ARP request
pkt.ether_type = htons(ETH_P_ARP); // Ethernet type for ARP
ioctl(sockfd, SIOCGIFHWADDR, &ifr); // Get the MAC address of the interface
memcpy(pkt.src_mac, ifr.ifr_hwaddr.sa_data, 6); // Source MAC address
memcpy(pkt.sender_mac, ifr.ifr_hwaddr.sa_data, 6); // Sender MAC
memset(pkt.dst_mac, 0xff, 6); // Broadcast MAC address
ioctl(sockfd, SIOCGIFADDR, &ifr); // Get the IP address of the interface
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
pkt.sender_ip = addr->sin_addr.s_addr; // Sender IP
inet_pton(AF_INET, ip_address.c_str(), &pkt.target_ip); // Target IP address
int result = sendto(sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
return result;
}
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <INTERFACE>" << std::endl;
return 1;
}
std::string interface = argv[1];
struct ifreq ifr;
strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
int tmp = socket(AF_INET, SOCK_DGRAM, 0);
if (ioctl(tmp, SIOCGIFINDEX, &ifr) < 0) {
std::cerr << "Interface not found: " << interface << std::endl;
close(tmp);
return 1;
}
close(tmp);
int sockfd = createSocket();
int32_t subnetMask = obtainSubnetMask(interface);
struct in_addr mask_addr;
mask_addr.s_addr = subnetMask;
std::cout << "Subnet Mask: " << inet_ntoa(mask_addr) << std::endl;
int32_t ipAddress = obtainIPAddress(interface);
struct in_addr ip_addr;
ip_addr.s_addr = ipAddress;
uint32_t network_prefix = ipAddress & subnetMask;
uint32_t broadcast_address = network_prefix | ~subnetMask;
std::cout << "Scanning network: " << inet_ntoa(ip_addr) << "/" << inet_ntoa(mask_addr) << std::endl;
uint32_t start = ntohl(network_prefix) + 1;
uint32_t end = ntohl(broadcast_address);
for (uint32_t i = start; i < end; ++i) {
struct in_addr a; a.s_addr = htonl(i);
sendTo(sockfd, inet_ntoa(a), interface);
};
struct timeval tv = {2, 0};
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
while (true) {
arp_packet pkt;
int rsp = recvfrom(sockfd, &pkt, sizeof(pkt), 0, NULL, NULL);
if (rsp < 0) break;
if (pkt.opcode == htons(2)) {
struct in_addr sender;
sender.s_addr = pkt.sender_ip;
std::cout << "Device alive! IP: " << inet_ntoa(sender) << " MAC: "
<< std::hex << std::setfill('0')
<< std::setw(2) << (int)pkt.sender_mac[0] << ":"
<< std::setw(2) << (int)pkt.sender_mac[1] << ":"
<< std::setw(2) << (int)pkt.sender_mac[2] << ":"
<< std::setw(2) << (int)pkt.sender_mac[3] << ":"
<< std::setw(2) << (int)pkt.sender_mac[4] << ":"
<< std::setw(2) << (int)pkt.sender_mac[5]
<< std::dec << std::endl;
}
}
close(sockfd);
return 0;
}