1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
/* Sniffit Packet Discription File */
/* - by: Brecht Claerhout */
#include "sn_config.h"
#include "sn_defines.h"
#include "sn_structs.h"
#include <netinet/in.h>
extern int PROTO_HEAD;
extern char NO_CHKSUM;
/* This routine stolen from ping.c */
unsigned short in_cksum(unsigned short *addr,int len)
{
register int nleft = len; /* leave this alone.. my opinion is that the */
register unsigned short *w = addr;
/* register is needed to make it work for both */
register int sum = 0; /* BIG and LITTLE endian machines */
unsigned short answer = 0;
/* but then again, who am I to make such statement */
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);
}
int unwrap_packet (unsigned char *sp, struct unwrap *unwrapped)
{
struct IP_header IPhead;
struct TCP_header TCPhead;
struct ICMP_header ICMPhead;
struct UDP_header UDPhead;
int i;
short int dummy; /* 2 bytes, important */
/*
printf("\n");
for(i=0;i<20;i++) printf("%X ",sp[i]);
printf("\n");
*/
memcpy(&IPhead,(sp+PROTO_HEAD),sizeof(struct IP_header));
/* IP header Conversion */
unwrapped->IP_len = (IPhead.verlen & 0xF) << 2;
unwrapped->TCP_len = 0; /* Reset structure NEEDED!!! */
unwrapped->UDP_len = 0;
unwrapped->DATA_len= 0;
unwrapped->FRAG_f = 0;
unwrapped->FRAG_nf = 0;
if(NO_CHKSUM == 0)
{
sp[PROTO_HEAD+10]=0; /* reset checksum to zero, Q&D way*/
sp[PROTO_HEAD+11]=0;
if(in_cksum((sp+PROTO_HEAD),unwrapped->IP_len) != IPhead.checksum)
{
#ifdef DEBUG_ONSCREEN
printf("Packet dropped... (invalid IP chksum)\n");
printf("%X %X (len %d)\n",in_cksum((sp+PROTO_HEAD),unwrapped->IP_len),IPhead.checksum,unwrapped->IP_len);
#endif
return NO_IP;
}
if(0)
{
#ifdef DEBUG_ONSCREEN
printf("Packet dropped... (invalid IP version)\n");
#endif
return NO_IP_4;
}
memcpy((sp+PROTO_HEAD),&IPhead,sizeof(struct IP_header));
/* restore orig buffer */
/* general programming rule */
}
#ifdef DEBUG_ONSCREEN
printf("IPheadlen: %d total length: %d\n", unwrapped->IP_len,
ntohs(IPhead.length));
#endif
dummy=ntohs(IPhead.flag_offset); dummy<<=3;
if( dummy!=0 ) /* we have offset */
{
unwrapped->FRAG_nf = 1;
}
dummy=ntohs(IPhead.flag_offset); dummy>>=13;
if( (dummy&IP_MF)&&(unwrapped->FRAG_nf==0) ) /* first frag */
{
unwrapped->FRAG_f = 1;
}
if(IPhead.protocol == TCP ) /* TCP */
{
if(unwrapped->FRAG_nf == 0) /* packet contains TCP header */
{
if( (ntohs(IPhead.length)-(unwrapped->IP_len))<20 )
{
if(unwrapped->FRAG_f==1)
{unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len);
if(unwrapped->DATA_len<0)
{unwrapped->DATA_len=0; return CORRUPT_IP;}
return TCP_FRAG_HEAD;
}
else
{return CORRUPT_IP;}
}
memcpy(&TCPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct TCP_header));
unwrapped->TCP_len = ntohs(TCPhead.offset_flag) & 0xF000;
unwrapped->TCP_len >>= 10;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->TCP_len);
/* IP options can not cause SEGFAULT */
if(unwrapped->DATA_len<0) /* Fragmented TCP options */
{
if(unwrapped->FRAG_f==1)
{unwrapped->TCP_len=0;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len);
if(unwrapped->DATA_len<0)
{unwrapped->DATA_len=0; return CORRUPT_IP;}
return TCP_FRAG_HEAD;
}
else
{return CORRUPT_IP;}
}
}
else
{
unwrapped->DATA_len = ntohs(IPhead.length) - (unwrapped->IP_len);
if(unwrapped->DATA_len<0)
{unwrapped->DATA_len=0; return CORRUPT_IP;}
}
return TCP;
}
if(IPhead.protocol == ICMP ) /* ICMP */
{
if(unwrapped->FRAG_nf == 0) /* Should contain header */
{
if( (ntohs(IPhead.length)-(unwrapped->IP_len))<4 )
{return NOT_SUPPORTED;}; /* no handling of frag headers*/
memcpy(&ICMPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct ICMP_header));
unwrapped->ICMP_len = ICMP_HEADLENGTH;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->ICMP_len);
if(unwrapped->DATA_len<0)
{
if(unwrapped->FRAG_f==1)
{unwrapped->TCP_len=0;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len);
if(unwrapped->DATA_len<0)
{unwrapped->DATA_len=0; return CORRUPT_IP;}
return NOT_SUPPORTED; /* don't handle fragmented ICMP */
}
else
{return CORRUPT_IP;}
}
return ICMP;
}
else
{
return NOT_SUPPORTED; /* don't handle fragmented ICMP */
}
}
if(IPhead.protocol == UDP ) /* UDP */
{
if(unwrapped->FRAG_nf == 0)
{
if( ((IPhead.length)-(unwrapped->IP_len))<8 )
{return NOT_SUPPORTED;}; /* don't handle frag. header */
memcpy(&UDPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct UDP_header));
unwrapped->UDP_len = UDP_HEADLENGTH;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->UDP_len);
if(unwrapped->DATA_len<0)
{
if(unwrapped->FRAG_f==1)
{unwrapped->UDP_len=0;
unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len);
if(unwrapped->DATA_len<0)
{unwrapped->DATA_len=0; return CORRUPT_IP;}
return NOT_SUPPORTED;
} /* don't handle fragmented UDP */
else
{return CORRUPT_IP;}
}
return UDP;
}
else
{
return NOT_SUPPORTED; /* don't handle fragmented UDP */
}
}
return NOT_SUPPORTED;
}
|