/*++
Copyright (C) 2001-2004 shadowstar's home, All rights reserved.
http://shadowstar.126.com/
Reversion History:
2004-07-15 修正在WinXP下开始嗅探后出现假死现象的问题
2002-05-25 实现简单的嗅探功能,Win2k/9x下测试通过
Note:
需要在工程文件里加入WS2_32.LIB这个文件,位置在
"D:\Program Files\Borland\CBuilder6\Lib\Psdk\ws2_32.lib"
shadowstar不明白为什么不加这个LIB也可以编译
--*/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include "netmon.h"
#include "WMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
// #pragma command(lib, "ws2_32.lib") // 在BCB6下这句代码似乎不起作用
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
WSADATA WSAData;
BOOL flag = true;
int nTimeout = 1000;
char LocalName[40];
struct hostent *pHost;
//检查 Winsock 版本号
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
throw Exception("WSAStartup error!");
//初始化 Raw Socket
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
throw Exception("socket setup error!");
//设置IP头操作选项
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR)
throw Exception("setsockopt IP_HDRINCL error!");
//获取本机名
if (gethostname((char*)LocalName, sizeof(LocalName)-1) == SOCKET_ERROR)
throw Exception("gethostname error!");
//获取本地 IP 地址
if ((pHost = gethostbyname((char*)LocalName)) == NULL)
throw Exception("gethostbyname error!");
addr_in.sin_addr = *(in_addr *)pHost->h_addr_list[0]; //IP
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(57274);
//把 sock 绑定到本地地址上
if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR)
throw Exception("bind error!");
iSortDirection = 1;
}
//---------------------------------------------------------------------------
__fastcall TMainForm::~TMainForm()
{
closesocket(sock);
WSACleanup();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::btnCtrlClick(TObject *Sender)
{
TListItem *Item;
DWORD dwValue;
int nIndex = 0;
if (btnCtrl->Caption == "&Start")
{
ShowMessage("start sniffer...");
dwValue = 1;
//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0)
throw Exception("ioctlsocket SIO_RCVALL error!");
bStop = false;
btnCtrl->Caption = "&Stop";
lsvPacket->Items->Clear();
}
else
{
ShowMessage("stop sniffer.");
dwValue = 0;
bStop = true;
btnCtrl->Caption = "&Start";
//设置SOCK_RAW为SIO_RCVALL,停止接收
if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0)
throw Exception("WSAIoctl SIO_RCVALL error!");
}
while (!bStop)
{
if (recv(sock, RecvBuf, BUFFER_SIZE, 0) > 0)
{
nIndex++;
ip = *(IP*)RecvBuf;
tcp = *(TCP*)(RecvBuf + (ip.HdrLen & IP_HDRLEN_MASK));
Item = lsvPacket->Items->Add();
Item->Caption = nIndex;
Item->SubItems->Add(GetProtocolTxt(ip.Protocol));
Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.SrcAddr));
Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.DstAddr));
Item->SubItems->Add(tcp.SrcPort);
Item->SubItems->Add(tcp.DstPort);
Item->SubItems->Add(ntohs(ip.TotalLen));
}
Application->ProcessMessages();
}
}
//---------------------------------------------------------------------------
AnsiString __fastcall TMainForm::GetProtocolTxt(int Protocol)
{
switch (Protocol)
{
case IPPROTO_IP : //0 /* dummy for IP */
return PROTOCOL_STRING_IP_TXT;
case IPPROTO_ICMP : //1 /* control message protocol */
return PROTOCOL_STRING_ICMP_TXT;
case IPPROTO_TCP : //6 /* tcp */
return PROTOCOL_STRING_TCP_TXT;
case IPPROTO_UDP : //17 /* user datagram protocol */
return PROTOCOL_STRING_UDP_TXT;
default :
return PROTOCOL_STRING_UNKNOWN_TXT;
}
}
void __fastcall TMainForm::lsvPacketColumnClick(TObject *Sender,
TListColumn *Column)
{
//排序方式,如果还是原来的一列反向
iSortDirection = (iColumnToSort == Column->Index)
? iSortDirection * -1
: 1;
//当前的一列
iColumnToSort = Column->Index;
((TCustomListView *)Sender)->AlphaSort();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::lsvPacketCompare(TObject *Sender,
TListItem *Item1, TListItem *Item2, int Data, int &Compare)
{
switch (iColumnToSort)
{
case 0 : //索引
Compare = Item1->Caption.ToInt() - Item2->Caption.ToInt();
break;
case 1 : //协议
Compare = CompareText(Item1->SubItems->Strings[0], Item2->SubItems->Strings[0]);
break;
case 2 : //源IP
case 3 : //目的IP
Compare = inet_addr(Item1->SubItems->Strings[iColumnToSort-1].c_str())
- inet_addr(Item2->SubItems->Strings[iColumnToSort-1].c_str());
break;
case 4 : //源端口
case 5 : //目的端口
case 6 : //目的端口
Compare = Item1->SubItems->Strings[iColumnToSort-1].ToInt()
- Item2->SubItems->Strings[iColumnToSort-1].ToInt();
break;
}
Compare *= iSortDirection;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Label1Click(TObject *Sender)
{
ShellExecute(Handle, "open", Label1->Caption.c_str(), NULL, NULL, SW_SHOW);
}
//---------------------------------------------------------------------------