/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* tcpip720 src/tcpip/usr/samples/tcpip/libpcap/pcap_exIII.c 1.1          */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2000                   */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/*
 *	    NOTICE TO USERS OF THE SOURCE CODE EXAMPLES
 *
 * INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THE SOURCE CODE
 * EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, "AS IS" WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
 * OF THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS,
 * IS WITH YOU.  SHOULD ANY PART OF THE SOURCE CODE EXAMPLES PROVE
 * DEFECTIVE, YOU (AND NOT IBM OR AN AUTHORIZED RISC System/6000* WORKSTATION
 * DEALER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR
 * CORRECTION.
 *
 *  RISC System/6000 is a trademark of International Business Machines
 *  Corporation.
 */

/*
 * Use pcap_open_offline() to open a savefile, containing packet capture data,
 * and use the print_addrs() routine to print the source and destination IP
 * addresses from the packet capture data to stdout.
 */

#include <stdio.h>
#include <pcap.h>

#define IFSZ 16
#define FLTRSZ 120
#define MAXHOSTSZ 256
#define PCAP_SAVEFILE "./pcap_savefile"

int packets = 0;   /* running count of packets read in */

int
usage(char *progname)
{
	printf("Usage: %s <interface> [<savefile name>]\n", basename(progname));
	exit(7);
}


/*
 * Function:	print_addrs()
 *
 * Description: Write source and destination IP addresses from packet data
 *		out to stdout.
 *		For simplification, in this example, we will assume the
 *		following about the captured packet data:
 *			- the addresses are IPv4 addresses
 *			- the data link type is ethernet
 *			- ethernet encapsulation, according to RFC 894, is used.
 *
 * Return:	0 upon success
 *		-1 on failure (if packet data was cut off before IP addresses).
 */
void
print_addrs(u_char *user, const struct pcap_pkthdr *hdr, const u_char *data)
{
	int offset = 26; /* 14 bytes for MAC header +
			  * 12 byte offset into IP header for IP addresses
			  */

	if (hdr->caplen < 30) {
		/* captured data is not long enough to extract IP address */
		fprintf(stderr,
			"Error: not enough captured packet data present to extract IP addresses.\n");
		return;
	}
		
	printf("Packet received from source address %d.%d.%d.%d\n",
		data[offset], data[offset+1], data[offset+2], data[offset+3]);
	if (hdr->caplen >= 34) {
		printf("and destined for %d.%d.%d.%d\n",
			data[offset+4], data[offset+5],
			data[offset+6], data[offset+7]);
	}
	packets++; /* keep a running total of number of packets read in */
}


int
main(int argc, char **argv)
{
	pcap_t *p;		 /* packet capture descriptor */
	char ifname[IFSZ];	 /* interface name (such as "en0") */
	char filename[80];	 /* name of savefile to read packet data from */
	char errbuf[PCAP_ERRBUF_SIZE];	/* buffer to hold error text */
	char prestr[80];	 /* prefix string for errors from pcap_perror */
	int majver = 0, minver = 0;  /* major and minor numbers for the */
				     /* current Pcap library version */

	/*
	 * For this program, the interface name must be passed to it on the
	 * command line. The savefile name may optionally be passed in
	 * as well. If no savefile name is passed in, "./pcap_savefile" is
	 * assumed. If there are no arguments, program has been invoked
	 * incorrectly.
	 */
	if (argc < 2)
		usage(argv[0]);

	if (strlen(argv[1]) > IFSZ) {
		fprintf(stderr, "Invalid interface name.\n");
		exit(1);
	}
	strcpy(ifname, argv[1]);

	/*
	 * If there is a second argument (the name of the savefile), save it in
	 * filename. Otherwise, use the default name.
	 */
	if (argc >= 3)
		strcpy(filename,argv[2]);
	else
		strcpy(filename, PCAP_SAVEFILE);

	/*
	 * Open a file containing packet capture data. This must be called
	 * before processing any of the packet capture data. The file
	 * containing pcaket capture data should have been generated by a
	 * previous call to pcap_open_live().
	 */
	if (!(p = pcap_open_offline(filename, errbuf))) {
		fprintf(stderr,
			"Error in opening savefile, %s, for reading: %s\n",
			filename, errbuf);
		exit(2);
	}

	/*
	 * Call pcap_dispatch() with a count of 0 which will cause
	 * pcap_dispatch() to read and process packets until an error or EOF
	 * occurs. For each packet read from the savefile, the output routine,
	 * print_addrs(), will be called to print the source and destinations
	 * addresses from the IP header in the packet capture data.
	 * NOTE that packet in this case may not be a complete packet. The
	 * amount of data captured per packet is determined by the snaplen
	 * variable which was passed into pcap_open_live() when the savefile
	 * was created.
	 */
	if (pcap_dispatch(p, 0, &print_addrs, (char *)0) < 0) {
		/*
		 * Print out appropriate text, followed by the error message
		 * generated by the packet capture library.
		 */
		sprintf(prestr,"Error reading packets from interface %s",
			ifname);
		pcap_perror(p,prestr);
		exit(4);
	}

	printf("\nPackets read in: %d\n", packets);

	/*
	 * Print out the major and minor version numbers. These are the version
	 * numbers associated with this revision of the packet capture library.
	 * The major and minor version numbers can be used to help determine
	 * what revision of libpcap created the savefile, and, therefore, what
	 * format was used when it was written.
	 */

	if (!(majver = pcap_major_version(p))) {
		fprintf(stderr,
			"Error getting major version number from interface %s",
			ifname);
		exit(5);
	}
	printf("The major version number used to create the savefile was: %d.\n", majver);

	if (!(minver = pcap_minor_version(p))) {
		fprintf(stderr,
			"Error getting minor version number from interface %s",
			ifname);
		exit(6);
	}
	printf("The minor version number used to create the savefile was: %d.\n", minver);

	/*
	 * Close the packet capture device and free the memory used by the
	 * packet capture descriptor.
	 */

	pcap_close(p);
}
