#include "StdAfx.h"
#include ".\packet.h"
CPacket::CPacket(void): packet(0), icmp(0), ip4(0), udp(0), tcp(0), data(0), datasize(0),
fakepack(0)
{
} // ip packet size (struct ippack)
CPacket::CPacket(u_char *packet, int size, ippacket *ippack): icmp(0), ip4(0), udp(0), tcp(0), data(0), datasize(0),
fakepack(0)
{
this->packet = packet;
this->size = size;
this->ippack = ippack;
parsepacket();
}
CPacket::~CPacket(void)
{
if (packet)
delete[] packet;
}
void CPacket::parsepacket()
{
WCHAR port[256];
in_addr addr;
int ip4hdrlen = 0; //ip4 hdr length
int tcphdrlen = 0; //tcp hdr len
_wstrtime(ippack->time);
_wstrdate(ippack->date);
if ((packet[0] & 0xF0) == 0x40) { //ip4
ip4 = (ip4_header *)packet;
ip4hdrlen = int(ip4->ver_ihl & 0x0F) * 4;
protoent *proto = getprotobynumber(ip4->proto);
if (proto)
MultiByteToWideChar(CP_ACP, 0, proto->p_name, (int)strlen(proto->p_name) + 1, ippack->proto, sizeof(ippack->proto) / sizeof(ippack->proto[0]));
else
wsprintf(ippack->proto, L"%u", ip4->proto);
wsprintf(ippack->ident, L"%u", ntohs(ip4->identification));
wsprintf(ippack->ttl, L"%u", ip4->ttl);
wsprintf(ippack->foffs, L"%u", ntohs(ip4->flags_fo)&0x1FFF);
MultiByteToWideChar(CP_ACP, 0, inet_ntoa(ip4->saddr), (int)strlen(inet_ntoa(ip4->saddr)) + 1, ippack->saddr, sizeof(ippack->saddr) / sizeof(ippack->saddr[0]));
MultiByteToWideChar(CP_ACP, 0, inet_ntoa(ip4->daddr), (int)strlen(inet_ntoa(ip4->daddr)) + 1, ippack->daddr, sizeof(ippack->daddr) / sizeof(ippack->daddr[0]));
switch (ip4->proto) {
case 1: //icmp
icmp = (icmp_header *)(packet + ip4hdrlen);
wsprintf(ippack->itype, L"%u", icmp->type);
wsprintf(ippack->icode, L"%u", icmp->code);
if (icmp->type != 5) {
wsprintf(ippack->iident, L"%u", ntohs(icmp->ident));
wsprintf(ippack->iseq, L"%u", ntohs(icmp->seqnum));
}
data = (u_char *)icmp + sizeof(icmp_header);
datasize = size - int(data - packet);
if (datasize <= 0) {
datasize = 0;
data = 0;
}
switch (icmp->type) {
case 17:
case 18:
addr.S_un.S_addr = *((u_long *)data);
MultiByteToWideChar(CP_ACP, 0, inet_ntoa(addr), (int)strlen(inet_ntoa(addr)) + 1, ippack->iaddr, sizeof(ippack->iaddr) / sizeof(ippack->iaddr[0]));
break;
case 5:
addr.S_un.S_addr = *((u_long *) & icmp->ident);
MultiByteToWideChar(CP_ACP, 0, inet_ntoa(addr), (int)strlen(inet_ntoa(addr)) + 1, ippack->iaddr, sizeof(ippack->iaddr) / sizeof(ippack->iaddr[0]));
break;
case 13:
case 14:
wsprintf(ippack->iorigt, L"%u", *((u_long *)data));
wsprintf(ippack->irecvt, L"%u", *((u_long *)data + 1));
wsprintf(ippack->itrant, L"%u", *((u_long *)data + 2));
break;
}
break;
case 6: //tcp
tcp = (tcp_header *)(packet + ip4hdrlen);
if (tcp->dataoffs >> 4) {
data = (u_char *)tcp + int(tcp->dataoffs >> 4) * 4;
datasize = size - int(data - packet);
if (datasize <= 0) {
datasize = 0;
data = 0;
}
}
wsprintf(port, L"(%u)", ntohs(tcp->sport));
lstrcat(ippack->saddr, port);
wsprintf(port, L"(%u)", ntohs(tcp->dport));
lstrcat(ippack->daddr, port);
wsprintf(ippack->seqnum, L"%u", ntohl(tcp->seqnum));
wsprintf(ippack->acknum, L"%u", ntohl(tcp->acknum));
for (int i = 0; i < 6; i++) {
if (u_char(1 << i) & tcp->ctrlbits)
lstrcat(ippack->ctrlbits, BITS[i].bits);
}
wsprintf(ippack->window, L"%u", ntohs(tcp->window));
break;
case 17: //udp
udp = (udp_header *)(packet + ip4hdrlen);
if (ntohs(udp->len) - sizeof(udp_header)) {
if ((size - ip4hdrlen) < ntohs(udp->len)) {
data = 0;
datasize = ntohs(udp->len) - sizeof(udp_header);
fakepack = true;
} else {
data = (u_char *)(udp) + sizeof(udp_header);
datasize = ntohs(udp->len) - sizeof(udp_header);
}
}
wsprintf(port, L"(%u)", ntohs(udp->sport));
lstrcat(ippack->saddr, port);
wsprintf(port, L"(%u)", ntohs(udp->dport));
lstrcat(ippack->daddr, port);
break;
default:
break;
}
wsprintf(ippack->size, L"%u", size);
wsprintf(port, L"(%u", datasize);
lstrcat(ippack->size, port);
if (fakepack)lstrcat(ippack->size, L"?");
lstrcat(ippack->size, L")");
if (size != ntohs(ip4->tlen)) {
wsprintf(port, L" %u?", ntohs(ip4->tlen));
lstrcat(ippack->size, port);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int CPacket::sendicmp(SOCKET s, ip4_header *ip4, icmp_header *icmp)
{
int status = 0, size = 0;
u_char *packet = 0;
char *data = 0, mess[] = "helo there.";
switch (icmp->type) {
case 0:
case 8: //Echo
data = new char[sizeof(mess) + 1000];
size = sizeof(mess);
memcpy(data, &mess, size);
break;
case 13:
case 14: //Time stamp
data = new char[4*3 + 1000]; //12 bytes for time stamps
size = 4 * 3;
memset(data, 0, 12);
break;
case 17:
case 18: //Addr mask
data = new char[4 + 1000];
size = 4;
memset(data, 0, 4);
break;
case 15:
case 16:
break;
default:
data = new char[sizeof(ip4_header) + 8]; //ip4hdr + 64bit
size = sizeof(ip4_header) + 8;
memset(data, 0, 4);
break;
}
if (data && size) {
int len = ntohs(ip4->tlen);
ip4->tlen = htons(len + size);
}
packet = new u_char[sizeof(ip4_header) + sizeof(icmp_header) + size];
/* CRC's */
ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header));
icmp->crc = icmpchksum(icmp, data, size);
/* CRC's */
memcpy(packet, ip4, sizeof(ip4_header));
memcpy(packet + sizeof(ip4_header), icmp, sizeof(icmp_header));
if (data && size)
memcpy(packet + sizeof(ip4_header) + sizeof(icmp_header), data, size);
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = 0;
saddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(icmp_header) + size,
0, (sockaddr *) & saddr, sizeof(saddr));
if (data) delete[] data;
if (packet) delete[] packet;
return status;
}
int CPacket::sendudp(SOCKET s, ip4_header *ip4, udp_header *udp, char *data, int size)
{
int status = 0;
u_char *packet = new u_char[sizeof(ip4_header) + sizeof(udp_header) + size];
/* CRC's */
ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header)); //?
udp->crc = udpchksum(ip4, udp, data, size); //?
/* CRC's */
memcpy(packet, ip4, sizeof(ip4_header));
memcpy(packet + sizeof(ip4_header), udp, sizeof(udp_header));
if (data && size)
memcpy(packet + sizeof(ip4_header) + sizeof(udp_header), data, size);
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = udp->dport; //already htons()
saddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(udp_header) + size,
0, (sockaddr *) & saddr, sizeof(saddr));
delete[] packet;
return status;
}
int CPacket::sendtcp(SOCKET s, ip4_header *ip4, tcp_header *tcp, char *data, int size)
{
int status = 0;
u_char *packet = new u_char[sizeof(ip4_header) + sizeof(tcp_header) + size];
// CRC's //
ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header)); //no htons ?
tcp->crc = tcpchksum(ip4, tcp, data, size); //??????????
// CRC's //
memcpy(packet, ip4, sizeof(ip4_header));
memcpy(packet + sizeof(ip4_header), tcp, sizeof(tcp_header));
if (data && size)
memcpy(packet + sizeof(ip4_header) + sizeof(tcp_header), data, size);
sockaddr_in daddr;
daddr.sin_family = AF_INET;
daddr.sin_port = tcp->dport; //already htons()
daddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(tcp_header) + size,
0, (sockaddr *) & daddr, sizeof(daddr));
delete[] packet;
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*FILE *fp = fopen("pack00.pck","wb");
fwrite(packet,1, sizeof(ip4_header) + sizeof(udp_header) + size, fp);
fclose(fp);*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////CRC's//////////////////////////////////////////////////////////////////////
u_short CPacket::ipchksum(u_short *addr, int len)
{
int sum = chksum(addr, len);
sum = (sum >> 16) + (sum & 0xffff);
return u_short(~sum);
}
u_short CPacket::udpchksum(ip4_header *ip4, udp_header *udp, char *data, int size)
{
int sum = chksum((u_short *) & ip4->saddr, 8); //saddr + daddr
sum += htons(ip4->proto); //proto
sum += udp->len; //len already htons()
sum += chksum((u_short *)udp, sizeof(udp_header)); //udp header
if (data && size)
sum += chksum((u_short *)data, size); //udp data
sum = (sum >> 16) + (sum & 0xffff);
return u_short(~sum);
}
u_short CPacket::tcpchksum(ip4_header *ip4, tcp_header *tcp, char *data, int size)
{
int sum = chksum((u_short *) & ip4->saddr, 8); //saddr + daddr
sum += htons(ip4->proto); //proto
sum += htons(u_short(sizeof(tcp_header) + size));
sum += chksum((u_short *)tcp, sizeof(tcp_header)); //udp header
if (data && size)
sum += chksum((u_short *)data, size); //udp data
sum = (sum >> 16) + (sum & 0xffff);
return u_short(~sum);
}
u_short CPacket::icmpchksum(icmp_header *icmp, char *data, int size)
{
int sum = chksum((u_short *)icmp, sizeof(icmp_header)); //icmp header
if (data && size)
sum += chksum((u_short *)data, size); //udp data
sum = (sum >> 16) + (sum & 0xffff);
return u_short(~sum);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int CPacket::chksum(u_short *addr, int len)
{
int nleft = len;
int sum = 0;
while (nleft > 1) {
sum += *addr++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1) {
u_short u = 0;
*(u_char *)(&u) = *(u_char *)addr ;
sum += u;
}
return sum;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
LPCTSTR CPacket::geterror()
{
switch (WSAGetLastError()) {
case WSAEINTR:
return L"Interrupted function call.";
case WSAEACCES:
return L"Permission denied.";
case WSAEFAULT:
return L"Bad address.";
case WSAEINVAL:
return L"Invalid argument.";
case WSAEMFILE:
return L"Too many open files.";
case WSAEWOULDBLOCK:
return 0;
case WSAEINPROGRESS:
return L"Operation now in progress.";
case WSAEALREADY:
return L"Operation already in progress.";
case WSAENOTSOCK:
return L"Socket operation on nonsocket.";
case WSAEDESTADDRREQ:
return L"Destination address required.";
case WSAEMSGSIZE:
return L"Message too long.";
case WSAEPROTOTYPE:
return L"Protocol wrong type for socket.";
case WSAENOPROTOOPT:
return L"Bad protocol option.";
case WSAEPROTONOSUPPORT:
return L"Protocol not supported.";
case WSAESOCKTNOSUPPORT:
return L"Socket type not supported.";
case WSAEOPNOTSUPP:
return L"Operation not supported.";
case WSAEPFNOSUPPORT:
return L"Protocol family not supported.";
case WSAEAFNOSUPPORT:
return L"Address family not supported by protocol family.";
case WSAEADDRINUSE:
return L"Address already in use.";
case WSAEADDRNOTAVAIL:
return L"Cannot assign requested address.";
case WSAENETDOWN:
return L"Network is down.";
case WSAENETUNREACH:
return L"Network is unreachable.";
case WSAENETRESET:
return L"Network dropped connection on reset.";
case WSAECONNABORTED:
return L"Software caused connection abort.";
case WSAECONNRESET:
return L"Connection reset by peer.";
case WSAENOBUFS:
return L"No buffer space available.";
case WSAEISCONN:
return L"Socket is already connected.";
case WSAENOTCONN:
return L"Socket is not connected.";
case WSAESHUTDOWN:
return L"Cannot send after socket shutdown.";
case WSAETIMEDOUT:
return L"Connection timed out.";
case WSAECONNREFUSED:
return L"Connection refused.";
case WSAEHOSTDOWN:
return L"Host is down.";
case WSAEHOSTUNREACH:
return L"No route to host.";
case WSAEPROCLIM:
return L"Too many processes.";
case WSASYSNOTREADY:
return L"Network subsystem is unavailable.";
case WSAVERNOTSUPPORTED:
return L"Winsock.dll version out of range.";
case WSANOTINITIALISED:
return L"Successful WSAStartup not yet performed.";
case WSAEDISCON:
return L"Graceful shutdown in progress.";
case WSATYPE_NOT_FOUND:
return L"Class type not found.";
case WSAHOST_NOT_FOUND:
return L"Host not found.";
case WSATRY_AGAIN:
return L"Nonauthoritative host not found.";
case WSANO_RECOVERY:
return L"This is a nonrecoverable error.";
case WSANO_DATA:
return L"Valid name, no data record of requested type.";
case WSA_INVALID_HANDLE:
return L"Specified event object handle is invalid.";
case WSA_INVALID_PARAMETER:
return L"One or more parameters are invalid.";
case WSA_IO_INCOMPLETE:
return L"Overlapped I/O event object not in signaled state.";
case WSA_IO_PENDING:
return L"Overlapped operations will complete later.";
case WSA_NOT_ENOUGH_MEMORY:
return L"Insufficient memory available.";
case WSA_OPERATION_ABORTED:
return L"Overlapped operation aborted.";
//case WSAINVALIDPROCTABLE: //not in Visual C++ 7.0
// return "Invalid procedure table from service provider.";
//case WSAINVALIDPROVIDER:
// return "Invalid service provider version number.";
//case WSAPROVIDERFAILEDINIT:
// return "Unable to initialize a service provider.";
case WSASYSCALLFAILURE:
return L"System call failure.";
default:
return L"Unknown code?";
}
}