#include "link.h"
#include <api_drv_common.h>
#include "include/adapters.h"
+#include "interface.h"
// === CONSTANTS ===
//! Default timeout value, 5 seconds
extern tVFS_Node gIP_AdaptersNode;
// === PROTOTYPES ===
-char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
+ int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
int IPStack_AddFile(tSocketFile *File);
-tInterface *IPStack_AddInterface(const char *Device, const char *Name);
+tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name);
-char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
+ int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data);
// === GLOBALS ===
+tVFS_NodeType gIP_RootNodeType = {
+ .ReadDir = IPStack_Root_ReadDir,
+ .FindDir = IPStack_Root_FindDir,
+ .IOCtl = IPStack_Root_IOCtl
+};
tVFS_NodeType gIP_InterfaceNodeType = {
.ReadDir = IPStack_Iface_ReadDir,
.FindDir = IPStack_Iface_FindDir,
/**
* \brief Read from the IP Stack's Device Directory
*/
-char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tInterface *iface;
- char *name;
ENTER("pNode iPos", Node, Pos);
// Routing Subdir
if( Pos == 0 ) {
- LEAVE('s', "routes");
- return strdup("routes");
+ strcpy(Dest, "routes");
+ return 0;
}
// Adapters
if( Pos == 1 ) {
- LEAVE('s', "adapters");
- return strdup("adapters");
+ strcpy(Dest, "adapters");
+ return 0;
}
// Pseudo Interfaces
if( Pos == 2 ) {
- LEAVE('s', "lo");
- return strdup("lo");
+ strcpy(Dest, "lo");
+ return 0;
}
Pos -= 3;
// Did we run off the end?
if(!iface) {
- LEAVE('n');
- return NULL;
- }
-
- name = malloc(4);
- if(!name) {
- Log_Warning("IPStack", "IPStack_Root_ReadDir - malloc error");
- LEAVE('n');
- return NULL;
+ LEAVE('i', -EINTERNAL);
+ return -EINVAL;
}
// Create the name
- Pos = iface->Node.ImplInt;
- if(Pos < 10) {
- name[0] = '0' + Pos;
- name[1] = '\0';
- }
- else if(Pos < 100) {
- name[0] = '0' + Pos/10;
- name[1] = '0' + Pos%10;
- name[2] = '\0';
- }
- else {
- name[0] = '0' + Pos/100;
- name[1] = '0' + (Pos/10)%10;
- name[2] = '0' + Pos%10;
- name[3] = '\0';
- }
+ strncpy(Dest, iface->Name, FILENAME_MAX);
- LEAVE('s', name);
- // Return the pre-generated name
- return name;
+ LEAVE('i', 0);
+ return 0;
}
/**
* \brief Get the node of an interface
*/
-tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
- #if 0
- int i, num;
- #endif
tInterface *iface;
ENTER("pNode sName", Node, Name);
/*
* add_interface
- * - Adds a new IP interface and binds it to a device
+ * - Adds a new interface and binds it to a device
*/
- case 4:
- if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1);
- if( !CheckString( Data ) ) LEAVE_RET('i', -1);
- LOG("New interface for '%s'", Data);
- {
- char name[4] = "";
- tInterface *iface = IPStack_AddInterface(Data, name);
- if(iface == NULL) LEAVE_RET('i', -1);
- tmp = iface->Node.ImplInt;
- }
+ case 4: {
+ const struct {
+ const char *Device;
+ const char *Name;
+ int Type;
+ } *ifinfo = Data;
+
+ if( Threads_GetUID() != 0 )
+ LEAVE_RET('i', -1);
+ if( !CheckMem(ifinfo, sizeof(*ifinfo)) )
+ LEAVE_RET('i', -1);
+ if( !MM_IsUser(ifinfo->Device) || !CheckString( ifinfo->Device ) )
+ LEAVE_RET('i', -1);
+ if( !MM_IsUser(ifinfo->Name) || !CheckString( ifinfo->Name ) )
+ LEAVE_RET('i', -1);
+
+ LOG("New interface of type %i for '%s' named '%s'",
+ ifinfo->Type, ifinfo->Device, ifinfo->Name);
+ tInterface *iface = IPStack_AddInterface(ifinfo->Device, ifinfo->Type, ifinfo->Name);
+ if(iface == NULL) LEAVE_RET('i', -1);
+
+ tmp = iface->Node.ImplInt;
LEAVE_RET('i', tmp);
+ }
}
LEAVE('i', 0);
return 0;
* \fn tInterface *IPStack_AddInterface(char *Device)
* \brief Adds an interface to the list
*/
-tInterface *IPStack_AddInterface(const char *Device, const char *Name)
+tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name)
{
tInterface *iface;
tAdapter *card;
- int nameLen;
+ int nameLen, addrsize;
ENTER("sDevice", Device);
+ // Check address type
+ addrsize = IPStack_GetAddressSize(Type);
+ if( addrsize == -1 ) {
+ Log_Debug("IPStack", "Bad address type %i", Type);
+ return NULL;
+ }
+
+ // Open card
card = Adapter_GetByName(Device);
if( !card ) {
Log_Debug("IPStack", "Unable to open card '%s'", Device);
LEAVE('n');
return NULL; // ERR_YOURBAD
}
-
- nameLen = sprintf(NULL, "%i", giIP_NextIfaceId);
-
+
+ // Get name length
+ if( Name[0] )
+ {
+ nameLen = strlen(Name);
+ }
+ else
+ {
+ nameLen = snprintf(NULL, 0, "%i", giIP_NextIfaceId);
+ }
+
iface = malloc(
sizeof(tInterface)
+ nameLen + 1
- + IPStack_GetAddressSize(-1)*3 // Address, Route->Network, Route->NextHop
+ + addrsize*3 // Address, Route->Network, Route->NextHop
);
if(!iface) {
Log_Warning("IPStack", "AddInterface - malloc() failed");
+ // TODO: Close card
LEAVE('n');
return NULL; // Return ERR_MYBAD
}
iface->Next = NULL;
- iface->Type = 0; // Unset type
+ iface->Type = Type; // Unset type
iface->Address = iface->Name + nameLen + 1; // Address
+ memset(iface->Address, 0, addrsize);
memset(&iface->Route, 0, sizeof(iface->Route));
- iface->Route.Network = iface->Address + IPStack_GetAddressSize(-1);
- iface->Route.NextHop = iface->Route.Network + IPStack_GetAddressSize(-1);
+ iface->Route.Network = iface->Address + addrsize;
+ memset(iface->Route.Network, 0, addrsize);
+ iface->Route.NextHop = iface->Route.Network + addrsize;
+ memset(iface->Route.NextHop, 0, addrsize);
// Create Node
iface->Node.ImplPtr = iface;
// Get adapter handle
iface->Adapter = card;
- // Delay setting ImplInt until after the adapter is opened
- // Keeps things simple
- iface->Node.ImplInt = giIP_NextIfaceId++;
- sprintf(iface->Name, "%i", (int)iface->Node.ImplInt);
+ // Set name
+ if( Name[0] )
+ {
+ iface->Node.ImplInt = 0;
+ strcpy(iface->Name, Name);
+ }
+ else
+ {
+ iface->Node.ImplInt = giIP_NextIfaceId++;
+ sprintf(iface->Name, "%i", (int)iface->Node.ImplInt);
+ }
+
+ LOG("Creating interface '%s'", iface->Name);
// Append to list
SHORTLOCK( &glIP_Interfaces );
}
SHORTREL( &glIP_Interfaces );
-// gIP_DriverInfo.RootNode.Size ++;
-
// Success!
LEAVE('p', iface);
return iface;
*/
int IPStack_AddFile(tSocketFile *File)
{
- Log_Log("IPStack", "Added file '%s'", File->Name);
+// Log_Log("IPStack", "Added file '%s'", File->Name);
File->Next = gIP_FileTemplates;
gIP_FileTemplates = File;
return 0;
/**
* \brief Read from an interface's directory
*/
-char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tSocketFile *file = gIP_FileTemplates;
while(Pos-- && file) {
file = file->Next;
}
- if(!file) return NULL;
+ if(!file)
+ return -EINVAL;
- return strdup(file->Name);
+ strncpy(Dest, file->Name, FILENAME_MAX);
+ return 0;
}
/**
* \brief Gets a named node from an interface directory
*/
-tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tSocketFile *file = gIP_FileTemplates;
{
if( strcmp(file->Name, Name) == 0 ) break;
}
- if(!file) return NULL;
+ if(!file) {
+ LOG("File '%s' unknown", Name);
+ return NULL;
+ }
// Pass the buck!
+ LOG("File '%s' calling %p", file->Init);
return file->Init(Node->ImplPtr);
}
// Set Type?
if( Data )
{
+#if 0
// Ok, it's set type
if( Threads_GetUID() != 0 ) {
LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID());
// Clear address
memset(iface->Address, 0, size);
+#endif
+ Log_Notice("IPStack", "Interface ioctl(settype) no longer usable");
}
LEAVE('i', iface->Type);
return iface->Type;