/*
* Taken from http://cvs.savannah.gnu.org/viewvc/vgabios/vgafonts.h?root=vgabios&view=markup
+ * Font is public domain
* Altered for Acess2
*/
#define FONT_WIDTH 8
#include <semaphore.h>
#include <threads.h>
#include <events.h>
+#include <timers.h>
// === CONSTANTS ===
#define NUM_THREADS_PER_ALLOC 4
}
}
- // - Fast return for polling
- if( Timeout && *Timeout == 0 ) return 0;
-
// Wait for things
- if( !Timeout || *Timeout > 0 )
+ if( !Timeout )
{
LOG("Semaphore_Wait()");
// TODO: Actual timeout
Threads_WaitEvents( THREAD_EVENT_VFS );
}
+ else if( *Timeout > 0 )
+ {
+ tTimer *t = Time_AllocateTimer(NULL, NULL);
+ // Clear timer event
+ Threads_ClearEvent( THREAD_EVENT_TIMER );
+ // TODO: Convert *Timeout?
+ LOG("Timeout %lli ms", *Timeout);
+ Time_ScheduleTimer( t, *Timeout );
+ // Wait for the timer or a VFS event
+ Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER );
+ Time_FreeTimer(t);
+ }
// Get return value
ret = 0;
VFS_int_Select_RemThread(*list, thisthread);
ret = ret || *flag == wanted;
}
+
+ Threads_ClearEvent( THREAD_EVENT_VFS );
+ Threads_ClearEvent( THREAD_EVENT_TIMER );
LEAVE('i', ret);
return ret;
LEAVE('i', ret);
return ret;
}
-
- // TODO: Implement timeout
- LOG("Timeout = %p", Timeout);
-
- // Wait (only if there is no timeout, or it is greater than zero
- if( !Timeout || *Timeout > 0 )
+
+ // Wait for things
+ if( !Timeout )
{
- // TODO: Timeout
- // TODO: Allow extra events to be waited upon
+ LOG("Semaphore_Wait()");
+ // TODO: Actual timeout
Threads_WaitEvents( THREAD_EVENT_VFS|ExtraEvents );
}
-
+ else if( *Timeout > 0 )
+ {
+ tTimer *t = Time_AllocateTimer(NULL, NULL);
+ // Clear timer event
+ Threads_ClearEvent( THREAD_EVENT_TIMER );
+ // TODO: Convert *Timeout?
+ LOG("Timeout %lli ms", *Timeout);
+ Time_ScheduleTimer( t, *Timeout );
+ // Wait for the timer or a VFS event
+ Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER|ExtraEvents );
+ Time_FreeTimer(t);
+ }
// Fill output (modify *Handles)
// - Also, de-register
ret = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
+
+ Threads_ClearEvent( THREAD_EVENT_VFS );
+ Threads_ClearEvent( THREAD_EVENT_TIMER );
+
LEAVE('i', ret);
return ret;
}
Dir "SBin" {
File "init" "__BIN__/SBin/init"
File "login" "__BIN__/SBin/login"
- File "dhcpc" "__BIN__/SBin/dhcpc"
}
Dir "Bin" {
File "CLIShell" "__BIN__/Bin/CLIShell"
File "ls" "__BIN__/Bin/ls"
File "cat" "__BIN__/Bin/cat"
File "mount" "__BIN__/Bin/mount"
- File "ifconfig" "__BIN__/Bin/ifconfig"
+ File "ip" "__BIN__/Bin/ip"
File "ping" "__BIN__/Bin/ping"
File "telnet" "__BIN__/Bin/telnet"
File "irc" "__BIN__/Bin/irc"
+ File "dhcpc" "__BIN__/SBin/dhcpc"
}
Dir "Libs" {
File "ld-acess.so" "__BIN__/Libs/ld-acess.so"
end = ts + Interface->TimeoutDelay;
while( !gICMP_PingSlots[i].bArrived && now() < end) Threads_Yield();
- if(now() >= end)
+ if( !gICMP_PingSlots[i].bArrived )
return -1;
return (int)( now() - ts );
#include "include/adapters.h"
// === CONSTANTS ===
-//! Default timeout value, 30 seconds
-#define DEFAULT_TIMEOUT (30*1000)
+//! Default timeout value, 5 seconds
+#define DEFAULT_TIMEOUT (5*1000)
// === IMPORTS ===
extern int IPv4_Ping(tInterface *Iface, tIPv4 Addr);
// TODO: Handle packet fragmentation
-
Log_Debug("IPv4", " From %i.%i.%i.%i to %i.%i.%i.%i",
hdr->Source.B[0], hdr->Source.B[1], hdr->Source.B[2], hdr->Source.B[3],
hdr->Destination.B[0], hdr->Destination.B[1], hdr->Destination.B[2], hdr->Destination.B[3]
// Routing
if(!iface)
{
+ #if 0
tMacAddr to;
tRoute *rt;
-
+
+
+ // TODO: Put this in another thread to avoid delays in the RX thread
Log_Debug("IPv4", "Route the packet");
// Drop the packet if the TTL is zero
if( hdr->TTL == 0 ) {
((tIPv4*)rt->NextHop)->B[2], ((tIPv4*)rt->NextHop)->B[3]);
Log_Warning("IPv4", "TODO: Implement forwarding with tIPStackBuffer");
// Link_SendPacket(rt->Interface->Adapter, IPV4_ETHERNET_ID, to, Length, Buffer);
+ #endif
return ;
}
*/
tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
{
- tInterface *iface = NULL;
+ tInterface *iface = NULL, *zero_iface = NULL;
Uint32 netmask;
Uint32 addr, this;
LEAVE('p', iface);
return iface;
}
-
+
+ LOG("iface->Address = 0x%x", *(Uint32*)iface->Address);
+
+ if( *(Uint32*)iface->Address == 0 ) {
+ if( zero_iface ) {
+ Log_Notice("IPv4", "Multiple 0.0.0.0 interfaces on the same adapter, ignoring");
+ }
+ else {
+ zero_iface = iface;
+ LOG("Zero IF %p", iface);
+ }
+ continue ;
+ }
+
if( !Broadcast ) continue;
// Check for broadcast
return iface;
}
}
+
+ // Special case for intefaces that are being DHCP configured
+ // - If the interface address is 0.0.0.0, then if there is no match for the
+ // destination the packet is treated as if it was addressed to 0.0.0.0
+ if( zero_iface && Broadcast )
+ {
+ LOG("Using 0.0.0.0 interface with magic!");
+ LEAVE('p', zero_iface);
+ return zero_iface;
+ }
+
LEAVE('n');
return NULL;
}
#define DESC_SIZE 16
#define N_RX_DESCS 16
#define RX_BUF_SIZE 1024
-#define N_RX_PAGES ((N_RX_DESCS*RX_BUF_SIZE)/PAGE_SIZE)
+#define N_RX_BUF_PER_PAGE (PAGE_SIZE/RX_BUF_SIZE)
+#define N_RX_BUF_PAGES ((N_RX_DESCS*RX_BUF_SIZE)/PAGE_SIZE)
#define N_TX_DESCS ((PAGE_SIZE/DESC_SIZE)-N_RX_DESCS)
#define CR0_BASEVAL (CR0_STRT|CR0_TXON|CR0_RXON)
int NextTX;
int nFreeTX;
- struct sRXDesc *FirstRX; // Most recent unread packet
- struct sRXDesc *LastRX; // End of RX descriptor queue
+ struct sRXDesc *NextRX; // Most recent unread packet
void *IPHandle;
Uint8 MacAddr[6];
{
rxdescs[i].RSR = 0;
rxdescs[i].BufferSize = RX_BUF_SIZE;
- rxdescs[i].RXBufferStart = Card->RXBuffers[i/(PAGE_SIZE/RX_BUF_SIZE)].Phys
- + (i % (PAGE_SIZE/RX_BUF_SIZE)) * RX_BUF_SIZE;
+ rxdescs[i].RXBufferStart = Card->RXBuffers[i/N_RX_BUF_PER_PAGE].Phys
+ + (i % N_RX_BUF_PER_PAGE) * RX_BUF_SIZE;
rxdescs[i].RDBranchAddress = Card->DescTablePhys + (i+1) * DESC_SIZE;
rxdescs[i].Length = (1 << 15); // set OWN
+ LOG("RX Desc %p = {Buf:0x%8x, Next:0x%x}", rxdescs,
+ rxdescs[i].RXBufferStart, rxdescs[i].RDBranchAddress
+ );
}
rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = Card->DescTablePhys;
- Card->FirstRX = &rxdescs[0];
- Card->LastRX = &rxdescs[N_RX_DESCS - 1];
+ Card->NextRX = &rxdescs[0];
Card->TXDescs = (void*)(rxdescs + N_RX_DESCS);
memset(Card->TXDescs, 0, sizeof(struct sTXDesc)*N_TX_DESCS);
LOG("RX started");
outb(Card->IOBase + REG_CR0, CR0_BASEVAL);
- outb(Card->IOBase + REG_CR1, CR1_DPOLL); // Disabled TX polling only?
+ outb(Card->IOBase + REG_CR1, 0); // Disabled TX polling only?
LOG("ISR state: %02x %02x", inb(Card->IOBase + REG_ISR0), inb(Card->IOBase + REG_ISR1));
}
}
nDesc = 0;
- desc = card->FirstRX;
+ desc = card->NextRX;
while( !(desc->Length & (1 << 15)) )
{
// LOG("desc(%p) = {RSR:%04x,Length:%04x,BufferSize:%04x,RXBufferStart:%08x,RDBranchAddress:%08x}",
LOG("%i descriptors in packet", nDesc);
ret = IPStack_Buffer_CreateBuffer(nDesc);
- desc = card->FirstRX;
+ desc = card->NextRX;
while( !(desc->Length & (1 << 15)) )
{
void *data = Rhine2_int_GetBufferFromPhys(card, desc->RXBufferStart);
);
desc = Rhine2_int_GetDescFromPhys(card, desc->RDBranchAddress);
}
- card->FirstRX = desc;
+ card->NextRX = desc;
LEAVE('p', ret);
return ret;
void Rhine2_int_FreeRXDesc(void *Ptr, size_t u1, size_t u2, const void *u3)
{
struct sRXDesc *desc = Ptr;
+
+ LOG("Descriptor %p returned to card", desc);
desc->RSR = 0;
desc->Length = (1 << 15); // Reset OWN
/*
+ *
+ * http://www.ietf.org/rfc/rfc2131.txt
*/
#include <unistd.h>
#include <stdint.h>
int Num;
int SocketFD;
int IfaceFD;
+
+ uint32_t TransactionID;
+ char HWAddr[6];
+
+ int64_t Timeout;
} tInterface;
// === PROTOTYPES ===
void Send_DHCPDISCOVER(tInterface *Iface);
void Send_DHCPREQUEST(tInterface *Iface, void *OfferBuffer, int TypeOffset);
int Handle_Packet(tInterface *Iface);
+void Handle_Timeout(tInterface *Iface);
+void Update_State(tInterface *Iface, int newState);
void SetAddress(tInterface *Iface, void *Addr, void *Mask, void *Router);
// === CODE ===
for( i = ifaces; i; i = i->Next )
{
- i->State = STATE_PREINIT;
if( Start_Interface(i) < 0 ) {
return -1;
}
+ i->State = STATE_PREINIT;
// Send request
Send_DHCPDISCOVER(i);
int maxfd;
fd_set fds;
tInterface *p;
+ int64_t timeout = 1000;
maxfd = 0;
FD_ZERO(&fds);
FD_SET(i->SocketFD, &fds);
if(maxfd < i->SocketFD) maxfd = i->SocketFD;
}
- if( select(maxfd+1, &fds, NULL, NULL, NULL) < 0 )
+
+ if( select(maxfd+1, &fds, NULL, NULL, &timeout) < 0 )
{
// TODO: Check error result
return -1;
}
+ _SysDebug("select() returned");
+
// Check for changes (with magic to allow inline deletion)
for( p = (void*)&ifaces, i = ifaces; i; p=i,i = i->Next )
{
i = p;
}
}
+
+ if( _SysTimestamp() > i->Timeout )
+ {
+ Handle_Timeout(i);
+ }
}
}
return 0;
// TODO: Check that the adapter is not in use
+ // Request MAC address from network adapter
+ {
+ char path[] = "/Devices/ip/adapters/ethXXXX";
+ sprintf(path, "/Devices/ip/adapters/%s", Iface->Adapter);
+ fd = open(path, 0);
+ if(fd == -1) {
+ _SysDebug("Unable to open adapter %s", path);
+ return -1;
+ }
+ ioctl(fd, 4, Iface->HWAddr);
+ // TODO: Check if ioctl() failed
+ close(fd);
+ }
+
// Initialise an interface, with a dummy IP address (zero)
fd = open("/Devices/ip", 0);
if( fd == -1 ) {
return 0;
}
+void Send_DHCPRELEASE(tInterface *Iface)
+{
+}
+
void Send_DHCPDISCOVER(tInterface *Iface)
{
uint32_t transaction_id;
char data[8 + sizeof(struct sDHCP_Message) + 3 + 1];
msg = (void*)data + 8;
+ _SysDebug("DHCPDISCOVER to %s", Iface->Adapter);
+
transaction_id = rand();
+ Iface->TransactionID = transaction_id;
msg->op = htonb(1); // BOOTREQUEST
msg->htype = htonb(1); // 10mb Ethernet
msg->hops = htonb(0); // Hop count so far
msg->xid = htonl(transaction_id); // Transaction ID
msg->secs = htons(0); // secs - No time has elapsed
- msg->flags = htons(0); // flags - TODO: Check if broadcast bit need be set
+ msg->flags = htons(0x0000); // flags - Broadcast is unset
msg->ciaddr = htonl(0); // ciaddr - Zero, as we don't have one yet
msg->yiaddr = htonl(0); // yiaddr - Zero?
msg->siaddr = htonl(0); // siaddr - Zero? maybe -1
msg->giaddr = htonl(0); // giaddr - Zero?
- // Request MAC address from network adapter
- {
- char path[] = "/Devices/ip/adapters/ethXXXX";
- sprintf(path, "/Devices/ip/adapters/%s", Iface->Adapter);
- int fd = open(path, 0);
- if(fd == -1) {
- _SysDebug("Unable to open adapter %s", path);
- }
- else {
- ioctl(fd, 4, msg->chaddr);
- // TODO: Check if ioctl() failed
- close(fd);
- }
- }
+ memcpy(msg->chaddr, Iface->HWAddr, 6);
+
memset(msg->sname, 0, sizeof(msg->sname)); // Nuke the rest
memset(msg->file, 0, sizeof(msg->file)); // Nuke the rest
msg->dhcp_magic = htonl(DHCP_MAGIC);
data[4] = 255; data[5] = 255; data[6] = 255; data[7] = 255;
write(Iface->SocketFD, data, sizeof(data));
- Iface->State = STATE_DISCOVER_SENT;
+ Update_State(Iface, STATE_DISCOVER_SENT);
}
void Send_DHCPREQUEST(tInterface *Iface, void *OfferPacket, int TypeOffset)
{
struct sDHCP_Message *msg;
+ int i;
msg = (void*) ((char*)OfferPacket) + 8;
// Reuses old data :)
- msg->op = 1;
- msg->options[TypeOffset+2] = 3; // DHCPREQUEST
- msg->options[TypeOffset+3] = 255;
+ msg->op = 1;
+ msg->htype = 1;
+ msg->hlen = 6;
+ msg->hops = 0;
+ msg->xid = msg->xid;
+ msg->secs = htons(0); // TODO: Maintain times
+ msg->flags = htons(0);
+ memcpy(msg->chaddr, Iface->HWAddr, 6);
+ memset(msg->sname, 0, sizeof(msg->sname)); // Nuke the rest
+ memset(msg->file, 0, sizeof(msg->file)); // Nuke the rest
+
+ i = 0;
+ msg->options[i++] = 53; // Message type = DHCPREQUEST
+ msg->options[i++] = 1;
+ msg->options[i++] = 3;
+ msg->options[i++] = 50; // Requested Address
+ msg->options[i++] = 4;
+ memcpy(msg->options + i, &msg->yiaddr, 4); i += 4;
+// msg->options[i++] = 54; // Server identifier
+// msg->options[i++] = 4;
+// memcpy(msg->options + i, (char*)OfferPacket + 4, 4); i += 4;
+ msg->options[i++] = 255;
- write(Iface->SocketFD, OfferPacket, 8 + sizeof(*msg) + TypeOffset + 4);
- Iface->State = STATE_REQUEST_SENT;
+ // Clear last because yiaddr is needed in option setup
+ msg->ciaddr = htonl(0);
+ msg->yiaddr = htonl(0);
+ msg->siaddr = htonl(0);
+ msg->giaddr = htonl(0);
+
+ // HACK
+ ((uint8_t*)OfferPacket)[4] = 255;
+ ((uint8_t*)OfferPacket)[5] = 255;
+ ((uint8_t*)OfferPacket)[6] = 255;
+ ((uint8_t*)OfferPacket)[7] = 255;
+
+ write(Iface->SocketFD, OfferPacket, 8 + sizeof(*msg) + i);
+ Update_State(Iface, STATE_REQUEST_SENT);
}
int Handle_Packet(tInterface *Iface)
return 0;
}
+
+ // Check if the packet is related to our requests
+ if( ntohl(msg->xid) != Iface->TransactionID ) {
+ _SysDebug("Transaction ID mis-match, ignoring (0x%x != 0x%x)",
+ ntohl(msg->xid), Iface->TransactionID);
+ return 0;
+ }
+ if( memcmp(msg->chaddr, Iface->HWAddr, 6) != 0 ) {
+ _SysDebug("Hardware address mis-match, ignoring");
+ return 0;
+ }
+
+ // Parse options
i = 0;
while( i < len - sizeof(*msg) - 8 && msg->options[i] != 255 )
{
case 4: // DHCPDECLINE - ?
break;
case 5: // DHCPACK
- // TODO: Apply address
SetAddress(Iface, &msg->yiaddr, subnet_mask, router);
+ // Return 1 to remove from list
return 1;
}
return 0;
}
+void Handle_Timeout(tInterface *Iface)
+{
+ switch(Iface->State)
+ {
+ case STATE_DISCOVER_SENT:
+ Send_DHCPDISCOVER(Iface);
+ break;
+ default:
+ _SysDebug("Timeout with state = %i", Iface->State);
+ break;
+ }
+}
+
+void Update_State(tInterface *Iface, int newState)
+{
+ if( Iface->State != newState )
+ {
+ Iface->Timeout = _SysTimestamp() + 500;
+ Iface->State = newState;
+ }
+ else
+ {
+ // TODO: Exponential backoff
+ Iface->Timeout = _SysTimestamp() + 3000;
+ _SysDebug("State %i repeated, timeout is 3000ms now", newState);
+ }
+}
+
void SetAddress(tInterface *Iface, void *Addr, void *Mask, void *Router)
{
int mask_bits = 0;
SYSCALL1(SysSetName, SYS_SETNAME)
SYSCALL2(SysGetName, SYS_GETNAME)
+SYSCALL0(_SysTimestamp, SYS_GETTIME)
SYSCALL1(SysSetPri, SYS_SETPRI)
EXP(SysSetName),
//EXP(SysGetName),
+ EXP(_SysTimestamp),
+
//EXP(SysSetPri),
EXP(SysSendMessage),
extern int _SysSetFaultHandler(int (*Handler)(int));
extern void SysSetName(const char *Name);
//extern int SysGetName(const char *Name);
+extern int64_t _SysTimestamp(void);
// --- Permissions ---
extern int getuid(void);