/* Socks Server 5 * Copyright (C) 2002 - 2006 by Matteo Ricchetti - * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * 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. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include"SS5Main.h" #include"SS5Mod_dump.h" S5RetCode InitModule( struct _module *m ) { m->AddDump = AddDump; m->FreeDump = FreeDump; m->GetDump = GetDump; m->OpenDump = OpenDump; m->WritingDump = WritingDump; m->CloseDump = CloseDump; return OK; } S5RetCode WritingDump( FILE *df, struct _SS5ProxyData *pd, unsigned int dumpMode ) { char headerTitle[128]; static unsigned int tx=0; static unsigned int rx=0; /* * TX */ if( pd->Fd == 0 ) { if( (dumpMode == TX) || (dumpMode == RTX) ) { if( tx == 0 ) { sprintf(headerTitle,"\n------------------------------ TX SEGMENT ------------------------------\n"); fwrite(headerTitle,sizeof(char),strlen(headerTitle),df); tx++; rx = 0; } fwrite(pd->Recv,sizeof(char),pd->TcpRBufLen,df); } } /* RX */ else { if( (dumpMode == RX) || (dumpMode == RTX) ) { if( rx == 0 ) { sprintf(headerTitle,"\n------------------------------ RX SEGMENT ------------------------------\n"); fwrite(headerTitle,sizeof(char),strlen(headerTitle),df); rx++; tx = 0; } fwrite(pd->Recv,sizeof(char),pd->TcpRBufLen,df); } } return OK; } S5RetCode OpenDump( FILE **df, struct _SS5AuthInfo *ai ) { char logString[128]; char dumpFileName[64]; char timeLog[32]; pid_t pid; time_t now = time(NULL); /* * Get child/thread pid */ if( NOTTHREADED() ) pid=getpid(); else pid=(unsigned int)pthread_self(); strftime(timeLog,sizeof(timeLog),"%d-%b-%Y-%H-%M-%S",localtime(&now)); sprintf(dumpFileName,"%s/ss5.%s.%u.%s.trc",S5TracePath,timeLog,pid,ai->Username); if( (*df = fopen(dumpFileName,"wb")) == NULL ) { ERRNO(pid) return ERR; } else return OK; } S5RetCode CloseDump( FILE *df ) { fflush(df); fclose(df); return OK; } /* ***************************** HASH for DUMP **************************** */ inline S5Limit S5DumpHash( unsigned long int da, unsigned int dp ) { register int idx; register int len; register long int hashVal = 0; char s[32]; snprintf(s,sizeof(s) - 1,"%lu%u",da,dp); len = strlen(s); for(idx = 0; idx < len; idx++) hashVal = 37*hashVal + s[idx]; hashVal %= MAXDUMPLIST; if(hashVal < 0) hashVal += MAXDUMPLIST; return hashVal; } S5RetCode GetDump(unsigned long int da, unsigned int dp, struct _SS5DumpInfo *di) { register unsigned int index,nm; register unsigned long int n_da; struct _S5DumpNode *node; for(nm=0;nm<=32;nm++) { if( nm < 32) n_da=((da >> nm) << nm); else n_da=0; index=S5DumpHash( n_da, dp ); if( S5DumpList[index]!= NULL ) { node=S5DumpList[index]; do { if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (node->DstPort == dp) ) { di->DumpMode=node->DumpMode; return OK; } node=node->next; } while(node != NULL ); } } for(nm=0;nm<=32;nm++) { if( nm < 32) n_da=((da >> nm) << nm); else n_da=0; index=S5DumpHash( n_da, 0 ); if( S5DumpList[index]!= NULL ) { node=S5DumpList[index]; do { if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) ) { di->DumpMode=node->DumpMode; return OK; } node=node->next; } while(node != NULL ); } } return ERR; } S5RetCode AddDump(unsigned long int da, unsigned long int dp, unsigned int dumpMode, unsigned int mask ) { int index; struct _S5DumpNode *node; if( dp > 65535 ) index=S5DumpHash( da, 0 ); else index=S5DumpHash( da, dp ); if( _tmp_S5DumpList[index]== NULL ) { _tmp_S5DumpList[index]=(struct _S5DumpNode *)calloc(1,sizeof(struct _S5DumpNode)); _tmp_S5DumpList[index]->Mask=mask; _tmp_S5DumpList[index]->DstAddr=da; if( dp > 65535 ) { _tmp_S5DumpList[index]->DstPort=0; _tmp_S5DumpList[index]->DstRangeMax=dp; _tmp_S5DumpList[index]->DstRangeMax >>= 16; _tmp_S5DumpList[index]->DstRangeMax <<= 16; _tmp_S5DumpList[index]->DstRangeMin = dp - _tmp_S5DumpList[index]->DstRangeMax; _tmp_S5DumpList[index]->DstRangeMax >>= 16; } else _tmp_S5DumpList[index]->DstPort=dp; _tmp_S5DumpList[index]->DumpMode=dumpMode; _tmp_S5DumpList[index]->next=NULL; } else { node=_tmp_S5DumpList[index]; while( node->next != NULL ){ node=node->next; } node->next=(struct _S5DumpNode *)calloc(1,sizeof(struct _S5DumpNode)); node->next->Mask=mask; node->next->DstAddr=da; if( dp > 65535 ) { node->next->DstPort=0; node->next->DstRangeMax=dp; node->next->DstRangeMax >>= 16; node->next->DstRangeMax <<= 16; node->next->DstRangeMin = dp - node->next->DstRangeMax; node->next->DstRangeMax >>= 16; } else node->next->DstPort=dp; node->next->DumpMode=dumpMode; node->next->next=NULL; } return OK; } S5RetCode FreeDump( struct _S5DumpNode **node ) { struct _S5DumpNode *lnode; struct _S5DumpNode *lnode_prev=NULL; lnode=*node; if( lnode != NULL ) { do { while( lnode->next != NULL ) { lnode_prev=lnode; lnode=lnode->next; } free(lnode); if( lnode_prev != NULL ) { lnode_prev->next=NULL; lnode=lnode_prev; lnode_prev=NULL; } else lnode=NULL; } while( (lnode) != NULL ); } *node=NULL; return OK; } S5RetCode S5BrowseDumpList( struct _S5DumpNode *node ) { struct _S5DumpNode *lnode; int found=0; lnode=node; do { if(lnode != NULL ) { printf("%lu %u %lu %u\f", lnode->DstAddr,lnode->Mask,lnode->DstPort,lnode->DumpMode); lnode=lnode->next; found++; } } while( lnode != NULL ); return found; }