3 * - Address Resolution Protocol
6 #define VERSION ((0<<8)|10)
10 #include <tpl_drv_common.h>
11 #include <tpl_drv_network.h>
17 int IPStack_Install(char **Arguments);
18 char *IPStack_ReadDir(tVFS_Node *Node, int Pos);
19 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name);
20 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data);
21 int IPStack_AddInterface(char *Device);
22 tAdapter *IPStack_GetAdapter(char *Path);
25 MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL);
26 tDevFS_Driver gIP_DriverInfo = {
29 .Size = 0, // Number of interfaces
31 .ACLs = &gVFS_ACL_EveryoneRX,
32 .Flags = VFS_FFLAG_DIRECTORY,
33 .ReadDir = IPStack_ReadDir,
34 .FindDir = IPStack_FindDir
37 int glIP_Interfaces = 0;
38 tInterface *gIP_Interfaces = NULL;
39 tInterface *gIP_Interfaces_Last = NULL;
40 int glIP_Adapters = 0;
41 tAdapter *gIP_Adapters = NULL;
45 * \fn int IPStack_Install(char **Arguments)
46 * \brief Intialise the relevant parts of the stack and register with DevFS
48 int IPStack_Install(char **Arguments)
55 // Parse module arguments
56 for( i = 0; Arguments[i]; i++ )
58 //if(strcmp(Arguments[i], "Device") == '=') {
67 * \brief Read from the IP Stack's Device Directory
69 char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
72 char name[5] = "ip0\0\0";
78 name[2] = '0' + Pos/10;
79 name[3] = '0' + Pos%10;
83 for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
85 // Did we run off the end?
86 if(!iface) return NULL;
88 // Return the pre-generated name
93 * \brief Get the node of an interface
95 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
100 if(Name[0] != 'i' || Name[1] != 'p') return NULL;
101 if(Name[2] < '0' || Name[2] > '9') return NULL;
103 if(Name[3] == '\0') {
105 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
106 if(!iface) return NULL;
110 if(Name[3] < '0' || Name[3] > '9') return NULL;
112 i = (Name[2] - '0')*10;
115 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
116 if(!iface) return NULL;
120 static const char *casIOCtls[] = { DRV_IOCTLNAMES, "add_interface", NULL };
122 * \brief Handles IOCtls for the IPStack root
124 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
128 // --- Standard IOCtls (0-3) ---
130 return DRV_TYPE_MISC;
132 case DRV_IOCTL_IDENT:
133 if( !CheckMem( Data, 4 ) ) return -1;
134 memcpy(Data, "IP\0\0", 4);
137 case DRV_IOCTL_VERSION:
140 case DRV_IOCTL_LOOKUP:
141 if( !CheckString( Data ) ) return -1;
142 return LookupString( (char**)casIOCtls, (char*)Data );
144 // --- Non-Standard IOCtls ---
147 * - Adds a new IP interface and binds it to a device
150 if( !CheckString( Data ) ) return -1;
151 return IPStack_AddInterface(Data);
158 * \fn int IPStack_AddInterface(char *Device)
159 * \brief Adds an interface to the list
161 int IPStack_AddInterface(char *Device)
165 iface = malloc(sizeof(tInterface));
166 if(!iface) return -2; // Return ERR_MYBAD
169 iface->Type = 0; // Unset type
172 iface->Node.Flags = VFS_FFLAG_DIRECTORY;
173 iface->Node.Size = 0;
174 iface->Node.NumACLs = 1;
175 iface->Node.ACLs = &gVFS_ACL_EveryoneRX;
176 iface->Node.ReadDir = NULL;
177 iface->Node.FindDir = NULL;
179 // Get adapter handle
180 iface->Adapter = IPStack_GetAdapter(Device);
181 if( !iface->Adapter ) {
183 return -1; // Return ERR_YOUFAIL
187 LOCK( &glIP_Interfaces );
188 if( gIP_Interfaces ) {
189 gIP_Interfaces_Last->Next = iface;
190 gIP_Interfaces_Last = iface;
193 gIP_Interfaces = iface;
194 gIP_Interfaces_Last = iface;
196 RELEASE( &glIP_Interfaces );
203 * \fn tAdapter *IPStack_GetAdapter(char *Path)
204 * \brief Gets/opens an adapter given the path
206 tAdapter *IPStack_GetAdapter(char *Path)
210 LOCK( &glIP_Adapters );
212 // Check if this adapter is already open
213 for( dev = gIP_Adapters; dev; dev = dev->Next )
215 if( strcmp(dev->Device, Path) == 0 ) {
217 RELEASE( &glIP_Adapters );
222 // Ok, so let's open it
223 dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
225 RELEASE( &glIP_Adapters );
230 strcpy( dev->Device, Path );
234 dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
235 if( dev->DeviceFD == -1 ) {
237 RELEASE( &glIP_Adapters );
241 // Check that it is a network interface
242 if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) {
243 Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
244 VFS_Close( dev->DeviceFD );
246 RELEASE( &glIP_Adapters );
251 VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
254 dev->Next = gIP_Adapters;
257 RELEASE( &glIP_Adapters );