mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 10:45:57 +01:00
129 lines
4.2 KiB
C++
129 lines
4.2 KiB
C++
/*
|
|
* libtins is a net packet wrapper library for crafting and
|
|
* interpreting sniffed packets.
|
|
*
|
|
* Copyright (C) 2011 Nasel
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <stdexcept>
|
|
#include <cstring>
|
|
#include <vector>
|
|
#ifndef WIN32
|
|
#include <linux/if_packet.h>
|
|
#include <net/if.h>
|
|
#endif
|
|
#include "network_interface.h"
|
|
#include "utils.h"
|
|
#include "endianness.h"
|
|
|
|
/** \cond */
|
|
struct InterfaceInfoCollector {
|
|
typedef Tins::NetworkInterface::Info info_type;
|
|
info_type *info;
|
|
int iface_id;
|
|
const char* iface_name;
|
|
bool found;
|
|
|
|
InterfaceInfoCollector(info_type *res, int id, const char* if_name)
|
|
: info(res), iface_id(id), iface_name(if_name), found(false) { }
|
|
|
|
bool operator() (struct ifaddrs *addr) {
|
|
using Tins::Endian::host_to_be;
|
|
using Tins::IPv4Address;
|
|
const struct sockaddr_ll* addr_ptr = ((struct sockaddr_ll*)addr->ifa_addr);
|
|
|
|
if(addr->ifa_addr->sa_family == AF_PACKET && addr_ptr->sll_ifindex == iface_id)
|
|
info->hw_addr = addr_ptr->sll_addr;
|
|
else if(addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
|
|
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
|
|
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
|
|
if((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)))
|
|
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_ifu.ifu_broadaddr)->sin_addr.s_addr);
|
|
else
|
|
info->bcast_addr = 0;
|
|
found = true;
|
|
}
|
|
return found;
|
|
}
|
|
};
|
|
/** \endcond */
|
|
|
|
namespace Tins {
|
|
// static
|
|
NetworkInterface NetworkInterface::default_interface() {
|
|
return NetworkInterface(0);
|
|
}
|
|
|
|
NetworkInterface::NetworkInterface() : iface_id(0) {
|
|
|
|
}
|
|
|
|
NetworkInterface::NetworkInterface(const char *name) {
|
|
iface_id = name ? resolve_index(name) : 0;
|
|
}
|
|
|
|
NetworkInterface::NetworkInterface(const std::string &name) {
|
|
iface_id = resolve_index(name.c_str());
|
|
}
|
|
|
|
NetworkInterface::NetworkInterface(IPv4Address ip) : iface_id(0) {
|
|
typedef std::vector<Utils::RouteEntry> entries_type;
|
|
|
|
if(ip == "127.0.0.1")
|
|
iface_id = resolve_index("lo");
|
|
else {
|
|
Utils::RouteEntry *best_match = 0;
|
|
entries_type entries;
|
|
uint32_t ip_int = ip;
|
|
Utils::route_entries(std::back_inserter(entries));
|
|
for(entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
|
|
if((ip_int & it->mask) == it->destination) {
|
|
if(!best_match || it->mask > best_match->mask)
|
|
iface_id = if_nametoindex(it->interface.c_str());
|
|
}
|
|
}
|
|
if(best_match)
|
|
throw std::runtime_error("Error looking up interface");
|
|
}
|
|
}
|
|
|
|
std::string NetworkInterface::name() const {
|
|
char iface_name[IF_NAMESIZE];
|
|
if(!if_indextoname(iface_id, iface_name))
|
|
throw std::runtime_error("Error fetching this interface's name");
|
|
return iface_name;
|
|
}
|
|
|
|
NetworkInterface::Info NetworkInterface::addresses() const {
|
|
const std::string &iface_name = name();
|
|
Info info;
|
|
InterfaceInfoCollector collector(&info, iface_id, iface_name.c_str());
|
|
Utils::generic_iface_loop(collector);
|
|
if(!collector.found)
|
|
throw std::runtime_error("Error looking up interface address");
|
|
return info;
|
|
}
|
|
|
|
NetworkInterface::id_type NetworkInterface::resolve_index(const char *name) {
|
|
id_type id = if_nametoindex(name);
|
|
if(!id)
|
|
throw std::runtime_error("Invalid interface error");
|
|
return id;
|
|
}
|
|
}
|
|
|