I'm trying to learn IOCP with C in Windows. The idea is to have a non-blocking server with threads that handle client messages.
I understand by now how to accept clients, etc.
But I still don't understand how to read each client's messages from GetQueuedCompletionStatus() and print them.
I see online that all people pass a struct to reference it with GetQueuedCompletionStatus() using the LPOVERLAPPED parameter, but how to do it without any struct?
Can someone tell me if that is possible, and show a little example?
You have to keep track of the buffers you pass to WSARecv(), etc. You do that by associating an OVERLAPPED with each buffer. When GetQueuedCompletionStatus() tells you which OVERLAPPED is finished, you thus known the associated buffer is ready.
This is commonly handled by defining a struct with an OVERLAPPED as its first member, so that a pointer to the OVERLAPPED is also equal to a pointer to the struct. Then you can put whatever other details you want in the struct, like the buffer, socket, etc, whatever your app needs to process the data.
For example:
enum IocpOp { opRead, opWrite };
typedef struct
{
WSAOVERLAPPED ov;
IocpOp opCode;
SOCKET sckt;
BYTE buffer[256];
DWORD numBytesInBuffer;
} MYIOCPINFO, *PMYIOCPINFO;
void IoComplete(PMYIOCPINFO io, DWORD errorCode, DWORD numBytesTransferred)
{
if (errorCode != ERROR_SUCCESS)
{
// handle failure as needed ...
free(io);
return;
}
switch (io->opCode)
{
case opRead:
// use io->buffer up to numBytesTransferred as needed ...
break;
case opWrite:
if (numBytesTransferred < io->numBytesInBuffer)
{
info->numBytesInBuffer -= numBytesTransferred;
memmove(io->buffer, io->buffer + numBytesTransferred, io->numBytesInBuffer);
WSABUF buf;
buf.len = io->numBytesInBuffer;
buf.buf = (CHAR*) io->buffer;
if (WSASend(io->sckt, &buf, 1, NULL, 0, &(io->ov), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// handle failure as needed ...
free(io);
}
}
return;
}
break;
}
// reuse io for the next I/O operation on io->sckt
// or free io now if done using it ...
free(io);
}
}
...
PMYIOCPINFO io = malloc(sizeof(MYIOCPINFO));
if (!io) ...
io->opCode = opRead;
io->sckt = sckt;
WSABUF buf;
buf.len = sizeof(io->buffer);
buf.buf = (CHAR*) io->buffer;
DWORD dwFlags = 0;
if (WSARecv(sckt, &buf, 1, NULL, &dwFlags, &(io->ov), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
IoComplete(io, WSAGetLastError(), 0);
}
...
PMYIOCPINFO io = malloc(sizeof(MYIOCPINFO));
if (!io) ...
io->opCode = opWrite;
io->sckt = sckt;
// fill io->buffer as needed ...
io->numBytesInBuffer = ...;
WSABUF buf;
buf.len = io->numBytesInBuffer;
buf.buf = (CHAR*) io->buffer;
if (WSASend(sckt, &buf, 1, NULL, 0, &(io->ov), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
IoComplete(io, WSAGetLastError(), 0);
}
...
DWORD dwBytesTransferred = 0;
ULONG_PTR ulCompletionKey = 0;
LPOVERLAPPED lpOverlapped = NULL;
if (GetQueuedCompletionStatus(hIOCP, &dwBytesTransferred, &ulCompletionKey, &lpOverlapped, INFINITE))
{
if (ulCompletionKey == MySocketIOCPKey) // specified in CreateIOCompletionPort()...
{
IoComplete((PMYIOCPINFO)lpOverlapped, ERROR_SUCCESS, dwBytesTransferred);
}
else
{
...
}
}
else
{
if (lpOverlapped)
{
// I/O operation belonging to ulCompletionKey failed...
if (ulCompletionKey == MySocketIOCPKey) // specified in CreateIOCompletionPort()...
{
IoComplete((PMYIOCPINFO)lpOverlapped, GetLastError(), dwBytesTransferred);
}
else
{
...
}
}
else
{
// GetQueuedCompletionStatus() itself failed...
}
}
I am running the program below which works with some of my devices, but in three of them after init, open, claim and bulk (write) to work OK, my bulk (read) is returning 0x01 0x60 in my answer buffer. Actually it doesn't matter what I send; after opening USB, if I try to bulk_read... I'm having this answer every time (even in an infinite looping). What it can be?
int main() {
libusb_device **devs; // Pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; // A device handle
libusb_context *ctx = NULL; // A libusb session
struct libusb_control_setup setup;
int r; // For return values
int i = 0;
int iCmdLen_BCR = 6;
int iCmdLen = 0;
int actual = 0; // Used to find out how many bytes were written
ssize_t cnt; // Holding number of devices in list
unsigned char sRsp[1024];
unsigned char sAux[1024];
unsigned char data[128];
unsigned char data_BCR[128]; // Data to write
memset(data, 0, sizeof(data));
memset(data_BCR, 0, sizeof(data_BCR));
memset(sRsp, 0, sizeof(sRsp));
memset(sAux, 0, sizeof(sAux));
r = libusb_init(&ctx); // Initialize the library for the session we just declared
if(r < 0) {
printf("[%04d] Init Error [%d]\n", __LINE__, r); // There was an error
return 1;
}
libusb_set_debug(ctx, 3); // Set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); // Get the list of devices
if(cnt < 0) {
printf("[%04d] Get Device Error\n", __LINE__); // There was an error
return 1;
}
printf("[%04d] Devices in list.\n", __LINE__);
dev_handle = libusb_open_device_with_vid_pid(ctx, VD_ID_BCR, PD_ID_BCR); // These are vendorID and productID I found for my usb device
if(dev_handle == NULL)
printf("[%04d] Cannot open device\n", __LINE__);
else
printf("[%04d] Device Opened\n", __LINE__);
libusb_free_device_list(devs, 1); // Free the list, unref the devices in it
if(libusb_kernel_driver_active(dev_handle, 0) == 1) { // Find out if kernel driver is attached
printf("[%04d] Kernel Driver Active\n", __LINE__);
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) // Detach it
printf("[%04d] Kernel Driver Detached!\n", __LINE__);
}
r = libusb_claim_interface(dev_handle, 0); // Claim interface 0 (the first) of device (mine had jsut 1)
if(r < 0) {
printf("[%04d] Cannot Claim Interface\n", __LINE__);
return 1;
}
printf("[%04d] Claimed Interface r[%d]\n", __LINE__, r);
memcpy(data_BCR, "\x04\xC8\x04\x00\xFF\x30", iCmdLen_BCR);
memcpy(data, data_BCR, iCmdLen_BCR);
iCmdLen = iCmdLen_BCR;
r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, iCmdLen, &actual, 0); // My device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
if(r >= 0)
{
printf("[%04d] Writing Successful!\n", __LINE__);
r = libusb_bulk_transfer(dev_handle, 0x81, sRsp, 1024, &actual, 10000);
for(i=0; i<actual ; i++)
{
sprintf(sAux+strlen(sAux), "%02X ", sRsp[i]);
}
printf("[%04d] result bulk read[%d] actual[%d] Rsp[%s]\n", __LINE__, r, actual, sAux);
}
else
{
printf("[%04d] Write Error\n", __LINE__);
}
r = libusb_release_interface(dev_handle, 0); // Release the claimed interface
if(r!=0) {
printf("[%04d] Cannot Release Interface\n", __LINE__);
return 1;
}
printf("[%04d] Released Interface\n", __LINE__);
libusb_close(dev_handle); // Close the device we opened
libusb_exit(ctx); // Needs to be called to end the
//delete[] data; // Delete the allocated memory for data
return 0;
}
we are building a NAT program,we change each packet that comes from our internal subnet,
change it's source IP address by libnet functions.( catch the packet with libpcap, put it
sniff structures and build the new packet with libnet)
over TCP, the syn/ack packets are good after the change, and when a HTTP-GET request is coming, we can see by wireshark that there is an error on the checksum field..
all the other fields are exactly the same as the original packet.
Is anyone knows what can cause this problem?
the new checksum in other packets is calculated as it should be..
but in the HTTP packet it doesn't..
Modern ethernet cards can compute the checksum in hardware, so TCP stacks tend to offload the job to the card. As a result, it is quite common for the checksum to be invalid in Wireshark.
Side note: There is an option in Wireshark to validate the checksum:
Edit
Preferences
Protocols
TCP
Validate the TCP checksum if possible
Turn this off to stop Wireshark nagging you about the checksum.
Is this actually causing a problem - i.e. does the packet with "bad checksum" get dropped or processed incorrectly? Or are you just worried about the "bad checksum" notification? If the packets are processed OK, this may be just checksum offloading and it's nothing to worry about.
Wireshark documentation says:
If the received checksum is wrong, Wireshark won't even see the packet, as the Ethernet hardware internally throws away the packet.
Hey, answering in her name.
The GET and ACK are separated, and yes the GET request is sent completely, this being said based on the fact that the packets are sent by Firefox or Wget. we do not create the packets, nor the responses of the server (which is an Apache).
Our code just runs in the middle. we have a 3rd machine besides the Client and the Server, and all of the three are Virtual Machines (in VMWare Server [NAT, Client = Ubuntu; Server = Fedora]). it has 2 NIC's (each one connected to each subnet accordingly) and it's goal is to change the Source IP and Source Port fields (in both directions of network traffic).
Thanks for the explanation about TCP checksum offload, which is guessed to happen by wireshark, but in my opinion is not the case because the error appears in the server side too (not 100% sure if that rules out the possibility, thoughts?).
If I'm right, what could be the reason for the checksum's incorrectness?
Here is a link to the current code:
http://rapidshare.com/files/393704745/13.5.10.tar.gz
Thanks a lot,
Aviv.
If it's better as a code in here, there you go:
#include "./main.h"
int main(int argc, char **argv)
{
pcap_t *pcapInt, *pcapExt; /* pcap descriptor */
u_char *intPacket, *extPacket;
int i;
struct pcap_pkthdr intPkthdr, extPkthdr;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program filter_code;
bpf_u_int32 intLocalNet, intNetmask, extLocalNet;
for(i=0;i to quit\n");
/* read the configuration file and store it's data in an array */
LIBXML_TEST_VERSION
xmlNode *cur_node = xmlDocGetRootElement(xmlReadFile(((argv[1]) != NULL ? argv[1] : "conf.xml"), NULL, 0));
strcpy(config.filter, "");
XMLtoConf(cur_node);
strcat(config.filter, " and not src host 192.168.191.137");
printf("FILTER: %s\n", config.filter);
/* get network number and mask associated with the internal capture device */
if (pcap_lookupnet(config.intNIC, &intLocalNet, &intNetmask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
config.intNIC, errbuf);
intLocalNet = 0;
intNetmask = 0;
}
/* open internal capture device */
pcapInt = pcap_open_live(config.intNIC, SNAP_LEN, 1, 1000, errbuf);
if (pcapInt == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", config.intNIC, errbuf);
exit(EXIT_FAILURE);
}
/* open external capture device */
pcapExt = pcap_open_live(config.extNIC, SNAP_LEN, 1, 1000, errbuf);
if (pcapExt == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", config.extNIC, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(pcapInt) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", config.intNIC);
exit(EXIT_FAILURE);
}
if (pcap_datalink(pcapExt) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", config.extNIC);
exit(EXIT_FAILURE);
}
/* compile the internal filter expression */
if (pcap_compile(pcapInt, &filter_code, config.filter, 1, intLocalNet) == -1) { //adsvfhakdhvkahdvkadh
fprintf(stderr, "Couldn't parse filter %s: %s\n",
argv[1], pcap_geterr(pcapInt));
exit(EXIT_FAILURE);
}
/* compile the external filter expression */
if (pcap_compile(pcapExt, &filter_code, NULL, 1, extLocalNet) == -1) { //adsvfhakdhvkahdvkadh
fprintf(stderr, "Couldn't parse filter %s: %s\n",
argv[1], pcap_geterr(pcapExt));
exit(EXIT_FAILURE);
}
/* apply the compiled internal filter */
if (pcap_setfilter(pcapInt, &filter_code) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
argv[1], pcap_geterr(pcapInt));
exit(EXIT_FAILURE);
}
//apply the compiled external filter
if (pcap_setfilter(pcapExt, &filter_code) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
argv[1], pcap_geterr(pcapExt));
exit(EXIT_FAILURE);
}
while (1 == 1)
{
intPacket = (u_char*)pcap_next(pcapInt, &intPkthdr);
extPacket = (u_char*)pcap_next(pcapExt, &extPkthdr);
if (intPacket != NULL)
{
sniff(intPacket,0);
}
if (extPacket != NULL)
{
sniff(extPacket,1);
}
}
printf("\nCapture complete.\n");
/* cleanup */
pcap_freecode(&filter_code);
pcap_close(pcapInt);
return (EXIT_SUCCESS);
}
int isStrBlank(unsigned char *s)
{
if (!s || strcmp((char *)s, "") == 0) return 1;
while(*s) {
if ( (' ' != *s) && ('\n' != *s) && ('\r' != *s) && ('\t' != *s)) return 0;
++s;
}
return 1;
}
static void XMLtoConf(xmlNode* node)
{
/*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*/
LIBXML_TEST_VERSION
xmlNode *cur_node = node;
int i,flag=0;
for (; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
//if (isStrBlank(cur_node->children->content) == 1) continue;
if (strcmp((char *)cur_node->name, "subnet_address") == 0){
strcat(config.filter, "src net ");
strcat(config.filter,(char *)cur_node->children->content);
}
//printf("1: %s", config.filter);
if (strcmp((char *)cur_node->name, "NIC") == 0){
if (strcmp((char *)cur_node->parent->name, "internal") == 0){
config.intNIC = strdup((char *)cur_node->children->content);
}
else{
config.extNIC = strdup((char *)cur_node->children->content);
}
}
for (i = 0; strncmp((char *)cur_node->name, "machine_", 8) == 0; i++){
strcat(config.filter, " and not");
strcat(config.filter, " src host ");
flag=1;
strcat(config.filter, (char *)cur_node->children->content);
cur_node = cur_node->next;
}
}
XMLtoConf(cur_node->children);
}
/*
*Free the global variables that may
*have been allocated by the parser.
*/
xmlCleanupParser();
/*
* If device is NULL, that means the user did not specify one and is
* leaving it up libpcap to find one.
*/
}
void sniff(const u_char *packet , int flag)
{
int i,x,tcpOpen=0;
int protocol=-1; // 0- tcp, 1- udp, 2 -icmp
tcp = (struct sniff_tcp*)(packet + 34); //skipping the ethernet and IP layers
udp = (struct sniff_udp *)(packet + 34); //skipping the ethernet and IP layers
ip = (struct sniff_ip *)(packet + SIZE_ETHERNET);
icmp = (struct sniff_icmp *)(packet+ 34);
ether = (struct sniff_ethernet *)(packet);
printf("/n1--%d/n",IP_HL(ip)*4);
//if(ntohs(tcp->th_sport) == 80 || ntohs(tcp->th_dport) == 80)
//{
if(ip->ip_p==IP_TYPE_TCP )
{
protocol = 0;
payload_s = ntohs(ip->ip_len) - TH_OFF(tcp)*4 - IP_HL(ip)*4;
if (payload_s)
payload = (char* )(packet + SIZE_ETHERNET + TH_OFF(tcp)*4 + IP_HL(ip)*4);
else
payload = NULL;
}
else if(ip->ip_p == IP_TYPE_UDP){
protocol = 1;
payload_s = ntohs(ip->ip_len) - ntohs(udp->udp_len) - IP_HL(ip)*4;
if (payload_s)
payload = (char* )(packet + SIZE_ETHERNET + ntohs(udp->udp_len) + IP_HL(ip)*4);
else
payload = NULL;
}
else if(ip->ip_p == IP_TYPE_ICMP)
{
protocol = 2;
payload_s = ntohs(ip->ip_len) - 8 - IP_HL(ip)*4;
if (payload_s)
payload = (char* )(packet + SIZE_ETHERNET + 8 + IP_HL(ip)*4);
else
payload = NULL;
}
if(flag == 0)// we got a packet from the internal
{
if( ip->ip_p == IP_TYPE_TCP)
{
for(i=0;iip_p)
if(nTable[i].ip_src.s_addr == ip->ip_src.s_addr)
if(nTable[i].ip_dst.s_addr == ip->ip_dst.s_addr)
if(ntohs(nTable[i].srcPort) == ntohs(tcp->th_sport))
if(ntohs(nTable[i].dstPort) == ntohs(tcp->th_dport))
{
printf("we are in an open connection \n");
changeSrcPacket(packet ,(i+2000)%8000 ,protocol);
tcpOpen = 1;
break;
}
}
}
if(tcpOpen == 0)
{
for(i=0;iip_p == IP_TYPE_UDP ||ip->ip_p == IP_TYPE_TCP )
{
if(nTable[i].free==0)
{
nTable[i].free=1;
nTable[i].ip_src = ip->ip_src;
nTable[i].ip_dst = ip->ip_dst;
nTable[i].srcPort = tcp->th_sport;
nTable[i].dstPort = tcp->th_dport;
nTable[i].protocol = ip->ip_p;
//printf("index : %d ipsrc : %s srcport : %d\n",i,inet_ntoa(nTable[i].ip_src),ntohs(nTable[i].srcPort));
////////////change packet and send it with the src ip of the nat machine
///////////and the src port is (i+2000)%8000
changeSrcPacket(packet ,(i+2000)%8000 ,protocol);
break;
}
}
else
{
if(icmpTable[i].free == 0)
{
icmpTable[i].free=1;
icmpTable[i].ip_src = ip->ip_src;
icmpTable[i].ip_dst = ip->ip_dst;
icmpTable[i].protocol = ip->ip_p;
icmpTable[i].icmp_type = icmp->icmp_type;
icmpTable[i].icmp_id1 = icmp->icmp_id1;
changeSrcPacket(packet ,-1 ,protocol);
break;
}
}
}
}
}
else // flag = 1
{
// we got a packet from the external. we want to send it to the right
// place in the internal
//nTable[(tcp->th_dport-2000)%8000];
//printf("dst: %d , src: %d \n",ntohs(tcp->th_dport),ntohs(tcp->th_sport));
if(ip->ip_p== IP_TYPE_ICMP)
{
changeDstPacket (packet,-1,protocol);
}
else
{
for(x=0;xip_p == IP_TYPE_TCP)
{
if(((int)(ntohs(tcp->th_dport))-2000)%8000 == x && nTable[x].free == 1)
{
changeDstPacket (packet,x,protocol);
break;
}
}
else
{
if(((int)(ntohs(udp->udp_destport))-2000)%8000 == x && nTable[x].free == 1)
{
changeDstPacket (packet,x,protocol);
break;
}
}
}
}
// we create a packet with thw same src ip and port as we got
// and only the dst port and ip will be the ones that are
//saved in nTable[(tcp->th_dport-2000)%8000]
// now if it is in udp we will put 0 in nTable[(tcp->th_dport-2000)%8000].free
}
}
void changeSrcPacket(const u_char *packet , int srcPort, int protocol)
{
libnet_t *l;
libnet_ptag_t ipv, ptag, popt,icmp;
char errbuf[LIBNET_ERRBUF_SIZE];
uint32_t nat_adder;
size_t ip_hlen=IP_HL(ip)*4;
size_t ip_len=ntohs(ip->ip_len);
size_t tcp_len = ip_len - ip_hlen;
printf("\n%d %d %d %d",IP_HL(ip),ip_hlen,ip_len,tcp_len);
icmp = ptag = ipv = LIBNET_PTAG_INITIALIZER;
nat_adder = libnet_name2addr4(l,"192.168.191.137",LIBNET_DONT_RESOLVE);
l = libnet_init(LIBNET_RAW4,config.extNIC, errbuf);
if(protocol == 0)//TCP
{
if(TH_OFF(tcp)*4 > TCP_HEADER_SIZE)
{
options = (char*)packet + 54;
options_s = TH_OFF(tcp)*4 - TCP_HEADER_SIZE;
popt = libnet_build_tcp_options((u_int8_t*)options,options_s, l,0);
}
ptag = libnet_build_tcp(
srcPort, // source port
ntohs(tcp->th_dport), // dest port
htonl(tcp->th_seq), // sequence number
ntohl(tcp->th_ack), // ack number
tcp->th_flags, // flags
ntohs(tcp->th_win), // window size
0, // checksum
ntohs(tcp->th_urp), // urg ptr
TH_OFF(tcp)*4, // total length of the TCP packet
(u_int8_t*)payload, // response
payload_s, // response_length
l, // libnet_t pointer
ptag // ptag
);
printf("%d, %d, %d, %d, %d\n", TH_OFF(tcp)*4, IP_HL(ip)*4, payload_s, ntohs(ip->ip_len),TH_OFF(tcp)*4);
if(ptag==-1)
{
fprintf(stderr, "Error building TCP header: %s\n",libnet_geterror(l));
exit(1);
}
if (libnet_do_checksum(l, (u_int8_t*)ip,IPPROTO_TCP, TH_OFF(tcp)*4) udp_destport), /* destination port */
udp->udp_len, /* packet length */
0, /* checksum */
(u_int8_t*)payload, /* payload */
payload_s, /* payload size */
l, /* libnet handle */
ptag); /* libnet id */
if(ptag==-1)
{
fprintf(stderr, "Error building UDP header: %s\n",libnet_geterror(l));
exit(1);
}
}
// if(protocol == 2)//ICMP
//{
///add functions of icmp
// icmp = libnet_build_icmpv4_echo(
//ICMP_ECHO, /* type */
//0, /* code */
//0, /* checksum */
//icmp->icmp_id1, /* id */
//icmp->icmp_seq1, /* sequence number */
//payload, /* payload */
//payload_s, /* payload size */
//l, /* libnet context */
//icmp); /* ptag */
//if (icmp == -1)
//{
// fprintf(stderr, "Can't build ICMP header: %s\n",
// libnet_geterror(l));
//}
// }
ipv = libnet_build_ipv4(
/* total length */
ntohs(ip->ip_len),
ip->ip_tos, /* type of service */
ntohs(ip->ip_id), /* identification */
ntohs(ip->ip_off), /* fragmentation */
ip->ip_ttl, /* time to live */
ip->ip_p, /* protocol */
0, /* checksum */
nat_adder, /* (Nat) source */
ip->ip_dst.s_addr, /* destination */
NULL, /* payload */
0, /* payload size */
l, /* libnet handle */
0); /* ptag */
if(ipv == -1)
{
fprintf(stderr,"Error building IP header: %s\n", libnet_geterror(l));
exit(1);
}
/*if (libnet_do_checksum(l, (u_int8_t*)l, IPPROTO_IP, ntohs(ip->ip_len) + payload_s) th_flags == 0x01)
{
nTable[index].fin++;
}
if(tcp->th_flags == 0x11 && nTable[index].fin == 1)
{
nTable[index].fin++;
}
if(tcp->th_flags == 0x10 && nTable[index].fin == 2)
{
nTable[index].free = 0;
nTable[index].fin = 0;
}
}
// Fix IP header checksum
// ip->ip_sum = 0;
if (libnet_do_checksum(l, (u_int8_t*)ip,IPPROTO_IP, IP_HL(ip)*4) th_sport),ntohs(nTable[index].srcPort));
printf("src ip : %s dst ip: %s\n",inet_ntoa(ip->ip_src), inet_ntoa(nTable[index].ip_src));
ptag = ipv = LIBNET_PTAG_INITIALIZER;
if(protocol == 0 || protocol == 1) // udp or tcp
{
if(nTable[index].free == 1)
{
l = libnet_init(LIBNET_RAW4,config.intNIC, errbuf);
if(protocol == 0 ) //TCP
{
if(TH_OFF(tcp)*4 > TCP_HEADER_SIZE)
{
options = (char*)packet + 54;
options_s = TH_OFF(tcp)*4 - TCP_HEADER_SIZE;
popt = libnet_build_tcp_options((u_int8_t*)options,options_s, l,0);
}
ptag = libnet_build_tcp(
ntohs(tcp->th_sport), // source port
ntohs(nTable[index].srcPort), // dest port
ntohl(tcp->th_seq), // sequence number
ntohl(tcp->th_ack), // ack number
tcp->th_flags, // flags
ntohs(tcp->th_win), // window size
0, // checksum
ntohs(tcp->th_urp), // urg ptr
TH_OFF(tcp)*4, // total length of the TCP packet
(u_int8_t*)payload, // response
payload_s, // response_length
l, // libnet_t pointer
ptag // ptag
);
if(ptag==-1)
{
fprintf(stderr, "Error building TCP header: %s\n",libnet_geterror(l));
exit(1);
}
}
if(protocol == 1)// UDP
{
ptag = libnet_build_udp(
ntohs(udp->udp_srcport), /* source port */
ntohs(nTable[index].srcPort), /* destination port */
udp->udp_len, /* packet length */
0, /* checksum */
(u_int8_t*)payload, /* payload */
payload_s, /* payload size */
l, /* libnet handle */
ptag); /* libnet id */
if(ptag==-1)
{
fprintf(stderr, "Error building UDP header: %s\n",libnet_geterror(l));
exit(1);
}
}
}
}
if(protocol == 2) // ICMP
{
for(i=0;i icmp_type)
if(icmpTable[i].ip_dst.s_addr == ip->ip_src.s_addr)
if(icmpTable[i].icmp_id1 == icmp->icmp_id1)
{
index = i;
break;
}
}
///add functions of icmp
}
ipv = libnet_build_ipv4(
/* total length */
ntohs(ip->ip_len),
ip->ip_tos, /* type of service */
ntohs(ip->ip_id), /* identification */
ntohs(ip->ip_off), /* fragmentation */
ip->ip_ttl, /* time to live */
ip->ip_p, /* protocol */
0, /* checksum */
ip->ip_src.s_addr, /* (Nat) source */
nTable[index].ip_src.s_addr, /* destination */
NULL, /* payload */
0, /* payload size */
l, /* libnet handle */
0); /* ptag */
if(ipv == -1)
{
fprintf(stderr,"Error building IP header: %s\n", libnet_geterror(l));
exit(1);
}
/*if (libnet_do_checksum(l, (u_int8_t*)l, IPPROTO_IP, ntohs(ip->ip_len) + payload_s) th_flags == 0x01)
{
nTable[index].fin++;
}
if(tcp->th_flags == 0x11 && nTable[index].fin == 1)
{
nTable[index].fin++;
}
if(tcp->th_flags == 0x10 && nTable[index].fin == 2)
{
nTable[index].free = 0;
nTable[index].fin = 0;
}
}
else
{
nTable[index].free = 0;
nTable[index].fin = 0;
}
}
if ( libnet_write(l) == -1 )
fprintf(stderr, "Error writing packet: %s\n",libnet_geterror(l));
libnet_destroy(l);
}