mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-28 02:20:18 +00:00
342 lines
9.4 KiB
C++
342 lines
9.4 KiB
C++
//===========================================
|
|
// PC-BSD source code
|
|
// Copyright (c) 2015, PC-BSD Software/iXsystems
|
|
// Available under the 3-clause BSD license
|
|
// See the LICENSE file for full details
|
|
//===========================================
|
|
// SysAdm source code for TrueOS
|
|
// Copyright (c) 2016-2017 TrueOS/iXsystems
|
|
// Available under the 3-clause BSD license
|
|
// See the LICENSE file for full details
|
|
//===========================================
|
|
// Note: This was almost entirely written by Tim McCormick in 2009 for
|
|
// the first PC-BSD library, and copied here by Ken Moore in 2015
|
|
//===========================================
|
|
#include "sysadm-network.h"
|
|
#include "sysadm-general.h"
|
|
|
|
#include "sysadm-global.h"
|
|
|
|
using namespace sysadm;
|
|
|
|
//====================
|
|
// STATIC LISTING FUNCTION
|
|
//====================
|
|
QStringList NetDevice::listNetDevices(){
|
|
QStringList result;
|
|
struct ifaddrs *ifap;
|
|
getifaddrs(&ifap);
|
|
char ifName[IFNAMSIZ];
|
|
//Probe the system for each device (one at a time)
|
|
while (ifap != NULL){
|
|
strncpy(ifName, ifap->ifa_name, IFNAMSIZ);
|
|
if (result.contains(ifName) == 0) result += ifName;
|
|
ifap = ifap->ifa_next;
|
|
}
|
|
//Close the structure
|
|
freeifaddrs(ifap);
|
|
return result;
|
|
}
|
|
|
|
//=====================
|
|
// CLASS FUNCTIONS
|
|
//=====================
|
|
//Get the name of the device (taking off any numbers)
|
|
QString NetDevice::devName(){
|
|
uint pos = name.indexOf(QRegExp("[0-9]+$"));
|
|
QString result = name;
|
|
result.truncate(pos);
|
|
return result;
|
|
}
|
|
|
|
//Return just the number of the device (removing the name)
|
|
uint NetDevice::devNum(){
|
|
uint pos = name.indexOf(QRegExp("[0-9]+$"));
|
|
return name.mid(pos).toInt();
|
|
}
|
|
|
|
//Fetch the IP and return it as a QString
|
|
QString NetDevice::ipAsString(){
|
|
struct ifreq ifr;
|
|
memset(&ifr, 0, sizeof(struct ifreq));
|
|
|
|
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
|
|
int s = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
|
ioctl(s, SIOCGIFADDR, &ifr);
|
|
struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
|
close(s); //close the file descriptor
|
|
return QString(inet_ntoa(in));
|
|
}
|
|
|
|
//Fetch the IPv6 and return it as a QString
|
|
QString NetDevice::ipv6AsString(){
|
|
//Get the sockaddr for the device
|
|
struct sockaddr *sadd = 0;
|
|
struct ifaddrs *addrs;
|
|
if( 0!=getifaddrs( &addrs ) ){ qDebug() << "Could not get addrs"; return ""; }
|
|
while(sadd==0 && addrs!=0){
|
|
if( QString(addrs->ifa_name)==name && addrs->ifa_addr->sa_family==AF_INET6){
|
|
//Found device (with IPv6 address)
|
|
sadd = addrs->ifa_addr;
|
|
break;
|
|
}else{
|
|
//Move to the next device
|
|
addrs = addrs->ifa_next;
|
|
}
|
|
}
|
|
// Causes crash in some cases
|
|
//free(addrs);
|
|
if(sadd==0){ qDebug() << "No socket address found"; return ""; }
|
|
//Now get the IPv6 address in string form
|
|
char straddr[INET6_ADDRSTRLEN];
|
|
int err = getnameinfo(sadd, sadd->sa_len, straddr, sizeof(straddr),NULL, 0, NI_NUMERICHOST);
|
|
if(err!=0){
|
|
qDebug() << "getnameinfo error:" << gai_strerror(err);
|
|
return "";
|
|
}else{
|
|
return QString(straddr);
|
|
}
|
|
}
|
|
|
|
|
|
//Fetch the netmask and return it as a QString
|
|
QString NetDevice::netmaskAsString(){
|
|
struct ifreq ifr;
|
|
memset(&ifr, 0, sizeof(struct ifreq));
|
|
|
|
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
|
|
int s = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
|
ioctl(s, SIOCGIFNETMASK, &ifr);
|
|
struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
|
close(s); //close the file descriptor
|
|
return QString(inet_ntoa(in));
|
|
}
|
|
|
|
//Returns the description string for the device
|
|
QString NetDevice::desc(){
|
|
QString name, num, parent;
|
|
if( isWireless() ){ parent = getWifiParent(); }
|
|
|
|
if(!parent.isEmpty()){
|
|
name = num = parent;
|
|
uint pos = name.indexOf(QRegExp("[0-9]+$"));
|
|
name.truncate(pos);
|
|
num.remove(0,pos);
|
|
}else{
|
|
name = devName();
|
|
num = QString::number(devNum());
|
|
}
|
|
return General::sysctl("dev." + name + "." + num + ".%desc");
|
|
}
|
|
|
|
//Fetch the mac address as a QString
|
|
QString NetDevice::macAsString(){
|
|
int mib[6];
|
|
size_t len;
|
|
char *buf;
|
|
struct sockaddr_dl *sdl;
|
|
char *ptr;
|
|
|
|
mib[0] = CTL_NET;
|
|
mib[1] = AF_ROUTE;
|
|
mib[2] = 0;
|
|
mib[3] = AF_LINK;
|
|
mib[4] = NET_RT_IFLIST;
|
|
mib[5] = if_nametoindex(name.toLocal8Bit());
|
|
|
|
//First find the size of the return, so we can adjust buf accordingly
|
|
sysctl(mib, 6, NULL, &len, NULL, 0);
|
|
buf = (char *) malloc(len);
|
|
sysctl(mib, 6, buf, &len, NULL, 0);
|
|
|
|
sdl = (sockaddr_dl *)(((if_msghdr *)buf)+1);
|
|
ptr = (char *) LLADDR(sdl);
|
|
|
|
QString mac;
|
|
for (uint i=0; i < 6; i++){
|
|
mac += QString::number(*(ptr+i), 16).right(2).rightJustified(2, '0');
|
|
if(i<5){ mac += ":"; }
|
|
}
|
|
return mac;
|
|
}
|
|
|
|
//Get the status of the device (active, associated, etc...)
|
|
QString NetDevice::mediaStatusAsString(){
|
|
struct ifmediareq ifm;
|
|
memset(&ifm, 0, sizeof(struct ifmediareq));
|
|
|
|
strncpy(ifm.ifm_name, name.toLocal8Bit(), IFNAMSIZ);
|
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
ioctl(s, SIOCGIFMEDIA, &ifm);
|
|
QString status;
|
|
|
|
switch (IFM_TYPE(ifm.ifm_active)){
|
|
case IFM_IEEE80211:
|
|
if (ifm.ifm_status & IFM_ACTIVE) status = "associated";
|
|
else status = "no carrier";
|
|
break;
|
|
default:
|
|
if (ifm.ifm_status & IFM_ACTIVE) status = "active";
|
|
else status = "no carrier";
|
|
}
|
|
close(s); //close the file descriptor
|
|
return status;
|
|
}
|
|
|
|
QString NetDevice::gatewayAsString(){
|
|
QString info = General::RunCommand("nice netstat -n -r").split("\n").filter(name).filter("default").join("\n");
|
|
if(info.isEmpty()){ return ""; }
|
|
//Pull the gateway out of the first line (<default> <gateway>)
|
|
info = info.replace("\t"," ").section("\n",0,0).simplified(); //ensure proper parsing
|
|
return info.section(" ",1,1);
|
|
}
|
|
|
|
//Check if a device is wireless or not
|
|
bool NetDevice::isWireless(){
|
|
struct ifmediareq ifm;
|
|
memset(&ifm, 0, sizeof(struct ifmediareq));
|
|
|
|
strncpy(ifm.ifm_name, name.toLocal8Bit(), IFNAMSIZ);
|
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
ioctl(s, SIOCGIFMEDIA, &ifm);
|
|
bool iswifi = (IFM_TYPE(ifm.ifm_active) == IFM_IEEE80211);
|
|
close(s); //close the file descriptor
|
|
return iswifi;
|
|
}
|
|
|
|
//Get the parent device (if this is a wireless wlan)
|
|
QString NetDevice::getWifiParent(){
|
|
if(!name.contains("wlan")){ return ""; }
|
|
return General::sysctl("net.wlan." + QString::number(this->devNum()) + ".%parent");
|
|
}
|
|
|
|
//See if the device is setup to use DHCP
|
|
bool NetDevice::usesDHCP(){
|
|
//The system does not keep track of how the device's address was assigned
|
|
// so the closest we can get to this is to see if the system is setup to use
|
|
// DHCP on startup (in /etc/rc.conf) (Ken Moore - 6/24/15)
|
|
return !Network::readRcConf().filter(name).filter("DHCP").isEmpty();
|
|
}
|
|
|
|
//See if the device is currently in use
|
|
bool NetDevice::isUp(){
|
|
struct ifreq ifr;
|
|
memset(&ifr, 0, sizeof(struct ifreq));
|
|
|
|
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
|
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
ioctl(s, SIOCGIFFLAGS, &ifr);
|
|
bool isup = (ifr.ifr_flags & IFF_UP);
|
|
close(s); //close the file descriptor
|
|
return isup;
|
|
}
|
|
|
|
//Determine the number of packets received by the device
|
|
long NetDevice::packetsRx(){
|
|
int mib[6];
|
|
size_t len;
|
|
char *buf;
|
|
struct if_msghdr *ifm;
|
|
|
|
mib[0] = CTL_NET;
|
|
mib[1] = AF_ROUTE;
|
|
mib[2] = 0;
|
|
mib[3] = AF_LINK;
|
|
mib[4] = NET_RT_IFLIST;
|
|
mib[5] = if_nametoindex(name.toLocal8Bit());
|
|
|
|
//First find the size of the return, so we can adjust buf accordingly
|
|
sysctl(mib, 6, NULL, &len, NULL, 0);
|
|
buf = (char *) malloc(len);
|
|
sysctl(mib, 6, buf, &len, NULL, 0);
|
|
|
|
ifm = (if_msghdr *) buf;
|
|
|
|
return ifm->ifm_data.ifi_ipackets;
|
|
}
|
|
|
|
//Determine the number of packets transmitted by the device
|
|
long NetDevice::packetsTx(){
|
|
int mib[6];
|
|
size_t len;
|
|
char *buf;
|
|
struct if_msghdr *ifm;
|
|
|
|
mib[0] = CTL_NET;
|
|
mib[1] = AF_ROUTE;
|
|
mib[2] = 0;
|
|
mib[3] = AF_LINK;
|
|
mib[4] = NET_RT_IFLIST;
|
|
mib[5] = if_nametoindex(name.toLocal8Bit());
|
|
|
|
//First find the size of the return, so we can adjust buf accordingly
|
|
sysctl(mib, 6, NULL, &len, NULL, 0);
|
|
buf = (char *) malloc(len);
|
|
sysctl(mib, 6, buf, &len, NULL, 0);
|
|
|
|
ifm = (if_msghdr *) buf;
|
|
|
|
return ifm->ifm_data.ifi_opackets;
|
|
}
|
|
|
|
//Determine the number of errors received
|
|
long NetDevice::errorsRx(){
|
|
int mib[6];
|
|
size_t len;
|
|
char *buf;
|
|
struct if_msghdr *ifm;
|
|
|
|
mib[0] = CTL_NET;
|
|
mib[1] = AF_ROUTE;
|
|
mib[2] = 0;
|
|
mib[3] = AF_LINK;
|
|
mib[4] = NET_RT_IFLIST;
|
|
mib[5] = if_nametoindex(name.toLocal8Bit());
|
|
|
|
//First find the size of the return, so we can adjust buf accordingly
|
|
sysctl(mib, 6, NULL, &len, NULL, 0);
|
|
buf = (char *) malloc(len);
|
|
sysctl(mib, 6, buf, &len, NULL, 0);
|
|
|
|
ifm = (if_msghdr *) buf;
|
|
|
|
return ifm->ifm_data.ifi_ierrors;
|
|
}
|
|
|
|
//Determine the number of errors transmitted
|
|
long NetDevice::errorsTx(){
|
|
int mib[6];
|
|
size_t len;
|
|
char *buf;
|
|
struct if_msghdr *ifm;
|
|
|
|
mib[0] = CTL_NET;
|
|
mib[1] = AF_ROUTE;
|
|
mib[2] = 0;
|
|
mib[3] = AF_LINK;
|
|
mib[4] = NET_RT_IFLIST;
|
|
mib[5] = if_nametoindex(name.toLocal8Bit());
|
|
|
|
//First find the size of the return, so we can adjust buf accordingly
|
|
sysctl(mib, 6, NULL, &len, NULL, 0);
|
|
buf = (char *) malloc(len);
|
|
sysctl(mib, 6, buf, &len, NULL, 0);
|
|
|
|
ifm = (if_msghdr *) buf;
|
|
|
|
return ifm->ifm_data.ifi_oerrors;
|
|
}
|
|
|
|
//=========================
|
|
// SETTING FUNCTIONS (requires root)
|
|
//=========================
|
|
void NetDevice::setUp(bool up){
|
|
//This only sets it up/down for the current session - does not change usage on next boot
|
|
General::RunCommand("ifconfig "+name+" "+ (up ? "up": "down") );
|
|
}
|