I am trying to convert hping3 to hping6. hping3 uses Pcap library to receive IPv4 packets. But I need to receive IPv6 packets.
That is possible. libpcap is able to catch anything on the wire.
Example using ETHERTYPE_IPV6:
static u_int16_t ether_packet(u_char *args, const struct pcap_pkthdr *pkthdr, co
nst u_char *p) {
struct ether_header *eptr = (struct ether_header*)p;
assert(pkthdr->caplen <= pkthdr->len);
assert(pkthdr->caplen >= sizeof(struct ether_header));
return eptr->ether_type;
}
// This is the callback. assumes ethernet frame.
static void pcap_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_
char* p)
{
const u_int16_t type = ether_packet(args, pkthdr, p);
switch (ntohs(type)) {
case ETHERTYPE_IP:
// handle IPv4
break;
case ETHERTYPE_IPV6:
// handle v6
break;
}
}
Related
I'm developing a C application using libpcap.
I can capture frames using this code that I developed:
void ethernetCaptureHandler( u_char *args, const struct pcap_pkthdr *packet_header, const u_char *packet_body)
{
struct ether_header *eptr;
eptr = (struct ether_header *) packet_body;
fprintf(stdout,"ethernet header source: %s\n"
,ether_ntoa((const struct ether_addr *)&eptr->ether_shost));
fprintf(stdout," destination: %s\n"
,ether_ntoa((const struct ether_addr *)&eptr->ether_dhost));
}
void *listenEthernetFrame(void *ehternetInterface){ //Thread Handler
struct ether_header *eptr;
char error_buffer[PCAP_ERRBUF_SIZE];
pcap_t *handle;
int timeout_limit = 10000; /* In milliseconds */
char *ethernet = (char *)ehternetInterface;
/* Open device for live capture */
handle = pcap_open_live(
ethernet,
BUFSIZ,
0,
timeout_limit,
error_buffer
);
if (handle == NULL) {
fprintf(stderr, "Could not open device %s: %s\n", ethernet, error_buffer);
return 2;
}
pcap_loop(handle, 0, ethernetCaptureHandler, NULL);
}
ethernetCaptureHandler function can listen to ethernet frames and as you can see I can get mac source and mac destination.
The question is: is there a way to know if the frame is sent or received? (supposing that frame mac source and mac destination doesn't change from node to an other)
Else is there a way to capture just only received frames?
I have a linux kernel module that needs to process the data received via netfilter hook as a socket buffer.
The data received on Debian 8 (kernel: 3.16.0) is good but with SlackWare 14.0 (kernel: 3.2.29) the data is incorrect. I do not understand what's wrong. I searched everywhere on the forum and on Google but I never found a solution.
This is my nfilter hook function:
static unsigned int magic_packet_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) {
struct iphdr *iph;
struct tcphdr *tcph;
//Return if empty
if(!skb)
return NF_ACCEPT;
//Get ip header
iph = ip_hdr(skb);
//Check protocol
if(iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
//Get tcp header
tcph = tcp_hdr(skb);
//Get & check data
char *data;
data = (char *)((unsigned char *)tcph+(tcph->doff*4));
if(!data)
return NF_ACCEPT;
//Print in dmesg
#ifdef DEBUG
printk("anhackit data: %s\n", data);
#endif
//Convert source ip to string
char ip[16];
snprintf(ip, 16, "%pI4", &iph->saddr);
//Convert destination port to string
char port[6];
sprintf(port, "%u", ntohs(tcph->dest));
#ifdef DEBUG
printk("anhackit - magic packet received from %s on port %s !\n", ip, port);
#endif
return NF_ACCEPT;}
I hope someone can help me. Thanks in advance.
I'm trying to create a kernel module that forward packets in certain conditions. Now I'm trying to do just a hard code test to forward a packet received in an interface and forward it to another interface. In this test I'm receiving a packet from 192.168.56.101 on eth0 and I want to forward this packet on eht1 for 192.168.57.103. In eth0 my ip is 192.168.56.102 and in eth1 my ip is 192.168.57.102. The transport protocol I'm using is a experimental protocol (253). The following code is just a simplified part of my code:
#define XOR_PROTOCOL 253
static unsigned int xor_pre_routing_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
struct xorhdr *ptr;
char sip[15];
char sip2[15];
iph = ip_hdr(skb);
sprintf(sip, "%pI4", &iph->saddr);
sprintf(sip2, "%pI4", &iph->daddr);
// Check if is XOR protocol
if (iph->protocol == XOR_PROTOCOL) {
DEBUG("(Ogirinal) From %pI4 to %pI4.\n", &iph->saddr, &iph->daddr);
if (strcmp(sip, "192.168.56.101") == 0 && strcmp(sip2, "192.168.56.255") == 0) {
//iph->saddr = inet_addr("192.168.57.102");
iph->daddr = inet_addr("192.168.57.103");
DEBUG("(Modified) From %pI4 to %pI4.\n", &iph->saddr, &iph->daddr);
iph = ip_hdr(skb);
iph->check = 0;
ip_send_check (iph);
return NF_ACCEPT;
}
}
accept:
return NF_ACCEPT;
}
This hook in NF_INET_PRE_ROUTING. I also have a hook to just print source and destination ip in NF_INET_FORWARD, but there is no packet passing through this hook.
I'm testing with 3 linux virtual machine on virtual box, and I enabled the forward option in each vm. Is possible to forward packets in this scenario? What I'm doing wrong and what can I do to solve this problem?
The problem is the broadcast ip 192.168.56.255, with the ip 192.168.56.102 the packets were forwarded.
Hi i am trying to parse a Ip/Udp packet's header details actually to get the timestamp,port adresses etc. I know i can use library to do this. So after googling a lot i found out a code to parse through a row packet in the following method
void dump_UDP_packet(const unsigned char *packet, struct timeval ts,
unsigned int capture_len)
{
struct ip *ip;
struct UDP_hdr *udp;
unsigned int IP_header_length;
/* For simplicity, we assume Ethernet encapsulation. */
if (capture_len < sizeof(struct ether_header))
{
/* We didn't even capture a full Ethernet header, so we
* can't analyze this any further.
*/
too_short(ts, "Ethernet header");
return;
}
/* Skip over the Ethernet header. */
packet += sizeof(struct ether_header);
capture_len -= sizeof(struct ether_header);
if (capture_len < sizeof(struct ip))
{ /* Didn't capture a full IP header */
too_short(ts, "IP header");
return;
}
ip = (struct ip*) packet;
IP_header_length = ip->ip_hl * 4; /* ip_hl is in 4-byte words */
if (capture_len < IP_header_length)
{ /* didn't capture the full IP header including options */
too_short(ts, "IP header with options");
return;
}
if (ip->ip_p != IPPROTO_UDP)
{
problem_pkt(ts, "non-UDP packet");
return;
}
/* Skip over the IP header to get to the UDP header. */
packet += IP_header_length;
capture_len -= IP_header_length;
if (capture_len < sizeof(struct UDP_hdr))
{
too_short(ts, "UDP header");
return;
}
udp = (struct UDP_hdr*) packet;
printf("%s UDP src_port=%d dst_port=%d length=%d\n",
timestamp_string(ts),
ntohs(udp->uh_sport),
ntohs(udp->uh_dport),
ntohs(udp->uh_ulen));
}
the thing is that i dont really know what are the parameters that i should use to invoke this function, ie, packet? timeval? etc am recieving my packets using socket api by listening to the port and using recv() function
for (;;)
{
len = sizeof(cliaddr);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
//sendto(sockfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
printf("-------------------------------------------------------\n");
printf("%s\n from:%s port number:%d",mesg,inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
printf("-------------------------------------------------------\n");
}
Now here can i use the the mesg[] to pass to the above function to get the packet details or else is there any other way to receive the packet from a specific port. What value shall i use for the timeVal. Any help would be useful for me. Thanks in advance
Here the most relevant is how do you open your socket. Do you create the socket with SOCK_RAW flag? If yes, then recvfrom will receive RAW packets which you can directly send to your function. I am not sure about Windows, but on Linux the code creating a raw socket is like::
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
The timeval argument is not directly relevant to the packet. It is supposed to be the time when you have got the packet. You will get it by calling gettimeofday after recvfrom.
Perhaps you should consider using libpcap (Packet CAPture library), the guts of tcpdump.
I am trying to change some fields in the IP and TCP header in a netfilter postrouting hook, however I can't seem to get the kernels TCP checksum function to work properly to amend it afterwards.
The checksum is fine during the TCP handshake, but as soon as the packet has any payload the checksum is wrong.
I have pulled this checksum code together from digging around the TCP source. I am fairly sure tcplen is correct, matching the expected TCP header + payload size.
static unsigned int posthook_fn(
unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
struct tcphdr *tcph;
iph = ip_hdr(skb);
tcph = (struct tcphdr *)(skb->data + iph->ihl * 4);
tcph->source = port;
iph->saddr = addr;
tcplen = (skb->len - (ip_header->ihl << 2));
tcph->check = 0;
tcph->check = tcp_v4_check(tcph, tcplen,
iph->saddr,
iph->daddr,
csum_partial((char *)tcph, tcplen, 0));
skb->ip_summed = CHECKSUM_NONE; //stop offloading
ip_header->check = ip_fast_csum((u8 *)iph, iph->ihl);
return NF_ACCEPT;
}
Am I correct in thinking that tcp_v4_check calculates the psuedo header and csum_partial calculates the unfolded checksum for the payload and tcp_header?
I really want to avoid writing the function myself as the kernel will be much faster as the underlying functions use assembly for the calculation.
Is there an alternative method that might work? Or is there something I am missing out?
There is no need for extra call to skb_is_nonlinear(), since include/linux/skbuff.h:
static inline int skb_linearize(struct sk_buff *skb)
{
return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
}
Also, you have to:
ip_header->check = 0
before:
ip_header->check = ip_fast_csum((u8 *)iph, iph->ihl);
It's taken a while to get here but the problem seems to be that the socket buffer isn't always linear, the following code ensures that it is before calculating the checksum.
if (skb_is_nonlinear(skb)) {
if (skb_linearize(skb) != 0) {
return NF_DROP;
}
iph = ip_hdr(skb);
tcph = (void *)iph + (iph->ihl << 2);
}