/********************************************************************** * OK335xS Qt network hacking * 说明: * 应该半年前尝试过来解读这个程序,但是那时候对有些东西不是很理解, * 最后不了了之了,这次因为需要,所以重新对network的mainwindow.cpp进行 * 一下解读。 * * 2016-4-8 深圳 南山平山村 曾剑锋 *********************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" // ifconfig -a|grep -E "eth[0-9]|wlan[0-9]"|cut -d' ' -f 1 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { // 设置UI界面 ui->setupUi(this); proc = NULL; flag = false; // 选择的网卡发生了改变 connect(ui->cb_interface, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(on_sel_changed(QString))); // 点击了OK按j钮 connect(ui->ok, SIGNAL(clicked()), this, SLOT(on_ok_clicked())); // 选择了dhcp单选按钮 connect(ui->radio_dhcp, SIGNAL(toggled(bool)), this, SLOT(on_toggled(bool))); // 选择了static单选按钮 connect(ui->radio_static, SIGNAL(toggled(bool)), this, SLOT(on_toggled(bool))); // 获取当前系统中的网卡,并创建对应的网卡实例 refreshInterfaces(); // 读取当前系统默认对网卡的配置 readConfigs(); // 将当前默认的网卡的数据显示 on_sel_changed(ui->cb_interface->currentText()); } MainWindow::~MainWindow() { delete ui; // 释放实例化的网卡实例 foreach(Interface *i,ints) delete i; } void MainWindow::state(bool dhcp) { // 设置UI显示状态 if(dhcp) { ui->radio_dhcp->setChecked(true); ui->radio_static->setChecked(false); ui->edt_ip->setDisabled(true); ui->edt_mask->setDisabled(true); ui->edt_gateway->setDisabled(true); ui->edt_dns->setDisabled(true); } else { ui->radio_dhcp->setChecked(false); ui->radio_static->setChecked(true); ui->edt_ip->setDisabled(false); ui->edt_mask->setDisabled(false); ui->edt_gateway->setDisabled(false); ui->edt_dns->setDisabled(false); } } void MainWindow::refreshInterfaces() { QStringList sl; /*过滤读eth[0-9] wlan[0-9]*/ // 获取网卡名保存在/tmp/interfaces文件中,一行一个网卡名 ::system("ifconfig -a|grep -E \"eth[0-9]\"|cut -d' ' -f 1 >/tmp/interfaces"); // 打开缓存文件 QFile f("/tmp/interfaces"); if(f.open(QFile::ReadOnly)) { // 创建文件流 QTextStream t(&f); // 判断是否到了文件末尾 while(!t.atEnd()) { // 获取一行,也就是一个网卡名 QString str=t.readLine(); if(str.size()>0) { //QMessageBox::about(this,"aaa",str); /** * 1. QList<Interface*> ints; * 2. class Interface * { * public: * Interface(QString &name); * public: * QString name; * bool dhcp; * QString ip; * QString mask; * QString gateway; * QString dns; * }; * 3. 实例化网卡,添加在list后面 * 4. 与后面的c_interface的index是一样的 * */ ints.append(new Interface(str)); sl<<str; } } } f.close(); ui->cb_interface->addItems(sl); } void MainWindow::readConfigs() { /*自己的配置文件*/ foreach(Interface *i,ints) { // 获取几个网卡的默认配置信息 QFile f("/etc/network/.conf/"+i->name); if(f.open(QFile::ReadOnly)) { QTextStream t(&f); QString str = t.readLine(); if(str == "dhcp")//do nothing ; // 从下面的内容可以知道,配置信息的循序必须按照下面读取的顺序进行排序写, // 否则会照成配置出错 else if(str == "static") { i->dhcp = false; i->ip = t.readLine(); i->mask = t.readLine(); i->gateway = t.readLine(); i->dns = t.readLine(); } } f.close(); } } /** * @brief ip2int * @param ip * @return * * 将IP地址转化成整数 */ unsigned int ip2int(QString ip) { QStringList sl = ip.split('.'); unsigned int r = 0; foreach(QString s,sl) { r <<= 8; r |= s.toUInt(); } return r; } /** * @brief int2ip * @param ip * @return * * 将int型整数,转化成点分十进制IP */ QString int2ip(unsigned int ip) { return QString::number((ip >> 24) & 0xff) + "." + QString::number((ip >> 16) & 0xff) + "." + QString::number((ip >> 8) & 0xff) + "." + QString::number(ip & 0xff); } void MainWindow::writeConfigs() { /*真正的配置文件*/ // 域名服务器IP ::system("rm /etc/resolv.conf"); QFile r("/etc/resolv.conf");//for dns QTextStream *t2 = NULL; if(r.open(QFile::WriteOnly)) { t2 = new QTextStream(&r); } // 网卡参数 QFile m("/etc/network/interfaces");//for interface QTextStream *t3 = NULL; if(m.open(QFile::WriteOnly)) { t3 = new QTextStream(&m); } /*write `lo` configration first*/ *t3<<QString("auto lo\n"); *t3<<QString("iface lo inet loopback\n"); ::system("mkdir -p /etc/network/.conf"); /*自己的配置文件*/ // 重写配置文件 foreach(Interface *i,ints) { QFile f("/etc/network/.conf/"+i->name); if(f.open(QFile::WriteOnly)) { QTextStream t(&f); if(i->dhcp) { t<<QString("dhcp")<<QString(QString("\n")); *t3<<QString("auto ")<<i->name<<QString(QString("\n")); *t3<<QString("iface ")<<i->name<<QString(" inet dhcp\n"); } else { t<<QString("static")<<QString("\n"); t<<i->ip<<QString("\n"); t<<i->mask<<QString("\n"); t<<i->gateway<<QString("\n"); t<<i->dns<<QString("\n"); *t3<<QString("auto ")<<i->name<<QString("\n"); *t3<<QString("iface ")<<i->name<<QString(" inet static\n"); *t3<<QString("address ")<<i->ip<<QString("\n"); *t3<<QString("netmask ")<<i->mask<<QString("\n"); *t3<<QString("gateway ")<<i->gateway<<QString("\n"); *t3<<QString("broadcast ")<<int2ip((ip2int(i->ip) & ip2int(i->mask))|(~ip2int(i->mask)))<<QString("\n"); *t2<<QString("nameserver ")+i->dns<<QString("\n");//同时写入到/etc/resolv.conf } } f.close(); } delete t2; delete t3; r.close(); m.close(); } void MainWindow::on_toggled(bool b) { // 通过这里知道当前索引的那张网卡 Interface *i = NULL; foreach(i,ints) { if(i->name == ui->cb_interface->currentText()) break; } // 根据当前的是否采用dhcp还是static来显示UI控件 state(ui->radio_dhcp->isChecked()); // 显示对应的数据 if(ui->radio_dhcp->isChecked()) { /*ui->edt_ip->clear(); ui->edt_mask->clear(); ui->edt_gateway->clear(); ui->edt_dns->clear();*/ } else { ui->edt_ip->setText(i->ip); ui->edt_mask->setText(i->mask); ui->edt_gateway->setText(i->gateway); ui->edt_dns->setText(i->dns); } } void MainWindow::on_sel_changed(const QString &text) { // 循环检查,如果当前次循环的网卡实例名与传入的参数一样,那么跳出循环, // i则指向了当前需要配置的网卡 Interface *i = NULL; foreach(i,ints) { if(i->name == text) break; } //QMessageBox::about(this,"aaa",i->name); // 设置UI显示状态 state(i->dhcp); // 重新设置UI中的值 if(i->dhcp) { ui->edt_ip->clear(); ui->edt_mask->clear(); ui->edt_gateway->clear(); ui->edt_dns->clear(); } else { ui->edt_ip->setText(i->ip); ui->edt_mask->setText(i->mask); ui->edt_gateway->setText(i->gateway); ui->edt_dns->setText(i->dns); } } void MainWindow::on_ok_clicked() { // 获取当前的网jjj卡 Interface *i = NULL; foreach(i,ints) { if(i->name == ui->cb_interface->currentText()) break; } // 设置当前的网卡 i->dhcp = ui->radio_dhcp->isChecked(); i->ip = ui->edt_ip->text(); i->mask = ui->edt_mask->text(); i->gateway = ui->edt_gateway->text(); i->dns = ui->edt_dns->text(); // 写入文件 writeConfigs(); // 同步,将内存中的数据写入NAND或者SD卡 ::system("sync"); // 如果proc存在,那么就释放 if(proc) delete proc; // 创建进程来重启网卡 proc = new QProcess(this); proc->start("/etc/init.d/networking restart"); // 防止进程未处理完之前,程序退出 connect(proc,SIGNAL(finished(int)),this,SLOT(proc_finished(int))); this->setDisabled(true); flag = true; } void MainWindow::closeEvent(QCloseEvent * evt) { if(flag) { evt->ignore(); QMessageBox::about(this,"info","network is restarting,please wait"); } else { destroy(); exit(0); } } void MainWindow::moveEvent(QMoveEvent *) { this->move(QPoint(0,0)); } void MainWindow::resizeEvent(QResizeEvent *) { this->showMaximized(); } void MainWindow::proc_finished(int code) { if(proc->exitStatus() == QProcess::NormalExit) { this->setDisabled(false); flag = false; QMessageBox::about(this,"info","network restart ok!"); } }