309 lines
8.0 KiB
Plaintext
309 lines
8.0 KiB
Plaintext
=========
|
|
General
|
|
=========
|
|
|
|
- We don't support any protocol other than TCP/IP.
|
|
- We're strictly a client-side implementation.
|
|
- Overall priorities are:
|
|
code simplicity / compactness
|
|
performance
|
|
resource consumption
|
|
- Adjustable configuration parameters are stored
|
|
in global variables with 'cfg' name prefix.
|
|
|
|
===================
|
|
Buffer management
|
|
===================
|
|
|
|
- There are two kinds of packets:
|
|
regular packets allocated out of pool memory, and
|
|
DMA packets allocated inside contiguous physical page
|
|
- We maintain a few lookaside lists for smaller-sized regular packets.
|
|
- DMA packets are fixed size, ~half a page and large enough
|
|
to hold an Ethernet frame.
|
|
- When packets are passed around, the callee takes over the ownership
|
|
of the packet. When the callee is done with the packet, it calls
|
|
CompletePacket to dispose of it. Exception to this rule will be
|
|
explicitly noted.
|
|
|
|
============
|
|
Interfaces
|
|
============
|
|
|
|
- Each interface has only one IP address.
|
|
- Interfaces supported:
|
|
Ethernet
|
|
PPP over USB serial modem
|
|
PPP over Ethernet
|
|
loopback
|
|
- Ethernet:
|
|
receive both Ethernet and IEEE 802.3 frames
|
|
send Ethernet frames only
|
|
assume we hear our own broadcast/multicast transmissions
|
|
- Default ARP configuration parameters:
|
|
positive ARP cache entry timeout = 10min
|
|
negative ARP cache entry timeout = 1min
|
|
ARP request retry count = 2
|
|
|
|
========
|
|
IP Layer
|
|
========
|
|
|
|
- We implement "Strong End-System" model, i.e.
|
|
when a datagram arrives on an interface, the destination
|
|
address must match that interface's address (or an
|
|
approriate broadcast / multicast address)
|
|
- We only support the all-1's form of broadcast addresses.
|
|
- We do NOT support fragmentation on outgoing datagrams.
|
|
- The default size limit for reassembled datagrams is 2048 bytes
|
|
and the default reassembly timeout period is 60sec.
|
|
- By default, the maximum number of datagrams that can be reassembled
|
|
simultaneously is 4.
|
|
- Subnet-directed broadcast are not received locally.
|
|
|
|
=======
|
|
Winsock
|
|
=======
|
|
|
|
- Our socket handles are not file handles, i.e.
|
|
you can NOT call Read/WriteFile APIs on them.
|
|
- Only limited validatation is performed on socket handles
|
|
passed into the API calls. If app passes in a random
|
|
handle value, the resulting behavior will be undefined.
|
|
- Overlapped completion routines are not supported.
|
|
- Since our socket handles are not file handles, apps can NOT
|
|
call CancelIO API to cancel outstanding overlapped I/O requests.
|
|
Apps must call WSACancelOverlappedIO function instead.
|
|
- We claim to support the following Winsock versions:
|
|
1.0, 1.1
|
|
2.0, 2.1, 2.2
|
|
- But we don't support 1.x blocking hooks, i.e. the following calls are
|
|
not supported:
|
|
WSASetBlockingHook
|
|
WSAUnhookBlockingHook
|
|
WSACancelBlockingCall
|
|
WSAIsBlocking
|
|
- Following calls from Winsock 2 are NOT supported:
|
|
WSAAsyncGetHostByAddr
|
|
WSAAsyncGetHostByName
|
|
WSAAsyncGetProtoByName
|
|
WSAAsyncGetProtoByNumber
|
|
WSAAsyncGetServByName
|
|
WSAAsyncGetServByPort
|
|
WSAAsyncSelect
|
|
WSACancelAsyncRequest
|
|
WSADuplicateSocket
|
|
WSAGetQOSByName
|
|
WSAJoinLeaf
|
|
WSAProviderConfigChange
|
|
WSARecvDisconnect
|
|
WSASendDisconnect
|
|
WSAHtonl
|
|
WSAHtons
|
|
WSANtohl
|
|
WSANtohs
|
|
WSAAddressToString
|
|
WSAStringToAddress
|
|
WSASocket
|
|
WSAAccept
|
|
WSAConnect
|
|
WSAIoctl
|
|
WSAEventSelect
|
|
WSAEnumProtocols
|
|
WSAEnumNetworkEvents
|
|
WSALookupServiceBegin
|
|
WSALookupServiceNext
|
|
WSALookupServiceEnd
|
|
WSAInstallServiceClass
|
|
WSARemoveServiceClass
|
|
WSAGetServiceClassInfo
|
|
WSAEnumNameSpaceProviders
|
|
WSAGetServiceClassNameByClassId
|
|
WSASetService
|
|
- closesocket always return immediately. If SO_LINGER is on and
|
|
timeout is non-zero, we use the graceful close semantics (i.e.
|
|
as if SO_DONTLINGER is on).
|
|
- For send calls, we don't support MSG_OOB and MSG_PARTIAL flags
|
|
and ignore MSG_DONTROUTE.
|
|
- For recv calls, we don't support MSG_OOB and MSB_PARTIAL flags.
|
|
MSG_PEEK flag is supported for datagram sockets.
|
|
- For WSARecv calls, we do not support more than one buffers.
|
|
- We do not support more than one outstanding overlapped I/O requests.
|
|
- We don't allow multiple threads to use the same socket handle simultanenously.
|
|
If two threads try to use the same socket handle at the same time, the first
|
|
one succeeds and the second one fails with a busy error.
|
|
|
|
=====================
|
|
Directory Structure
|
|
=====================
|
|
|
|
inc common include files
|
|
phy PHY (Ethernet transceiver) code in ROM
|
|
lib common library functions
|
|
enet Ethernet interface driver
|
|
modem modem driver
|
|
ppp PPP interface driver
|
|
ip IP/ICMP/IGMP code
|
|
tcp TCP/UDP code
|
|
dhcp DHCP client code
|
|
dns DNS client code
|
|
winsock Winsock code, and everytying is built into XNET.DLL
|
|
http lightweight HTTP client library
|
|
test test programs
|
|
|
|
======
|
|
Issues
|
|
======
|
|
|
|
- need to pass TCP related ICMP messages from IP layer to TCP layer
|
|
- path MTU discovery
|
|
- dead gateway detection
|
|
- implement TCP urgent data?
|
|
- support source route IP options for TCP connections?
|
|
- do receive work in a separate system thread
|
|
instead of at DISPATCH_LEVEL?
|
|
|
|
|
|
=======================================
|
|
Winsock API Parameter Validation RIPs
|
|
=======================================
|
|
|
|
bind:
|
|
name != NULL
|
|
namelen >= sizeof(struct sockaddr)
|
|
name->sin_family == AF_INET
|
|
|
|
connect:
|
|
same as bind
|
|
|
|
listen:
|
|
socket must be a TCP socket
|
|
|
|
accept:
|
|
socket must be a TCP socket
|
|
either addr == NULL, or
|
|
addrlen != NULL and addrlen >= sizeof(struct sockaddr)
|
|
|
|
getsockname:
|
|
name != NULL
|
|
namelen != NULL
|
|
*namelen >= sizeof(struct sockaddr)
|
|
|
|
getpeername:
|
|
same as getsockname
|
|
|
|
gethostbyaddr:
|
|
addr != NULL
|
|
len >= sizeof(struct in_addr)
|
|
type == AF_INET
|
|
|
|
gethostbyname:
|
|
name != NULL
|
|
|
|
|
|
getservbyname:
|
|
name != NULL
|
|
|
|
getprotobyname:
|
|
name != NULL
|
|
|
|
GetBestIpAddress
|
|
addr != NULL
|
|
|
|
recv:
|
|
either len > 0 and buf != NULL, or
|
|
len == 0
|
|
|
|
WSARecv:
|
|
dwBufferCount == 1
|
|
lpBuffers != NULL
|
|
ether lpBuffers->len > 0 and lpBuffers->buf != NULL, or
|
|
lpBuffers->len == 0
|
|
lpNumberOfBytesRecvd != NULL
|
|
lpFlags != NULL
|
|
lpCompletionRoutine == NULL
|
|
|
|
recvfrom:
|
|
either len > 0 and buf != NULL, or
|
|
len == 0
|
|
either from == NULL, or
|
|
fromlen != NULL and *fromlen >= sizeof(struct sockaddr)
|
|
|
|
WSARecvFrom:
|
|
same as WSARecv, and
|
|
either from == NULL, or
|
|
fromlen != NULL and *fromlen >= sizeof(struct sockaddr)
|
|
|
|
WSAGetOverlappedResult:
|
|
lpOverlapped != NULL
|
|
lpcbTransfer != NULL
|
|
lpdwFlags != NULL
|
|
|
|
send:
|
|
either len > 0 and buf != NULL, or
|
|
len == 0
|
|
flags == 0
|
|
|
|
WSASend:
|
|
dwBufferCount > 0
|
|
lpBuffers != NULL
|
|
for each WSABUF
|
|
either len > 0 and buf != NULL, or
|
|
len == 0
|
|
lpNumberOfBytesSent != NULL
|
|
dwFlags == 0
|
|
lpCompletionRoutine == NULL
|
|
|
|
sendto:
|
|
either len > 0 and buf != NULL, or
|
|
len == 0
|
|
flags == 0
|
|
either to == NULL, or
|
|
tolen >= sizeof(struct sockaddr)
|
|
|
|
WSASendTo:
|
|
same as WSASend, and
|
|
either lpTo == NULL, or
|
|
iToLen >= sizeof(struct sockaddr)
|
|
|
|
shutdown:
|
|
how must be one of the following values:
|
|
SD_RECEIVE
|
|
SD_SEND
|
|
SD_BOTH
|
|
|
|
WSAStartup:
|
|
lpWSAData != NULL
|
|
|
|
inet_addr:
|
|
cp != NULL
|
|
|
|
setsockopt:
|
|
optval != NULL
|
|
optlen > 0
|
|
additional requirements for specific options:
|
|
SO_LINGER:
|
|
optlen >= sizeof(LINGER)
|
|
SO_ERROR:
|
|
SO_RCVTIMEO:
|
|
SO_SNDTIMEO:
|
|
SO_RCVBUF:
|
|
SO_SNDBUF:
|
|
optlen >= sizeof(INT)
|
|
SO_MULTICASTIF:
|
|
optlen >= sizeof(struct in_addr)
|
|
SO_ADD_MEMBERSHIP:
|
|
SO_DROP_MEMBERSHIP:
|
|
optlen >= sizeof(struct ip_mreq)
|
|
|
|
getsockopt:
|
|
optval != NULL
|
|
optlen != NULL
|
|
*optlen > 0
|
|
additional requirements for specific options:
|
|
same as setsockopt
|
|
|
|
ioctlsocket:
|
|
argp != NULL
|
|
|