#ifndef IFACE_H
#define IFACE_H

/*
 * Encapsulate access to a network interface
 *
 * Copyright (C) 2003--2007  Enrico Zini <enrico@debian.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

/* 
 * Provide the class and exceptions required to access interface data
 */

#include <time.h>
#include <netinet/in.h>
#include <wibble/exception.h>

struct ifreq;

namespace wibble {
namespace exception {

/// Exception raised when an error occurs accessing an interface
class IFace : public System
{
public:
	IFace(const std::string& context) throw () : System(context) {}
	IFace(int code, const std::string& context) throw () : System(code, context) {}

	virtual const char* type() const throw () { return "IFace"; }
};

/// Exception raised when an error occurs accessing the MII functionality of an
/// interface
class MII : public IFace
{
public:
	MII(const std::string& context) throw () : IFace(context) {}
	MII(int code, const std::string& context) throw () : IFace(code, context) {}

	virtual const char* type() const throw () { return "MII"; }
};

}
}

/// Configuration data for a network interface
struct if_params
{
  short flags;
  unsigned int addr_flags;
  struct sockaddr_in addr;
  struct sockaddr_in dstaddr;
  struct sockaddr_in broadaddr;
  struct sockaddr_in netmask;
  struct sockaddr hwaddr;

  // Debugging function, not thread safe
  void print();
};

/// Access the informations on an interface
class IFace
{
protected:
	int _socket;
	struct ifreq* _ifr;
	bool _up;
	bool _run;
	bool _conn;
	bool _has_iface;
	bool _has_mii;

	void read_interface_configuration(struct if_params *ifp)
		throw (wibble::exception::IFace);

	void write_interface_configuration(const struct if_params& ifp)
		throw (wibble::exception::IFace);

	int mdio_read(int location) throw (wibble::exception::MII);

public:
	/// Create an object to access informations of the interface whose name
	/// is in `name'
	IFace(const std::string& name) throw (wibble::exception::System, wibble::exception::IFace, wibble::exception::MII);
	~IFace() throw ();

	/// Tell if the interface was up at the time of the last update()
	bool up() const throw () { return _up; }
	/// Tell if the interface was running at the time of the last update()
	bool running() const throw () { return _run; }
	/// Tell if the interface was connected at the time of the last update()
	bool connected() const throw () { return _conn; }

	/// Tell if the interface exists
	bool has_iface() const throw () { return _has_iface; }

	/// Tell if the interface MII interface is working
	bool has_mii() const throw () { return _has_mii; }

	/// Get the interface name
	std::string name() const throw ();

	/// Update the interface status
	void update() throw (wibble::exception::IFace, wibble::exception::MII);

	/// Bring the interface up in broadcast mode
	/**
	 * Returns a struct if_params descriving the previous interface configuration
	 */
	if_params initBroadcast(int timeout) throw (wibble::exception::IFace);

	/// Get the interface configuration
	/**
	 * Returns a struct if_params descriving the current interface configuration
	 */
	if_params getConfiguration() throw (wibble::exception::IFace);

	/// Set the interface configuration
	/**
	 * Returns a struct if_params descriving the previous interface configuration
	 */
	if_params setConfiguration(const if_params& config) throw (wibble::exception::IFace);
};

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