#include #include #include #include #include #include #include "nu_header.h" static void bailout( char *reason ); static mainsock = -1; static childsock = -1; static void netbios_read( SMB_HEADER **buf) { BYTE bytes[4]; ssize_t bytesread, bytestoread; if( read( childsock, bytes, 4) < 4 ) bailout( "Short read." ); bytestoread = htons(*(WORD*)(2+bytes)); if( (*buf = (SMB_HEADER*)realloc( *buf, 4 + bytestoread )) == NULL) bailout( "Out of memory"); *(DWORD*)*buf = *(DWORD*)bytes; bytesread = read( childsock, ((BYTE*)buf) + 4, bytestoread); if( bytesread != bytestoread ) bailout( "Short read." ); } static void netbios_write( BYTE command, BYTE *buf, WORD size ) { BYTE netbios_header[4] = { command, 0, size >> 8, size & 255 }; if( write( childsock, netbios_header, 4 ) <= 0 || write( childsock, buf, size ) < 0 ) bailout( "Write failed." ); } static void child( ) { SMB_HEADER *inpacket = NULL; DWORD bytesread; /* I should spare that code... */ if( mainsock != -1 ) { close( mainsock ); mainsock = -1; } /* Try to answer first netbios packet */ netbios_read( &inpacket ); if( inpacket->netbios_command != 0x81 ) bailout( "No session request"); netbios_write( 0x82, NULL, 0 ); while( 1 ) { netbios_read( &inpacket ); if( inpacket->netbios_command != 0 ) bailout( "Unhandled netbios command" ); if( inpacket->Protocol != SMB_HEADER_PROTOCOL_MAGIC ) bailout( "Protocol identifier mismatch"); switch( inpacket->Command ) { case SMB_COM_NEGOTIATE: { BYTE outblock[5] = { 0xff,0,0,0,0 }; netbios_write( 0, outblock, sizeof( outblock )); break; } default: { fprintf( stderr, "Got message: %02X\n", inpacket->Command ); break; } } } /* End main loop */ } void sigint( int reason ) { bailout( "User interrupt." ); } int main() { struct sockaddr_in sa; int l=1; signal( SIGINT, sigint); bzero( &sa, sizeof( sa)); sa.sin_family = PF_INET; sa.sin_port = htons( 139 ); sa.sin_addr.s_addr = INADDR_ANY; if( ( mainsock = socket( PF_INET, SOCK_STREAM, 0) ) == -1) bailout( "Could not open socket"); setsockopt( mainsock, SOL_SOCKET, SO_REUSEPORT, &l, sizeof(l)); if( bind( mainsock, (struct sockaddr *)&sa, sizeof( sa)) != 0) bailout( "Could not bind socket"); if( listen( mainsock, 1024) != 0 ) bailout( "Could not make socket listen"); while( 1 ) { struct sockaddr otherend; int size = sizeof( otherend ); if( ( childsock = accept( mainsock, &otherend, &size) ) == -1) bailout( "Socket Broke."); if (!fork()) child( ); } } /* Graceful exit. */ static void bailout( char *reason) { fputs( reason, stderr); fputs( "\nCleaning up.\n", stderr); if( mainsock != -1 ) close( mainsock ); if( childsock != -1 ) { shutdown( childsock, SHUT_RDWR); close( childsock ); } exit( 0 ); }