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)
57 // Parse module arguments
58 for( i = 0; Arguments[i]; i++ )
60 //if(strcmp(Arguments[i], "Device") == '=') {
70 * \brief Read from the IP Stack's Device Directory
72 char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
75 char name[5] = "ip0\0\0";
81 name[2] = '0' + Pos/10;
82 name[3] = '0' + Pos%10;
86 for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
88 // Did we run off the end?
89 if(!iface) return NULL;
91 // Return the pre-generated name
96 * \brief Get the node of an interface
98 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
103 if(Name[0] != 'i' || Name[1] != 'p') return NULL;
104 if(Name[2] < '0' || Name[2] > '9') return NULL;
106 if(Name[3] == '\0') {
108 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
109 if(!iface) return NULL;
113 if(Name[3] < '0' || Name[3] > '9') return NULL;
115 i = (Name[2] - '0')*10;
118 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
119 if(!iface) return NULL;
123 static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL };
124 static const char *casIOCtls_Iface[] = {
127 "get_address", "set_address",
129 "get_gateway", "set_gateway",
133 * \brief Handles IOCtls for the IPStack root/interfaces
135 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
139 // --- Standard IOCtls (0-3) ---
141 return DRV_TYPE_MISC;
143 case DRV_IOCTL_IDENT:
144 if( !CheckMem( Data, 4 ) ) return -1;
145 memcpy(Data, "IP\0\0", 4);
148 case DRV_IOCTL_VERSION:
151 case DRV_IOCTL_LOOKUP:
152 if( !CheckString( Data ) ) return -1;
154 if( Node == &gIP_DriverInfo.RootNode )
155 return LookupString( (char**)casIOCtls_Root, (char*)Data );
157 return LookupString( (char**)casIOCtls_Iface, (char*)Data );
160 if(Node == &gIP_DriverInfo.RootNode)
166 * - Adds a new IP interface and binds it to a device
169 if( Threads_GetUID() != 0 ) return -1;
170 if( !CheckString( Data ) ) return -1;
171 return IPStack_AddInterface(Data);
177 tInterface *iface = (tInterface*)Node->ImplPtr;
182 * - Get/Set the interface type
186 if( !Data ) return iface->Type;
188 if( Threads_GetUID() != 0 ) return -1;
189 if( !CheckMem( Data, sizeof(int) ) ) return -1;
190 switch( *(int*)Data )
194 memset(&iface->IP6, 0, sizeof(tIPv6)); // Clear address
198 memset(&iface->IP4, 0, sizeof(tIPv4));
202 memset(&iface->IP6, 0, sizeof(tIPv6));
211 * - Get the interface's address
218 if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1;
219 memcpy( Data, &iface->IP4, sizeof(tIPv4) );
222 if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1;
223 memcpy( Data, &iface->IP6, sizeof(tIPv6) );
230 * - Get the interface's address
233 if( Threads_GetUID() != 0 ) return -1;
238 if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1;
239 iface->Type = 0; // One very hacky mutex/trash protector
240 memcpy( &iface->IP4, Data, sizeof(tIPv4) );
244 if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1;
246 memcpy( &iface->IP6, Data, sizeof(tIPv6) );
254 * - Get/Set the bits in the address subnet
260 switch( iface->Type )
262 case 4: return iface->IP4.SubnetBits;
263 case 6: return iface->IP6.SubnetBits;
269 if( Threads_GetUID() != 0 ) return -1;
270 if( !CheckMem(Data, sizeof(int)) ) return -1;
272 // Check and set the subnet bits
273 switch( iface->Type )
276 if( *(int*)Data < 0 || *(int*)Data > 31 ) return -1;
277 iface->IP4.SubnetBits = *(int*)Data;
278 return iface->IP4.SubnetBits;
280 if( *(int*)Data < 0 || *(int*)Data > 127 ) return -1;
281 iface->IP6.SubnetBits = *(int*)Data;
282 return iface->IP6.SubnetBits;
296 * \fn int IPStack_AddInterface(char *Device)
297 * \brief Adds an interface to the list
299 int IPStack_AddInterface(char *Device)
303 iface = malloc(sizeof(tInterface));
304 if(!iface) return -2; // Return ERR_MYBAD
307 iface->Type = 0; // Unset type
310 iface->Node.Flags = VFS_FFLAG_DIRECTORY;
311 iface->Node.Size = 0;
312 iface->Node.NumACLs = 1;
313 iface->Node.ACLs = &gVFS_ACL_EveryoneRX;
314 iface->Node.ReadDir = NULL;
315 iface->Node.FindDir = NULL;
317 // Get adapter handle
318 iface->Adapter = IPStack_GetAdapter(Device);
319 if( !iface->Adapter ) {
321 return -1; // Return ERR_YOUFAIL
325 LOCK( &glIP_Interfaces );
326 if( gIP_Interfaces ) {
327 gIP_Interfaces_Last->Next = iface;
328 gIP_Interfaces_Last = iface;
331 gIP_Interfaces = iface;
332 gIP_Interfaces_Last = iface;
334 RELEASE( &glIP_Interfaces );
341 * \fn tAdapter *IPStack_GetAdapter(char *Path)
342 * \brief Gets/opens an adapter given the path
344 tAdapter *IPStack_GetAdapter(char *Path)
348 LOCK( &glIP_Adapters );
350 // Check if this adapter is already open
351 for( dev = gIP_Adapters; dev; dev = dev->Next )
353 if( strcmp(dev->Device, Path) == 0 ) {
355 RELEASE( &glIP_Adapters );
360 // Ok, so let's open it
361 dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
363 RELEASE( &glIP_Adapters );
368 strcpy( dev->Device, Path );
372 dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
373 if( dev->DeviceFD == -1 ) {
375 RELEASE( &glIP_Adapters );
379 // Check that it is a network interface
380 if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) {
381 Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
382 VFS_Close( dev->DeviceFD );
384 RELEASE( &glIP_Adapters );
389 VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
392 dev->Next = gIP_Adapters;
395 RELEASE( &glIP_Adapters );