-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathping.h
More file actions
214 lines (178 loc) · 7.17 KB
/
ping.h
File metadata and controls
214 lines (178 loc) · 7.17 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
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#ifndef PING_H
#define PING_H
#include "ip.h"
struct PingConfig {
mode ping_mode;
int pingCount = -1;
string src_ip;
string dest_ip;
};
class Ping {
private:
int16 count = rand() % 50000;
int16 id, seq;
int16 icmp_payload_size;
type packet_type;
int16 payload_size;
const int8* payload;
const int8* src;
const int8* dest;
int pingCount = 1;
bool show = false;
mode ping_mode;
struct EchoRequestPayload {
int16 id;
int16 seq;
int8 data[];
}packed;
struct PingData {
int16 id, seq;
int bytes_sent = -1;
bool is_ping_sent = false;
};
EchoRequestPayload* createEchoRequestPayload(const int8* payload, int16 payload_size, int16 icmp_payload_size, int16 id, int16 seq) {
EchoRequestPayload* e = (EchoRequestPayload *)malloc(icmp_payload_size);
e->id = utils::endian16(id);
e->seq = utils::endian16(seq);
memcpy(e->data, payload, payload_size);
return e;
}
void show_packets(const IcmpBuilder* icmp, const IpBuilder* ip){
icmp->show_icmp();
ip->show_ip();
}
int32 get_socket() {
int32 s, one;
int tmp;
one = (int32) 1;
tmp = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(tmp > 2) s = (int32)tmp;
else s = (int32)0;
tmp = setsockopt((int)s, SOL_IP, IP_HDRINCL, (int *)&one, sizeof(int32));
if(tmp == -1) cout<<"setting socket option failed\n";
if(tmp) return (int32)0;
return s;
}
PingData sent_ping(const int32 s, const int32 dest_ip, const int8* rawIpBuffer, int16 rawIpBufferSize) {
if(!s) return {id, seq, -1, false};
int bytes_sent = -1;
sockaddr_in sock;
memset(&sock, 0, sizeof(sock));
sock.sin_addr.s_addr = (in_addr_t)dest_ip;
bytes_sent = sendto(
(int) s,
rawIpBuffer,
(int) rawIpBufferSize,
MSG_DONTWAIT,
(const sockaddr *)&sock,
sizeof(sock)
);
return { id, seq, bytes_sent, bytes_sent < 0? false:true };
}
IpBuilder* buildPackets(int seq, const int8* src, const int8* dest, bool show_packet = false) {
if(!dest) return nullptr;
IcmpBuilder* icmpB;
IpBuilder* ipB;
EchoRequestPayload* echoRequestPayload;
echoRequestPayload = createEchoRequestPayload(payload, payload_size, icmp_payload_size, id, seq);
icmpB = new IcmpBuilder(packet_type, icmp_payload_size, (const int8 *)echoRequestPayload);
assert(icmpB);
ipB = new IpBuilder(protocol::ICMP, src, dest, icmpB, 0, &count);
assert(ipB);
if(show_packet) show_packets(icmpB, ipB);
free(echoRequestPayload);
delete icmpB;
return ipB;
}
IpPacket* recvIp(int32 s){
if(!s) return (IpPacket *)0;
int8 rawIpBuffer[1600];
int16 id, bytes_read, csum, orgCheck, ipHeaderLength, totalIpPacketLength;
vector<int8> src_vec, dest_vec;
const int8* src, *dest;
const int8* icmpPayload;
protocol protocol_type;
IpBuilder* ipBuilder;
IcmpBuilder* icmpBuilder;
int icmpPayloadSize;
type icmp_type;
memset(rawIpBuffer, 0, 1600);
int ret = recvfrom((int)s, &rawIpBuffer, 1599, 0, 0, 0);
if(ret < 0) return (IpPacket *)0;
else bytes_read = (int16)ret;
(void)bytes_read;
RawIpPacket* rawIpPacket = (RawIpPacket *)rawIpBuffer;
orgCheck = rawIpPacket->checksum;
rawIpPacket->checksum = (int16)0;
id = utils::endian16(rawIpPacket->id);
ipHeaderLength = (rawIpPacket->ver_ihl & 0x0f) * 4;
totalIpPacketLength = utils::endian16(rawIpPacket->length);
src_vec = utils::getStringToByteVector(utils::convertIpToString(rawIpPacket->src));
dest_vec = utils::getStringToByteVector(utils::convertIpToString(rawIpPacket->dest));
src = src_vec.data();
dest = dest_vec.data();
protocol_type = (rawIpPacket->protocol == 1? protocol::ICMP:protocol::UNASSIGNED_PROTO);
csum = utils::checksum(rawIpBuffer, totalIpPacketLength);
// printf("CHECKSUM CALCULATED: 0x%04X\nCHECKSUM IN PACKET: 0x%04X\n", csum, orgCheck);
if(csum != orgCheck){
throw runtime_error("Packet checksum invalid: corrupted or malformed packet");
}
if(protocol_type == protocol::UNASSIGNED_PROTO){
throw runtime_error("Unsupported packet type");
}
const int8* rawIcmpBuffer = (const int8*)(rawIpBuffer + ipHeaderLength);
const RawIcmpPacket* rawIcmpPacket = (RawIcmpPacket *)rawIcmpBuffer;
icmpPayloadSize = (int)totalIpPacketLength - (int)ipHeaderLength - (int)sizeof(RawIcmpPacket);
if(icmpPayloadSize <= 0) icmpPayload = nullptr;
else icmpPayload = (const int8 *)(rawIcmpBuffer + sizeof(RawIcmpPacket));
if(rawIcmpPacket->type == 8 && rawIcmpPacket->code == 0) icmp_type = type::ECHO;
else if(rawIcmpPacket->type == 0 && rawIcmpPacket->code == 0) icmp_type = type::ECHOREPLY;
else icmp_type = type::UNASSIGNED;
icmpBuilder = new IcmpBuilder(icmp_type, static_cast<int16>(icmpPayloadSize), icmpPayload);
ipBuilder = new IpBuilder(protocol_type, (const int8 *)src, (const int8 *)dest, icmpBuilder, id, 0);
delete icmpBuilder;
IpPacket* ipPacket = new IpPacket(*ipBuilder->get_ip_packet());
delete ipBuilder;
return ipPacket;
}
public:
Ping(type packet_type, int16 payload_size, const int8* payload, const int8* src, const int8* dest, int pingCount = 1, bool show = false)
: packet_type(packet_type), payload_size(payload_size), payload(payload), src(src), dest(dest), pingCount(pingCount), show(show) {
icmp_payload_size = payload_size + sizeof(EchoRequestPayload);
id = 5000;
seq = 1;
}
~Ping() { }
void recv() {
IpPacket* ipPacket = recvIp(get_socket());
if(!ipPacket) cout<<"Error\n";
else{
cout<<"Source: "<<utils::convertIpToString(ipPacket->src)<<"\n"
<<"Destination: "<<utils::convertIpToString(ipPacket->dest)<<"\n"
<<"Packet ID: "<<ipPacket->id<<"\n"
<<"protocol: "<<(ipPacket->protocol_type == protocol::ICMP? "ICMP" : "UNDEFINED")<<"\n";
}
}
void sent() {
int c = 0;
const int32 soc = get_socket();
while(pingCount < 0 || c < pingCount){
IpBuilder* ipBuilder = buildPackets(seq, src, dest, show);
if(!ipBuilder) {
cerr<<"IP Builder failed to create raw ip buffer\n";
continue;
}
PingData pingData = sent_ping(soc, ipBuilder->get_dest_ip(), ipBuilder->get_raw_ip_buffer(), ipBuilder->get_raw_ip_buffer_size());
cout<<"PING: "<<(pingData.is_ping_sent?"true":"false")
<<", ID: "<<pingData.id
<<", seq: "<<pingData.seq
<<", bytes sent: "<<pingData.bytes_sent<<"\n";
delete ipBuilder;
++c;
++seq;
this_thread::sleep_for(chrono::seconds(1));
}
close(soc);
}
};
#endif