This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/TM4C1294NCPDT: Problem saving new IP Address

Part Number: TM4C1294NCPDT

Tool/software: TI-RTOS

Problem trying to save a new IP Address using the config.c CfgSave routine. i have created a new IP address successfully and am using the example save routine show on page 52 of the NDK v2.25 user guide. My Save routine returns a byte count but the pBuf is not being filled. 

I'm somewhat confused if hCfg in the AddEntry routine picks up the new IP address I furnish it in the *phCfgEntry argument. That's what I am sending to the CfgSave routine.

Any examples of a working add new address/save address would be extremely appreciated.

  • Here's the code that I'm having problems with:

    void netIPAddress(void){
    CI_IPNET NewIPAddr;
    UINT8 *pBuf;
    int size, size1;
    HANDLE hCfgIpAddr;

    /* Setup manual IP address */

    bzero(&NewIPAddr, sizeof(NewIPAddr));
    NewIPAddr.IPAddr = inet_addr("192.168.138.1");
    NewIPAddr.IPMask = inet_addr("255.255.255.0");
    strcpy(NewIPAddr.Domain, "ecam.net");
    NewIPAddr.NetType = 0;

    hCfgIpAddr = CfgNew();
    /* get the current static IP entry */


    /* remove the current static IP entry */
    CfgRemoveEntry(0, hCfgIpAddr);

    /* add a new static IP entry */
    CfgAddEntry(hCfgIpAddr, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (UINT8 *)&NewIPAddr, 0);

    size = 200;

    CfgSave( hCfgIpAddr, &size, 0 );
    if( size && (pBuf = malloc(size) ) )
    {
    size1 = CfgSave(hCfgIpAddr, &size, pBuf );
    //MyMemorySave( pBuf, size );
    free( pBuf );
    }
    }

    As I mentioned above the CfgAddEntry is working OK. What I'm not able to verify is if hCfgIpAddr contains the new address--perhaps there's a way to see data in a HANDLE but CCS says it's not a primitive data type so no can see! CfgSave seems to be working and does return 104 but there is nothing stored in the linear buffer pBuf. Once I have pBuf with data I will store it in external flash (the MyMemorySave). .

  • Some one will answer shortly.
  • I will appreciate greatly any help I can get!

  • My apologies for the extremely large font in my last submittal. it was accidental, my bad!

  • Sorry about the delay. The engineer assigned to look at this was on PTO and I did not realize it. He's back on Monday. Sorry again for the delay.
  • That will be fine. Many thanks for the help in any manner you can provide it. If I can solve this issue before my 85th birthday on July 5th that will be great :).

  • Hi Michael,

    First off, Happy (early) Birthday!

    CfgSave() is meant to be used in conjunction with CfgLoad().

    I think you're running into a problem because that example is assuming that the config was saved in non-volatile storage (via MyMemorySave).  Because of that assumption, pbuf is freed after that.  But, in your case, freeing pbuf blows away your saved configuration!

    I'll attach an older NDK example file that shows CfgSave and CfgLoad example usage.  However, this example won't work easily with NDK 2.25, mainly because the code of "StackTest" is now generated C code. (You could get it to work, but it would take some tweaking. I could guide you with that if you want.  But, I'd say it's best to stick with what you have already, and just take the example CfgSave/Load code as needed)

    In short, the example does this:

    // Global variables:
    UINT8 MainConfig[512];
    int   MainConfigSize   = 0;
    int   MainConfigValid  = 0;
    
    
        // Save the configuration to a linear buffer
        MainConfigSize = 0;
        CfgSave( hCfg, &MainConfigSize, 0 );
        printf("%d bytes required for save\n",MainConfigSize);
        if( MainConfigSize > sizeof( MainConfig ) )
            printf("FATAL: Config buffer too small\n");
        else
        {
            CfgSave( hCfg, &MainConfigSize, MainConfig );
        }
    
        ...
    
        // Load the configuration
        CfgLoad( hCfg, MainConfigSize, MainConfig );

    Can you try that?  Just try saving the configuration, and then reloading it.

    Steve

    webinfo.h

    cfgdemo.c
    /*
     *  Copyright 2007 by Texas Instruments Incorporated.
     *  All rights reserved. Property of Texas Instruments Incorporated.
     *  Restricted rights to use, duplicate or disclose this code are
     *  granted through contract.
     *
     *  @(#) TCP/IP_Network_Developers_Kit 1.93.00.09 08-16-2007 (ndk-c09)
     */
    //--------------------------------------------------------------------------
    // IP Stack Test Program
    //--------------------------------------------------------------------------
    // CfgDemo.c
    //
    // TCP/IP Client Configuration Demo
    //
    // Author: Michael A. Denio
    // Copyright 1999, 2000 by Texas Instruments Inc.
    //-------------------------------------------------------------------------
    #include <stdio.h>
    #include <netmain.h>
    #include <_stack.h>
    #include <common/console/console.h>
    #include <common/servers/servers.h>
    #include "cfgdemo.h"
    #include <c62.h> 
    
    //---------------------------------------------------------------------------
    // Version String
    //
    char *VerStr = "\nTCP/IP Stack Client Configuration Demo\n";
    
    // Simulate a non-volatile configuration
    //=====================================
    UINT8 MainConfig[512];
    int   MainConfigSize   = 0;
    int   MainConfigValid  = 0;
    //=====================================
    
    // Our simulated boot entry point
    static void   NetBoot();
    
    // Routine to get IP address from Ping packet
    static void GetIP( uint IfIdx );
    
    // NC Callback Functions
    static void   NetworkOpen();
    static void   NetworkClose();
    static void   NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd );
    
    // Fun reporting function
    void   ServiceReport( uint Item, uint Status, uint Report, HANDLE hCfgEntry );
    
    
    //---------------------------------------------------------------------
    // Main Entry Point
    //---------------------------------------------------------------------
    int main()
    {}
    
    // This callback function is called by the evaluation stack 5 min before the
    // evaluation period times out.
    void evalCallBack() 
    {
        printf("The Stack is going to shutdown in 5 min\n");
    }
    
    //
    // Main Thread
    //
    int StackTest()
    {
        HANDLE   hCfg;
        char     *hn = "tidsp";
        int      rc;
        uint     tmp;
    
        //
        // THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!!
        //
        rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
        if( rc )
        {
            printf("NC_SystemOpen Failed (%d)\n",rc);
            for(;;);
        }
    
        // Print a banner
        printf(VerStr);
    
        // Enable the EDMA interrupt - since the EDMA interrupt
        // is configurable, this one line of code has no home.
        //
        // NOTE: This code is not required for DM642, nor any
        //       driver environment that does not use EMDA sharing.
        //       However, it doesn't hurt to turn it on.
        C62_enableIER( 1<<8 );
    
        //
        // We'll build a phony "default" configuration in this routine.
        // It will simulate having a default configuration stored in
        // non-volatile storage
        //
    
        // Create a new configuration
        hCfg = CfgNew();
        if( !hCfg )
        {
            printf("Unable to open configuration\n");
            goto main_exit;
        }
    
        // The evaluation version of TCP/IP Stack restricts usage of stack
        // to maximum of 24 Hours. If application wants to be notified 5 min
        // before the timeout, it can register a callback function by using   
        // the following configuration code section.
        {
            void (*pFxn)() = &evalCallBack;
            CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_SYSINFO_EVALCALLBACK, 0,
                        sizeof(void(*)()), (UINT8*) &pFxn, 0 );
        }
    
        // Add our global hostname (to be claimed in all connected domains)
        CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
                     strlen(hn), (UINT8 *)hn, 0 );
    
        // Specify TELNET service
        {
            CI_SERVICE_TELNET telnet;
    
            bzero( &telnet, sizeof(telnet) );
            telnet.cisargs.IPAddr = INADDR_ANY;
            telnet.cisargs.pCbSrv = &ServiceReport;
            telnet.param.MaxCon   = 2;
            telnet.param.Callback = &ConsoleOpen;
            CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_TELNET, 0,
                         sizeof(telnet), (UINT8 *)&telnet, 0 );
        }
    
        // Create RAM based WEB files for HTTP
        AddWebFiles();
    
        // Specify HTTP service
        {
            CI_SERVICE_HTTP http;
    
            bzero( &http, sizeof(http) );
            http.cisargs.IPAddr = INADDR_ANY;
            http.cisargs.pCbSrv = &ServiceReport;
            CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_HTTP, 0,
                         sizeof(http), (UINT8 *)&http, 0 );
        }
    
        // We don't want to see debug messages less than WARNINGS
        tmp = DBG_WARN;
        CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,
                     CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&tmp, 0 );
    
        // Save the configuration to a linear buffer
        MainConfigSize = 0;
        CfgSave( hCfg, &MainConfigSize, 0 );
        printf("%d bytes required for save\n",MainConfigSize);
        if( MainConfigSize > sizeof( MainConfig ) )
            printf("FATAL: Config buffer too small\n");
        else
        {
            CfgSave( hCfg, &MainConfigSize, MainConfig );
            CfgFree( hCfg );
    
            // Now call what would really be the "boot" function
            NetBoot();
        }
    
        // Free the WEB files
        RemoveWebFiles();
    
        // Close the OS
    main_exit:
        NC_SystemClose();
        return(0);
    }
    
    
    //---------------------------------------------------------------------
    // Simulated Boot Entry Point
    //---------------------------------------------------------------------
    static void NetBoot()
    {
        HANDLE   hCfg;
        int      rc;
    
        //
        // Initialize the OS
        //
        // Note - we normally call NC_SystemOpen() here, but its already
        // been done in this simulation.
        //
    
        //
        // Boot the system using stored configuration
        //
        // We keep booting until the function returns 0. This allows
        // us to have a "reboot" command.
        //
        do
        {
            // Create a new configuration
            hCfg = CfgNew();
            if( !hCfg )
            {
                printf("Unable to open configuration\n");
                break;
            }
    
            // Load the configuration
            CfgLoad( hCfg, MainConfigSize, MainConfig );
    
            // Start the stack
            rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );
    
            // Delete Configuration
            CfgFree( hCfg );
        } while( rc > 0 );
    
        //
        // Close the OS
        //
        // Note - we normally call NC_SystemClose() here, but its done for
        // us in this simulation.
        //
    }
    
    //
    // System Task Code
    //
    static HANDLE hGetIP=0,hEcho=0,hData=0,hNull=0,hOob=0;
    
    #ifdef _INCLUDE_IPv6_CODE
    static HANDLE hEcho6=0;
    #endif
    
    //
    // NetworkOpen
    //
    // This function is called after the configuration has booted
    //
    static void NetworkOpen()
    {
        // If we don't have any kind of IP in our configuration, we
        // do a "config by ping" function. The calling parameter is the
        // interface index to configure.
        if( !MainConfigValid )
            hGetIP = TaskCreate( GetIP, "GetIP", OS_TASKPRINORM, 0x1000, 1, 0, 0 );
    
        // Create our local servers
        hEcho = TaskCreate( echosrv, "EchoSrv", OS_TASKPRINORM, 0x1400, 0, 0, 0 );
        hData = TaskCreate( datasrv, "DataSrv", OS_TASKPRINORM, 0x1400, 0, 0, 0 );
        hNull = TaskCreate( nullsrv, "NullSrv", OS_TASKPRINORM, 0x1400, 0, 0, 0 );
        hOob  = TaskCreate( oobsrv,  "OobSrv", OS_TASKPRINORM, 0x1000, 0, 0, 0 );
    
    #ifdef _INCLUDE_IPv6_CODE
        hEcho6 = TaskCreate( v6echosrv, "V6EchoSrv", OS_TASKPRINORM, 0x1400, 0, 0, 0 );
    #endif
    }
    
    //
    // NetworkClose
    //
    // This function is called when the network is shutting down,
    // or when it no longer has any IP addresses assigned to it.
    //
    static void NetworkClose()
    {
        // Kill the GetIP task only if it did not complete
        if( hGetIP )
            fdCloseSession( hGetIP );
        fdCloseSession( hOob );
        fdCloseSession( hNull );
        fdCloseSession( hData );
        fdCloseSession( hEcho );
    
    #ifdef _INCLUDE_IPv6_CODE
        fdCloseSession (hEcho6);
    #endif
    
        // Kill any active console
        ConsoleClose();
    
        // If we opened NETCTRL as NC_PRIORITY_HIGH, we can't
        // kill our task threads until we've given them the
        // opportunity to shutdown. We do this by manually
        // setting our task priority to NC_PRIORITY_LOW.
        TaskSetPri( TaskSelf(), NC_PRIORITY_LOW );
    
        if( hGetIP )
            TaskDestroy( hGetIP );
        TaskDestroy( hOob );
        TaskDestroy( hNull );
        TaskDestroy( hData );
        TaskDestroy( hEcho );
    }
    
    //
    // NetworkIPAddr
    //
    // This function is called whenever an IP address binding is
    // added or removed from the system.
    //
    static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
    {
        IPN IPTmp;
    
        if( fAdd )
            printf("Network Added: ");
        else
            printf("Network Removed: ");
    
        // Print a message
        IPTmp = ntohl( IPAddr );
        printf("If-%d:%d.%d.%d.%d\n", IfIdx,
                (UINT8)(IPTmp>>24)&0xFF, (UINT8)(IPTmp>>16)&0xFF,
                (UINT8)(IPTmp>>8)&0xFF, (UINT8)IPTmp&0xFF );
    }
    
    //
    // Service Status Reports
    //
    // Here's a quick example of using service status updates
    //
    static char *TaskName[]  = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };
    static char *ReportStr[] = { "","Running","Updated","Complete","Fault" };
    static char *StatusStr[] = { "Disabled","Waiting","IPTerm","Failed","Enabled" };
    void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
    {
        printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",
                TaskName[Item-1], StatusStr[Status],
                ReportStr[Report/256], Report&0xFF );
    }
    
    
    //
    // GetIP()
    //
    // Use ICMP ECHO request to get IP address
    //
    #define MAXPACKET 1000 // max packet size
    static void GetIP( uint IfIdx )
    {
        SOCKET   s;
        struct   sockaddr_in from;
        char     *pBuf = 0;
        int      cc, fromlen;
        IPN      IPMe;
        ICMPHDR  *pIcHdr;
        IPHDR    *pIpHdr;
        int      IPHdrLen;
        CI_IPNET NA;
    
        // Allocate FDT
        fdOpenSession( TaskSelf() );
    
        // Create the ICMP Socket
        s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if( s == INVALID_SOCKET )
            goto abort;
    
        // Initialize the "from" address
        bzero( &from, sizeof(struct sockaddr_in));
        from.sin_family     = AF_INET;
        from.sin_len        = sizeof( from );
    
        // Allocate a working buffer
        if( !(pBuf = mmBulkAlloc( MAXPACKET )) )
            goto abort;
    
        printf("GetIP Ready\n");
    
        while(1)
        {
            // Receive ICMP packet data
            fromlen = sizeof(from);
            cc = (int)recvfrom( s, pBuf, MAXPACKET, 0, (PSA)&from, &fromlen );
            if( cc < 0 )
                goto abort;
    
            // Get header pointers
            pIpHdr   = (IPHDR *)pBuf;
            IPHdrLen = (pIpHdr->VerLen & 0xF) * 4;
            pIcHdr   = (ICMPHDR *)(pBuf+IPHdrLen);
    
            // Verify the ICMP type is ECHO request
            if( pIcHdr->Type != ICMP_ECHO )
                continue;
    
            // Use the destination address as our IP address
            IPMe = RdNet32( &pIpHdr->IPDst );
    
            // Add the IP to the configuration
            // Assume the netmask is 255.255.254.0
            bzero( &NA, sizeof(NA) );
            NA.IPAddr = IPMe;
            NA.IPMask = inet_addr("255.255.254.0");
            strcpy( NA.Domain, "default.net" );
            if( CfgAddEntry( 0, CFGTAG_IPNET, IfIdx, 0,
                             sizeof(CI_IPNET), (UINT8 *)&NA, 0 ) >= 0 )
                break;
        }
    
    abort:
        hGetIP = 0;
    
        printf("GetIP Closing\n");
    
        if( pBuf )
            mmBulkFree( pBuf );
        if( s != INVALID_SOCKET )
            fdClose( s );
    
        fdCloseSession( TaskSelf() );
        TaskExit();
    }
    
    

    webpage.c
    /*
     *  Copyright 2007 by Texas Instruments Incorporated.
     *  All rights reserved. Property of Texas Instruments Incorporated.
     *  Restricted rights to use, duplicate or disclose this code are
     *  granted through contract.
     *
     *  @(#) TCP/IP_Network_Developers_Kit 1.93.00.09 08-16-2007 (ndk-c09)
     */
    //--------------------------------------------------------------------------
    // IP Stack Configuration Demonstration
    //--------------------------------------------------------------------------
    // webpage.c
    //
    // Web page and CGI function
    //
    // Author: Michael A. Denio
    // Copyright 2000, 2001 by Texas Instruments Inc.
    //-------------------------------------------------------------------------
    #include <std.h>
    #include <sys.h>
    #include <sem.h>
    #include <tsk.h>
    #include <netmain.h>
    #include "../../../tools/common/console/console.h"
    #include "../../../tools/common/cgi/cgiparse.h"
    #include "cfgdemo.h"
    #include "webinfo.h"
    
    #pragma DATA_SECTION(DEFAULT, ".far:NDK_OBJMEM");
    #include "webdata/default.c"
    #pragma DATA_SECTION(CONFIG, ".far:NDK_OBJMEM");
    #include "webdata/config.c"
    #pragma DATA_SECTION(USERMSG, ".far:NDK_OBJMEM");
    #include "webdata/usermsg.c"
    #pragma DATA_SECTION(TIBUG, ".far:NDK_OBJMEM");
    #include "webdata/tibug.c"
    
    static int cgiCfgStart(SOCKET htmlSock, int ContentLength, char *pArgs);
    static int cgiCfgPass(SOCKET htmlSock, int ContentLength, char *pArgs);
    static int cgiCfgDone(SOCKET htmlSock, int ContentLength, char *pArgs);
    static void UserMessage(SOCKET htmlSock, char *pMsg);
    
    void AddWebFiles(void)
    {
        void *pFxn;
    
        efs_createfile("index.html", DEFAULT_SIZE, DEFAULT);
        efs_createfile("tibug.jpg", TIBUG_SIZE, TIBUG);
        pFxn = (void*) &cgiCfgStart;
        efs_createfile("cfgstart.cgi", 0, (UINT8 *) pFxn);
        pFxn = (void*) &cgiCfgPass;
        efs_createfile("cfgpass.cgi",  0, (UINT8 *) pFxn);
        pFxn = (void*) &cgiCfgDone;
        efs_createfile("cfgdone.cgi",  0, (UINT8 *) pFxn);
    }
    
    void RemoveWebFiles(void)
    {
        efs_destroyfile("cfgstart.cgi");
        efs_destroyfile("cfgpass.cgi");
        efs_destroyfile("cfgdone.cgi");
        efs_destroyfile("tibug.jpg");
        efs_destroyfile("index.html");
    }
    
    // Default password is 'config'
    static char CfgPassword[17] = { 'c', 'o', 'n', 'f', 'i', 'g', 0 };
    
    //
    // Page Creation Macro
    //
    #define html(str) httpSendClientStr(htmlSock, (char *)str)
    
    //
    // Config Functions
    //
    static void ReadConfig();
    static void BuildConfig();
    
    //
    // Current configuration
    //
    // Note if MainConfigValid == 1 then we have *some* valid
    // configuration. Otherwise, we're still in "ping" IP mode
    //
    static char   Hostname[32];
    static char   Domainname[32];
    static char   SessionID[9];
    static int    SessionValid = 0;
    static int    fUseDHCP;
    static IPN    IpAddr;
    static IPN    IpMask;
    static IPN    IpGate;
    static IPN    IpDNS;
    
    //
    // cgiCfgStart()
    //
    // This function is used to request access to a valid confiuration
    // page. It will check the password entered, and generate a new
    // session ID for the page. Then it will fill in the page with the
    // current configuration and display it to the user.
    //
    static int cgiCfgStart(SOCKET htmlSock, int ContentLength, char *pArgs )
    {
        char    *password = 0;
        char    *buffer, *key, *value;
        int     len;
        int     parseIndex;
        UINT32  session,tmp;
        char    IpString[32];
    
        // CGI Functions can now support URI arguments as well if the
        // pArgs pointer is not NULL, and the ContentLength were zero,
        // we could parse the arguments off of pArgs instead.
    
        // First, allocate a buffer for the request
        buffer = (char*) mmBulkAlloc( ContentLength + 1 );
        if ( !buffer )
            goto ERROR;
    
        // Now read the data from the client
        len = recv( htmlSock, buffer, ContentLength, MSG_WAITALL );
        if ( len < 1 )
            goto ERROR;
    
        // Setup to parse the post data
        parseIndex = 0;
        buffer[ContentLength] = '\0';
    
        // Process request variables until there are none left
        do
        {
            key   = cgiParseVars( buffer, &parseIndex );
            value = cgiParseVars( buffer, &parseIndex );
    
            if( !strcmp("password", key) )
                password = value;
        } while ( parseIndex != -1 );
    
        //
        // Output the data we read in...
        //
    
        httpSendStatusLine(htmlSock, HTTP_OK, CONTENT_TYPE_HTML);
        // CRLF before entity
        html( CRLF );
    
        //
        // Generate response
        //
    
        // If the password is incorrect or missing, generate an error
        if( !password || strcmp( CfgPassword, password ) )
        {
            UserMessage( htmlSock, "The password you entered is invalid" );
            goto ERROR;
        }
    
        //
        // The password is corrent. Gernerate the config screen
        //
    
        // Get a new session ID - This is a demo - don't need to be too elaborate
        session = llTimerGetTime( &tmp ) * 113417;
        session += tmp * 705213;
        sprintf( SessionID, "%08x", session );
        SessionValid = 1;
    
        // Read in the current configuration
        ReadConfig();
    
        // Clear the message fields
        memset( CONFIG+CONFIG_SESSIONID_OFFSET, ' ', CONFIG_SESSIONID_MAXLEN );
        memset( CONFIG+CONFIG_HOSTNAME_OFFSET, ' ', CONFIG_HOSTNAME_MAXLEN );
        memset( CONFIG+CONFIG_DOMAIN_OFFSET, ' ', CONFIG_DOMAIN_MAXLEN );
        memset( CONFIG+CONFIG_ADDRTYPE_OFFSET, ' ', CONFIG_ADDRTYPE_MAXLEN );
        memset( CONFIG+CONFIG_IPADDR_OFFSET, ' ', CONFIG_IPADDR_MAXLEN );
        memset( CONFIG+CONFIG_IPMASK_OFFSET, ' ', CONFIG_IPMASK_MAXLEN );
        memset( CONFIG+CONFIG_GATEWAY_OFFSET, ' ', CONFIG_GATEWAY_MAXLEN );
        memset( CONFIG+CONFIG_DNS_OFFSET, ' ', CONFIG_DNS_MAXLEN );
    
        // Fill in the fields
    
        // SessionID
        *(CONFIG+CONFIG_SESSIONID_OFFSET) = '"';
        memcpy(CONFIG+CONFIG_SESSIONID_OFFSET+1,SessionID,8);
        *(CONFIG+CONFIG_SESSIONID_OFFSET+9) = '"';
    
        // Hostname
        mmCopy( CONFIG+CONFIG_HOSTNAME_OFFSET, Hostname, strlen(Hostname) );
    
        // Domainname
        mmCopy( CONFIG+CONFIG_DOMAIN_OFFSET, Domainname, strlen(Domainname) );
    
        // AddrType
        if( !MainConfigValid )
            mmCopy( CONFIG+CONFIG_ADDRTYPE_OFFSET, "Temporary", 9 );
        else if( fUseDHCP )
            mmCopy( CONFIG+CONFIG_ADDRTYPE_OFFSET, "DHCP", 4 );
        else
            mmCopy( CONFIG+CONFIG_ADDRTYPE_OFFSET, "Fixed", 5 );
    
        // IP Addr
        NtIPN2Str( IpAddr, IpString );
        mmCopy( CONFIG+CONFIG_IPADDR_OFFSET, IpString, strlen(IpString) );
    
        // IP Mask
        NtIPN2Str( IpMask, IpString );
        mmCopy( CONFIG+CONFIG_IPMASK_OFFSET, IpString, strlen(IpString) );
    
        // IP Gate
        if( IpGate )
        {
            NtIPN2Str( IpGate, IpString );
            mmCopy( CONFIG+CONFIG_GATEWAY_OFFSET, IpString, strlen(IpString) );
        }
        else
            mmCopy( CONFIG+CONFIG_GATEWAY_OFFSET, "<i>None</i>", 11 );
    
        // IP Addr
        if( IpDNS )
        {
            NtIPN2Str( IpDNS, IpString );
            mmCopy( CONFIG+CONFIG_DNS_OFFSET, IpString, strlen(IpString) );
        }
        else
            mmCopy( CONFIG+CONFIG_DNS_OFFSET, "<i>None</i>", 11 );
    
        // Send the completed form
        send( htmlSock, CONFIG, CONFIG_SIZE, 0 );
    
    ERROR:
        if( buffer )
            mmBulkFree( buffer );
    
        return( 1 );
    }
    
    //
    // cgiCfgPass()
    //
    // This function is used to change the user password.
    //
    static int cgiCfgPass(SOCKET htmlSock, int ContentLength, char *pArgs )
    {
        char    *password = 0, *passnew1 = 0, *passnew2 = 0;
        char    *buffer, *key, *value;
        int     len;
        int     parseIndex;
    
        // CGI Functions can now support URI arguments as well if the
        // pArgs pointer is not NULL, and the ContentLength were zero,
        // we could parse the arguments off of pArgs instead.
    
        // First, allocate a buffer for the request
        buffer = (char*) mmBulkAlloc( ContentLength + 1 );
        if ( !buffer )
            goto ERROR;
    
        // Now read the data from the client
        len = recv( htmlSock, buffer, ContentLength, MSG_WAITALL );
        if ( len < 1 )
            goto ERROR;
    
        // Setup to parse the post data
        parseIndex = 0;
        buffer[ContentLength] = '\0';
    
        // Process request variables until there are none left
        do
        {
            key   = cgiParseVars( buffer, &parseIndex );
            value = cgiParseVars( buffer, &parseIndex );
    
            if( !strcmp("password", key) )
                password = value;
            else if( !strcmp("passnew1", key) )
                passnew1 = value;
            else if( !strcmp("passnew2", key) )
                passnew2 = value;
        } while ( parseIndex != -1 );
    
        //
        // Output the data we read in...
        //
    
        httpSendStatusLine(htmlSock, HTTP_OK, CONTENT_TYPE_HTML);
        // CRLF before entity
        html( CRLF );
    
        //
        // Generate response
        //
    
        // If the password is incorrect or missing, generate an error
        if( !password || strcmp( CfgPassword, password ) )
        {
            UserMessage( htmlSock, "The password you entered is invalid" );
            goto ERROR;
        }
    
        // If the new passwords don't match, generate an error
        if( !passnew1 || !passnew2 || strcmp( passnew1, passnew2 ) )
        {
            UserMessage( htmlSock, "The new passwords you entered do not match" );
            goto ERROR;
        }
    
        // The new password can not be too long, but we won't chance it (the
        // user may have modified the form.
        *(passnew1+16) = 0;
        strcpy( CfgPassword, passnew1 );
        UserMessage( htmlSock, "The password has been changed successfully" );
    
    ERROR:
        if( buffer )
            mmBulkFree( buffer );
    
        return( 1 );
    }
    
    
    //
    // cgiCfgDone()
    //
    // This function is used to submit a new configuration.
    //
    static int cgiCfgDone(SOCKET htmlSock, int ContentLength, char *pArgs )
    {
        char    *sessionid = 0, *hostname = 0, *ipaddrtype = 0, *domain = 0;
        char    *ipaddr = 0, *ipmask = 0, *ipgate = 0, *ipdns = 0;
        char    *buffer, *key, *value;
        int     len;
        int     parseIndex;
        char    StrIp[16];
    
        // CGI Functions can now support URI arguments as well if the
        // pArgs pointer is not NULL, and the ContentLength were zero,
        // we could parse the arguments off of pArgs instead.
    
        // First, allocate a buffer for the request
        buffer = (char*) mmBulkAlloc( ContentLength + 1 );
        if ( !buffer )
            goto ERROR;
    
        // Now read the data from the client
        len = recv( htmlSock, buffer, ContentLength, MSG_WAITALL );
        if ( len < 1 )
            goto ERROR;
    
        // Setup to parse the post data
        parseIndex = 0;
        buffer[ContentLength] = '\0';
    
        // Process request variables until there are none left
        do
        {
            key   = cgiParseVars( buffer, &parseIndex );
            value = cgiParseVars( buffer, &parseIndex );
    
            if( !strcmp("sessionid", key) )
                sessionid = value;
            else if( !strcmp("hostname", key) )
                hostname = value;
            else if( !strcmp("ipaddrtype", key) )
                ipaddrtype = value;
            else if( !strcmp("domain", key) )
                domain = value;
            else if( !strcmp("IPADDR", key) )
                ipaddr = value;
            else if( !strcmp("IPMASK", key) )
                ipmask = value;
            else if( !strcmp("IPGATE", key) )
                ipgate = value;
            else if( !strcmp("IPDNS", key) )
                ipdns = value;
        } while ( parseIndex != -1 );
    
        //
        // Output the data we read in...
        //
    
        httpSendStatusLine(htmlSock, HTTP_OK, CONTENT_TYPE_HTML);
        // CRLF before entity
        html( CRLF );
    
        //
        // Generate response
        //
    
        // If the sessionid is incorrect or missing, generate an error
        if( !SessionValid || !sessionid || strcmp( sessionid, SessionID ) )
        {
            UserMessage( htmlSock, "The configuration session has expired. Operation aborted." );
            goto ERROR;
        }
    
        // The form limits string input, but bound the length anyway in case the form
        // is user-modified.
    
        strncpy( Hostname, hostname, 16 );
        Hostname[16] = 0;
    
        if( !strcmp( ipaddrtype, "auto") )
            fUseDHCP = 1;
        else
        {
            fUseDHCP = 0;
    
            strncpy( Domainname, domain, 31 );
            Hostname[31] = 0;
    
            strncpy( StrIp, ipaddr, 15 );
            StrIp[15] = 0;
            IpAddr = inet_addr(StrIp);
    
            strncpy( StrIp, ipmask, 15 );
            StrIp[15] = 0;
            IpMask = inet_addr(StrIp);
    
            strncpy( StrIp, ipgate, 15 );
            StrIp[15] = 0;
            IpGate = inet_addr(StrIp);
    
            strncpy( StrIp, ipdns, 15 );
            StrIp[15] = 0;
            IpDNS = inet_addr(StrIp);
        }
    
        // Sanity check the results.
        // A real product may want to do more checks than this!
        if( !strlen(Hostname) || (!fUseDHCP &&(!IpAddr || !IpMask)) )
        {
            UserMessage( htmlSock, "The configuration entries are not valid." );
            goto ERROR;
        }
    
        // Install this configuration
        BuildConfig();
    
        UserMessage( htmlSock, "The system is reconfigured and restarting. \
        If the IP address has changed, you may no longer be able to access these pages.");
    
        // Close the socket
        fdClose( htmlSock );
        htmlSock = INVALID_SOCKET;
    
        // Don't accept this session handle again
        SessionValid = 0;
    
        // Wait a second for the confirmation message to go out
        TaskSleep(1000);
    
        // Request stack reboot
        NC_NetStop(1);
    
    ERROR:
        if( buffer )
            mmBulkFree( buffer );
    
        if( htmlSock != INVALID_SOCKET )
            return( 1 );
        return( 0 );
    }
    
    //
    // UserMessage
    //
    // This function alters the usermsg.htm file with the supplied message
    // and sends it to the supplied socket
    //
    static void UserMessage( SOCKET htmlSock, char *pMsg )
    {
        // Clear out any old message
        memset( USERMSG+USERMSG_MESSAGE_OFFSET, ' ', USERMSG_MESSAGE_MAXLEN);
    
        // Copy in new message
        mmCopy( USERMSG+USERMSG_MESSAGE_OFFSET, pMsg, strlen(pMsg) );
    
        // Send out the message
        send( htmlSock, USERMSG, USERMSG_SIZE, 0 );
    }
    
    //
    // ReadConfig()
    //
    // Read Configuration Info from hCfg Handle
    //
    static void ReadConfig()
    {
        CI_SERVICE_DHCPC  dhcpc;
        CI_IPNET          ci_net;
        CI_ROUTE          RT;
        IPN               IP;
        int               i,tmp;
    
        // Get hostname
        tmp = CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 1,
                               31, (UINT8 *)Hostname);
        Hostname[tmp]=0;
    
        // See if we're using DHCP
        tmp = CfgGetImmediate( 0, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT,
                               1, sizeof(dhcpc), (UINT8 *)&dhcpc );
        if( tmp )
            fUseDHCP = 1;
        else
            fUseDHCP = 0;
    
        // Get the IP address information
        IpAddr = 0;
        IpMask = 0;
        strcpy( Domainname, "<i>None</i>" );
    
        tmp = CfgGetImmediate( 0, CFGTAG_IPNET, 1, 1,
                               sizeof(ci_net), (UINT8 *)&ci_net );
        if( tmp )
        {
            IpAddr = ci_net.IPAddr;
            IpMask = ci_net.IPMask;
            *(ci_net.Domain+31) = 0;
            strcpy( Domainname, ci_net.Domain );
        }
    
        // Get the default route (if any)
        IpGate = 0;
        for( i=1; ; i++ )
        {
            tmp = CfgGetImmediate( 0, CFGTAG_ROUTE, 0, i,
                                   sizeof(RT), (UINT8 *)&RT );
            if( !tmp )
                break;
    
            // Look only for a default route
            if( RT.IPDestAddr == 0 && RT.IPDestMask == 0 )
            {
                IpGate = RT.IPGateAddr;
                break;
            }
        }
    
        // Get the DNS values
        tmp = CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
                               1, 4, (UINT8 *)&IP );
        if( tmp == 4 )
            IpDNS = IP;
        else
            IpDNS = 0;
    }
    
    //
    // BuildConfig()
    //
    // Build configuration into linear buffer
    //
    static void BuildConfig()
    {
        int               rc;
        HANDLE            hCfg;
        CI_SERVICE_TELNET telnet;
        CI_SERVICE_HTTP   http;
    
        // Create a new configuration
        hCfg = CfgNew();
        if( !hCfg )
            return;
    
        // Add our global hostname to hCfg (to be claimed in all connected domains)
        CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
                     strlen(Hostname), (UINT8 *)Hostname, 0 );
    
        // If the IP address is specified, use it
        if( !fUseDHCP )
        {
            CI_IPNET NA;
            CI_ROUTE RT;
            IPN      IPTmp;
    
            // Setup manual IP address
            bzero( &NA, sizeof(NA) );
            NA.IPAddr  = IpAddr;
            NA.IPMask  = IpMask;
            strcpy( NA.Domain, Domainname );
            NA.NetType = 0;
    
            // Add the address to interface 1
            CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0,
                               sizeof(CI_IPNET), (UINT8 *)&NA, 0 );
    
            // Add the default gateway. Since it is the default, the
            // destination address and mask are both zero (we go ahead
            // and show the assignment for clarity).
            bzero( &RT, sizeof(RT) );
            RT.IPDestAddr = 0;
            RT.IPDestMask = 0;
            RT.IPGateAddr = IpGate;
    
            // Add the route
            CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,
                               sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );
    
            // Manually add the DNS server when specified
            if( IpDNS )
                CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
                             0, sizeof(IPTmp), (UINT8 *)&IpDNS, 0 );
        }
        // Else we specify DHCP
        else
        {
            CI_SERVICE_DHCPC dhcpc;
    
            // Specify DHCP Service on IF-1
            bzero( &dhcpc, sizeof(dhcpc) );
            dhcpc.cisargs.Mode   = CIS_FLG_IFIDXVALID;
            dhcpc.cisargs.IfIdx  = 1;
            dhcpc.cisargs.pCbSrv = &ServiceReport;
            CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                         sizeof(dhcpc), (UINT8 *)&dhcpc, 0 );
        }
    
        // Specify TELNET service for our Console example
        bzero( &telnet, sizeof(telnet) );
        telnet.cisargs.IPAddr = INADDR_ANY;
        telnet.cisargs.pCbSrv = &ServiceReport;
        telnet.param.MaxCon   = 2;
        telnet.param.Callback = &ConsoleOpen;
        CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_TELNET, 0,
                     sizeof(telnet), (UINT8 *)&telnet, 0 );
    
        // Specify HTTP service
        bzero( &http, sizeof(http) );
        http.cisargs.IPAddr = INADDR_ANY;
        http.cisargs.pCbSrv = &ServiceReport;
        CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_HTTP, 0,
                     sizeof(http), (UINT8 *)&http, 0 );
    
        //
        // Configure IPStack/OS Options
        //
    
        // We don't want to see debug messages less than WARNINGS
        rc = DBG_WARN;
        CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,
                     CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
    
        // Save the configuration to a linear buffer. If the size is not
        // over our max, install the new configuration.
        rc=0;
        CfgSave( hCfg, &rc, 0 );
        if( rc <= 512 )
        {
            MainConfigSize=512;
            CfgSave( hCfg, &MainConfigSize, MainConfig );
            MainConfigValid = 1;
        }
    
        CfgFree( hCfg );
    }
    
    

  • Thank you so much for taking the time to help me and for your birthday wishes!

    So actually I'm checking the buffer contents before it is freed. I'm setting a break point inside the Save routine and checking the buffer contents there after it supposedly has been filled. Eventually I will program the buffer in external flash--our PCB has a 1 MByte flash device where I already save quite a bit of data. Then at startup my intent is to call the Load routine using the saved IP data.

    A big confusion for me is what is contained in hCfg. Obviously, it seems, it has to contain the new IP info but how does it get it? 

    BTW, the program interfaces with a UAV used for reconnaissance. I'm the only programmer on this project that also includes three C# GUI programs that communicate with the RTOS program via both RS232 and ethernet.

    Again, thanks for any help you can provide,

    Michael

  • Hi Michael,

    Michael Antares said:
    A big confusion for me is what is contained in hCfg. Obviously, it seems, it has to contain the new IP info but how does it get it? 

    There's an array of structs that's used to hold the values in the configuration (see struct CFGMAIN in ti/ndk/nettools/config/config.h, which has array of _cfgentry *pCfgEntry[]).

    When saving a configuration, the data of each element of that array is copied into another struct of type CFGENTRYSAVE, and then it is written into the buffer that's provided.

    You can see all of this in the config.h file mentioned above, and the config.c source file in the same directory.

    Michael Antares said:
    So actually I'm checking the buffer contents before it is freed. I'm setting a break point inside the Save routine and checking the buffer contents there after it supposedly has been filled

    Do you see anything in the buffer's contents?

    You should try viewing pBuf in the CCS expressions window (under "view" menu of CCS).


    Try casting pBuf to a CFGENTRYSAVE struct to view it. I.e. enter the following new expression in the expressions window (once you open it):

        (struct CFGENTRYSAVE)pBuf


    Steve

  • Thanks Steve, I'll try your suggestions and let you know the results...