Added a mini networking stack to the boot loader. It speaks basic ARP,
IP, and UDP, as well as a home brewn UDP based protocol, "remote disk", which provides random access to a single remote file/device. The Open Firmware flavored boot loader automatically initializes the net stack, searches for a remote disk, and tries to boot from it, if the boot device is a network device (e.g. when loading the boot loader via TFTP). This is quite nice for developing with a two-machine setup, since one doesn't even need to install Haiku on the test machine anymore, but can serve it directly from the development machine. When the networking support in the kernel is working, this method could even be used to fully boot, not just for loading kernel and initial modules. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15689 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_ARP_H
|
||||
#define _BOOT_ARP_H
|
||||
|
||||
#include <boot/net/Ethernet.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
class ARPService : public EthernetSubService {
|
||||
// actually ARP for IP over ethernet
|
||||
public:
|
||||
ARPService(EthernetService *ethernet);
|
||||
virtual ~ARPService();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual uint16 EthernetProtocol() const;
|
||||
|
||||
virtual void HandleEthernetPacket(EthernetService *ethernet,
|
||||
const mac_addr_t &targetAddress, const void *data, size_t size);
|
||||
|
||||
status_t GetMACForIP(ip_addr_t ip, mac_addr_t &mac);
|
||||
|
||||
private:
|
||||
enum { MAP_ENTRY_COUNT = 10 };
|
||||
enum { ARP_REQUEST_RETRY_COUNT = 3 };
|
||||
enum { ARP_REPLY_TIMEOUT = 5000 };
|
||||
|
||||
struct MapEntry {
|
||||
int32 age;
|
||||
ip_addr_t ip;
|
||||
mac_addr_t mac;
|
||||
};
|
||||
|
||||
status_t _SendARPPacket(ip_addr_t ip, const mac_addr_t &mac, uint16 opcode);
|
||||
|
||||
MapEntry *_FindEntry(ip_addr_t ip);
|
||||
void _PutEntry(ip_addr_t ip, const mac_addr_t &mac);
|
||||
|
||||
EthernetService *fEthernet;
|
||||
int32 fAge;
|
||||
MapEntry fEntries[MAP_ENTRY_COUNT];
|
||||
};
|
||||
|
||||
#endif // _BOOT_ARP_H
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_NET_CHAIN_BUFFER_H
|
||||
#define _BOOT_NET_CHAIN_BUFFER_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class ChainBuffer {
|
||||
public:
|
||||
|
||||
ChainBuffer(void *data = 0, uint32 size = 0, ChainBuffer *next = NULL,
|
||||
bool freeData = false);
|
||||
~ChainBuffer();
|
||||
|
||||
void *Data() const { return fData; }
|
||||
uint32 Size() const { return fSize; }
|
||||
uint32 TotalSize() const { return fTotalSize; }
|
||||
|
||||
ChainBuffer *Next() const { return fNext; }
|
||||
ChainBuffer *DetachNext();
|
||||
|
||||
void Append(ChainBuffer *next);
|
||||
|
||||
void Flatten(void *_buffer) const;
|
||||
|
||||
private:
|
||||
// TODO: Implement Create() and Delete(). Make new and delete operators private.
|
||||
enum {
|
||||
CHAIN_BUFFER_HEAD = 0x1,
|
||||
CHAIN_BUFFER_EMBEDDED_DATA = 0x2,
|
||||
CHAIN_BUFFER_FREE_DATA = 0x4,
|
||||
CHAIN_BUFFER_ON_STACK = 0x8,
|
||||
};
|
||||
|
||||
void _Init(void *data, uint32 size, ChainBuffer *next, uint32 flags);
|
||||
void _Destroy();
|
||||
|
||||
uint32 fFlags:4;
|
||||
uint32 fSize:14;
|
||||
uint32 fTotalSize:14;
|
||||
void *fData;
|
||||
ChainBuffer *fNext;
|
||||
uint8 fBuffer[0];
|
||||
};
|
||||
|
||||
#endif // _BOOT_NET_CHAIN_BUFFER_H
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_ETHERNET_H
|
||||
#define _BOOT_ETHERNET_H
|
||||
|
||||
#include <boot/net/NetDefs.h>
|
||||
#include <util/Vector.h>
|
||||
|
||||
class ChainBuffer;
|
||||
class EthernetService;
|
||||
|
||||
// EthernetInterface
|
||||
class EthernetInterface {
|
||||
public:
|
||||
EthernetInterface();
|
||||
virtual ~EthernetInterface();
|
||||
|
||||
ip_addr_t IPAddress() const;
|
||||
void SetIPAddress(ip_addr_t ipAddress);
|
||||
|
||||
virtual mac_addr_t MACAddress() const = 0;
|
||||
|
||||
virtual void *AllocateSendReceiveBuffer(size_t size) = 0;
|
||||
virtual void FreeSendReceiveBuffer(void *buffer) = 0;
|
||||
|
||||
virtual ssize_t Send(const void *buffer, size_t size) = 0;
|
||||
virtual ssize_t Receive(void *buffer, size_t size) = 0;
|
||||
|
||||
protected:
|
||||
ip_addr_t fIPAddress;
|
||||
};
|
||||
|
||||
// EthernetSubService
|
||||
class EthernetSubService : public NetService {
|
||||
public:
|
||||
EthernetSubService(const char *serviceName);
|
||||
virtual ~EthernetSubService();
|
||||
|
||||
virtual uint16 EthernetProtocol() const = 0;
|
||||
|
||||
virtual void HandleEthernetPacket(EthernetService *ethernet,
|
||||
const mac_addr_t &targetAddress, const void *data, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
// EthernetService
|
||||
class EthernetService : public NetService {
|
||||
public:
|
||||
EthernetService();
|
||||
virtual ~EthernetService();
|
||||
|
||||
status_t Init(EthernetInterface *interface);
|
||||
|
||||
mac_addr_t MACAddress() const;
|
||||
ip_addr_t IPAddress() const;
|
||||
void SetIPAddress(ip_addr_t ipAddress);
|
||||
|
||||
status_t Send(const mac_addr_t &destination, uint16 protocol,
|
||||
ChainBuffer *buffer);
|
||||
void ProcessIncomingPackets();
|
||||
|
||||
bool RegisterEthernetSubService(EthernetSubService *service);
|
||||
bool UnregisterEthernetSubService(EthernetSubService *service);
|
||||
|
||||
virtual int CountSubNetServices() const;
|
||||
virtual NetService *SubNetServiceAt(int index) const;
|
||||
|
||||
private:
|
||||
enum {
|
||||
SEND_BUFFER_SIZE = 2048,
|
||||
RECEIVE_BUFFER_SIZE = SEND_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
EthernetInterface *fInterface;
|
||||
void *fSendBuffer;
|
||||
void *fReceiveBuffer;
|
||||
Vector<EthernetSubService*> fServices;
|
||||
};
|
||||
|
||||
|
||||
#endif // _BOOT_ETHERNET_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_IP_H
|
||||
#define _BOOT_IP_H
|
||||
|
||||
#include <boot/net/Ethernet.h>
|
||||
|
||||
class ARPService;
|
||||
class IPService;
|
||||
|
||||
// IPSubService
|
||||
class IPSubService : public NetService {
|
||||
public:
|
||||
IPSubService(const char *serviceName);
|
||||
virtual ~IPSubService();
|
||||
|
||||
virtual uint8 IPProtocol() const = 0;
|
||||
|
||||
virtual void HandleIPPacket(IPService *ipService, ip_addr_t sourceIP,
|
||||
ip_addr_t destinationIP, const void *data, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
// IPService
|
||||
class IPService : public EthernetSubService {
|
||||
// actually IP over ethernet
|
||||
public:
|
||||
IPService(EthernetService *ethernet, ARPService *arpService);
|
||||
virtual ~IPService();
|
||||
|
||||
status_t Init();
|
||||
|
||||
ip_addr_t IPAddress() const;
|
||||
|
||||
virtual uint16 EthernetProtocol() const;
|
||||
|
||||
virtual void HandleEthernetPacket(EthernetService *ethernet,
|
||||
const mac_addr_t &targetAddress, const void *data, size_t size);
|
||||
|
||||
status_t Send(ip_addr_t destination, uint8 protocol, ChainBuffer *buffer);
|
||||
|
||||
void ProcessIncomingPackets();
|
||||
|
||||
bool RegisterIPSubService(IPSubService *service);
|
||||
bool UnregisterIPSubService(IPSubService *service);
|
||||
|
||||
virtual int CountSubNetServices() const;
|
||||
virtual NetService *SubNetServiceAt(int index) const;
|
||||
|
||||
private:
|
||||
uint16 _Checksum(const ip_header &header);
|
||||
|
||||
EthernetService *fEthernet;
|
||||
ARPService *fARPService;
|
||||
Vector<IPSubService*> fServices;
|
||||
};
|
||||
|
||||
uint16 ip_checksum(ChainBuffer *buffer);
|
||||
|
||||
|
||||
#endif // _BOOT_IP_H
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* 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];
|
||||
}
|
||||
|
||||
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_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__));
|
||||
|
||||
|
||||
// #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;
|
||||
|
||||
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
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_NET_STACK_H
|
||||
#define _BOOT_NET_STACK_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class EthernetInterface;
|
||||
class EthernetService;
|
||||
class ARPService;
|
||||
class IPService;
|
||||
class UDPService;
|
||||
|
||||
|
||||
class NetStack {
|
||||
private:
|
||||
NetStack();
|
||||
~NetStack();
|
||||
|
||||
status_t Init();
|
||||
|
||||
public:
|
||||
static status_t CreateDefault();
|
||||
static NetStack *Default();
|
||||
|
||||
status_t AddEthernetInterface(EthernetInterface *interface);
|
||||
|
||||
EthernetInterface *GetEthernetInterface() const
|
||||
{ return fEthernetInterface; }
|
||||
EthernetService *GetEthernetService() const { return fEthernetService; }
|
||||
ARPService *GetARPService() const { return fARPService; }
|
||||
IPService *GetIPService() const { return fIPService; }
|
||||
UDPService *GetUDPService() const { return fUDPService; }
|
||||
|
||||
private:
|
||||
static NetStack *sNetStack;
|
||||
|
||||
EthernetInterface *fEthernetInterface;
|
||||
EthernetService *fEthernetService;
|
||||
ARPService *fARPService;
|
||||
IPService *fIPService;
|
||||
UDPService *fUDPService;
|
||||
};
|
||||
|
||||
|
||||
// net_stack_init() creates the NetStack and calls platform_net_stack_init()
|
||||
// afterwards, which is supposed to add network interfaces.
|
||||
status_t net_stack_init();
|
||||
status_t platform_net_stack_init();
|
||||
|
||||
|
||||
#endif // _BOOT_NET_STACK_H
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_REMOTE_DISK_H
|
||||
#define _BOOT_REMOTE_DISK_H
|
||||
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/net/NetDefs.h>
|
||||
#include <boot/net/RemoteDiskDefs.h>
|
||||
|
||||
class UDPPacket;
|
||||
class UDPSocket;
|
||||
|
||||
class RemoteDisk : public Node {
|
||||
public:
|
||||
RemoteDisk();
|
||||
~RemoteDisk();
|
||||
|
||||
status_t Init(ip_addr_t serverAddress, uint16 serverPort, off_t imageSize);
|
||||
|
||||
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
|
||||
size_t bufferSize);
|
||||
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const;
|
||||
virtual off_t Size() const;
|
||||
|
||||
static RemoteDisk *FindAnyRemoteDisk();
|
||||
|
||||
private:
|
||||
ssize_t _ReadFromPacket(off_t &pos, uint8 *&buffer, size_t &bufferSize);
|
||||
|
||||
static status_t _SendRequest(UDPSocket *socket, ip_addr_t serverAddress,
|
||||
uint16 serverPort, remote_disk_header *request, size_t size,
|
||||
uint8 expectedReply, UDPPacket **packet);
|
||||
status_t _SendRequest(remote_disk_header *request, size_t size,
|
||||
uint8 expectedReply, UDPPacket **packet);
|
||||
|
||||
private:
|
||||
ip_addr_t fServerAddress;
|
||||
uint16 fServerPort;
|
||||
off_t fImageSize;
|
||||
uint64 fRequestID;
|
||||
UDPSocket *fSocket;
|
||||
UDPPacket *fPacket;
|
||||
};
|
||||
|
||||
#endif // _BOOT_REMOTE_DISK_H
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_REMOTE_DISK_DEFS_H
|
||||
#define _BOOT_REMOTE_DISK_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
REMOTE_DISK_SERVER_PORT = 8765,
|
||||
REMOTE_DISK_BLOCK_SIZE = 1024,
|
||||
};
|
||||
|
||||
enum {
|
||||
// requests
|
||||
|
||||
REMOTE_DISK_HELLO_REQUEST = 0,
|
||||
// port: client port
|
||||
|
||||
REMOTE_DISK_READ_REQUEST = 1,
|
||||
// port: client port
|
||||
// offset: byte offset of data to read
|
||||
// size: number of bytes to read (server might serve more, though)
|
||||
|
||||
REMOTE_DISK_WRITE_REQUEST = 2,
|
||||
// port: client port
|
||||
// offset: byte offset of data to write
|
||||
// size: number of bytes to write
|
||||
// data: the data
|
||||
|
||||
// replies
|
||||
|
||||
REMOTE_DISK_HELLO_REPLY = 3,
|
||||
// offset: disk size
|
||||
|
||||
REMOTE_DISK_READ_REPLY = 4, // port unused
|
||||
// offset: byte offset of read data
|
||||
// size: number of bytes of data read; < 0 => error
|
||||
// data: read data
|
||||
|
||||
REMOTE_DISK_WRITE_REPLY = 5, // port, data unused
|
||||
// offset: byte offset of data written
|
||||
// size: number of bytes of data written; < 0 => error
|
||||
};
|
||||
|
||||
// errors
|
||||
enum {
|
||||
REMOTE_DISK_IO_ERROR = -1,
|
||||
REMOTE_DISK_BAD_REQUEST = -2,
|
||||
};
|
||||
|
||||
struct remote_disk_header {
|
||||
uint64_t offset;
|
||||
uint64_t request_id;
|
||||
int16_t size;
|
||||
uint16_t port;
|
||||
uint8_t command;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#endif // _BOOT_REMOTE_DISK_DEFS_H
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_UDP_H
|
||||
#define _BOOT_UDP_H
|
||||
|
||||
#include <boot/net/IP.h>
|
||||
|
||||
// UDPPacket
|
||||
class UDPPacket {
|
||||
public:
|
||||
UDPPacket();
|
||||
~UDPPacket();
|
||||
|
||||
status_t SetTo(const void *data, size_t size, ip_addr_t sourceAddress,
|
||||
uint16 sourcePort, ip_addr_t destinationAddress,
|
||||
uint16 destinationPort);
|
||||
|
||||
UDPPacket *Next() const;
|
||||
void SetNext(UDPPacket *next);
|
||||
|
||||
const void *Data() const;
|
||||
size_t DataSize() const;
|
||||
|
||||
ip_addr_t SourceAddress() const;
|
||||
uint16 SourcePort() const;
|
||||
ip_addr_t DestinationAddress() const;
|
||||
uint16 DestinationPort() const;
|
||||
|
||||
private:
|
||||
UDPPacket *fNext;
|
||||
void *fData;
|
||||
size_t fSize;
|
||||
ip_addr_t fSourceAddress;
|
||||
ip_addr_t fDestinationAddress;
|
||||
uint16 fSourcePort;
|
||||
uint16 fDestinationPort;
|
||||
};
|
||||
|
||||
|
||||
class UDPService;
|
||||
|
||||
// UDPSocket
|
||||
class UDPSocket {
|
||||
public:
|
||||
UDPSocket();
|
||||
~UDPSocket();
|
||||
|
||||
ip_addr_t Address() const { return fAddress; }
|
||||
uint16 Port() const { return fPort; }
|
||||
|
||||
status_t Bind(ip_addr_t address, uint16 port);
|
||||
|
||||
status_t Send(ip_addr_t destinationAddress, uint16 destinationPort,
|
||||
ChainBuffer *buffer);
|
||||
status_t Send(ip_addr_t destinationAddress, uint16 destinationPort,
|
||||
const void *data, size_t size);
|
||||
status_t Receive(UDPPacket **packet, bigtime_t timeout = 0);
|
||||
|
||||
void PushPacket(UDPPacket *packet);
|
||||
UDPPacket *PopPacket();
|
||||
|
||||
private:
|
||||
UDPService *fUDPService;
|
||||
UDPPacket *fFirstPacket;
|
||||
UDPPacket *fLastPacket;
|
||||
ip_addr_t fAddress;
|
||||
uint16 fPort;
|
||||
};
|
||||
|
||||
|
||||
// UDPService
|
||||
class UDPService : public IPSubService {
|
||||
public:
|
||||
UDPService(IPService *ipService);
|
||||
virtual ~UDPService();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual uint8 IPProtocol() const;
|
||||
|
||||
virtual void HandleIPPacket(IPService *ipService, ip_addr_t sourceIP,
|
||||
ip_addr_t destinationIP, const void *data, size_t size);
|
||||
|
||||
status_t Send(uint16 sourcePort, ip_addr_t destinationAddress,
|
||||
uint16 destinationPort, ChainBuffer *buffer);
|
||||
|
||||
void ProcessIncomingPackets();
|
||||
|
||||
status_t BindSocket(UDPSocket *socket, ip_addr_t address, uint16 port);
|
||||
void UnbindSocket(UDPSocket *socket);
|
||||
|
||||
private:
|
||||
uint16 _ChecksumBuffer(ChainBuffer *buffer, ip_addr_t source,
|
||||
ip_addr_t destination, uint16 length);
|
||||
uint16 _ChecksumData(const void *data, uint16 length, ip_addr_t source,
|
||||
ip_addr_t destination);
|
||||
|
||||
UDPSocket *_FindSocket(ip_addr_t address, uint16 port);
|
||||
|
||||
IPService *fIPService;
|
||||
Vector<UDPSocket*> fSockets;
|
||||
};
|
||||
|
||||
#endif // _BOOT_UDP_H
|
||||
Reference in New Issue
Block a user