/*
 *            Copyright (c) 1998-2003 by NETsilicon Inc.
 *
 *  This software is copyrighted by and is the sole property of 
 *  NETsilicon.  All rights, title, ownership, or other interests
 *  in the software remain the property of NETsilicon.  This
 *  software may only be used in accordance with the corresponding
 *  license agreement.  Any unauthorized use, duplication, transmission,  
 *  distribution, or disclosure of this software is expressly forbidden.
 *
 *  This Copyright notice may not be removed or modified without prior
 *  written consent of NETsilicon.
 *
 *  NETsilicon, reserves the right to modify this software
 *  without notice.
 *
 *  NETsilicon
 *  411 Waverley Oaks Road                  USA 781.647.1234
 *  Suite 304                               http://www.netsilicon.com
 *  Waltham, MA 02452                       AmericaSales@netsilicon.com
 *
 *************************************************************************
 *
 *  Description
 *  ====================================================================
 *  This file contains definitions used in ACE.
 *
 */
#ifndef ace_h
#define ace_h

#include <stddef.h>
#include <time.h>
#include "npttypes.h"
#include "time.h"
#include "naifconfig.h"

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * Address Configuration Executive (ACE) controls the process of acquiring
 * an IP address and other IP configuration settings, and configures the 
 * IP stack.  The ACE API is broken up into three categories.
 *
 * <list type="unordered">
 *  <item>ACE Callbacks: describes a set of callback functions that are called by
 *        ACE when certain events happen.  You must update the template implementations
 *        of these functions as required by your application.</item>
 *  <item>ACE Parameters: describes the functions used to read and write the ACE
 *        configuration in NVRAM, and the default values for the configuration.  You
 *        must update the default values as required by your application.</item>
 *  <item>ACE API: describes the functions and data structures that will be needed
 *        by the callback functions, and by any custom protocols that you implement.</item>
 * </list>
 *
 * @external
 * @category ACE
 * @since 6.0
 * @overview ACE
 */



/**
 * ACE has built
 * in support for DHCP, BOOTP, Ping ARP, RARP, and Auto IP protocols, and for 
 * using static IP addresses.  ACE invokes a set of callback functions at various
 * points in the process of acquiring an address.  The ACE API consists of the 
 * functions that the callbacks can use to get more information about the IP information
 * ACE acquired, and to configure an IP interface with the new settings.
 *
 *
 * ACE also has provisions for supporting an application specific protocol for 
 * acquire an IP configuration.  The ACE API also defines the ACE functions needed
 * by such an implementation.
 *
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 * @overview ACE API
 */


/**
 * Maximum number of protocols running under ACE.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 */
#define ACE_MAX_PROTOCOLS	8   

/**
 * Maximum number of IP addresses of DNS servers 
 * obtained by ACE.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 */   
#define ACE_MAX_DNS_SERVERS 3

/**
 * Maximum size of domain name in bytes. 
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 */   
#define ACE_MAX_DOMAIN_NAME 128


/**
 * The structure of this type is returned to ACE by a protocol  
 * routine get_addr_fn and passed to the application
 * by ACE have_addr_fn and  have_2nd_addr_fn callbacks.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param ipaddr                host IP address
 * @param netmask               subnet mask
 * @param servaddr              IP address of the server that assigned 
 *                              this host IP address - DHCP, BOOTP 
 *                              server, etc. 
 * @param def_gateway           default gateway IP address 
 * @param mtu                   maximum transmission unit
 * @param protocol              Protocol which received this IP address
 * @param name_server_address   DNS servers IP addresses
 *
 */
typedef struct
{
	WORD32  ipaddr;
	WORD32  netmask;
    WORD32  servaddr; 
    WORD32  def_gateway;
    int     mtu;
    int     protocol;
    WORD32  name_server_address[ACE_MAX_DNS_SERVERS];
 
} aceAddrInfo; 

/**
 * This type is used for a protocol specific routine that is called by ACE to  
 * start a protocol for an interface. A pointer to this function 
 * is passed to ACE in the aceStart routine as a field of  
 * aceProtocolInfo type structure.
 *
 * @external
 * @category ACE:ace_api  
 * @since 6.0
 *
 * @param   ifname              A null terminated string identifying the 
 *                              network interface.
 *
 * @param   handle              A value passed by ACE to the protocol to identify 
 *                              an interface instance. The same handle will be
 *                              used in the call to a protocol function get_addr_fn 
 *                              made by ACE, and aceAddressEvent call made by the protocol.
 *
 * @param   proto_spec_info     A protocol specific data used to start this 
 *                              protocol.
 * @param   proto_spec_info_size    number of bytes in proto_spec_info buffer
 *
 * @return TRUE                 Protocol was successfully started. 
 * @return FALSE                Protocol could not be started due to an error.
 *                              
 */
typedef BOOLEAN (* aceProtoStartSrvRtn)(char * ifname, void * handle, const void * proto_spec_info, size_t proto_spec_info_size);

/**
 * This type is used for a protocol specific routine that is called by ACE to  
 * stop a protocol. A pointer to this function 
 * is passed to ACE in the aceStart routine as a field of the
 * aceProtocolInfo type structure.
 *
 * @external
 * @category ACE:ace_api  
 * @since 6.0
 *
 * @param   ifname              A null terminated string identifying the 
 *                              network interface.
 *
 * @return TRUE                 Protocol was successfully stopped. 
 * @return FALSE                Protocol could not be sopped due to an error.
 *                              
 */
typedef BOOLEAN (* aceProtoStopSrvRtn)(char * ifname);

/**
 * This type is used for a protocol specific routine that is called by ACE to  
 * convert IP address information from the protocol specific format
 * to aceAddrInfo type. A pointer to this function is passed to
 * ACE in the aceStart routine as a field of the aceProtocolInfo type
 * structure.
 *
 * @external
 * @category ACE:ace_api  
 * @since 6.0
 *
 * @param handle            A value passed by ACE to the protocol in the start_protocol_fn
 *                          routine to identify an interface instance. The same handle will 
 *                          be used in the aceAddressEvent call made by the protocol.
 * @param event_info        Protocol-specific IP address configuration data passed to 
 *                          ACE by the protocol in the aceAddressEvent function.
 * @param event_info_size   Size in bytes of event_info buffer.
 * @param addr_info         Pointer to IP address information structure.
 *
 * @return TRUE             Address information is valid and is returned in 
 *                          addr_info argument.
 * @return FALSE            Address information is invalid
 *                              
 */
typedef BOOLEAN (* aceProtoGetAddrSrvRtn)(void * handle, const void * event_info, size_t event_info_size, aceAddrInfo * addr_info);

/**
 * This type is used for a protocol specific routine that is called by ACE to  
 * release an aquired IP address, if aceHaveAddrCallback returned FALSE.
 * A pointer to this function is passed to ACE in the aceStart routine,
 * as a field of the aceProtocolInfo type structure. A NULL pointer 
 * might be used, if the protocol does not need to release an IP address.
 * Of all pre-defined protocols only DHCP defines this function.
 *
 * @external
 * @category ACE:ace_api  
 * @since 6.0
 *
 * @param ifname        A null terminated string identifying the 
 *                      network interface.
 *
 */
typedef void (* aceProtoReleaseAddrSrvRtn)(char * ifname);

/**
 * This type specifies whether the protocol is stopped after an IP
 * address is configured for the interface. DHCP and Auto IP 
 * must have ACE_CONT_IF_GOT_ADDRESS shutdown type, RARP and 
 * BOOTP must have ACE_ALWAYS_SHUTDOWN type, Ping ARP can be
 * configured with ACE_ALWAYS_SHUTDOWN or ACE_NEVER_SHUTDOWN
 * type. The protocols that have been stopped are restarted 
 * in the event of lost IP address.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param ACE_ALWAYS_SHUTDOWN        Shut down the protocol after an
 *                                   IP address has been configured 
 *                                   for this interface. 
 * @param ACE_CONT_IF_GOT_ADDRESS    Continue to run if an IP address
 *                                   was configured by this protocol,
 *                                   shut down if another protocol
 *                                   obtained the IP address.
 * @param ACE_NEVER_SHUTDOWN         The protocol must never shut down.   
 *
 */
typedef enum
{
	ACE_ALWAYS_SHUTDOWN		  = 0,      
	ACE_CONT_IF_GOT_ADDRESS   = 1,       
	ACE_NEVER_SHUTDOWN        = 2       

} aceProtoShutdownType;


/**
 * This type defines common information to start a protocol.
 * The delay_before_start field provides the primary method for 
 * favoring one protocol over another.  For example, if the user 
 * prefers to use DHCP over all other methods to obtain an IP 
 * address, it should be assigned a delay value of 0 (no delay.)  
 * Less preferred methods should be assigned a longer delay ensuring 
 * that they are invoked only after DHCP has been given a reasonable 
 * interval to succeed. The priority field is used only if two 
 * protocols both produce an address "simultaneously."
 * In that event, the protocol with the higher priority "wins."
 * 
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param protocol              Protocol number. Protocol numbers are defined 
 *                              in ace_params.h.
 * @param priority              Non-negative number to favor the protocol,
 *                              if several of them obtained IP addresses at 
 *                              the same time. The highest priority is 0.
 * @param delay_before_start    Number of seconds to wait before starting 
 *                              the protocol.
 * @param shutdown_type         ACE_ALWAYS_SHUTDOWN, ACE_CONT_IF_GOT_ADDRESS,
 *                              or ACE_NEVER_SHUTDOWN
 *
 */
typedef struct
{
	int          protocol;              
	unsigned int priority;				
	time_t	     delay_before_start;	

	aceProtoShutdownType	shutdown_type;		

} aceProtoStartInfo;


/**
 * An array of the following structures contains an entry for each protocol 
 * to be used by the aceStart function. The "proto_specific_info" pointer is cast 
 * by the protocol start method to address one of the protocol-specific structures,
 * described in the ace_params.h header file. 
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param proto_start_info          Generic data used to start the protocol.
 * @param proto_specific_info       Protocol-specific data used to start the 
 *                                  protocol.
 * @param proto_specific_info_size  Size in bytes of proto_specific_info buffer.
 * @param proto_event_info_size     Size in bytes of the buffer to store data 
 *                                  passed to ACE by the protocol in the
 *                                  aceAddressEvent function.
 * @param start_protocol_fn         Pointer to a function to start the protocol.
 * @param stop_protocol_fn          Pointer to a function to stop the protocol.
 * @param get_addr_fn               Pointer to a function to convert IP address 
 *                                  information from the protocol specific format
 *                                  to aceAddrInfo type. 
 * @param release_addr_fn           Pointer to a function to release an IP 
 *                                  address, might be NULL.
 * @param detect_addr_conflict      If TRUE IP address conflict detection by ACE
 *                                  is enabled for this protocol
 */
typedef struct
{
    aceProtoStartInfo           proto_start_info;
    void                        * proto_specific_info; 
    size_t                      proto_specific_info_size;
    size_t                      proto_event_info_size;
    aceProtoStartSrvRtn	        start_protocol_fn;
    aceProtoStopSrvRtn          stop_protocol_fn;
    aceProtoGetAddrSrvRtn       get_addr_fn;
    aceProtoReleaseAddrSrvRtn   release_addr_fn;
    BOOLEAN                     detect_addr_conflict;

} aceProtocolInfo;

/*
 * Used by ACE to get a configuration for IP address conflict detection for the interface
 */
int aceGetAddrConflictData(char const * ifname, NAAddrConflictConfigType * data);


/**
 * ACE calls a function of this type, registered, if an IP address conflict occurs during 
 * initial IP address configuration. 
 * 
 * @param ifname        Interface name, for example, eth0 or eth0:0
 * @param ipaddr        Conflict IP address, already in use by another network device
 * @param protocol      Protocol which received this IP address  
 * @param ip_configured TRUE - IP address is already configured on this interface. This 
 *                      can occur if some of the protocols had ACE_NEVER_SHUTDOWN type  
 *
 * @since 6.2
 * @external
 * @category ACE:ace_api
 */
typedef void (* aceAddrConflictCallbackType)(const char * ifname, WORD32 ipaddr, int protocol, BOOLEAN ip_configured); 

/* Register the ACE-level IP address conflict callback */
void aceRegisterAddrConflictCallback(aceAddrConflictCallbackType addr_cinflict_fn);


/**
 * Protocols report address events of the following types using the 
 * aceAddressEvent function. ACE then invokes have_addr_fn, have_2nd_addr_fn,
 * or lost_address_fn callback function as needed to inform the application 
 * software of the event.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param ACE_ADDR_NULL             No event.
 * @param ACE_ADDR_NEW	            New IP address event.
 * @param ACE_ADDR_RENEWED          Renewd IP address event, used by DHCP. 
 * @param ACE_ADDR_REBOUND          Rebound IP address event, used by DHCP.
 * @param ACE_ADDR_LOST             Lost IP address event.     	       
 * @param ACE_ADDR_FAILED           Protocol failed to get IP address and terminated.
 * @param ACE_ADDR_CONFLICT         Protocol had an IP address conflict and has terminated,
 *                                  this can happen for DHCP, where the if IP address 
 *                                  conflict detection is done not by ACE, but by the protocol itself
 *
 */
typedef enum
{
    ACE_ADDR_NULL           = 0,
	ACE_ADDR_NEW	        = 1,
	ACE_ADDR_RENEWED        = 2,
	ACE_ADDR_REBOUND        = 3,
	ACE_ADDR_LOST	        = 4,
    ACE_ADDR_FAILED         = 5,
    ACE_ADDR_CONFLICT       = 6


} aceAddrEventType;

/*
 * Protocols report events of getting or loosing an IP address via the 
 * aceAddressEvent function. ACE then uses the aceProtoGetAddrSrvRtn 
 * callback to convert protocol-specific IP address data to aceAddrInfo 
 * type. ACE then invokes the have_addr_fn, or have_2nd_addr_fn, or  
 * lost_address_fn callbacks as needed to inform the application software 
 * of the event. 
 *
 * If the application decides to use the IP address it must 
 * configure it for the interface directly in the have_addr_fn / 
 * have_2nd_addr_fn and this callback must return TRUE. In this case
 * ACE updates its IP address information for the interface, and shuts down
 * protocols, according to their shutdown type.
 * 
 * If have_addr_fn or have_2nd_addr_fn returns FALSE ACE discards
 * the IP address.
 * 
 * In case of lost address event, ACE will clear the IP address information
 * for the interface and call lost_address_fn callback, if this was the previously 
 * configured IP address.
 *
 */
BOOLEAN aceAddressEvent(void * handle, int protocol, aceAddrEventType addr_event, const void * event_info, size_t event_info_size);

/**
 * This type is used for the callback ACE makes to the application to 
 * inform it that an IP address has been obtained. 
 * 
 * If the application decides to use the IP address it must configure the 
 * IP address for the interface directly in the context of this callback 
 * and this callback must return TRUE. After the return ACE shuts down protocols, 
 * according to their shutdown type.
 * 
 * If the application does not want to use this IP address, this callback 
 * returns FALSE, and ACE discards this IP address.
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param ifname            A null terminated string identifying the 
 *                          network interface.
 * @param protocol          Protocol number. Protocol numbers are defined 
 *                          in ace_params.h.
 * @param addr_event        ACE_ADDR_NEW, ACE_ADDR_RENEWED, 
 *                          ACE_ADDR_REBOUND, or ACE_ADDR_LOST.
 * @param addr_info         TCP/IP configuration settings retrieved by ACE.
 * @param proto_event_info  Protocol-specific IP address data. In case
 *                          of DHCP or BOOTP it includes all data returned
 *                          by the server.
 * @param proto_event_info_size   The size of protocol-specific IP address data.
 *
 * @return TRUE             Ip address has been configured. 
 * @return FALSE            Discard this IP address.
 */
typedef BOOLEAN (* aceHaveAddrCallback)(const char * ifname, int protocol, aceAddrEventType	addr_event, aceAddrInfo * addr_info, const void * proto_event_info, size_t proto_event_info_size);

/**
 * This type is used for the callback ACE makes to the application to 
 * inform it that an IP address has been lost. 
 *
 * The application must unconfigure the IP address for the interface
 * in the context of this callback, or reboot the unit.
 *
 * After callback returns ACE restarts protocols that have been previously stopped
 * using their initial delays. Protocols that are still running continue to run. 
 *
 * @external
 * @category ACE:ace_api
 * @since 6.0
 *
 * @param ifname            A null terminated string identifying the 
 *                          network interface.
 * @param protocol          Protocol number. Protocol numbers are defined 
 *                          in ace_params.h.
 * @param addr_event        ACE_ADDR_LOST.
 *
 */
typedef void (* aceLostAddrCallback)(const char * ifname, int protocol, aceAddrEventType addr_event);


/*
 * The aceStart routine is used to activate ACE for a specific interface.
 */
int aceStart(const char * ifname, const aceProtocolInfo * proto_info, int num_protocols, aceHaveAddrCallback have_addr_fn, aceHaveAddrCallback have_2nd_addr_fn, aceLostAddrCallback lost_address_fn);

/* Add a protocol at runtime. To be used from ACE callbacks */
int aceAddProtocolAtRuntime(const char * ifname, const aceProtocolInfo * proto_info);

/*
 * The aceStop routine is used to deactivate ACE for a specific interface.
 */
int aceStop(const char * ifname);


/*
 * Initialize ACE thread
 */
int aceInitialize(void);

/*
 * customizeStartAce is called by netosStartTCP() to start ACE.  It does the following:
 *
 *      1.  Read ACE configuration data from NVRAM.
 *      2.  Call aceInitialize() to initialize data structures inside of ACE.
 *      3.  Extract the protocol specific information for each interface from the NVRAM structure.
 *      4.  Call aceStart() for each enabled interface to start the process of getting an
 *          IP address.
 */
int customizeStartAce(void);

#ifdef __cplusplus
}
#endif

#endif

