PPI: Add missing TargetDgramWriter doku
[senf.git] / Socket / NetdeviceController.cc
index 6cc7d6b..b514904 100644 (file)
@@ -1,9 +1,9 @@
-// $Id: BufferingPolicy.cc 533 2007-11-23 17:34:30Z g0dil $
+// $Id$
 //
 // Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-//     Thorsten Horstmann <thorsten.horstmann@fokus.fraunhofer.de>
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Thorsten Horstmann <tho@berlios.de>
 //
 // 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
@@ -21,7 +21,7 @@
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief BufferingPolicy non-inline non-template implementation
+    \brief NetdeviceController non-inline non-template implementation
  */
 
 #include "NetdeviceController.hh"
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
-#include <netinet/ether.h>
 #include "../Utils/Exception.hh"
 
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ senf::NetdeviceController::NetdeviceController(std::string const interface_name)
+prefix_ senf::NetdeviceController::NetdeviceController(std::string const & interface_name)
 {
-    sockfd_ = ::socket(PF_PACKET, SOCK_DGRAM, 0);
-    if (sockfd_ < 0)
-        throwErrno();
-    interfacename_ = interface_name;
+    openSocket();
+    struct ifreq ifr;
+    ::memset( &ifr, 0, sizeof(ifr));
+    interface_name.copy( ifr.ifr_name, IFNAMSIZ);
+    doIoctl( ifr, SIOCGIFINDEX);
+    ifindex_ = ifr.ifr_ifindex;
+}
+
+prefix_ senf::NetdeviceController::NetdeviceController(int interface_index)
+{
+    openSocket();
+    ifindex_ = interface_index;
+}
+
+prefix_ std::string senf::NetdeviceController::interfaceName()
+    const
+{
+    struct ifreq ifr;
+    ifrName( ifr);
+    return std::string( ifr.ifr_name);
+}
+
+prefix_ void senf::NetdeviceController::interfaceName(const std::string & newname)
+{
+    if (sizeof(newname) <= IFNAMSIZ) {
+        struct ifreq ifr;
+        ifrName(ifr);
+        strncpy(ifr. ifr_newname, newname.c_str(), IFNAMSIZ);
+        try {
+            doIoctl(ifr, SIOCSIFNAME);
+        } catch (senf::SystemException e) {
+            e << "Could not change the interface name. Is the interface really down?";
+            throw ;
+        }
+    }
+    return;
 }
 
 prefix_ senf::MACAddress senf::NetdeviceController::hardwareAddress()
+    const
 {
     struct ifreq ifr;
-    ::memset( &ifr, 0, sizeof(ifr));
-    interfacename_.copy( ifr.ifr_name, IFNAMSIZ);
-    if ( ::ioctl( sockfd_, SIOCGIFHWADDR , &ifr ) < 0 )
-        throwErrno();
-    return senf::MACAddress::from_string( 
-            ether_ntoa( (struct ether_addr*) ifr.ifr_hwaddr.sa_data ) );
+    ifrName( ifr);
+    doIoctl( ifr, SIOCGIFHWADDR);
+    return senf::MACAddress::from_data( ifr.ifr_hwaddr.sa_data);
+}
+
+prefix_ void senf::NetdeviceController::hardwareAddress(const MACAddress &newAddress) {
+    struct ifreq ifr;
+    ifrName( ifr);
+    ifr.ifr_hwaddr.sa_family = 1; // TODO: lookup named constant; PF_LOCAL ???
+    std::copy(newAddress.begin(), newAddress.end(), ifr.ifr_hwaddr.sa_data);
+    try {
+        doIoctl(ifr, SIOCSIFHWADDR);
+    } catch (senf::SystemException e) {
+        e << "Could not change the interface MAC address. Is the interface really down?";
+        throw ;
+    }
+}
+
+prefix_ int senf::NetdeviceController::mtu()
+    const
+{
+    struct ifreq ifr;
+    ifrName( ifr);
+    doIoctl( ifr, SIOCGIFMTU);
+    return ifr.ifr_mtu;
+}
+
+prefix_ void senf::NetdeviceController::mtu(int new_mtu)
+{
+    struct ifreq ifr;
+    ifrName( ifr);
+    ifr.ifr_mtu = new_mtu;
+    doIoctl( ifr, SIOCSIFMTU);
+}
+
+prefix_ bool senf::NetdeviceController::promisc()
+    const
+{
+    struct ifreq ifr;
+    ifrName( ifr);
+    doIoctl( ifr, SIOCGIFFLAGS);
+    return ifr.ifr_flags & IFF_PROMISC;
+}
+
+prefix_ void senf::NetdeviceController::promisc(bool mode)
+{
+    struct ifreq ifr;
+    ifrName( ifr);
+    doIoctl( ifr, SIOCGIFFLAGS);
+    if (mode)
+        ifr.ifr_flags |= IFF_PROMISC;
+    else
+        ifr.ifr_flags &= ~IFF_PROMISC;
+    doIoctl( ifr, SIOCSIFFLAGS);
+}
+
+prefix_ bool senf::NetdeviceController::isUp()
+    const
+{
+    struct ifreq ifr;
+    ifrName(ifr);
+    doIoctl(ifr, SIOCGIFFLAGS);
+    return ifr.ifr_flags & IFF_UP;
+}
+
+prefix_ void senf::NetdeviceController::up()
+{
+    struct ifreq ifr;
+    ifrName(ifr);
+    doIoctl(ifr, SIOCGIFFLAGS);
+    ifr.ifr_flags |= IFF_UP;
+    doIoctl(ifr, SIOCSIFFLAGS);
+}
+
+prefix_ void senf::NetdeviceController::down()
+{
+    struct ifreq ifr;
+    ifrName(ifr);
+    doIoctl(ifr, SIOCGIFFLAGS);
+    ifr.ifr_flags &= ~IFF_UP;
+    doIoctl(ifr, SIOCSIFFLAGS);
+}
+
+prefix_ int senf::NetdeviceController::interfaceIndex()
+    const
+{
+    return ifindex_;
 }
 
 prefix_ senf::NetdeviceController::~NetdeviceController()
 {
-    close( sockfd_ );
+    close( sockfd_);
+}
+
+prefix_ void senf::NetdeviceController::openSocket()
+{
+    sockfd_ = ::socket( PF_INET, SOCK_DGRAM, 0);
+    if ( sockfd_ < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("Could not open socket for NetdeviceController.");
 }
 
+prefix_ void senf::NetdeviceController::ifrName(ifreq& ifr)
+    const
+{
+    ::memset( &ifr, 0, sizeof(ifr));
+    ifr.ifr_ifindex = ifindex_;
+    if ( ::ioctl( sockfd_, SIOCGIFNAME, &ifr ) < 0 )
+        SENF_THROW_SYSTEM_EXCEPTION("NetdeviceController")
+        << " could not discover the name of the interface with index " << ifindex_ << ".";
+}
 
+prefix_ void senf::NetdeviceController::doIoctl(ifreq& ifr, int request)
+    const
+{
+    if ( ::ioctl( sockfd_, request, &ifr ) < 0 )
+        SENF_THROW_SYSTEM_EXCEPTION("NetdeviceController::doIoctl failed.");
+}
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "NetdeviceController.mpp"
 
-\f
+
 // Local Variables:
 // mode: c++
 // fill-column: 100