Traceroute和数据包捕获

时间:2013-05-18 20:45:08

标签: pcap libpcap packet-capture packet-sniffers traceroute

当数据包从本地路由器移动到目标路由器时,需要以下代码来捕获数据包所采用的路由。它应该打印所有中间路由器及其IP地址。代码如下。但输出未列出所有IP地址。它只显示一个路由器的IP。如何修改代码以便显示所有中间IP地址?请帮帮我。谢谢!

输入格式./a.out (destination ip) (port no) (MAX_TTL) (max_probe)

输出我得到的是这样的:

./a.out 68.71.216.176 80 10 2

使用MAX_TTL 10跟踪68.71.216.176到端口80,带有2个探头

1>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

1>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

2>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

2>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

3>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

3>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

4>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

4>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

5>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

5>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

6>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

6>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

7>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit

7>192.168.1.1:80.....192.168.1.3:35410------------------->Time-to-live exceeded: Time-to-live exceeded on transit


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<errno.h>
#include<netinet/ip.h>
#include<pcap.h>
#include<signal.h>
#include<arpa/inet.h>

/*IP HEADER*/

struct ip_hdr
{
unsigned char ip_v:4, ip_hl:4;
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
struct in_addr ip_src, ip_dst;
};

/*ICMP HEADER*/

struct icmp_hdr
{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short int icmp_chksum;
int icmo_nouse;
};

struct udp_hdr
{
unsigned short int udp_srcport;
unsigned short int udp_destport;
unsigned short int udp_len;
unsigned short int udp_chksum;
};

int sockfd1;
char *buf = "s",dst[INET_ADDRSTRLEN],src[INET_ADDRSTRLEN];
int ttl,max_ttl,max_probe,pac;
struct sockaddr_in servaddr;

pcap_t *handle;
unsigned short int port_now;
int Initiate_pcapsession();
void send_packets(int);
void parse(u_char *,const struct pcap_pkthdr *,const u_char *);

int main (int argc, char **argv)
{
int state;
unsigned short int port;
if (argc < 5)
{
    printf ("\n USAGE ./a.out <d-IP> <port> <maxttl> <maxprobe>\n");
    return 0;
}
port = atoi (argv[2]);
max_ttl = atoi (argv[3]);
max_probe = atoi (argv[4]);

printf ("tracing %s with MAX_TTL %d on to port %u  with %d probes\n", argv[1], max_ttl, port, max_probe);
servaddr.sin_family = AF_INET;

if (inet_pton (AF_INET, argv[1], &servaddr.sin_addr) < 0)
    {
        perror ("\tspecified address is invalid:progrm terminates:inet_pton");
        return 0;
    }

if ((sockfd1 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
        perror ("Error creating Socket:socket");
        return 0;
    }

if((state=Initiate_pcapsession())==-1)
{
    printf("\nCoudnt create a Packet capture session:TERMINATING");
    return 0;
}

for (ttl = 1; ttl <= max_ttl; ttl++)
    { 
    port_now=htons(port + ttl -1);
        //printf("\n%d>",ttl);
        servaddr.sin_port = port_now;
        send_packets (ttl);
    }

pcap_close(handle);
close (sockfd1);
return 0;
}

int Initiate_pcapsession()
{
int state;
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
char filter_exp[]="icmp and (icmp[0] = 11 and icmp[1] = 0) or (icmp[0] = 3 and icmp[1] = 3)";
bpf_u_int32 mask,net;

if((dev=pcap_lookupdev(errbuf))==NULL)
{
    printf("\nCoudnt find  default device: %s\n",errbuf);
    return -1;
}
//  else
//      printf("\nFound default device %s ",dev);

if (pcap_lookupnet ("wlan0", &net, &mask, errbuf) == -1)
{
    printf ("\nCoudn't get the netmask for device %s:%s\n", "wlan0", errbuf);
        return -1;
}

if ((handle = pcap_open_live ("wlan0", BUFSIZ, 1, 270000, errbuf)) == NULL)
    {
        printf ("\nCoudn't open device %s:%s","wlan0", errbuf);
        return -1;
    }

if((state=pcap_setnonblock(handle, 1, errbuf))==-1)
{
    printf("\nCoudn't set capture descriptor to non-blocking mode :%s",errbuf);
    return -1;
}

if (pcap_compile (handle, &fp, filter_exp, 0, net) == -1)
    {
        printf ("\nCoudn't parse filter %s:%s", filter_exp, pcap_geterr (handle));
        return -1;
    }

if (pcap_setfilter (handle, &fp) == -1)
    {
        printf ("\nCoudn't install filter %s:%s\n", filter_exp, pcap_geterr (handle));
        return -1;
    }

return 1;
}

void send_packets( int ttl_now)
{
pid_t pid;
int p,num,status;
setsockopt (sockfd1, IPPROTO_IP, IP_TTL, &ttl_now, sizeof (ttl_now));

for(p=1;p<=max_probe;p++)
{
        if ((sendto(sockfd1, buf, sizeof (buf), 0, (struct sockaddr *) &servaddr,sizeof (servaddr))) == -1)
            {
                perror ("sendto");
            }
            else
            {    
        pac+=1;
                    //printf("\n\t\tSENT PACKET %d",pac);
                    if((pid=fork())<0)
                    {
                        perror("fork");
                            exit(0);
                    }
                    if(pid==0)
                    {
                            num=pcap_loop(handle,-1,parse,NULL);
                            if(num) 
                printf("\npcap_dispatch:%d packets captured",num);
                            else    
                printf("\npcap_dispatch:No pcakets captured");
                    }
                    else
                    {
                            sleep(1);
                            //wait(&status);
                            kill(pid,SIGSTOP);
                    }
    }
}
}

void parse(u_char *args,const struct pcap_pkthdr *header,const u_char *packet)
{
struct ip_hdr *ip1 = (struct ip_hdr *) (packet + 14);   /*initialising ip pointer beyond the sll protocol header 16 bytes */
struct icmp_hdr *icmp = (struct icmp_hdr *) (packet + 14 + sizeof (struct ip_hdr));
struct ip_hdr *ip2 = (struct ip_hdr *) (packet + 14 + sizeof (struct ip_hdr) + sizeof (struct icmp_hdr));
struct udp_hdr *udp = (struct udp_hdr *) (packet + 14 + sizeof (struct ip_hdr) + sizeof (struct icmp_hdr) + sizeof (struct ip_hdr));

    //if (ntohs (udp->udp_destport) == ntohs (port_now))
    //{
    inet_ntop (AF_INET, &ip1->ip_dst, dst, 16);
    inet_ntop (AF_INET, &ip1->ip_src, src, 16);
    printf ("\n\t%d>%s:%u.....%s:%u------------------->",ttl, src,ntohs (udp->udp_destport), dst,ntohs (udp->udp_srcport));

if(icmp->icmp_code==0)
        printf("Time-to-live exceeded: Time-to-live exceeded on transit\n");
else if(icmp->icmp_code==3)
        printf("Destination unreachable: Port unreachable\n");
//}

exit(0);
}

1 个答案:

答案 0 :(得分:0)

此类ICMP数据包有2个IP标头。您要查找的地址不在ip1(这是您正在打印的地址),它位于ip2(您加载了,但之后您没有打印任何值)。