You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
590 lines
13 KiB
590 lines
13 KiB
/*++
|
|
|
|
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)
|