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