Cleanups & Implementations to allow IPStack to compile
[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         // Parse module arguments
56         for( i = 0; Arguments[i]; i++ )
57         {
58                 //if(strcmp(Arguments[i], "Device") == '=') {
59                 //      
60                 //}
61         }
62         
63         return 1;
64 }
65
66 /**
67  * \brief Read from the IP Stack's Device Directory
68  */
69 char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
70 {
71         tInterface      *iface;
72         char    name[5] = "ip0\0\0";
73         
74         // Create the name
75         if(Pos < 10)
76                 name[2] = '0' + Pos;
77         else {
78                 name[2] = '0' + Pos/10;
79                 name[3] = '0' + Pos%10;
80         }
81         
82         // Traverse the list
83         for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
84         
85         // Did we run off the end?
86         if(!iface)      return NULL;
87         
88         // Return the pre-generated name
89         return strdup(name);
90 }
91
92 /**
93  * \brief Get the node of an interface
94  */
95 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
96 {
97          int    i;
98          tInterface     *iface;
99         
100         if(Name[0] != 'i' || Name[1] != 'p')    return NULL;
101         if(Name[2] < '0' || Name[2] > '9')      return NULL;
102         
103         if(Name[3] == '\0') {
104                 i = Name[2] - '0';
105                 for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
106                 if(!iface)      return NULL;
107                 return &iface->Node;
108         }
109         
110         if(Name[3] < '0' || Name[3] > '9')      return NULL;
111         
112         i = (Name[2] - '0')*10;
113         i += Name[3] - '0';
114         
115         for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
116         if(!iface)      return NULL;
117         return &iface->Node;
118 }
119
120 static const char *casIOCtls[] = { DRV_IOCTLNAMES, "add_interface", NULL };
121 /**
122  * \brief Handles IOCtls for the IPStack root
123  */
124 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
125 {
126         switch(ID)
127         {
128         // --- Standard IOCtls (0-3) ---
129         case DRV_IOCTL_TYPE:
130                 return DRV_TYPE_MISC;
131         
132         case DRV_IOCTL_IDENT:
133                 if( !CheckMem( Data, 4 ) )      return -1;
134                 memcpy(Data, "IP\0\0", 4);
135                 return 1;
136         
137         case DRV_IOCTL_VERSION:
138                 return VERSION;
139         
140         case DRV_IOCTL_LOOKUP:
141                 if( !CheckString( Data ) )      return -1;
142                 return LookupString( (char**)casIOCtls, (char*)Data );
143         
144         // --- Non-Standard IOCtls ---
145         /*
146          * add_interface
147          * - Adds a new IP interface and binds it to a device
148          */
149         case 4:
150                 if( !CheckString( Data ) )      return -1;
151                 return IPStack_AddInterface(Data);
152         }
153         return 0;
154 }
155
156 // --- Internal ---
157 /**
158  * \fn int IPStack_AddInterface(char *Device)
159  * \brief Adds an interface to the list
160  */
161 int IPStack_AddInterface(char *Device)
162 {
163         tInterface      *iface;
164         
165         iface = malloc(sizeof(tInterface));
166         if(!iface)      return -2;      // Return ERR_MYBAD
167         
168         iface->Next = NULL;
169         iface->Type = 0;        // Unset type
170         
171         // Create Node
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;
178         
179         // Get adapter handle
180         iface->Adapter = IPStack_GetAdapter(Device);
181         if( !iface->Adapter ) {
182                 free( iface );
183                 return -1;      // Return ERR_YOUFAIL
184         }
185         
186         // Append to list
187         LOCK( &glIP_Interfaces );
188         if( gIP_Interfaces ) {
189                 gIP_Interfaces_Last->Next = iface;
190                 gIP_Interfaces_Last = iface;
191         }
192         else {
193                 gIP_Interfaces = iface;
194                 gIP_Interfaces_Last = iface;
195         }
196         RELEASE( &glIP_Interfaces );
197         
198         // Success!
199         return 1;
200 }
201
202 /**
203  * \fn tAdapter *IPStack_GetAdapter(char *Path)
204  * \brief Gets/opens an adapter given the path
205  */
206 tAdapter *IPStack_GetAdapter(char *Path)
207 {
208         tAdapter        *dev;
209         
210         LOCK( &glIP_Adapters );
211         
212         // Check if this adapter is already open
213         for( dev = gIP_Adapters; dev; dev = dev->Next )
214         {
215                 if( strcmp(dev->Device, Path) == 0 ) {
216                         dev->NRef ++;
217                         RELEASE( &glIP_Adapters );
218                         return dev;
219                 }
220         }
221         
222         // Ok, so let's open it
223         dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
224         if(!dev) {
225                 RELEASE( &glIP_Adapters );
226                 return NULL;
227         }
228         
229         // Fill Structure
230         strcpy( dev->Device, Path );
231         dev->NRef = 1;
232         
233         // Open Device
234         dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
235         if( dev->DeviceFD == -1 ) {
236                 free( dev );
237                 RELEASE( &glIP_Adapters );
238                 return NULL;
239         }
240         
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 );
245                 free( dev );
246                 RELEASE( &glIP_Adapters );
247                 return NULL;
248         }
249         
250         // Get MAC Address
251         VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
252         
253         // Add to list
254         dev->Next = gIP_Adapters;
255         gIP_Adapters = dev;
256         
257         RELEASE( &glIP_Adapters );
258         return dev;
259 }

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