I need to change the IP address and submask of a specific network interface from a C/C++ program. In Windows documentation, I have found that I should use AddIPAddress()/DeleteIpAddress() from the Windows API. However, DeleteIpAddress(), for instance, requires a NTEContext as a parameter. I have found an example that uses GetAdaptersInfo() to get the index of the interface and context. However, the page also explicitly states that:
On Windows XP and later: Use the GetAdaptersAddresses function instead of GetAdaptersInfo.
But, while GetAdaptersInfo() populates an IP_ADAPTER_INFO struct in which the index/NTEcontext are present, GetAdaptersAddresses() provides an IP_ADAPTER_ADDRESSES struct in which there are no such members.
What should I do with the newer GetAdaptersAddresses() function to get the index/context for interfaces?
Based on https://learn.microsoft.com/en-us/windows/win32/iphlp/managing-network-adapters, you should be able to use the following:
GetAdapterIndex
GetPerAdapterInfo
IP_PER_ADAPTER_INFO_W2KSP1
IP_ADDR_STRING
Something like this should work:
ULONG IfIndex = 0;
/* check error returned */ GetAdapterIndex(AdapterName, &IfIndex);
IP_PER_ADAPTER_INFO/*_W2KSP1?*/ PerAdapterInfo;
ULONG OutBufLen = sizeof(PerAdapterInfo);
/* check error returned */ GetPerAdapterInfo(IfIndex, &PerAdapterInfo, &OutBufLen);
/* check error returned */ DeleteIPAddress(PerAdapterInfo.DnsServerList.Context);
P.S. For older versions of Windows, this might work: https://microsoft.public.vb.winapi.narkive.com/TW7rVsdu/how-to-obtain-ntecontext-for-use-in-deleteipaddress-without-first-calling-addipaddress
This example retrieves the IP_ADAPTER_ADDRESSES structure for the adapters associated with the system and prints some members for each adapter interface.
The following example retrieves the IP address table to determine the interface index for the first adapter, then adds the IP address specified on command line to the first adapter. The IP address that was added is then deleted.
I combined the two programs and modified the code.
It can output network card description, IP address, MAC address and DNS address. Also, it can add the IP address to the first adapter and delete the same address.
Caution:
The DeleteIPAddress() function deletes an IP address previously added using AddIPAddress().
If you just only use AddIPAddress() to add an IP address, after that you need to delete it manually.
This picture shows the IP added, and you can delete the added IP by “edit” on the left side.
Here is the code:
#pragma comment (lib, "Ws2_32.lib")
// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<iostream>
#include<IPHlpApi.h>
using namespace std;
#pragma warning(disable:4996)
int main()
{
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
IP_ADAPTER_DNS_SERVER_ADDRESS* pDnServer = nullptr;
ULONG outBufLen = 0;
DWORD dwRetVal = 10;
char buff[128];
DWORD bufflen = 128;
int i;
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize =128;
UINT iaIPAddress;
UINT imIPMask;
ULONG NTEContext = 0;
ULONG NTEInstance = 0;
LPVOID lpMsgBuf;
pIPAddrTable = (MIB_IPADDRTABLE*)VirtualAlloc(&dwSize, sizeof(PMIB_IPADDRTABLE), MEM_RESERVE, NULL);
pIPAddrTable = (MIB_IPADDRTABLE*)malloc(150 * sizeof(MIB_IPADDRTABLE));
GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen);
pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
if ((dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen)) == NO_ERROR) {
while (pAddresses) {
printf("%S, %.2x-%.2x-%.2x-%.2x-%.2x-%.2x: \n",
pAddresses->FriendlyName,
pAddresses->PhysicalAddress[0], pAddresses->PhysicalAddress[1],
pAddresses->PhysicalAddress[2], pAddresses->PhysicalAddress[3],
pAddresses->PhysicalAddress[4], pAddresses->PhysicalAddress[5]);
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress;
pDnServer = pAddresses->FirstDnsServerAddress;
if (pDnServer)
{
sockaddr_in* sa_in = (sockaddr_in*)pDnServer->Address.lpSockaddr;
printf("DNS:%s\n", inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen));
}
if (pAddresses->OperStatus == IfOperStatusUp)
{
printf("Status: active\n");
}
else
{
printf("Status: deactive\n");
}
for (i = 0; pUnicast != NULL; i++)
{
if (pUnicast->Address.lpSockaddr->sa_family == AF_INET)
{
sockaddr_in* sa_in = (sockaddr_in*)pUnicast->Address.lpSockaddr;
printf("IPV4 Unicast Address:%s\n", inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen));
}
else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6)
{
sockaddr_in6* sa_in6 = (sockaddr_in6*)pUnicast->Address.lpSockaddr;
printf("IPV6:%s\n", inet_ntop(AF_INET6, &(sa_in6->sin6_addr), buff, bufflen));
}
else
{
printf("\tUNSPEC");
}
pUnicast = pUnicast->Next;
}
printf("Number of Unicast Addresses: %d\n", i);
pAddresses = pAddresses->Next;
}
}
else {
LPVOID lpMsgBuf;
printf("Call to GetAdaptersAddresses failed.\n");
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwRetVal,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL)) {
printf("\tError: %s", lpMsgBuf);
}
}
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
{
GlobalFree(pIPAddrTable);
}
// Make a second call to GetIpAddrTable to get the
// actual data we want
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) == NO_ERROR) {
printf("\t Address: %d\n", pIPAddrTable->table[0].dwAddr);
printf("\t Mask: %d\n", pIPAddrTable->table[0].dwMask);
printf("\t Index: %d\n", pIPAddrTable->table[0].dwIndex);
printf("\t BCast: %d\n", pIPAddrTable->table[0].dwBCastAddr);
printf("\t Reasm: %d\n", pIPAddrTable->table[0].dwReasmSize);
}
else {
printf("Call to GetIpAddrTable failed.\n");
}
// IP and mask we will be adding
iaIPAddress = inet_addr("192.168.0.27");
imIPMask = inet_addr("255.255.255.0");
if ((dwRetVal = AddIPAddress(iaIPAddress,
imIPMask,
pIPAddrTable->table[0].dwIndex,
&NTEContext, &NTEInstance)) == NO_ERROR)
{
printf("\tIP address added.\n");
}
else {
printf("Error adding IP address.\n");
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwRetVal,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
NULL))
{
printf(" Error: %d");
}
LocalFree(lpMsgBuf);
}
if ((dwRetVal = DeleteIPAddress(NTEContext)) == NO_ERROR)
{
printf("\t IP Address Deleted.\n");
}
else {
printf("\t Call to DeleteIPAddress failed.\n");
}
free(pAddresses);
VirtualFree(&dwSize, 0, MEM_RELEASE);
return 0;
}
I'm working on a proxy application in C for a project. I have an issue with getaddrinfo() being unsuccessful when I pass it the parsed host name. If I hard code the host, for example "www.google.ca" it doesn't error but when given the URL (from a GET request that the code receives) it does produce an error (The exact error is "Unknown name or service"). I've tried debugging in NetBeans and as far as I can tell the parsed URL is no different from the one I've hard coded. Below is the code that I'm using:
Snippet of code that receives the request and tries to forward it:
...
//Message is received in the code before this
if (get_host(message, &url) == 0)
{
//Tries to open a socket to the parsed URL. This is where the issue happens
forawrd_fd = create_forward_socket(url, "80");
}
...
The get host function:
int get_host(char *request, char **host_url)
{
char url[BUFFER_SIZE];
if(sscanf(request, "%*s %s HTTP/1.1\r\n", url) != 1)
{
return -1;
}
else
{
int len = strlen(url);
//If there is a / at the end of the URL remove it
if(url[len-1] == '/')
{
printf("%c%c\n", url[len-2], url[len-1]);
url[len-1] = '\0';
printf("%s\n", url);
}
*host_url = &url;
//If the start of the string is http:// remove it
if(url[0] == 'h' && url[1] == 't' && url[2] == 't'&& url[3] == 'p')
{
*host_url += 7;
}
return 0;
}
}
Function that gets the file descriptor and makes the getaddrinfo
int create_forward_socket(char* url, const char* port)
{
//Status variable needed for some calls
int status, socket_fd, received_data;
//Setup address info structs
struct addrinfo hints;
struct addrinfo *result, *current;
//Initialize our hints.
memset(&hints, 0, sizeof hints);
//IPv4 or IPv6 we don't
hints.ai_family = AF_UNSPEC;
//We want a stream socket not datagram
hints.ai_socktype = SOCK_STREAM;
//Whatever this means (I forget but again the interwebs says...)
hints.ai_flags = AI_PASSIVE;
//Get a linked list of address info that we will choose from
if ((status = getaddrinfo(url, port, &hints, &result)) != 0) //Status here is -2 when called with the parsed URL
{
return -1;
}
for (current = result; current != NULL; current = current->ai_next)
{
if ((socket_fd = socket(current->ai_family, current->ai_socktype, current->ai_protocol)) != -1)
{
if (connect(socket_fd, current->ai_addr, current->ai_addrlen) != -1)
{
//We found a usable socket
break;
}
else
{
close(socket_fd);
}
}
}
if (current == NULL)
{
return -2;
}
else
{
return socket_fd;
}
}
Any help would be appreciated. If more of my code is needed please let me know. I included only what I thought was important so the post wasn't too long.
My guess is that you are returning a pointer to a local variable. See, url is a local variable, and the *host_url = url; line (I'm assuming that this is an output parameter) will return it to the caller. But local variables will be destroyed just when the function returns, and then, *host_url will point to the middle of nowhere.
The code calling get_host() is like:
char *host;
get_host(req, &host);
//call getaddrinfo with host
But host will not point to valid memory outside of get_host.
The solution is that the caller allocates the buffer:
int get_host(char *request, char *url)
{ ... }
And when you call it:
char host[BUFFER_SIZE];
get_host(req, host);
//call getaddrinfo with host
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);
}