-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmainwindow.cpp
323 lines (267 loc) · 9.32 KB
/
mainwindow.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
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->startScanButton,&QPushButton::clicked,this,&MainWindow::startScan);
}
MainWindow::~MainWindow()
{
delete ui;
}
unsigned short MainWindow::CheckSum(unsigned short *buff, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buff++;
size -= sizeof(unsigned short);
}
// 是奇数
if(size)
{
cksum += *(unsigned char*)buff;
}
// 将32位的chsum高16位和低16位相加,然后取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16); // ???
return (unsigned short)(~cksum);
}
int MainWindow::SendEchoRequest(int socketRaw, (const sockaddr *) addrDest,DecodeResult *stDecodeResult)
{
int nRet;
//创建发送的ICMP数据包
char icmpSendBuff[sizeof(IcmpHeader)];
//填充数据包
memset(icmpSendBuff, 0, sizeof(icmpSendBuff));
IcmpHeader * pIcmp=(IcmpHeader *)icmpSendBuff;
//初始化ICMP包
pIcmp->icmp_type=8;
pIcmp->icmp_code=0;
pIcmp->icmp_id=(unsigned short)::GetCurrentProcessId(); //线程号命名
pIcmp->icmp_code = 0;
// pIcmp->icmp_checksum=0;
pIcmp->icmp_sequence=0;
pIcmp->icmp_timestamp=0x01020304; //随意设置
pIcmp->icmp_checksum=CheckSum((unsigned short*)pIcmp, sizeof(IcmpHeader));
stDecodeResult->dwRoundTripTime = gettimeofday();
//开始发送和接受ICMP封包
nRet=sendto(socketRaw,icmpSendBuff,sizeof(icmpSendBuff),MSG_NOSIGNAL,&addrDest,sizeof(sockaddr_in));
//SOCKET_ERROR win下
if (nRet==-1)
{
// cout << "sendto() failed "<< nRet << endl;
return -1;
}
return 0;
}
bool MainWindow::DecodeIcmpResponse(char *pBuf, int iPacketSize, MainWindow::DecodeResult &stDecodeResult,char* timeinfo)
{
IPHeader* pIpHdr = (IPHeader*)pBuf;
int iIpHdrLen = ((IPHeader*)pBuf)->headlen * 4;
// int iIpHdrLen = 20;//IPV4 ip头部,固定20字节
//ip首部占用20字节,定位到icmp报文
IcmpHeader* pIcmpHdr = (IcmpHeader*)(pBuf + iIpHdrLen);
unsigned short usID;
unsigned short usSquNo;
// ICMP回显应答报文
if(pIcmpHdr->icmp_type == 0) {
// 报文ID
usID = pIcmpHdr->icmp_id;
// 序列号
usSquNo = pIcmpHdr->icmp_sequence;
}
// ICMP超时差错报文
else if (pIcmpHdr->icmp_type ==11 )
{
// 载荷中的IP头
char *pInnerIpHdr = pBuf + iIpHdrLen + sizeof(IcmpHeader);
// 载荷中的IP头长
int iInnerIpHdrLen = ((IPHeader*)pInnerIpHdr)->headlen * 4;
// 载荷中的ICMP头
IcmpHeader *pInnerIcmpHdr = (IcmpHeader*)(pInnerIpHdr + iInnerIpHdrLen);
// 报文ID
usID = pInnerIcmpHdr->icmp_id;
// 序列号
usSquNo = pInnerIcmpHdr->icmp_sequence;
}
else {
return false;
}
// if(usID != (USHORT)GetCurrentProcessId() || usSquNo != stDecodeResult.usSeqNo) {
// cout << "usID != (USHORT)GetCurrentProcessId() || usSquNo != stDecodeResult.usSeqNo" << endl;
// return false;
// }
//返回解码结果
stDecodeResult.dwIPaddr.s_addr =((IPHeader*)pBuf)->sourceIP; //linux下 sockaddr_in.sin_addr.s_addr=inet_addr("192.168.0.1");
stDecodeResult.dwRoundTripTime = gettimeofday() - stDecodeResult.dwRoundTripTime;
// 打印往返时间信息
// if(stDecodeResult.dwRoundTripTime) {
// cout << " " << stDecodeResult.dwRoundTripTime << "ms" << endl;
// }
// else {
// cout << " " << "<1" << "ms" << endl;
// }
return true;
}
int MainWindow::RecvEchoReply(int s, sockaddr_in *saFrom, sockaddr_in *saDest, MainWindow::DecodeResult *stDecodeResult,char* destIP)
{
int nRet;
int nAddrLen = sizeof(struct sockaddr_in);
//创建ICMP包接收缓冲区
char IcmpRecvBuf[1024];
memset(IcmpRecvBuf, 0, sizeof(IcmpRecvBuf));
// 接收
nRet = recvfrom(s, // socket
IcmpRecvBuf, // buffer
1024, // size of buffer
0, // flags
(const sockaddr *)&saFrom, // From address
&nAddrLen); // pointer to address len
//打印输出
if (nRet != -1) //接收没有错误
{
char* timeinfo;
//解码得到的数据包
if (DecodeIcmpResponse(IcmpRecvBuf, nRet, *stDecodeResult,timeinfo))
{
// if (stDecodeResult->dwIPaddr.s_addr == saDest->sin_addr.s_addr)
// {
// ui->outputBrowser->append(destIP);
// cout << "alive \n";
// return 1;
// }
// cout << "dwIPaddr.s_addr" << stDecodeResult->dwIPaddr.s_addr << endl;
// cout << "saDest->sin_addr.s_addr" << saDest->sin_addr.s_addr << endl;
// if(stDecodeResult->dwRoundTripTime) {
// char* time_info =" ";
// strcat(time_info,(int)(stDecodeResult->dwRoundTripTime)+"ms ");
// cout << " " << stDecodeResult->dwRoundTripTime << "ms" << endl;
// }
// else {
// char* time_info=" <1ms ";
// cout << " " << "<1" << "ms" << endl;
// }
strcat(destIP," 主机存活");
ui->outputBrowser->append(destIP);
// cout << "alive \n";
return 1;
}
else {
strcat(destIP," 主机没有存活");
ui->outputBrowser->append(destIP);
return -1;
}
}
else
{
strcat(destIP," 请求超时");
ui->outputBrowser->append(destIP);
return -1;
}
return 0;
}
int MainWindow::Ping(char *stdSzDestIP)
{
//linux下声明socket
int socketRaw;
if( (socketRaw = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
//win下下需要用WSAStartup启动Ws2_32.lib,并且要用#pragma comment(lib,"Ws2_32")来告知编译器链接该lib。linux下不需要
// SOCKET socketRaw;
// //目的地址
// WSADATA wsaData;
// iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
// if (iResult != 0)
// {
// cout << "Winsock Initialization failed" <<endl;
// return -1;
// }
//创建原始套接字
//AF_INET表示地址族为IPV4
//SOCK_RAW表示创建的为原始套接字,若在UNIX/LINUX环境下,应该获得root权限,在Windows环境下使用管理员权限运行程序
// socketRaw=::socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
int iResult;
sockaddr_in addrDest, addrSrc;
DecodeResult stDecodeResult;
unsigned short usSeqNo =0;
//超时选项
int nTimeout=5000;
iResult = setsockopt(socketRaw, SOL_SOCKET,SO_RCVTIMEO,(char*)&nTimeout, sizeof(nTimeout));
memset(&stDecodeResult, 0, sizeof(DecodeResult));
addrDest.sin_family = AF_INET;
// addrDest.sin_port = htons(0);
//获取扫描的ip
//win下
addrDest.sin_addr.s_addr=inet_addr(stdSzDestIP); //无法处理255.255.255.255
//linux下
// addrDest.sin_addr.s_addr=inet_addr(stdSzDestIP);
/**发送ICMP Echo请求
*
*/
iResult = SendEchoRequest(socketRaw, &addrDest, &stDecodeResult);
// cout << "SendEchoRequest result" << iResult << endl;
// if (iResult == SOCKET_ERROR)
// {
// if (WSAGetLastError() == WSAEHOSTUNREACH){
//// cout << "目的主机不可达" << endl;
// return -1;
// }
// }
//接收ICMP的EchoReply数据报
iResult = RecvEchoReply(socketRaw, &addrSrc, &addrDest, &stDecodeResult,stdSzDestIP);
// cout << "RecvEchoReply result" << iResult << endl;
//linux下close(...)
close(socketRaw);
//win下
// closesocket(socketRaw);
// WSACleanup();
return 0;
// //初始化数据包
// memset(&icmpSendBuff[sizeof(IcmpHeader)],'E',32);
// USHORT nSeq=0;
// //接收ICMP包缓存区
// char revBuf[1024];
// SOCKADDR_IN from;
// int nLen=sizeof(from);
// //填充ICMP包
// pIcmp->icmp_checksum=0;
// pIcmp->icmp_timestamp=::GetTickCount();
// pIcmp->icmp_sequence=nSeq++;
// pIcmp->icmp_checksum=CheckSum((USHORT *)icmpSendBuff,sizeof(IcmpHeader)+32);
// //接受回显回答
// iResult=::recvfrom(socketRaw,revBuf,1024,0,(sockaddr *)&from,&nLen);
// if (iResult==SOCKET_ERROR)
// {
// cout << stdSzDestIP << "response timeout\n";
// return -1;
// }
// cout <<stdSzDestIP << "live \n" << endl;
// //linux下close(...)
// closesocket(iResult);//win下
// WSACleanup();//win下
// return 0;
}
void MainWindow::startScan()
{
QString startIp = ui->IPBeginInput->text();
char* stdStartIp= startIp.toLatin1().data();
// QString endIp = ui->IPEndInput->text();
// char* stdEndIP = endIp.toLatin1().data();
// char* listIP[10];
// listIP[0]=stdStartIp;
// char* a = stdStartIp;
// for(int coutIP=1; coutIP < 5;coutIP++){
// char* a = increment_address(a);
// listIP[coutIP] = a;
// }
// for (int k = 0; k < 5; k ++) {
// Ping(listIP[k]);
// }
// for( int i=0; i<4; i ++){
Ping(stdStartIp);
}