发新话题
打印

[转载]TCP-Traceroute核心代码

[转载]TCP-Traceroute核心代码

文章作者:记忆碎片
复制内容到剪贴板
代码:
//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 &#39;13th Floor&#39;
//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
曾几何时,有人对我说:装B遭雷劈。我说:去你妈的。于是,这个人又对我说:如果再说脏话,上帝会惩罚你的。我说:我操上帝。结论:彪悍的人生不需要上帝。

TOP

发新话题