b7e825d6e7
Modelled after UDP, add limited TCP support to the boot net stack. The socket works by queuing received packets as well as sent packets that have not yet been ACK'ed. Some known issues are documented, especially there's only limited congestion control. I.e., we send immediately and in unlimited quantity, thus its use should be restricted to local networks, and due to a fixed window size there is potential for our socket being overrun with data packets before they are read. Some corner cases like wrapping sequence numbers may cause a timeout. The TCP implementation is based on Andrew S. Tanenbaum's "Computer Networks", 4th ed., as well as lecture notes from Prof. W. Effelsberg, the relevant RFCs and Wikipedia. The pseudo-random number Galois LFSR used for the sequence number was suggested by Endre Varga. Since the code is unlikely to get much smaller, better merge it now so that subsequent changes get easier to review. No platform actively uses TCP sockets yet, and the receiving code has been reviewed for endianness issues and should terminate okay after verifying the checksum if no sockets are open. Based on a version tested with custom code (#5240) as well as with iSCSI. Compile-tested boot_loader_openfirmware, pxehaiku-loader with gcc4 and haiku_loader with gcc2. Closes ticket #5240. Changes from #5240 proposed patch: * Various bug fixes related to queuing, some memory leaks fixed. * Never bump the sequence number when dequeuing a packet. It's done afterwards. * Don't bump the sequence number again when resending the queue or ACK'ing. * Aggressively ACK while waiting for packets. * Don't queue sent ACK-only packets. * More trace output, esp. for queue inspection. * Adapted use of TCP header flags to r38434. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38472 a95241bf-73f2-0310-859d-f6bbb57e9c96
248 lines
6.4 KiB
C++
248 lines
6.4 KiB
C++
/*
|
|
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
|
|
* Copyright 2010, Andreas Färber <andreas.faerber@web.de>
|
|
* All rights reserved. Distributed under the terms of the MIT License.
|
|
*/
|
|
#ifndef _BOOT_NET_DEFS_H
|
|
#define _BOOT_NET_DEFS_H
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <ByteOrder.h>
|
|
#include <SupportDefs.h>
|
|
|
|
#include <util/kernel_cpp.h>
|
|
|
|
|
|
// Ethernet
|
|
|
|
#define ETH_ALEN 6
|
|
#define ETHERTYPE_IP 0x0800 // IP
|
|
#define ETHERTYPE_ARP 0x0806 // Address resolution
|
|
|
|
#define ETHER_MIN_TRANSFER_UNIT 46
|
|
#define ETHER_MAX_TRANSFER_UNIT 1500
|
|
|
|
struct mac_addr_t {
|
|
mac_addr_t() {}
|
|
|
|
mac_addr_t(uint8 *address)
|
|
{
|
|
memcpy(this->address, address, ETH_ALEN);
|
|
}
|
|
|
|
mac_addr_t(const mac_addr_t& other)
|
|
{
|
|
memcpy(address, other.address, sizeof(address));
|
|
}
|
|
|
|
uint64 ToUInt64() const
|
|
{
|
|
return ((uint64)address[0] << 40)
|
|
| ((uint64)address[1] << 32)
|
|
| ((uint64)address[2] << 24)
|
|
| ((uint64)address[3] << 16)
|
|
| ((uint64)address[4] << 8)
|
|
| (uint64)address[5];
|
|
}
|
|
|
|
uint8 operator[](int index)
|
|
{
|
|
return address[index];
|
|
}
|
|
|
|
mac_addr_t& operator=(const mac_addr_t& other)
|
|
{
|
|
memcpy(address, other.address, sizeof(address));
|
|
return *this;
|
|
}
|
|
|
|
bool operator==(const mac_addr_t& other) const
|
|
{
|
|
return memcmp(address, other.address, sizeof(address)) == 0;
|
|
}
|
|
|
|
bool operator!=(const mac_addr_t& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
uint8 address[ETH_ALEN];
|
|
} __attribute__ ((__packed__));
|
|
|
|
extern const mac_addr_t kBroadcastMACAddress;
|
|
extern const mac_addr_t kNoMACAddress;
|
|
|
|
// 10/100 Mb/s ethernet header
|
|
struct ether_header {
|
|
mac_addr_t destination; /* destination eth addr */
|
|
mac_addr_t source; /* source ether addr */
|
|
uint16 type; /* packet type ID field */
|
|
} __attribute__ ((__packed__));
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
// Address Resolution Protocol (ARP)
|
|
|
|
typedef uint32 ip_addr_t;
|
|
|
|
// ARP protocol opcodes
|
|
#define ARPOP_REQUEST 1 /* ARP request. */
|
|
#define ARPOP_REPLY 2 /* ARP reply. */
|
|
#define ARPOP_RREQUEST 3 /* RARP request. */
|
|
#define ARPOP_RREPLY 4 /* RARP reply. */
|
|
#define ARPOP_InREQUEST 8 /* InARP request. */
|
|
#define ARPOP_InREPLY 9 /* InARP reply. */
|
|
#define ARPOP_NAK 10 /* (ATM)ARP NAK. */
|
|
|
|
// ARP header for IP over ethernet (RFC 826)
|
|
struct arp_header {
|
|
uint16 hardware_format; /* Format of hardware address. */
|
|
uint16 protocol_format; /* Format of protocol address. */
|
|
uint8 hardware_length; /* Length of hardware address. */
|
|
uint8 protocol_length; /* Length of protocol address. */
|
|
uint16 opcode; /* ARP opcode (command). */
|
|
|
|
// IP over ethernet
|
|
mac_addr_t sender_mac; /* Sender hardware address. */
|
|
ip_addr_t sender_ip; /* Sender IP address. */
|
|
mac_addr_t target_mac; /* Target hardware address. */
|
|
ip_addr_t target_ip; /* Target IP address. */
|
|
} __attribute__ ((__packed__));
|
|
|
|
// ARP protocol HARDWARE identifiers.
|
|
#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
// Internet Protocol (IP)
|
|
|
|
#define INADDR_ANY ((ip_addr_t) 0x00000000)
|
|
/* Address to send to all hosts. */
|
|
#define INADDR_BROADCAST ((ip_addr_t) 0xffffffff)
|
|
/* Address indicating an error return. */
|
|
#define INADDR_NONE ((ip_addr_t) 0xffffffff)
|
|
|
|
// IP packet header (no options
|
|
struct ip_header {
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
uint8 header_length:4; // header length
|
|
uint8 version:4; // IP protocol version
|
|
#endif
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
uint8 version:4; // IP protocol version
|
|
uint8 header_length:4; // header length
|
|
#endif
|
|
uint8 type_of_service; // type of service
|
|
uint16 total_length; // total IP packet length
|
|
uint16 identifier; // fragment identification
|
|
uint16 fragment_offset; // fragment offset and flags (0xe000)
|
|
uint8 time_to_live; // time to live
|
|
uint8 protocol; // protocol
|
|
uint16 checksum; // checksum (header)
|
|
ip_addr_t source; // source IP address
|
|
ip_addr_t destination; // destination IP address
|
|
} __attribute__ ((__packed__));
|
|
|
|
// IP protocol version 4
|
|
#define IP_PROTOCOL_VERSION_4 4
|
|
|
|
// fragment flags/offset mask
|
|
#define IP_DONT_FRAGMENT 0x4000 /* dont fragment flag */
|
|
#define IP_FRAGMENT_OFFSET_MASK 0x1fff /* mask for fragment offset */
|
|
|
|
// Internet implementation parameters.
|
|
#define IP_MAX_TIME_TO_LIVE 255 /* maximum time to live */
|
|
#define IP_DEFAULT_TIME_TO_LIVE 64 /* default ttl, from RFC 1340 */
|
|
|
|
// IP protocols
|
|
#define IPPROTO_TCP 6
|
|
#define IPPROTO_UDP 17
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
// User Datagram Protocol (UDP)
|
|
|
|
// UDP header (RFC 768)
|
|
struct udp_header {
|
|
uint16 source; // source port
|
|
uint16 destination; // destination port
|
|
uint16 length; // length of UDP packet (header + data)
|
|
uint16 checksum; // checksum
|
|
} __attribute__ ((__packed__));
|
|
|
|
|
|
// Transmission Control Protocol (TCP)
|
|
|
|
// TCP header (RFC 793, RFC 3168)
|
|
struct tcp_header {
|
|
uint16 source; // source port
|
|
uint16 destination; // destination port
|
|
uint32 seqNumber; // sequence number
|
|
uint32 ackNumber; // acknowledgment number
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
uint8 dataOffset : 4; // data offset
|
|
uint8 reserved : 4; // reserved
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
uint8 reserved : 4;
|
|
uint8 dataOffset : 4;
|
|
#endif
|
|
uint8 flags; // ACK, SYN, FIN, etc.
|
|
uint16 window; // window size
|
|
uint16 checksum; // checksum
|
|
uint16 urgentPointer; // urgent pointer
|
|
} __attribute__ ((__packed__));
|
|
|
|
#define TCP_FIN (1 << 0)
|
|
#define TCP_SYN (1 << 1)
|
|
#define TCP_RST (1 << 2)
|
|
#define TCP_PSH (1 << 3)
|
|
#define TCP_ACK (1 << 4)
|
|
#define TCP_URG (1 << 5)
|
|
#define TCP_ECE (1 << 6) // RFC 3168
|
|
#define TCP_CWR (1 << 7) // RFC 3168
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
// NetService
|
|
|
|
// net service names
|
|
extern const char *const kEthernetServiceName;
|
|
extern const char *const kARPServiceName;
|
|
extern const char *const kIPServiceName;
|
|
extern const char *const kUDPServiceName;
|
|
extern const char *const kTCPServiceName;
|
|
|
|
class NetService {
|
|
public:
|
|
NetService(const char *name);
|
|
virtual ~NetService();
|
|
|
|
const char *NetServiceName();
|
|
|
|
virtual int CountSubNetServices() const;
|
|
virtual NetService *SubNetServiceAt(int index) const;
|
|
virtual NetService *FindSubNetService(const char *name) const;
|
|
|
|
template<typename ServiceType>
|
|
ServiceType *FindSubNetService(const char *name) const
|
|
{
|
|
// We should actually use dynamic_cast<>(), but we better spare us the
|
|
// RTTI stuff.
|
|
if (NetService *service = FindSubNetService(name))
|
|
return static_cast<ServiceType*>(service);
|
|
return NULL;
|
|
}
|
|
|
|
private:
|
|
const char *fName;
|
|
};
|
|
|
|
|
|
#endif // _BOOT_NET_DEFS_H
|