IPStack / ifconfig - Routing changes
authorJohn Hodge <[email protected]>
Tue, 25 Jan 2011 13:41:13 +0000 (21:41 +0800)
committerJohn Hodge <[email protected]>
Tue, 25 Jan 2011 13:41:13 +0000 (21:41 +0800)
- Implemented implicit routes in interface.c/routing.c
 > Implicit routes are routes that are constructed on the fly from
   an interface.
- Vastly improved the route support in ifconfig
- (Misc) Added some missing syscalls to Usermode/acess/sys.h

Modules/IPStack/interface.c
Modules/IPStack/ipstack.h
Modules/IPStack/routing.c
Usermode/Applications/ifconfig_src/main.c
Usermode/Libraries/libnet.so_src/net.h
Usermode/include/acess/sys.h

index 50d4c22..fc79e9e 100644 (file)
@@ -251,7 +251,7 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
        iface = malloc(
                sizeof(tInterface)
                + nameLen + 1
-               + IPStack_GetAddressSize(-1)
+               + IPStack_GetAddressSize(-1)*3  // Address, Route->Network, Route->NextHop
                );
        if(!iface) {
                LEAVE('n');
@@ -261,6 +261,8 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
        iface->Next = NULL;
        iface->Type = 0;        // Unset type
        iface->Address = iface->Name + nameLen + 1;     // Address
+       iface->Route.Network = iface->Address + IPStack_GetAddressSize(-1);
+       iface->Route.NextHop = iface->Route.Network + IPStack_GetAddressSize(-1);
        
        // Create Node
        iface->Node.ImplPtr = iface;
index e6ded4b..b0dff23 100644 (file)
@@ -38,21 +38,6 @@ struct sMacAddr {
        Uint8   B[6];
 } __attribute__((packed));
 
-struct sInterface {
-       struct sInterface       *Next;  //!< Next interface in list
-       
-       tVFS_Node       Node;   //!< Node to use the interface
-       
-       tAdapter        *Adapter;       //!< Adapter the interface is associated with
-        int    TimeoutDelay;   //!< Time in miliseconds before a packet times out
-        int    Type;   //!< Interface type, see ::eInterfaceTypes
-       
-       void    *Address;       //!< IP address (stored after the Name)
-        int    SubnetBits;     //!< Number of bits that denote the address network
-       
-       char    Name[];
-};
-
 /**
  * \brief Route definition structure
  */
@@ -69,6 +54,23 @@ typedef struct sRoute {
         int    Metric; //!< Route priority
 }      tRoute;
 
+struct sInterface {
+       struct sInterface       *Next;  //!< Next interface in list
+       
+       tVFS_Node       Node;   //!< Node to use the interface
+       
+       tAdapter        *Adapter;       //!< Adapter the interface is associated with
+        int    TimeoutDelay;   //!< Time in miliseconds before a packet times out
+        int    Type;   //!< Interface type, see ::eInterfaceTypes
+       
+       void    *Address;       //!< IP address (stored after the Name)
+        int    SubnetBits;     //!< Number of bits that denote the address network
+       
+       tRoute  Route;  //!< Interface route
+       
+       char    Name[];
+};
+
 /**
  * \brief Represents a network adapter
  */
index 53d5c88..26817b6 100644 (file)
@@ -251,6 +251,8 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
 {
        tRoute  *rt;
        tRoute  *best = NULL;
+       tInterface      *iface;
+        int    addrSize;
        
        ENTER("iAddressType pInterface sAddress",
                AddressType, Interface, IPStack_PrintAddress(AddressType, Address));
@@ -261,6 +263,10 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
                return NULL;
        }
        
+       // Get address size
+       addrSize = IPStack_GetAddressSize(AddressType);
+       
+       // Check against explicit routes
        for( rt = gIP_Routes; rt; rt = rt->Next )
        {
                // Check interface
@@ -290,6 +296,56 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
                best = rt;
        }
        
+       // Check against implicit routes
+       if( !best && !Interface )
+       {
+               for( iface = gIP_Interfaces; iface; iface = iface->Next )
+               {
+                       if( Interface && iface != Interface )   continue;
+                       if( iface->Type != AddressType )        continue;
+                       
+                       
+                       // Check if the address matches
+                       if( !IPStack_CompareAddress(AddressType, iface->Address, Address, iface->SubnetBits) )
+                               continue;
+                       
+                       if( best ) {
+                               // More direct routes are preferred
+                               if( best->SubnetBits > rt->SubnetBits ) {
+                                       LOG("Skipped - less direct (%i < %i)", rt->SubnetBits, best->SubnetBits);
+                                       continue;
+                               }
+                               // If equally direct, choose the best metric
+                               if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) {
+                                       LOG("Skipped - higher metric (%i > %i)", rt->Metric, best->Metric);
+                                       continue;
+                               }
+                       }
+                       
+                       rt = &iface->Route;
+                       memcpy(rt->Network, iface->Address, addrSize);
+                       memset(rt->NextHop, 0, addrSize);
+                       rt->Metric = DEFAUTL_METRIC;
+                       rt->SubnetBits = iface->SubnetBits;
+                       
+                       best = rt;
+               }
+       }
+       if( !best && Interface )
+       {
+               rt = &Interface->Route;
+               // Make sure route is up to date
+               memcpy(rt->Network, iface->Address, addrSize);
+               memset(rt->NextHop, 0, addrSize);
+               rt->Metric = DEFAUTL_METRIC;
+               rt->SubnetBits = iface->SubnetBits;
+               
+               if( IPStack_CompareAddress(AddressType, rt->Network, Address, rt->SubnetBits) )
+               {
+                       best = rt;
+               }
+       }
+       
        LEAVE('p', best);
        return best;
 }
index 3a45530..9aa9d72 100644 (file)
@@ -11,6 +11,7 @@
 // === CONSTANTS ===
 #define FILENAME_MAX   255
 #define IPSTACK_ROOT   "/Devices/ip"
+#define DEFAULT_METRIC 30
 
 // TODO: Move this to a header
 #define ntohs(v)       (((v&0xFF)<<8)|((v>>8)&0xFF))
@@ -22,10 +23,10 @@ void        DumpRoutes(void);
 void   DumpInterface(const char *Name);
 void   DumpRoute(const char *Name);
  int   AddInterface(const char *Device);
-void   AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop);
+void   AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop);
  int   DoAutoConfig(const char *Device);
  int   SetAddress(int IFNum, const char *Address);
- int   ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits);
+ int   ParseIPAddress(const char *Address, uint8_t *Dest, int *SubnetBits);
 
 // === CODE ===
 /**
@@ -41,13 +42,93 @@ int main(int argc, char *argv[])
                return 0;
        }
        
-       if( strcmp(argv[1], "routes") == 0 ) {
-               DumpRoutes();
+       // Routes
+       if( strcmp(argv[1], "route") == 0 )
+       {
+               // Add new route
+               if( strcmp(argv[2], "add") == 0 )
+               {
+                       uint8_t dest[16] = {0};
+                       uint8_t nextHop[16] = {0};
+                        int    addrType, subnetBits = -1;
+                        int    nextHopType, nextHopBits=-1;
+                       char    *ifaceName;
+                        int    metric = DEFAULT_METRIC;
+                       // Usage:
+                       // ifconfig route add <host>[/<prefix>] <interface> [<metric>]
+                       // ifconfig route add <host>[/<prefix>] <next hop> [<metric>]
+                       if( argc - 3  < 2 ) {
+                               fprintf(stderr, "ERROR: '%s route add' takes at least two arguments, %i passed\n",
+                                       argv[0], argc-3);
+                               PrintUsage(argv[0]);
+                               return -1;
+                       }
+                       
+                       if( argc - 3 > 3 ) {
+                               fprintf(stderr, "ERROR: '%s route add' takes at most three arguments, %i passed\n",
+                                       argv[0], argc-3);
+                               PrintUsage(argv[0]);
+                               return -1;
+                       }
+                       
+                       // Destination IP
+                       addrType = ParseIPAddress(argv[3], dest, &subnetBits);
+                       if( subnetBits == -1 ) {
+                               subnetBits = Net_GetAddressSize(addrType)*8;
+                       }
+                       // Interface Name / Next Hop
+                       if( (nextHopType = ParseIPAddress(argv[4], nextHop, &nextHopBits)) == 0 )
+                       {
+                               // Interface name
+                               ifaceName = argv[4];
+                       }
+                       else
+                       {
+                               // Next Hop
+                               // - Check if it's the same type as the network/destination
+                               if( nextHopType != addrType ) {
+                                       fprintf(stderr, "ERROR: Address type mismatch\n");
+                                       return -1;
+                               }
+                               // - Make sure there's no mask
+                               if( nextHopBits != -1 ) {
+                                       fprintf(stderr, "Error: Next hop cannot be masked\n");
+                                       return -1;
+                               }
+                       }
+                       
+                       // Metric
+                       if( argc - 3 >= 3 )
+                       {
+                               metric = atoi(argv[5]);
+                               if( metric == 0 && argv[5][0] != '0' ) {
+                                       fprintf(stderr, "ERROR: Metric should be a number\n");
+                                       return -1;
+                               }
+                       }
+                       
+                       // Make the route!
+                       AddRoute(ifaceName, addrType, dest, subnetBits, metric, nextHop);
+                       
+                       return 0;
+               }
+               // Delete a route
+               else if( strcmp(argv[2], "del") == 0 )
+               {
+                       // Usage:
+                       // ifconfig route del <routenum>
+                       // ifconfig route del <host>[/<prefix>]
+               }
+               else
+               {
+                       // List routes
+                       DumpRoutes();
+               }
                return 0;
        }
-       
        // Add a new interface
-       if( strcmp(argv[1], "add") == 0 ) {
+       else if( strcmp(argv[1], "add") == 0 )
+       {
                if( argc < 4 ) {
                        fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2);
                        PrintUsage(argv[0]);
@@ -59,9 +140,9 @@ int main(int argc, char *argv[])
                ret = SetAddress( ret, argv[3] );
                return ret;
        }
-       
        // Delete an interface
-       if( strcmp(argv[1], "del") == 0 ) {
+       else if( strcmp(argv[1], "del") == 0 )
+       {
                if( argc < 3 ) {
                        fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]);
                        PrintUsage(argv[0]);
@@ -69,16 +150,21 @@ int main(int argc, char *argv[])
                }
                // TODO:
        }
-       
        // Autoconfigure an interface
        // NOTE: Debugging hack (see the function for more details)
-       if( strcmp(argv[1], "autoconf") == 0 ) {
+       else if( strcmp(argv[1], "autoconf") == 0 )
+       {
                DoAutoConfig(argv[2]);
                return 0;
        }
+       else if( strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 )
+       {
+               PrintUsage(argv[0]);
+               return 0;
+       }
        
-       // Print usage instructions
-       PrintUsage(argv[0]);
+       // Dump a named interface
+       DumpInterface(argv[1]);
        
        return 0;
 }
@@ -93,12 +179,18 @@ void PrintUsage(const char *ProgName)
        fprintf(stderr, "        Add a new interface listening on <device> with the specified\n");
        fprintf(stderr, "        address.\n");
        fprintf(stderr, "    %s del <interface>\n", ProgName);
-       fprintf(stderr, "    %s set <interface> <option> <value>\n", ProgName);
-       fprintf(stderr, "        Set an option on an interface, a list of valid options follows\n");
-       fprintf(stderr, "        gw      IPv4 default gateway\n");
+       fprintf(stderr, "        Delete an interface\n");
        fprintf(stderr, "    %s [<interface>]\n", ProgName);
        fprintf(stderr, "        Print the current interfaces (or only <interface> if passed)\n");
        fprintf(stderr, "\n");
+       fprintf(stderr, "    %s routes\n", ProgName);
+       fprintf(stderr, "        Print the routing tables\n");
+       fprintf(stderr, "    %s routes add <host>[/<prefix>] [<nexthop> OR <iface>] [<metric>]\n", ProgName);
+       fprintf(stderr, "        Add a new route\n");
+       fprintf(stderr, "    %s routes del <host>[/<prefix>]\n", ProgName);
+       fprintf(stderr, "    %s routes del <routenum>\n", ProgName);
+       fprintf(stderr, "        Add a new route\n");
+       fprintf(stderr, "\n");
        fprintf(stderr, "A note on Acess's IP Stack:\n");
        fprintf(stderr, "    Each interface corresponds to only one IP address (either IPv4\n");
        fprintf(stderr, "    or IPv6). A network device can have multiple interfaces bound\n");
@@ -157,7 +249,7 @@ void DumpInterface(const char *Name)
        
        fd = open(path, OPENFLAG_READ);
        if(fd == -1) {
-               printf("%s:\tUnable to open ('%s')\n", Name, path);
+               fprintf(stderr, "Bad interface name '%s' (%s does not exist)\t", Name, path);
                return ;
        }
        
@@ -315,11 +407,51 @@ int AddInterface(const char *Device)
        return ret;
 }
 
-void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop)
+void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop)
 {
         int    fd;
         int    num;
        char    tmp[sizeof(IPSTACK_ROOT"/routes/") + 5];        // enough for 4 digits
+       char    *ifaceToFree = NULL;
+       
+       // Get interface name
+       if( !Interface )
+       {
+               if( !NextHop ) {
+                       fprintf(stderr,
+                               "BUG: AddRoute(Interface=NULL,...,NextHop=NULL)\n"
+                               "Only one should be NULL\n"
+                               );
+                       return ;
+               }
+               
+               // Query for the interface name
+               Interface = ifaceToFree = Net_GetInterface(AddressType, NextHop);
+       }
+       // Check address type (if the interface was passed)
+       // - If we got the interface name, then it should be correct
+       else
+       {
+               char    ifacePath[sizeof(IPSTACK_ROOT"/")+strlen(Interface)+1];
+               
+               // Open interface
+               strcpy(ifacePath, IPSTACK_ROOT"/");
+               strcat(ifacePath, Interface);
+               fd = open(ifacePath, 0);
+               if( fd == -1 ) {
+                       fprintf(stderr, "Error: Interface '%s' does not exist\n", Interface);
+                       return ;
+               }
+               // Get and check type
+               num = ioctl(fd, ioctl(fd, 3, "getset_type"), NULL);
+               if( num != AddressType ) {
+                       fprintf(stderr, "Error: Passed type does not match interface type (%i != %i)\n",
+                               AddressType, num);
+                       return ;
+               }
+               
+               close(fd);
+       }
        
        // Create route
        fd = open(IPSTACK_ROOT"/routes", 0);
@@ -331,11 +463,16 @@ void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop)
        fd = open(tmp, 0);
        
        ioctl(fd, ioctl(fd, 3, "set_network"), Dest);
-       ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
+       if( NextHop )
+               ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
        ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), &MaskBits);
+       ioctl(fd, ioctl(fd, 3, "getset_metric"), &Metric);
        
        close(fd);
        
+       // Check if the interface name was allocated by us
+       if( ifaceToFree )
+               free(ifaceToFree);
 }
 
 /**
@@ -376,8 +513,8 @@ int DoAutoConfig(const char *Device)
        // Set routes
        {
                uint8_t net[4] = {0,0,0,0};
-               AddRoute(path + sizeof(IPSTACK_ROOT), addr, subnet, net);       // This interface
-               AddRoute(path + sizeof(IPSTACK_ROOT), net, 0, gw);      // Gateway
+               AddRoute(path + sizeof(IPSTACK_ROOT), 4, addr, subnet, DEFAULT_METRIC, net);    // This interface
+               AddRoute(path + sizeof(IPSTACK_ROOT), 4, net, 0, DEFAULT_METRIC, gw);   // Gateway
        }
        
        close(fd);
@@ -401,7 +538,7 @@ int SetAddress(int IFNum, const char *Address)
         int    tmp, fd, subnet;
        
        // Parse IP Address
-       type = ParseIPAddres(Address, addr, &subnet);
+       type = ParseIPAddress(Address, addr, &subnet);
        if(type == 0) {
                fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
                return -1;
@@ -440,7 +577,7 @@ int SetAddress(int IFNum, const char *Address)
  * \brief Parse an IP Address
  * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
  */
-int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
+int ParseIPAddress(const char *Address, uint8_t *Dest, int *SubnetBits)
 {
        const char      *p = Address;
        
@@ -485,7 +622,7 @@ int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
                        if(val > 32) {
                                printf("Notice: Subnet size >32 (%i)\n", val);
                        }
-                       *SubnetBits = val;
+                       if(SubnetBits)  *SubnetBits = val;
                }
                if(Address[i] != '\0') {
                        //printf("EOS != '\\0', '%c'\n", Address[i]);
@@ -560,7 +697,7 @@ int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
                        if(val > 128) {
                                printf("Notice: Subnet size >128 (%i)\n", val);
                        }
-                       *SubnetBits = val;
+                       if(SubnetBits)  *SubnetBits = val;
                }
                
                for( j = 0; j < split; j ++ )
index f45646f..fcd213f 100644 (file)
@@ -21,6 +21,13 @@ extern int   Net_ParseAddress(const char *String, void *Addr);
  */
 extern const char *Net_PrintAddress(int AddressType, void *Address);
 
+/**
+ * \brief Get the size in bytes of an address type
+ * \param AddressType  Address type returned by Net_ParseAddress
+ * \return Size of an address in bytes
+ */
+extern int Net_GetAddressSize(int AddressType);
+
 /**
  * \brief Get the interface required to reach \a Addr
  * \param AddrType     Addresss Family (4: IPv4, 6: IPv6)
index 368524a..ba58ffe 100644 (file)
@@ -66,6 +66,7 @@ extern void   _SysDebug(const char *format, ...);
 extern void    _exit(int status)       __attribute__((noreturn));
 extern void    sleep();
 extern void    yield();
+extern int     kill(int pid, int sig);
 extern void    wait(int miliseconds);
 extern int     waittid(int id, int *status);
 extern int     clone(int flags, void *stack);
@@ -73,6 +74,8 @@ extern int    execve(char *path, char **argv, char **envp);
 extern int     gettid();
 extern int     getpid();
 extern int     _SysSetFaultHandler(int (*Handler)(int));
+extern void    SysSetName(const char *Name);
+//extern int   SysGetName(const char *Name);
 
 // --- Permissions ---
 extern int     getuid();

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