6 #define VERSION VER2(0,10)
9 #include <api_drv_common.h>
10 #include "include/adapters.h"
11 #include "interface.h"
14 //! Default timeout value, 5 seconds
15 #define DEFAULT_TIMEOUT (5*1000)
18 extern int IPv4_Ping(tInterface *Iface, tIPv4 Addr);
19 //extern int IPv6_Ping(tInterface *Iface, tIPv6 Addr);
20 extern tVFS_Node gIP_RouteNode;
21 extern tVFS_Node gIP_AdaptersNode;
24 int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
25 tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
26 int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
28 int IPStack_AddFile(tSocketFile *File);
29 tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name);
31 int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
32 tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
33 int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data);
36 tVFS_NodeType gIP_RootNodeType = {
37 .ReadDir = IPStack_Root_ReadDir,
38 .FindDir = IPStack_Root_FindDir,
39 .IOCtl = IPStack_Root_IOCtl
41 tVFS_NodeType gIP_InterfaceNodeType = {
42 .ReadDir = IPStack_Iface_ReadDir,
43 .FindDir = IPStack_Iface_FindDir,
44 .IOCtl = IPStack_Iface_IOCtl
46 //! Loopback (127.0.0.0/8, ::1) Pseudo-Interface
47 tInterface gIP_LoopInterface = {
49 .ImplPtr = &gIP_LoopInterface,
50 .Flags = VFS_FFLAG_DIRECTORY,
53 .ACLs = &gVFS_ACL_EveryoneRX,
54 .Type = &gIP_InterfaceNodeType
59 tShortSpinlock glIP_Interfaces;
60 tInterface *gIP_Interfaces = NULL;
61 tInterface *gIP_Interfaces_Last = NULL;
62 int giIP_NextIfaceId = 1;
64 tSocketFile *gIP_FileTemplates;
69 * \brief Read from the IP Stack's Device Directory
71 int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
74 ENTER("pNode iPos", Node, Pos);
79 strcpy(Dest, "routes");
84 strcpy(Dest, "adapters");
95 for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
97 // Did we run off the end?
99 LEAVE('i', -EINTERNAL);
104 strncpy(Dest, iface->Name, FILENAME_MAX);
111 * \brief Get the node of an interface
113 tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
117 ENTER("pNode sName", Node, Name);
120 if( strcmp(Name, "routes") == 0 ) {
121 LEAVE('p', &gIP_RouteNode);
122 return &gIP_RouteNode;
126 if( strcmp(Name, "adapters") == 0 ) {
127 LEAVE('p', &gIP_AdaptersNode);
128 return &gIP_AdaptersNode;
132 if( strcmp(Name, "lo") == 0 ) {
133 LEAVE('p', &gIP_LoopInterface.Node);
134 return &gIP_LoopInterface.Node;
137 for( iface = gIP_Interfaces; iface; iface = iface->Next )
139 if( strcmp(iface->Name, Name) == 0 )
141 LEAVE('p', &iface->Node);
150 static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL };
152 * \brief Handles IOCtls for the IPStack root
154 int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data)
157 ENTER("pNode iID pData", Node, ID, Data);
161 // --- Standard IOCtls (0-3) ---
162 BASE_IOCTLS(DRV_TYPE_MISC, "IPStack", VERSION, casIOCtls_Root)
166 * - Adds a new interface and binds it to a device
175 if( Threads_GetUID() != 0 )
177 if( !CheckMem(ifinfo, sizeof(*ifinfo)) )
179 if( !MM_IsUser(ifinfo->Device) || !CheckString( ifinfo->Device ) )
181 if( !MM_IsUser(ifinfo->Name) || !CheckString( ifinfo->Name ) )
184 LOG("New interface of type %i for '%s' named '%s'",
185 ifinfo->Type, ifinfo->Device, ifinfo->Name);
186 tInterface *iface = IPStack_AddInterface(ifinfo->Device, ifinfo->Type, ifinfo->Name);
187 if(iface == NULL) LEAVE_RET('i', -1);
189 tmp = iface->Node.ImplInt;
198 * \fn tInterface *IPStack_AddInterface(char *Device)
199 * \brief Adds an interface to the list
201 tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name)
205 int nameLen, addrsize;
207 ENTER("sDevice", Device);
209 // Check address type
210 addrsize = IPStack_GetAddressSize(Type);
211 if( addrsize == -1 ) {
212 Log_Debug("IPStack", "Bad address type %i", Type);
217 card = Adapter_GetByName(Device);
219 Log_Debug("IPStack", "Unable to open card '%s'", Device);
221 return NULL; // ERR_YOURBAD
227 nameLen = strlen(Name);
231 nameLen = snprintf(NULL, 0, "%i", giIP_NextIfaceId);
237 + addrsize*3 // Address, Route->Network, Route->NextHop
240 Log_Warning("IPStack", "AddInterface - malloc() failed");
243 return NULL; // Return ERR_MYBAD
247 iface->Type = Type; // Unset type
248 iface->Address = iface->Name + nameLen + 1; // Address
249 memset(iface->Address, 0, addrsize);
250 memset(&iface->Route, 0, sizeof(iface->Route));
251 iface->Route.Network = iface->Address + addrsize;
252 memset(iface->Route.Network, 0, addrsize);
253 iface->Route.NextHop = iface->Route.Network + addrsize;
254 memset(iface->Route.NextHop, 0, addrsize);
257 iface->Node.ImplPtr = iface;
258 iface->Node.Flags = VFS_FFLAG_DIRECTORY;
259 iface->Node.Size = -1;
260 iface->Node.NumACLs = 1;
261 iface->Node.ACLs = &gVFS_ACL_EveryoneRX;
262 iface->Node.Type = &gIP_InterfaceNodeType;
265 iface->TimeoutDelay = DEFAULT_TIMEOUT;
267 // Get adapter handle
268 iface->Adapter = card;
273 iface->Node.ImplInt = 0;
274 strcpy(iface->Name, Name);
278 iface->Node.ImplInt = giIP_NextIfaceId++;
279 sprintf(iface->Name, "%i", (int)iface->Node.ImplInt);
282 LOG("Creating interface '%s'", iface->Name);
285 SHORTLOCK( &glIP_Interfaces );
286 if( gIP_Interfaces ) {
287 gIP_Interfaces_Last->Next = iface;
288 gIP_Interfaces_Last = iface;
291 gIP_Interfaces = iface;
292 gIP_Interfaces_Last = iface;
294 SHORTREL( &glIP_Interfaces );
302 * \brief Adds a file to the socket list
304 int IPStack_AddFile(tSocketFile *File)
306 // Log_Log("IPStack", "Added file '%s'", File->Name);
307 File->Next = gIP_FileTemplates;
308 gIP_FileTemplates = File;
316 * \brief Read from an interface's directory
318 int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
320 tSocketFile *file = gIP_FileTemplates;
321 while(Pos-- && file) {
328 strncpy(Dest, file->Name, FILENAME_MAX);
333 * \brief Gets a named node from an interface directory
335 tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
337 tSocketFile *file = gIP_FileTemplates;
339 // Get file definition
340 for(;file;file = file->Next)
342 if( strcmp(file->Name, Name) == 0 ) break;
345 LOG("File '%s' unknown", Name);
350 LOG("File '%s' calling %p", file->Init);
351 return file->Init(Node->ImplPtr);
355 * \brief Names for interface IOCtl Calls
357 static const char *casIOCtls_Iface[] = {
360 "get_address", "set_address",
367 * \brief Handles IOCtls for the IPStack interfaces
369 int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
372 tInterface *iface = (tInterface*)Node->ImplPtr;
373 ENTER("pNode iID pData", Node, ID, Data);
377 // --- Standard IOCtls (0-3) ---
378 BASE_IOCTLS(DRV_TYPE_MISC, "IPStack", VERSION, casIOCtls_Iface)
382 * - Get/Set the interface type
390 if( Threads_GetUID() != 0 ) {
391 LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID());
395 if( !CheckMem( Data, sizeof(int) ) ) {
396 LOG("Invalid pointer %p", Data);
402 iface->Type = *(int*)Data;
403 LOG("Interface type set to %i", iface->Type);
404 size = IPStack_GetAddressSize(iface->Type);
405 // Check it's actually valid
406 if( iface->Type != 0 && size == 0 ) {
413 memset(iface->Address, 0, size);
415 Log_Notice("IPStack", "Interface ioctl(settype) no longer usable");
417 LEAVE('i', iface->Type);
422 * - Get the interface's address
425 size = IPStack_GetAddressSize(iface->Type);
426 if( !CheckMem( Data, size ) ) LEAVE_RET('i', -1);
427 memcpy( Data, iface->Address, size );
433 * - Set the interface's address
436 if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1);
438 size = IPStack_GetAddressSize(iface->Type);
439 if( !CheckMem( Data, size ) ) LEAVE_RET('i', -1);
440 // TODO: Protect against trashing
441 LOG("Interface address set to '%s'", IPStack_PrintAddress(iface->Type, Data));
442 memcpy( iface->Address, Data, size );
447 * - Get/Set the bits in the address subnet
450 // Do we want to set the value?
453 // Are we root? (TODO: Check Owner/Group)
454 if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1);
455 // Is the memory valid
456 if( !CheckMem(Data, sizeof(int)) ) LEAVE_RET('i', -1);
459 if( *(int*)Data < 0 || *(int*)Data > IPStack_GetAddressSize(iface->Type)*8-1 )
461 LOG("Set subnet bits to %i", *(int*)Data);
463 iface->SubnetBits = *(int*)Data;
465 LEAVE_RET('i', iface->SubnetBits);
469 * - Gets the name of the attached device
472 if( iface->Adapter == NULL )
474 char *name = Adapter_GetName(iface->Adapter);
475 int len = strlen(name);
477 if( !CheckMem( Data, len+1 ) ) {
481 strcpy( Data, name );
488 * - Send an ICMP Echo
497 if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1);
498 tmp = IPv4_Ping(iface, *(tIPv4*)Data);