Using AddIpAddress()/DeleteIpAddress() with info from GetAdaptersAddresses() - c

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;
}

Related

GetQueuedCompletionStatus - How to read clients messages without any socket struct

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...
}
}

Obtaining real device of VLAN-interface through the netlink

I need to obtain the real_dev (f.e. ID) of the given VLAN-inteface.
I wrote some test snippet using libnl:
int main(void) {
struct nl_sock *sock;
struct nl_cache *cache;
char iface[] = "eno1.10";
//char iface[] = "eno1";
if (!(sock = nl_socket_alloc())) {
perror("nl_socket_alloc");
return -1;
}
if (nl_connect(sock, NETLINK_ROUTE) < 0) {
perror("nl_connect");
nl_socket_free( sock );
return -1;
}
if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache) < 0) {
perror("rtnl_link_alloc_cache");
nl_socket_free( sock );
nl_close( sock );
return -1;
}
{
int ifindex;
struct rtnl_link *link = NULL;
if (!(ifindex = rtnl_link_name2i(cache, iface))) {
perror("rtnl_link_name2i");
return -1;
}
printf("ind: %d\n", ifindex);
if (!(link = rtnl_link_get(cache, ifindex))) {
perror("rtnl_link_get");
return -1;
}
if (rtnl_link_is_vlan(link)) {
puts("It's VLAN link");
/* alas it's not about the 'real' device */
printf("master: %d\n", rtnl_link_get_master(link));
} else
puts("It's 'real' link");
}
return 0;
}
So I have some interface ID and I can check if it's a VLAN-interface, but I have no idea how to obtain the interface the vlan is attached to.
It seems that libnl's API does not provide such possibility.
Is there a way to obtain the VLAN's "parent" interface ID through the libnl or the native netlink API?
It's all about IFLA_LINK:
/* IFLA_LINK.
For usual devices it is equal ifi_index.
If it is a "virtual interface" (f.e. tunnel), ifi_link
can point to real physical interface (f.e. for bandwidth calculations),
or maybe 0, what means, that real media is unknown (usual
for IPIP tunnels, when route to endpoint is allowed to change)
*/
Thus through the native netlink API it could be done such a way:
/* some preparation code */
struct rtattr *rta = IFLA_RTA(msg);
int len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len))
if (rta->rta_type == IFLA_LINK) {
printf("Real device ID:%u\n",
*(unsigned short *)((char *) rta + NLA_HDRLEN));
break;
}
Full example on github.

libusb bulk read returning same aswer everytime

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;
}

Find Single Interface IP address (libpcap)

I'm trying to extract a single IP address for a single interface, i've got this to print out all of the IP addresses for all the interfaces and tried to do
if (d->name == en0) {
char myip = inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr);
// print myip
}
But it just returns null. I'm not all that familiar with C unfortunately, how can I extract the IP address based on the interface name?
static char errbuf[PCAP_ERRBUF_SIZE];
void getInterfaces()
{
char myip;
pcap_if_t *alldevs;
int status = pcap_findalldevs(&alldevs, errbuf);
if(status != 0)
{
printf("%s\n", errbuf);
}
for(pcap_if_t *d=alldevs; d!=NULL; d=d->next)
{
printf("%s:", d->name);
for(pcap_addr_t *a=d->addresses; a!=NULL; a=a->next)
{
if(a->addr->sa_family == AF_INET)
{
printf(" %s", inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr));
}
}
printf("\n");
}
pcap_freealldevs(alldevs);
}
----Console:-----------------------------------------------
en0: 192.168.56.1
awdl0:
bridge0:
tun0: 10.20.30.40
en1:
en2:
p2p0:
lo0: 127.0.0.1
char myip = inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr);
inet_ntoa returns a char * (not a char), change to:
char *myip = inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr);
This line is also wrong:
if (d->name == en0) {
you want:
if (strcmp(d->name, "en0") == 0) {

Building an http packet in libnet(tcp packet), Please help us as soon as posible. we are stuck!

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);
}

Resources