From: pavel Date: Sun, 13 Jul 2003 21:23:55 +0000 (+0000) Subject: r30: Winnbd code from Folkert van Heusden X-Git-Url: http://git.alex.org.uk r30: Winnbd code from Folkert van Heusden --- diff --git a/winnbd/license.txt b/winnbd/license.txt new file mode 100644 index 0000000..046f4c6 --- /dev/null +++ b/winnbd/license.txt @@ -0,0 +1,2 @@ +The license of this program can be obtained from: http://www.vanheusden.com/license.txt +It is actually the GNU Public License. diff --git a/winnbd/nbdsrvr.cpp b/winnbd/nbdsrvr.cpp new file mode 100644 index 0000000..fc38e70 --- /dev/null +++ b/winnbd/nbdsrvr.cpp @@ -0,0 +1,359 @@ +#include +#include + +int portnr; +char *filename; + +int READ(SOCKET sh, UCHAR *whereto, int howmuch) +{ + int pnt = 0; + +#ifdef _DEBUG + printf("read: %d bytes requested\n", howmuch); +#endif + + while(howmuch > 0) + { + int nread = recv(sh, (char *)&whereto[pnt], howmuch, 0); + if (nread == 0) + break; + if (nread == SOCKET_ERROR) + { + fprintf(stderr, "Connection dropped. Error: %d\n", WSAGetLastError()); + break; + } + + pnt += nread; + howmuch -= nread; + } + + return pnt; +} + +int WRITE(SOCKET sh, UCHAR *wherefrom, int howmuch) +{ + int pnt = 0; + + while(howmuch > 0) + { + int nwritten = send(sh, (char *)&wherefrom[pnt], howmuch, 0); + if (nwritten == 0) + break; + if (nwritten == SOCKET_ERROR) + { + fprintf(stderr, "Connection dropped. Error: %d\n", WSAGetLastError()); + break; + } + + pnt += nwritten; + howmuch -= nwritten; + } + + return pnt; +} + +BOOL getu32(SOCKET sh, ULONG *val) +{ + UCHAR buffer[4]; + + if (READ(sh, buffer, 4) != 4) + return FALSE; + + *val = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]); + + return TRUE; +} + +BOOL putu32(SOCKET sh, ULONG value) +{ + UCHAR buffer[4]; + + buffer[0] = (value >> 24) & 255; + buffer[1] = (value >> 16) & 255; + buffer[2] = (value >> 8) & 255; + buffer[3] = (value ) & 255; + + if (WRITE(sh, buffer, 4) != 4) + return FALSE; + else + return TRUE; +} + +DWORD WINAPI draad(LPVOID data) +{ + SOCKET sockh = (SOCKET)data; + HANDLE fh; + char neg = 1; + + // open file 'filename' + fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (fh == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "Error opening file %s: %d\n", filename, GetLastError()); + } + + for(;fh != INVALID_HANDLE_VALUE;) + { + UCHAR handle[9]; + ULONG magic, from, len, type, dummy; + + /* negotiating time? */ + if (neg) + { + printf("Negotiating...\n"); + if (WRITE(sockh, (unsigned char *)"NBDMAGIC", 8) != 8) + { + fprintf(stderr, "Failed to send magic string\n"); + break; + } + + // some other magic value + unsigned char magic[8]; + magic[0] = 0x00; + magic[1] = 0x00; + magic[2] = 0x42; + magic[3] = 0x02; + magic[4] = 0x81; + magic[5] = 0x86; + magic[6] = 0x12; + magic[7] = 0x53; + if (WRITE(sockh, magic, 8) != 8) + { + fprintf(stderr, "Failed to send 2nd magic string\n"); + break; + } + + // send size of file + unsigned char exportsize[8]; + DWORD fsize = GetFileSize(fh, NULL); + if (fsize == 0xFFFFFFFF) + { + fprintf(stderr, "Failed to get filesize. Error: %d\n", GetLastError()); + break; + } + exportsize[7] = (fsize ) & 255; + exportsize[6] = (fsize >> 8) & 255; + exportsize[5] = (fsize >> 16) & 255; + exportsize[4] = (fsize >> 24) & 255; + exportsize[3] = (fsize >> 32) & 255; + exportsize[2] = (fsize >> 40) & 255; + exportsize[1] = (fsize >> 48) & 255; + exportsize[0] = (fsize >> 56) & 255; +#ifdef _DEBUG + printf("File is %ld bytes\n", fsize); +#endif + if (WRITE(sockh, exportsize, 8) != 8) + { + fprintf(stderr, "Failed to send filesize\n"); + break; + } + + // send a couple of zeros */ + unsigned char buffer[128]; + memset(buffer, 0x00, 128); + if (WRITE(sockh, buffer, 128) != 128) + { + fprintf(stderr, "Failed to send a couple of 0x00s\n"); + break; + } + + printf("Started!\n"); + neg = 0; + } + + if (getu32(sockh, &magic) == FALSE || // 0x12560953 + getu32(sockh, &type) == FALSE || // 0=read,1=write + READ(sockh, handle, 8) != 8 || // handle + getu32(sockh, &dummy) == FALSE || // ... high word of offset + getu32(sockh, &from) == FALSE || // offset + getu32(sockh, &len) == FALSE) // length + { + fprintf(stderr, "Failed to read from socket\n"); + break; + } + +#ifdef _DEBUG + handle[8] = 0x00; + printf("Magic: %lx\n", magic); + printf("Offset: %ld\n", from); + printf("Len: %ld\n", len); + printf("Handle: %s\n", handle); + printf("Req.type: %ld (%s)\n\n", type, type?"write":"read"); +#endif + + // verify protocol + if (magic != 0x25609513) + { + fprintf(stderr, "Unexpected protocol version! (got: %lx, expected: 0x25609513)\n", magic); + break; + } + + // seek to 'from' + if (SetFilePointer(fh, from, NULL, FILE_BEGIN) == 0xFFFFFFFF) + { + fprintf(stderr, "Error seeking in file %s to position %d: %d\n", filename, from, GetLastError()); + break; + } + + if (type == 1) // write + { + while(len > 0) + { + DWORD dummy; + UCHAR buffer[32768]; + // read from socket + int nb = recv(sockh, (char *)buffer, min(len, 32768), 0); + if (nb == 0) + break; + + // write to file; + if (WriteFile(fh, buffer, nb, &dummy, NULL) == 0) + { + fprintf(stderr, "Failed to write to %s: %d\n", filename, GetLastError()); + break; + } + if (dummy != nb) + { + fprintf(stderr, "Failed to write to %s: %d (written: %d, requested to write: %d)\n", filename, GetLastError(), dummy, nb); + break; + } + + len -= nb; + } + if (len) // connection was closed + { + fprintf(stderr, "Connection was dropped while receiving data\n"); + break; + } + + // send 'ack' + if (putu32(sockh, 0x67446698) == FALSE || + putu32(sockh, 0) == FALSE || + WRITE(sockh, handle, 8) != 8) + { + fprintf(stderr, "Failed to send through socket\n"); + break; + } + } + else if (type == 0) + { + // send 'ack' + if (putu32(sockh, 0x67446698) == FALSE || + putu32(sockh, 0) == FALSE || + WRITE(sockh, handle, 8) != 8) + { + fprintf(stderr, "Failed to send through socket\n"); + break; + } + + while(len > 0) + { + DWORD dummy; + UCHAR buffer[32768]; + int nb = min(len, 32768); + int pnt = 0; + + // read nb to buffer; + if (ReadFile(fh, buffer, nb, &dummy, NULL) == 0) + { + fprintf(stderr, "Failed to read from %s: %d\n", filename, GetLastError()); + break; + } + if (dummy != nb) + { + fprintf(stderr, "Failed to read from %s: %d\n", filename, GetLastError()); + break; + } + + // send through socket + if (WRITE(sockh, buffer, nb) != nb) // connection was closed + { + fprintf(stderr, "Connection dropped while sending block\n"); + break; + } + + len -= nb; + } + if (len) // connection was closed + break; + } + else + { + printf("Unexpected commandtype: %d\n", type); + break; + } + } + + // close file + if (CloseHandle(fh) == 0) + { + fprintf(stderr, "Failed to close handle: %d\n", GetLastError()); + } + + closesocket(sockh); + + ExitThread(0); + + return 0; +} + +int main(int argc, char *argv[]) +{ + SOCKET newconnh; + WSADATA WSAData; + + printf("nbdsrvr v0.1, (C) 2003 by folkert@vanheusden.com\n"); + + if (argc != 3) + { + fprintf(stderr, "Usage: %s file portnr\n", argv[0]); + return 1; + } + filename = argv[1]; + portnr = atoi(argv[2]); + + // initialize WinSock library + (void)WSAStartup(0x101, &WSAData); + + // create listener socket + newconnh= socket(AF_INET, SOCK_STREAM, 0); + if (newconnh == INVALID_SOCKET) + return -1; + + // bind + struct sockaddr_in ServerAddr; + int ServerAddrLen; + ServerAddrLen = sizeof(ServerAddr); + memset((char *)&ServerAddr, '\0', ServerAddrLen); + ServerAddr.sin_family = AF_INET; + ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY); + ServerAddr.sin_port = htons(portnr); + if (bind(newconnh, (struct sockaddr *)&ServerAddr, ServerAddrLen) == -1) + return -1; + + // listen + if (listen(newconnh, 5) == -1) + return -1; + + for(;;) + { + SOCKET clienth; + struct sockaddr_in clientaddr; + int clientaddrlen; + + clientaddrlen = sizeof(clientaddr); + + /* accept a connection */ + clienth = accept(newconnh, (struct sockaddr *)&clientaddr, &clientaddrlen); + + if (clienth != INVALID_SOCKET) + { + printf("Connection made with %s\n", inet_ntoa(clientaddr.sin_addr)); + + DWORD tid; + HANDLE th = CreateThread(NULL, 0, draad, (void *)clienth, 0, &tid); + } + } + + return 0; +} diff --git a/winnbd/nbdsrvr.dsp b/winnbd/nbdsrvr.dsp new file mode 100644 index 0000000..9909542 --- /dev/null +++ b/winnbd/nbdsrvr.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="nbdsrvr" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=nbdsrvr - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "nbdsrvr.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nbdsrvr.mak" CFG="nbdsrvr - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nbdsrvr - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "nbdsrvr - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "nbdsrvr - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "nbdsrvr - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "nbdsrvr - Win32 Release" +# Name "nbdsrvr - Win32 Debug" +# Begin Source File + +SOURCE=.\nbdsrvr.cpp +# End Source File +# End Target +# End Project diff --git a/winnbd/nbdsrvr.dsw b/winnbd/nbdsrvr.dsw new file mode 100644 index 0000000..18f4634 --- /dev/null +++ b/winnbd/nbdsrvr.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "nbdsrvr"=.\nbdsrvr.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/winnbd/readme.txt b/winnbd/readme.txt new file mode 100644 index 0000000..d7c6a49 --- /dev/null +++ b/winnbd/readme.txt @@ -0,0 +1,31 @@ +nbdsrvr is (C) 2003 by folkert@vanheusden.com +New versions can be obtained from: +http://www.vanheusden.com/ (browse to the +"microsoft windows software" section). + +Usage: + +nbdsrvr filename portnumber + +filename must be an image of a filesystem or +whatever kind of device you whish to use. Can +also be an empty file. +For example, create an empty file of 10MB +called "image.dat" +Then: +nbdsrvr image.dat 9000 +On your linux-box: +nbd-client hostname 9000 /dev/ndX +hostname is the hostname of your windows-box, +/dev/ndX is the device you want to couple the +image to. +After that, you could create a filesystem on +this image: on your Linux-box, type: +mke2fs /dev/ndX +and then mount it: +mount /dev/ndX /mnt + +Good luck! + + +-- Folkert van Heusden, 2003/07/13, 21:59