#ifndef NETTYPES_H
#define NETTYPES_H

/*
 * (sub-optimal) Platform independent encapsulation of network types and
 * addresses
 *
 * Copyright (C) 2003  Enrico Zini <enrico@debian.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 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
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <string.h>	/* memcpy, memcmp */
#include <string>
#include <net/ethernet.h>       /* needed to compile on S390
								 * (thanks to Gerhard Tonn <GerhardTonn@swol.de>)
								 */
#include <net/if_arp.h>

#include <wibble/exception.h>

extern "C" {
#include <libnet.h>
}

/* #ifdef WORD_BIGENDIAN */
/* TODO: check if byte ordering is ok here or if we need to do the ifdef and
 * byte swap a little bit */
#define IPv4_COPY(target, source) memcpy(target, source, 4)
#define IPv4_FROM_ARP(target, source) memcpy(target, source, 4)
#define IPv4_MATCHES(addr1, addr2) (memcmp((addr1), (addr2), 4) == 0)
#define MAC_COPY(target, source) memcpy(target, source, 6)
#define MAC_FROM_ARP(target, source) memcpy(target, source, 6)
#define MAC_MATCHES(addr1, addr2) (memcmp((addr1), (addr2), 6) == 0)

/* TODO: check if these four work well on big endian machines */

inline struct ether_addr* arp_get_sha(const struct libnet_arp_hdr* hdr) throw ()
{
	// Get the address of the start of variable-length data inside the packet
	char* base = (char*)&(hdr->ar_op) + sizeof(hdr->ar_op);

	return (ether_addr*)base;
}

inline struct in_addr* arp_get_sip(const struct libnet_arp_hdr* hdr) throw ()
{
	// Get the address of the start of variable-length data inside the packet
	char* base = (char*)&(hdr->ar_op) + sizeof(hdr->ar_op);

	return (struct in_addr*)(base + hdr->ar_hln);
}

inline struct ether_addr* arp_get_tha(const struct libnet_arp_hdr* hdr) throw ()
{
	// Get the address of the start of variable-length data inside the packet
	char* base = (char*)&(hdr->ar_op) + sizeof(hdr->ar_op);

	return (ether_addr*)(base + hdr->ar_hln + hdr->ar_pln);
}

inline struct in_addr* arp_get_tip(const struct libnet_arp_hdr* hdr) throw ()
{
	// Get the address of the start of variable-length data inside the packet
	char* base = (char*)&(hdr->ar_op) + sizeof(hdr->ar_op);

	return (struct in_addr*)(base + hdr->ar_hln * 2 + hdr->ar_pln);
}

class IPAddress
{
protected:
	struct in_addr addr;
	
public:
	IPAddress(const in_addr& addr) throw () : addr(addr) {}

	// Parse an IPV4 address from a dotted-quad string
	IPAddress(const std::string& str) throw (wibble::exception::Consistency);

	unsigned long int s_addr() const throw () { return addr.s_addr; }
	const in_addr_t* s_addr_p() const throw () { return &(addr.s_addr); }

	operator const struct in_addr*() const { return &addr; }
	bool operator==(const IPAddress& addr) const;
	bool operator!=(const IPAddress& addr) const;

	std::string toString() const;
};

/* Format an IPv4 address in a static char buffer */
std::string fmt(const IPAddress& addr) throw ();

/* Format a MAC address in a static char buffer */
std::string fmt(const struct ether_addr& addr) throw ();

bool parse_ipv4(struct in_addr* target, const std::string& str) throw ();

/* Parse a MAC address from its canonical string representation */
bool parse_mac(struct ether_addr* target, const std::string& str) throw ();

// vim:set ts=4 sw=4:
#endif
