/******************************************************************************
 * file    include/sockunion.h 
 * author  YuLiang
 * version 1.0.0
 * date    09-Oct-2021
 * brief   This file provides all the headers of the sockunion functions.
 ******************************************************************************
 * Attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2021 LandPower</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of LandPower nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/

#ifndef _SOCKUNION_H_
#define _SOCKUNION_H_

/* Includes ------------------------------------------------------------------*/

/* Define --------------------------------------------------------------------*/
#define IPV4_MAX_BITLEN 32
#define IPV6_MAX_BITLEN 128

#define PNBBY 8
#define AFI_IP                    1
#define AFI_IP6                   2
#define AFI_MAX                   3

#define SU_ADDRSTRLEN 46
/* Default address family. */
#ifdef HAVE_IPV6
#define AF_INET_UNION AF_INET6
#else
#define AF_INET_UNION AF_INET
#endif

/* Exported types ------------------------------------------------------------*/
/* IPv4 and IPv6 unified prefix structure. */
typedef struct _prefix
{
    uint8_t family;
    uint8_t prefixlen;
    union 
    {
        uint8_t prefix;
        struct in_addr prefix4;
#ifdef HAVE_IPV6
        struct in6_addr prefix6;
#endif /* HAVE_IPV6 */
        struct 
        {
            struct in_addr id;
            struct in_addr adv_router;
        } lp;
        uint8_t val[8];
    } u __attribute__ ((aligned (8)));
} prefix_t;

/* IPv4 prefix structure. */
typedef struct _prefix_ipv4
{
    uint8_t family;
    uint8_t prefixlen;
    struct in_addr prefix __attribute__ ((aligned (8)));
} prefix_ipv4_t;

/* IPv6 prefix structure. */
#ifdef HAVE_IPV6
typedef struct _prefix_ipv6
{
    uint8_t family;
    uint8_t prefixlen;
    struct in6_addr prefix __attribute__ ((aligned (8)));
} prefix_ipv6_t;
#endif /* HAVE_IPV6 */

typedef enum
{
    ACCESS_TYPE_STRING,
    ACCESS_TYPE_NUMBER
} ACCESS_TYPE_E;

/* Filter type is made by `permit', `deny' and `dynamic'. */
typedef enum
{
    FILTER_DENY,
    FILTER_PERMIT,
    FILTER_DYNAMIC
} FILTER_TYPE_E;

/* List of access_list. */
typedef struct
{
    struct _access_list *head;
    struct _access_list *tail;
} access_list_list_t;

/* Master structure of access_list. */
typedef struct
{
    /* List of access_list which name is number. */
    access_list_list_t num;

    /* List of access_list which name is string. */
    access_list_list_t str;

    /* Hook function which is executed when new access_list is added. */
    void (*add_hook)(struct _access_list *);

    /* Hook function which is executed when access_list is deleted. */
    void (*delete_hook)(struct _access_list *);
} access_master_t;

typedef struct
{
    /* Cisco access-list */
    int extended;
    struct in_addr addr;
    struct in_addr addr_mask;
    struct in_addr mask;
    struct in_addr mask_mask;
} filter_cisco_t;

typedef struct
{
    /* If this filter is "exact" match then this flag is set. */
    int exact;

    /* Prefix information. */
    prefix_t prefix;
} filter_zebra_t;

/* Filter element of access list */
typedef struct _filter
{
    /* For doubly linked list. */
    struct _filter *next;
    struct _filter *prev;

    /* Filter type information. */
    FILTER_TYPE_E type;

    /* Cisco access-list */
    int cisco;

    union
    {
        filter_cisco_t cfilter;
        filter_zebra_t zfilter;
    } u;
} filter_t;

/* Access list */
typedef struct _access_list
{
  char *name;
  char *remark;

  access_master_t *master;

  ACCESS_TYPE_E type;

  struct _access_list *next;
  struct _access_list *prev;

  filter_t *head;
  filter_t *tail;
} access_list_t;

typedef union 
{
    struct sockaddr sa;
    struct sockaddr_in sin;
#ifdef HAVE_IPV6
    struct sockaddr_in6 sin6;
#endif /* HAVE_IPV6 */
} SOCKUNION_U;

/* Exported macro ------------------------------------------------------------*/

/* Extern global variables ---------------------------------------------------*/

/* Extern functions ----------------------------------------------------------*/
extern void prefix_free(prefix_t *p);
extern prefix_ipv4_t *prefix_ipv4_new(void);
#ifdef HAVE_IPV6
extern prefix_ipv6_t *prefix_ipv6_new(void);
#endif /* HAVE_IPV6 */

extern access_list_t *access_list_lookup(uint16_t afi, const char *name);
extern FILTER_TYPE_E access_list_apply(access_list_t *access, void *object);
extern void masklen2ip(int masklen, struct in_addr *netmask);
extern int prefix_match(const prefix_t *n, const prefix_t *p);

extern int str2sockunion(const char *str, SOCKUNION_U *su);
extern const char *sockunion2str(SOCKUNION_U *su, char *buf, size_t len);
extern int sockunion_accept(int sock, SOCKUNION_U *su);
extern int set_nonblocking(int fd);
extern prefix_t *sockunion2hostprefix(const SOCKUNION_U *su);
extern char *sockunion_su2str(SOCKUNION_U *su);
extern int sockunion_stream_socket(SOCKUNION_U *su);
extern int sockunion_reuseaddr(int sock);
extern int sockunion_bind(int sock, SOCKUNION_U *su, unsigned short port, SOCKUNION_U *su_addr);
extern int sockunion_ip_set(char *name, unsigned int addr);
extern int sockunion_mask_set(char *name, unsigned int mask);
extern int sockunion_gw_set(char *name, unsigned int gateway, unsigned int gateway_old);

#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/
