H3C 802.1x兼容客户端编程简述(2)
下面给出程序源代码,欢迎批评指正
bool UserSended = false; //用于标记是否发送过密码
bool FirstPacket = true; //用于标记第一个包是否已经发送
bool online = false; // 是否在线的标记
HWND hOwner = 0; // 界面的窗体句柄
pcap_t *fp = NULL; // 网卡设备
初始化各种待发送的包,略(包结构参考有关资料)
unsigned char ConnectBuf[60] 请求连接包
unsigned char DisconnectBuf[60] 请求断开包
unsigned char UnknowBufA[67] 我不知道的包
unsigned char PasswordBuf[60] 包含密码、用户名的包
unsigned char KeepBuf[60] 保持连接的包,包含IP、用户名
unsigned char SendUsernameBuf[60] 发送IP、用户名的包
//打开网卡,用pcap_findalldevs()获得*device
bool OpenDevice(char* device)
{
char errbuf[PCAP_ERRBUF_SIZE];
//抓取的最大包的字节为60, 20ms抓取一次
if ((fp = pcap_open_live(device, 60, 1, 20, errbuf)) == NULL)
return false;
return true;
}
void CloseDevice()// 关闭网卡
{
if (fp != NULL)
{
pcap_close(fp);
}
}
void DeviceLoop()// 启动包处理循环
{
if (fp == NULL)
return;
pcap_loop(fp, 0, packet_handler, NULL);
}
// 分析包并产生相应动作
void packet_handler(unsigned char *param,
const struct pcap_pkthdr *header,
const unsigned char *pkt_data)
{
// 判断包的类型的标志
static unsigned char Type[4] = {0x88, 0x8e, 0x01, 0x00}; //协议类型
static unsigned char SessionFlagA[3] = {0x00, 0x05, 0x01}; //保持连接包
static unsigned char SessionFlagB[3] = {0x00, 0x05, 0x01};
static unsigned char Unknow[3] = {0x00, 0x05, 0x02};
static unsigned char RequestPwdA[3] = {0x00, 0x16, 0x01}; //请求密码包
static unsigned char RequestPwdB[3] = {0x00, 0x16, 0x04};
static unsigned char SuccessA[3] = {0x00, 0x04, 0x03}; //成功认证包
static unsigned char SuccessB[3] = {0x00, 0x04, 0x00};
static unsigned char ByeA[3] = {0x00, 0x06, 0x04}; //成功断线包
static unsigned char ByeB[3] = {0x00, 0x07, 0x08};
// 找包的大小为60个字节, 协议为EAPoL的包
if (header->len == 60 && !memcmp(pkt_data + 0x0c, Type, 4))
{
//获得以后我们所要回复的MAC地址,并放入包
if (FirstPacket)
{
FirstPacket = false;
ChangeDestMac(pkt_data + 0x06);
}
// 判断是否为对话维持包或要求发送用户名的包(这两种包的特征是一样的)
if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) &&
!memcmp(pkt_data + 0x14, SessionFlagB, 3))
{
if (online)//已经上线,发送对话维持包
{
SetSessionID(pkt_data + 0x13); //设置标识位
pcap_sendpacket(fp, KeepBuf, 60);
if (online == false)
{
online = true;
ShowOnline(); //上线处理
}
}
else // 否则就发送用户名
{
SetUsernameID(pkt_data + 0x13); //设置标识位
pcap_sendpacket(fp, SendUsernameBuf, 60); //包含IP、用户名
UserSended = true;
}
return;
}
// 判断是否为未知类型的包
if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) &&
!memcmp(pkt_data + 0x14, Unknow, 3))
{
pcap_sendpacket(fp, UnknowBufA, 67); //固定的包
return;
}
// 判断是否为要求发送密码的包
if (!memcmp(pkt_data + 0x10, RequestPwdA, 3) &&
!memcmp(pkt_data + 0x14, RequestPwdB, 3))
{
SetPasswordID(pkt_data + 0x13); //设置标识位
SetMd5Buf(pkt_data + 0x13, pkt_data + 0x18);//MD5加密
pcap_sendpacket(fp, PasswordBuf, 60); //发送包含密码和用户名的包
return;
}
// 判断是否为认证成功的包 code=3
if (!memcmp(pkt_data + 0x10, SuccessA, 3) &&
!memcmp(pkt_data + 0x14, SuccessB, 3))
{
if (online == false)
{
online = true;
ShowOnline(); //上线处理
}
return;
}
// failure包 code=4
if (!memcmp(pkt_data + 0x10, ByeA, 3))
{
// 判断是否为断线成功的包
if(!memcmp(pkt_data + 0x14, ByeB, 3))
{
if (online == true)
{
online = false;
ShowOffline(); //离线处理
UserSended = false; // 重置UserSended
}
return;
}
else// 其他离线包
{
ShowOffline();
{//提示出错原因
strMsg.Format("%s", (pkt_data+0x18));
MessageBox(hOwner, strMsg, "连接失败",MB_ICONWARNING);
}
return;
}
}
}
}
十分感谢cshacker的帮助