#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.x 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("x", p[i]);
if ((i1) % 4 == 0)
{
flg = 1;
printf(" ");
}
else
flg = 0;
cch[j] = (isprint(p[i])) ? p[i] : '.';
if (j >= nlen && flg == 1)
{
ll = j;
cch[j1] = '\0';
printf(" %s\n", cch);
j = -1;
}
}
cch[j] = '\0';
for (; j <= ll; j)
{
printf(" ");
if ((j1) % 4 == 0) printf(" ");
}
printf(" %s\n", cch);
}
|