051d064d18e861d1aa136b13e8173dfe21b9845d
[tpg/acess2.git] / Modules / IPStack / main.c
1 /*
2  * Acess2 IP Stack
3  * - Address Resolution Protocol
4  */
5 #define DEBUG   0
6 #define VERSION ((0<<8)|10)
7 #include "ipstack.h"
8 #include <modules.h>
9 #include <fs_devfs.h>
10 #include <tpl_drv_common.h>
11 #include <tpl_drv_network.h>
12
13 // === IMPORTS ===
14  int    ARP_Initialise();
15
16 // === PROTOTYPES ===
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);
23
24 // === GLOBALS ===
25 MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL);
26 tDevFS_Driver   gIP_DriverInfo = {
27         NULL, "ip",
28         {
29         .Size = 0,      // Number of interfaces
30         .NumACLs = 1,
31         .ACLs = &gVFS_ACL_EveryoneRX,
32         .Flags = VFS_FFLAG_DIRECTORY,
33         .ReadDir = IPStack_ReadDir,
34         .FindDir = IPStack_FindDir
35         }
36 };
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;
42
43 // === CODE ===
44 /**
45  * \fn int IPStack_Install(char **Arguments)
46  * \brief Intialise the relevant parts of the stack and register with DevFS
47  */
48 int IPStack_Install(char **Arguments)
49 {
50          int    i = 0;
51         
52         // Install Handlers
53         ARP_Initialise();
54         
55         if(Arguments)
56         {
57                 // Parse module arguments
58                 for( i = 0; Arguments[i]; i++ )
59                 {
60                         //if(strcmp(Arguments[i], "Device") == '=') {
61                         //      
62                         //}
63                 }
64         }
65         
66         return 1;
67 }
68
69 /**
70  * \brief Read from the IP Stack's Device Directory
71  */
72 char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
73 {
74         tInterface      *iface;
75         char    name[5] = "ip0\0\0";
76         
77         // Create the name
78         if(Pos < 10)
79                 name[2] = '0' + Pos;
80         else {
81                 name[2] = '0' + Pos/10;
82                 name[3] = '0' + Pos%10;
83         }
84         
85         // Traverse the list
86         for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
87         
88         // Did we run off the end?
89         if(!iface)      return NULL;
90         
91         // Return the pre-generated name
92         return strdup(name);
93 }
94
95 /**
96  * \brief Get the node of an interface
97  */
98 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
99 {
100          int    i;
101          tInterface     *iface;
102         
103         if(Name[0] != 'i' || Name[1] != 'p')    return NULL;
104         if(Name[2] < '0' || Name[2] > '9')      return NULL;
105         
106         if(Name[3] == '\0') {
107                 i = Name[2] - '0';
108                 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
109                 if(!iface)      return NULL;
110                 return &iface->Node;
111         }
112         
113         if(Name[3] < '0' || Name[3] > '9')      return NULL;
114         
115         i = (Name[2] - '0')*10;
116         i += Name[3] - '0';
117         
118         for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
119         if(!iface)      return NULL;
120         return &iface->Node;
121 }
122
123 static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL };
124 static const char *casIOCtls_Iface[] = {
125         DRV_IOCTLNAMES,
126         "getset_type",
127         "get_address", "set_address",
128         "getset_subnet",
129         "get_gateway", "set_gateway",
130         NULL
131         };
132 /**
133  * \brief Handles IOCtls for the IPStack root/interfaces
134  */
135 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
136 {
137         switch(ID)
138         {
139         // --- Standard IOCtls (0-3) ---
140         case DRV_IOCTL_TYPE:
141                 return DRV_TYPE_MISC;
142         
143         case DRV_IOCTL_IDENT:
144                 if( !CheckMem( Data, 4 ) )      return -1;
145                 memcpy(Data, "IP\0\0", 4);
146                 return 1;
147         
148         case DRV_IOCTL_VERSION:
149                 return VERSION;
150         
151         case DRV_IOCTL_LOOKUP:
152                 if( !CheckString( Data ) )      return -1;
153                 
154                 if( Node == &gIP_DriverInfo.RootNode )
155                         return LookupString( (char**)casIOCtls_Root, (char*)Data );
156                 else
157                         return LookupString( (char**)casIOCtls_Iface, (char*)Data );
158         }
159         
160         if(Node == &gIP_DriverInfo.RootNode)
161         {
162                 switch(ID)
163                 {
164                 /*
165                  * add_interface
166                  * - Adds a new IP interface and binds it to a device
167                  */
168                 case 4:
169                         if( Threads_GetUID() != 0 )     return -1;
170                         if( !CheckString( Data ) )      return -1;
171                         return IPStack_AddInterface(Data);
172                 }
173                 return 0;       
174         }
175         else
176         {
177                 tInterface      *iface = (tInterface*)Node->ImplPtr;
178                 switch(ID)
179                 {
180                 /*
181                  * getset_type
182                  * - Get/Set the interface type
183                  */
184                 case 4:
185                         // Get Type?
186                         if( !Data )     return iface->Type;
187                         // Ok, it's set type
188                         if( Threads_GetUID() != 0 )     return -1;
189                         if( !CheckMem( Data, sizeof(int) ) )    return -1;
190                         switch( *(int*)Data )
191                         {
192                         case 0: // Disable
193                                 iface->Type = 0;
194                                 memset(&iface->IP6, 0, sizeof(tIPv6));  // Clear address
195                                 break;
196                         case 4: // IPv4
197                                 iface->Type = 4;
198                                 memset(&iface->IP4, 0, sizeof(tIPv4));
199                                 break;
200                         case 6: // IPv6
201                                 iface->Type = 6;
202                                 memset(&iface->IP6, 0, sizeof(tIPv6));
203                                 break;
204                         default:
205                                 return -1;
206                         }
207                         return 0;
208                 
209                 /*
210                  * get_address
211                  * - Get the interface's address
212                  */
213                 case 5:
214                         switch(iface->Type)
215                         {
216                         case 0: return 1;
217                         case 4:
218                                 if( !CheckMem( Data, sizeof(tIPv4) ) )  return -1;
219                                 memcpy( Data, &iface->IP4, sizeof(tIPv4) );
220                                 return 1;
221                         case 6:
222                                 if( !CheckMem( Data, sizeof(tIPv6) ) )  return -1;
223                                 memcpy( Data, &iface->IP6, sizeof(tIPv6) );
224                                 return 1;
225                         }
226                         return 0;
227                 
228                 /*
229                  * set_address
230                  * - Get the interface's address
231                  */
232                 case 6:
233                         if( Threads_GetUID() != 0 )     return -1;
234                         switch(iface->Type)
235                         {
236                         case 0: return 1;
237                         case 4:
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) );
241                                 iface->Type = 4;
242                                 return 1;
243                         case 6:
244                                 if( !CheckMem( Data, sizeof(tIPv6) ) )  return -1;
245                                 iface->Type = 0;
246                                 memcpy( &iface->IP6, Data, sizeof(tIPv6) );
247                                 iface->Type = 6;
248                                 return 1;
249                         }
250                         return 0;
251                 
252                 /*
253                  * getset_subnet
254                  * - Get/Set the bits in the address subnet
255                  */
256                 case 7:
257                         // Get?
258                         if( Data == NULL )
259                         {
260                                 switch( iface->Type )
261                                 {
262                                 case 4:         return iface->IP4.SubnetBits;
263                                 case 6:         return iface->IP6.SubnetBits;
264                                 default:        return 0;
265                                 }
266                         }
267                         
268                         // Ok, set.
269                         if( Threads_GetUID() != 0 )     return -1;
270                         if( !CheckMem(Data, sizeof(int)) )      return -1;
271                         
272                         // Check and set the subnet bits
273                         switch( iface->Type )
274                         {
275                         case 4:
276                                 if( *(int*)Data < 0 || *(int*)Data > 31 )       return -1;
277                                 iface->IP4.SubnetBits = *(int*)Data;
278                                 return iface->IP4.SubnetBits;
279                         case 6:
280                                 if( *(int*)Data < 0 || *(int*)Data > 127 )      return -1;
281                                 iface->IP6.SubnetBits = *(int*)Data;
282                                 return iface->IP6.SubnetBits;
283                         default:
284                                 break;
285                         }
286                         
287                         return 0;
288                 }
289         }
290         
291         return 0;
292 }
293
294 // --- Internal ---
295 /**
296  * \fn int IPStack_AddInterface(char *Device)
297  * \brief Adds an interface to the list
298  */
299 int IPStack_AddInterface(char *Device)
300 {
301         tInterface      *iface;
302         
303         iface = malloc(sizeof(tInterface));
304         if(!iface)      return -2;      // Return ERR_MYBAD
305         
306         iface->Next = NULL;
307         iface->Type = 0;        // Unset type
308         
309         // Create Node
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;
316         
317         // Get adapter handle
318         iface->Adapter = IPStack_GetAdapter(Device);
319         if( !iface->Adapter ) {
320                 free( iface );
321                 return -1;      // Return ERR_YOUFAIL
322         }
323         
324         // Append to list
325         LOCK( &glIP_Interfaces );
326         if( gIP_Interfaces ) {
327                 gIP_Interfaces_Last->Next = iface;
328                 gIP_Interfaces_Last = iface;
329         }
330         else {
331                 gIP_Interfaces = iface;
332                 gIP_Interfaces_Last = iface;
333         }
334         RELEASE( &glIP_Interfaces );
335         
336         // Success!
337         return 1;
338 }
339
340 /**
341  * \fn tAdapter *IPStack_GetAdapter(char *Path)
342  * \brief Gets/opens an adapter given the path
343  */
344 tAdapter *IPStack_GetAdapter(char *Path)
345 {
346         tAdapter        *dev;
347         
348         LOCK( &glIP_Adapters );
349         
350         // Check if this adapter is already open
351         for( dev = gIP_Adapters; dev; dev = dev->Next )
352         {
353                 if( strcmp(dev->Device, Path) == 0 ) {
354                         dev->NRef ++;
355                         RELEASE( &glIP_Adapters );
356                         return dev;
357                 }
358         }
359         
360         // Ok, so let's open it
361         dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
362         if(!dev) {
363                 RELEASE( &glIP_Adapters );
364                 return NULL;
365         }
366         
367         // Fill Structure
368         strcpy( dev->Device, Path );
369         dev->NRef = 1;
370         
371         // Open Device
372         dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
373         if( dev->DeviceFD == -1 ) {
374                 free( dev );
375                 RELEASE( &glIP_Adapters );
376                 return NULL;
377         }
378         
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 );
383                 free( dev );
384                 RELEASE( &glIP_Adapters );
385                 return NULL;
386         }
387         
388         // Get MAC Address
389         VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
390         
391         // Add to list
392         dev->Next = gIP_Adapters;
393         gIP_Adapters = dev;
394         
395         RELEASE( &glIP_Adapters );
396         return dev;
397 }

UCC git Repository :: git.ucc.asn.au