/*
 * sniff.c: Sniffer che visualizza la struttura dei pacchetti su stdout
 *
 *
 * Copyright (c) 2003, eazy <eazy@ondaquadra.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * *  Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * *  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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS 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.
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/ethernet.h>

#define SNAP 200
#define PROMISC 1
#define TIMEOUT 100
#define ETHADDR_LEN 18
#define VERSION_LEN 7
#define IHL_LEN 7
#define TOTLEN_LEN 31
#define ID_LEN 31
#define FRAGOFF_LEN 25
#define TTL_LEN 15
#define PROTOCOL_LEN 15
#define CHECK_LEN 31
#define SADDR_LEN 63
#define DADDR_LEN 63
#define ETHDADDR_LEN 95
#define ETHSADDR_LEN 95
#define ETHTYPE 31
#define HARDTYPE_LEN 31
#define PROTOTYPE_LEN 31
#define HARDSIZE_LEN 15
#define PROTOSIZE_LEN 15
#define OPCODE_LEN 31
#define SHWADDR_LEN 95
#define SIPADDR_LEN 63
#define THWADDR_LEN 95
#define TIPADDR_LEN 63
#define SPORT_LEN 31
#define DPORT_LEN 31
#define SEQ_LEN 63
#define ACK_LEN 63
#define OFF_LEN 7
#define WIN_LEN 31
#define TCPSUM_LEN 31
#define URP_LEN 31
#define ADDR_LEN 16
#define VALUE_LEN 11

int             ethdr_len;
char            errbuf[PCAP_ERRBUF_SIZE];

void 
err_quit(void)
{
	fprintf(stderr, "%s\n", errbuf);
	exit(0);
}

u_int16_t 
ethtype(const u_char * packet)
{

	return ntohs(((struct ether_header *) packet)->ether_type);

}

void 
print_space(int num)
{

	int             i;

	for (i = 0; i < num; i++)
		printf(" ");

}

void 
print_ethaddr(const struct ether_addr * addr, int field_len)
{

	int             nspace;
	char            addr_to_str[ETHADDR_LEN];

	bzero(addr_to_str, ETHADDR_LEN);

	strncpy(addr_to_str, ether_ntoa(addr), ETHADDR_LEN - 1);
	nspace = (field_len - strlen(addr_to_str)) / 2;
	if ((field_len - strlen(addr_to_str)) % 2)
		printf(" ");
	print_space(nspace);
	printf("%s", addr_to_str);
	print_space(nspace);

}

void 
print_ipaddr(const struct in_addr * addr, int field_len)
{

	int             nspace;
	char            addr_to_str[ADDR_LEN];

	bzero(addr_to_str, ADDR_LEN);

	strncpy(addr_to_str, inet_ntoa(*addr), ADDR_LEN - 1);
	nspace = (field_len - strlen(addr_to_str)) / 2;
	if ((field_len - strlen(addr_to_str)) % 2)
		printf(" ");
	print_space(nspace);
	printf("%s", addr_to_str);
	print_space(nspace);

}

void 
print_field(const u_int32_t value, int field_len)
{

	int             nspace;
	char            value_to_str[VALUE_LEN];

	bzero(value_to_str, VALUE_LEN);

	snprintf(value_to_str, VALUE_LEN - 1, "%u", value);
	nspace = (field_len - strlen(value_to_str)) / 2;
	if ((field_len - strlen(value_to_str)) % 2)
		printf(" ");
	print_space(nspace);
	printf("%s", value_to_str);
	print_space(nspace);

}

void 
printtcp_reserved(void)
{

	printf("           ");

}

void 
printtcp_flags(void)
{

	printf(" | | | | | ");

}

void 
printip_flags(void)
{

	printf("     ");

}

void 
printip_tos(void)
{

	printf("               ");

}

void 
printarp(const u_char * packet)
{

	/*
	
	    0                   1                   2                   3                   4
	    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |         Hardware Type         |         Protocol Type         | Hardware Size | Protocol Size |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |             Opcode            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                                    Sender Ethernet Address                                    |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                       Sender IP Address                       |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                                    Target Ethernet Address                                    |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                       Target IP Address                       |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	
	*/

	struct in_addr  saddr, taddr;
	struct ether_arp *arpptr;

	arpptr = (struct ether_arp *) (packet + ethdr_len);

	memcpy(&saddr.s_addr, arpptr->arp_spa, 4);
	memcpy(&taddr.s_addr, arpptr->arp_tpa, 4);

	printf("    0                   1                   2                   3                   4\n");
	printf("    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |         Hardware Type         |         Protocol Type         | Hardware Size | Protocol Size |\n");

	printf("   |");
	print_field(ntohs(arpptr->ea_hdr.ar_hrd), HARDTYPE_LEN);
	printf("|");
	print_field(ntohs(arpptr->ea_hdr.ar_pro), PROTOTYPE_LEN);
	printf("|");
	print_field(arpptr->ea_hdr.ar_hln, HARDSIZE_LEN);
	printf("|");
	print_field(arpptr->ea_hdr.ar_pln, PROTOSIZE_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |             Opcode            |\n");

	printf("   |");
	print_field(ntohs(arpptr->ea_hdr.ar_op), OPCODE_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                                    Sender Ethernet Address                                    |\n");

	printf("   |");
	print_ethaddr((struct ether_addr *) arpptr->arp_sha, SHWADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                       Sender IP Address                       |\n");

	printf("   |");
	print_ipaddr(&saddr, SIPADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                                    Target Ethernet Address                                    |\n");

	printf("   |");
	print_ethaddr((struct ether_addr *) arpptr->arp_tha, THWADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                       Target IP Address                       |\n");

	printf("   |");
	print_ipaddr(&taddr, TIPADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");

}

void 
printtcp(const u_char * packet)
{

	/*
	    0                   1                   2                   3
	    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |          Source Port          |       Destination Port        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                        Sequence Number                        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                    Acknowledgment Number                      |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Data |           |U|A|P|R|S|F|                               |
	   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
	   |       |           |G|K|H|T|N|N|                               |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |           Checksum            |         Urgent Pointer        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                    Options                    |    Padding    |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                             data                              |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	*/

	struct iphdr   *ipptr;
	struct tcphdr  *tcpptr;

	ipptr = (struct iphdr *) (packet + ethdr_len);
	tcpptr = (struct tcphdr *) (packet + ethdr_len + (ipptr->ihl << 2));

	printf("    0                   1                   2                   3\n");
	printf("    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |          Source Port          |       Destination Port        |\n");

	printf("   |");
	print_field(ntohs(tcpptr->source), SPORT_LEN);
	printf("|");
	print_field(ntohs(tcpptr->dest), DPORT_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                        Sequence Number                        |\n");

	printf("   |");
	print_field(ntohl(tcpptr->seq), SEQ_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                    Acknowledgment Number                      |\n");

	printf("   |");
	print_field(ntohl(tcpptr->ack_seq), ACK_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   | Offset|  Reserved |U|A|P|R|S|F|             Window            |\n");

	printf("   |");
	print_field(tcpptr->doff, OFF_LEN);
	printf("|");
	printtcp_reserved();
	printf("|");
	printtcp_flags();
	printf("|");
	print_field(ntohs(tcpptr->window), WIN_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |           Checksum            |         Urgent Pointer        |\n");

	printf("   |");
	print_field(ntohl(tcpptr->check), TCPSUM_LEN);
	printf("|");
	print_field(ntohl(tcpptr->urg_ptr), URP_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                    Options                    |    Padding    |\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                             data                              |\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");


}

void 
printip(const u_char * packet)
{

	/*
	    0                   1                   2                   3
	    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |Version|  IHL  |Type of Service|          Total Length         |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |         Identification        |Flags|      Fragment Offset    |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Time to Live |    Protocol   |         Header Checksum       |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                         Source Address                        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                      Destination Address                      |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                    Options                    |    Padding    |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	*/

	struct in_addr  saddr, daddr;
	struct iphdr   *ipptr;

	ipptr = (struct iphdr *) (packet + ethdr_len);

	memcpy(&saddr.s_addr, &ipptr->saddr, 4);
	memcpy(&daddr.s_addr, &ipptr->daddr, 4);

	printf("    0                   1                   2                   3\n");
	printf("    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |Version|  IHL  |Type of Service|          Total Length         |\n");

	printf("   |");
	print_field(ipptr->version, VERSION_LEN);
	printf("|");
	print_field(ipptr->ihl, IHL_LEN);
	printf("|");
	printip_tos();
	//da cambiare
		printf("|");
	print_field(ntohs(ipptr->tot_len), TOTLEN_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |         Identification        |Flags|      Fragment Offset    |\n");

	printf("   |");
	print_field(ntohs(ipptr->id), ID_LEN);
	printf("|");
	printip_flags();
	//da cambiare
		printf("|");
	print_field(ntohs(ipptr->frag_off), FRAGOFF_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |  Time to Live |    Protocol   |         Header Checksum       |\n");

	printf("   |");
	print_field(ipptr->ttl, TTL_LEN);
	printf("|");
	print_field(ipptr->protocol, PROTOCOL_LEN);
	//da cambiare
		printf("|");
	print_field(ntohs(ipptr->check), CHECK_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                         Source Address                        |\n");

	printf("   |");
	print_ipaddr(&saddr, SADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                      Destination Address                      |\n");

	printf("   |");
	print_ipaddr(&daddr, DADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                    Options                    |    Padding    |\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");


	/*
          Aggiungere un if che controlli il campo protocol dell'header IP e chiamare
          printtcp() nel caso corrisponda al protocollo TCP, altrimenti stampa un msg
         */
	printtcp(packet);

}

void 
printeth(const u_char * packet)
{

	/*
	    0                   1                   2                   3                   4
	    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                                       Destination Address                                     |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                                         Source Address                                        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |              Type             |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	*/

	struct ether_header *ethptr;

	ethptr = (struct ether_header *) (packet);

	printf("    0                   1                   2                   3                   4\n");
	printf("    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7\n");
	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                                       Destination Address                                     |\n");

	printf("   |");
	print_ethaddr((struct ether_addr *) & (ethptr->ether_dhost), ETHDADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |                                         Source Address                                        |\n");

	printf("   |");
	print_ethaddr((struct ether_addr *) & (ethptr->ether_shost), ETHSADDR_LEN);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
	printf("   |              Type             |\n");

	printf("   |");
	print_field(ntohs(ethptr->ether_type), ETHTYPE);
	printf("|\n");

	printf("   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");

}

void 
callback(u_char * none, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{

	printeth(packet);

	switch (ethtype(packet)) {

	case ETHERTYPE_IP:
		printip(packet);
		break;
	case ETHERTYPE_ARP:
		printarp(packet);
		break;
	case ETHERTYPE_REVARP:
		printarp(packet);
		break;
	default:
		fprintf(stderr, "Protocol not supported\n");
	}

}

int 
main(int argc, char **argv)
{

	char           *dev;
	pcap_t         *ret;

	if (geteuid()) {
		fprintf(stderr, "You need to be root!\n");
		exit(0);
	}
	if ((dev = pcap_lookupdev(errbuf)) == NULL)
		err_quit();

	errbuf[0] = 0;
	if ((ret = pcap_open_live(dev, SNAP, PROMISC, TIMEOUT, errbuf)) == NULL)
		err_quit();

	if (strlen(errbuf))
		fprintf(stderr, "%s\n", errbuf);

	switch (pcap_datalink(ret)) {

	case DLT_EN10MB:
		ethdr_len = 14;
		break;
	default:
		fprintf(stderr, "Datalink not supported\n");
		exit(0);

	}

	pcap_loop(ret, -1, callback, NULL);
	return 0;
}
