#ifndef SANCP_H #include "sancp.h" #endif /************************************************************************** **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool * ************************************************************************ * * Copyright (C) 2003 John Curry * * * * This program is distributed under the terms of version 1.0 of the * * Q Public License. See LICENSE.QPL for further details. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * ***********************************************************************/ void decode(struct cnx* nc, int len, const u_char *pkt ) { extern struct gvars gVars; u_int8_t e_hlen=14; u_int8_t ip_hlen=0; u_int8_t tcp_hlen=0; u_int16_t udp_len=0; u_int16_t ip_len=0; 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; nc->timeout=gVars.default_timeout; nc->next=NULL; nc->prev=NULL; nc->hash=0; nc->fH=0; nc->start_time=nc->last_pkt=gVars.timeptr.tv_sec; nc->limit=gVars.default_limit; // // If we don't have a pkt then perhaps we should not have been called // if(!pkt){ printf("Error decode: received empty packet\n"); return; } nc->s_total_pkts=1; nc->stats=gVars.smode?1:0; nc->realtime=gVars.rmode?1:0; nc->pcap=gVars.pmode?1:0; nc->cmode=CMODE_BOTH; /* TODO: calculate packet payload for UDP or TCP */ nc->next=NULL; nc->prev=NULL; nc->h_proto=*(u_int16_t*)(pkt + e_hlen-2); memcpy(&nc->eth_hdr,(void *)pkt,e_hlen); nc->s_total_bytes=len -(e_hlen); if(nc->h_proto == ETHPROTO_IP ) { ip_hlen=(pkt[e_hlen]&0x0F)<<2; nc->s_ip=*(u_int32_t*)(pkt + e_hlen + 12); nc->d_ip=*(u_int32_t*)(pkt + e_hlen+ 16); nc->proto=((pkt[e_hlen + 9])&0xFF); ip_len=ntohs(*(u_int16_t*)(pkt+e_hlen + 2)); nc->s_total_bytes=ip_len-ip_hlen; if(nc->proto==IPPROTO_TCP||nc->proto==IPPROTO_UDP){ nc->s_port=*(u_int16_t*)(pkt + (e_hlen + ip_hlen)); nc->d_port=*(u_int16_t *)(pkt + (e_hlen + ip_hlen + 2)); if(nc->proto==IPPROTO_TCP ){ tcp_hlen=(u_int8_t)(pkt[e_hlen + ip_hlen + 12]&0xF0)>>2; nc->s_total_bytes-=tcp_hlen; nc->tcpFlags[0]=pkt[(e_hlen + ip_hlen+ 13)]; // Look for a syn flag if((nc->tcpFlags[0]&(R_SYN))==R_SYN) { nc->os_info.ttl=(u_int8_t)pkt[e_hlen+8]; nc->os_info.len=ip_len; nc->os_info.wss=ntohs(*(u_int16_t*)(pkt + e_hlen + ip_hlen + 14)); nc->os_info.df=((pkt[e_hlen + 6]&0x40)==0x40)?1:0; #ifdef EXPERIMENTAL_TCPOPTIONS u_int16_t tcpoptlen=0; u_int16_t bytes_processed=0; int loopctr=0 u_int8_t done=0; // // THIS CODE DOES NOT PROPERLY PARSE TCPOPTIONS FOR ALL PACKETS // INFINITE LOOPS WERE POSSIBLE IN THIS PORTION OF CODE UNTIL // int loopctr WAS INTRODUCED TO LIMIT OPTIONS TO TCPOPTIONS_MAX // //tcpopt = *pkt + (e_hlen + ip_hlen + 20); // this is where we should find tcp options int tcpoptctr=(e_hlen + ip_hlen + 20); nc->os_info.wscale=0; tcpoptlen=tcp_hlen>20?(tcp_hlen - 20):0; while((bytes_processedos_info.mss=ntohs(*(u_int16_t*)(pkt+tcpoptctr+2)); tcpoptctr+=4; bytes_processed+=4; break; case TCPOPT_NOP: nc->os_info.nop=1; tcpoptctr++; bytes_processed++; break; case TCPOPT_WSCALE: nc->os_info.wscale=*(pkt+tcpoptctr+2); tcpoptctr+=3; bytes_processed+=3; break; case TCPOPT_SACKOK: nc->os_info.sack_ok=1; tcpoptctr+=2; bytes_processed+=2; break; default: bytes_processed+=*(pkt+tcpoptctr+1); tcpoptctr+=*(pkt+tcpoptctr+1); break; } loopctr++; // Bail out after 8 'options' - NEEDED UNTIL THIS CODE IS FIXED TO PROPERLY PARSE TCPOPTIONS if(loopctr>TCPOPTIONS_MAX){ done = 1; } } #endif } } else if( nc->proto==IPPROTO_UDP ) { udp_len=ntohs(*(u_int16_t*)(pkt + e_hlen + ip_hlen + 4)); nc->s_total_bytes=udp_len; } // Don't log reset packets /*if(nc->proto==6 && (pkt[(((pkt[14]&15)<<2)+27)]&4)==4){ nc->log=0; nc->collect=0; } */ } else { // non TCP/UDP packet decoding goes here if( nc->proto==IPPROTO_ICMP && gVars.log_icmp_type_code ) { nc->s_port=*(u_int8_t*)(pkt + (e_hlen + ip_hlen)); nc->d_port=*(u_int8_t *)(pkt + (e_hlen + ip_hlen + 1)); nc->s_port<<=8; nc->d_port<<=8; } } } else { // non IP packet decoding goes here } }