|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
precomp.h
Abstract:
This header contains all the RFC constants, structure definitions used by all modules, and function declarations.
Author:
Jeffrey C. Venable, Sr. (jeffv) 01-Jun-2001
Revision History:
--*/
#pragma once
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <svcs.h>
#include <stdlib.h>
//
// TFTPD protocol-specific values, per RFC.
//
typedef enum _TFTPD_DATA_SIZE {
// RFC 2348.
TFTPD_MIN_DATA = 8,
// RFC 1350.
TFTPD_DEF_DATA = 512,
// RFC 1783 (obsoleted by RFC 2348 which says 1428).
// We implement RFC 2348, but honor RFC 1783.
TFTPD_MTU_DATA = 1432,
// RFC 2348.
TFTPD_MAX_DATA = 65464,
} TFTPD_DATA_SIZE;
typedef enum _TFTPD_BUFFER_SIZE TFTPD_BUFFER_SIZE; typedef struct _TFTPD_CONTEXT TFTPD_CONTEXT, *PTFTPD_CONTEXT;
typedef struct _TFTPD_SOCKET {
LIST_ENTRY linkage; SOCKET s; SOCKADDR_IN addr; PTFTPD_CONTEXT context; HANDLE wSelectWait; HANDLE hSelect; TFTPD_BUFFER_SIZE buffersize; TFTPD_DATA_SIZE datasize; LONG numBuffers; DWORD postedBuffers; DWORD lowWaterMark; DWORD highWaterMark;
} TFTPD_SOCKET, *PTFTPD_SOCKET;
typedef struct _TFTPD_BUFFER {
struct _internal { PTFTPD_SOCKET socket; DWORD datasize; PTFTPD_CONTEXT context; struct { SOCKADDR_IN peer; INT peerLen; DWORD bytes; DWORD flags; union { WSAOVERLAPPED overlapped; IO_STATUS_BLOCK ioStatus; }; // WSARecvMsg values:
WSAMSG msg; struct { WSACMSGHDR header; IN_PKTINFO info; } control; } io; } internal;
#pragma pack( push, 1 )
struct _message { USHORT opcode; union { struct _rrq { char data[1]; } rrq; struct _wrq { char data[1]; } wrq; struct _data { USHORT block; char data[1]; } data; struct _ack { USHORT block; } ack; struct _error { USHORT code; char error[1]; } error; struct _oack { char data[1]; } oack; }; } message; #pragma pack( pop )
} TFTPD_BUFFER, *PTFTPD_BUFFER;
typedef enum _TFTPD_BUFFER_SIZE { TFTPD_DEF_BUFFER = (FIELD_OFFSET(TFTPD_BUFFER, message.data.data) + TFTPD_DEF_DATA), TFTPD_MTU_BUFFER = (FIELD_OFFSET(TFTPD_BUFFER, message.data.data) + TFTPD_MTU_DATA), TFTPD_MAX_BUFFER = (FIELD_OFFSET(TFTPD_BUFFER, message.data.data) + TFTPD_MAX_DATA),
} TFTPD_BUFFER_SIZE;
typedef enum _TFTPD_PACKET_TYPE {
TFTPD_RRQ = 1, TFTPD_WRQ = 2, TFTPD_DATA = 3, TFTPD_ACK = 4, TFTPD_ERROR = 5, TFTPD_OACK = 6,
} TFTPD_PACKET_TYPE;
typedef enum _TFTPD_ERROR_CODE {
TFTPD_ERROR_UNDEFINED = 0, TFTPD_ERROR_FILE_NOT_FOUND = 1, TFTPD_ERROR_ACCESS_VIOLATION = 2, TFTPD_ERROR_DISK_FULL = 3, TFTPD_ERROR_ILLEGAL_OPERATION = 4, TFTPD_ERROR_UNKNOWN_TRANSFER_ID = 5, TFTPD_ERROR_FILE_EXISTS = 6, TFTPD_ERROR_NO_SUCH_USER = 7, TFTPD_ERROR_OPTION_NEGOT_FAILED = 8,
} TFTPD_ERROR_CODE;
typedef enum _TFTPD_MODE {
TFTPD_MODE_TEXT = 1, TFTPD_MODE_BINARY = 2, TFTPD_MODE_MAIL = 3,
} TFTPD_MODE;
typedef enum _TFTPD_OPTION_VALUES {
TFTPD_OPTION_BLKSIZE = 0x00000001, TFTPD_OPTION_TIMEOUT = 0x00000002, TFTPD_OPTION_TSIZE = 0x00000004,
} TFTPD_OPTION_VALUES;
typedef struct _TFTPD_CONTEXT {
LIST_ENTRY linkage; volatile LONG reference;
TFTPD_PACKET_TYPE type; SOCKADDR_IN peer; PTFTPD_SOCKET socket; DWORD options; HANDLE hFile; PCHAR filename; LARGE_INTEGER filesize; LARGE_INTEGER fileOffset; LARGE_INTEGER translationOffset; TFTPD_MODE mode; DWORD blksize; DWORD timeout; USHORT block; USHORT sorcerer; BOOL danglingCR; HANDLE hWait; HANDLE wWait; HANDLE hTimer; ULONG retransmissions; volatile LONG state;
} TFTPD_CONTEXT, *PTFTPD_CONTEXT;
typedef enum _TFTPD_STATE {
TFTPD_STATE_BUSY = 0x00000001, TFTPD_STATE_DEAD = 0x00000002,
} TFTPD_STATE;
typedef struct _TFTPD_HASH_BUCKET {
CRITICAL_SECTION cs; // #if defined(DBG)
DWORD numEntries; // #endif // defined(DBG)
LIST_ENTRY bucket;
} TFTPD_HASH_BUCKET, *PTFTPD_HASH_BUCKET;
//
// Global variables :
//
typedef struct _TFTPD_GLOBALS {
// Initialization flags :
struct _initialized { BOOL ioCS; BOOL reaperContextCS; BOOL reaperSocketCS; BOOL winsock; BOOL contextHashTable; } initialized;
// Service control :
struct _service { SERVICE_STATUS_HANDLE hStatus; SERVICE_STATUS status; HANDLE hEventLogSource; volatile DWORD shutdown; } service;
// Service private heap :
HANDLE hServiceHeap;
// Registry parameters :
struct _parameters {
DWORD hashEntries; ULONG lowWaterMark; ULONG highWaterMark; DWORD maxRetries; CHAR rootDirectory[MAX_PATH]; CHAR validClients[16]; // IPv4 "xxx.xxx.xxx.xxx"
CHAR validReadFiles[MAX_PATH]; CHAR validMasters[16]; // IPv4 "xxx.xxx.xxx.xxx"
CHAR validWriteFiles[MAX_PATH]; #if defined(DBG)
DWORD debugFlags; #endif // defined(DBG)
} parameters;
// I/O mechanisms (sockets) :
struct _io {
CRITICAL_SECTION cs; TFTPD_SOCKET master; TFTPD_SOCKET def; TFTPD_SOCKET mtu; TFTPD_SOCKET max; HANDLE hTimerQueue; LONG numContexts; LONG numBuffers;
} io;
struct _hash {
PTFTPD_HASH_BUCKET table; #if defined(DBG)
DWORD numEntries; #endif // defined(DBG)
} hash;
struct _fp {
LPFN_WSARECVMSG WSARecvMsg;
} fp;
struct _reaper {
CRITICAL_SECTION contextCS; LIST_ENTRY leakedContexts; DWORD numLeakedContexts;
CRITICAL_SECTION socketCS; LIST_ENTRY leakedSockets; DWORD numLeakedSockets;
} reaper;
#if defined(DBG)
struct _performance {
DWORD maxClients; DWORD timeouts; DWORD drops; DWORD privateSockets; DWORD sorcerersApprentice;
} performance; #endif // defined(DBG)
} TFTPD_GLOBALS, *PTFTPD_GLOBALS;
extern TFTPD_GLOBALS globals;
//
// Useful macros
//
#define TFTPD_MIN_RECEIVED_DATA \
(FIELD_OFFSET(TFTPD_BUFFER, message.data.data) - \ FIELD_OFFSET(TFTPD_BUFFER, message.opcode))
#define TFTPD_DATA_AMOUNT_RECEIVED(buffer) \
(buffer->internal.io.bytes - TFTPD_MIN_RECEIVED_DATA) \
#define TFTPD_ACK_SIZE \
(FIELD_OFFSET(TFTPD_BUFFER, message.ack.block) - \ FIELD_OFFSET(TFTPD_BUFFER, message.opcode) + \ sizeof(buffer->message.ack))
//
// Function prototypes : context.c
//
PTFTPD_CONTEXT TftpdContextAllocate( );
BOOL TftpdContextAdd( PTFTPD_CONTEXT context );
DWORD TftpdContextAddReference( PTFTPD_CONTEXT context );
PTFTPD_CONTEXT TftpdContextAquire( PSOCKADDR_IN addr );
DWORD TftpdContextRelease( PTFTPD_CONTEXT context );
BOOL TftpdContextUpdateTimer( PTFTPD_CONTEXT context );
BOOL TftpdContextFree( PTFTPD_CONTEXT context );
void TftpdContextKill( PTFTPD_CONTEXT context );
void TftpdContextLeak( PTFTPD_CONTEXT context );
//
// Function prototypes : io.c
//
PTFTPD_BUFFER TftpdIoAllocateBuffer( PTFTPD_SOCKET socket );
PTFTPD_BUFFER TftpdIoSwapBuffer( PTFTPD_BUFFER buffer, PTFTPD_SOCKET socket );
void TftpdIoFreeBuffer( PTFTPD_BUFFER buffer );
DWORD TftpdIoPostReceiveBuffer( PTFTPD_SOCKET socket, PTFTPD_BUFFER buffer );
void TftpdIoInitializeSocketContext( PTFTPD_SOCKET socket, PSOCKADDR_IN addr, PTFTPD_CONTEXT context );
BOOL TftpdIoAssignSocket( PTFTPD_CONTEXT context, PTFTPD_BUFFER buffer );
BOOL TftpdIoDestroySocketContext( PTFTPD_SOCKET context );
void TftpdIoSendErrorPacket( PTFTPD_BUFFER buffer, TFTPD_ERROR_CODE error, char *reason );
PTFTPD_BUFFER TftpdIoSendPacket( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdIoSendOackPacket( PTFTPD_BUFFER buffer );
//
// Function prototypes : log.c
//
void TftpdLogEvent( WORD type, DWORD request, WORD numStrings );
//
// Function prototypes : process.c
//
BOOL TftpdProcessComplete( PTFTPD_BUFFER buffer );
void CALLBACK TftpdProcessTimeout( PTFTPD_CONTEXT context, BOOLEAN );
void TftpdProcessError( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdProcessReceivedBuffer( PTFTPD_BUFFER buffer );
//
// Function prototypes: read.c
//
PTFTPD_BUFFER TftpdReadResume( PTFTPD_BUFFER buffer );
DWORD WINAPI TftpdReadQueuedResume( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdReadAck( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdReadRequest( PTFTPD_BUFFER buffer );
//
// Function prototypes : service.c
//
void TftpdServiceAttemptCleanup( );
//
// Function prototypes : util.c
//
BOOL TftpdUtilGetFileModeAndOptions( PTFTPD_CONTEXT context, PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdUtilSendOackPacket( PTFTPD_BUFFER buffer );
BOOL TftpdUtilMatch( const char *const p, const char *const q );
//
// Function prototypes: write.c
//
PTFTPD_BUFFER TftpdWriteSendAck( PTFTPD_BUFFER buffer );
DWORD WINAPI TftpdWriteQueuedResume( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdWriteData( PTFTPD_BUFFER buffer );
PTFTPD_BUFFER TftpdWriteRequest( PTFTPD_BUFFER buffer );
//
// Debug
//
#if defined(DBG)
void __cdecl TftpdOutputDebug(ULONG flag, char *format, ...);
#define TFTPD_DEBUG(x) TftpdOutputDebug x
#define TFTPD_DBG_SERVICE 0x00000001
#define TFTPD_DBG_IO 0x00000002
#define TFTPD_DBG_PROCESS 0x00000004
#define TFTPD_DBG_CONTEXT 0x00000008
#define TFTPD_TRACE_SERVICE 0x00010000
#define TFTPD_TRACE_IO 0x00020000
#define TFTPD_TRACE_PROCESS 0x00040000
#define TFTPD_TRACE_CONTEXT 0x00080000
#else
#define TFTPD_DEBUG(x)
#endif // defined(DBG)
|