ATA Fixes, Module compilation fixups
authorJohn Hodge <[email protected]>
Thu, 15 Jul 2010 13:26:51 +0000 (21:26 +0800)
committerJohn Hodge <[email protected]>
Thu, 15 Jul 2010 13:26:51 +0000 (21:26 +0800)
- Working on getting the InitRD working again
- Also, I shouldn't blame stable code for bugs (elf loader was blamed
  for issued arising from the module compilation)
- Also been slightly fiddling with the IPStack code

Kernel/bin/elf.c
Kernel/debug.c
Kernel/lib.c
Modules/Filesystems/InitRD/files.lst
Modules/IPStack/tcp.c
Modules/Makefile.tpl
Modules/Storage/ATA/main.c
Usermode/Applications/ifconfig_src/main.c

index 3209c04..731d151 100644 (file)
@@ -285,7 +285,7 @@ int Elf_Relocate(void *Base)
        // Parse Program Header to get Dynamic Table\r
        phtab = Base + hdr->phoff;\r
        iSegmentCount = hdr->phentcount;\r
-       for(i=0;i<iSegmentCount;i++)\r
+       for(i = 0; i < iSegmentCount; i ++ )\r
        {\r
                // Determine linked base address\r
                if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
@@ -294,7 +294,7 @@ int Elf_Relocate(void *Base)
                // Find Dynamic Section\r
                if(phtab[i].Type == PT_DYNAMIC) {\r
                        if(dynamicTab) {\r
-                               Warning("ELF", "Elf_Relocate - Multiple PT_DYNAMIC segments\n");\r
+                               Log_Warning("ELF", "Elf_Relocate - Multiple PT_DYNAMIC segments\n");\r
                                continue;\r
                        }\r
                        dynamicTab = (void *) (tVAddr) phtab[i].VAddr;\r
@@ -305,7 +305,7 @@ int Elf_Relocate(void *Base)
        \r
        // Check if a PT_DYNAMIC segement was found\r
        if(!dynamicTab) {\r
-               Warning("ELF", "Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
+               Log_Warning("ELF", "Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
                LEAVE('x', hdr->entrypoint);\r
                return hdr->entrypoint;\r
        }\r
@@ -347,7 +347,7 @@ int Elf_Relocate(void *Base)
 \r
 \r
        // Alter Symbols to true base\r
-       for(i=0;i<iSymCount;i++)\r
+       for(i = 0; i < iSymCount; i ++)\r
        {\r
                dynsymtab[i].value += iBaseDiff;\r
                dynsymtab[i].nameOfs += (Uint)dynstrtab;\r
@@ -369,10 +369,10 @@ int Elf_Relocate(void *Base)
                // --- Needed Library ---\r
                case DT_NEEDED:\r
                        libPath = dynstrtab + dynamicTab[j].d_val;\r
-                       LOG("Required Library '%s' (IGNORED in kernel mode)\n", libPath);\r
+                       Log_Notice("ELF", "%p - Required Library '%s' (Ignored in kernel mode)\n", Base, libPath);\r
                        break;\r
                // --- PLT/GOT ---\r
-               case DT_PLTGOT: pltgot = (void*)iBaseDiff+(dynamicTab[j].d_val);        break;\r
+               case DT_PLTGOT: pltgot = (void*)(iBaseDiff+dynamicTab[j].d_val);        break;\r
                case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val);   break;\r
                case DT_PLTREL: pltType = dynamicTab[j].d_val;  break;\r
                case DT_PLTRELSZ:       pltSz = dynamicTab[j].d_val;    break;\r
@@ -381,6 +381,7 @@ int Elf_Relocate(void *Base)
                case DT_REL:    rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
                case DT_RELSZ:  relSz = dynamicTab[j].d_val;    break;\r
                case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;\r
+               \r
                case DT_RELA:   rela = (void*)(iBaseDiff + dynamicTab[j].d_val);        break;\r
                case DT_RELASZ: relaSz = dynamicTab[j].d_val;   break;\r
                case DT_RELAENT:        relaEntSz = dynamicTab[j].d_val;        break;\r
@@ -419,6 +420,7 @@ int Elf_Relocate(void *Base)
                {\r
                        Elf32_Rel       *pltRel = plt;\r
                        j = pltSz / sizeof(Elf32_Rel);\r
+                       LOG("PLT Rel - plt = %p, pltSz = %i (%i ents)", plt, pltSz, j);\r
                        for(i = 0; i < j; i++)\r
                        {\r
                                ptr = (void*)(iBaseDiff + pltRel[i].r_offset);\r
@@ -431,9 +433,10 @@ int Elf_Relocate(void *Base)
                {\r
                        Elf32_Rela      *pltRela = plt;\r
                        j = pltSz / sizeof(Elf32_Rela);\r
+                       LOG("PLT RelA - plt = %p, pltSz = %i (%i ents)", plt, pltSz, j);\r
                        for(i=0;i<j;i++)\r
                        {\r
-                               ptr = (void*)((Uint)Base + pltRela[i].r_offset);\r
+                               ptr = (void*)(iBaseDiff + pltRela[i].r_offset);\r
                                if( !Elf_Int_DoRelocate(pltRela[i].r_info, ptr, pltRela[i].r_addend, dynsymtab, (Uint)Base) ) {\r
                                        bFailed = 1;\r
                                }\r
@@ -476,7 +479,7 @@ int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symta
                if( !Elf_GetSymbol((void*)base, sSymName, &val) )       // Search this binary first\r
                        if( !Binary_GetSymbol( sSymName, &val ) )\r
                                return 0;\r
-               LOG("R_386_32 *0x%x += 0x%x('%s')", ptr, val, sSymName);\r
+               LOG("%08x R_386_32 *0x%x += 0x%x('%s')", r_info, ptr, val, sSymName);\r
                *ptr = val + addend;\r
                break;\r
                \r
@@ -485,7 +488,7 @@ int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symta
                if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
                        if( !Binary_GetSymbol( sSymName, &val ) )\r
                                return 0;\r
-               LOG("R_386_PC32 *0x%x = 0x%x + 0x%x('%s') - 0x%x", ptr, *ptr, val, sSymName, (Uint)ptr );\r
+               LOG("%08x R_386_PC32 *0x%x = 0x%x + 0x%x('%s') - 0x%x", r_info, ptr, *ptr, val, sSymName, (Uint)ptr );\r
                // TODO: Check if it needs the true value of ptr or the compiled value\r
                // NOTE: Testing using true value\r
                *ptr = val + addend - (Uint)ptr;\r
@@ -496,7 +499,7 @@ int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symta
                if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
                        if( !Binary_GetSymbol( sSymName, &val ) )\r
                                return 0;\r
-               LOG("R_386_GLOB_DAT *0x%x = 0x%x (%s)", ptr, val, sSymName);\r
+               LOG("%08x R_386_GLOB_DAT *0x%x = 0x%x (%s)", r_info, ptr, val, sSymName);\r
                *ptr = val;\r
                break;\r
        \r
@@ -505,13 +508,13 @@ int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symta
                if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
                        if( !Binary_GetSymbol( sSymName, &val ) )\r
                                return 0;\r
-               LOG("R_386_JMP_SLOT *0x%x = 0x%x (%s)", ptr, val, sSymName);\r
+               LOG("%08x R_386_JMP_SLOT *0x%x = 0x%x (%s)", r_info, ptr, val, sSymName);\r
                *ptr = val;\r
                break;\r
 \r
        // Base Address (B+A)\r
        case R_386_RELATIVE:\r
-               LOG("R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, base, addend);\r
+               LOG("%08x R_386_RELATIVE *0x%x = 0x%x + 0x%x", r_info, ptr, base, addend);\r
                *ptr = base + addend;\r
                break;\r
                \r
index ac5c059..1fe332c 100644 (file)
@@ -11,7 +11,6 @@
 #define DEBUG_TO_SERIAL        1
 #define        SERIAL_PORT     0x3F8
 #define        GDB_SERIAL_PORT 0x2F8
-#define DEBUG_USE_VSNPRINTF    0
 #define        DEBUG_MAX_LINE_LEN      256
 
 // === IMPORTS ===
@@ -56,8 +55,8 @@ int getDebugChar(void)
        if(!gbGDB_SerialSetup) {
                outb(GDB_SERIAL_PORT + 1, 0x00);    // Disable all interrupts
                outb(GDB_SERIAL_PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
-               outb(GDB_SERIAL_PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
-               outb(GDB_SERIAL_PORT + 1, 0x00);    //                  (hi byte)
+               outb(GDB_SERIAL_PORT + 0, 0x0C);    // Set divisor to 12 (lo byte) 9600 baud
+               outb(GDB_SERIAL_PORT + 1, 0x00);    //                   (hi byte)
                outb(GDB_SERIAL_PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
                outb(GDB_SERIAL_PORT + 2, 0xC7);    // Enable FIFO with 14-byte threshold and clear it
                outb(GDB_SERIAL_PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
@@ -77,8 +76,8 @@ static void Debug_PutCharDebug(char ch)
        if(!gbDebug_SerialSetup) {
                outb(SERIAL_PORT + 1, 0x00);    // Disable all interrupts
                outb(SERIAL_PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
-               outb(SERIAL_PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
-               outb(SERIAL_PORT + 1, 0x00);    //                  (hi byte)
+               outb(SERIAL_PORT + 0, 0x0C);    // Set divisor to 12 (lo byte) 9600 baud
+               outb(SERIAL_PORT + 1, 0x00);    //                   (hi byte)
                outb(SERIAL_PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
                outb(SERIAL_PORT + 2, 0xC7);    // Enable FIFO with 14-byte threshold and clear it
                outb(SERIAL_PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
index 5decb9f..a7cffd6 100644 (file)
@@ -691,6 +691,9 @@ Uint rand(void)
  */
 int CheckString(char *String)
 {
+       if( !MM_GetPhysAddr( (tVAddr)String ) )
+               return 0;
+       
        // Check 1st page
        if( MM_IsUser( (tVAddr)String ) )
        {
index 6aa6670..6c91791 100644 (file)
@@ -11,8 +11,9 @@ Dir "Bin" {
 Dir "Libs" {
        File "ld-acess.so" "../../../Usermode/Libraries/ld-acess.so"
        File "libacess.so" "../../../Usermode/Libraries/libacess.so"
-       File "libc.so.1" "../../../Usermode/Libraries/libc.so"
+       File "libc.so" "../../../Usermode/Libraries/libc.so"
        File "libgcc.so" "../../../Usermode/Libraries/libgcc.so"
+       File "libreadline.so" "../../../Usermode/Libraries/libreadline.so"
 }
 Dir "Conf" {
        File "BootConf.cfg" "../../../Usermode/Filesystem/Conf/BootConf.cfg"
index 90f3dc9..bf88dd5 100644 (file)
@@ -124,6 +124,16 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
        Log_Log("TCP", "Checksum = 0x%x", htons(hdr->Checksum));
        Log_Log("TCP", "UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
 */
+       Log_Log("TCP", "Flags = %s%s%s%s%s%s",
+               (hdr->Flags & TCP_FLAG_CWR) ? "CWR " : "",
+               (hdr->Flags & TCP_FLAG_ECE) ? "ECE " : "",
+               (hdr->Flags & TCP_FLAG_URG) ? "URG " : "",
+               (hdr->Flags & TCP_FLAG_ACK) ? "ACK " : "",
+               (hdr->Flags & TCP_FLAG_PSH) ? "PSH " : "",
+               (hdr->Flags & TCP_FLAG_RST) ? "RST " : "",
+               (hdr->Flags & TCP_FLAG_SYN) ? "SYN " : "",
+               (hdr->Flags & TCP_FLAG_FIN) ? "FIN " : ""
+               );
 
        if( Length > (hdr->DataOffset >> 4)*4 )
        {
@@ -823,7 +833,7 @@ Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buf
  */
 void TCP_StartConnection(tTCPConnection *Conn)
 {
-       tTCPHeader      hdr;
+       tTCPHeader      hdr = {0};
 
        Conn->State = TCP_ST_SYN_SENT;
 
@@ -835,7 +845,6 @@ void TCP_StartConnection(tTCPConnection *Conn)
        hdr.Flags = TCP_FLAG_SYN;
        hdr.WindowSize = htons(TCP_WINDOW_SIZE);        // Max
        hdr.Checksum = 0;       // TODO
-       hdr.UrgentPointer = 0;
        
        TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr );
        
index 60824e8..0c66fdd 100644 (file)
@@ -14,13 +14,15 @@ CFGFILES += $(shell test -f Makefile.cfg && echo Makefile.cfg)
 CPPFLAGS := -I$(ACESSDIR)/Kernel/include -I$(ACESSDIR)/Kernel/arch/$(ARCHDIR)/include -DARCH=$(ARCH) $(_CPPFLAGS)
 CFLAGS := -Wall -Werror -fno-stack-protector $(CPPFLAGS) -O3 -fno-builtin
 
-ifeq ($(BUILDTYPE),dynamic)
+ifneq ($(CATEGORY),)
+       FULLNAME := $(CATEGORY)_$(NAME)
+else
+       FULLNAME := $(NAME)
+endif
+
+ifneq ($(BUILDTYPE),static)
        _SUFFIX := dyn_$(ARCH)
-       ifneq ($(CATEGORY),)
-               BIN := ../$(CATEGORY)_$(NAME).kmd.$(ARCH)
-       else
-               BIN := ../$(NAME).kmd.$(ARCH)
-       endif
+       BIN := ../$(FULLNAME).kmd.$(ARCH)
        CFLAGS += $(DYNMOD_CFLAGS) -fPIC
 else
        _SUFFIX := st_$(ARCH)
@@ -41,16 +43,16 @@ clean:
        $(RM) $(BIN) $(BIN).dsm $(KOBJ) $(OBJ) $(DEPFILES)
 
 install: $(BIN)
-ifeq ($(BUILDTYPE),dynamic)
+ifneq ($(BUILDTYPE),static)
        $(xCP) $(BIN) $(DISTROOT)/Modules/$(NAME).kmd.$(ARCH)
 else
 endif
 
-ifeq ($(BUILDTYPE),dynamic)
+ifneq ($(BUILDTYPE),static)
 $(BIN): %.kmd.$(ARCH): $(OBJ)
        @echo --- $(LD) -o $@
-#      $(LD) -T $(ACESSDIR)/Modules/link.ld --allow-shlib-undefined -shared -nostdlib -o $@ $(OBJ)
-       @$(LD) --allow-shlib-undefined -shared -nostdlib -o $@ $(OBJ)
+#      @$(LD) -T $(ACESSDIR)/Modules/link.ld --allow-shlib-undefined -shared -nostdlib -o $@ $(OBJ)
+       @$(LD) --allow-shlib-undefined -shared -nostdlib -o $@ $(OBJ) -defsym=DriverInfo=_DriverInfo_$(FULLNAME)
        @$(DISASM) $(BIN) > $(BIN).dsm
 else
 $(BIN): %.xo.$(ARCH): $(OBJ)
index 4aee411..5e9eaac 100644 (file)
@@ -12,6 +12,8 @@
 #include <tpl_drv_disk.h>
 #include "common.h"
 
+#define IO_DELAY()     do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
+
 // === STRUCTURES ===
 typedef struct
 {
@@ -251,21 +253,34 @@ int ATA_ScanDisk(int Disk)
 
        LOG("base = 0x%x", base);
 
-       if( 0xFF == inb(base+7) ) {
-               LOG("Floating bus");
-               LEAVE('i', 0);
-               return 0;
-       }
-
        // Send Disk Selector
        if(Disk == 1 || Disk == 3)
                outb(base+6, 0xB0);
        else
                outb(base+6, 0xA0);
+       IO_DELAY();
+       
+       // Check for a floating bus
+       if( 0xFF == inb(base+7) ) {
+               LOG("Floating bus");
+               LEAVE('i', 0);
+               return 0;
+       }
+       
+       // Check for the controller
+       outb(base+0x02, 0x66);
+       outb(base+0x03, 0xFF);
+       if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) {
+               LOG("No controller");
+               LEAVE('i', 0);
+               return 0;
+       }
 
        // Send IDENTIFY
        outb(base+7, 0xEC);
+       IO_DELAY();
        val = inb(base+7);      // Read status
+       LOG("val = 0x%02x", val);
        if(val == 0) {
                LEAVE('i', 0);
                return 0;       // Disk does not exist
index ca9b73b..5f50dac 100644 (file)
@@ -3,6 +3,7 @@
  */
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
 #include <acess/sys.h>
 
 #define FILENAME_MAX   255
 #define IPSTACK_ROOT   "/Devices/ip"
 
+// TODO: Move this to a header
+#define ntohs(v)       (((v&0xFF)<<8)|((v>>8)&0xFF))
+
 // === PROTOTYPES ===
 void   PrintUsage(const char *ProgName);
 void   DumpInterfaces(void);
 void   DumpInterface(const char *Name);
  int   AddInterface(const char *Device);
  int   DoAutoConfig(const char *Device);
+ int   SetAddress(int IFNum, const char *Address);
+ int   ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits);
 
 // === CODE ===
 /**
@@ -23,6 +29,7 @@ void  DumpInterface(const char *Name);
  */
 int main(int argc, char *argv[])
 {
+        int    ret;
        // No args, dump interfaces
        if(argc == 1) {
                DumpInterfaces();
@@ -32,12 +39,25 @@ int main(int argc, char *argv[])
        // Add a new interface
        if( strcmp(argv[1], "add") == 0 ) {
                if( argc < 4 ) {
-                       fprintf(stderr, "ERROR: %s add require two arguments, %i passed\n", argv[0], argc-2);
+                       fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2);
                        PrintUsage(argv[0]);
-                       return 0;
+                       return -1;
                }
                // TODO: Also set the IP address as the usage says it does
-               return AddInterface( argv[2] );
+               ret = AddInterface( argv[2] );
+               if(ret < 0)     return ret;
+               ret = SetAddress( ret, argv[3] );
+               return ret;
+       }
+       
+       // Delete an interface
+       if( strcmp(argv[1], "del") == 0 ) {
+               if( argc < 3 ) {
+                       fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]);
+                       PrintUsage(argv[0]);
+                       return -1;
+               }
+               // TODO:
        }
        
        // Autoconfigure an interface
@@ -149,8 +169,8 @@ void DumpInterface(const char *Name)
                ioctl(fd, 5, ip);       // Get IP Address
                subnet = ioctl(fd, 7, NULL);    // Get Subnet Bits
                printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
-                       ip[0], ip[1], ip[2], ip[3],
-                       ip[4], ip[5], ip[6], ip[7],
+                       ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
+                       ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
                        subnet);
                }
                break;
@@ -173,7 +193,6 @@ int AddInterface(const char *Device)
        
        dp = open(IPSTACK_ROOT, OPENFLAG_READ);
        ret = ioctl(dp, 4, (void*)Device);
-       printf("AddInterface: ret = 0x%x = %i\n", ret, ret);
        close(dp);
        
        if( ret < 0 ) {
@@ -232,3 +251,200 @@ int DoAutoConfig(const char *Device)
        
        return 0;
 }
+
+/**
+ * \brief Set the address on an interface from a textual IP address
+ */
+int    SetAddress(int IFNum, const char *Address)
+{
+       uint8_t addr[16];
+        int    type;
+       char    path[sizeof(IPSTACK_ROOT)+1+5+1];       // ip000
+        int    tmp, fd, subnet;
+       
+       // Parse IP Address
+       type = ParseIPAddres(Address, addr, &subnet);
+       if(type == 0) {
+               fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
+               return -1;
+       }
+       
+       // Open file
+       sprintf(path, IPSTACK_ROOT"/%i", IFNum);
+       fd = open(path, OPENFLAG_READ);
+       if( fd == -1 ) {
+               fprintf(stderr, "Unable to open '%s'\n", path);
+               return -1;
+       }
+       
+       tmp = type;
+       tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
+       if( tmp != type ) {
+               fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
+               close(fd);
+               return -1;
+       }
+       // Set Address
+       ioctl(fd, ioctl(fd, 3, "set_address"), addr);
+       
+       // Set Subnet
+       ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
+       
+       close(fd);
+       
+       // Dump!
+       //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
+       
+       return 0;
+}
+
+/**
+ * \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)
+{
+       const char      *p = Address;
+       
+       // Check first block
+       while(*p && *p >= '0' && *p <= '9')     p ++;
+       
+       // IPv4?
+       if(*p == '.')
+       {
+                int    i = 0, j;
+                int    val;
+               
+               for( j = 0; Address[i] && j < 4; j ++ )
+               {
+                       val = 0;
+                       for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
+                       {
+                               val = val*10 + Address[i] - '0';
+                       }
+                       if(val > 255) {
+                               //printf("val > 255 (%i)\n", val);
+                               return 0;
+                       }
+                       Dest[j] = val;
+                       
+                       if(Address[i] == '.')
+                               i ++;
+               }
+               if( j != 4 ) {
+                       //printf("4 parts expected, %i found\n", j);
+                       return 0;
+               }
+               // Parse subnet size
+               if(Address[i] == '/') {
+                       val = 0;
+                       i ++;
+                       while('0' <= Address[i] && Address[i] <= '9') {
+                               val *= 10;
+                               val += Address[i] - '0';
+                               i ++;
+                       }
+                       if(val > 32) {
+                               printf("Notice: Subnet size >32 (%i)\n", val);
+                       }
+                       *SubnetBits = val;
+               }
+               if(Address[i] != '\0') {
+                       //printf("EOS != '\\0', '%c'\n", Address[i]);
+                       return 0;
+               }
+               return 4;
+       }
+       
+       // IPv6
+       if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
+       {
+                int    i = 0;
+                int    j, k;
+                int    val, split = -1, end;
+               uint16_t        hi[8], low[8];
+               
+               for( j = 0; Address[i] && j < 8; j ++ )
+               {
+                       if(Address[i] == '/')
+                               break;
+                       
+                       if(Address[i] == ':') {
+                               if(split != -1) {
+                                       printf("Two '::'s\n");
+                                       return 0;
+                               }
+                               split = j;
+                               i ++;
+                               continue;
+                       }
+                       
+                       val = 0;
+                       for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
+                       {
+                               val *= 16;
+                               if('0' <= Address[i] && Address[i] <= '9')
+                                       val += Address[i] - '0';
+                               else if('A' <= Address[i] && Address[i] <= 'F')
+                                       val += Address[i] - 'A' + 10;
+                               else if('a' <= Address[i] && Address[i] <= 'f')
+                                       val += Address[i] - 'a' + 10;
+                               else {
+                                       printf("%c unexpected\n", Address[i]);
+                                       return 0;
+                               }
+                       }
+                       
+                       if(val > 0xFFFF) {
+                               printf("val (0x%x) > 0xFFFF\n", val);
+                               return 0;
+                       }
+                       
+                       if(split == -1)
+                               hi[j] = val;
+                       else
+                               low[j-split] = val;
+                       
+                       if( Address[i] == ':' ) {
+                               i ++;
+                       }
+               }
+               end = j;
+               
+               // Parse subnet size
+               if(Address[i] == '/') {
+                       val = 0;
+                       while('0' <= Address[i] && Address[i] <= '9') {
+                               val *= 10;
+                               val += Address[i] - '0';
+                               i ++;
+                       }
+                       if(val > 128) {
+                               printf("Notice: Subnet size >128 (%i)\n", val);
+                       }
+                       *SubnetBits = val;
+               }
+               
+               for( j = 0; j < split; j ++ )
+               {
+                       //printf("%04x:", hi[j]);
+                       Dest[j*2] = hi[j]>>8;
+                       Dest[j*2+1] = hi[j]&0xFF;
+               }
+               for( ; j < 8 - (end - split); j++ )
+               {
+                       //printf("0000:", hi[j]);
+                       Dest[j*2] = 0;
+                       Dest[j*2+1] = 0;
+               }
+               for( k = 0; j < 8; j ++, k++)
+               {
+                       //printf("%04x:", low[k]);
+                       Dest[j*2] = low[k]>>8;
+                       Dest[j*2+1] = low[k]&0xFF;
+               }
+               return 6;
+       }
+       // Unknown type
+       return 0;
+}

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