Open Source codes, knowledge, experiences sharing

Tags

I am working on this, porting to Win32.最大的特点是他的struct,与标准不一样的。

#include "sys/socket.h"       
#include "netdb.h"
#include "stdlib.h"
#include "unistd.h"
#include "stdio.h"
#include "errno.h"
#include "netinet/in.h"
#include "netinet/ip.h"
#include "linux/if.h"
#include "sys/ioctl.h"
#include "sys/types.h"
#include "signal.h"
#include "fcntl.h"

#undef  DEBUG
#define IP_VERSION      4                 
#define MTU             1500
#define IP_HEAD_BASE    20                /* using fixed lengths to send   */
#define TCP_HEAD_BASE   20                /* no options etc...             */
#define UDP_HEAD_BASE   8                 /* Always fixed                  */

#define IO_HANDLE       1
#define IO_NONBLOCK     2

int DEV_PREFIX = 9999;
sig_atomic_t WAIT_PACKET_WAIT_TIME=0;

/**** IO_HANDLE ************************************************************/
int rc_fd_abc123;
sig_atomic_t RC_FILTSET=0;
char rc_filter_string[50];                       /* x.x.x.x.p-y.y.y.y.g  */

sig_atomic_t SP_DATA_BUSY=0;
unsigned long int CUR_SEQ=0, CUR_ACK=0, CUR_COUNT=0;
unsigned int CUR_DATALEN;
unsigned short CUR_FLAGS;
/***************************************************************************/

struct sp_wait_packet
{
        unsigned long seq,ack;
        unsigned short flags;
        int datalen;
};

#define URG 32       /* TCP flags */
#define ACK 16
#define PSH 8
#define RST 4
#define SYN 2
#define FIN 1

struct PACKET_info
{
        int len, datalen;
        unsigned long int seq_nr, ACK_nr;
        u_char FLAGS;
};

struct IP_header                        /* The IPheader (without options) */
{
        unsigned char verlen, type;
        unsigned short length, ID, flag_offset;
        unsigned char TTL, protocol;
        unsigned short checksum;
        unsigned long int source, destination;
};

struct TCP_header                     /* The TCP header (without options) */
{
        unsigned short source, destination;
        unsigned long int seq_nr, ACK_nr;
        unsigned short offset_flag, window, checksum, urgent;
};

struct UDP_header                                      /* The UDP header */
{
        unsigned short source, destination;
        unsigned short length, checksum;
};

struct pseudo_IP_header          /* The pseudo IP header (checksum calc) */
{
        unsigned long int source, destination;
        char zero_byte, protocol;
        unsigned short TCP_UDP_len;
};

/* data structure for argument passing  */

struct sp_data_exchange {
        int fd;                                /* Sh!t from transmit_TCP  */
        char *data;
        int datalen;
        char *source; unsigned short source_port;
        char *dest;   unsigned short dest_port;
        unsigned long seq, ack;
        unsigned short flags;

        char *buffer;               /* work buffer */

        int IP_optlen;             /* IP options length in bytes  */
        int TCP_optlen;            /* TCP options length in bytes */
        };

/**************** all functions  *******************************************/
void transmit_TCP (int fd, char *sp_data,
                           int sp_ipoptlen, int sp_tcpoptlen, int sp_datalen,
                           char *sp_source, unsigned short sp_source_port,
                           char *sp_dest, unsigned short sp_dest_port,
                           unsigned long sp_seq, unsigned long sp_ack,
                           unsigned short sp_flags);

void transmit_UDP (int sp_fd, char *sp_data,
                           int  ipoptlen, int sp_datalen,
                           char *sp_source, unsigned short sp_source_port,
                           char *sp_dest, unsigned short sp_dest_port);

int get_packet (int rc_fd, char *buffer, int *, unsigned char*);
int wait_packet(int,struct sp_wait_packet *,char *, unsigned short,char *,
                unsigned short, int, int);

static unsigned long sp_getaddrbyname(char *);

int open_sending (void);
int open_receiving (char *, char);
void close_receiving (void);

void sp_send_packet (struct sp_data_exchange *, unsigned char);
void sp_fix_TCP_packet (struct sp_data_exchange *);
void sp_fix_UDP_packet (struct sp_data_exchange *);
void sp_fix_IP_packet (struct sp_data_exchange *, unsigned char);
unsigned short in_cksum(unsigned short *, int );

void rc_sigio (int);
void set_filter (char *, unsigned short, char *, unsigned short);

/********************* let the games commence ****************************/

static unsigned long sp_getaddrbyname(char *sp_name)
{
struct hostent *sp_he;
int i;

if(isdigit(*sp_name))
  return inet_addr(sp_name);

for(i=0;i<100;i++)
     {
     if(!(sp_he = gethostbyname(sp_name)))
        {printf("WARNING: gethostbyname failure!\n");
        sleep(1);
        if(i>=3)       /* always a retry here in this kind of application */
           printf("Coudn't resolv hostname."), exit(1);
        }
     else break;
     }
return sp_he ? *(long*)*sp_he->h_addr_list : 0;
}

int open_sending (void)
{
struct protoent *sp_proto;
int sp_fd;
int dummy=1;

/* they don't come rawer */
if ((sp_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==-1)
        perror("Couldn't open Socket."), exit(1);

#ifdef DEBUG
        printf("Raw socket ready\n");
#endif
return sp_fd;
}

void sp_send_packet (struct sp_data_exchange *sp, unsigned char proto)
{
int sp_status;
struct sockaddr_in sp_server;
struct hostent *sp_help;
int HEAD_BASE;

/* Construction of destination */
bzero((char *)&sp_server, sizeof(struct sockaddr));
sp_server.sin_family = AF_INET;
sp_server.sin_addr.s_addr = inet_addr(sp->dest);
if (sp_server.sin_addr.s_addr == (unsigned int)-1)
        {                      /* if target not in DOT/number notation */
        if (!(sp_help=gethostbyname(sp->dest)))
          fprintf(stderr,"unknown host %s\n", sp->dest), exit(1);
        bcopy(sp_help->h_addr, (caddr_t)&sp_server.sin_addr, sp_help->h_length);
        };

switch(proto)
        {
        case 6: HEAD_BASE = TCP_HEAD_BASE;  break;                  /* TCP */
        case 17: HEAD_BASE = UDP_HEAD_BASE; break;                  /* UDP */
        default: exit(1); break;
        };
sp_status = sendto(sp->fd, (char *)(sp->buffer),
                   sp->datalen+HEAD_BASE+IP_HEAD_BASE+sp->IP_optlen, 0,
                   (struct sockaddr *)&sp_server,sizeof(struct sockaddr));
if (sp_status < 0 || sp_status != 
            sp->datalen+HEAD_BASE+IP_HEAD_BASE+sp->IP_optlen)
        {
        if (sp_status < 0)
          perror("Sendto"), exit(1);
        printf("hmm... Only transmitted %d of %d bytes.\n", sp_status,
                                                sp->datalen+HEAD_BASE);
        };
#ifdef DEBUG
        printf("Packet transmitted...\n");
#endif
}

void sp_fix_IP_packet (struct sp_data_exchange *sp, unsigned char proto)
{
struct IP_header *sp_help_ip;
int HEAD_BASE;

switch(proto)
        {
        case 6: HEAD_BASE = TCP_HEAD_BASE;  break;                  /* TCP */
        case 17: HEAD_BASE = UDP_HEAD_BASE; break;                  /* UDP */
        default: exit(1); break;
        };

sp_help_ip = (struct IP_header *) (sp->buffer);
sp_help_ip->verlen = (IP_VERSION << 4) | ((IP_HEAD_BASE+sp->IP_optlen)/4);
sp_help_ip->type = 0;
sp_help_ip->length = 
        htons(IP_HEAD_BASE+HEAD_BASE+sp->datalen+sp->IP_optlen+sp->TCP_optlen);
sp_help_ip->ID = htons(12545);                                  /* TEST */
sp_help_ip->flag_offset = 0;
sp_help_ip->TTL = 69;
sp_help_ip->protocol = proto;
sp_help_ip->source = sp_getaddrbyname(sp->source);
sp_help_ip->destination =  sp_getaddrbyname(sp->dest);
sp_help_ip->checksum=in_cksum((unsigned short *) (sp->buffer),
                                                IP_HEAD_BASE+sp->IP_optlen);
#ifdef DEBUG
        printf("IP header fixed...\n");
#endif
}

void sp_fix_TCP_packet (struct sp_data_exchange *sp)
{
char sp_pseudo_ip_construct[MTU];
struct TCP_header *sp_help_tcp;
struct pseudo_IP_header *sp_help_pseudo;
int i;

for(i=0;i<MTU;i++)
  {sp_pseudo_ip_construct[i]=0;}

sp_help_tcp = (struct TCP_header *) (sp->buffer+IP_HEAD_BASE+sp->IP_optlen);
sp_help_pseudo = (struct pseudo_IP_header *) sp_pseudo_ip_construct;

sp_help_tcp->offset_flag = htons( 
                     (((TCP_HEAD_BASE+sp->TCP_optlen)/4)<<12) | sp->flags);
sp_help_tcp->seq_nr = htonl(sp->seq);
sp_help_tcp->ACK_nr = htonl(sp->ack);
sp_help_tcp->source = htons(sp->source_port);
sp_help_tcp->destination = htons(sp->dest_port);
sp_help_tcp->window = htons(0x7c00);             /* dummy for now 'wujx' */

sp_help_pseudo->source = sp_getaddrbyname(sp->source);
sp_help_pseudo->destination =  sp_getaddrbyname(sp->dest);
sp_help_pseudo->zero_byte = 0;
sp_help_pseudo->protocol = 6;
sp_help_pseudo->TCP_UDP_len = htons(sp->datalen+TCP_HEAD_BASE+sp->TCP_optlen);

memcpy(sp_pseudo_ip_construct+12, sp_help_tcp,
                             sp->TCP_optlen+sp->datalen+TCP_HEAD_BASE);
sp_help_tcp->checksum=in_cksum((unsigned short *) sp_pseudo_ip_construct,
                                  sp->datalen+12+TCP_HEAD_BASE+sp->TCP_optlen);
#ifdef DEBUG
        printf("TCP header fixed...\n");
#endif
}

void transmit_TCP (int sp_fd, char *sp_data,
                           int sp_ipoptlen, int sp_tcpoptlen, int sp_datalen,
                           char *sp_source, unsigned short sp_source_port,
                           char *sp_dest, unsigned short sp_dest_port,
                           unsigned long sp_seq, unsigned long sp_ack,
                           unsigned short sp_flags)
{
char sp_buffer[1500];
struct sp_data_exchange sp_struct;

bzero(sp_buffer,1500);
if (sp_ipoptlen!=0)
        memcpy(sp_buffer+IP_HEAD_BASE,sp_data,sp_ipoptlen);

if (sp_tcpoptlen!=0)
        memcpy(sp_buffer+IP_HEAD_BASE+TCP_HEAD_BASE+sp_ipoptlen,
                                            sp_data+sp_ipoptlen,sp_tcpoptlen);
if (sp_datalen!=0)
        memcpy(sp_buffer+IP_HEAD_BASE+TCP_HEAD_BASE+sp_ipoptlen+sp_tcpoptlen,
                        sp_data+sp_ipoptlen+sp_tcpoptlen,sp_datalen);

sp_struct.fd          = sp_fd;
sp_struct.data        = sp_data;
sp_struct.datalen     = sp_datalen;
sp_struct.source      = sp_source;
sp_struct.source_port = sp_source_port;
sp_struct.dest        = sp_dest;
sp_struct.dest_port   = sp_dest_port;
sp_struct.seq         = sp_seq;
sp_struct.ack         = sp_ack;
sp_struct.flags       = sp_flags;
sp_struct.buffer      = sp_buffer;
sp_struct.IP_optlen   = sp_ipoptlen;
sp_struct.TCP_optlen  = sp_tcpoptlen;

sp_fix_TCP_packet(&sp_struct);
sp_fix_IP_packet(&sp_struct, 6);
sp_send_packet(&sp_struct, 6);
}

void sp_fix_UDP_packet (struct sp_data_exchange *sp)
{
char sp_pseudo_ip_construct[MTU];
struct UDP_header *sp_help_udp;
struct pseudo_IP_header *sp_help_pseudo;
int i;

for(i=0;i<MTU;i++)
  {sp_pseudo_ip_construct[i]=0;}

sp_help_udp = (struct UDP_header *) (sp->buffer+IP_HEAD_BASE+sp->IP_optlen);
sp_help_pseudo = (struct pseudo_IP_header *) sp_pseudo_ip_construct;

sp_help_udp->source = htons(sp->source_port);
sp_help_udp->destination = htons(sp->dest_port);
sp_help_udp->length =  htons(sp->datalen+UDP_HEAD_BASE);

sp_help_pseudo->source = sp_getaddrbyname(sp->source);
sp_help_pseudo->destination =  sp_getaddrbyname(sp->dest);
sp_help_pseudo->zero_byte = 0;
sp_help_pseudo->protocol = 17;
sp_help_pseudo->TCP_UDP_len = htons(sp->datalen+UDP_HEAD_BASE);

memcpy(sp_pseudo_ip_construct+12, sp_help_udp, sp->datalen+UDP_HEAD_BASE);
sp_help_udp->checksum=in_cksum((unsigned short *) sp_pseudo_ip_construct,
                                                  sp->datalen+12+UDP_HEAD_BASE);
#ifdef DEBUG
        printf("UDP header fixed...\n");
#endif
}

void transmit_UDP (int sp_fd, char *sp_data,
                           int sp_ipoptlen, int sp_datalen,
                           char *sp_source, unsigned short sp_source_port,
                           char *sp_dest, unsigned short sp_dest_port)
{
char sp_buffer[1500];
struct sp_data_exchange sp_struct;

bzero(sp_buffer,1500);

if (sp_ipoptlen!=0)
        memcpy(sp_buffer+IP_HEAD_BASE,sp_data,sp_ipoptlen);
if (sp_data!=NULL)
        memcpy(sp_buffer+IP_HEAD_BASE+UDP_HEAD_BASE+sp_ipoptlen,
                                             sp_data+sp_ipoptlen,sp_datalen);
sp_struct.fd          = sp_fd;
sp_struct.data        = sp_data;
sp_struct.datalen     = sp_datalen;
sp_struct.source      = sp_source;
sp_struct.source_port = sp_source_port;
sp_struct.dest        = sp_dest;
sp_struct.dest_port   = sp_dest_port;
sp_struct.buffer      = sp_buffer;
sp_struct.IP_optlen   = sp_ipoptlen;
sp_struct.TCP_optlen  = 0;

sp_fix_UDP_packet(&sp_struct);
sp_fix_IP_packet(&sp_struct, 17);
sp_send_packet(&sp_struct, 17);
}

/* This routine stolen from ping.c -- HAHAHA!*/
unsigned short in_cksum(unsigned short *addr,int len)
{
register int nleft = len;
register unsigned short *w = addr;
register int sum = 0;
unsigned short answer = 0;

while (nleft > 1)
        {
        sum += *w++;
        nleft -= 2;
        }
if (nleft == 1)
        {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
        }
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}

/************************* Receiving department  ****************************/

int open_receiving (char *rc_device, char mode)
{
int or_fd;
struct sigaction rc_sa;
int fcntl_flag;
struct ifreq ifinfo;
char test;

/* create snoop socket and set interface promisc */
if ((or_fd = socket(AF_INET, SOCK_PACKET, htons(0x3)))==-1)
        perror("Couldn't open Socket."), exit(1);
strcpy(ifinfo.ifr_ifrn.ifrn_name,rc_device);
if(ioctl(or_fd,SIOCGIFFLAGS,&ifinfo)<0)
        perror("Couldn't get flags."), exit(1);
ifinfo.ifr_ifru.ifru_flags |= IFF_PROMISC;
if(ioctl(or_fd,SIOCSIFFLAGS,&ifinfo)<0)
        perror("Couldn't set flags. (PROMISC)"), exit(1);

if(mode&IO_HANDLE)
        {               /* install handler */
        rc_sa.sa_handler=rc_sigio;        /* we don't use signal()        */
        sigemptyset(&rc_sa.sa_mask);      /* because the timing window is */
        rc_sa.sa_flags=0;                 /* too big...                   */
        sigaction(SIGIO,&rc_sa,NULL);
        }

if(fcntl(or_fd,F_SETOWN,getpid())<0)
        perror("Couldn't set ownership"), exit(1);

if(mode&IO_HANDLE)
        {
        if( (fcntl_flag=fcntl(or_fd,F_GETFL,0))<0)
                perror("Couldn't get FLAGS"), exit(1);
        if(fcntl(or_fd,F_SETFL,fcntl_flag|FASYNC|FNDELAY)<0)
                perror("Couldn't set FLAGS"), exit(1);
        rc_fd_abc123=or_fd;
        }
else
        {
        if(mode&IO_NONBLOCK)
                {
                if( (fcntl_flag=fcntl(or_fd,F_GETFL,0))<0)
                        perror("Couldn't get FLAGS"), exit(1);
                if(fcntl(or_fd,F_SETFL,fcntl_flag|FNDELAY)<0)
                        perror("Couldn't set FLAGS"), exit(1);
                };
        };

#ifdef DEBUG
        printf("Reading socket ready\n");
#endif
return or_fd;
}

/* returns 0 when no packet read!  */
int get_packet (int rc_fd, char *buffer,
                int *TCP_UDP_start,unsigned  char *proto)
{
char help_buffer[MTU];
int pack_len;
struct IP_header *gp_IPhead;

pack_len = read(rc_fd,help_buffer,1500);
if(pack_len<0)
        {
        if(errno==EWOULDBLOCK)
                {pack_len=0;}
        else
                {perror("Read error:"); exit(1);}
        };
if(pack_len>0)
        {
        pack_len -= DEV_PREFIX;
        memcpy(buffer,help_buffer+DEV_PREFIX,pack_len);
        gp_IPhead = (struct IP_header *) buffer;
        if(proto != NULL)
                *proto = gp_IPhead->protocol;
        if(TCP_UDP_start != NULL)
                *TCP_UDP_start = (gp_IPhead->verlen & 0xF) << 2;
        }
return pack_len;
}

void wait_packet_timeout (int sig)
{
alarm(0);
WAIT_PACKET_WAIT_TIME=1;
}

int wait_packet(int wp_fd,struct sp_wait_packet *ret_values,
                char *wp_source, unsigned short wp_source_port,
                char *wp_dest, unsigned short wp_dest_port, int wp_flags,
                int wait_time)
{
char wp_buffer[1500];
struct IP_header *wp_iphead;
struct TCP_header *wp_tcphead;
unsigned long wp_sourcel, wp_destl;
int wp_tcpstart;
char wp_proto;

wp_sourcel=sp_getaddrbyname(wp_source);
wp_destl=sp_getaddrbyname(wp_dest);

WAIT_PACKET_WAIT_TIME=0;
if(wait_time!=0)
        {
        signal(SIGALRM,wait_packet_timeout);
        alarm(wait_time);
        }

while(1)
  {
  while(get_packet(wp_fd, wp_buffer, &wp_tcpstart, &wp_proto)<=0)
        {
        if (WAIT_PACKET_WAIT_TIME!=0)   {alarm(0); return -1;}
        };
  if(wp_proto == 6)
    {
    wp_iphead= (struct IP_header *) wp_buffer;
    wp_tcphead= (struct TCP_header *) (wp_buffer+wp_tcpstart);
    if( (wp_sourcel==wp_iphead->source)&&(wp_destl==wp_iphead->destination) )
      {
      if( (ntohs(wp_tcphead->source)==wp_source_port) &&
                               (ntohs(wp_tcphead->destination)==wp_dest_port) )
        {
        if( (wp_flags==0) || (ntohs(wp_tcphead->offset_flag)&wp_flags) )
          {
          ret_values->seq=ntohl(wp_tcphead->seq_nr);
          ret_values->ack=ntohl(wp_tcphead->ACK_nr);
          ret_values->flags=ntohs(wp_tcphead->offset_flag)&
                                                (URG|ACK|PSH|FIN|RST|SYN);
          ret_values->datalen = ntohs(wp_iphead->length) -
                           ((wp_iphead->verlen & 0xF) << 2) -
                            ((ntohs(wp_tcphead->offset_flag) & 0xF000) >> 10);
          alarm(0);
          return 0;
          }
        }
      }
    }
  }
/*impossible to get here.. but anyways*/
alarm(0); return -1;
}


void close_receiving (void)
{
close(rc_fd_abc123);
}

void rc_sigio (int sig)                     /* Packet handling routine */
{
char rc_buffer[1500];
char packet_id [50];
unsigned char *rc_so, *rc_dest;
struct IP_header *rc_IPhead;
struct TCP_header *rc_TCPhead;
int pack_len;

if(RC_FILTSET==0) return;

if(SP_DATA_BUSY!=0)              /* skip this packet */
        return;

pack_len = read(rc_fd_abc123,rc_buffer,1500);
rc_IPhead = (struct IP_header *) (rc_buffer + DEV_PREFIX);
if(rc_IPhead->protocol!=6) return;                          /* if not TCP */
rc_TCPhead = (struct TCP_header *) (rc_buffer + DEV_PREFIX +
                                              ((rc_IPhead->verlen & 0xF) << 2));

rc_so   = (unsigned char *) &(rc_IPhead->source);
rc_dest = (unsigned char *) &(rc_IPhead->destination);
sprintf(packet_id,"%u.%u.%u.%u.%u-%u.%u.%u.%u.%u",
              rc_so[0],rc_so[1],rc_so[2],rc_so[3],ntohs(rc_TCPhead->source),
              rc_dest[0],rc_dest[1],rc_dest[2],rc_dest[3],
              ntohs(rc_TCPhead->destination));
        
if(strcmp(packet_id,rc_filter_string)==0)
        {
        SP_DATA_BUSY=1;
        CUR_SEQ = ntohl(rc_TCPhead->seq_nr);
        CUR_ACK = ntohl(rc_TCPhead->ACK_nr);
        CUR_FLAGS = ntohs(rc_TCPhead->offset_flag);
        CUR_DATALEN = ntohs(rc_IPhead->length) -
                      ((rc_IPhead->verlen & 0xF) << 2) -
                      ((ntohs(rc_TCPhead->offset_flag) & 0xF000) >> 10);
        CUR_COUNT++;
        SP_DATA_BUSY=0;
        }
}

void set_filter (char *f_source, unsigned short f_source_port,
                 char *f_dest, unsigned short f_dest_port)
{
unsigned char *f_so, *f_des;
unsigned long f_sol, f_destl;

RC_FILTSET=0;
if(DEV_PREFIX==9999)
        fprintf(stderr,"DEV_PREFIX not set!\n"), exit(1);
f_sol   = sp_getaddrbyname(f_source);
f_destl = sp_getaddrbyname(f_dest);
f_so    = (unsigned char *) &f_sol;
f_des   = (unsigned char *) &f_destl;
sprintf(rc_filter_string,"%u.%u.%u.%u.%u-%u.%u.%u.%u.%u",
                              f_so[0],f_so[1],f_so[2],f_so[3],f_source_port,
                              f_des[0],f_des[1],f_des[2],f_des[3],f_dest_port);
RC_FILTSET=1;
}

0 个留言

发表评论

Ads