1 #ifndef SANCP_H
2 #include "sancp.h"
3 #endif
4 /**************************************************************************
5  **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool
6  * ************************************************************************
7  * * Copyright (C) 2003 John Curry <john.curry@metre.net>
8  * *
9  * * This program is distributed under the terms of version 1.0 of the
10  * * Q Public License.  See LICENSE.QPL for further details.
11  * *
12  * * This program is distributed in the hope that it will be useful,
13  * * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  * *
16  * ***********************************************************************/
17 
decode(struct cnx * nc,int len,const u_char * pkt)18 void decode(struct cnx* nc, int len, const u_char *pkt )
19 {
20 	extern struct gvars gVars;
21 	u_int8_t e_hlen=14;
22 	u_int8_t ip_hlen=0;
23 	u_int8_t tcp_hlen=0;
24 	u_int16_t udp_len=0;
25 	u_int16_t ip_len=0;
26 
27 	nc->d_total_pkts=nc->s_ip=nc->d_ip=nc->free=nc->proto=nc->s_port=nc->d_port=nc->d_total_bytes=nc->collected=0;
28 	nc->timeout=gVars.default_timeout;
29 	nc->next=NULL;
30 	nc->prev=NULL;
31 	nc->hash=0;
32 	nc->fH=0;
33 	nc->start_time=nc->last_pkt=gVars.timeptr.tv_sec;
34 	nc->limit=gVars.default_limit;
35         //
36         // If we don't have a pkt then perhaps we should not have been called
37         //
38         if(!pkt){
39           printf("Error decode: received empty packet\n");
40           return;
41         }
42 	nc->s_total_pkts=1;
43 	nc->stats=gVars.smode?1:0;
44 	nc->realtime=gVars.rmode?1:0;
45 	nc->pcap=gVars.pmode?1:0;
46 	nc->cmode=CMODE_BOTH;
47 	/* TODO: calculate packet payload for UDP or TCP */
48 	nc->next=NULL;
49 	nc->prev=NULL;
50 	nc->h_proto=*(u_int16_t*)(pkt + e_hlen-2);
51 	memcpy(&nc->eth_hdr,(void *)pkt,e_hlen);
52 	nc->s_total_bytes=len -(e_hlen);
53 	if(nc->h_proto == ETHPROTO_IP ) {
54 	    ip_hlen=(pkt[e_hlen]&0x0F)<<2;
55    	    nc->s_ip=*(u_int32_t*)(pkt + e_hlen + 12);
56 	    nc->d_ip=*(u_int32_t*)(pkt + e_hlen+ 16);
57 	    nc->proto=((pkt[e_hlen + 9])&0xFF);
58 	    ip_len=ntohs(*(u_int16_t*)(pkt+e_hlen + 2));
59 	    nc->s_total_bytes=ip_len-ip_hlen;
60 	    if(nc->proto==IPPROTO_TCP||nc->proto==IPPROTO_UDP){
61 		nc->s_port=*(u_int16_t*)(pkt + (e_hlen + ip_hlen));
62 		nc->d_port=*(u_int16_t *)(pkt + (e_hlen + ip_hlen + 2));
63 		if(nc->proto==IPPROTO_TCP ){
64 			tcp_hlen=(u_int8_t)(pkt[e_hlen + ip_hlen + 12]&0xF0)>>2;
65 			nc->s_total_bytes-=tcp_hlen;
66 			nc->tcpFlags[0]=pkt[(e_hlen + ip_hlen+ 13)];
67 			// Look for a syn flag
68 			if((nc->tcpFlags[0]&(R_SYN))==R_SYN)
69 			{
70 				nc->os_info.ttl=(u_int8_t)pkt[e_hlen+8];
71 				nc->os_info.len=ip_len;
72 				nc->os_info.wss=ntohs(*(u_int16_t*)(pkt + e_hlen + ip_hlen + 14));
73 				nc->os_info.df=((pkt[e_hlen + 6]&0x40)==0x40)?1:0;
74 
75 #ifdef EXPERIMENTAL_TCPOPTIONS
76                                u_int16_t tcpoptlen=0;
77                                u_int16_t bytes_processed=0;
78                                int loopctr=0
79                                u_int8_t done=0;
80 
81                                //
82                                //  THIS CODE DOES NOT PROPERLY PARSE TCPOPTIONS FOR ALL PACKETS
83                                //  INFINITE LOOPS WERE POSSIBLE IN THIS PORTION OF CODE UNTIL
84                                //  int loopctr WAS INTRODUCED TO LIMIT OPTIONS TO TCPOPTIONS_MAX
85                                //
86                                //tcpopt = *pkt + (e_hlen + ip_hlen + 20);  // this is where we should find tcp options
87 
88                                 int tcpoptctr=(e_hlen + ip_hlen + 20);
89 
90                                 nc->os_info.wscale=0;
91 
92 				tcpoptlen=tcp_hlen>20?(tcp_hlen - 20):0;
93 
94 				while((bytes_processed<tcpoptlen) && !done)
95 				{
96 
97 					switch(*(pkt+tcpoptctr))
98 					{
99 						case TCPOPT_EOL:
100 							done=1;
101 							break;
102 						case TCPOPT_MAXSEG:
103 							nc->os_info.mss=ntohs(*(u_int16_t*)(pkt+tcpoptctr+2));
104 							tcpoptctr+=4;
105 							bytes_processed+=4;
106 							break;
107 						case TCPOPT_NOP:
108 							nc->os_info.nop=1;
109 							tcpoptctr++;
110 							bytes_processed++;
111 							break;
112 						case TCPOPT_WSCALE:
113 							nc->os_info.wscale=*(pkt+tcpoptctr+2);
114 							tcpoptctr+=3;
115 							bytes_processed+=3;
116 							break;
117 						case TCPOPT_SACKOK:
118 							nc->os_info.sack_ok=1;
119 							tcpoptctr+=2;
120 							bytes_processed+=2;
121 							break;
122 						default:
123 							bytes_processed+=*(pkt+tcpoptctr+1);
124 							tcpoptctr+=*(pkt+tcpoptctr+1);
125 
126 							break;
127 					}
128 					loopctr++;
129 					// Bail out after 8 'options' - NEEDED UNTIL THIS CODE IS FIXED TO PROPERLY PARSE TCPOPTIONS
130 					if(loopctr>TCPOPTIONS_MAX){ done = 1; }
131 				}
132 #endif
133 			}
134 		}
135 		else if( nc->proto==IPPROTO_UDP )
136 		{
137 			udp_len=ntohs(*(u_int16_t*)(pkt + e_hlen + ip_hlen + 4));
138 			nc->s_total_bytes=udp_len;
139 		}
140 		// Don't log reset packets
141 		/*if(nc->proto==6 && (pkt[(((pkt[14]&15)<<2)+27)]&4)==4){
142 			nc->log=0;
143 			nc->collect=0;
144 		}
145 		*/
146 	    }
147 	    else
148 	    {
149 	    // non TCP/UDP packet decoding goes here
150 		if( nc->proto==IPPROTO_ICMP && gVars.log_icmp_type_code )
151 		{
152 			nc->s_port=*(u_int8_t*)(pkt + (e_hlen + ip_hlen));
153 			nc->d_port=*(u_int8_t *)(pkt + (e_hlen + ip_hlen + 1));
154 			nc->s_port<<=8;
155 			nc->d_port<<=8;
156 		}
157 	    }
158 	}
159         else
160         {
161         // non IP packet decoding goes here
162         }
163 
164 
165 }
166 
167