improved parser and bugfixes
This commit is contained in:
parent
e09d7e4f69
commit
99c8147033
1 changed files with 147 additions and 43 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <error.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -14,26 +15,26 @@
|
|||
#include <linux/if_packet.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#define SNAPLEN 65536
|
||||
#define INTERFACE "eth1"
|
||||
#define SNAPLEN 1024
|
||||
|
||||
const char* icmp_type_str[] = {
|
||||
[ 0 ] = "Echo Reply",
|
||||
[ 1 ... 2 ] = NULL,
|
||||
[ 1 ... 2 ] = NULL,
|
||||
[ 3 ] = "Destination Unreachable",
|
||||
[ 4 ] = "Source Quench",
|
||||
[ 5 ] = "Redirect",
|
||||
[ 6 ] = "Alternate Host Address",
|
||||
[ 7 ] = NULL,
|
||||
[ 7 ] = NULL,
|
||||
[ 8 ] = "Echo",
|
||||
[ 9 ] = "Router Advertisement",
|
||||
[ 10 ] = "Router Solicitation",
|
||||
|
@ -47,61 +48,161 @@ const char* icmp_type_str[] = {
|
|||
[ 18 ] = "Address Mask Reply"
|
||||
};
|
||||
|
||||
int hexdump(void *buf, size_t len)
|
||||
int hexdump(char *buf, size_t len)
|
||||
{
|
||||
uint16_t *data = (uint16_t *) buf;
|
||||
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
if (i % 16 == 0 && i != 0)
|
||||
size_t i;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
/* ASCII */
|
||||
if (i % 16 == 0 && i != 0) {
|
||||
printf("\t");
|
||||
for (size_t j = i-16; j < i; j++)
|
||||
printf("%c", isprint(buf[j]) ? buf[j] : '.');
|
||||
printf("\n");
|
||||
}
|
||||
/* Address offset */
|
||||
if (i % 16 == 0)
|
||||
printf("\t\t%#06x:\t", i);
|
||||
|
||||
printf("%04hx ", ntohs(data[i/2]));
|
||||
}
|
||||
|
||||
printf("\t");
|
||||
for (; i < len; i++)
|
||||
printf("%c", isprint(buf[i]) ? buf[i] : '.');
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int parse_packet(uint8_t *data, size_t len)
|
||||
int parse_packet(char *data, size_t len)
|
||||
{
|
||||
/* Parse Ethertype */
|
||||
int protocol;
|
||||
char *next_hdr;
|
||||
static int cnt;
|
||||
|
||||
printf("%5d >>> Received packet with %u bytes:\n", cnt++, len);
|
||||
|
||||
layer2: {
|
||||
struct ethhdr *eth = (struct ethhdr*) data;
|
||||
|
||||
printf("ether_src: %s ", ether_ntoa((const struct ether_addr*) eth->h_source));
|
||||
printf("ether_dst: %s ", ether_ntoa((const struct ether_addr*) eth->h_dest));
|
||||
printf("ether_type: %#04x ", eth->h_proto);
|
||||
|
||||
if (eth->h_proto == ETH_P_IP) {
|
||||
/* Parse IP protocol */
|
||||
struct iphdr *ip = (struct iphdr*) (eth+1);
|
||||
printf("\tEthernet src: %s dst: %s type: %#04x\n",
|
||||
ether_ntoa((const struct ether_addr*) eth->h_source),
|
||||
ether_ntoa((const struct ether_addr*) eth->h_dest),
|
||||
ntohs(eth->h_proto)
|
||||
);
|
||||
|
||||
protocol = ntohs(eth->h_proto);
|
||||
next_hdr = (char *) (eth + 1);
|
||||
}
|
||||
|
||||
|
||||
layer3: switch (protocol) {
|
||||
case ETH_P_IP: {
|
||||
/* Parse IP protocol */
|
||||
struct iphdr *ip = (struct iphdr*) next_hdr;
|
||||
char buf[32];
|
||||
|
||||
printf("ip_version: %u ", ip->version);
|
||||
printf("ip_ihl: %u ", ip->ihl);
|
||||
printf("ip_ttl: %u ", ip->ttl);
|
||||
printf("ip_protocol: %u ", ip->protocol);
|
||||
printf("ip_src: %u ", *((struct in_addr*) &ip->saddr));
|
||||
printf("ip_dst: %u ", *((struct in_addr*) &ip->daddr));
|
||||
printf("\tIP version: %u ihl: %u ttl: %u protocol: %u src: %s dst %s\n",
|
||||
ip->version,
|
||||
ip->ihl,
|
||||
ip->ttl,
|
||||
ip->protocol,
|
||||
inet_ntop(AF_INET, &ip->saddr, buf, sizeof(buf)),
|
||||
inet_ntop(AF_INET, &ip->daddr, buf, sizeof(buf))
|
||||
);
|
||||
|
||||
protocol = ip->protocol;
|
||||
next_hdr = (char*) ip + ip->ihl * 4;
|
||||
goto layer4;
|
||||
}
|
||||
|
||||
if (ip->protocol == IPPROTO_ICMP) {
|
||||
case ETH_P_IPV6: {
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr*) next_hdr;
|
||||
char buf[32];
|
||||
|
||||
printf("\tIP version: %u class: %u flow: %u hlim: %u: next: %u src: %s dst %s\n",
|
||||
ip6->ip6_vfc >> 4,
|
||||
ip6->ip6_vfc & 0xf,
|
||||
ip6->ip6_flow,
|
||||
ip6->ip6_hlim,
|
||||
ip6->ip6_nxt,
|
||||
inet_ntop(AF_INET6, &ip6->ip6_src, buf, sizeof(buf)),
|
||||
inet_ntop(AF_INET6, &ip6->ip6_dst, buf, sizeof(buf))
|
||||
);
|
||||
|
||||
protocol = ip6->ip6_nxt;
|
||||
next_hdr = (char*) (ip6 + 1);
|
||||
goto layer4;
|
||||
}
|
||||
|
||||
case ETH_P_ARP:
|
||||
printf("\tARP\n");
|
||||
goto dump;
|
||||
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
|
||||
layer4: switch (protocol) {
|
||||
case IPPROTO_ICMP: {
|
||||
/* Parse ICMP */
|
||||
struct icmphdr *icmp = (struct icmphdr*) ((char*) ip + ip->ihl * 4);
|
||||
|
||||
printf("icmp_type: %u (%s) ");
|
||||
printf("icmp_code: %u ");
|
||||
struct icmphdr *icmp = (struct icmphdr*) next_hdr;
|
||||
|
||||
printf("\tICMP type: %u (%s) code: %u\n",
|
||||
icmp->type,
|
||||
icmp_type_str[icmp->type],
|
||||
icmp->code
|
||||
);
|
||||
|
||||
goto dump;
|
||||
}
|
||||
else if (ip->protocol == IPPROTO_UDP) {
|
||||
|
||||
case IPPROTO_UDP: {
|
||||
/* Parse UDP */
|
||||
struct udphdr *udp = (struct udphdr*) ((char*) ip + ip->ihl * 4);
|
||||
|
||||
printf("udp_port: %u ");
|
||||
struct udphdr *udp = (struct udphdr*) next_hdr;
|
||||
|
||||
printf("\tUDP src: %u dst: %u len: %u\n",
|
||||
ntohs(udp->source),
|
||||
ntohs(udp->dest),
|
||||
ntohl(udp->len)
|
||||
);
|
||||
goto layer5;
|
||||
}
|
||||
else if (ip->protocol == IPPROTO_TCP) {
|
||||
|
||||
case IPPROTO_TCP: {
|
||||
/* Parse TCP */
|
||||
struct tcphdr *tcp = (struct tcphdr*) ((char*) ip + ip->ihl * 4);
|
||||
|
||||
printf("tcp_port: %u ");
|
||||
struct tcphdr *tcp = (struct tcphdr*) next_hdr;
|
||||
|
||||
printf("\tTCP src: %u dst: %u seq: %u win: %u ",
|
||||
ntohs(tcp->source),
|
||||
ntohs(tcp->dest),
|
||||
ntohl(tcp->seq),
|
||||
ntohs(tcp->window)
|
||||
);
|
||||
|
||||
if (tcp->fin) printf("FIN ");
|
||||
if (tcp->syn) printf("SYN ");
|
||||
if (tcp->rst) printf("RST ");
|
||||
if (tcp->ack) printf("ACK ");
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (tcp->fin || tcp->syn || tcp->rst)
|
||||
goto end;
|
||||
else
|
||||
goto layer5;
|
||||
}
|
||||
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
|
||||
dump:
|
||||
layer5:
|
||||
hexdump(next_hdr, len - (next_hdr - data));
|
||||
|
||||
end:
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
|
@ -111,7 +212,10 @@ int main (int argc, char *argv[])
|
|||
struct ifreq ifr;
|
||||
struct sockaddr_ll sll;
|
||||
|
||||
sd = socket(AF_INET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (argc != 2)
|
||||
error(-1, 0, "Usage %s INTERFACE", argv[0]);
|
||||
|
||||
sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (sd < 0)
|
||||
error(-1, errno, "Failed to create socket");
|
||||
|
||||
|
@ -120,7 +224,7 @@ int main (int argc, char *argv[])
|
|||
error(-1, errno, "Failed to set socket option: SO_REUSEADDR");
|
||||
|
||||
/* Get interface flags */
|
||||
strncpy(ifr.ifr_name, INTERFACE, IFNAMSIZ);
|
||||
strncpy(ifr.ifr_name, argv[1], IFNAMSIZ);
|
||||
if (ioctl(sd, SIOCGIFFLAGS, &ifr))
|
||||
error(-1, errno, "Failed to get interface flags");
|
||||
|
||||
|
@ -135,6 +239,7 @@ int main (int argc, char *argv[])
|
|||
|
||||
/* Bind socket to interface */
|
||||
memset(&sll, 0, sizeof(sll));
|
||||
sll.sll_family = AF_PACKET;
|
||||
sll.sll_protocol = htons(ETH_P_ALL);
|
||||
sll.sll_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
|
@ -143,15 +248,14 @@ int main (int argc, char *argv[])
|
|||
|
||||
printf("Successfully put interface %s (%u) into promiscuous mode!\n",
|
||||
ifr.ifr_name, ifr.ifr_ifindex);
|
||||
printf("The socket is now bound/listening on interface %s", ifr.ifr_name);
|
||||
printf("The socket is now bound/listening on interface %s\n", ifr.ifr_name);
|
||||
|
||||
while (1) {
|
||||
ssize_t bytes = recv(sd, packet, sizeof(packet), 0);
|
||||
if (bytes == -1)
|
||||
error(-1, errno, "Failed to recv");
|
||||
|
||||
printf("Received %u bytes\n", bytes);
|
||||
parse_packet(packet, sizeof(packet));
|
||||
parse_packet(packet, bytes);
|
||||
}
|
||||
|
||||
close(sd);
|
||||
|
|
Loading…
Add table
Reference in a new issue