--- ../../kisdn-0.7.2-pro/kisdn/connection.cpp	Sat Jan  9 19:42:18 1999
+++ /home/gis/src/kisdn/kisdn/connection.cpp	Mon Jan 25 09:39:29 1999
@@ -1,44 +1,40 @@
-/*  
+/*
  *  This file is part of kISDN, Copyright (C) 1998 by
  *
  *  Thorsten Westheider <twesthei@phya1.physik.uni-bielefeld.de>
  *  Carsten Pfeiffer <carpdjih@sp.zrz.tu-berlin.de>
  *
- *	Revision 1 (T. Westheider, 1998/10/12)		
- *
  ****************************************************************/
- 
-// $Id: connection.cpp,v 1.9 1998/11/14 16:31:08 twesthei Exp $
+
+// $Id: connection.cpp,v 1.15 1998/12/20 22:05:28 twesthei Exp $
 //
 // $Log: connection.cpp,v $
-// Revision 1.9  1998/11/14 16:31:08  twesthei
-// Replaced file buffering by file backup; in addition,
-// ip-up and ip-down are saved, too, now.
-//
-// Revision 1.8  1998/10/30 17:19:03  twesthei
-// Implemented TimRu check in ISDNconfig and Connection
-//
-// Revision 1.7  1998/10/27 21:44:40  twesthei
-// Lots of last-in-minute fixes, teasers etc..
+// Revision 1.15  1998/12/20 22:05:28  twesthei
+// Still profiling dual mode
 //
-// Revision 1.6  1998/10/24 22:52:23  gis
+// Revision 1.14  1998/12/19 23:10:42  twesthei
+// Implemented config keys handling of 2 ISDN cards at
+// the same time (dual mode preparations)
 //
-// Segfault hunting... lots of debug messages added and removed :-}
+// Revision 1.13  1998/11/22 14:59:21  twesthei
+// One more step in Q.931 interpretation (information
+// identifier field)
 //
-// Revision 1.5  1998/10/20 14:55:14  twesthei
-// Implemented 'Explicitly enable interface' option; not
-// working yet, since we need recent HiSax headers (will there
-// be problems ?)
+// Revision 1.12  1998/11/21 23:19:41  twesthei
+// DoD is working again; it was broken because of upgrading
+// to HiSax 3.1 (contained in Kernel 2.0.36)
 //
-// Revision 1.4  1998/10/18 15:03:35  twesthei
-// Implemented loading of different MSN's for voice and data
-// connections
+// Revision 1.11  1998/11/20 18:21:01  twesthei
+// New class for handling kernel modules
 //
-// Revision 1.3  1998/10/14 22:33:58  twesthei
-// Added Id and Log headers
+// Revision 1.10  1998/11/19 23:24:20  twesthei
+// Implemented methods for Ip masquerading
 //
+// Revision 1.9  1998/11/14 16:31:08  twesthei
+// Replaced file buffering by file backup; in addition,
+// ip-up and ip-down are saved, too, now.
+
 
- 
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -56,21 +52,23 @@
 #include "general.h"
 
 
-Connection::Connection(AccountData *acc, char *dev, char *slave, NetCtrl *net, ISDNCtrl *ctrl, 
-                       ISDNConfig *config, QWidget *parent, const char *name) : QWidget(parent, name)
+Connection::Connection(AccountData *acc, char *dev, char *slave, NetCtrl *net, ISDNCtrl *ctrl,
+		       ModuleCtrl *mod, ISDNConfig *config, QWidget *parent,
+		       const char *name) : QWidget(parent, name)
 {
   char  ipneg[48], user[NAMESIZE+1], device[16], ipppd[PATHSIZE+1];
   char  buf[16];
-    
+
   GeneralData      *gen    = ISDNData.generalData();
   AdvancedOptions  *adv    = gen->advancedOptions();
   Device           *master = acc->masterDevice();
   Adapter          ad;
   int              encapsulation;
-  
-  bundling = acc->enabledBundling();  
-  encaps   = master->protEncaps(); 
-      
+
+  bundling = acc->enabledBundling();
+  encaps   = master->protEncaps();
+  account  = acc;
+
   switch (encaps)
   {
     case Device::RAWIP    : encapsulation = PROTRAWIP;
@@ -84,46 +82,62 @@
     case Device::SYNCPPP  : encapsulation = PROTSYNC;
                             break;
     case Device::IPUI     : encapsulation = PROTIPUI;
-  } 
-   
-  strcpy(condev, dev);
+  }
+
+  strcpy(condev,   dev);
   strcpy(conslave, slave);
 
   isdnctrl   = ctrl;
   isdnconfig = config;
+  modctrl    = mod;
   netctrl    = net;
-  
+
+  isdnconfig->setMaster(condev);
+  isdnconfig->setSlave(conslave);
+  isdnconfig->setAdapterID(0, ad.Id[ad.NewIndex(gen->adapterType(0))].data());
+
   if (!writeScripts(acc)) ::message("Error writing system scripts");
-  
-  createInterface(acc, ad.Id[ad.NewIndex(gen->adapterType())].data());
-   
+
+  createInterface(acc, ad.Id[ad.NewIndex(gen->adapterType(0))].data());
+
+  if (acc->enabledIPMasquerading())
+  {
+    if (acc->loadIPMasqAliasModule())
+      if (!modctrl->loadModule(QString("ip_alias.o"), QString("")))
+        ::message("Failed to load module ip_alias.o");
+	
+    if (acc->loadIPMasqFTPModule())
+      if (!modctrl->loadModule(QString("ip_masq_ftp.o"), QString("")))
+        ::message("Failed to load module ip_masq_ftp.o");
+  }
+
   if (encaps == Device::SYNCPPP)
   {
     ::message("Starting ipppd for syncPPP interface");
-    
-    sprintf(user,   "%s",      acc->username().data()); 
+
+    sprintf(user,   "%s",      acc->username().data());
     sprintf(device, "/dev/%s", condev);
     sprintf(ipppd,  "%s",      gen->ipppdPath().data());
-  
+
     if (acc->assignType() == AccountData::DYNAMIC) sprintf(ipneg, "noipdefault");
     else sprintf(ipneg, "%s:%s", acc->localIP().string().data(), acc->remoteIP().string().data());
-  
+
     IPPPD = new KProcess();
- 
+
     *IPPPD << ipppd
            << ipneg
            << "user"
            << user;
-	 
+	
     if (acc->enabledBundling()) *IPPPD << "+mp";
-   
+
     if (acc->enabledCallback() && acc->callbackInit())
     {
       *IPPPD << "callback";
       sprintf(buf, "3,%s%s", gen->prefix().data(), gen->msnData().data());
       *IPPPD << buf;
     }
-    
+
     if (adv->bsdCompression())         *IPPPD << "-bsdcomp";
     if (adv->increaseDebug())          *IPPPD << "debug";
 
@@ -147,25 +161,25 @@
       sprintf(buf, "%i", adv->mtu());
       *IPPPD << buf;
     }
-  
+
     if (adv->debugLevel())
     {
       *IPPPD << "kdebug";
       sprintf(buf, "%i", adv->debugLevel());
       *IPPPD << buf;
     }
-  
+
     *IPPPD << "-detach"
            << "lock"
            << "defaultroute"
            << device;
-     
-    if (bundling)     
+
+    if (bundling)
     {
       sprintf(device, "/dev/%s", conslave);
-      *IPPPD << device; 
+      *IPPPD << device;
     }
-    
+
     if (!IPPPD->start()) QMessageBox::warning(this, "Fatal Error",
                                                     "ipppd could not be\n"
                                                     "started !\n\n", "OK", 0);
@@ -175,12 +189,23 @@
 
 Connection::~Connection()
 {
+  if (account->enabledIPMasquerading())
+  {
+    if (account->loadIPMasqAliasModule())
+      if (!modctrl->removeModule(QString("ip_alias.o"), 5))
+        ::message("Failed to remove module ip_alias.o");
+	
+    if (account->loadIPMasqFTPModule())
+      if (!modctrl->removeModule(QString("ip_masq_ftp.o"), 5))
+        ::message("Failed to remove module ip_masq_ftp.o");
+  }
+
   if (encaps == Device::SYNCPPP)
-  { 
+  {
     ::message("Killing ipppd that was started for syncPPP interface");
-    
+
     if (!IPPPD->kill(SIGKILL)) ::message("ipppd could not be killed");
-    else 
+    else
     {
       deleteInterface();
       delete IPPPD;		// Possible memory leak before
@@ -193,18 +218,18 @@
 void Connection::createInterface(AccountData *acc, const char *adapterID)
 {
   char msn[64];
-    
+
   GeneralData  *gen    = ISDNData.generalData();
   Device       *master = acc->masterDevice();
   Phone        *phone;
-  
+
   fprintf(stderr, "kISDN: Setup interface %s\n", condev);
-  
+
   isdnctrl->Addif(condev);
   isdnctrl->setDialMode(condev, ISDNCtrl::MANUAL);
 
   isdnctrl->Eaz(condev, strcat(strcpy(msn, gen->prefix().data()), gen->msnData().data()));
-  
+
   if (master->phoneList().isEmpty()) QMessageBox::warning(this, "Fatal Error",
                                                                 "No phone number supplied\n"
                                                                 "for this ISP !\n\n", "OK", 0);
@@ -213,7 +238,7 @@
   {
     for (phone = master->firstPhone(); phone != 0L; phone = master->nextPhone())
       isdnctrl->AddphoneOut(condev, phone->number().data());
-    
+
     isdnctrl->Dialmax(condev,    master->dialAttempts());
     isdnctrl->Huptimeout(condev, master->hupTime());
     isdnctrl->Encaps(condev,     master->protEncaps());
@@ -226,29 +251,29 @@
       fprintf(stderr, "kISDN: Adding & configuring slave device %s\n", conslave);
       isdnctrl->Addslave(condev, conslave);
       isdnctrl->Eaz(conslave, strcat(strcpy(msn, gen->prefix().data()), gen->msnData().data()));
-      
+
       for (phone = master->firstPhone(); phone != 0L; phone = master->nextPhone())
 	isdnctrl->AddphoneOut(conslave, phone->number().data());
-      
+
       isdnctrl->Dialmax(conslave,    master->dialAttempts());
       isdnctrl->Huptimeout(conslave, master->hupTime());
       isdnctrl->Encaps(conslave,     master->protEncaps());
       isdnctrl->L2_Prot(conslave,    master->protLayer2());
       isdnctrl->L3_Prot(conslave,    master->protLayer3());
       isdnctrl->Secure(conslave,     (acc->secureMode() == AccountData::ON) ? true : false);
-      
+
       isdnctrl->Sdelay(condev, master->delay());
-      
+
       // Now let's bind master to channel 0 and slave to channel 1
-      
-      isdnctrl->Bind(condev, adapterID, 0, false);	
+
+      isdnctrl->Bind(condev,   adapterID, 0, false);	
       isdnctrl->Bind(conslave, adapterID, 1, false);
-    } 
-    
+    }
+
     if (acc->enabledCallback())
     {
-      ushort  cbtype = (acc->callbackInit()) ? CBOUT : CBIN;  
-       
+      ushort  cbtype = (acc->callbackInit()) ? CBOUT : CBIN;
+
       if (acc->stripZeroes())
       {
         QString  inphone;
@@ -256,16 +281,16 @@
         for (phone = master->firstPhone(); phone != 0L; phone = master->nextPhone())
         {
 	  inphone = phone->number().copy();
-	  
+	
 	  if (inphone.left(1) == "0") inphone = inphone.right(inphone.length()-1).copy();
-	  
+	
           isdnctrl->AddphoneIn(condev, inphone.data());
         }
       }
       else isdnctrl->AddphoneIn(condev, acc->ingoingPhone().data());
-      
+
       isdnctrl->Callback(condev, cbtype);
-      
+
       if (cbtype == CBOUT) isdnctrl->CBDelay(condev, acc->hangupTime());
       else
       {
@@ -273,9 +298,9 @@
 	isdnctrl->CBDelay(condev,  acc->callbackTime());
       }
     }
-    
+
     netctrl->ifPointToPoint(condev, "1.1.1.1", "1.1.1.1");
-  } 
+  }
 }
 
 
@@ -283,29 +308,41 @@
 {
   FILE   *OutStream;
   bool   quote = (bool) strchr(acc->username().data(), '#');
-  IP    *dns;   
-    
-  if (quote) 
+  bool   quotePassword = (bool) strchr(acc->password().data(), '#');
+  IP    *dns;
+  QString user, pass;
+
+  if (quote || quotePassword)
   {
-    ::message("Username contains the character '#' (T-Online)");
+    ::message("Username/password contains the character '#' (e.g. T-Online)");
     ::message("I will quote it in ioptions and the secret files");
   }
-    
+
+  if ( quote )
+    user = "\"" + acc->username() + "\"";
+  else
+    user = acc->username();
+
+  if ( quotePassword )
+    pass = "\"" + acc->password() + "\"";
+  else
+    pass = acc->password();
+  
+  
   if (acc->authType() == AccountData::PAP)
   {
     if ((OutStream = fopen(PAPFILE, "w")) != 0)
     {
       fprintf(stderr, "kISDN: Writing %s...\n", PAPFILE);
-      
-      if (quote) fprintf(OutStream, "%c%s%c * %s\n", 34, acc->username().data(), 34, acc->password().data());
-      else       fprintf(OutStream, "%s * %s\n", acc->username().data(), acc->password().data());
+
+      fprintf(OutStream, "%s * %s\n", user.data(), pass.data());
 	
       fclose(OutStream);
-      
+
       chown(PAPFILE, 0, 0);
-      chmod(PAPFILE, S_IRUSR | S_IWUSR);      
+      chmod(PAPFILE, S_IRUSR | S_IWUSR);
     }
-    else 
+    else
     {
       messageCantOpenFile(PAPFILE);
       return false;
@@ -319,15 +356,14 @@
       {
         fprintf(stderr, "kISDN: Writing %s...\n", CHAPFILE);
 	
-        if (quote) fprintf(OutStream, "%c%s%c * %s\n", 34, acc->username().data(), 34, acc->password().data());	
-	else       fprintf(OutStream, "%s * %s\n", acc->username().data(), acc->password().data());
-        
+	fprintf(OutStream, "%s * %s\n", user.data(), pass.data());
+
 	fclose(OutStream);
-      
+
         chown(CHAPFILE, 0, 0);
-        chmod(CHAPFILE, S_IRUSR | S_IWUSR);      
+        chmod(CHAPFILE, S_IRUSR | S_IWUSR);
       }
-      else 
+      else
       {
         messageCantOpenFile(CHAPFILE);
         return false;
@@ -336,19 +372,19 @@
     else	// We don't need neither PAP nor CHAP so let's remove the secrets !
     {
       ::message("No authentication for this ISP");
-      
+
       if ((OutStream = fopen(PAPFILE, "w")) != 0)
       {
         fprintf(stderr, "kISDN: Deleting %s...\n", PAPFILE);
         fclose(OutStream);
       }
-      
+
       if ((OutStream = fopen(CHAPFILE, "w")) != 0)
       {
         fprintf(stderr, "kISDN: Deleting %s...\n", CHAPFILE);
         fclose(OutStream);
       }
-      
+
     }
   }
 
@@ -356,12 +392,12 @@
   {
     fprintf(stderr, "kISDN: Writing %s...\n", DNSFILE);
     fprintf(OutStream, "search %s\n", acc->domain().data());
-    
+
     if (acc->firstDNS() != 0L)
     {
       for (dns = acc->firstDNS(); dns != 0L; dns = acc->nextDNS())
         fprintf(OutStream, "nameserver %s\n", dns->string().data());
-          
+
       fclose(OutStream);
     }
     else
@@ -371,22 +407,21 @@
       return false;
     }
   }
-  else 
+  else
   {
     messageCantOpenFile(DNSFILE);
     return false;
   }
-  
+
   if ((OutStream = fopen(OPTFILE, "wb")) != 0)
   {
-    fprintf(stderr, "kISDN: Writing %s...\n", OPTFILE);    
-    
-    if (quote) fprintf(OutStream, "name %c%s%c\n", 34, acc->username().data(), 34);
-    else       fprintf(OutStream, "name %s\n", acc->username().data());
-      
+    fprintf(stderr, "kISDN: Writing %s...\n", OPTFILE);
+
+    fprintf(OutStream, "name %s\n", user.data());
+
     fclose(OutStream);
   }
-  else 
+  else
   {
     messageCantOpenFile(OPTFILE);
     return false;
@@ -398,14 +433,14 @@
 void Connection::deleteInterface(void)
 {
   netctrl->ifDown(condev);			
-  
+
   if (bundling)
   {
     isdnctrl->Unbind(condev);			// We don't need to shutdown the slave
     isdnctrl->Unbind(conslave);			// interface - the kernel doesn't know about it !
     isdnctrl->Delif(conslave);
   }
-  
+
   isdnctrl->Delif(condev);
 }
 
@@ -415,37 +450,37 @@
   if (encaps != PROTSYNC)
   {
     AccountData  *acc = ISDNData.currentAccount();
-    
+
     netctrl->ifPointToPoint(condev, acc->localIP().string().data(), acc->remoteIP().string().data());
     netctrl->ifSetFlag(condev, (IFF_UP | IFF_RUNNING));
     netctrl->routeAddHost(acc->remoteIP().string().data(), condev);
     netctrl->routeAddGateway(acc->remoteIP().string().data());
   }
-   
+
   // if (!isdnconfig->activeDoD()) isdnctrl->setDialMode(condev, ISDNCtrl::MANUAL);
 
-  isdnctrl->Dial(condev); 
+  isdnctrl->Dial(condev);
 }
 
 
 void  Connection::hangUp(void)
 {
-  isdnctrl->Hangup(condev); 
-  
+  isdnctrl->Hangup(condev);
+
   // if (!isdnconfig->activeDoD()) isdnctrl->setDialMode(condev, ISDNCtrl::OFF);
 
   if (netctrl->routeHaveDefault(condev)) netctrl->routeDelete("0.0.0.0");
 }
 
 
-/* 
- * Error message boxes 
+/*
+ * Error message boxes
  ***********************/
 
 void  Connection::messageCantOpenFile(const char *fname)
 {
   char buffer[128];
-  
+
   sprintf(buffer, "Can't open file\n%s !\n\n", fname);
   QMessageBox::warning(this, i18n("I/O Error"), buffer, "OK", 0);
 }
@@ -454,10 +489,10 @@
 void  Connection::messageNoDNSSupplied(void)
 {
   QString tmp;
-  
+
   tmp  = i18n("You forgot to specify a\n");
   tmp += i18n("nameserver for this ISP\n\n");
-  
+
   QMessageBox::warning(this, i18n("Can't connect"), tmp, "Ok", 0);
 }
 
