2 * Acess2 Networking Stack
3 * - By John Hodge (thePowersGang)
6 * - Network Adapter Management
9 #define VERSION VER2(0,1)
11 #include "include/buffer.h"
12 #include "include/adapters.h"
13 #include "include/adapters_int.h"
15 #include <api_drv_common.h> // For the VFS hack
16 #include <api_drv_network.h>
19 // --- "External" (NIC) API ---
20 void *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr);
21 void IPStack_Adapter_Del(void *Handle);
23 int Adapter_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
24 tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
25 int Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data);
26 int Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data);
27 // --- "Internal" (IPStack) API ---
28 tAdapter *Adapter_GetByName(const char *Name);
29 void Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer);
31 void Adapter_int_WatchThread(void *Ptr);
32 tIPStackBuffer *Adapter_int_LoopbackWaitPacket(void *Unused);
33 int Adapter_int_LoopbackSendPacket(void *Unused, tIPStackBuffer *Buffer);
37 tVFS_NodeType gIP_AdaptersDirType = {
38 .ReadDir = Adapter_ReadDir,
39 .FindDir = Adapter_FindDir,
40 .IOCtl = Adapter_DirIOCtl
42 tVFS_NodeType gIP_AdapterType = {
43 // TODO: Should direct IO be allowed?
44 .IOCtl = Adapter_IOCtl
46 tVFS_Node gIP_AdaptersNode = {
47 .Type = &gIP_AdaptersDirType,
48 .Flags = VFS_FFLAG_DIRECTORY,
51 // --- Loopback Adapter ---
52 tIPStack_AdapterType gIP_LoopAdapterType = {
54 .WaitForPacket = Adapter_int_LoopbackWaitPacket,
55 .SendPacket = Adapter_int_LoopbackSendPacket
57 tAdapter gIP_LoopAdapter;
58 // --- Main adapter list ---
60 tAdapter *gpIP_AdapterList;
61 tAdapter *gpIP_AdapterList_Last = (void*)&gpIP_AdapterList; // HACK!
62 int giIP_NextAdapterIndex;
65 // --- "External" (NIC) API ---
66 void *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr)
70 ret = malloc(sizeof(tAdapter) + 6); // TODO: Don't assume 6-byte MAC addresses
73 ret->CardHandle = Ptr;
75 ret->Index = giIP_NextAdapterIndex++;
76 memcpy(ret->HWAddr, HWAddr, 6);
78 memset(&ret->Node, 0, sizeof(ret->Node));
79 ret->Node.Type = &gIP_AdapterType;
80 ret->Node.ImplPtr = ret;
82 Mutex_Acquire( &glIP_Adapters );
83 gpIP_AdapterList_Last->Next = ret;
84 gpIP_AdapterList_Last = ret;
85 Mutex_Release( &glIP_Adapters );
87 Log_Log("IPStack", "Adapter %i: %s %02x:%02x:%02x:%02x:%02x:%02x",
88 ret->Index, Type->Name,
89 ret->HWAddr[0], ret->HWAddr[1], ret->HWAddr[2],
90 ret->HWAddr[3], ret->HWAddr[4], ret->HWAddr[5]
93 // Watch the adapter for incoming packets
94 void *worker = Proc_SpawnWorker(Adapter_int_WatchThread, ret);
96 Log_Warning("IPStack", "Unable to create watcher thread for %p", ret);
102 void *IPStack_Adapter_AddVFS(const char *Path)
107 ENTER("sPath", Path);
110 fd = VFS_Open( Path, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
116 // Check that it is a network interface
117 tmp = VFS_IOCtl(fd, 0, NULL);
118 LOG("Device type = %i", tmp);
119 if( tmp != DRV_TYPE_NETWORK ) {
120 Log_Warning("IPStack", "IPStack_Adapter_AddVFS: '%s' is not a network interface", Path);
127 VFS_IOCtl(fd, NET_IOCTL_GETMAC, mac);
129 return IPStack_Adapter_Add(NULL, (void*)(tVAddr)fd, mac);
132 void IPStack_Adapter_Del(void *Handle)
134 Log_Error("IPStack", "TODO: Implement IPStack_Adapter_Del");
135 // TODO: Allow removing adapters during system operation
139 int Adapter_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
141 if( Pos < 0 ) return -EINVAL;
150 #define CHECK_LIST(list, type) do{ \
152 for(i=0,a=list; i < Pos && a; i ++, a = a->Next ); \
154 strncpy(Dest, Adapter_GetName(a), FILENAME_MAX);\
160 CHECK_LIST(gpIP_AdapterList, "eth");
161 // TODO: Support other types of adapters (wifi, tap, ...)
166 tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
168 tAdapter *a = Adapter_GetByName(Name);
175 static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_vfs_adapter", NULL };
176 int Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data)
180 BASE_IOCTLS(DRV_TYPE_MISC, "IPStack-AdapterList", VERSION, casIOCtls_Root)
183 if( !CheckString(Data) )
186 // Return non-zero if add fails
187 return IPStack_Adapter_AddVFS(Data) == NULL;
192 static const char *casIOCtls_Dev[] = { DRV_IOCTLNAMES, "get_hwaddr", NULL };
193 int Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data)
195 tAdapter *adapter = Node->ImplPtr;
198 BASE_IOCTLS(DRV_TYPE_MISC, "IPStack-Adapter", VERSION, casIOCtls_Dev)
201 if( !CheckMem(Data, 6) )
204 memcpy(Data, adapter->HWAddr, 6);
210 // --- "Internal" (IPStack) API ---
211 tAdapter *Adapter_GetByName(const char *Name)
213 if( strcmp(Name, "lo") == 0 ) {
214 return &gIP_LoopAdapter;
217 if( strncmp(Name, "eth", 3) == 0 )
219 // Possibly an ethX interface
222 // Get the index at the end
223 ofs = ParseInt(Name + 3, &index);
224 if( ofs == 0 || Name[3+ofs] != '\0' )
227 // Find the adapter with that index
228 for( tAdapter *a = gpIP_AdapterList; a && a->Index <= index; a = a->Next ) {
229 if( a->Index == index )
239 char *Adapter_GetName(tAdapter *Adapter)
241 if( Adapter == &gIP_LoopAdapter )
247 // TODO: Support multiple adapter types
248 char buf[sizeof("eth")+10];
249 sprintf(buf, "eth%i", Adapter->Index);
254 void Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer)
256 if( Handle->Type == NULL )
259 void *data = IPStack_Buffer_CompactBuffer(Buffer, &outlen);
260 VFS_Write((tVAddr)Handle->CardHandle, outlen, data);
265 Handle->Type->SendPacket( Handle->CardHandle, Buffer );
268 IPStack_Buffer_DestroyBuffer(Buffer);
272 void Adapter_int_WatchThread(void *Ptr)
274 tAdapter *Adapter = Ptr;
275 const int MTU = 1520;
276 tIPStackBuffer *buf = NULL;
279 if( Adapter->Type == NULL )
281 data = malloc( MTU );
282 buf = IPStack_Buffer_CreateBuffer(1);
286 Threads_SetName("Adapter Watcher");
287 Log_Log("IPStack", "Thread %i watching eth%i '%s'", Threads_GetTID(), Adapter->Index,
288 Adapter->Type?Adapter->Type->Name:"VFS");
292 if( Adapter->Type == NULL )
294 int len = VFS_Read((tVAddr)Adapter->CardHandle, MTU, data);
295 IPStack_Buffer_AppendSubBuffer(buf, len, 0, buf, NULL, NULL);
299 buf = Adapter->Type->WaitForPacket( Adapter->CardHandle );
302 Link_HandlePacket(Adapter, buf);
304 if( Adapter->Type == NULL )
306 IPStack_Buffer_ClearBuffer(buf);
310 IPStack_Buffer_DestroyBuffer(buf);
315 tIPStackBuffer *Adapter_int_LoopbackWaitPacket(void *Unused)
321 int Adapter_int_LoopbackSendPacket(void *Unused, tIPStackBuffer *Buffer)
323 // This is a little hacky :)
324 Link_HandlePacket(&gIP_LoopAdapter, Buffer);
328 // --- Broadcast Debugging ---
329 extern Uint16 IPv4_Checksum(const void *Buf, size_t Length);
330 void IPStack_SendDebugText(const char *Text)
332 const Uint8 pkt_hdr[] = {
333 0xFF,0xFF, 0xFF,0xFF, 0xFF,0xFF,
334 0x00,0x00, 0x00,0x00, 0x00,0x00,
337 0x45,0x00, // Version/Length, DiffServices
338 0xFF,0xFF, // Total Length
339 0x00,0x00, // Identifcation
340 0x00,0x00, 0xFF,0x11, // Flags,Fragment, TTL=255,proto=UDP
341 0x00,0x00, // Header checksum
342 0x00,0x00,0x00,0x00, // Source
343 0xFF,0xFF,0xFF,0xFF, // Destination
345 0x80,0x00, 0x80,0x00,
346 0xFF,0xFF, 0xFF,0xFF,
348 static tShortSpinlock lLock;
350 // Fast return if there's no avaliable adapters
351 if( !gpIP_AdapterList )
354 if( CPU_HAS_LOCK(&lLock) )
358 __asm__ __volatile__ ("sti"); // Start interrupts (x86 specific)
361 // Cache packets until a newline
362 static char cache[1500 - (sizeof(pkt_hdr) + 4)];
363 static int cache_len;
365 int len = strlen(Text);
368 strncpy(cache + cache_len, Text, sizeof(cache) - cache_len);
370 // TODO: Detect overflows.
372 // If there's no newline, only buffer
373 if( strpos(Text, '\n') == -1 ) {
379 int link_checksum_ofs = sizeof(pkt_hdr) + cache_len;
380 char buffer[sizeof(pkt_hdr) + cache_len + 4];
382 memcpy(buffer, pkt_hdr, sizeof(pkt_hdr));
383 memcpy(buffer + sizeof(pkt_hdr), cache, cache_len);
385 ((Uint16*)buffer)[(14+2)/2] = BigEndian16( sizeof(pkt_hdr)-14 + cache_len ); // IP Size
386 ((Uint16*)buffer)[(14+10)/2] = BigEndian16( 0 ); // IP Header
387 ((Uint16*)buffer)[(14+20+4)/2] = BigEndian16( 8+cache_len ); // UDP Size
388 ((Uint16*)buffer)[(14+20+6)/2] = BigEndian16( 0 ); // UDP Checksum
389 // *(Uint32*)&buffer[link_checksum_ofs] = BigEndian32( 0 ); // 802.3 checksum?
390 // TODO: Calculate checksums
391 ((Uint16*)buffer)[(14+10)/2] = BigEndian16( IPv4_Checksum(buffer+14,20) ); // IP Header
394 tIPStackBuffer *buf = IPStack_Buffer_CreateBuffer(1);
395 IPStack_Buffer_AppendSubBuffer(buf, link_checksum_ofs+4, 0, buffer, NULL, NULL);
398 for( tAdapter *a = gpIP_AdapterList; a; a = a->Next )
400 a->Type->SendPacket( a->CardHandle, buf );
403 IPStack_Buffer_DestroyBuffer(buf);