#########################################################
#  pcap library Ͽ Ŷ ƺ v0.2 #
#                                                       #
# ۾ : 뱤                                        #
# e-mail : djstop@orgio.net                             #
# homepage : http://myhome.shinbiro.com/~nkm24          #
# tcpdump, libpcap Ҽִ° : ftp.ee.lbl.gov         #
#########################################################

 ý, Ʈ α׷ ̰ Ұ  ̰͵
ϱ  ҽ   ϴ OSԴϴ.
  Ű Ÿ ִٸ ̷ α׷   
 .   ý, Ʈ α׷ ϰ   پⰡ
Ͻ е  ̷ ª ̳   Ҵ  
   ÷ ϴ. ⿡ ϴ   socket ̿
Ʈ α׷  ٸ Դϴ.

 Ʈ α׷ ϱ     ҽ  ֽϴ.
 Ʈ    ߴ  tcpdumpԴϴ.   Ʈ
 Ŷ Ƽ ؽƮ  ؼ ִ α׷..
׷     Ʈ Ŷ Ƽ   ְڱϰ  .

׷ Ŷ   󸶳    ڽϴ.


int main(int argc, char *argv[])
{
	.
	.
	.
	.
	.
	
	opterr = 0;
	
	device = pcap_lookupdev(ebuf);
	if(device == NULL) {
   	perror(ebuf);           
   	exit(1);
   	}
	
	pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf);
	if(pd == NULL) {
   	perror(ebuf);          
   	exit(1);
   	}

	if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	setuid(getuid());
	
	if(pcap_compile(pd, &fcode, filter_rule, 0, netmask) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	if(pcap_setfilter(pd, &fcode) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	fflush(stderr);
	
	printer = lookup_printer(pcap_datalink(pd));
	pcap_userdata = 0;
	
	if(pcap_loop(pd, packetcnt, printer, pcap_userdata) < 0) {
   	perror("pcap_loop error");
   	exit(1);
   	}
	
	pcap_close(pd);
	exit(0);
}

Ʈ  Ŷ   pcap library   Լ ϱ⸸ 
ϸ ˴ϴ. ʴ ?

	device = pcap_lookupdev(ebuf);
	
  ӽ Ʈ ̽  ԼԴϴ. Ŷ 
Ʈ ̽ ؾ ?  ̳  ٺ̽  ȣ 
 ̽  ˴ϴ.  eth0̰...

	pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf)
	
 Լ  ⸦ ִ  ϴ  snaplen Ŷ 
̽ ,  datalink Ŷ ũ⸦ Ͽ ϴ κи
 Ǵ Դϴ.    Ÿ 
ʿ .
PROMISCUOUS 1̸ Ʈ ̽   Ŷ ްڴٴ
ǹԴϴ.  带 ڼϰ ϸ lan  Ŷ broadcastingǸ
ϴ  Ʈ ̽  Ʈ ٸ ȣƮ Ŷ ϴ ϰ
˴ϴ.  ׷, Ʈ ̽ ⺻ ڽ Ŷ
ްԲ Ǿֽϴ. ׷Ƿ ٸ ȣƮ Ŷ  Ǵ Դϴ.
׷ promiscuous ̽ 带 ٲٰ Ǹ  Ŷ ޾Ƶ̰
Ǵ Դϴ. ۸ α׷   带 ϰ ˴ϴ.
 ° ڴ Ŷ ۷ ޵  ٷ ޵Ǵ  ƴ϶
  ð Ѱ  ۰  ä  α׷
޵Ǵ Դϴ. 


	pcap_lookupnet(device, &localnet, &netmask, ebuf)
	
 Ŷ ĸ ̽ Ʈ ּҿ  ũ Ѱݴϴ.

	pcap_compile(pd, &fcode, filter_rule, 0, netmask)	
	
 ͷ꿡   α׷ ϰ Ǵµ 츮 ϴ Ŷ
ͷ ־߸ ϴ Ŷ   ֽϴ.  tcpdump ϴ 
ͷ ⿡ Դϴ.   "tcp port 80" ... ڼ ͷ꿡  
 tcpdump ޴    ֽϴ.

	pcap_setfilter(pd, &fcode)
	
 ռ   α׷ Ŷ ĸ ̽ о̰ ˴ϴ.
̷ Ͽ ϴ Ŷ  غ ϰ ˴ϴ.	

	printer = lookup_printer(pcap_datalink(pd));
	
 Ŷ ĸ ̽ datalink  Ѱ ޾ ̿  
Լ͸ Ҵϰ ˴ϴ.

	pcap_loop(pd, packetcnt, printer, pcap_userdata)
	
   Ŷ Ƽ  Լ  ִ ԼԴϴ.
packetcnt ŭ Ŷ Ƽ    printer ġ Լ 
ϰ ˴ϴ. packetcnt 0 ϸ Ѵ Լ մϴ.

 ڼ  Ѵٸ Ƽ콺   unp(unix network programming)
  26忡 pcap library    ֽϴ.

׷  pcap library ̿  Ʈ ip tcp, udp, icmp Ŷ
Ƽ ؽƮ ʵ庰 ѷִ ҽ  սô.
 ҽ  tcpdump ҽ  밡 α׷  ̸ 
ڼ   ʱ ϰڽϴ.
̿  ƿƼ ִ ɷ ˰ ֽϴ.
 ҽ ... ׷ ּܿ Ҹ  ...

##################################################################################
#include <sys/time.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <pcap/pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

#define	 PROMISCUOUS 1

struct  iphdr  *iph;
struct tcphdr  *tcph;
struct udphdr  *udph;
struct icmp    *icmph;
static	pcap_t *pd;
const unsigned char *packetp;
const unsigned char *snapend;
int sockfd;
int pflag;      // DATA ڷ  .
int rflag;      // DATA   .
int eflag;      // DATALINK layer print option
int cflag;      // Ŷ  ڸŭ ְ Ѵ.
int chcnt;      // ڸ   ī ٿ 
void packet_analysis(unsigned char *, const struct pcap_pkthdr *, 
                    const unsigned char *);

struct printer {
   pcap_handler f;
   int type;
   };
   
/* datalink type  Ҹ Լ 
   ϵ  ü                
     datalink  򰥷
    𸣰ڴ.				*/
static struct printer printers[] = {
   { packet_analysis, DLT_IEEE802 },
   { packet_analysis, DLT_EN10MB  },
   { NULL, 0 },
   };
   
/*  datalink type   Լ ϰ ȴ.
    ̴ pcap_handler Լ   Եȴ. */
static pcap_handler lookup_printer(int type) 
{
	struct printer *p;
    
	for(p=printers; p->f; ++p)
   	if(type == p->type)
	return p->f;
	perror("unknown data link type");
}

/*
 * By default, print the packet out in hex.
 *
 * (BTW, please don't send us patches to print the packet out in ascii)
 */
/* pcap_loop()  Ŷ   ҷ Լ
   pcap_handler  Լ ϰ ֱ ̴ */
void packet_analysis(unsigned char *user, const struct pcap_pkthdr *h, 
                    const unsigned char *p)
{
    	int j, temp, udpdata_offset, is_llchdr = 0, next_line = 0;
	int *isipx;
	unsigned int caplen = h->caplen;
	unsigned int length = h->len;
	struct ether_header *ep;
	unsigned short ether_type;
	unsigned short extracted_ethertype;
	unsigned char *tcpdata, *udpdata,*icmpdata;
	register const unsigned short *sp;
	register unsigned int i;
	register int nshorts;

	packetp = p;
	snapend = p + caplen;
		
	chcnt = 0;
	if(rflag) {
		while(length--) {
	    		printf("%02x ", *(p++));
	    		if( (++chcnt % 16) == 0 ) printf("\n\t");
		}
		fprintf(stdout, "\n");
		return;
	}

	length -= sizeof(struct ether_header);
	caplen -= sizeof(struct ether_header);
	
	ep = (struct ether_header *)p;
	p += sizeof(struct ether_header);
	ether_type = ntohs(ep->ether_type);
	
	printf("\n");
	// lan frame IEEE802ΰ ether_typeʵ尡 ʵ尡 ȴ.
	if(ether_type <= 1500) {
	    ;
	    /*while(length--) {
		if(++is_llchdr <= 3) {
		    fprintf(stdout,"%02x",*p++);
		    continue;
		}
		if(++next_line == 16) {
		    next_line = 0;	
		    printf("\n\t");
		}
		printf("%02x",*p++);
	    }*/
	}

	else 
	{    
	    if(eflag) {
	    	printf("\n\n    =================== Datalink layer ===================\n\t");
	    	for(j=0; j<ETH_ALEN; j++){ 
			printf("%X", ep->ether_dhost[j]); 
			if(j !=	5) printf(":");
	    	}
	    	printf("  ------> ");
	    	for(j=0; j<ETH_ALEN; j++) {
			printf("%X", ep->ether_shost[j]);
	        	if(j != 5) printf(":");
	    	}	
	    	printf("\n\tether_type -> %x\n", ntohs(ep->ether_type));
	    }

	    extracted_ethertype = 0;
	    iph = (struct iphdr *) p;
	    sp = (unsigned short *)p;
	    nshorts = (unsigned int) length / sizeof(unsigned short);
	    i = 0;
	    if (ntohs(ep->ether_type) == ETHERTYPE_IP) {	// ip Ŷΰ?
		// packet capturing  ȭ鿡 ϴ κ
	        printf("\n\n    ===================    IP HEADER   ===================\n");
		printf("\t%s -----> ",   inet_ntoa(iph->saddr));
		printf("%s\n", inet_ntoa(iph->daddr));
		printf("\tVersion:         %d\n", iph->version);
		printf("\tHerder Length:   %d\n", iph->ihl);
		printf("\tService:         %#x\n",iph->tos);
		printf("\tTotal Length:    %d\n", ntohs(iph->tot_len)); 
		printf("\tIdentification : %d\n", ntohs(iph->id));
		printf("\tFragment Offset: %d\n", ntohs(iph->frag_off)); 
		printf("\tTime to Live:    %d\n", iph->ttl);
		printf("\tChecksum:        %d\n", ntohs(iph->check));
	

		/* packet ipκ   20bytes ǳʶ 
   		tcp header  ȴ.                            */
		if(iph->protocol == IPPROTO_TCP) {
		        tcph = (struct tcphdr *) (p + iph->ihl * 4);
		        tcpdata = (unsigned char *) (p + iph->ihl*4) + 20;
	                printf("\n\n    ===================   TCP HEADER   ===================\n");
	       	        printf("\tSource Port:              %d\n", ntohs(tcph->source));
		        printf("\tDestination Port:         %d\n", ntohs(tcph->dest));
			printf("\tSequence Number:          %d\n", ntohl(tcph->seq));
			printf("\tAcknowledgement Number:   %d\n", ntohl(tcph->ack_seq));
			printf("\tData Offset:              %d\n", tcph->doff);
			printf("\tWindow:                   %d\n", ntohs(tcph->window));
			printf("\tURG:%d ACK:%d PSH:%d RST:%d SYN:%d FIN:%d\n", 
				tcph->urg, tcph->ack, tcph->psh, tcph->rst, 
				tcph->syn, tcph->fin, ntohs(tcph->check), 
				ntohs(tcph->urg_ptr));
			printf("\n    ===================   TCP DATA(HEXA)  =================\n\t"); 
			chcnt = 0;
			for(temp = (iph->ihl * 4) + (tcph->doff * 4); 
	    		temp <= ntohs(iph->tot_len) - 1; temp++) {
	   		
			    printf("%02x ", *(tcpdata++));
			    if( (++chcnt % 16) == 0 ) printf("\n\t");
			}
			if (pflag) {
			    
			    printf("\n===================   TCP DATA(CHAR)  =================\n"); 
		            tcpdata = (unsigned char *) (p + iph->ihl*4) + 20;
			    for(temp = (iph->ihl * 4) + (tcph->doff * 4); 
	    		    temp <= ntohs(iph->tot_len) - 1; temp++)
	   		        printf("%c", *(tcpdata++));
			}
			
			printf("\n\t\t<<<<< End of Data >>>>>\n");
	        }
		else if(iph->protocol == IPPROTO_UDP) {
	    	    udph = (struct udphdr *) (p + iph->ihl * 4);
		    udpdata = (unsigned char *) (p + iph->ihl*4) + 8;
		    printf("\n   ==================== UDP HEADER =====================\n");
		    printf("\tSource Port :      %d\n",ntohs(udph->source));
		    printf("\tDestination Port : %d\n", ntohs(udph->dest));
		    printf("\tLength :           %d\n", ntohs(udph->len));
	   	    printf("\tChecksum :         %x\n", ntohs(udph->check));
	            printf("\n    ===================  UDP DATA(HEXA)  ================\n\t");	 
		    //p = (unsigned char *) sp;
		    //udpdata_offset = (iph->ihl*4)+8;
		    chcnt = 0;
		    for(temp = (iph->ihl*4)+8; temp<=ntohs(iph->tot_len) -1; temp++) {
		       printf("%02x ", *(udpdata++));
		       if( (++chcnt % 16) == 0) printf("\n\t"); 
		    }

		    udpdata = (unsigned char *) (p + iph->ihl*4) + 8;
		    if(pflag) {
			
	                printf("\n===================  UDP DATA(CHAR)  ================\n");	 
		        for(temp = (iph->ihl*4)+8; temp<=ntohs(iph->tot_len) -1; temp++) 
		           printf("%c", *(udpdata++));
		    }
		    
		    printf("\n\t\t<<<<< End of Data >>>>>\n");
		}	  
		else if(iph->protocol == IPPROTO_ICMP) {
		        icmph = (struct icmp *) (p + iph->ihl * 4);
		        icmpdata = (unsigned char *) (p + iph->ihl*4) + 8;
	                printf("\n\n    ===================   ICMP HEADER   ===================\n");
	       	        printf("\tType :                    %d\n", icmph->icmp_type);
		        printf("\tCode :                    %d\n", icmph->icmp_code);
			printf("\tChecksum :                %02x\n", icmph->icmp_cksum);
			printf("\tID :                      %d\n", icmph->icmp_id);
			printf("\tSeq :                     %d\n", icmph->icmp_seq);
			
			printf("\n    ===================   ICMP DATA(HEXA)  =================\n\t"); 
			chcnt = 0;
			for(temp = (iph->ihl * 4) + 8;
	    		temp <= ntohs(iph->tot_len) - 1; temp++) {
	   		
			    printf("%02x ", *(icmpdata++));
			    if( (++chcnt % 16) == 0 ) printf("\n\t");
			}
			
			printf("\n\t\t<<<<< End of Data >>>>>\n");
	        }
	    }	
	}
}

void sig_int(int sig)
{
    printf("Bye!!\n");
    pcap_close(pd);
    close(sockfd);
    exit(0);
}

void usage(void)
{
    fprintf(stdout," Usage : pa filter_rule [-pch]\n");
    fprintf(stdout,"         -p  :  Ÿ ڷ ´\n");
    fprintf(stdout,"         -c  :  ־ ڸŭ Ŷ Ѵ\n");
    fprintf(stdout,"         -h  :  \n");
}

int main(int argc, char *argv[])
{
	struct	bpf_program fcode;
	pcap_handler printer;
	char	*device, *filter_rule;
	char	ebuf[PCAP_ERRBUF_SIZE];
	int	c, i, snaplen = 68, size, packetcnt;
	//unsigned long	localnet, netmask;
	bpf_u_int32 myself, localnet, netmask;
	unsigned char	*pcap_userdata;
	char	*cp;
	
	filter_rule = argv[1];
	
	signal(SIGINT,sig_int);
	
	opterr = 0;
	
	if(argc-1 < 1) {
	    usage(); 
	    exit(1);
	}
	
	while( (c = getopt(argc, argv,"c:pher")) != -1) {
	    switch(c) {
	    	case 'p' : 
			        pflag = 1; break;
	    	case 'c' : 
			        cflag = 1; 
				packetcnt = atoi(optarg);
				if(packetcnt <= 0) {
				    fprintf(stderr,"invalid pacet number %s",optarg);
				    exit(1);
				}
				break;
		case 'e' :      
				eflag = 1;
				break;		
		case 'r' :      
				rflag = 1;
				break;		
	    	case 'h' :
				usage();
				exit(1);
	    }
	}	    
	
	device = pcap_lookupdev(ebuf);
	if(device == NULL) {
   	perror(ebuf);           
   	exit(1);
   	}
	
	pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf);
	if(pd == NULL) {
   	perror(ebuf);          
   	exit(1);
   	}
	
	i = pcap_snapshot(pd);
	if(snaplen < i) {
   	perror(ebuf);                            
  	exit(1);
   	}
	
	if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	setuid(getuid());
	
	if(pcap_compile(pd, &fcode, filter_rule, 0, netmask) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	if(pcap_setfilter(pd, &fcode) < 0) {
   	perror(ebuf);
   	exit(1);
   	}
	
	fflush(stderr);
	
	printer = lookup_printer(pcap_datalink(pd));
	pcap_userdata = 0;
	
	if(pcap_loop(pd, packetcnt, printer, pcap_userdata) < 0) {
   	perror("pcap_loop error");
   	exit(1);
   	}
	
	pcap_close(pd);
	exit(0);
}


##################################################################################

Ե  ŵ β ҽ ÷ҽϴ. 
   Ȩ ÷ ֽϴ.
 κ̳ 輱   ҽ ļ   ƿƼ   
   . ׷ 츮  Ű   ִ  
 α׷ ϴ  ...^^

 ҽ ؼ ϱ ؼ pcap library ־ ϸ 
Ƹ   /usr/lib/libpcap.a ȭϷ  Դϴ.
Ͻ bpf.h ٴ ޼    ȭ ãƼ   ָ
˴ϴ.  丮  ָ ǰ...

׸ tcp/ip õ  䱸Ǵ ҽ̹Ƿ å  ø鼭 α׷
Ͻô  Ͻ Դϴ.  ȴ翡  "TCP/IP " ̶ å
ֽϴ. ̷ 뵵   α׷ ϴµ   ˴ϴ.

⼭ ܼ Ŷ Ƽ ִ  ġ    ø
Ŷ   ٸ ȣƮ   ֽϴ.
pcap_library ҽ ļ    ְ raw socket ̿  
ֽϴ.   pcap_library pcap_read() Լ ణ ļ ipx packet
 Ÿ ũ   Լ µ...  Ǵ...
raw socket ̿ϴ ǥ δ ping α׷   ֽϴ.
unp ø ҽ  ִµ ̸  мϽø icmp ƴ϶ ip,tcp,udp
Ŷ     ֽϴ.

 ȭϵ 캸  ݺ  ü ִµ ̸
ϸ ˴ϴ.  ҽ include κ ȭϵԴϴ. 
 ٸ ݵ Ŀ °   شٸ ...
̷Ը ȴٸ   ǰ ִ DOS   ذ   ֽϴ.
û Ŷ   LOOP  ...
   ̷  ϱ    İ  ġǾ
ִ İ  α׷  ʿϰ...
 Ⱑ õ   . ư ҽ ð Ʈ α׷ Ͻôµ
̳  Ǽ մϴ.