Cygwin에서 WinPcap으로 간단한 IP dump utility.
build machine에서 WinPcap이 설치되어 잇어야하고,
WpdPack_4_1_1/WpdPack/Examples-pcap 의 include, lib가 설치되어 잇어야함.
1. Makefile
# Makefile for cygwin gcc
# Nate Lawson <nate@rootlabs.com>
OUTNAME=ipd
CC=gcc
PCAP_PATH = ../lib
CFLAGS = -g -Wall -O -mno-cygwin -I../include
#CFLAGS = -g -Wall -I../include
OBJS = \
wp_util.o \
ipd_main.o
LIBS = -L ${PCAP_PATH} -lwpcap
all: ${OBJS}
${CC} ${CFLAGS} -o ${OUTNAME}.exe ${OBJS} ${LIBS}
clean:
rm -f ${OBJS} ${OUTNAME}.exe
.c.o:
${CC} ${CFLAGS} -c -o $*.o $<
2. wp_util
2.1 wp_util.h
/*-----------------------------------------------------------------------------
wp_util.h
General definition
version : 1.0
Programed by : jakeoh
Date : 18Dec09-18Dec09
Compiler :
Description :
18Dec09 jakeoh utility functions for WinPcap
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include "pcap.h"
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#else
#include <winsock.h>
#endif
/*-----------------------------------------------------------------------------
Predefine
-----------------------------------------------------------------------------*/
#define ROK 1
#define RFAIL -1
/*-----------------------------------------------------------------------------
function prototypes
-----------------------------------------------------------------------------*/
extern int fnGetDeviceAll (void);
extern int fnDevMon (int nNo);
extern void fnPacket_Handler (u_char *pParam, const struct pcap_pkthdr *pstHeader, const u_char *pPkt_data);
extern pcap_t *fnOpenDevice (int nNo);
extern int fnCloseDevice (pcap_t *pHandle);
extern int fnReadPacket (pcap_t *pHandle);
/*----------------------------------------------------------------------------
End of wp_util.h
-----------------------------------------------------------------------------*/
2.2 wp_util.c
/*-----------------------------------------------------------------------------
wp_util.c
Utility functions for WinPcap
18Dec09-18Dec09
18Dec09 jakeoh from ~/WpdPack_4_1_1/WpdPack/Examples-pcap/basic_dump.c
21Dec09 jakeoh fnGetDeviceAll (), fnDevMon (), fnPacket_Handler ()
22Dec09 jakeoh fnOpenDevice (), fnCloseDevice (), fnMon ()
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Include files
-----------------------------------------------------------------------------*/
#include "wp_util.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
fnInet_ntop ()
Date : 22Dec09-22Dec09
Input :
Output :
Description
22Dec09 jakeoh from inet_ntop ()
-----------------------------------------------------------------------------*/
const char *fnInet_ntop
(
int family,
const void *addrptr,
char *strptr,
size_t len
)
{
const u_char *p = (const u_char *) addrptr;
if (family == AF_INET)
{
// char temp[INET_ADDRSTRLEN];
char temp[15+1];
snprintf (temp, sizeof (temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
if (strlen (temp) >= len)
{
// errno = ENOSPC;
return (NULL);
}
strcpy (strptr, temp);
return (strptr);
}
// errno = EAFNOSUPPORT;
return (NULL);
} /* end of fnInet_ntop () */
/* From tcptraceroute, convert a numeric IP address to a string */
#define IPTOSBUFFERS 12
#if 0
/*-----------------------------------------------------------------------------
iptos ()
Date : 21Dec09-21Dec09
Input :
Output :
Description
21Dec09 jakeoh IP address to string
-----------------------------------------------------------------------------*/
char *iptos
(
u_long in
)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *) ∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
_snprintf_s (output[which], sizeof(output[which]), sizeof(output[which]),"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
/*-----------------------------------------------------------------------------
ip6tos ()
Date : 21Dec09-21Dec09
Input :
Output :
Description
21Dec09 jakeoh IPv6 to string
-----------------------------------------------------------------------------*/
char* ip6tos
(
struct sockaddr *sockaddr,
char *address,
int addrlen
)
{
socklen_t sockaddrlen;
#ifdef WIN32
sockaddrlen = sizeof (struct sockaddr_in6);
#else
sockaddrlen = sizeof (struct sockaddr_storage);
#endif
if (getnameinfo (sockaddr,
sockaddrlen,
address,
addrlen,
NULL,
0,
NI_NUMERICHOST) != 0) address = NULL;
return address;
}
#endif
/*-----------------------------------------------------------------------------
fnDebugDump ()
Programed by : jakeoh
Date : 07Jul05-07Jul05
Input : hex dump utility function
Output : success = ROK
error = RFAIL
Description :
02Jul05 jakeoh draft
-----------------------------------------------------------------------------*/
void fnDebugDump
(
unsigned char* pData,
int dwLen
)
{
int nCnt0, nIndex;
char szHex[4];
char szBuff[81];
memset (szBuff, 0x00, sizeof (szBuff));
nIndex = 0;
printf ("Len [%d]\n", dwLen);
for (nCnt0=0; nCnt0 < dwLen; nCnt0++)
{
memset (szHex, 0x00, sizeof (szHex));
sprintf (szHex, "%02x ", pData[nCnt0]);
strcat (szBuff, szHex);
nIndex++;
if (nIndex%16 == 0)
{
printf ("%s\n", szBuff);
memset (szBuff, 0x00, sizeof (szBuff));
}
}
if (strlen (szBuff) > 0)
{
printf ("%s\n", szBuff);
}
} /* end of fnDebugDump () */
/*-----------------------------------------------------------------------------
fnIfPrint ()
Date : 21Dec09-21Dec09
Input : pcap_if_t
Output : Information in pcap_if_t
Description
21Dec09 jakeoh Print out to interface info from pcap_if_t
-----------------------------------------------------------------------------*/
void fnIfPrint
(
pcap_if_t *pIf
)
{
char szTmp[128];
pcap_addr_t *pAddr;
/* Name */
if (pIf->name)
printf ("\tNAME [%s]\n", pIf->name);
/* Description */
if (pIf->description)
printf ("\tDESCRIPTION [%s]\n", pIf->description);
/* Loopback Address */
printf ("\tLOOPBACK FLAG [%s]\n", (pIf->flags & PCAP_IF_LOOPBACK)?"YES":"NO");
/* IP address */
for (pAddr=pIf->addresses; pAddr ; pAddr=pAddr->next)
{
// printf ("\tADDRESS FAMILY [%d]\n", pAddr->addr->sa_family);
switch (pAddr->addr->sa_family)
{
case AF_INET:
printf ("\tAddress Family [AF_INET]\n");
#if 1
if (pAddr->addr)
printf ("\tADDRESS [%s]\n", fnInet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->addr)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->netmask)
printf ("\tNETMASK [%s]\n", fnInet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->netmask)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->broadaddr)
printf ("\tBROADCAST [%s]\n", fnInet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->broadaddr)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->dstaddr)
printf ("\tDEST ADDRESS [%s]\n", fnInet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->dstaddr)->sin_addr, szTmp, sizeof (szTmp)));
#else
if (pAddr->addr)
printf ("\tADDRESS [%s]\n", inet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->addr)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->netmask)
printf ("\tNETMASK [%s]\n", inet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->netmask)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->broadaddr)
printf ("\tBROADCAST [%s]\n", inet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->broadaddr)->sin_addr, szTmp, sizeof (szTmp)));
if (pAddr->dstaddr)
printf ("\tDEST ADDRESS [%s]\n", inet_ntop (AF_INET, &((struct sockaddr_in *)pAddr->dstaddr)->sin_addr, szTmp, sizeof (szTmp)));
#endif
break;
#if 0
case AF_INET6:
char szIPv6[128];
printf ("\tAddress Family [AF_INET6]\n");
if (pAddr->addr)
printf ("\tADDRESS [%s]\n", ip6tos (pAddr->addr, szIPv6, sizeof (szIPv6)));
break;
#endif
default:
printf ("\tAddress Family [Unknwon]\n");
break;
}
}
printf ("\n");
} /* end of fnIfPrint */
/*-----------------------------------------------------------------------------
fnGetDeviceAll ()
Date : 18Dec09-18Dec09
Input : void
Output : Number of Device
Description
18Dec09 jakeoh Get all device and print out
-----------------------------------------------------------------------------*/
int fnGetDeviceAll
(
void
)
{
int nCnt=0;
pcap_if_t *pAlldevs;
pcap_if_t *pIft;
char szErrBuf[PCAP_ERRBUF_SIZE];
/* Retrieve the device list */
#if 1
if (pcap_findalldevs (&pAlldevs, szErrBuf) == -1)
{
printf ("[%s] pcap_findalldevs () FAILED [%s]\n", __func__, szErrBuf);
return RFAIL;
}
#else
if (pcap_findalldevs_ex ("rpcap://", NULL, &pAlldevs, szErrBuf) == -1)
{
printf ("[%s] pcap_findalldevs () FAILED [%s]\n", __func__, szErrBuf);
return RFAIL;
}
#endif
else
printf ("[%s] Device List [0x%08lx]\n", __func__, (unsigned long) pAlldevs);
/* List out */
for (pIft=pAlldevs; pIft; pIft=pIft->next)
{
printf ("\t[%d]\n", nCnt);
fnIfPrint (pIft);
nCnt++;
}
/* Free the device list */
pcap_freealldevs (pAlldevs);
printf ("[%s] Interface found [%d]\n", __func__, nCnt);
return nCnt;
} /* end of fnGetDeviceAll () */
/*-----------------------------------------------------------------------------
fnDevMon ()
Date : 21Dec09-21Dec09
Input : Device No
Output : ROK, RFAIL
Description
21Dec09 jakeoh Open Device and Start monitoring
-----------------------------------------------------------------------------*/
int fnDevMon
(
int nNo
)
{
int nCnt;
pcap_t *pHandle;
pcap_if_t *pAlldevs;
pcap_if_t *pIft;
char szErrBuf[PCAP_ERRBUF_SIZE];
pHandle = NULL;
printf ("[%s] Device No [%d]\n", __func__, nNo);
/* Get Device info */
if (pcap_findalldevs (&pAlldevs, szErrBuf) == -1)
{
printf ("[%s] pcap_findalldevs () FAILED [%s]\n", __func__, szErrBuf);
return RFAIL;
}
/* Jump to the selected device */
for (pIft=pAlldevs, nCnt=0; nCnt < nNo; pIft=pIft->next, nCnt++);
/* Open the device */
if ((pHandle = pcap_open_live (pIft->name, // name of the device
65536, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
1, // promiscuous mode (nonzero means promiscuous)
1000, // read timeout
szErrBuf // error buffer
)) == NULL)
{
printf ("[%s] Unable to open the adapter. %s is not supported by WinPcap\n", __func__, pIft->name);
printf ("[%s] ERR : %s\n", __func__, szErrBuf);
/* Free the device list */
pcap_freealldevs (pAlldevs);
return RFAIL;
}
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs (pAlldevs);
printf ("[%s] Listening on %s...\n", __func__, pIft->description);
/* start the capture */
pcap_loop (pHandle, 0, fnPacket_Handler, NULL);
/* Close */
pcap_close (pHandle);
return ROK;
} /* end of fnDevMon () */
/*-----------------------------------------------------------------------------
fnPacket_Handler ()
Date : 21Dec09-21Dec09
Input :
Output :
Description
21Dec09 jakeoh Callback function invoked by libpcap for every incoming packet
-----------------------------------------------------------------------------*/
void fnPacket_Handler
(
u_char *pParam,
const struct pcap_pkthdr *pstHeader,
const u_char *pPkt_data
)
{
struct tm *ltime;
char timestr[16];
time_t local_tv_sec;
/*
* unused parameters
*/
(VOID)(pParam);
(VOID)(pPkt_data);
/* convert the timestamp to readable format */
local_tv_sec = pstHeader->ts.tv_sec;
ltime = localtime (&local_tv_sec);
strftime (timestr, sizeof timestr, "%H:%M:%S", ltime);
printf ("-> [%s,%.6d] [len:%d] [caplen:%d]\n", timestr, pstHeader->ts.tv_usec, pstHeader->len, pstHeader->caplen);
fnDebugDump ((char *) pPkt_data, pstHeader->len);
} /* end of fnPacket_Handler () */
/*-----------------------------------------------------------------------------
fnOpenDevice ()
Date : 21Dec09-21Dec09
Input : Device No
Output : pcat_t *
Description
21Dec09 jakeoh Open selected device
-----------------------------------------------------------------------------*/
pcap_t *fnOpenDevice
(
int nNo
)
{
int nCnt;
pcap_t *pHandle;
pcap_if_t *pAlldevs;
pcap_if_t *pIft;
char szErrBuf[PCAP_ERRBUF_SIZE];
pHandle = NULL;
printf ("[%s] Device No [%d]\n", __func__, nNo);
/* Get Device info */
if (pcap_findalldevs (&pAlldevs, szErrBuf) == -1)
{
printf ("[%s] pcap_findalldevs () FAILED [%s]\n", __func__, szErrBuf);
return pHandle;
}
/* Jump to the selected device */
for (pIft=pAlldevs, nCnt=0; nCnt < nNo; pIft=pIft->next, nCnt++);
/* Open the device */
if ((pHandle = pcap_open_live (pIft->name, // name of the device
65536, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
1, // promiscuous mode (nonzero means promiscuous)
1000, // read timeout
szErrBuf // error buffer
)) == NULL)
{
printf ("[%s] Unable to open the adapter. %s is not supported by WinPcap\n", __func__, pIft->name);
printf ("[%s] ERR : %s\n", __func__, szErrBuf);
/* Free the device list */
pcap_freealldevs (pAlldevs);
return pHandle;
}
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs (pAlldevs);
return pHandle;
} /* end of fnOpenDevice () */
/*-----------------------------------------------------------------------------
fnCloseDevice ()
Date : 21Dec09-21Dec09
Input : pcat_t*
Output : ROK, RFAIL
Description
21Dec09 jakeoh Close selected device
-----------------------------------------------------------------------------*/
int fnCloseDevice
(
pcap_t *pHandle
)
{
pcap_close (pHandle);
return ROK;
} /* end of fnCloseDevice () */
/*-----------------------------------------------------------------------------
fnReadPacket ()
Date : 22Dec09-22Dec09
Input : pcap_t *
Output : return code
Description
22Dec09 jakeoh Read packet from selected handle
-----------------------------------------------------------------------------*/
int fnReadPacket
(
pcap_t *pHandle
)
{
int nRet;
char timestr[16];
time_t local_tv_sec;
struct tm *ltime;
const u_char *pPkt_data;
struct pcap_pkthdr *pstHeader;
nRet = pcap_next_ex (pHandle, &pstHeader, &pPkt_data);
if (nRet == 0) /* timeout elapsed */
return 0;
if (nRet < 0) /* error */
{
printf ("[%s] ERROR [%s]\n", __func__, pcap_geterr (pHandle));
return nRet;
}
/* convert the timestamp to readable format */
local_tv_sec = pstHeader->ts.tv_sec;
ltime = localtime (&local_tv_sec);
strftime (timestr, sizeof timestr, "%H:%M:%S", ltime);
printf ("-> [%s,%.6d] [len:%d] [caplen:%d]\n", timestr, pstHeader->ts.tv_usec, pstHeader->len, pstHeader->caplen);
fnDebugDump ((char *) pPkt_data, pstHeader->len);
return nRet;
} /* end of fnReadPacket () */
/*-----------------------------------------------------------------------------
End of wp_util.c
-----------------------------------------------------------------------------*/
3. ipd
3.1 gen.h
/*-----------------------------------------------------------------------------
gen.h
General definition
version : 1.0
Programed by : jakeoh
Date : 18Dec09-18Dec09
Compiler :
Description :
18Dec09 jakeoh Initial
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Predefine
-----------------------------------------------------------------------------*/
#define BUFSIZE256 256+1
/*-----------------------------------------------------------------------------
function prototypes
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
End of gen.h
-----------------------------------------------------------------------------*/
3.2 ipd_main.c
/*-----------------------------------------------------------------------------
ipd_main.c
IP Dump utility using winpcap library
18Dec09-18Dec09
18Dec09 jakeoh from ~/WpdPack_4_1_1/WpdPack/Examples-pcap/basic_dump.c
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Include files
-----------------------------------------------------------------------------*/
#include "gen.h"
#include "wp_util.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
int errno; /* global error number */
char gszAppName[30]; /* Application name */
/*-----------------------------------------------------------------------------
main ()
Date : 18Dec09-18Dec09
Input :
Output :
Description
18Dec09 jakeoh View device list, select device, monitoring device
-----------------------------------------------------------------------------*/
int main
(
int argc, /* argument count */
char **argv /* argument values */
)
{
int nRet, nCnt;
int nDev;
#if 0
char szCmd[BUFSIZE256];
char szTmp[BUFSIZE256], szBaseKey[BUFSIZE256];
char *pEnd;
int nShmKey;
char *pShm;
#endif
/* argument check */
/* set App name */
strcpy (gszAppName, argv[0]);
#if 0
gnLogLevel = LOG_LVL_FULL;
nRet = fnInitLogFiles ();
if (nRet != RETOK)
{
printf ("[%s] ***ERROR*** Log init failed \n", __func__);
exit (0);
}
logPrint2 (LDEBUG, gnLogLevel, gnTrcLogId, FL, "[%s] -------------------------------------\n", __func__);
logPrint2 (LDEBUG, gnLogLevel, gnTrcLogId, FL, "[%s] STARTUP [%s]\n", __func__, gszAppName);
logPrint2 (LDEBUG, gnLogLevel, gnTrcLogId, FL, "[%s] -------------------------------------\n", __func__);
#endif
printf ("[%s] -------------------------------------\n", __func__);
printf ("[%s] STARTUP [%s]\n", __func__, gszAppName);
printf ("[%s] -------------------------------------\n", __func__);
#if 0
/* Init signal */
InitSignal ();
fnTerminate ();
#endif
/* View all device */
nRet = fnGetDeviceAll ();
/* Select device */
printf ("[%s] Select Device No 0-%d : ", __func__, nRet-1);
scanf ("%d", &nDev);
/* Check device range */
if (nDev < 0 || nDev >= nRet)
{
printf ("[%s] Invalid device no %d\n", __func__, nDev);
exit (0);
}
/* Start monitor */
#if 0
if (fnDevMon (nDev) == RFAIL)
{
printf ("[%s] Device open failed\n", __func__);
exit (0);
}
#else
pcap_t *pHandle;
/* Open Device */
pHandle = (pcap_t *) fnOpenDevice (nDev);
if (pHandle == NULL)
{
printf ("[%s] fnOpenDevice (%d) FAILED [0x%08lx]\n", __func__, nDev, (unsigned long) pHandle);
printf ("[%s] TERMINATE [%s]\n", __func__, gszAppName);
exit (0);
}
else
printf ("[%s] fnOpenDevice (%d) [0x%08lx]\n", __func__, nDev, (unsigned long) pHandle);
nCnt = 0;
/* Monitoring Loop */
while (1)
{
nRet = fnReadPacket (pHandle);
if (nRet == 0)
{
printf ("[%s] Timeout elapsed\n", __func__);
continue;
}
if (nRet == -1)
{
printf ("[%s] Error reading the packets: %s\n", __func__, pcap_geterr (pHandle));
break;
}
nCnt++;
if (nCnt >= 10)
break;
}
/* Close Device */
fnCloseDevice (pHandle);
#endif
printf ("[%s] TERMINATE [%s]\n", __func__, gszAppName);
return 0;
} /* end of main () */
/*-----------------------------------------------------------------------------
End of ipd_main.c
-----------------------------------------------------------------------------*/