TCP-Traceroute 核心代码

测试环境:

操作系统: Microsoft Windows 2000 with Service Pack 4
开发环境: Microsoft Visual C++6 with Service Pack 6
其它: Winpcap 3.1 beta 3



代码
//tracer.c
//Copyright (c) 1999 - 2004
//S8S8.net Network Tech. Forum
//written by '13th Floor'
//All rights reserved.

#include <winsock2.h>
#include <ws2tcpip.h>

#include <cstring>
#include <queue>
using namespace std;

#include "pcap.h"
#include "headers.h"
#include "tracer.h"

char* FLT_EXPR = "ip and icmp[icmptype]=icmp-timxceed or tcp[tcpflags]=tcp-rst";

unsigned short checksum(unsigned short *buffer, int size)
{
       unsigned long cksum = 0;
       while(size > 1) {
               cksum += *buffer++;
               size -= sizeof(unsigned short);
       }
       if(size)
               cksum += *(unsigned char*)buffer;
       cksum = (cksum >> 16) + (cksum & 0xffff);
       cksum += (cksum >> 16);
       return (unsigned short)(~cksum);
}


int build_packets(
       unsigned long local_addr,
       unsigned long dst_addr,
       char* buf,
       unsigned char TTL)
{
       static unsigned long SEQ = 0x2344512;
       int datasize =0;
       IP_HDR ip_header;
       TCP_HDR tcp_header;
       PSD_HDR psd_header;

       ip_header.h_verlen =
                       (4 << 4 | sizeof(ip_header) / sizeof(unsigned long));
       ip_header.total_len = htons(sizeof(IP_HDR) + sizeof(TCP_HDR));
       ip_header.ident = 1;
       ip_header.frag_and_flags = 0;
       ip_header.ttl = TTL;
       ip_header.proto = IPPROTO_TCP;
       ip_header.checksum = 0;
       ip_header.saddr = local_addr;
       ip_header.daddr = dst_addr;

       tcp_header.th_sport = htons(7000);        
       tcp_header.th_dport = htons(5000);
       tcp_header.th_seq = SEQ++;
       tcp_header.th_ack = 0;
       tcp_header.th_lenres = (sizeof(TCP_HDR) / 4 << 4 | 0);
       tcp_header.th_flag = 16;
       tcp_header.th_win = htons(16384);
       tcp_header.th_urp = 0;
       tcp_header.th_sum = 0;

       psd_header.saddr = ip_header.saddr;
       psd_header.daddr = ip_header.daddr;
       psd_header.mbz = 0;
       psd_header.proto = IPPROTO_TCP;
       psd_header.tcpl = htons(sizeof(tcp_header));

       memcpy(buf, &psd_header, sizeof(psd_header));
       memcpy(buf + sizeof(psd_header), &tcp_header, sizeof(tcp_header));
       tcp_header.th_sum = checksum((unsigned short *)buf,
                               sizeof(psd_header) + sizeof(tcp_header));
       memcpy(buf, &ip_header, sizeof(ip_header));
       memcpy(buf + sizeof(ip_header), &tcp_header, sizeof(tcp_header));
       memset(buf + sizeof(ip_header) + sizeof(tcp_header), 0, 4);
       datasize = sizeof(ip_header) + sizeof(tcp_header);
       ip_header.checksum = checksum((unsigned short*)buf,datasize);
       memcpy(buf, &ip_header, sizeof(ip_header));

       return 0;
}


int start_trace(
       queue<unsigned long>& dst_addr_queue,
       unsigned long local_addr,
       SOCKET& socket)
{
       char snd_buf[128];
       int ret;
       sockaddr_in dst_addr;
       pcap_t* adhandle;
       struct pcap_pkthdr *header;
       const u_char *pkt_data;

       //Setup for winpcap
       pcap_if_t        *alldevs, *d;
       char                errbuf[PCAP_ERRBUF_SIZE];
       unsigned int        netmask;
       bpf_program        fcode;

       if (pcap_findalldevs(&alldevs, errbuf) == -1)
               throw ("Error in pcap_findalldevs");        
       try {
           d = alldevs->next;
               if ((adhandle= pcap_open_live(
                                       d->name, //adapter
                                       65536,
                                       1,
                                       1000, //time out
                                       errbuf))
                       == NULL)
                       throw ("Failed to open adapter!");
               if(d->addresses != NULL)
                       netmask=((struct sockaddr_in *)
                               (d->addresses->netmask))
                               ->sin_addr.S_un.S_addr;
               else
                       netmask=0xffffff;
               if(pcap_compile(adhandle,
                               &fcode,
                               FLT_EXPR,
                               1,
                               netmask) <0
                               )
                       throw ("Failed to compile the filter");
               if(pcap_setfilter(adhandle, &fcode)<0) {
                       throw ("Error setting the filter");
               }
       }
       catch (const char * error) {
               pcap_freealldevs(alldevs);
               throw (error);
       }
       pcap_freealldevs(alldevs);
       
       //Setup for Winsock
       WSADATA        wsaData;
       BOOL flag = TRUE;
       int time_out = 2000;
       socket = INVALID_SOCKET;

       if (WSAStartup(MAKEWORD(2, 1), &wsaData) !=0)
               throw ("WSAStartup() failed");
       try {
               socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW,
                       NULL,0, WSA_FLAG_OVERLAPPED);
               if (socket == INVALID_SOCKET)
                       throw ("WSASocket() failed");
               if (setsockopt(socket, IPPROTO_IP, IP_HDRINCL,
                       (char*)&flag, sizeof(int)) == SOCKET_ERROR)
                       throw ("Failed to set IP_HDRINCL");
               if (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO,
                       (char*)&time_out, sizeof(time_out)) == SOCKET_ERROR)
                       throw ("Failed to set SO_SNDTIMEO");
       }
       catch(const char* error) {
               if (socket != INVALID_SOCKET)
                       closesocket(socket);
               WSACleanup();
               throw error;
       }

       //Get local address
       char name[255];
       PHOSTENT hostinfo;
       if (gethostname(name, sizeof(name))==0)
               if ((hostinfo = gethostbyname(name)) !=NULL)
                       local_addr = (*(struct in_addr*)
                                       *hostinfo->h_addr_list).s_addr;

       //Start Trace
       while (dst_addr_queue.empty() == false) {
               unsigned long crt_addr  = dst_addr_queue.front();

               memset(&dst_addr, 0, sizeof(dst_addr));
               dst_addr.sin_family = AF_INET;
               dst_addr.sin_addr.s_addr = crt_addr;
               
               printf("/n/nTracing: ");
               printf("%s/n", inet_ntoa(*(in_addr*)&crt_addr));
               for (unsigned char ttl = 1; ttl <= 30; ttl++) {
                       build_packets(local_addr, crt_addr, snd_buf, ttl);
                       ret = sendto(socket, snd_buf, sizeof(IP_HDR)+sizeof(TCP_HDR),
                               0, (sockaddr*)&dst_addr, sizeof(dst_addr));
                       ret = pcap_next_ex(adhandle, &header, &pkt_data);
                       if (ret == 0) {
                               printf("%s/n", "time out");
                               continue;
                       }
                       IP_HDR* iphdr = (IP_HDR*)(pkt_data + 14);
                       printf("%s/n", inet_ntoa(*(in_addr*)&(iphdr->saddr)));
                       if (iphdr->proto == IPPROTO_TCP) break;
               }
               dst_addr_queue.pop();
       }
       return 0;
}
//headers.h
//Copyright (c) 1999 - 2004
//S8S8.net Network Tech. Forum
//written by '13th Floor'
//All rights reserved.


#ifndef _HEADERS_H
#define _HEADERS_H

//IP Header
typedef struct _iphdr {
       unsigned char  h_verlen;        //IP Version
       unsigned char  tos;                //Type of Service; 8 bits
       unsigned short total_len;        //total length; 16 bits
       unsigned short ident;                //Identification; 16 bits
       unsigned short frag_and_flags;        //Flags
       unsigned char  ttl;                //Time to live; 8 bits
       unsigned char  proto;                //Protocol; 8 bits
       unsigned short checksum;        //Checksum; 16 bits
       unsigned long  saddr;                //Source IP address; 32 bits
       unsigned long  daddr;                //Destination IP address; 32 bits
} IP_HDR;  

//PSD Header
typedef struct _psdhdr {
       unsigned long  saddr;                //Source IP address; 32 bits
       unsigned long  daddr;                //Destination IP address; 32 bits
       unsigned char  mbz;                //padding
       unsigned char  proto;                //Protocol; 8 bits
       unsigned short tcpl;                //TCP length; 16 bits
} PSD_HDR;

//TCP Header
typedef struct _tcphdr {
       unsigned short th_sport;        //Source port; 16 bits
       unsigned short th_dport;        //Destination port; 16 bits
       unsigned long  th_seq;                //Sequence Number; 32 bits
       unsigned long  th_ack;                //Acknowledgment Number; 32 bits
       unsigned char  th_lenres;        //Data Offset / reserved
       unsigned char  th_flag;                //ECN / Control Bits; 6 bits
       unsigned short th_win;                //Window; 16 bits
       unsigned short th_sum;                //Checksum; 16 bits
       unsigned short th_urp;                //Urgent Pointer; 16 bits
} TCP_HDR;

//ICMP Header
typedef struct _icmphdr {
       unsigned char  i_type;                //ICMP Type; 8 bits
       unsigned char  i_code;                //ICMP Code; 8 bits
       unsigned short i_cksum;                //ICMP header checksum; 16 bits
       unsigned short i_id;                //Identification; 16 bits
       unsigned short i_seq;                //Sequence Number; 16 bits
       unsigned long  timestamp;        //Timestamp; 32 bits
} ICMP_HDR;

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值