Fixed compilation issues in IPStack
[tpg/acess2.git] / Modules / IPStack / routing.c
1 /*
2  * Acess2 IP Stack
3  * - Routing Tables
4  */
5 #define DEBUG   0
6 #define VERSION VER2(0,10)
7 #include <acess.h>
8 #include <tpl_drv_common.h>
9 #include "ipstack.h"
10 #include "link.h"
11
12 // === IMPORTS ===
13 tVFS_Node       *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename);
14
15 // === TYPES ===
16 typedef struct sRoute {
17         struct sRoute   *Next;
18         
19         tVFS_Node       Node;
20         
21         tInterface      *Interface;     // Interface for this route
22          int    AddressType;    // 0: Invalid, 4: IPv4, 6: IPv4
23         void    *Network;       // Network - Pointer to tIPv4/tIPv6/... at end of structure
24          int    SubnetBits;     // Number of bits in \a Network that are valid
25         void    *NextHop;       // Next Hop address - Pointer to tIPv4/tIPv6/... at end of structure
26          int    Metric; // Route priority
27 }       tRoute;
28
29 // === PROTOTYPES ===
30 // - Routes directory
31 char    *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos);
32 tVFS_Node       *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name);
33  int    IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data);
34  int    IPStack_Route_Create(const char *InterfaceName);
35 // - Individual Routes
36  int    IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data);
37
38 // === GLOBALS ===
39  int    giIP_NextRouteId = 1;
40 tRoute  *gIP_Routes;
41 tRoute  *gIP_RoutesEnd;
42 tVFS_Node       gIP_RouteNode = {
43         Flags: VFS_FFLAG_DIRECTORY,
44         Size: -1,
45         NumACLs: 1,
46         ACLs: &gVFS_ACL_EveryoneRX,
47         ReadDir: IPStack_RouteDir_ReadDir,
48         FindDir: IPStack_RouteDir_FindDir,
49         IOCtl: IPStack_RouteDir_IOCtl
50 };
51
52 // === CODE ===
53 /**
54  * \brief ReadDir for the /Devices/ip/routes/ directory
55  */
56 char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos)
57 {
58         tRoute  *rt;
59         
60         for(rt = gIP_Routes; rt && Pos --; rt = rt->Next);
61         
62         if( !rt ) {
63                 return NULL;
64         }
65         
66         {
67                  int    len = sprintf(NULL, "%i", rt->Node.Inode);
68                 char    buf[len+1];
69                 sprintf(buf, "%i", rt->Node.Inode);
70                 return strdup(buf);
71         }
72 }
73
74 /**
75  * \brief FindDir for the /Devices/ip/routes/ directory
76  */
77 tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name)
78 {
79          int    num = atoi(Name);
80         tRoute  *rt;
81         
82         // Zero is invalid, sorry :)
83         if( !num )      return NULL;
84         
85         // The list is inherently sorted, so we can do a quick search
86         for(rt = gIP_Routes; rt && rt->Node.Inode < num; rt = rt->Next);
87         // Fast fail on larger number
88         if( rt->Node.Inode > num )
89                 return NULL;
90         
91         return &rt->Node;
92 }
93
94 /**
95  * \brief Names for the route list IOCtl Calls
96  */
97 static const char *casIOCtls_RouteDir[] = {
98         DRV_IOCTLNAMES,
99         "add_route",    // Add a route - char *InterfaceName
100         NULL
101         };
102
103 /**
104  * \brief IOCtl for /Devices/ip/routes/
105  */
106 int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data)
107 {
108          int    tmp;
109         switch(ID)
110         {
111         // --- Standard IOCtls (0-3) ---
112         case DRV_IOCTL_TYPE:
113                 LEAVE('i', DRV_TYPE_MISC);
114                 return DRV_TYPE_MISC;
115         
116         case DRV_IOCTL_IDENT:
117                 tmp = ModUtil_SetIdent(Data, STR(IDENT));
118                 LEAVE('i', 1);
119                 return 1;
120         
121         case DRV_IOCTL_VERSION:
122                 LEAVE('x', VERSION);
123                 return VERSION;
124         
125         case DRV_IOCTL_LOOKUP:
126                 tmp = ModUtil_LookupString( (char**)casIOCtls_RouteDir, (char*)Data );
127                 LEAVE('i', tmp);
128                 return tmp;
129         
130         case 4: // Add Route
131                 if( !CheckString(Data) )        return -1;
132                 return IPStack_Route_Create(Data);
133         }
134         return 0;
135 }
136
137 /**
138  * \brief Create a new route entry
139  * \param InterfaceName Name of the interface using this route
140  */
141 int IPStack_Route_Create(const char *InterfaceName)
142 {
143         tRoute  *rt;
144         tInterface      *iface;
145          int    size;
146         
147         // Get interface
148         // Note: Oh man! This is such a hack
149         {
150                 tVFS_Node       *node = IPStack_Root_FindDir(NULL, InterfaceName);
151                 if( !node )     return 0;
152                 iface = node->ImplPtr;
153         }
154         
155         // Get the size of the specified address type
156         size = IPStack_GetAddressSize(iface->Type);
157         if( size == 0 ) {
158                 return 0;
159         }
160         
161         // Allocate space
162         rt = calloc(1, sizeof(tRoute) + size*2 );
163         
164         // Set up node
165         rt->Node.ImplPtr = rt;
166         rt->Node.Inode = giIP_NextRouteId ++;
167         rt->Node.Size = 0;
168         rt->Node.NumACLs = 1,
169         rt->Node.ACLs = &gVFS_ACL_EveryoneRO;
170         rt->Node.IOCtl = IPStack_Route_IOCtl;
171         
172         // Set up state
173         rt->AddressType = iface->Type;
174         rt->Network = (void *)( (tVAddr)rt + sizeof(tRoute) );
175         rt->SubnetBits = 0;
176         rt->NextHop = (void *)( (tVAddr)rt + sizeof(tRoute) + size );
177         rt->Interface = iface;
178         
179         // Add to list
180         if( gIP_RoutesEnd ) {
181                 gIP_RoutesEnd->Next = rt;
182                 gIP_RoutesEnd = rt;
183         }
184         else {
185                 gIP_Routes = gIP_RoutesEnd = rt;
186         }
187         
188         return rt->Node.Inode;
189 }
190
191 /**
192  * \brief Names for route IOCtl Calls
193  */
194 static const char *casIOCtls_Route[] = {
195         DRV_IOCTLNAMES,
196         "get_network",  // Get network - (void *Data)
197         "set_network",  // Set network - (void *Data)
198         "get_nexthop",  // Get next hop - (void *Data)
199         "set_nexthop",  // Set next hop - (void *Data)
200         "getset_subnetbits",    // Get/Set subnet bits - (int *Bits)
201         "getset_metric",        // Get/Set metric - (int *Metric)
202         NULL
203         };
204
205 /**
206  * \brief IOCtl for /Devices/ip/routes/#
207  */
208 int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data)
209 {
210          int    tmp;
211          int    *iData = Data;
212         tRoute  *rt = Node->ImplPtr;
213          int    addrSize = IPStack_GetAddressSize(rt->AddressType);
214         
215         switch(ID)
216         {
217         // --- Standard IOCtls (0-3) ---
218         case DRV_IOCTL_TYPE:
219                 LEAVE('i', DRV_TYPE_MISC);
220                 return DRV_TYPE_MISC;
221         
222         case DRV_IOCTL_IDENT:
223                 tmp = ModUtil_SetIdent(Data, STR(IDENT));
224                 LEAVE('i', 1);
225                 return 1;
226         
227         case DRV_IOCTL_VERSION:
228                 LEAVE('x', VERSION);
229                 return VERSION;
230         
231         case DRV_IOCTL_LOOKUP:
232                 tmp = ModUtil_LookupString( (char**)casIOCtls_Route, (char*)Data );
233                 LEAVE('i', tmp);
234                 return tmp;
235         
236         // Get Network
237         case 4:
238                 if( !CheckMem(Data, addrSize) ) return -1;
239                 memcpy(Data, rt->Network, addrSize);
240                 return 1;
241         // Set Network
242         case 5:
243                 if( !CheckMem(Data, addrSize) ) return -1;
244                 memcpy(rt->Network, Data, addrSize);
245                 return 1;
246         
247         // Get Next Hop
248         case 6:
249                 if( !CheckMem(Data, addrSize) ) return -1;
250                 memcpy(Data, rt->NextHop, addrSize);
251                 return 1;
252         // Set Next Hop
253         case 7:
254                 if( !CheckMem(Data, addrSize) ) return -1;
255                 memcpy(rt->NextHop, Data, addrSize);
256                 return 1;
257         
258         // Get/Set Subnet Bits
259         case 8:
260                 if( Data ) {
261                         if( !CheckMem(Data, sizeof(int)) )      return -1;
262                         if( *iData < 0 || *iData > addrSize*8 )
263                                 return -1;
264                         rt->SubnetBits = *iData;
265                 }
266                 return rt->SubnetBits;
267         
268         // Get/Set Metric
269         case 9:
270                 if( Data ) {
271                         if( !CheckMem(Data, sizeof(int)) )      return -1;
272                         if( *iData < 0 )        return -1;
273                         rt->Metric = *iData;
274                 }
275                 return rt->Metric;
276         
277         default:
278                 return 0;
279         }
280 }

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