On Wednesday 04 June 2003 11:15 am, Aaron B. Iba wrote:
> It would be great if I could a copy of this file (sniffer.c), and I am
See attached source file.
/* sniffer.c
Copyright (c) 2002 Tim Carstens
2002-01-07
Demonstration of using libpcap
timcarst -at- yahoo -dot- com
gcc -o sniffer sniffer.c -lpcap
Distributed under these terms:
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. The name "Tim Carstens" may not be used to endorse or promote
* products derived from this software without prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define _BSD_SOURCE 1
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ip_hl:4, /* header length */
ip_v:4; /* version */
#if BYTE_ORDER == BIG_ENDIAN
u_int ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
#endif /* not _IP_VHL */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
/* TCP header */
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */
#endif
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
static int count = 1; /* Just a counter of how many packets we've had */
/* Define pointers for packet's attributes */
const struct sniff_ethernet *ethernet; /* The ethernet header */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
/* And define the size of the structures we're using */
int size_ethernet = sizeof(struct sniff_ethernet);
int size_ip = sizeof(struct sniff_ip);
int size_tcp = sizeof(struct sniff_tcp);
/* -- Define our packet's attributes -- */
ethernet = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(packet + size_ethernet);
tcp = (struct sniff_tcp*)(packet + size_ethernet + size_ip);
payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp);
printf("Packet number %d has just been sniffed\n", count);
printf("\tFrom: %s:%d\n", inet_ntoa(ip->ip_src), ntohs(tcp->th_sport));
printf("\tTo: %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(tcp->th_dport));
printf("\tPayload: %s\n", payload);
count++;
}
int main()
{
char *dev; /* Sniffing devise */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error buffer */
pcap_t *descr; /* Sniff handler */
struct bpf_program fp; /* hold compiled program */
bpf_u_int32 maskp; /* subnet mask */
bpf_u_int32 netp; /* ip */
char filter_app[] = "";
int numOfPackets = 10; /* How many packets to sniff */
/* Set our device */
dev = pcap_lookupdev(errbuf);
pcap_lookupnet(dev, &netp, &maskp, errbuf);
/* Print devise to the user */
printf("Device: [%s]\n", dev);
printf("Num of packets: [%d]\n", numOfPackets);
printf("Filter app: [%s]\n", filter_app);
/* Open the device so we can spy */
descr = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
if (descr == NULL)
{
printf("pcap_open_live(): %s\n", errbuf);
exit(1);
}
/* Apply the rules */
if( pcap_compile(descr, &fp, filter_app, 0, netp) == -1)
{
printf("pcap_compile borqed\n");
exit(1);
}
if (pcap_setfilter(descr, &fp) == -1)
{
printf("pcap_setfilter said 'eat shit'\n");
exit(1);
}
/* Now we can set our callback function */
pcap_loop(descr, numOfPackets, got_packet, NULL);
pcap_close(descr);
printf("Done sniffing\n");
return(0);
}