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