source: src-qt4/libpcbsd/utils/netif.cpp @ 68ecb7a

releng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 68ecb7a was 68ecb7a, checked in by Kris Moore <kris@…>, 12 months ago

Fix a typo

  • Property mode set to 100644
File size: 19.7 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2008 by Tim McCormick   *
3 *   tim@pcbsd.org   *
4 *                                                                         *
5 *   Permission is hereby granted, free of charge, to any person obtaining *
6 *   a copy of this software and associated documentation files (the       *
7 *   "Software"), to deal in the Software without restriction, including   *
8 *   without limitation the rights to use, copy, modify, merge, publish,   *
9 *   distribute, sublicense, and/or sell copies of the Software, and to    *
10 *   permit persons to whom the Software is furnished to do so, subject to *
11 *   the following conditions:                                             *
12 *                                                                         *
13 *   The above copyright notice and this permission notice shall be        *
14 *   included in all copies or substantial portions of the Software.       *
15 *                                                                         *
16 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
17 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
18 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
20 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
21 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
22 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
23 ***************************************************************************/
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/ioctl.h>
28#include <sys/sysctl.h>
29#include <unistd.h>
30
31#include <net/if.h>
32#include <net/if_dl.h>
33#include <net/if_media.h>
34
35#include <ifaddrs.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <stdlib.h>
39
40#include <qregexp.h>
41#include <QDebug>
42#include <QFile>
43#include <qstring.h>
44//#include <QMessageBox> //for debugging purposes
45
46#include "pcbsd-netif.h"
47#include "pcbsd-utils.h"
48
49using namespace pcbsd;
50
51QStringList NetworkInterface::getInterfaces()
52{
53   QStringList result;
54   struct ifaddrs *ifap;
55   getifaddrs(&ifap);
56   char ifName[IFNAMSIZ];
57   
58   while (ifap != NULL)
59   {
60      strncpy(ifName, ifap->ifa_name, IFNAMSIZ);
61      if (result.contains(ifName) == 0) result += ifName;
62      ifap = ifap->ifa_next;
63   }
64
65   freeifaddrs(ifap);
66   return result;
67}
68
69NetworkInterface::NetworkInterface(QString devName)
70{
71   name = devName;
72}
73
74QString NetworkInterface::ipAsString()
75{
76   struct ifreq ifr;
77   memset(&ifr, 0, sizeof(struct ifreq));
78
79   strncpy(ifr.ifr_name, name.toAscii(), IFNAMSIZ);
80   int s = socket(PF_INET, SOCK_DGRAM, 0);
81   
82   ioctl(s, SIOCGIFADDR, &ifr);
83   struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
84
85   return QString(inet_ntoa(in));
86}
87
88QString NetworkInterface::netmaskAsString()
89{
90   struct ifreq ifr;
91   memset(&ifr, 0, sizeof(struct ifreq));
92
93   strncpy(ifr.ifr_name, name.toAscii(), IFNAMSIZ);
94   int s = socket(PF_INET, SOCK_DGRAM, 0);
95   
96   ioctl(s, SIOCGIFNETMASK, &ifr);
97   struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
98
99   return QString(inet_ntoa(in));
100}
101
102QString NetworkInterface::macAsString()
103{
104   int mib[6];
105   size_t len;
106   char *buf;
107   struct sockaddr_dl *sdl;
108   char *ptr;
109
110   mib[0] = CTL_NET;
111   mib[1] = AF_ROUTE;
112   mib[2] = 0;
113   mib[3] = AF_LINK;
114   mib[4] = NET_RT_IFLIST;
115   mib[5] = if_nametoindex(name.toAscii());
116
117   //First find the size of the return, so we can adjust buf accordingly
118   sysctl(mib, 6, NULL, &len, NULL, 0);
119   buf = (char *) malloc(len);
120   sysctl(mib, 6, buf, &len, NULL, 0);
121
122   sdl = (sockaddr_dl *)(((if_msghdr *)buf)+1);
123   ptr = (char *) LLADDR(sdl);
124   
125   QString mac;
126   for (uint i=0; i < 6; i++)
127   {
128      mac += QString::number(*(ptr+i), 16).right(2).rightJustified(2, '0');
129      if (i<5) mac += ":";
130   }
131   
132   return mac;
133}
134
135QString NetworkInterface::mediaStatusAsString()
136{
137   struct ifmediareq ifm;
138   memset(&ifm, 0, sizeof(struct ifmediareq));
139
140   strncpy(ifm.ifm_name, name.toAscii(), IFNAMSIZ);
141   int s = socket(AF_INET, SOCK_DGRAM, 0);
142
143   ioctl(s, SIOCGIFMEDIA, &ifm);
144   QString status;
145
146   switch (IFM_TYPE(ifm.ifm_active))
147   {
148      case IFM_FDDI:
149      case IFM_TOKEN:
150         if (ifm.ifm_status & IFM_ACTIVE) status = "inserted";
151         else status = "no ring";
152         break;
153      case IFM_IEEE80211:
154         if (ifm.ifm_status & IFM_ACTIVE) status = "associated";
155         else status = "no carrier";
156         break;
157      default:
158         if (ifm.ifm_status & IFM_ACTIVE) status = "active";
159         else status = "no carrier";
160   }
161   return status;
162}
163
164QString NetworkInterface::desc()
165{
166   return Utils::sysctl("dev." + devName() + "." + QString::number(devNum()) + ".%desc");
167}
168
169QString NetworkInterface::devName()
170{
171   uint pos = name.indexOf(QRegExp("[0-9]+$"));
172   QString result = name;
173   result.truncate(pos);
174   return result;
175}
176
177bool NetworkInterface::isWireless()
178{
179   struct ifmediareq ifm;
180   memset(&ifm, 0, sizeof(struct ifmediareq));
181
182   strncpy(ifm.ifm_name, name.toAscii(), IFNAMSIZ);
183   int s = socket(AF_INET, SOCK_DGRAM, 0);
184
185   ioctl(s, SIOCGIFMEDIA, &ifm);
186
187   return IFM_TYPE(ifm.ifm_active) == IFM_IEEE80211;
188}
189
190bool NetworkInterface::isUp()
191{
192   struct ifreq ifr;
193   memset(&ifr, 0, sizeof(struct ifreq));
194
195   strncpy(ifr.ifr_name, name.toAscii(), IFNAMSIZ);
196   int s = socket(AF_INET, SOCK_DGRAM, 0);
197
198   ioctl(s, SIOCGIFFLAGS, &ifr);
199
200   return (ifr.ifr_flags & IFF_UP) ? 1 : 0;
201}
202
203long NetworkInterface::packetsRx()
204{
205   int mib[6];
206   size_t len;
207   char *buf;
208   struct if_msghdr *ifm;
209
210   mib[0] = CTL_NET;
211   mib[1] = AF_ROUTE;
212   mib[2] = 0;
213   mib[3] = AF_LINK;
214   mib[4] = NET_RT_IFLIST;
215   mib[5] = if_nametoindex(name.toAscii());
216
217   //First find the size of the return, so we can adjust buf accordingly
218   sysctl(mib, 6, NULL, &len, NULL, 0);
219   buf = (char *) malloc(len);
220   sysctl(mib, 6, buf, &len, NULL, 0);
221
222   ifm = (if_msghdr *) buf;
223
224   return ifm->ifm_data.ifi_ipackets;
225}
226
227long NetworkInterface::packetsTx()
228{
229   int mib[6];
230   size_t len;
231   char *buf;
232   struct if_msghdr *ifm;
233
234   mib[0] = CTL_NET;
235   mib[1] = AF_ROUTE;
236   mib[2] = 0;
237   mib[3] = AF_LINK;
238   mib[4] = NET_RT_IFLIST;
239   mib[5] = if_nametoindex(name.toAscii());
240
241   //First find the size of the return, so we can adjust buf accordingly
242   sysctl(mib, 6, NULL, &len, NULL, 0);
243   buf = (char *) malloc(len);
244   sysctl(mib, 6, buf, &len, NULL, 0);
245
246   ifm = (if_msghdr *) buf;
247
248   return ifm->ifm_data.ifi_opackets;
249}
250
251long NetworkInterface::errorsRx()
252{
253   int mib[6];
254   size_t len;
255   char *buf;
256   struct if_msghdr *ifm;
257
258   mib[0] = CTL_NET;
259   mib[1] = AF_ROUTE;
260   mib[2] = 0;
261   mib[3] = AF_LINK;
262   mib[4] = NET_RT_IFLIST;
263   mib[5] = if_nametoindex(name.toAscii());
264
265   //First find the size of the return, so we can adjust buf accordingly
266   sysctl(mib, 6, NULL, &len, NULL, 0);
267   buf = (char *) malloc(len);
268   sysctl(mib, 6, buf, &len, NULL, 0);
269
270   ifm = (if_msghdr *) buf;
271
272   return ifm->ifm_data.ifi_ierrors;
273}
274
275long NetworkInterface::errorsTx()
276{
277   int mib[6];
278   size_t len;
279   char *buf;
280   struct if_msghdr *ifm;
281
282   mib[0] = CTL_NET;
283   mib[1] = AF_ROUTE;
284   mib[2] = 0;
285   mib[3] = AF_LINK;
286   mib[4] = NET_RT_IFLIST;
287   mib[5] = if_nametoindex(name.toAscii());
288
289   //First find the size of the return, so we can adjust buf accordingly
290   sysctl(mib, 6, NULL, &len, NULL, 0);
291   buf = (char *) malloc(len);
292   sysctl(mib, 6, buf, &len, NULL, 0);
293
294   ifm = (if_msghdr *) buf;
295
296   return ifm->ifm_data.ifi_oerrors;
297}
298
299uint NetworkInterface::devNum()
300{
301   uint pos = name.indexOf(QRegExp("[0-9]+$"));
302   return name.mid(pos).toInt();
303}
304
305void NetworkInterface::restart(){
306  //restart all network connections
307  system("(sync; ifconfig lagg0 destroy; route -n flush; /etc/rc.d/netif restart) &");
308}
309
310QStringList NetworkInterface::parseWifiScanLine( QString linein, bool isverbose){
311  /*
312    This function works given a single line of the command:
313      "ifconfig (wifi device) list scan" (verbose or not)
314    Output: QStringList[ssid,bssid,channel,rate,signal%,INT,CAPS,etc]
315  */
316  int n; //index for end of the SSID section
317  if(isverbose){n=33;} //verbose can display full ssid names between 16-33 characters long
318  else{n=16;}
319  QString line = linein; //make sure we do not change the line outside the function
320  //Parse the line into its components
321  QString ssid = line.left(n); //Entire SSID/MESH ID column
322    ssid = ssid.trimmed(); //remove excess whitespace at the ends
323    line.remove(0,n); //remove the ssid from the line (multiple words mess up later parts otherwise)
324  QString bssid = line.section(" ",0,0,QString::SectionSkipEmpty); //BSSID column
325  QString chan = line.section(" ",1,1,QString::SectionSkipEmpty); //CHAN column
326  QString rate = line.section(" ",2,2,QString::SectionSkipEmpty); //RATE column
327  QString signoise = line.section(" ",3,3,QString::SectionSkipEmpty); //S:G column
328  QString inte = line.section(" ",4,4,QString::SectionSkipEmpty); //INT column
329  QString caps = line.section(" ",5,5,QString::SectionSkipEmpty); //CAPS column
330  QString etc = line.section(" ",6,50,QString::SectionSkipEmpty); //Everything at the end (security info)
331
332    //change signoise into signal strength(%)
333    QString sig = signoise.section(":",0,0); //determine signal
334    QString noise = signoise.section(":",1,1); //determine noise
335    //determine the signal strength
336    int signal = ( sig.toInt()-noise.toInt() )*4;
337    if(signal<0){signal=0;}
338    if(signal>100){signal=100;}
339    //output result as a QString percentage
340    QString strength = QString::number(signal);
341    strength.append("%");
342
343  //get the security type
344    QString secType = parseWifiSecurity(caps,etc);
345  //put into QStringList for output
346  QStringList out;
347  out << ssid << bssid << chan << rate << strength << inte << secType;
348  return out;
349}
350
351QString NetworkInterface::getWifiSecurity( QString SSID, QString deviceName ){
352  //Make sure the SSID is short enough (non verbose will be used to search)
353  QString smSSID;
354  if(SSID.size() > 10){
355    smSSID = SSID.left(10);
356  }else{
357    smSSID = SSID; 
358  }
359  //Scan the wifi to determine the security type
360  //If there are multiple wifi's with the same SSID, it will use the first one only
361  QString command = "ifconfig " + deviceName + " list scan";
362  QString ifconfOut = Utils::runShellCommandSearch(command,smSSID);
363  QStringList parsed = NetworkInterface::parseWifiScanLine(ifconfOut,false);
364  //get the security type
365  QString output = parsed[6];
366  return output;
367}
368
369QString NetworkInterface::parseWifiSecurity( QString caps, QString etc ){
370  // INPUT: caps and etc are the last two fields output from "ifconfig (device) list scan"
371 
372  QStringList secure = etc.split(" "); //put each security type in a different list element
373   
374  //Examine the CAPS and Security data to determine the wifi encryption type
375  bool isDisabled = !caps.contains("P") && caps.contains("ES"); //CAPS = "ES" only -> no wifi encryption
376  bool isWEP = caps.contains("EP"); //CAPS = "EP" or "EPS" only (could also be RADIUS security type)
377  bool isWPA = secure.contains("WPA"); //both WPA personal and enterprise
378  bool isWPA2 = secure.contains("RSN"); //both WPA2 personal and enterprise
379 
380  //qDebug() << "caps: "+caps+"\netc: "+etc;
381
382  //Output the security type
383  QString securityType;
384  if(isDisabled){ 
385    securityType = "None";
386  }else if(isWPA2){ 
387    securityType = "WPA2";
388  }else if(isWPA){ 
389    securityType = "WPA";
390  }else if(isWEP){ 
391    securityType = "WEP";
392  }else{ 
393    securityType = "ERROR";
394  }
395  return securityType;
396}
397
398QString NetworkInterface::getFirstWiredDevice()
399{
400  QString tmp;
401
402  QStringList ifs = getInterfaces();
403  for ( QStringList::Iterator it = ifs.begin(); it != ifs.end(); ++it )
404  {
405     // List of devices to exclude not real ethernet
406     QString tmpDev = *it;
407     if (tmpDev.indexOf("lo0") == -1
408         && tmpDev.indexOf("lagg") == -1
409         && tmpDev.indexOf("lo1") == -1
410         && tmpDev.indexOf("lo2") == -1
411         && tmpDev.indexOf("lo3") == -1
412         && tmpDev.indexOf("fwe") == -1
413         && tmpDev.indexOf("plip") == -1
414         && tmpDev.indexOf("pfsync") == -1
415         && tmpDev.indexOf("pflog") == -1
416         && tmpDev.indexOf("ipfw") == -1
417         && tmpDev.indexOf("tun") == -1
418         && tmpDev.indexOf("usbus") == -1
419         && tmpDev.indexOf("vboxnet") == -1
420         && tmpDev.indexOf("wlan") == -1 )
421     {
422        NetworkInterface ifr(tmpDev);
423        if (! ifr.isWireless()) {
424          return tmpDev;
425        }
426     }
427  }
428
429  return tmp;
430}
431
432QString NetworkInterface::getWifiParent(QString dev)
433{
434   dev.remove(0, dev.size() -1 );
435   QString DevNum = dev;
436   return Utils::sysctl("net.wlan." + DevNum + ".%parent");
437}
438
439void NetworkInterface::wifiQuickConnect(QString SSID, QString netKey, QString DeviceName){
440  /*
441     This function uses a set of defaults to connect to a wifi access point with a minimum
442     of information from the user. It does *NOT* (currently) support the WPA-Enterprise encryption
443  */
444 
445    //do nothing if no SSID given
446    if( SSID.isEmpty() ){
447      return;
448    }
449 
450    QString tmp;
451    QString ifConfigLine;
452   
453    //Set defaults for quick-connect
454    ifConfigLine="SYNCDHCP"; //Use DHCP
455
456    //setup for not using the lagg interface
457      Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_lagg0", "", -1);
458      Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_" + DeviceName, \
459                 "ifconfig_" + DeviceName + "=\"WPA " + ifConfigLine + "\"", -1);
460
461       
462    //Determine if the wpa_supplicant file exists already or is empty
463    bool newWPASup = true;
464    bool existingSSID = false;
465    QStringList tmpFileList;
466    QString tmpEntry;
467    QFile fileout( "/etc/wpa_supplicant.conf" );
468    if( fileout.open( QIODevice::ReadOnly ) ){
469      QTextStream streamtmp(&fileout);
470      streamtmp.setCodec("UTF-8");
471        QString line;
472        bool inEntry = false;
473        bool eStart, eEnd;
474        while ( !streamtmp.atEnd() ) {
475            eStart = false; 
476            eEnd = false;       
477            line = streamtmp.readLine();
478            if ( line.contains("ctrl_interface=/var/run/wpa_supplicant") ) {
479                newWPASup = false;
480            }else if(line.contains("ssid=") && line.contains(SSID)){
481                existingSSID=true;
482            }else if(line.contains("network={")){eStart = true;}
483            else if(line.contains("}")){eEnd = true; }
484           
485            //Save the file by entry temporarily
486            if(eStart){ tmpEntry = line; inEntry = true; }
487            else if(eEnd){ tmpEntry.append(" ::: "+line); tmpFileList << tmpEntry; inEntry=false; }         
488            else if(inEntry){ tmpEntry.append(" ::: "+line); }
489            else{ tmpFileList << line; }
490        }
491        fileout.close();
492    }
493    //If the desired SSID already has an entry, remove it from wpa_supplicant.conf
494    if(existingSSID){
495      QFile tmpFile( "/etc/wpa_supplicant.conf.tmp" );
496      if(tmpFile.open(QIODevice::WriteOnly | QIODevice::Text )){
497        QTextStream oStr(&tmpFile);
498        for(int i=0; i<tmpFileList.length(); i++){
499          if(tmpFileList[i].contains("network={")){
500            QStringList tmp = tmpFileList[i].split(" ::: ");
501            //skip it if the new SSID
502            int idx = tmp.indexOf("ssid=");
503            if( (idx!= -1) && !tmp[idx].contains(SSID) ){
504              for(int j=0; j<tmp.length(); j++){
505                oStr << tmp[j] + "\n";             
506              }
507            }
508          }else{
509            oStr << tmpFileList[i] + "\n";       
510          }                     
511        }
512      }
513      tmpFile.close();
514      Utils::runShellCommand("mv /etc/wpa_supplicant.conf.tmp /etc/wpa_supplicant.conf");
515    }
516   
517    // Create the wpa_supplicant file based on saved configuration   
518    if ( fileout.open( QIODevice::Append ) ) {
519       QTextStream streamout( &fileout );
520
521       // Fix to prevent kernel panic
522       if(newWPASup)
523           streamout << "ctrl_interface=/var/run/wpa_supplicant\n\n";
524       //Use SSID for network connection
525       streamout << "\nnetwork={\n ssid=\"" + SSID + "\"\n";
526       streamout << " priority=" << 146 << "\n";
527       streamout << " scan_ssid=1\n";
528
529       //Determine the security type for the given SSID
530       QString SecType = getWifiSecurity(SSID,DeviceName);
531       
532       //Configure the wifi Security Settings for the proper type
533       if ( SecType.contains("None") ){
534          streamout << " key_mgmt=NONE\n";
535         
536       } else if ( SecType.contains("WEP") ) {
537          //Set WEP Defaults
538          int WEPIndex = 0;
539          bool WEPHex = true; //Use Hex WEP key
540         
541          streamout << " key_mgmt=NONE\n";
542          streamout << " wep_tx_keyidx=" + tmp.setNum(WEPIndex) + "\n";
543          // Check if we are using a plaintext WEP or not
544          if ( WEPHex ) {
545            streamout << " wep_key" + tmp.setNum(WEPIndex) + "=" + netKey + "\n";
546          } else {
547            streamout << " wep_key" + tmp.setNum(WEPIndex) + "=\"" + netKey + "\"\n";
548          }
549
550       } else if ( SecType.contains("WPA") ) {
551          streamout << " psk=\"" + netKey + "\"\n";     
552       } 
553
554       streamout << "}\n\n";
555
556       fileout.close();
557     } 
558
559    // Flush to disk, so that when we restart network it picks up the changes
560    sync();
561
562    Utils::restartNetworking();
563   
564   return;
565}
566
567// Function which sets up the lagg0 interface for the specified wlan[0-9] device
568void NetworkInterface::enableLagg(QString dev)
569{
570  // Get the first wired device, we will enable lagg0 to use it
571  QString wiredDev, wifiParent, wifiConf, tmp, newWifiConf;
572  wiredDev = NetworkInterface::getFirstWiredDevice();
573  wifiParent = NetworkInterface::getWifiParent(dev);
574
575  // If no wired device on this box or no valid wifi parent we can return, no need to setup lagg
576  if ( wiredDev.isEmpty() || wifiParent.isEmpty() )
577     return;
578
579  // Get the config for this wifi device
580  wifiConf = Utils::getConfFileValue( "/etc/rc.conf", "ifconfig_" + dev + "=", 1 );
581  if ( wifiConf.isEmpty() )
582     wifiConf = Utils::getConfFileValue( "/etc/rc.conf", "ifconfig_lagg0=", 1 );
583  else if ( wifiConf == "WPA" ) {
584     // If it just equals WPA, check if anything already exists in lagg0 line
585     tmp = Utils::getConfFileValue( "/etc/rc.conf", "ifconfig_lagg0=", 1 );
586     if ( ! tmp.isEmpty() )
587        wifiConf = tmp;
588  }
589
590  // No valid config? We can't save this..
591  if ( wifiConf.isEmpty() )
592     return;
593
594  // Setup the ethernet mac address cloning for this device
595  Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_" + wifiParent, "ifconfig_" + wifiParent + "=\"`ifconfig " + wiredDev + " ether`\"", 1);
596  Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_" + wifiParent, "ifconfig_" + wifiParent + "=\"ether ${ifconfig_" + wifiParent + "##*ether }\"", 2);
597  Utils::setConfFileValue( "/etc/rc.conf", "wlans_" + wifiParent, "wlans_" + wifiParent + "=\"" + dev + "\"", -1);
598
599  wifiConf = wifiConf.simplified();
600
601  // Check if we have a WPA setting, and put it in the right device slot
602  if ( wifiConf.indexOf("WPA") != -1 )
603  {
604    newWifiConf="WPA";
605    wifiConf = wifiConf.replace("WPA", "");
606  }
607
608  // Check if we have a Country code setting, and put it in the right device slot
609  if ( wifiConf.indexOf("country ") != -1 )
610  {
611    tmp = wifiConf;
612    tmp.remove(0, tmp.lastIndexOf("country") + 8);
613    tmp = tmp.section(" ", 0,0);
614
615    newWifiConf+=" country " + tmp;
616    wifiConf = wifiConf.remove(wifiConf.indexOf("country"), wifiConf.indexOf("country") + 10 );
617  }
618
619
620  // Save the new wifi config line
621  newWifiConf = newWifiConf.simplified();
622  Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_" + dev, "ifconfig_" + dev + "=\"" + newWifiConf + "\"", -1);
623
624  // Set the wired device to UP
625  Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_" + wiredDev, "ifconfig_" + wiredDev + "=\"UP\"", -1);
626
627  // Enable the lagg0 interface
628  wifiConf = wifiConf.simplified();
629  Utils::setConfFileValue( "/etc/rc.conf", "cloned_interfaces", "cloned_interfaces=\"lagg0\"", -1);
630  Utils::setConfFileValue( "/etc/rc.conf", "ifconfig_lagg0", "ifconfig_lagg0=\"laggproto failover laggport " + wiredDev + " laggport " + dev + " " + wifiConf + "\"", -1);
631
632}
Note: See TracBrowser for help on using the repository browser.