RAW TCP socket in windows with C? - c

I am writing a proxy in C (Windows 8.1 Environment). I did the same in Linux without any trouble but in windows things look different.
First of all, I am aware of MS Windows restrictions for sending RAW TCP Data and read this post. I also found WinPcap as a potential solution. The difference is I need to add Ethernet frame (DstMac, SrcMac, and Protocol Type) and ran the following codes:
if ((fp = pcap_open_live(d->name, // name of the device
65536, // portion of the packet to capture. It doesn't matter in this case
1, // promiscuous mode (nonzero means promiscuous)
1000, // read timeout
errbuf // error buffer
)) == NULL)
{
fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
}
then I created a packet:
u_char * data;
data = (u_char *)malloc(sizeof(u_char)*(ip_size+14));
memcpy((void*)data, (void*)dmac, 6);
memcpy((void*)(data + 6), (void*)smac, 6);
USHORT TmpType = 8;
memcpy((void*)(data + 12), (void*)&TmpType, 2);
memcpy(data+14, iphdr, ip_size); //iphdr is the full packet -(minus) ethernet header
//ip_size is the sizeof(iphdr)
pcap_sendpacket(fp, data, ip_size+14); //14: size of ethernet header
free(data);
In my test the first iphdr is a TCP Syn packet. When I send it to the network, I can capture it in Wireshark. However, the remote server does not respond to this packet and I got [TCP Out-of-Ordfer] messages and then a few RST packet and nothing happens.
my questions are:
1- Is winpcap the only feasible solution in windows with C?
2- If no, could you please provide any example/resource for developing RAW TCP sockets in C?
3- If yes, what causes the server does not response my manually crafted TCP Syn.
PS: I use the same code for creating TCP SYN in linux and it works perfectly. So, I have no doubt the tcphdr contain the IP header, TCP header and payload with correct checksums in both IP, and TCP headers.

Related

What is a best way to send message from tcp server to raspberry pi?

I'm trying to use REST API server on my pi1 and TCP server on AWS EC2
I have two raspberry pis and as I wanted to use tcp server (in C) that I learned
(first one at home, second one at anywhere with wifi)
My goal is
if anyone (external) sends something on my pi's raspberry pi REST API server INSTANTLY
in an endpoint function, creates tcp client and also sending some JSON result to send somewhere
let mut stream =
TcpStream::connect("ec2-XXX-compute.amazonaws.com:8888")
.await
.expect("connect failed");
// Buffer the bytes
stream
.write_all(action.as_bytes())
.await
.expect("sending msg");
stream
.shutdown(Shutdown::Both)
.expect("shutdown call failed");
this client sends the message to EC2's TCP server and read with C language
if ((client_socket = accept(server_fd, (struct sockaddr *)&newAddr,
&addr_size)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(client_socket, buffer, 10);
printf("From client: %s\n", buffer);
It works very well so far but what I want to do from here is to send the buffer data to
my another raspberry pi (pi2)
(pi 2's wifi keeps changing so it can only access internet, can't run server here)
What will be the best way to do this without delay or checking?
Sorry for the ugly picture but hope this helps your understanding
on PI 1, I'm running rest api/tcp server
and pi 2 can run tcp client server anywhere and connect to the pi 1
implemented with multiple clients without threading
Thanks all who watched this question!

2 program get same udp packets from a port

there is a server will send some UDP packets to my localhost, for example: if it send some UDP packets to my localhost and destination port is 5000. and there will have a client program to receive it on port 5000. but, what I want is to create another program, it will try to receive the same packets on port 5000.
if the server send packets p1, p2, p3....pn to my localhost port 5000, I want to both client programs will receive same packets. (client program 1: p1, p2, p3....pn, client program 2: p1, p2, p3...pn)
I tried to use pcap to do this, but seems lost some packets in sometimes.(the server will send some video stream to client)
You need to use multicast if you want to do this with a single send / sendto on the server process. Here are quick examples done in Python 2.7.x for the sake of brevity / reuse of code I had laying around.
It's import for the transmit side to set IP_MULTICAST_LOOP if you are going to use this method with transmitter & receivers running on the same host.
sender.py:
#!/usr/bin/env python
import socket
import sys
MCAST_GROUP=sys.argv[1]
MCAST_PORT=int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt( socket.SOL_SOCKET, socket.IP_MULTICAST_LOOP, 1 )
for ii in xrange(10):
msg = 'message %d' %ii
print 'sending: "%s"' %msg
s.sendto( msg, (MCAST_GROUP, MCAST_PORT)
receiver.py:
#!/usr/bin/env python
import socket
import sys
import struct
MCAST_GROUP=sys.argv[1]
MCAST_PORT=int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
s.bind( (MCAST_GROUP, MCAST_PORT) )
# In C, you'll want to use struct ip_mreq here. See 'man 7 ip' for details.
# Python's socket module doesn't define a convenient way to do this, hence the
# 'manual' struct.pack
mreq = struct.pack( '4sI', socket.inet_aton(MCAST_GROUP), socket.INADDR_ANY )
s.setsockopt( socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq )
while True:
rx_data = s.recv(1000)
print 'received: "%s"' %rx_data
Both programs expect two command line arguments, an IPv4 multicast IP (224.0.0.0 - 239.255.255.255), and a port. For example (./sender.py 239.10.10.10 5000).
You should be able to run as many instances of receiver.py as you like in different terminals, and see that a single instance of sender.py will transmit to all receivers.
To translate this to C, it's basically:
Convert s = socket.socket(...) -> s = socket(...)
Convert s.X(...) to X(s, ...) for X={setsockopt, bind, send, recv}
See notes about ip_mreq.
Once you read/recv on the socket the messages will be gone from the socket, so even if you use SO_REUSEADDR/ SO_REUSEPORT, I don't think you will be able to read the packets with both clients.
I think the easiest option is to have a local service running on port 5000 which then forwards all packets to the other services. Whether you write that as a server pub/sub style or hard-code it is probably something to decide based on how much effort you want to put into this.

why i am getting Remote ip address 0.0.0.0 from recvfrom()?

I have a server listening on a port
The request is sent from my local client to the server running on my local pc.
Following is my code snippet
remote_len = sizeof(remote_addr);
if ((bytes=recvfrom(sockfd, buf, MAXBUFLEN , 0,
(struct sockaddr *)&remote_addr, &remote_len)) <= 0) {
exit(1);
}
printf("remote ip = %s\n",inet_ntoa(remote_addr.sin_addr));
When i print the ip i get 0.0.0.0 ??
Is this not the remote IP adrress which i am trying to print?
Edit : Its a TCP socket and i recevied buffer successfully.
See TCP recvfrom() doesn't store 'from' - apparently it's not supported for TCP. All you're seeing is the zero bytes that were originally there. That's why remote_len returns 0 - because no address was set.
That link is to windows related docs; I don't see that behaviour in the Linux man page, which says only "may be used to receive data on a socket whether or not it is connection-oriented", but at http://www.beej.us/guide/bgnet/output/html/multipage/recvman.html it says that recvfrom is for UDP. It's not mentioned in Harbison + Steele, unfortunately, and I can't find a copy of Unix Network Programming.

network device module equivalent to ping

I have made a module which is transmitting but I don't know whether the packet which I am transmitting is a ping packet or not. Code is shown below:
icmp.type = 8;
icmp.code = 0;
icmp.un.echo.sequence = i;
ip4.protocol = 1; //for icmp protocol
ip4.frag_off = 0;
ip4.daddr = in_aton(procfs_buffer);
ip4.saddr = in_aton(ifr->ifr_addr.sa_data);
len = sizeof(data);
skb = dev_alloc_skb(1500);
skb->dev = __dev_get_by_name(&init_net,"wlan0");
skb_reserve(skb,NET_IP_ALIGN); // header of 2 bytes; increments tail and
// data pointer
skb->data = skb_put(skb,sizeof(len)); // increments all pointer or adds data
memcpy(data,skb->data,len);
skb->transport_header =skb_push(skb,sizeof(icmp));
memset(skb->transport_header,0,sizeof(struct icmphdr));
memcpy(skb->transport_header,&icmp,sizeof(struct icmphdr));
skb->network_header=skb_push(skb,sizeof(ip4));
memset(skb->network_header,0,sizeof(struct iphdr));
memcpy(skb->network_header,&ip4,sizeof(struct iphdr));
// printk("i::%d\n",i);
// skb->mac_header = skb_push(skb,6*sizeof(0xFF));
// memset(skb->mac_header,0xFF,6*sizeof(0xFF));
dev_queue_xmit(skb);
kfree(skb);
How can I know that it is a ping packet which I am creating and transmitting? Further I want to receieve the ping packet in response to my ping packet which I have transmitted. I would like to use napi but wont mind any other suggestions.
please read a topic : reception napi mode here i could nt understand what to do from the link above.....
You can use wireshark to capture all network traffic going in and out of one of your network interface. You'll be able to check that the packet has been sent and if it was actually what you expect it to be. You'll also be able to see if there is an answer to your ping.
Regarding your question on how to intercept the ping answer from your module, you can use the netfilter API offered by the kernel. Here is a good article to start with using netfilter.
a ping packet is simply icmp packet with code 8, with timestamp in its data
icmp echo reply (ping reply) just copies the data from the icmp echo request and sends it back, this way ping can tell you how much time it took for the round trip (now - prev' sended time)
i am not very familiar with the linux kernel, but be sure to calculate the correct ip and icmp checksums
also for receiving, it might be better to use netfilter

C pcap detecting inbound datagrams

In C I bind a datagram socket (AF_INET, SOCK_DGRAM) to INADDR_ANY. I then periodically use this socket to send and receive datagrams, and monitor the flow of packets with pcap. The problem is, I can't tell whether a packet is incoming or outgoing using pcap.
The transmission/receiving and the pcap monitoring are running in separate threads, and for synchronisation reasons they can't communicate. I only want to track the incoming packets, not the ones being sent, so does anyone have an idea as to how I can do that?
I thought already of testing the destination ip address, but I can't figure out any way to get my local ip. the machine this is running on doesn't have a static ip, much less an assigned domain name, and it seems that getsockname doesn't work on sockets bound to INADDR_ANY. Also tried using ioctl(sockfd, SIOCGIFCONF, &buffer), which didn't work either - sets buffer.ifc_len=0.
Found a solution. I can get my own ip using this:
char *command = malloc(100);
sprintf(command,"ifconfig %s|grep -o \"inet addr:[^ ]\"|grep -o -e \"[0-9]\.[0-9]\.[0-9]\.[0-9]*\"",device);
char path[1035];
FILE *fp;
fp = popen(command,"r");
fgets(path, 1034, fp);
pclose(fp);
my_ip = malloc(sizeof(char)*(1+strlen(path)));
memcpy(my_ip, path, strlen(path)-1);
my_ip[strlen(path)-1] = 0;

Resources