#include <sys/time.h>
#include <netinet/in.h>
#include <net/ethernet.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>
#include <pcap/pcap.h>
#define PROMISCUOUS 1
#define NONPROMISCUOUS 0
#define TCPHEADERSIZE 6*4
// IP 헤더 구조체
struct ip *iph;
// TCP 헤더 구조체
struct tcphdr *tcph;
// 패킷을 받아들일경우 이 함수를 호출한다.
// packet 가 받아들인 패킷이다.
void callback(u_char *useless, const struct pcap_pkthdr *pkthdr,
const u_char *packet)
{
struct ether_header *ep;
unsigned short ether_type;
char *uname = NULL;
char *pass = NULL;
char buf[80];
// 이더넷 헤더를 가져온다.
ep = (struct ether_header *)packet;
// IP 헤더를 가져오기 위해서
// 이더넷 헤더 크기만큼 offset 한다.
packet += sizeof(struct ether_header);
ether_type = ntohs(ep->ether_type);
// Network Layer 의 Protocol 타입을 알아낸다.
// 만약 IP 프로토콜을 사용한다면
// IP 정보를 얻어온다.
if (ether_type == ETHERTYPE_IP)
{
iph = (struct ip *)packet;
if (iph->ip_p == IPPROTO_TCP)
{
tcph = (struct tcp *)(packet + iph->ip_hl * 4);
}
memset(buf, 0x00, 80);
// 유저 데이타를 얻어오기 위해서
// IP, TCP, Ethernet 헤더 크기만큼 offset 한다.
packet += (iph->ip_hl * 4)+TCPHEADERSIZE+(sizeof(struct ether_header));
// 패킷에 ID와 password 관련 문자열을 포함하는지 확인한다.
/* if ( ((uname = strstr(packet, "uname=")) != NULL)// 패킷받은것 중에 "안의 내용(uname=) "중에 포함되있는 문자가 있으면 포인터를 리턴
&& ((pass = strstr(packet, "&pass=")) != NULL))
{
// 헤더 정보를 출력한후
printf("HEADER INFO\n");
printf("Src Address : %s\n", inet_ntoa(iph->ip_src));
printf("Dst Address : %s\n", inet_ntoa(iph->ip_dst));
printf("Src Port : %d\n" , ntohs(tcph->source));
printf("Dst Port : %d\n" , ntohs(tcph->dest));
// 문자열에서 필요한 정보 즉 ID와 Password 만을
// 추출해 낸다.
strncpy(buf, uname+6, strstr(uname, "&") - (uname + 6));
printf("Uname : <%s>\n", buf);
memset(buf, 0x00, 80);
strncpy(buf, pass+6, strstr(pass+6, "&") - (pass + 6));
printf("Pass : <%s>\n", buf);
printf("======================\n\n");
}*/
}
}
int main(int argc, char **argv)
{
char *dev;
char *net;
char *mask;
bpf_u_int32 netp;
bpf_u_int32 maskp;
char errbuf[PCAP_ERRBUF_SIZE];
int ret;
struct pcap_pkthdr hdr;
struct in_addr net_addr, mask_addr;
struct bpf_program fp;
pcap_t *pcd; // packet capture descriptor
// 디바이스 이름을 얻어온다.
dev = pcap_lookupdev(errbuf);
if (dev == NULL)
{
printf("%s\n", errbuf);
exit(1);
}
printf("DEV : %s\n", dev);
// 디바이스에 대한 네트웍 정보를 얻어온다.
ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
if (ret == -1)
{
printf("%s\n", errbuf);
exit(1);
}
// 네트웍 정보를 사람이 보기 쉽도록
// 변환한다음 출력한다.
net_addr.s_addr = netp;
net = inet_ntoa(net_addr);
printf("NET : %s\n", net);
mask_addr.s_addr = maskp;
mask = inet_ntoa(mask_addr);
printf("MSK : %s\n", mask);
printf("=======================\n");
// 디바이스에 대한 packet capture descriptor
// 를 얻어온다.
pcd = pcap_open_live(dev, BUFSIZ, NONPROMISCUOUS, -1, errbuf);
if (pcd == NULL)
{
printf("%s\n", errbuf);
exit(1);
}
// 컴파일 옵션을 준다.
if (pcap_compile(pcd, &fp, argv[2], 0, netp) == -1)// argv[2]>>>port 80
{
printf("compile error\n");
exit(1);
}
// 컴파일 옵션대로 필터룰을 세팅한다.
if (pcap_setfilter(pcd, &fp) == -1)
{
printf("setfilter error\n");
exit(0);
}
// 지정된 횟수만큼 패킷캡쳐를 한다.
// pcap_setfilter 을 통과한 패킷에 대해서
// callback 함수를 호출한다.
pcap_loop(pcd, atoi(argv[1]), callback, NULL);
}// atoi(argv[1]콜백함수 몇번 실행할 것인지 결정