[완료]패킷 캡쳐후 패킵 복사 문제

indeok84의 이미지

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define MAX_NUM 3
#define SNAP_LEN
#define TIMEOUT 100
#define PROMISCUOUS 1
#define NONPROMISCUOUS 0
#define PACKET_ARRAY_SIZE 10000

int pkt_cnt=0;

struct packetBox{
u_int pkt_len;
u_char *pkt;
};

struct packetBox pb[10000];

void callback(u_char *, const struct pcap_pkthdr *, const u_char *);
void packetContainer(void);

int main(){
char *dev;
char *net;
char *mask;

char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 netp,maskp;
//struct pcap_pkthdr hdr;
struct in_addr net_addr,mask_addr;
//struct ether_header *eptr;
//const u_char *packet;
pcap_t *pd;
pcap_if_t *tmp, *alldev;
int ret,i;

pcap_findalldevs(&alldev,errbuf);

for(tmp = alldev,i=0; tmp ; tmp=tmp->next){
printf("%d. %s",++i,tmp->name);
if(tmp->description)
printf("(%s)\n",tmp->description);
else
printf("No description\n");
}
if(!i){
printf("No Devices\n");
return -1;
}
printf("Choose one of the lists : ");
scanf("%d",&ret);

for(tmp = alldev,i=0;inext,i++);

/*

if((dev = pcap_lookupdev(errbuf)) == NULL){
printf("%s\n",errbuf);
exit(1);
}
strcpy(dev,"wlan0");
*/
dev = tmp->name;
if((ret = pcap_lookupnet(dev,&netp,&maskp,errbuf)) == -1){
printf("%s\n",errbuf);
exit(1);
}
printf("Device : %s\n",dev);
net_addr.s_addr = netp;
mask_addr.s_addr = maskp;
net = inet_ntoa(net_addr);
printf("Net : %s\n",net);
mask = inet_ntoa(mask_addr);
printf("Mask : %s\n",mask);

pd = pcap_open_live(dev,1024,PROMISCUOUS,100,errbuf);
pcap_loop(pd,MAX_NUM,callback,0);

packetContainer();

pcap_close(pd);

return 0;
}

void packetContainer(){
int len,l_cnt;
for(l_cnt=0; l_cnt < pkt_cnt;l_cnt++){
printf("l_cnt : %d\n",l_cnt);
for(len=0;len < pb[l_cnt].pkt_len ; ){
//printf("(len:%d)",len);
printf("%02x ",*(pb[l_cnt].pkt++));
if( !(++len%16))printf("\n");
}printf("\n");
}

}

void callback(u_char *usr, const struct pcap_pkthdr *h,const u_char *packet){
int len=0;
struct ether_header *ep;
u_short ether_type;
struct ip *iph;
static int cnt=0;

printf("\nPACKET NO.%d\t",++cnt);

ep = (struct ether_header *)packet;
packet += sizeof(struct ether_header);

ether_type = ntohs(ep->ether_type);


if(ether_type == ETHERTYPE_IP){
iph = (struct ip*)packet;
printf("%s ->",inet_ntoa(iph->ip_src));
printf("%s\n",inet_ntoa(iph->ip_dst));
printf("IP packet ");
if(iph->ip_p == IPPROTO_TCP){
printf("TCP\n");

}
else if(iph->ip_p == IPPROTO_UDP){
printf("UDP\n");
}
else if(iph->ip_p == IPPROTO_ICMP){
printf("IP_ICMP\n");
}
pb[pkt_cnt].pkt_len = h->len;
pb[pkt_cnt].pkt = (u_char*)malloc(sizeof(packet));
printf("size of Packet:%d\n",sizeof(packet));
//strcpy(pb[pkt_cnt].pkt,packet);
memcpy(pb[pkt_cnt].pkt,packet,strlen((char*)packet));


/* while(len < h->len){
printf("%02x ",*(pb[pkt_cnt].pkt++));
if( ++len%16 == 0 )printf("\n");
}printf("\n");*/
pkt_cnt++;
printf("pkt_cnt:%d\n",pkt_cnt);
while(len < h->len){
printf("%02x ",*(packet++));
if( (++len %16) == 0)
printf("\n");
}
printf("\n");
}
else
printf("Non IP packet\n");

}

libpcap를 이용해 패킷분석하는 프로그램을 만들어 보려고 합니다.
QT를 이용해 비쥬얼하게 하려고 하는데요.
와이어샤크나 이더리얼처럼 세개의 레이어로 나뉘어 맨 상단의 패킷 열을 클릭하면 맨 아래 레이어에 패킷 정보를 보여주려고 합니다.

callback함수는 한번 호출되서 죽기때문에 패킷정보를 저장해야될것 같아서 상단에 정말 간단한 구조체를 두고 패킷을 복사하려고 합니다.
그런데 packet 크기는 복사가 되는데 내용물은 쓸데없는 이상한값이 자꾸 들어가네요;;;
왜 그런지 아시는 분 있나요;;;;
strcpy도 해봤고 memcpy도 해봤는데 안되네요;;;;;
답변 주시면 정말 감사하겠습니다!!!!!!!!!

indeok84의 이미지

참고로 저 소스는 http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/libpcap%C0%BB_%C0%CC%BF%EB%C7%D1_%C7%C1%B7%CE%B1%D7%B7%A1%B9%D6 를 비롯한 여러 예제 소스를 보고 만든 테스트 프로그램입니다. -

JuEUS-U의 이미지

pb[pkt_cnt].pkt = (u_char*)malloc(sizeof(packet));
printf("size of Packet:%d\n",sizeof(packet));

여기서 패킷 사이즈가 정녕 sizeof(packet)인지 진지하게 고찰해보시기 바랍니다 '~');;

indeok84의 이미지

여기서 sizeof(packet)은 packet의 사이즈라기보다는 char형의 사이즈죠.
즉 4byte크기로 pb[pkt_cnt].pkt에 메모리를 할당해주는것이죠.

문제는 그 아래에서 수행하려고 하는 패킷의 내용복사입니다.

//strcpy(pb[pkt_cnt].pkt,packet);
memcpy(pb[pkt_cnt].pkt,packet,strlen((char*)packet));

위 두 방식을 모두 사용해보았지만 엉뚱한 패킷내용이 복사가 됩니다.

패킷 내용을 뿌려주는 다른 함수내에서 pb[pkt_cnt].pkt를 참조하여 출력하면
엉뚱한 값이 복사된것을 알 수가 있습니다.
이것에 대한 해결책은 없는건가요?

신근태의 이미지

00126 struct pcap_pkthdr {
00127 struct timeval ts;
00128 bpf_u_int32 caplen;
00129 bpf_u_int32 len;
00130 };

indeok84의 이미지

처음에 무슨 말인지 몰라 헤더파일 뒤져보고, packet 길이와 사이즈 뒤져보면서 수정했습니다 ^^
님 덕분에 알아냈네요 ㅎㅎ

charsyam의 이미지

strlen 으로 패킷의 데이터의 길이를 잴 수 있나요? 아마 헤더에 패킷길이가 따로 있을 것
같은데요. strlen 계열의 함수는 중간에 0 값이 있으면 해당 크기까지만 인식합니다.

패킷이라면 어떤 데이터가 있을지 모르는데, strlen으로 복사하는 건 위험할것 같습니다.

=========================
CharSyam ^^ --- 고운 하루
=========================

=========================
CharSyam ^^ --- 고운 하루
=========================

indeok84의 이미지

네 strlen((char*)packet) 하니 1이 나오더라고요.
정작 진짜 패킷의 길이는 h->caplen 이랑 h->len이 가지고 있는데요

메모리 할당할때 h->len 만큼 할당해주고, 복사할때 또 그만큼 하니 제대로 되네요.
감사합니다 ^^!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.