nimuppp.c.patch
Produced: 07/29/2020 12:26:55 PM
   
Mode:  All  
Left file: /tmp/bDAiJi_nimuppp.c  
Right file: /db/vtree/connell/ndk/ndk3.80/ndk-3.80-standard/src/ti/ndk/stack/ppp/nimuppp.c  
/* = /*
 * Copyright (c) 2012-2017, Texas Instruments Incorporated    * Copyright (c) 2012-2017, Texas Instruments Incorporated
 * All rights reserved.    * All rights reserved.
 *    *
 * Redistribution and use in source and binary forms, with or without    * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions    * modification, are permitted provided that the following conditions
 * are met:    * are met:
 *    *
 * *  Redistributions of source code must retain the above copyright    * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.    *    notice, this list of conditions and the following disclaimer.
 *    *
 * *  Redistributions in binary form must reproduce the above copyright    * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the    *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.    *    documentation and/or other materials provided with the distribution.
 *    *
 * *  Neither the name of Texas Instruments Incorporated nor the names of    * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived    *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.    *    from this software without specific prior written permission.
 *    *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * */    * */
/*   /*
 * ======== nimuppp.c ========    * ======== nimuppp.c ========
 *    *
 *  This file has functions which implement the PPP Driver to be compliant    *  This file has functions which implement the PPP Driver to be compliant
 *  with the  Network Interface Management Unit (NIMU). The driver is based    *  with the  Network Interface Management Unit (NIMU). The driver is based
 *  on the original PPP driver but because of the number of changes to the    *  on the original PPP driver but because of the number of changes to the
 *  driver to make it NIMU compliant it was decided to break it into two    *  driver to make it NIMU compliant it was decided to break it into two
 *  seperate files for clarity and readability.    *  seperate files for clarity and readability.
 *    *
 *  The file is only compiled if NIMU support and PPP is enabled.    *  The file is only compiled if NIMU support and PPP is enabled.
 *    *
 */    */
     
#include <stkmain.h>   #include <stkmain.h>
#include <netmain.h>   #include <netmain.h>
  -+ #include "hdlcif.h"
#include "ppp.h" = #include "ppp.h"
     
#ifdef _INCLUDE_PPP_CODE   #ifdef _INCLUDE_PPP_CODE
     
/*********************************************************************   /*********************************************************************
 * FUNCTION NAME : PPPStart    * FUNCTION NAME : PPPStart
 *********************************************************************    *********************************************************************
 * DESCRIPTION   :    * DESCRIPTION   :
 *  The function is used to initialize and start the PPP Protocol    *  The function is used to initialize and start the PPP Protocol
 *    *
 * RETURNS       :    * RETURNS       :
 *  0   -   Success    *  0   -   Success
 *  <0  -   Error    *  <0  -   Error
 *********************************************************************/    *********************************************************************/
static int PPPStart (NETIF_DEVICE* ptr_net_device)   static int PPPStart (NETIF_DEVICE* ptr_net_device)
{   {
    PPP_SESSION*    p;       PPP_SESSION*    p;
     
    /* Get the PPP Session Information from the network device. */       /* Get the PPP Session Information from the network device. */
    p = (PPP_SESSION *)ptr_net_device->pvt_data;       p = (PPP_SESSION *)ptr_net_device->pvt_data;
     
    /* Init PPP Protocols */       /* Init PPP Protocols */
    lcpInit( (void *)p );       lcpInit( (void *)p );
    authInit( (void *)p );       authInit( (void *)p );
    ipcpInit( (void *)p );       ipcpInit( (void *)p );
     
    /* Open LCP */       /* Open LCP */
    lcpOpen( (void *)p, 1 );       lcpOpen( (void *)p, 1 );
    return 0;       return 0;
}   }
     
/*********************************************************************   /*********************************************************************
 * FUNCTION NAME : PPPStop    * FUNCTION NAME : PPPStop
 *********************************************************************    *********************************************************************
 * DESCRIPTION   :    * DESCRIPTION   :
 *  The function is used to de-initialize and stop the PPP protocol    *  The function is used to de-initialize and stop the PPP protocol
 *    *
 * RETURNS       :    * RETURNS       :
 *  0   -   Success    *  0   -   Success
 *  <0  -   Error    *  <0  -   Error
 *********************************************************************/    *********************************************************************/
static int PPPStop (NETIF_DEVICE* ptr_net_device)   static int PPPStop (NETIF_DEVICE* ptr_net_device)
{   {
    PPP_SESSION*    p;       PPP_SESSION*    p;
     
    /* Get the PPP Session Information from the network device. */       /* Get the PPP Session Information from the network device. */
    p = (PPP_SESSION *)ptr_net_device->pvt_data;       p = (PPP_SESSION *)ptr_net_device->pvt_data;
    if( !p || p->Type != HTYPE_PPP )       if( !p || p->Type != HTYPE_PPP )
    {       {
        DbgPrintf(DBG_ERROR,"PPPStop: Bad Handle %08x",p);           DbgPrintf(DBG_ERROR,"PPPStop: Bad Handle %08x",p);
        return -1;           return -1;
    }       }
     
    /* close down LCP if ref count is INUSE_IDLE and not LOCKED */       /* close down LCP if ref count is INUSE_IDLE and not LOCKED */
    if( p->InUse != INUSE_LOCKED )       if( p->InUse != INUSE_LOCKED )
    {       {
        if( p->InUse > INUSE_IDLE )           if( p->InUse > INUSE_IDLE )
        {           {
            p->InUse--;                 /* Deref one count */               p->InUse--;                 /* Deref one count */
        }           }
        else           else
        {           {
            /* Close protocols (closing LCP is sufficient) */               /* Close protocols (closing LCP is sufficient) */
            lcpClose( p );               lcpClose( p );
     
            /* Lock ref count */               /* Lock ref count */
            p->InUse = INUSE_LOCKED;               p->InUse = INUSE_LOCKED;
        }           }
    }       }
    return 0;       return 0;
}   }
     
/*********************************************************************   /*********************************************************************
 * FUNCTION NAME : PPPSend    * FUNCTION NAME : PPPSend
 *********************************************************************    *********************************************************************
 * DESCRIPTION   :    * DESCRIPTION   :
 *  The function is the interface routine invoked by the NDK stack to    *  The function is the interface routine invoked by the NDK stack to
 *  pass packets to the driver.     *  pass packets to the driver. 
 *    *
 * RETURNS       :    * RETURNS       :
 *  0   -   Success    *  0   -   Success
 *  <0  -   Error    *  <0  -   Error
 *********************************************************************/    *********************************************************************/
static int PPPSend (NETIF_DEVICE* ptr_net_device, PBM_Handle hPkt)   static int PPPSend (NETIF_DEVICE* ptr_net_device, PBM_Handle hPkt)
{   {
    PPP_SESSION*    p;       PPP_SESSION*    p;
     
    /* Get the PPP Session Information from the network device. */       /* Get the PPP Session Information from the network device. */
    p = (PPP_SESSION *)ptr_net_device->pvt_data;       p = (PPP_SESSION *)ptr_net_device->pvt_data;
     
    /* Use the call back function to interface this with the PPPoE        /* Use the call back function to interface this with the PPPoE 
     * Layer. NOTE: We will send packets only if the PPP connection        * Layer. NOTE: We will send packets only if the PPP connection
     * is UP and RUNNING; else packets are dropped. */        * is UP and RUNNING; else packets are dropped. */
    if( p->hNet || p->hRoute )       if( p->hNet || p->hRoute )
    {       {
        /* Pass the packet through the call back API for transmission. */                       /* Pass the packet through the call back API for transmission. */            
        p->SICtrl( p->hSI, SI_MSG_SENDPACKET, PPPPROT_IP, (PBM_Pkt *)hPkt);           p->SICtrl( p->hSI, SI_MSG_SENDPACKET, PPPPROT_IP, (PBM_Pkt *)hPkt);
        return 0;           return 0;
    }       }
     
    /* The connection was not up and running; unable to transmit the       /* The connection was not up and running; unable to transmit the
     * packet. */        * packet. */
    return -1;       return -1;
}   }
     
/*********************************************************************   /*********************************************************************
 * FUNCTION NAME : pppNew    * FUNCTION NAME : pppNew
 *********************************************************************    *********************************************************************
 * DESCRIPTION   :    * DESCRIPTION   :
 *  The API is used to create a new PPP device instance. The function    *  The API is used to create a new PPP device instance. The function
 *  has been modified from the original version to be compatible with    *  has been modified from the original version to be compatible with
 *  the NIMU architecture. The function creates a network interface    *  the NIMU architecture. The function creates a network interface
 *  object and registers this with the Network Interface Management    *  object and registers this with the Network Interface Management
 *  Unit.    *  Unit.
 *    *
 * RETURNS       :    * RETURNS       :
 *  Handle to the PPP connection   -   Success    *  Handle to the PPP connection   -   Success
 *  NULL                           -   Error    *  NULL                           -   Error
 *********************************************************************/    *********************************************************************/
void *pppNew( void *hSI, uint32_t pppFlags, uint32_t mru,   void *pppNew( void *hSI, uint32_t pppFlags, uint32_t mru,
               uint32_t IPServer, uint32_t IPMask, uint32_t IPClient,                  uint32_t IPServer, uint32_t IPMask, uint32_t IPClient,
               char *Username, char *Password, uint32_t cmap,                  char *Username, char *Password, uint32_t cmap,
               void (*SICtrl)( void *, uint32_t, uint32_t, PBM_Pkt * ) )                  void (*SICtrl)( void *, uint32_t, uint32_t, PBM_Pkt * ) )
{   {
    PPP_SESSION*    p;       PPP_SESSION*    p;
    NETIF_DEVICE*   ptr_ppp_device;       NETIF_DEVICE*   ptr_ppp_device;
     
    /* Allocate space for PPP Session */       /* Allocate space for PPP Session */
    if( !(p = mmAlloc( sizeof(PPP_SESSION) )) )       if( !(p = mmAlloc( sizeof(PPP_SESSION) )) )
    {       {
        DbgPrintf(DBG_WARN,"pppNew: OOM");           DbgPrintf(DBG_WARN,"pppNew: OOM");
        NotifyLowResource();           NotifyLowResource();
        return(0);           return(0);
    }       }
     
    /* Initialize the allocated block of memory. */       /* Initialize the allocated block of memory. */
    mmZeroInit( p, sizeof(PPP_SESSION) );       mmZeroInit( p, sizeof(PPP_SESSION) );
     
    /* Initialize the session structure. */       /* Initialize the session structure. */
    p->Type     = HTYPE_PPP;       p->Type     = HTYPE_PPP;
    p->InUse    = INUSE_IDLE;       p->InUse    = INUSE_IDLE;
    p->hSI      = hSI;       p->hSI      = hSI;
    p->ProtMTU  = mru;       p->ProtMTU  = mru;
    p->SICtrl   = SICtrl;       p->SICtrl   = SICtrl;
    p->Flags    = pppFlags;       p->Flags    = pppFlags;
    p->MTU_Phys = mru;       p->MTU_Phys = mru;
    p->CMap     = cmap;       p->CMap     = cmap;
    p->MTU_Tx   = p->MTU_Phys;       p->MTU_Tx   = p->MTU_Phys;
    p->MTU_Rx   = p->MTU_Phys;       p->MTU_Rx   = p->MTU_Phys;
     
    /* Allocate memory for the NIMU Network Interface Object. */       /* Allocate memory for the NIMU Network Interface Object. */
    ptr_ppp_device = mmAlloc(sizeof(NETIF_DEVICE));       ptr_ppp_device = mmAlloc(sizeof(NETIF_DEVICE));
    if (ptr_ppp_device == NULL)       if (ptr_ppp_device == NULL)
    {       {
        DbgPrintf(DBG_WARN,"pppNew: OOM");           DbgPrintf(DBG_WARN,"pppNew: OOM");
        NotifyLowResource();           NotifyLowResource();
        return(0);           return(0);
    }       }
     
    /* Initialize the allocated memory block. */       /* Initialize the allocated memory block. */
    mmZeroInit (ptr_ppp_device, sizeof(NETIF_DEVICE));       mmZeroInit (ptr_ppp_device, sizeof(NETIF_DEVICE));
     
    /* Link the PPP Session and NIMU Objects together */       /* Link the PPP Session and NIMU Objects together */
    ptr_ppp_device->pvt_data    = (void *)p;       ptr_ppp_device->pvt_data    = (void *)p;
    p->ptr_ppp_device           = ptr_ppp_device;       p->ptr_ppp_device           = ptr_ppp_device;
     
    /* Populate the Network Interface Object. */       /* Populate the Network Interface Object. */
    strcpy (ptr_ppp_device->name, "ppp0");       strcpy (ptr_ppp_device->name, "ppp0");
    ptr_ppp_device->mtu         = mru;       ptr_ppp_device->mtu         = mru;
     
    /* PPP does not need to have an ARP protocol. */       /* PPP does not need to have an ARP protocol. */
    ptr_ppp_device->flags       = ptr_ppp_device->flags | NIMU_DEVICE_NO_ARP;       ptr_ppp_device->flags       = ptr_ppp_device->flags | NIMU_DEVICE_NO_ARP;
     
    /* Populate the Driver Interface Functions. */       /* Populate the Driver Interface Functions. */
    ptr_ppp_device->start       = PPPStart;       ptr_ppp_device->start       = PPPStart;
    ptr_ppp_device->stop        = PPPStop;       ptr_ppp_device->stop        = PPPStop;
    ptr_ppp_device->poll        = NULL;       ptr_ppp_device->poll        = NULL;
    ptr_ppp_device->send        = PPPSend;       ptr_ppp_device->send        = PPPSend;
    ptr_ppp_device->pkt_service = NULL;       ptr_ppp_device->pkt_service = NULL;
    ptr_ppp_device->ioctl       = NULL;       ptr_ppp_device->ioctl       = NULL;
    ptr_ppp_device->add_header  = NULL;       ptr_ppp_device->add_header  = NULL;
     
    /* Register the device with NIMU */       /* Register the device with NIMU */
    if (NIMURegister (ptr_ppp_device) < 0)       if (NIMURegister (ptr_ppp_device) < 0)
    {       {
        DbgPrintf(DBG_INFO, "pppNew: Error: Unable to register the PPP Device\n");           DbgPrintf(DBG_INFO, "pppNew: Error: Unable to register the PPP Device\n");
        return 0;           return 0;
    }       }
     
    /* Reread the device index received after the NIMURegister as it will have       /* Reread the device index received after the NIMURegister as it will have
     * a unique value assigned to the interface. */        * a unique value assigned to the interface. */
    p->llIndex  = ptr_ppp_device->index;       p->llIndex  = ptr_ppp_device->index;
     
    /* Remaining options are server/client dependent */       /* Remaining options are server/client dependent */
    if( p->Flags & PPPFLG_SERVER )       if( p->Flags & PPPFLG_SERVER )
    {       {
        /* Set the local and peer IP addr */           /* Set the local and peer IP addr */
        p->IPClient = IPClient;           p->IPClient = IPClient;
        p->IPServer = IPServer;           p->IPServer = IPServer;
        p->IPMask   = IPMask;           p->IPMask   = IPMask;
     
        /* If using MS extensions, get the current DNS and NBNS IP addrs */           /* If using MS extensions, get the current DNS and NBNS IP addrs */
        if( p->Flags & PPPFLG_OPT_USE_MSE )           if( p->Flags & PPPFLG_OPT_USE_MSE )
        {           {
            if( p->Flags & PPPFLG_OPT_LOCALDNS )               if( p->Flags & PPPFLG_OPT_LOCALDNS )
            {               {
                /* Read the default DNS and NBNS */                   /* Read the default DNS and NBNS */
                p->IPDNS1   = IPServer;                   p->IPDNS1   = IPServer;
                p->IPDNS2   = 0x0;                   p->IPDNS2   = 0x0;
            }               }
            else               else
            {               {
                /* Here we go external to get the DNS servers */                   /* Here we go external to get the DNS servers */
                llExit();                   llExit();
                CfgGetImmediate( 0, CFGTAG_SYSINFO,                   CfgGetImmediate( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_DOMAINNAMESERVER, 1,                                    CFGITEM_DHCP_DOMAINNAMESERVER, 1,
                                 sizeof(p->IPNBNS1), (unsigned char *)&p->IPDNS1);                                    sizeof(p->IPNBNS1), (unsigned char *)&p->IPDNS1);
                CfgGetImmediate( 0, CFGTAG_SYSINFO,                   CfgGetImmediate( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_DOMAINNAMESERVER, 2,                                    CFGITEM_DHCP_DOMAINNAMESERVER, 2,
                                 sizeof(p->IPNBNS2), (unsigned char *)&p->IPDNS2);                                    sizeof(p->IPNBNS2), (unsigned char *)&p->IPDNS2);
                llEnter();                   llEnter();
            }               }
     
            /* We always go external to get the NBNS servers */               /* We always go external to get the NBNS servers */
            llExit();               llExit();
            CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_NBNS, 1,               CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_NBNS, 1,
                             sizeof(p->IPNBNS1), (unsigned char *)&p->IPNBNS1);                                sizeof(p->IPNBNS1), (unsigned char *)&p->IPNBNS1);
            CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_NBNS, 2,               CfgGetImmediate( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_NBNS, 2,
                             sizeof(p->IPNBNS2), (unsigned char *)&p->IPNBNS2);                                sizeof(p->IPNBNS2), (unsigned char *)&p->IPNBNS2);
            llEnter();               llEnter();
        }           }
    }       }
    else       else
    {       {
        if( Username && strlen(Username) < sizeof(p->UserId) )           if( Username && strlen(Username) < sizeof(p->UserId) )
            strcpy( p->UserId, Username );               strcpy( p->UserId, Username );
        if( Password && strlen(Password) < sizeof(p->Password) )           if( Password && strlen(Password) < sizeof(p->Password) )
            strcpy( p->Password, Password );               strcpy( p->Password, Password );
    }       }
     
    return( (void *)p );       return( (void *)p );
}   }
     
/*********************************************************************   /*********************************************************************
 * FUNCTION NAME : pppFree    * FUNCTION NAME : pppFree
 *********************************************************************    *********************************************************************
 * DESCRIPTION   :    * DESCRIPTION   :
 *  The API is used to close and cleanup an existing PPP connection.    *  The API is used to close and cleanup an existing PPP connection.
 *********************************************************************/    *********************************************************************/
void pppFree( void *hPPP )   void pppFree( void *hPPP )
{   {
    PPP_SESSION*    p;       PPP_SESSION*    p;
     
    /* Get the PPP Session Information and validate it. */           /* Get the PPP Session Information and validate it. */    
    p = (PPP_SESSION *)hPPP;       p = (PPP_SESSION *)hPPP;
    if( !p )       if( !p )
    {       {
        DbgPrintf(DBG_ERROR,"pppFree: Bad Handle %08x",p);           DbgPrintf(DBG_ERROR,"pppFree: Bad Handle %08x",p);
        return;           return;
    }       }
    else if( p->Type != HTYPE_PPP )       else if( p->Type != HTYPE_PPP )
    {       {
        DbgPrintf(DBG_ERROR,"pppFree: Error: Type (%d) != HTYPE_PPP", p->Type);           DbgPrintf(DBG_ERROR,"pppFree: Error: Type (%d) != HTYPE_PPP", p->Type);
        return;           return;
    }       }
     
    /* Remove the route if we have one */       /* Remove the route if we have one */
    if( p->hRoute )       if( p->hRoute )
    {       {
        RtRemove( p->hRoute, FLG_RTF_REPORT, RTC_NETUNREACH );           RtRemove( p->hRoute, FLG_RTF_REPORT, RTC_NETUNREACH );
        RtDeRef( p->hRoute );           RtDeRef( p->hRoute );
    }       }
     
    /* Remove all configuration entries */       /* Remove all configuration entries */
     
    /* Remove client record if any */       /* Remove client record if any */
    if( p->hClient )       if( p->hClient )
    {       {
        CfgRemoveEntry( 0, p->hClient );           CfgRemoveEntry( 0, p->hClient );
    }       }
     
    /* Remove the IP address */       /* Remove the IP address */
    if ( p->hNet )       if ( p->hNet )
    {       {
        llExit();           llExit();
        CfgRemoveEntry(0, p->hNet);           CfgRemoveEntry(0, p->hNet);
        llEnter();           llEnter();
    }       }
     
    /* Unregister and stop the device. */       /* Unregister and stop the device. */
    if (NIMUUnregister(p->ptr_ppp_device) < 0)       if (NIMUUnregister(p->ptr_ppp_device) < 0)
    {       {
        DbgPrintf(DBG_INFO,           DbgPrintf(DBG_INFO,
                "pppFree: Error: Unregistering PPP device %d failed\n",                   "pppFree: Error: Unregistering PPP device %d failed\n",
                p->llIndex);                   p->llIndex);
    }       }
     
    /* Cleanup the memory allocated in pppNew (ptr_ppp_device freed by NIMU) */       /* Cleanup the memory allocated in pppNew (ptr_ppp_device freed by NIMU) */
    mmFree (p);       mmFree (p);
     
    return;       return;
}   }
     
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
/* pppTimer() */   /* pppTimer() */
/* Timer function called once per second */   /* Timer function called once per second */
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
void pppTimer( void *hPPP )   void pppTimer( void *hPPP )
{   {
    PPP_SESSION *p = (PPP_SESSION *)hPPP;       PPP_SESSION *p = (PPP_SESSION *)hPPP;
  -+     void *hHDLC;
  =  
    if( !p || p->Type != HTYPE_PPP )       if( !p || p->Type != HTYPE_PPP )
    {       {
        DbgPrintf(DBG_ERROR,"pppTimer: Bad Handle %08x",p);           DbgPrintf(DBG_ERROR,"pppTimer: Bad Handle %08x",p);
        return;           return;
    }       }
     
    /* Add reference and execute */       /* Add reference and execute */
    if( p->InUse < (INUSE_LOCKED-1) )       if( p->InUse < (INUSE_LOCKED-1) )
    {       {
        p->InUse++;           p->InUse++;
     
  -+         /*
             * On disconnect, any of the following timer functions may actually
             * free the PPP session (i.e. 'p'). If this happens, the HDLC instance's
             * status will be set to disconnected.
             */
            hHDLC = p->hSI;
     
        lcpTimer( p ); =         lcpTimer( p );
  -+         if (hdlcGetStatus(hHDLC) >= SI_CSTATUS_DISCONNECT) {
                // lcpTimer has freed the PPP session! Further operations on 'p'
                // are invalid
                return;
            }
     
        authTimer( p ); =         authTimer( p );
  -+         if (hdlcGetStatus(hHDLC) >= SI_CSTATUS_DISCONNECT) {
                // authTimer has freed the PPP session! Further operations on 'p'
                // are invalid
                return;
            }
     
        ipcpTimer( p ); =         ipcpTimer( p );
  -+         if (hdlcGetStatus(hHDLC) >= SI_CSTATUS_DISCONNECT) {
                // ipcpTimer has freed the PPP session! Further operations on 'p'
                // are invalid
                return;
            }
  =  
        /* Remove reference */           /* Remove reference */
        if( p->InUse == INUSE_IDLE )           if( p->InUse == INUSE_IDLE )
            pppFree( p );               pppFree( p );
        else           else
            p->InUse--;               p->InUse--;
    }       }
}   }
     
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
/* pppInput() */   /* pppInput() */
/* Called when a packet is received by the serial interface */   /* Called when a packet is received by the serial interface */
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
void pppInput( void *hPPP, PBM_Pkt *pPkt )   void pppInput( void *hPPP, PBM_Pkt *pPkt )
{   {
    PPP_SESSION *p = (PPP_SESSION *)hPPP;       PPP_SESSION *p = (PPP_SESSION *)hPPP;
    uint16_t    type;       uint16_t    type;
    unsigned char     *pb;       unsigned char     *pb;
     
    if( !p || p->Type != HTYPE_PPP )       if( !p || p->Type != HTYPE_PPP )
    {       {
        DbgPrintf(DBG_ERROR,"pppInput: Bad Handle %08x",p);           DbgPrintf(DBG_ERROR,"pppInput: Bad Handle %08x",p);
        PBM_free( pPkt );           PBM_free( pPkt );
        return;           return;
    }       }
     
    if( !pPkt || pPkt->ValidLen < 2 )       if( !pPkt || pPkt->ValidLen < 2 )
    {       {
        DbgPrintf(DBG_ERROR,"pppInput: Bad packet!");           DbgPrintf(DBG_ERROR,"pppInput: Bad packet!");
        return;           return;
    }       }
     
    /* Add reference and execute */       /* Add reference and execute */
    if( p->InUse < (INUSE_LOCKED-1) )       if( p->InUse < (INUSE_LOCKED-1) )
    {       {
        p->InUse++;           p->InUse++;
     
        /* Set pb to point to PPP header */           /* Set pb to point to PPP header */
        pb = pPkt->pDataBuffer + pPkt->DataOffset;           pb = pPkt->pDataBuffer + pPkt->DataOffset;
     
        /* Adjust packet to point to next header */           /* Adjust packet to point to next header */
        pPkt->DataOffset += 2;           pPkt->DataOffset += 2;
        pPkt->ValidLen   -= 2;           pPkt->ValidLen   -= 2;
     
        type = RdNet16s(pb);           type = RdNet16s(pb);
     
        switch( type )           switch( type )
        {           {
        case PPPPROT_IP:           case PPPPROT_IP:
            /* Only pass IP if hNet or hRoute is set */               /* Only pass IP if hNet or hRoute is set */
            if( p->hNet || p->hRoute )               if( p->hNet || p->hRoute )
            {               {
                /* Setup packet to look like it came from Ethernet */                   /* Setup packet to look like it came from Ethernet */
                pPkt->hIFRx       = p->ptr_ppp_device;                   pPkt->hIFRx       = p->ptr_ppp_device;
                pPkt->EtherType   = 0x800;                   pPkt->EtherType   = 0x800;
     
                /* Give it to IP */                   /* Give it to IP */
                IPRxPacket( pPkt );     /* Consume packet */                   IPRxPacket( pPkt );     /* Consume packet */
                break;                   break;
            }               }
            PBM_free( pPkt );           /* Free packet */               PBM_free( pPkt );           /* Free packet */
            break;               break;
     
        case PPPPROT_LCP:           case PPPPROT_LCP:
            lcpInput( p, pPkt );        /* Consume packet */               lcpInput( p, pPkt );        /* Consume packet */
            break;               break;
     
        case PPPPROT_PAP:           case PPPPROT_PAP:
            papInput( p, pPkt );        /* Consume packet */               papInput( p, pPkt );        /* Consume packet */
            break;               break;
     
        case PPPPROT_CHAP:           case PPPPROT_CHAP:
            chapInput( p, pPkt );       /* Consume packet */               chapInput( p, pPkt );       /* Consume packet */
            break;               break;
     
        case PPPPROT_IPCP:           case PPPPROT_IPCP:
            ipcpInput( p, pPkt );       /* Consume packet */               ipcpInput( p, pPkt );       /* Consume packet */
            break;               break;
     
        default:           default:
            /* Put the protocol back on the packet */               /* Put the protocol back on the packet */
            pPkt->DataOffset -= 2;               pPkt->DataOffset -= 2;
            pPkt->ValidLen   += 2;               pPkt->ValidLen   += 2;
            lcpReject( p, pPkt );       /* Reject packet */               lcpReject( p, pPkt );       /* Reject packet */
            break;               break;
        }           }
     
        /* Remove reference */           /* Remove reference */
        if( p->InUse == INUSE_IDLE )           if( p->InUse == INUSE_IDLE )
            pppFree( p );               pppFree( p );
        else           else
            p->InUse--;               p->InUse--;
    }       }
}   }
     
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
/* pppAddIP() */   /* pppAddIP() */
/* Local function to add IP address via the configuration system */   /* Local function to add IP address via the configuration system */
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
static void *pppAddIP( uint32_t Index, uint32_t NetType, uint32_t IPAddr,   static void *pppAddIP( uint32_t Index, uint32_t NetType, uint32_t IPAddr,
                        uint32_t IPMask )                           uint32_t IPMask )
{   {
    CI_IPNET NA;       CI_IPNET NA;
    int      rc;       int      rc;
    void  *hNet;       void  *hNet;
     
    /* Initialize Network Address */       /* Initialize Network Address */
    mmZeroInit( &NA, sizeof(NA) );       mmZeroInit( &NA, sizeof(NA) );
    NA.NetType = NetType;       NA.NetType = NetType;
    NA.IPAddr  = IPAddr;       NA.IPAddr  = IPAddr;
    NA.IPMask  = IPMask;       NA.IPMask  = IPMask;
    NDK_sprintf( NA.Domain, "localppp%d.net", Index );       NDK_sprintf( NA.Domain, "localppp%d.net", Index );
     
    /* Add the Entry */       /* Add the Entry */
    /* Note we need to keep a copy of the address we add in the event */       /* Note we need to keep a copy of the address we add in the event */
    /* that we need to remove it later. An alternate way of doing this */       /* that we need to remove it later. An alternate way of doing this */
    /* would be to search the configuration for the entry we want to */       /* would be to search the configuration for the entry we want to */
    /* remove once its time, but this way is cleaner. */       /* remove once its time, but this way is cleaner. */
    llExit();       llExit();
    rc = CfgAddEntry( 0, CFGTAG_IPNET, Index,       rc = CfgAddEntry( 0, CFGTAG_IPNET, Index,
            CFG_ADDMODE_NOSAVE | CFG_ADDMODE_UNIQUE, sizeof(CI_IPNET),               CFG_ADDMODE_NOSAVE | CFG_ADDMODE_UNIQUE, sizeof(CI_IPNET),
            (unsigned char *)&NA, &hNet );               (unsigned char *)&NA, &hNet );
    if( rc < 0 )       if( rc < 0 )
    {       {
        /* If this is a service error, the entry was still added */           /* If this is a service error, the entry was still added */
        if( rc <= CFGERROR_SERVICE )           if( rc <= CFGERROR_SERVICE )
            CfgRemoveEntry( 0, hNet );               CfgRemoveEntry( 0, hNet );
        hNet = 0;           hNet = 0;
    }       }
    llEnter();       llEnter();
     
    return(hNet);       return(hNet);
}   }
     
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
/* pppAddClient() */   /* pppAddClient() */
/* Local function to add a client record to the configuration system */   /* Local function to add a client record to the configuration system */
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
static void *pppAddClient( uint32_t Index, uint32_t IPAddr, char *Name )   static void *pppAddClient( uint32_t Index, uint32_t IPAddr, char *Name )
{   {
    CI_CLIENT CC;       CI_CLIENT CC;
    int       rc;       int       rc;
    void   *hClient;       void   *hClient;
     
    /* Initialize Network Address */       /* Initialize Network Address */
    mmZeroInit( &CC, sizeof(CC) );       mmZeroInit( &CC, sizeof(CC) );
     
    CC.ClientType = CFG_CLIENTTYPE_DYNAMIC;       CC.ClientType = CFG_CLIENTTYPE_DYNAMIC;
    CC.IPAddr     = IPAddr;       CC.IPAddr     = IPAddr;
    CC.Status     = CFG_CLIENTSTATUS_STATIC;       CC.Status     = CFG_CLIENTSTATUS_STATIC;
     
    if (strlen(Name) < CFG_HOSTNAME_MAX) {       if (strlen(Name) < CFG_HOSTNAME_MAX) {
        strcpy( CC.Hostname, Name );           strcpy( CC.Hostname, Name );
    }       }
    else {       else {
        return (0);           return (0);
    }       }
     
    /* Add it to the configuration */       /* Add it to the configuration */
    llExit();       llExit();
    rc = CfgAddEntry( 0, CFGTAG_CLIENT, Index, CFG_ADDMODE_NOSAVE,       rc = CfgAddEntry( 0, CFGTAG_CLIENT, Index, CFG_ADDMODE_NOSAVE,
                      sizeof(CI_CLIENT), (unsigned char *)&CC, &hClient );                         sizeof(CI_CLIENT), (unsigned char *)&CC, &hClient );
    if( rc < 0 )       if( rc < 0 )
    {       {
        /* If this is a service error, the entry was still added */           /* If this is a service error, the entry was still added */
        if( rc <= CFGERROR_SERVICE )           if( rc <= CFGERROR_SERVICE )
            CfgRemoveEntry( 0, hClient );               CfgRemoveEntry( 0, hClient );
        hClient = 0;           hClient = 0;
    }       }
    llEnter();       llEnter();
     
    return(hClient);       return(hClient);
}   }
     
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
/* pppEvent() */   /* pppEvent() */
/* Event function called by upper level protocols */   /* Event function called by upper level protocols */
/*-------------------------------------------------------------------- */   /*-------------------------------------------------------------------- */
void pppEvent( void *hPPP, uint32_t Event )   void pppEvent( void *hPPP, uint32_t Event )
{   {
    PPP_SESSION *p = (PPP_SESSION *)hPPP;       PPP_SESSION *p = (PPP_SESSION *)hPPP;
    NETIF_DEVICE*   ptr_ppp_device;       NETIF_DEVICE*   ptr_ppp_device;
     
    switch( Event )       switch( Event )
    {       {
    case PPP_EVENT_LCP_CONNECT:       case PPP_EVENT_LCP_CONNECT:
        if( p->auth.Protocol )           if( p->auth.Protocol )
        {           {
            authStart( p );               authStart( p );
            p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_AUTHORIZE, 0);               p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_AUTHORIZE, 0);
            break;               break;
        }           }
     
        /* Fallthrough ... */           /* Fallthrough ... */
     
    case PPP_EVENT_AUTH_CONNECT:       case PPP_EVENT_AUTH_CONNECT:
        ipcpStart( p );           ipcpStart( p );
        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_CONFIGURE, 0);           p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_CONFIGURE, 0);
        break;           break;
     
    case PPP_EVENT_IPCP_CONNECT:       case PPP_EVENT_IPCP_CONNECT:
        /* Use the smallest of all the MTU's */           /* Use the smallest of all the MTU's */
        if( p->ProtMTU > p->MTU_Tx )           if( p->ProtMTU > p->MTU_Tx )
            p->ProtMTU = p->MTU_Tx;               p->ProtMTU = p->MTU_Tx;
        if( p->ProtMTU > p->MTU_Rx )           if( p->ProtMTU > p->MTU_Rx )
            p->ProtMTU = p->MTU_Rx;               p->ProtMTU = p->MTU_Rx;
     
        /* Get the pointer to the PPP Network Interface Object */           /* Get the pointer to the PPP Network Interface Object */
        ptr_ppp_device = NIMUFindByIndex (p->llIndex);           ptr_ppp_device = NIMUFindByIndex (p->llIndex);
        if (ptr_ppp_device == NULL)           if (ptr_ppp_device == NULL)
        {           {
            DbgPrintf(DBG_ERROR,"pppEvent: NIMU Object for PPP %d does not exist", p->llIndex);               DbgPrintf(DBG_ERROR,"pppEvent: NIMU Object for PPP %d does not exist", p->llIndex);
            return;               return;
        }           }
     
        if( p->Flags & PPPFLG_SERVER )           if( p->Flags & PPPFLG_SERVER )
        {           {
            /* SERVER MODE */               /* SERVER MODE */
     
            /* Create the Local Address */               /* Create the Local Address */
            if( p->Flags & PPPFLG_OPT_LOCALDNS )               if( p->Flags & PPPFLG_OPT_LOCALDNS )
            {               {
                p->hNet = pppAddIP( p->llIndex,                   p->hNet = pppAddIP( p->llIndex,
                                    CFG_NETTYPE_DYNAMIC | CFG_NETTYPE_VIRTUAL,                                       CFG_NETTYPE_DYNAMIC | CFG_NETTYPE_VIRTUAL,
                                    p->IPServer, p->IPMask );                                       p->IPServer, p->IPMask );
                p->hClient = pppAddClient(p->llIndex, p->IPClient, p->UserId);                   p->hClient = pppAddClient(p->llIndex, p->IPClient, p->UserId);
            }               }
            else               else
                p->hNet = pppAddIP( p->llIndex, CFG_NETTYPE_DYNAMIC,                   p->hNet = pppAddIP( p->llIndex, CFG_NETTYPE_DYNAMIC,
                                    p->IPServer, p->IPMask );                                       p->IPServer, p->IPMask );
     
            /* Create a route to the client. Also proxy it just in case its */               /* Create a route to the client. Also proxy it just in case its */
            /* on the same subnet as our Ethernet devices. */               /* on the same subnet as our Ethernet devices. */
            p->hRoute = RtCreate( FLG_RTF_REPORT, FLG_RTE_PROXY | FLG_RTE_HOST,               p->hRoute = RtCreate( FLG_RTF_REPORT, FLG_RTE_PROXY | FLG_RTE_HOST,
                                  p->IPClient, 0xffffffff, (void *)ptr_ppp_device, 0, 0 );                                     p->IPClient, 0xffffffff, (void *)ptr_ppp_device, 0, 0 );
        }           }
        else           else
        {           {
            /* CLIENT MODE */               /* CLIENT MODE */
     
            /* Create the Local Address */               /* Create the Local Address */
            p->hNet = pppAddIP( p->llIndex, CFG_NETTYPE_DYNAMIC,               p->hNet = pppAddIP( p->llIndex, CFG_NETTYPE_DYNAMIC,
                                p->IPClient, 0xffffffff );                                   p->IPClient, 0xffffffff );
     
            /* If point to point mode, create a direct route */               /* If point to point mode, create a direct route */
            if( p->Flags & PPPFLG_OPT_CLIENT_P2P )               if( p->Flags & PPPFLG_OPT_CLIENT_P2P )
                p->hRoute = RtCreate( FLG_RTF_REPORT, FLG_RTE_PROXY | FLG_RTE_HOST,                   p->hRoute = RtCreate( FLG_RTF_REPORT, FLG_RTE_PROXY | FLG_RTE_HOST,
                                      p->IPServer, 0xffffffff, (void *)ptr_ppp_device, 0, 0 );                                         p->IPServer, 0xffffffff, (void *)ptr_ppp_device, 0, 0 );
            /* Else create a default route that sends everything up this uplink */               /* Else create a default route that sends everything up this uplink */
            else               else
                p->hRoute = RtCreate( FLG_RTF_REPORT, 0, 0, 0, (void *)ptr_ppp_device, 0, 0 );                   p->hRoute = RtCreate( FLG_RTF_REPORT, 0, 0, 0, (void *)ptr_ppp_device, 0, 0 );
     
            /* If using MS extensions, record the new values */               /* If using MS extensions, record the new values */
            if( p->Flags & PPPFLG_OPT_USE_MSE )               if( p->Flags & PPPFLG_OPT_USE_MSE )
            {               {
                void *hEntry;                   void *hEntry;
     
                llExit();                   llExit();
     
                /* Remove all current DNS Entries from configuration */                   /* Remove all current DNS Entries from configuration */
                while( CfgGetEntry( 0, CFGTAG_SYSINFO,                   while( CfgGetEntry( 0, CFGTAG_SYSINFO,
                       CFGITEM_DHCP_DOMAINNAMESERVER, 1, &hEntry ) )                          CFGITEM_DHCP_DOMAINNAMESERVER, 1, &hEntry ) )
                    CfgRemoveEntry( 0, hEntry );                       CfgRemoveEntry( 0, hEntry );
     
                /* Remove all current NBNS Entries from configuration */                   /* Remove all current NBNS Entries from configuration */
                while( CfgGetEntry( 0, CFGTAG_SYSINFO,                   while( CfgGetEntry( 0, CFGTAG_SYSINFO,
                       CFGITEM_DHCP_NBNS, 1, &hEntry ) )                          CFGITEM_DHCP_NBNS, 1, &hEntry ) )
                    CfgRemoveEntry( 0, hEntry );                       CfgRemoveEntry( 0, hEntry );
     
                /* Add the entries we got from the server */                   /* Add the entries we got from the server */
                if( p->IPDNS1 )                   if( p->IPDNS1 )
                    CfgAddEntry( 0, CFGTAG_SYSINFO,                       CfgAddEntry( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_DOMAINNAMESERVER,                                    CFGITEM_DHCP_DOMAINNAMESERVER,
                                 CFG_ADDMODE_NOSAVE,                                    CFG_ADDMODE_NOSAVE,
                                 4, (unsigned char *)&p->IPDNS1, 0 );                                    4, (unsigned char *)&p->IPDNS1, 0 );
     
                if( p->IPDNS2 )                   if( p->IPDNS2 )
                    CfgAddEntry( 0, CFGTAG_SYSINFO,                       CfgAddEntry( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_DOMAINNAMESERVER,                                    CFGITEM_DHCP_DOMAINNAMESERVER,
                                 CFG_ADDMODE_NOSAVE,                                    CFG_ADDMODE_NOSAVE,
                                 4, (unsigned char *)&p->IPDNS2, 0 );                                    4, (unsigned char *)&p->IPDNS2, 0 );
     
                if( p->IPNBNS1 )                   if( p->IPNBNS1 )
                    CfgAddEntry( 0, CFGTAG_SYSINFO,                       CfgAddEntry( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_NBNS,                                    CFGITEM_DHCP_NBNS,
                                 CFG_ADDMODE_NOSAVE,                                    CFG_ADDMODE_NOSAVE,
                                 4, (unsigned char *)&p->IPNBNS1, 0 );                                    4, (unsigned char *)&p->IPNBNS1, 0 );
     
                if( p->IPNBNS2 )                   if( p->IPNBNS2 )
                    CfgAddEntry( 0, CFGTAG_SYSINFO,                       CfgAddEntry( 0, CFGTAG_SYSINFO,
                                 CFGITEM_DHCP_NBNS,                                    CFGITEM_DHCP_NBNS,
                                 CFG_ADDMODE_NOSAVE,                                    CFG_ADDMODE_NOSAVE,
                                 4, (unsigned char *)&p->IPNBNS2, 0 );                                    4, (unsigned char *)&p->IPNBNS2, 0 );
     
                llEnter();                   llEnter();
            }               }
        }           }
        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_CONNECTED, 0);           p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_CONNECTED, 0);
        break;           break;
     
    case PPP_EVENT_LCP_STOPPED:       case PPP_EVENT_LCP_STOPPED:
        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_LCP, 0);           p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_LCP, 0);
        break;           break;
     
    case PPP_EVENT_AUTH_STOPPED:       case PPP_EVENT_AUTH_STOPPED:
        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_AUTH, 0);           p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_AUTH, 0);
        break;           break;
     
    case PPP_EVENT_IPCP_STOPPED:       case PPP_EVENT_IPCP_STOPPED:
        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_IPCP, 0);           p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT_IPCP, 0);
        break;           break;
    }       }
}   }
     
#endif /* _INCLUDE_PPP_CODE */   #endif /* _INCLUDE_PPP_CODE */