/*
 *  This file provides functions for IP Version 4 based checks and conversions.
 *  Author: Samuel Abels <spam debain org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef HAVE_LIB_IPV4_H
#define HAVE_LIB_IPV4_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "lib_regexp.h"


#define ERR_INVALID_FORMAT     -1
#define ERR_OUT_OF_RANGE       -2
#define ERR_INVALID_PREFIXLEN  -3

typedef struct Prefix_S {
  unsigned long      net;
  unsigned short int len;
} Prefix;


/* Checks the syntax of an human readable (byte notated) IP address for
 * validity.
 * Returns: 0 on success, <0 otherwise:
 *          INVALID_FORMAT if the IP format is incorrect.
 *          OUT_OF_RANGE   if at least one of the IP's integer values is
 *                         out-of-range.
 */
short int ipv4_check_ip(const char* ip);

/* Checks the an IP prefixlength for validity.
 * Returns: 0 on success, <0 otherwise:
 *          INVALID_PREFIXLEN if the prefixlength is invalid.
 */
short int ipv4_check_prefixlen(unsigned short int pfxlen);

/* Checks the syntax of an human readable (x.x.x.x/pfxlen) IP prefix for
 * validity.
 * Returns: 0 on success, <0 otherwise:
 *          INVALID_FORMAT    if the IP format is incorrect.
 *          OUT_OF_RANGE      if at least one of the IP's integer values is
 *                            out-of-range.
 *          INVALID_PREFIXLEN if the prefixlength value is out of range.
 */
short int ipv4_check_prefix(const char* prefix);

/* Convert a human readable (byte notated) ip address to a 4-byte integer value.
 * Returns: 0 on success, <0 otherwise:
 *          INVALID_FORMAT if the IP format is incorrect.
 *          OUT_OF_RANGE   if at least one of the IP's integer values is
 *                         out-of-range.
 */
short int ipv4_ip2integer(const char* ip, unsigned long* ip_int);

/* Converts a 4 byte integer value into a human readable (byte notated) ip
 * address. Returns 0.
 */
short int ipv4_integer2ip(unsigned long ip_int, char* ip);

/* Converts a 4 byte integer value into a human readable (byte notated) binary
 * ip address.
 */
short int ipv4_integer2bin(unsigned long ip_int, char* ip_bin);

/* Converts a 4 byte integer value into a hexadezimal value.
 */
short int ipv4_integer2hex(unsigned long ip_int, char* ip_hex);

/* Convert a prefixlength to an IP mask.
 * Returns: 0 on success, <0 otherwise:
 *          INVALID_PREFIXLEN if the prefixlength is invalid.
 */
short int ipv4_pfxlen2mask(unsigned short int pfxlen, unsigned long *mask);

/* Convert an IP mask address to a prefixlength.
 * Returns 0.
 */
short int ipv4_mask2pfxlen(unsigned long mask, unsigned short int* pfxlen);

/* Given an IP address and a netmask, this function stores the broadcast
 * address in "broadcast". Returns 0.
 */
short int ipv4_get_broadcast(unsigned long ip,
                             unsigned long mask,
                             unsigned long* broadcast);

/* Given a prefix length, this function stores the number of
 * host addresses in "num", EXCLUDING network/broadcast. Returns 0.
 */
short int ipv4_get_num_hosts(unsigned short int pfxlen, unsigned int* num);

/* Given a prefix length, this function stores the number of
 * host addresses in "num" INCLUDING network/broadcast. Returns 0.
 */
short int ipv4_get_num_hosts_all(unsigned short int pfxlen, unsigned int* num);

/* Given a prefix length, this function stores the number of
 * subnet addresses in "num". Returns 0.
 */
short int ipv4_get_num_subnets(unsigned short int pfxlen, unsigned int* num);

/* Checks whether "prefix_txt" meets all of the given criterias (arguments).
 * Returns: TRUE if match, FALSE if no match, <0 on an error.
 */
short int ipv4_prefix_match(unsigned long net_txt,
                            unsigned long mask_txt,
                            unsigned short int le,
                            unsigned short int ge,
                            unsigned long prefix_txt);

/* Given an address range, this function returns a list of prefixes covering
 * all its addresses, and /only/ the range addresses.
 * Returns: 0.
 */
short int ipv4_get_prefixes_from_range(unsigned long from,
                                       unsigned long to,
                                       Prefix **prefixlist);

/* Same as ipv4_get_prefixes_from_range, but uses fixed length subnetting.
 * Returns: 0.
 */
short int ipv4_get_prefixes_from_range_flsm(unsigned long from,
                                            unsigned long to,
                                            unsigned short int pfxlen,
                                            Prefix **prefixlist,
                                            unsigned int maxmatch);

/* Frees the content of a prefixlist previously returned by
 * ipv4_get_prefixes_from_range().
 */
void ipv4_free_prefixlist(Prefix **prefixlist);

#endif
