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)18void 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