What I wanna do: Implement a layer 2 protocol in user-space.
So I'm using pcap under Linux 2.6.32 to sniff packets:
...
struct pcap_t *pcap_h = pcap_open_live("wlan0", BUFSIZ, 1, 0, errbuf);
...
while (1) {
int ret = pcap_loop(pcap_h, -1, newpkt_callback, NULL);
...
}
...
Which works just fine for all packets. But, when I use pcap to send packets with no ether_head and no IP header:
const char pkt[] = "WHATEVER";
nsent = pcap_sendpacket(pcap_h, (const u_char *)pkt, len);
...
I can only sniff the packet on the localhost, and not on other laptops that are running the same program. So the question is "how can I broadcast messages without ether_head on a wlan"? Any pointers would be appreciated.
You can't do this if you are using an access point (infrastructure mode), as the access point relays the frames between other wireless stations and thus must know how to talk your layer 2 protocol.
I suggest implementing your protocol at layer 3 (and you may want to look into PF_PACKET sockets).
You have to send complete frame with it's headers, not just some random data.
Take a look at this manual http://linux.die.net/man/3/pcap at function pcap_inject(). In creating new frame this could help http://www.tcpdump.org/pcap.html, or just use libnet library http://libnet.sourceforge.net/libnet.html.
Related
I'm implementing packet collector, but I suffer from packet drops.
My binary can get most of packets from some specific IP region. (Ex. 100.101.1.1, 100.101.2.1). But to some specific IP region, I cannot get any packet. (Ex. 200.201.1.1, 200.201.2.1)
At that time, tcpdump can get packets from any IP regions.
My pcap code snippet from my implementation is followings:
struct bpf_program fp;
pcap_t *pcd;
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 netp;
char port[16], dev[16];
......
pcd = pcap_open_live(dev, BUFSIZ, PROMISCUOUS, -1, errbuf);
pcap_compile(pcd, &fp, port, 0, netp);
pcap_setfilter(pcd, &fp);
while(1){
packet = pcap_next(pcd, &hdr);
}
Is there any idea for me?
Since you mentioned that you can get all the ip packets on the interface using tcpdump, I would consider the following line in your code is all right as long as you are using the same interface name for the parameter dev as you use for tcpdump.
pcap_open_live(dev, BUFSIZ, PROMISCUOUS, -1, errbuf);
The issue might be in the line,
pcap_compile(pcd, &fp, port, 0, netp);
In the above line, port variable is a filter string. Your packet collector will only collect the packets that passes this filter. If you are not using proper filter parameters in your port string to allow also the packets involving ip addresses 200.201.x.x, you will not capture them.
I have a client on PC. I have a server on PC. The client and server are connected via a router with firmware based on Linux OS.
The client sends a packet to the server and receive a response. The router must intercept the packets and modify it. Something like sniffing but it's not a sniffing because i need to modify the packets.
I must to write a program for this.
I tried to open a raw socket on the router, but reсvfrom on raw socket does not intercept the packet and just copy it. The packet is going on.
Could you suggest me any way to solve this problem?
P.S. Sorry for my bad English. :)
I'd use a mix of iptables and libnetfilter_queue (assuming your kernel is relatively recent)
Add to the iptables a rules that forward all the udp packets to the NFQUEUE 0 in order to get packets from kernel to user space.
iptables -A INPUT -p udp -m udp --dport xxxxx -j NFQUEUE --queue-num 0
Build a process who listen to the NFQUEUE number 0, modify payload and give the full packet back to the kernel space using libnetfilter_queue capabilities. Follow this link to know how to do it.
In a nutshell you have to open the queue 0 (nfq_create_queue), set the mode in order to get the content of the packet (nfq_set_mode), then loop in an infinite recv to get ever udp packet filtered by iptables
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
printf("pkt received\n");
nfq_handle_packet(h, buf, rv);
}
Everytime you call nfq_handle_packet is called, the callback defined during the nfq_create_queue phase is called. In that callback you have to modify the payload, update the size and recalculate the checksum, then set as "valid" with nfq_set_verdict
I wrote the module for the kernel and some applications. Module uses netfilter and discards packets that I need to netfilter_queue. The application processes a queue and I decide what to do with each package.
uint hook_main(uint hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *) )
{
struct iphdr *ip;
struct udphdr *udp;
if (skb->protocol == htons(ETH_P_IP)){
ip = (struct iphdr *)(skb->data);
if (ip->version == 4 && ip->protocol == IPPROTO_UDP){
udp = (struct udphdr *)(skb->data + sizeof(struct iphdr));
if(ntohs(udp->dest) == SOME_PORT){
return NF_QUEUE;
}
}
}
return NF_ACCEPT;
}
int init_module ()
{
printk("[udp-catch] start udp-catch\n");
catch_hook.hook = hook_main;
catch_hook.owner = THIS_MODULE;
catch_hook.pf = PF_INET;
catch_hook.hooknum = NF_INET_FORWARD;
catch_hook.priority = NF_IP_PRI_FIRST;
nf_register_hook(&catch_hook);
return 0;
}
And a redesigned sample from netfilter.org is the application.
Routers will automatically send out whatever they receive on their other ports.
e.g. For a 4 port router, what comes in on port 1 will be sent out on ports 2,3 & 4.
To do what you require, you need another PC with 2 network cards. Connect your client PC to one network card, and the server PC to the other.
Then your program will need to recvfrom on one network card, modify the packet and sendto on the other network card.
I'm working with Cortex M3, Stellaris® LM3S6965 Evaluation Board. I'm sending an UDP packet to my pc. That works because I checked it with wireshark. But what I do see is that I don't have a source port. And I have no clue how so solve this.
I call this function to sent the a udp packet
void send_udp(){
RIT128x96x4Enable(1000000);
RIT128x96x4StringDraw("UDP data verzonden..", 0, 40, 15);
struct ip_addr serverIp;
IP4_ADDR(&serverIp,192,168,1,100);
u16_t port;
port = 64000;
struct udp_pcb * pcb;
pcb = udp_new();
udp_bind(pcb, &serverIp, port);
udp_recv(pcb, udp_echo_recv, NULL);
struct pbuf *p;
char msg[]="request";
//Allocate packet buffer
p = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg),PBUF_RAM);
memcpy (p->payload, msg, sizeof(msg));
udp_sendto(pcb, p, &serverIp, port);
pbuf_free(p); //De-allocate packet buffer
}
Wireshark example of packet: (click here to enlarge)
The call to udp_bind() should assign the local port, but it seems to be failing for you.
The number you're using (64000) is in the range called dynamic, private or ephemeral ports, which might be why it's not working as expected.
From the documentation, udp_bind() supports port number 0 to get a dynamically assigned number; this is typically the way to go if the source port isn't important.
I also saw that "time to live" in the ipv4 pcb was 0.
So I added this line,
pcb->ttl = UDP_TTL; // Time to live
This solved my issue
What is the right (portable, stable) way to get the ToS byte of a received packet? I'm doing UDP with recvmsg() and on linux I can get the ToS if I setsockopt() IP_RECVTOS/IPV6_RECVTCLASS, but IP_RECVTOS doesn't seem to be available on my BSD systems. What is the right way to do this?
I primarily want this to work on the BSDs and Solaris.
Edit:
To clarify:
I currently use recvmsg() where I get the TTL and TOS in the msg_control field on Linux, but in order to get TTL and TOS I need to setsockopt()-enable IP_RECVTTL and IP_RECVTOS. And since Solaris and BSD (working with FreeBSD at the moment) don't have IP_RECVTOS from what I can see I don't get TOS when looping over the CMSG data.
I tried enabling IP_RECVOPTS and IP_RECVRETOPTS, but I still don't get any IP_TOS type CMSG.
Edit 2:
I want ToS to be able to verify (as much as possible) that it wasn't overwritten in transit. If for example a VoIP app all of a sudden notices that it's not getting EF tagged packets, then something is wrong and there should be an alarm. (and no, I'm not expecting EF to be respected or preserved over the public internet)
I want TTL basically just because I can. Hypothetically this could be used to trigger "something changed in the network between me and the other side" alerts, which can be useful to know if somethings stops working at the same time.
I was thinking if you can create two sockets.
One socket of type DGRAM used exclusively for sending
One Raw socket used exclusively for receiving.
Since you are using UDP, you can call a bind + recvFrom on the Raw Sock Fd and then manually unpack the IP header to determine the TOS or TTL.
When you want to send, use the DGRAM sockFd so you dont have to bother to actually create the UDP & IP packet yourself.
There may be issues like the kernel may pass the received buffer to both sockets or to the UDP socket instead of Raw socket or just to the Raw socket. If that is the case (or if it is implementation dependent) then we are back to square one. However, you can try calling bind on the Raw socket and see if it helps. I am aware this maybe a hack but searching on the net for a setsockopt for BSD returned nothing.
EDIT: I wrote a sample program
It kind of achieves the objective.
The code below creates two sockets (one raw & one udp). The udp socket is bound on the actual port I am expecting to receive data whereas the raw socket is bound on Port 0. I tested this on Linux and like I expected any data for port 2905 is received by both the sockets. I am however able to retrieve the TTL & TOS values. Dont downvote for the quality of the code. I am just experimenting whether it will work.
Further EDIT: Disabled the receive by UDP socket.
I have further enhanced the code to disable the receive by the UDP packet. Using setsockopt, I set the UDP's socket receive buffer to 0. This ensures the kernel does not pass the packet to the UDP socket. IMHO,You can now use the UDP socket exclusively for sending and the raw socket for reading. This should work for you in BSD and Solaris also.
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<string.h>
#include "protHeaders.x"
#include "gen.h"
int main(void)
{
S32 rawSockFd;
S32 udpSockFd;
struct sockaddr_in rsin;
struct sockaddr_in usin;
S32 one = 1;
const S32* val = &one;
struct timeval tv;
fd_set rfds;
S32 maxFd;
S16 ret;
S8 rawBuffer[2048];
S8 udpBuffer[2048];
struct sockaddr udpFrom,rawFrom;
socklen_t rLen,uLen;
memset(rawBuffer,0,sizeof(rawBuffer));
memset(udpBuffer,0,sizeof(udpBuffer));
memset(udpFrom,0,sizeof(udpFrom));
memset(rawFrom,0,sizeof(rawFrom));
if ((rawSockFd = socket(PF_INET,SOCK_RAW,IPPROTO_UDP)) < 0)
{
perror("socket:create");
RETVALUE(RFAILED);
}
/* doing the IP_HDRINCL call */
if (setsockopt(rawSockFd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0)
{
perror("Server:setsockopt");
RETVALUE(RFAILED);
}
rsin.sin_family = AF_INET;
rsin.sin_addr.s_addr = htonl(INADDR_ANY);
rsin.sin_port = htons(0);
usin.sin_family = AF_INET;
usin.sin_addr.s_addr = htons(INADDR_ANY);
usin.sin_port = htons(2905);
if(bind(rawSockFd,(struct sockaddr *)&rsin, sizeof(rsin)) < 0 )
{
perror("Server: bind failed");
RETVALUE(RFAILED);
}
if ((udpSockFd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
{
perror("socket:create");
RETVALUE(RFAILED);
}
if(bind(udpSockFd,(struct sockaddr *)&usin, sizeof(usin)) < 0 )
{
perror("Server: bind failed on udpsocket");
RETVALUE(RFAILED);
}
/*set upd socket receive buffer to 0 */
one = 0;
if (setsockopt(udpSockFd,SOL_SOCKET,SO_RCVBUF,(char *)&one,sizeof(one)) < 0)
{
perror("Server:setsockopt on udpsocket failed");
RETVALUE(RFAILED);
}
tv.tv_sec = 0;
tv.tv_usec = 0;
maxFd = (rawSockFd > udpSockFd)? rawSockFd:udpSockFd;
while(1)
{
FD_ZERO(&rfds);
FD_SET(rawSockFd,&rfds);
FD_SET(udpSockFd,&rfds);
ret = select(maxFd+1,&rfds,0,0,&tv);
if ( ret == -1)
{
perror("Select Failed");
RETVALUE(RFAILED);
}
if(FD_ISSET(rawSockFd,&rfds))
{
printf("Raw Socked Received Message\n");
if(recvfrom(rawSockFd,rawBuffer,sizeof(rawBuffer),0,&rawFrom,&rLen) == -1)
{
perror("Raw socket recvfrom failed");
RETVALUE(RFAILED);
}
/*print the tos */
printf("TOS:%x\n",*(rawBuffer+1));
printf("TTL:%x\n",*(rawBuffer+8));
}
if(FD_ISSET(udpSockFd,&rfds))
{
printf("UDP Socked Received Message\n");
if(recvfrom(udpSockFd,udpBuffer,sizeof(udpBuffer),0,&udpFrom,&uLen) == -1)
{
perror("Udp socket recvfrom failed");
RETVALUE(RFAILED);
}
printf("%s\n",udpBuffer);
}
}
RETVALUE(ROK);
}
The "proper" and standard solution is probably to use cmsg(3). You'll find a complete description in Stevens' "Unix network programming" book, a must-read.
Google Code Search found me this example of use.
My understanding is that firstly BSD does not support IP_RECVTOS like functionality and secondly BSD raw sockets do not support the reception of UDP nor TCP packets. However there are two other ways of doing this, firstly by using the /dev/bpf interface - either directly or via libpcap. Or secondly by using DIVERT sockets which allow for diversion of specified traffic flows to userland.
Has anyone actually tested the code above on a BSD box? (it may work on Solaris...)
On Linux this approach will work but as mentioned it is also possible (and more convenient) to use setsockopt() with IP_TOS on the outgoing socket to set the outgoing TOS byte and setsockopt() with IP_RECVTOS on the incoming socket and use recvmsg() to retrieve the TOS byte.
Unfortuneatly this sort of thing usually varies across different *ixs. On Solaris you want to use getsockopt with IP_TOS; I don't know about BSD.
See man 7 ip for details.
I want to write a real-time analysis tool for wireless traffic.
Does anyone know how to read from a promiscuous (or sniffing) device in C?
I know that you need to have root access to do it. I was wondering if anyone knows what functions are necessary to do this. Normal sockets don't seem to make sense here.
On Linux you use a PF_PACKET socket to read data from a raw device, such as an ethernet interface running in promiscuous mode:
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
This will send copies of every packet received up to your socket. It is quite likely that you don't really want every packet, though. The kernel can perform a first level of filtering using BPF, the Berkeley Packet Filter. BPF is essentially a stack-based virtual machine: it handles a small set of instructions such as:
ldh = load halfword (from packet)
jeq = jump if equal
ret = return with exit code
BPF's exit code tells the kernel whether to copy the packet to the socket or not. It is possible to write relatively small BPF programs directly, using setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ). (WARNING: The kernel takes a struct sock_fprog, not a struct bpf_program, do not mix those up or your program will not work on some platforms).
For anything reasonably complex, you really want to use libpcap. BPF is limited in what it can do, in particular in the number of instructions it can execute per packet. libpcap will take care of splitting a complex filter up into two pieces, with the kernel performing a first level of filtering and the more-capable user-space code dropping the packets it didn't actually want to see.
libpcap also abstracts the kernel interface out of your application code. Linux and BSD use similar APIs, but Solaris requires DLPI and Windows uses something else.
I once had to listen on raw ethernet frames and ended up creating a wrapper for this. By calling the function with the device name, ex eth0 I got a socket in return that was in promiscuous mode.
What you need to do is to create a raw socket and then put it into promiscuous mode. Here is how I did it.
int raw_init (const char *device)
{
struct ifreq ifr;
int raw_socket;
memset (&ifr, 0, sizeof (struct ifreq));
/* Open A Raw Socket */
if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
{
printf ("ERROR: Could not open socket, Got #?\n");
exit (1);
}
/* Set the device to use */
strcpy (ifr.ifr_name, device);
/* Get the current flags that the device might have */
if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not retrive the flags from the device.\n");
exit (1);
}
/* Set the old flags plus the IFF_PROMISC flag */
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not set flag IFF_PROMISC");
exit (1);
}
printf ("Entering promiscuous mode\n");
/* Configure the device */
if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
{
perror ("Error: Error getting the device index.\n");
exit (1);
}
return raw_socket;
}
Then when you have your socket you can just use select to handle packets as they arrive.
You could use the pcap library (see http://www.tcpdump.org/pcap.htm) which is also used by tcpdump and Wireshark.
Why wouldn't you use something like WireShark?
It is open source, so at least you could learn a few things from it if you don't want to just use it.
WireShark on linux has the capability to capture the PLCP (physical layer convergence protocol) header information.