#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <ctype.h> #include <stdint.h> #include <sys/types.h>
#include <signal.h> #include <string.h> #include <errno.h>
#include <sys/socket.h> #include <netinet/if_ether.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/udp.h> #include <netinet/tcp.h>
#include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h>
#define SNIF_BUFFER_SIZE 8192
struct recv_packet { struct ether_header *ethdr; /* IEEE802.3 Ethernet header */ struct iphdr *iphdr; /* IP packet header */ struct udphdr *udphdr; /* UDP packet header */ struct tcphdr *tcphdr; /* TCP packet header */ uint8_t *data; /* pointer to data */ uint32_t len; /* data length */ };
/** * print ip packet information */ static void print_eth_header(struct ether_header *etp); static void print_ip_header(struct iphdr *ip); static void print_udp_header(struct udphdr *up); static void print_tcp_header(struct tcphdr *up); static void print_data(uint8_t *p, uint32_t len); static int is_filter(struct recv_packet *rcv);
/** * CTRL + C for exit */ static int isc; static void exit_while(int signo) { isc = 0; }
int main(int argc, char **argv) { int sd, rlen; unsigned char buf[SNIF_BUFFER_SIZE], *p, *pe; struct ifreq ethreq; struct recv_packet rcv;
/* Ctrl+C */ signal(SIGINT, exit_while);
if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0) { fprintf(stderr, "socket create error: %s\n", strerror(errno)); goto err_1; }
strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); ioctl(sd, SIOCGIFFLAGS, ðreq); ethreq.ifr_flags |= IFF_PROMISC; ioctl(sd, SIOCSIFFLAGS, ðreq);
p = buf; rcv.ethdr = (struct ether_header *)p; p += sizeof(struct ether_header);
rcv.iphdr = (struct iphdr *)p; p += sizeof(struct iphdr);
rcv.udphdr = (struct udphdr *)p; rcv.tcphdr = (struct tcphdr *)p;
isc = 1; while (isc) { rlen = recvfrom(sd, buf, SNIF_BUFFER_SIZE, 0, NULL, NULL); if (rlen < 42) { fprintf(stderr, "Recv incomplete header information. \n"); continue; } /* pointer to data end */ pe = buf + rlen; if (is_filter(&rcv) == 1) continue;
print_eth_header(rcv.ethdr); print_ip_header(rcv.iphdr); switch (rcv.iphdr->protocol) { case IPPROTO_UDP: print_udp_header(rcv.udphdr); rcv.data = (uint8_t *)rcv.udphdr + sizeof(struct udphdr); break;
case IPPROTO_TCP: print_tcp_header(rcv.tcphdr); rcv.data = (uint8_t *)rcv.tcphdr + sizeof(struct tcphdr); break; }
rcv.len = pe - rcv.data; print_data(rcv.data, rcv.len);
printf("\n"); }
close(sd);
return (0);
err_1: return (-1); }
static int is_filter(struct recv_packet *rcv) { uint32_t saddr, daddr; #if 0 uint32_t spip; #endif
saddr = ntohl(rcv->iphdr->saddr); daddr = ntohl(rcv->iphdr->daddr);
#if 0 /* set your sniffer IP */ spip = ntohl(inet_addr("192.168.1.84")); #endif
/* filter the loopback packet */ if (saddr == INADDR_LOOPBACK || daddr == INADDR_LOOPBACK) return (1);
#if 0 if (saddr == spip || daddr == spip) return (0); else return (1); #endif
return (0); }
/** * IEEE 802.3 */ static void print_eth_header(struct ether_header *etp) { #define _XFF(t) ((t)&0xFF) #define SNIF_ADDR_MAC(p) \ _XFF((p)[0]),_XFF((p)[1]),_XFF((p)[2]),_XFF((p)[3]),_XFF((p)[4]),_XFF((p)[5])
/* dest mac addr [6] | src mac addr [6] | type [2] * | ip data packet */ printf("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X ==> %.2X:%.2X:%.2X:%.2X:%.2X:%.2X " , SNIF_ADDR_MAC(etp->ether_shost) , SNIF_ADDR_MAC(etp->ether_dhost));
printf("type."); switch (ntohs(etp->ether_type)) { case ETHERTYPE_PUP: printf("Xerox PUP "); break; case ETHERTYPE_IP: printf("IP "); break; case ETHERTYPE_ARP: printf("ARP "); break; case ETHERTYPE_REVARP: printf("RARP "); break; default: printf("Unkown type "); break; }
printf("\n"); }
/** * IP data packet header */ static void print_ip_header(struct iphdr *ip) { struct in_addr saddr, daddr; char sip[24], dip[24];
/* ver 4bit | header length 4bits | TOS 8bits | total length 16 bits * flags identification 16bits | flags 3bits | offset 13bits * TTL 8 bits | protocol type 8bits | checksum 16bits * src ip address 32bits * dest ip address 32bits * options values * * tcp/udp data packet */
saddr.s_addr = ip->saddr; strcpy(sip, inet_ntoa(saddr));
daddr.s_addr = ip->daddr; strcpy(dip, inet_ntoa(daddr));
printf("IP %s ==> %s \n", sip, dip); printf("IP Packet: ver.%d header-length.%d TOS.%04X total-len.%d TTL.%d \n" "id.%d offset.%d checksum.%d " , ip->version, ip->ihl, ip->tos, ntohs(ip->tot_len), ip->ttl , ntohs(ip->id), ntohs(ip->frag_off), ntohs(ip->check) );
printf("protocol."); switch (ip->protocol) { case IPPROTO_ICMP: printf("ICMP "); break; case IPPROTO_IGMP: printf("IGMP "); break; case IPPROTO_IPIP: printf("IPIP "); break; case IPPROTO_RAW: printf("RAW "); break;
case IPPROTO_TCP: printf("TCP "); break; case IPPROTO_UDP: printf("UDP "); break; default: printf("Unkown protocol type.%d ", ip->protocol); }
printf("\n"); }
/** * UDP data packet header */ static void print_udp_header(struct udphdr *up) { printf("UDP src-port.%d dest-port.%d len.%d checksum.%d " , ntohs(up->source), ntohs(up->dest) , ntohs(up->len), ntohs(up->check));
printf("\n"); }
/** * TCP data packet header */ static void print_tcp_header(struct tcphdr *tp) { printf("TCP src-port.%d dest-port.%d seq.%u ack_seq.%u \n" "windows.%d checksum.%d pointer.%d " , ntohs(tp->source), ntohs(tp->dest) , ntohl(tp->seq), ntohl(tp->ack_seq) , ntohs(tp->window), ntohs(tp->check), ntohs(tp->urg_ptr));
if (tp->syn) printf("syn "); if (tp->rst) printf("rst "); if (tp->ack) printf("ack "); if (tp->psh) printf("psh "); if (tp->fin) printf("fin "); if (tp->urg) printf("urg ");
printf("\n"); }
/** * dump data information */ static void print_data(uint8_t *p, uint32_t len) { int i, nlen, j; int flg, ll; char cch[62];
printf("data.%p data-len.%d \n", p, len); nlen = ll = 20;
for (i = j = 0; i < len; i++, j++) { printf("%02X", p[i]); if ((i+1) % 4 == 0) { flg = 1; printf(" "); } else flg = 0;
cch[j] = (isprint(p[i])) ? p[i] : '.';
if (j >= nlen && flg == 1) { ll = j;
cch[j+1] = '\0'; printf(" %s\n", cch); j = -1; } }
cch[j] = '\0'; for (; j <= ll; j++) { printf(" "); if ((j+1) % 4 == 0) printf(" "); }
printf(" %s\n", cch); }
|