mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 02:20:17 +00:00
Merge branch 'master' of https://github.com/pcbsd/sysadm
This commit is contained in:
19
src/binary/binary.pro
Normal file
19
src/binary/binary.pro
Normal file
@@ -0,0 +1,19 @@
|
||||
TEMPLATE = app
|
||||
LANGUAGE = C++
|
||||
|
||||
CONFIG += qt warn_on release
|
||||
QT = core
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
LIBS = -L../library -L/usr/lib -L/usr/local/lib -lsysadm
|
||||
INCLUDEPATH += ../library /usr/include /usr/local/include
|
||||
|
||||
TARGET=sysadm
|
||||
target.path=/usr/local/bin
|
||||
|
||||
|
||||
INSTALLS += target
|
||||
|
||||
|
||||
QMAKE_LIBDIR = /usr/local/lib/qt5 /usr/local/lib
|
||||
33
src/binary/main.cpp
Normal file
33
src/binary/main.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
#include <sysadm-network.h>
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
//Run a simple test of all the sysadm backend functions
|
||||
QStringList devs = sysadm::NetDevice::listNetDevices();
|
||||
qDebug() <<"Devices:" << devs;
|
||||
for(int i=0; i<devs.length(); i++){
|
||||
sysadm::NetDevice D(devs[i]);
|
||||
qDebug() << "Check Device:" << D.device();
|
||||
qDebug() << " - name:" << D.devName();
|
||||
qDebug() << " - number:" << D.devNum();
|
||||
qDebug() << " - IPv4:" << D.ipAsString();
|
||||
qDebug() << " - IPv6:" << D.ipv6AsString();
|
||||
qDebug() << " - netmask:" << D.netmaskAsString();
|
||||
qDebug() << " - description:" << D.desc();
|
||||
qDebug() << " - MAC:" << D.macAsString();
|
||||
//qDebug() << " - Media Type:" << D.mediaTypeAsString();
|
||||
qDebug() << " - Media Status:" << D.mediaStatusAsString();
|
||||
bool iswifi = D.isWireless();
|
||||
qDebug() << " - Is Wireless:" << iswifi;
|
||||
if(iswifi){
|
||||
qDebug() << " -- Wifi Parent:" << D.getWifiParent();
|
||||
}
|
||||
qDebug() << " - Is Active:" << D.isUp();
|
||||
qDebug() << " - Packets Rx:" << D.packetsRx() << "Errors:" << D.errorsRx();
|
||||
qDebug() << " - Packets Tx:" << D.packetsTx() << "Errors:" << D.errorsTx();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
311
src/library/NetDevice.cpp
Normal file
311
src/library/NetDevice.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
// 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
|
||||
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;
|
||||
|
||||
return QString(inet_ntoa(in));
|
||||
}
|
||||
|
||||
//Fetch the IPv6 and return it as a QString
|
||||
QString NetDevice::ipv6AsString(){
|
||||
//Note: New on 6/24/15 - still needs testing
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
|
||||
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
|
||||
int s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
|
||||
ioctl(s, SIOCGIFADDR, &ifr);
|
||||
struct in6_addr in = ((sockaddr_in6 *) &ifr.ifr_addr)->sin6_addr;
|
||||
char straddr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &in, straddr, sizeof(straddr));
|
||||
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;
|
||||
|
||||
return QString(inet_ntoa(in));
|
||||
}
|
||||
|
||||
//Returns the description string for the device
|
||||
QString NetDevice::desc(){
|
||||
return General::sysctl("dev." + devName() + "." + QString::number(devNum()) + ".%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_FDDI:
|
||||
case IFM_TOKEN:
|
||||
if (ifm.ifm_status & IFM_ACTIVE) status = "inserted";
|
||||
else status = "no ring";
|
||||
break;
|
||||
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";
|
||||
}
|
||||
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);
|
||||
|
||||
return IFM_TYPE(ifm.ifm_active) == IFM_IEEE80211;
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
return (ifr.ifr_flags & IFF_UP) ? 1 : 0;
|
||||
}
|
||||
|
||||
//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") );
|
||||
}
|
||||
27
src/library/library.pro
Normal file
27
src/library/library.pro
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
QT += core network
|
||||
|
||||
TARGET=sysadm
|
||||
target.path = /usr/local/lib
|
||||
|
||||
DESTDIR= $$_PRO_FILE_PWD_
|
||||
|
||||
TEMPLATE = lib
|
||||
LANGUAGE = C++
|
||||
VERSION = 1.0.0
|
||||
|
||||
HEADERS += sysadm-global.h \
|
||||
sysadm-general.h \
|
||||
sysadm-network.h
|
||||
|
||||
|
||||
SOURCES += sysadm-general.cpp \
|
||||
sysadm-network.cpp \
|
||||
NetDevice.cpp
|
||||
|
||||
include.path=/usr/local/include/
|
||||
include.files=sysadm-*.h
|
||||
|
||||
INSTALLS += target include
|
||||
|
||||
QMAKE_LIBDIR = /usr/local/lib/qt5 /usr/local/lib
|
||||
119
src/library/sysadm-general.cpp
Normal file
119
src/library/sysadm-general.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
#include "sysadm-general.h"
|
||||
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
|
||||
|
||||
#include "sysadm-global.h"
|
||||
|
||||
using namespace sysadm;
|
||||
//=================
|
||||
// RunCommand() variations
|
||||
//=================
|
||||
//Note: environment changes should be listed as such: <variable>=<value>
|
||||
|
||||
//Return CLI output (and success/failure)
|
||||
QString General::RunCommand(bool &success, QString command, QStringList arguments, QString workdir, QStringList env){
|
||||
QProcess proc;
|
||||
proc.setProcessChannelMode(QProcess::MergedChannels); //need output
|
||||
//First setup the process environment as necessary
|
||||
QProcessEnvironment PE = QProcessEnvironment::systemEnvironment();
|
||||
if(!env.isEmpty()){
|
||||
for(int i=0; i<env.length(); i++){
|
||||
if(!env[i].contains("=")){ continue; }
|
||||
PE.insert(env[i].section("=",0,0), env[i].section("=",1,100));
|
||||
}
|
||||
}
|
||||
proc.setProcessEnvironment(PE);
|
||||
//if a working directory is specified, check it and use it
|
||||
if(!workdir.isEmpty()){
|
||||
proc.setWorkingDirectory(workdir);
|
||||
}
|
||||
//Now run the command (with any optional arguments)
|
||||
if(arguments.isEmpty()){ proc.start(command); }
|
||||
else{ proc.start(command, arguments); }
|
||||
//Wait for the process to finish (but don't block the event loop)
|
||||
while( !proc.waitForFinished(500) ){ QCoreApplication::processEvents(); }
|
||||
success = (proc.exitCode()==0); //return success/failure
|
||||
return QString(proc.readAllStandardOutput());
|
||||
}
|
||||
|
||||
QString General::RunCommand(QString command, QStringList arguments, QString workdir, QStringList env){
|
||||
//Overloaded simplification for text-only output
|
||||
bool junk = false;
|
||||
return General::RunCommand(junk,command,arguments,workdir,env);
|
||||
}
|
||||
|
||||
bool General::RunQuickCommand(QString command, QStringList arguments,QString workdir, QStringList env){
|
||||
//Overloaded simplification for success-only output
|
||||
bool success = false;
|
||||
General::RunCommand(success, command, arguments, workdir, env);
|
||||
return success;
|
||||
}
|
||||
|
||||
//=================
|
||||
// TEXT FILE INTERACTION
|
||||
//=================
|
||||
QStringList General::readTextFile(QString filepath){
|
||||
QStringList out;
|
||||
QFile file(filepath);
|
||||
if(file.open(QIODevice::Text | QIODevice::ReadOnly)){
|
||||
QTextStream in(&file);
|
||||
while(!in.atEnd()){
|
||||
out << in.readLine();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool General::writeTextFile(QString filepath, QStringList contents, bool overwrite){
|
||||
//Simplification for user directory
|
||||
if(filepath.startsWith("~")){ filepath = filepath.replace(0,1,QDir::homePath()); }
|
||||
QFile file(filepath);
|
||||
//Check existance/validity
|
||||
if(file.exists() && !overwrite){ return false; }
|
||||
if(!file.exists()){
|
||||
//See if we need to create the parent directory as well
|
||||
QDir dir = QFileInfo(filepath).dir(); //get the parent directory
|
||||
if(!dir.exists()){
|
||||
if(!dir.mkpath(dir.absolutePath())){ return false; } //could not create parent directory
|
||||
}
|
||||
}
|
||||
//Make sure that something is there to be written
|
||||
// - to delete a file, use QFile::remove() instead of this function
|
||||
if(contents.isEmpty()){ contents << "\n"; }
|
||||
else if(contents.last().isEmpty()){ contents << "\n"; }
|
||||
//Now save the contents to the file
|
||||
bool ok = false;
|
||||
if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
|
||||
QTextStream out(&file);
|
||||
out << contents.join("\n");
|
||||
file.close();
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//===========================
|
||||
// SYSCTL ACCESS (might require root)
|
||||
//===========================
|
||||
//Retrieve a text-based sysctl
|
||||
QString General::sysctl(QString var){
|
||||
char result[1000];
|
||||
size_t len = sizeof(result);
|
||||
sysctlbyname(var.toLocal8Bit(), result, &len, NULL, 0);
|
||||
result[len] = '\0';
|
||||
return QString(result);
|
||||
}
|
||||
|
||||
//Retrieve a number-based sysctl
|
||||
long long General::sysctlAsInt(QString var){
|
||||
long long result = 0;
|
||||
size_t len = sizeof(result);
|
||||
sysctlbyname(var.toLocal8Bit(), &result, &len, NULL, 0);
|
||||
return result;
|
||||
}
|
||||
37
src/library/sysadm-general.h
Normal file
37
src/library/sysadm-general.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
#ifndef __PCBSD_LIB_UTILS_GENERAL_H
|
||||
#define __PCBSD_LIB_UTILS_GENERAL_H
|
||||
|
||||
#include "sysadm-global.h"
|
||||
|
||||
namespace sysadm{
|
||||
|
||||
class General{
|
||||
public:
|
||||
//Non-event-blocking versions of QProcess::execute() or system()
|
||||
//Note: environment changes should be listed as such: [<variable>=<value>]
|
||||
// - Both success/log of output
|
||||
static QString RunCommand(bool &success, QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() );
|
||||
// - Log output only
|
||||
static QString RunCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() );
|
||||
// - success output only
|
||||
static bool RunQuickCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() );
|
||||
|
||||
//File Access Functions
|
||||
static QStringList readTextFile(QString filename);
|
||||
static bool writeTextFile(QString filename, QStringList contents, bool overwrite = true);
|
||||
|
||||
//Retrieve a text-based sysctl
|
||||
static QString sysctl(QString var);
|
||||
//Retrieve a number-based sysctl
|
||||
static long long sysctlAsInt(QString var);
|
||||
};
|
||||
|
||||
} //end of pcbsd namespace
|
||||
|
||||
#endif
|
||||
36
src/library/sysadm-global.h
Normal file
36
src/library/sysadm-global.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
#ifndef __PCBSD_LIB_UTILS_GENERAL_INCLUDES_H
|
||||
#define __PCBSD_LIB_UTILS_GENERAL_INCLUDES_H
|
||||
|
||||
//Qt Includes
|
||||
#include <QProcess>
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDateTime>
|
||||
|
||||
//FreeBSD Includes
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h> //from "man getnetent" (network entries)
|
||||
|
||||
#endif
|
||||
125
src/library/sysadm-network.cpp
Normal file
125
src/library/sysadm-network.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
#include "sysadm-network.h"
|
||||
//PLEASE: Keep the functions in the same order as listed in pcbsd-network.h
|
||||
#include "sysadm-general.h"
|
||||
|
||||
using namespace sysadm;
|
||||
//=====================
|
||||
// NETWORK FUNCTIONS
|
||||
//=====================
|
||||
QList<NetworkEntry> Network::listNetworkEntries(){
|
||||
QList<NetworkEntry> out;
|
||||
netent *entry = getnetent();
|
||||
while(entry!=0){
|
||||
//Copy over this data into the output structure
|
||||
NetworkEntry tmp;
|
||||
tmp.name = QString::fromLocal8Bit(entry->n_name);
|
||||
for(int i=0; entry->n_aliases[i] != 0; i++){
|
||||
tmp.aliases << QString::fromLocal8Bit(entry->n_aliases[i]);
|
||||
}
|
||||
tmp.netnum = entry->n_net;
|
||||
out << tmp;
|
||||
//Now load the next entry
|
||||
entry = getnetent();
|
||||
}
|
||||
endnetent(); //make sure to close the file since we are finished reading it
|
||||
return out;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
QStringList Network::readRcConf(){
|
||||
static QStringList contents = QStringList();
|
||||
static QDateTime lastread;
|
||||
if(!lastread.isValid() || contents.isEmpty() || (QFileInfo("/etc/rc.conf").lastModified()> lastread) ){
|
||||
lastread = QDateTime::currentDateTime();
|
||||
contents = General::readTextFile("/etc/rc.conf");
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
NetDevSettings Network::deviceRCSettings(QString dev){
|
||||
QStringList info = Network::readRcConf().filter(dev);
|
||||
NetDevSettings set;
|
||||
if(info.isEmpty()){ return set; } //no settings
|
||||
set.device = dev;
|
||||
set.wifihost = false;
|
||||
for(int i=0; i<info.length(); i++){
|
||||
QString var = info[i].section("=",0,0).simplified();
|
||||
QString val = info[i].section("=",1,100).simplified();
|
||||
if(val.startsWith("\"")){ val = val.remove(1); }
|
||||
if(val.endsWith("\"")){ val.chop(1); }
|
||||
val.prepend(" "); //just to make additional parsing easier later - each "variable" should have whitespace on both sides
|
||||
if(var==("ifconfig_"+dev)){
|
||||
QStringList vals = val.split(" ",QString::SkipEmptyParts);
|
||||
//HOSTAP set.wifihost = true;
|
||||
|
||||
//This is the main settings line: lots of things to look for:
|
||||
if(!val.contains("DHCP")){
|
||||
//Look for the static networking values
|
||||
if(val.contains(" netmask ")){ set.staticNetmask = val.section(" netmask ",1,1).section(" ",0,0); }
|
||||
if(val.contains(" gateway ")){ set.staticGateway = val.section(" gateway ",1,1).section(" ",0,0); }
|
||||
if(val.contains(" inet ")){ set.staticIPv4 = val.section(" inet ",1,1).section(" ",0,0); }
|
||||
if(val.contains(" inet6 ")){ set.staticIPv6 = val.section(" inet6 ",1,1).section(" ",0,0); }
|
||||
if(set.staticIPv4.isEmpty() || set.staticIPv6.isEmpty()){
|
||||
//IPv4/6 address can sometimes not have the "inet(6)" identifier - look through the first few values to as well
|
||||
QStringList vals = val.split(" ",QString::SkipEmptyParts);
|
||||
|
||||
for(int v=0; v<vals.length(); v++){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
NetDevSettings Network::deviceIfconfigSettings(QString dev){
|
||||
QString info = General::RunCommand("ifconfig "+dev);
|
||||
NetDevSettings set;
|
||||
if(info.isEmpty() || info.contains("interface "+dev+"does not exist")){ return set; } //empty stucture
|
||||
//Now parse all the available info from ifconfig
|
||||
info = info.replace("\t"," ").replace("\n"," ").simplified(); //ensure that whitespace is used for parsing
|
||||
//if(info.contains("inet ")){ set.staticIPv4 = info.section("inet ",1,1).section(" ",0,0); }
|
||||
//if(info.contains("inet6 ")){ set.staticIPv6 = info.section("inet6 ",1,1).section("%",0,0); }
|
||||
set.device = dev;
|
||||
if(info.contains(" ether ")){ set.etherMac = info.section(" ether ",1,1).section(" ",0,0); }
|
||||
if(info.contains(" ssid ")){ set.wifiSSID = info.section(" ssid ",1,1).section(" ",0,0); }
|
||||
if(info.contains(" bssid ")){ set.wifiBSSID = info.section(" bssid ",1,1).section(" ",0,0); }
|
||||
if(info.contains(" country ")){ set.wifiCountry = info.section(" country ",1,1).section(" ",0,0); }
|
||||
if(info.contains(" channel ")){ set.staticIPv4 = info.section(" channel ",1,1).section(" ",0,0); }
|
||||
return set;
|
||||
}
|
||||
|
||||
//=====================
|
||||
// NETWORK-ROOT FUNCTIONS
|
||||
//=====================
|
||||
bool NetworkRoot::saveNetworkEntry(NetworkEntry data){
|
||||
netent *entry = getnetbyname(data.name.toLocal8Bit());
|
||||
if(entry==0){
|
||||
//This entry does not exist yet - need to add it
|
||||
return false; //not implemented yet - add it to /etc/networks?
|
||||
}else{
|
||||
//This entry already exists, update it
|
||||
endnetent(); //Make sure to close the file when finished
|
||||
return false; //not implemented yet
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
bool NetworkRoot::saveRCSettings(NetDevSettings){
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
bool NetworkRoot::setIfconfigSettings(NetDevSettings){
|
||||
return false;
|
||||
}
|
||||
97
src/library/sysadm-network.h
Normal file
97
src/library/sysadm-network.h
Normal file
@@ -0,0 +1,97 @@
|
||||
//===========================================
|
||||
// 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
|
||||
//===========================================
|
||||
#ifndef __PCBSD_LIB_UTILS_NETWORK_H
|
||||
#define __PCBSD_LIB_UTILS_NETWORK_H
|
||||
|
||||
#include "sysadm-global.h"
|
||||
|
||||
namespace sysadm{
|
||||
|
||||
//General purpose enumeration of network encryption types
|
||||
enum NetCrypt {UNKNOWN, NONE, WEP, WPA1, WPA2, WPAE};
|
||||
|
||||
//Data structure for network entries ("/etc/networks" entries for example)
|
||||
struct NetworkEntry{
|
||||
QString name;
|
||||
QStringList aliases;
|
||||
unsigned int netnum;
|
||||
};
|
||||
|
||||
struct NetDevSettings{
|
||||
QString device; //the device these settings correspond with (usually unset if there was an error)
|
||||
QString asDevice; //associated device (Example: wifi device -> wlan<num> device)
|
||||
//Wifi
|
||||
QString wifiCountry, wifiSSID, wifiBSSID, wifichannel;
|
||||
bool wifihost;
|
||||
//General
|
||||
QString etherMac;
|
||||
//NOTE: All the "static" variables are only used for rc.conf settings
|
||||
// For the current IP/IPv6 information use the "NetDevice" class below
|
||||
QString staticIPv4, staticNetmask, staticIPv6; //assumes DHCP if none are set
|
||||
QString staticGateway;
|
||||
};
|
||||
|
||||
//General data class for network devices
|
||||
// Note: Sources in NetDevice.cpp
|
||||
class NetDevice{
|
||||
private:
|
||||
QString name;
|
||||
public:
|
||||
NetDevice(QString devName){ name = devName; }
|
||||
QString device(){ return name; } //full device name (wlan0)
|
||||
QString devName(); //name only (wlan)
|
||||
uint devNum(); //number only (0)
|
||||
QString ipAsString();
|
||||
QString ipv6AsString();
|
||||
QString netmaskAsString();
|
||||
QString desc();
|
||||
QString macAsString();
|
||||
//QString mediaTypeAsString();
|
||||
QString mediaStatusAsString();
|
||||
QString gatewayAsString();
|
||||
bool isWireless();
|
||||
QString getWifiParent();
|
||||
bool usesDHCP();
|
||||
bool isUp();
|
||||
long packetsRx();
|
||||
long packetsTx();
|
||||
long errorsRx();
|
||||
long errorsTx();
|
||||
|
||||
//Setting Functions (to make changes - requires root)
|
||||
void setUp(bool up); //Turn device on/off (temporary - not saved globally)
|
||||
|
||||
//Generic listing of devices
|
||||
static QStringList listNetDevices(); //probe the system for all network devices
|
||||
};
|
||||
|
||||
//General data structure for wifi access points (local or available)
|
||||
struct NetWifi{
|
||||
NetCrypt encryption;
|
||||
};
|
||||
|
||||
|
||||
//The general-purpose class that any user/app can utilitize
|
||||
class Network{
|
||||
public:
|
||||
static QList<NetworkEntry> listNetworkEntries();
|
||||
static QStringList readRcConf(); //use this when reading /etc/rc.conf for network stuff - prevents opening the file repeatedly
|
||||
static NetDevSettings deviceRCSettings(QString dev); //settings in rc.conf (bootup)
|
||||
static NetDevSettings deviceIfconfigSettings(QString dev); //settings currently running
|
||||
};
|
||||
|
||||
//The class that requires overarching root permissions (usually for changes to system)
|
||||
class NetworkRoot{
|
||||
public:
|
||||
static bool saveNetworkEntry(NetworkEntry); //**Not implemented yet**
|
||||
static bool saveRCSettings(NetDevSettings); //rc.conf settings (bootup)
|
||||
static bool setIfconfigSettings(NetDevSettings); //ifconfig settings (temporary session)
|
||||
};
|
||||
|
||||
} //end of pcbsd namespace
|
||||
|
||||
#endif
|
||||
8
src/sysadm.pro
Normal file
8
src/sysadm.pro
Normal file
@@ -0,0 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += recursive
|
||||
|
||||
SUBDIRS+= library binary
|
||||
|
||||
#Make sure to list the library as a requirement for the others (for parallellized builds)
|
||||
binary.depends = library
|
||||
|
||||
Reference in New Issue
Block a user