  /*

  knetfilter v 1.2.2

  Copyright (C) 2000 Luigi Genoni
  		     venom@DarkStar.sns.it
  */
  

#include <qlayout.h>
#include <qmultilinedit.h>
#include <qkeycode.h>
#include <qbuttongroup.h>
#include <qlabel.h>
#include <qstring.h>
#include <qstrlist.h>
#include <strings.h>

#include <kmsgbox.h>
#include <kiconloader.h>
#include <klocale.h>

#include "knat.h"


// interlaced facilities

// nat masquerade rules


void knetfilter::startmasqRules() {

    QString intranetwork, intranet, intramask, extranetwork, extranet, extramask, masqpos, extrainterface, masqsport, masqdport, masqicmp;

    // let's do some check
    intranetwork.sprintf((const char *)(firstmasqNet->text()));
    intramask.sprintf((const char *)(firstmasqNetMask->text()));
    extranetwork.sprintf((const char *)(secondmasqNet->text()));
    extramask.sprintf((const char *)(secondmasqNetMask->text()));
    masqsport.sprintf((const char *)(masqSPortNumber->text()));
    masqdport.sprintf((const char *)(masqDPortNumber->text()));
    masqicmp.sprintf((const char *)(masqSPortNumber->text()));

    //    if(intramask.length()==0)
    //      {
    //	intramask.sprintf("255.255.255.255");
    //      }

    //    if(extramask.length()==0)
    //      {
    //	extramask.sprintf("255.255.255.255");
    //      }

    intranet.sprintf("%s/%s",(const char *)(intranetwork), (const char *)(intramask));
    extranet.sprintf("%s/%s",(const char *)(extranetwork), (const char *)(extramask));

    masqon.clearArguments();
    
    //    if(intranetwork.length()==0)
    //      {
    //	intranet.sprintf("0.0.0.0/0");
    //      }

    if(extranetwork.length()==0)
      {
	extranet.sprintf("0.0.0.0/0");
	extramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(firstmasqNet->text())),"0.0.0.0")==0)
      {
	intranet.sprintf("0.0.0.0/0");	
	intramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(secondmasqNet->text())),"0.0.0.0")==0)
      {
	extranet.sprintf("0.0.0.0/0");	
	extramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(masqSPortNumber->text())),"all")==0)
      {
	masqsport.sprintf(":");
      }

    if(strcmp(((const char *)(masqDPortNumber->text())),"all")==0)
      {
	masqdport.sprintf(":");
      }

    if (masqsport.length()==0)
      {
	masqsport.sprintf(":");
      }

    if (masqdport.length()==0)
      {
	masqdport.sprintf(":");
      }
    

    masqpos.sprintf((const char *)(addmasqRuleNumber->text()));
    if(masqpos.length()==0)
      {
	masqruleaction="-A";
	masqpos.sprintf("-v");
      }
    else
      {
	masqruleaction="-I";
      }

    char interfaceChoicem[5];
    strcpy( interfaceChoicem, masqinterfaceChoice );
    interfaceChoicemasq = strcat ( interfaceChoicem, masqinterfacenrChoicedmp); 

    extrainterface.sprintf(interfaceChoicemasq);
    if(extrainterface.length()<3)
      {
	QMessageBox::critical(0, "Error",
			      "Please, you have to select the extranet interface.\n");
      }
    else if(intranetwork.length()==0)
      {
	QMessageBox::critical(0, "Error",
			      "You have to supply an Intranet IP address,\n"
			      "and a Netmask address for Networks.\n");
      }
    else if(intramask.length()==0)
      {
	QMessageBox::critical(0, "Error",
			      "You have to supply an Intranet Netmask address.\n");
      }
    else if(extramask.length()==0)
      {
	QMessageBox::critical(0, "Error",
			      "You have to supply an Extranet Netmask address.\n");
      }
    else
      {
	if(strcmp(masqprotocolChoice,"icmp") != 0)
	  {
	    if(strcmp(masqprotocolChoice,"all") == 0)
	      {
		masqon << "iptables" << "-t" << "nat" << masqruleaction << "POSTROUTING" << masqpos << "-p" << masqprotocolChoice << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
	      }
	    else
	      {
		masqon << "iptables" << "-t" << "nat" << masqruleaction << "POSTROUTING" << masqpos << "-p" << masqprotocolChoice << "--sport" << masqsport << "--dport" << masqdport << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
	      }
	  }
	else
	  {
	    if(strcmp(((const char *)(masqSPortNumber->text())),"all")==0 || (masqsport.length()==0))
	      {
		masqon << "iptables" << "-t" << "nat" << masqruleaction << "POSTROUTING" << masqpos << "-p" << masqprotocolChoice << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
	      }
	    else
	      {
		masqon << "iptables" << "-t" << "nat" << masqruleaction << "POSTROUTING" << masqpos << "-p" << masqprotocolChoice << "--icmp-type" << masqsport << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
	      }
	  }
      };
    
    bool success=masqon.start();
    if (success)
      statusbar->message(i18n("Running..."),2000);
    else
      statusbar->message(i18n("Couldn't start iptables"), 2000);
    
    
  };

// masquerade log facilities
void knetfilter::masqonDone() {

  if (masqon.normalExit() && (masqon.exitStatus()==0)) {
    statusbar->message(i18n("Masquerading turned on"), 2000);
    QString msg;
    msg.sprintf("Allow %s protocol outgoing",masqprotocolChoice);
    messageLog->insertItem(msg);
    firstmasqNet->clear();
    firstmasqNetMask->setText("255.255.255.0");
    secondmasqNet->setText("0.0.0.0");
    secondmasqNetMask->setText("0.0.0.0");
    masqSPortNumber->setText("all");
    masqDPortNumber->setText("all");
    addmasqRuleNumber->clear();
  } else {
      statusbar->message(i18n("iptables died"), 2000);
    };
    firstmasqNet->setFocus();
    firstmasqNetMask->setFocus();
    secondmasqNet->setFocus();
    secondmasqNetMask->setFocus();
    masqSPortNumber->setFocus();
    masqDPortNumber->setFocus();
    addmasqRuleNumber->setFocus();

};

void knetfilter::stopmasqRules() {
    QString intranetwork, intranet, intramask, extranetwork, extranet, extramask, masqpos, extrainterface, masqsport, masqdport, masqicmp;

    // let's do some check
    intranetwork.sprintf((const char *)(firstmasqNet->text()));
    intramask.sprintf((const char *)(firstmasqNetMask->text()));
    extranetwork.sprintf((const char *)(secondmasqNet->text()));
    extramask.sprintf((const char *)(secondmasqNetMask->text()));
    masqsport.sprintf((const char *)(masqSPortNumber->text()));
    masqdport.sprintf((const char *)(masqDPortNumber->text()));
    masqicmp.sprintf((const char *)(masqSPortNumber->text()));


    //    if(intramask.length()==0)
    //      {
    //	intramask.sprintf("255.255.255.255");
    //      }

    //    if(extramask.length()==0)
    //      {
    //	extramask.sprintf("255.255.255.255");
    //      }

    intranet.sprintf("%s/%s",(const char *)(intranetwork), (const char *)(intramask));
    extranet.sprintf("%s/%s",(const char *)(extranetwork), (const char *)(extramask));

    masqoff.clearArguments();
    
    //    if(intranetwork.length()==0)
    //      {
    //	intranet.sprintf("0.0.0.0/0");
    //      }

    if(extranetwork.length()==0)
      {
	extranet.sprintf("0.0.0.0/0");
	extramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(firstmasqNet->text())),"0.0.0.0")==0)
      {
	intranet.sprintf("0.0.0.0/0");	
	intramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(secondmasqNet->text())),"0.0.0.0")==0)
      {
	extranet.sprintf("0.0.0.0/0");	
	extramask.sprintf("0.0.0.0");
      }

    if(strcmp(((const char *)(masqSPortNumber->text())),"all")==0)
      {
	masqsport.sprintf(":");
      }

    if(strcmp(((const char *)(masqDPortNumber->text())),"all")==0)
      {
	masqdport.sprintf(":");
      }

    if (masqsport.length()==0)
      {
	masqsport.sprintf(":");
      }

    if (masqdport.length()==0)
      {
	masqdport.sprintf(":");
      }
    

    masqpos.sprintf((const char *)(addmasqRuleNumber->text()));

    if(masqpos.length()!=0)
      {
	masqoff << "iptables" << "-t" << "nat" <<"-D" << "POSTROUTING" << masqpos;
      }
    else
      {
	char interfaceChoicem[5];
	strcpy( interfaceChoicem, masqinterfaceChoice );
	interfaceChoicemasq = strcat ( interfaceChoicem, masqinterfacenrChoicedmp); 
	
	extrainterface.sprintf(interfaceChoicemasq);
	if(extrainterface.length()<3)
	  {
	    QMessageBox::critical(0, "Error",
				  "Please, you have to select the extranet interface.\n");
	  }
	else if(intranetwork.length()==0)
	  {
	    QMessageBox::critical(0, "Error",
				  "You have to supply an Intranet IP address,\n"
				  "and a Netmask address for networks.\n");
	  }
	else if(intramask.length()==0)
	  {
	    QMessageBox::critical(0, "Error",
				  "You have to supply an Intranet Netmask address.\n");
	  }
	else if(extramask.length()==0)
	  {
	    QMessageBox::critical(0, "Error",
				  "You have to supply an Extranet Netmask address.\n");
      }
	else
	  {
	    if(strcmp(masqprotocolChoice,"icmp") != 0)
	      {
		if(strcmp(masqprotocolChoice,"all") == 0)
		  {
		    masqoff << "iptables" << "-t" << "nat" << "-D" << "POSTROUTING" << "-p" << masqprotocolChoice << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
		  }
		else
		  {
		    masqoff << "iptables" << "-t" << "nat" << "-D"  << "POSTROUTING" << "-p" << masqprotocolChoice << "--sport" << masqsport << "--dport" << masqdport << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
		  }
	      }
	    else
	      {
		if(strcmp(((const char *)(masqSPortNumber->text())),"all")==0 || (masqsport.length()==0))
		  {
		    masqoff << "iptables" << "-t" << "nat" << "-D" << "POSTROUTING" << "-p" << masqprotocolChoice << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
		  }
		else
		  {
		    masqoff << "iptables" << "-t" << "nat" << "-D" << "POSTROUTING" << "-p" << masqprotocolChoice << "--icmp-type" << masqsport << "-s" << intranet << "-d" << extranet << "-o" << interfaceChoicemasq << "-j" << "MASQUERADE";
		  }
	      }
	  }
      };
    
    bool success=masqoff.start();
    if (success)
      statusbar->message(i18n("Running..."),2000);
    else
      statusbar->message(i18n("Couldn't start iptables"), 2000);
    

};

void knetfilter::masqoffDone() {
  
  if (masqoff.normalExit() && (masqoff.exitStatus()==0)) {
    statusbar->message(i18n("Masquerade turned off"), 2000);
    QString msg;
    msg.sprintf("Deny %s protocol outgoing",masqprotocolChoice);
    messageLog->insertItem(msg);
    firstmasqNet->clear();
    firstmasqNetMask->setText("255.255.255.0");
    secondmasqNet->setText("0.0.0.0");
    secondmasqNetMask->setText("0.0.0.0");
    masqSPortNumber->setText("all");
    masqDPortNumber->setText("all");
    addmasqRuleNumber->clear();
  } else {
      statusbar->message(i18n("iptables died"), 2000);
    };
    firstmasqNet->setFocus();
    firstmasqNetMask->setFocus();
    secondmasqNet->setFocus();
    secondmasqNetMask->setFocus();
    masqSPortNumber->setFocus();
    masqDPortNumber->setFocus();
    addmasqRuleNumber->setFocus();

};

void knetfilter::masqRules() {
  if ( masqWin == NULL )
    {
      
	  setupConnect();

      masqWin = new KNFWidget();
      masqWin->resize(640,310);
      masqWin->setCaption("Set Masquerade policy");

      QBoxLayout *top = new QBoxLayout(masqWin, QBoxLayout::LeftToRight, 10);
      QGridLayout *grid = new QGridLayout(10,10);
      top->addLayout(grid,10);
      
      QLabel *labelmasqProtocol = new QLabel(masqWin);
      labelmasqProtocol->setText("Protocol:");
      
      grid->addMultiCellWidget(labelmasqProtocol,1,1,1,2);

      masqprotocol = new QComboBox( FALSE, masqWin, "Protocol");
      masqprotocol->insertItem("ALL");
      masqprotocol->insertItem("TCP");
      masqprotocol->insertItem("UDP");
      masqprotocol->insertItem("ICMP");
      masqprotocol->setFixedHeight(masqprotocol->sizeHint().height());
      connect(masqprotocol,SIGNAL(activated(int)), SLOT(masqprotocolActivated(int)));
      grid->addMultiCellWidget(masqprotocol,1,1,3,4);


      QLabel *labelmasqSPort = new QLabel(masqWin);
      labelmasqSPort->setText("Source Port/Icmp Type:");
      masqSPortNumber = new QLineEdit(masqWin);
      masqSPortNumber->setFixedHeight(masqSPortNumber->sizeHint().height());

      masqSPortNumber->setText("all");
      
      grid->addMultiCellWidget(labelmasqSPort,1,1,5,7);
      grid->addMultiCellWidget(masqSPortNumber,1,1,8,9);

      QLabel *labelmasqDPort = new QLabel(masqWin);
      labelmasqDPort->setText("Destination Port:");
      masqDPortNumber = new QLineEdit(masqWin);
      masqDPortNumber->setFixedHeight(masqDPortNumber->sizeHint().height());

      masqDPortNumber->setText("all");
      
      grid->addMultiCellWidget(labelmasqDPort,2,2,5,7);
      grid->addMultiCellWidget(masqDPortNumber,2,2,8,9);

      QLabel *labelmasqRuleNumber = new QLabel(masqWin);
      labelmasqRuleNumber->setText("Rule Position:");
      addmasqRuleNumber = new QLineEdit(masqWin);
      addmasqRuleNumber->setFixedHeight(addmasqRuleNumber->sizeHint().height());
      addmasqRuleNumber->setText("");

      grid->addMultiCellWidget(labelmasqRuleNumber,8,8,6,7);
      grid->addMultiCellWidget(addmasqRuleNumber,8,8,8,9);
      
      QLabel *labelfirstmasqNet = new QLabel(masqWin);
      labelfirstmasqNet->setText("source address:");

      QLabel *labelfirstmasqNetMask = new QLabel(masqWin);
      labelfirstmasqNetMask->setText("netmask");

      grid->addMultiCellWidget(labelfirstmasqNet,3,3,0,2);
      grid->addMultiCellWidget(labelfirstmasqNetMask,3,3,5,6);

      firstmasqNet = new QLineEdit(masqWin);
      firstmasqNetMask = new QLineEdit(masqWin);
      
      firstmasqNet->setFixedHeight(firstmasqNet->sizeHint().height());
      firstmasqNetMask->setFixedHeight(firstmasqNetMask->sizeHint().height());

      grid->addMultiCellWidget(firstmasqNet,3,3,3,4);
      grid->addMultiCellWidget(firstmasqNetMask,3,3,7,8);

      firstmasqNet->setText("");
      firstmasqNetMask->setText("255.255.255.0");

      QLabel *labelsecondmasqNet = new QLabel(masqWin);
      labelsecondmasqNet->setText("destination address:");

      QLabel *labelsecondmasqNetMask = new QLabel(masqWin);
      labelsecondmasqNetMask->setText("netmask");


      grid->addMultiCellWidget(labelsecondmasqNet,4,4,0,2);
      grid->addMultiCellWidget(labelsecondmasqNetMask,4,4,5,6);

      secondmasqNet = new QLineEdit(masqWin);
      secondmasqNetMask = new QLineEdit(masqWin);

      secondmasqNet->setFixedHeight(secondmasqNet->sizeHint().height());
      secondmasqNetMask->setFixedHeight(secondmasqNetMask->sizeHint().height());

      grid->addMultiCellWidget(secondmasqNet,4,4,3,4);
      grid->addMultiCellWidget(secondmasqNetMask,4,4,7,8);

      secondmasqNet->setText("0.0.0.0");
      secondmasqNetMask->setText("0.0.0.0");

      QLabel *labelmasqInterface = new QLabel(masqWin);
      labelmasqInterface->setText("ExtraNet Interface:");
      grid->addMultiCellWidget(labelmasqInterface,6,6,0,2);
      
      masqinterface = new QComboBox( FALSE, masqWin, "interface");
      masqinterface->insertItem("eth");
      masqinterface->insertItem("tr");
      masqinterface->insertItem("bond");
      masqinterface->insertItem("lo");
      masqinterface->insertItem("slip");
      masqinterface->insertItem("plip");
      masqinterface->insertItem("ppp");
      masqinterface->insertItem("ippp");
      masqinterface->setFixedHeight(masqinterface->sizeHint().height());
      connect(masqinterface,SIGNAL(activated(int)), SLOT(masqinterfaceActivated(int)));
      grid->addMultiCellWidget(masqinterface,6,6,3,5);

      QLabel *labelwarnInterface = new QLabel(masqWin);
      labelwarnInterface->setText("BE SURE THIS TO BE CORRECT");
      grid->addMultiCellWidget(labelwarnInterface,6,6,6,9);

      QLabel *labelmasqInterfacenr = new QLabel(masqWin);
      labelmasqInterfacenr->setText("Interface nr:");
      grid->addMultiCellWidget(labelmasqInterfacenr,7,7,0,1);
      
      masqinterfacenr = new QComboBox( FALSE, masqWin, "interface nr");
      masqinterfacenr->insertItem("0");
      masqinterfacenr->insertItem("1");
      masqinterfacenr->insertItem("2");
      masqinterfacenr->insertItem("3");
      masqinterfacenr->insertItem("4");
      masqinterfacenr->insertItem("5");
      masqinterfacenr->setFixedHeight(masqinterfacenr->sizeHint().height());
      connect(masqinterfacenr,SIGNAL(activated(int)), SLOT(masqinterfacenrActivated(int)));
      grid->addMultiCellWidget(masqinterfacenr,7,7,3,5);

      QLabel *labelwarn2Interface = new QLabel(masqWin);
      labelwarn2Interface->setText("OR NOTHING WILL WORK");
      grid->addMultiCellWidget(labelwarn2Interface,7,7,6,9);

      QPushButton *btnRules = new QPushButton(masqWin);
      btnRules->setText("Commit");
      btnRules->setFixedHeight(btnRules->sizeHint().height());
      connect(btnRules,SIGNAL(clicked()), this, SLOT(startmasqRules()));
      grid->addWidget(btnRules,9,1);

      QPushButton *btnDelRules = new QPushButton(masqWin);
      btnDelRules->setText("Delete");
      btnDelRules->setFixedHeight(btnRules->sizeHint().height());
      connect(btnDelRules,SIGNAL(clicked()), this, SLOT(stopmasqRules()));
      grid->addWidget(btnDelRules,9,3);

      QPushButton *btnClose = new QPushButton(masqWin);
      btnClose->setText("Close");
      btnClose->setFixedHeight(btnClose->sizeHint().height());
      connect(btnClose,SIGNAL(clicked()), this, SLOT(closemasqRules()));
      grid->addWidget(btnClose,9,6);
      
      masqWin->show();
      setView(masqWin);
    }
  else
    {
      if ( !masqWin->isVisible() )
	{
	  masqWin->show();
	}
      else
	{
	  QMessageBox::critical(0,"Warning", "Already Running\n");
	}
    }  
};


void knetfilter::setmasqRules(KProcess *, char *data, int len) {
  if (len<0)
    return;
  static QString remainder;
  QString list;

  char dst[len+1];
  memmove(dst,data,len);
  dst[len]=0;

  list=remainder+dst;
  QStrList lines;
  int index=0;
  int newindex=0;

  while (1)
  {
    newindex=list.find('\n',index);
    if(newindex==-1) {
      remainder=list.right(list.length()-index);
      break;
    } else {
      lines.append(list.mid(index,newindex-index));
      index=newindex+1;
    };
  };
};

void knetfilter::masqinterfaceActivated(int index) {
  switch(index) {
  default:
    masqinterfaceChoice = "eth";
  case 0:
    masqinterfaceChoice = "eth";
    break;
  case 1:
    masqinterfaceChoice = "tr";
    break;
  case 2:
    masqinterfaceChoice = "bond";
    break;
  case 3:
    masqinterfaceChoice = "lo";
    break;
  case 4:
    masqinterfaceChoice = "slip";
    break;
  case 5:
    masqinterfaceChoice = "plip";
    break;
  case 6:
    masqinterfaceChoice = "ppp";
    break;
  case 7:
    masqinterfaceChoice = "ippp";
    break;
  };
};

void knetfilter::masqinterfacenrActivated(int index) {
  switch(index) {
  default:
    masqinterfacenrChoice = 0;
    masqinterfacenrChoicedmp = "0";
  case 0:
    masqinterfacenrChoice = 0;
    masqinterfacenrChoicedmp = "0";
    break;
  case 1:
    masqinterfacenrChoice = 1;
    masqinterfacenrChoicedmp = "1";
    break;
  case 2:
    masqinterfacenrChoice = 2;
    masqinterfacenrChoicedmp = "2";
    break;
  case 3:
    masqinterfacenrChoice = 3;
    masqinterfacenrChoicedmp = "3";
    break;
  case 4:
    masqinterfacenrChoice = 4;
    interfacenrChoicedmp = "4";
    break;
  case 5:
    masqinterfacenrChoice = 5;
    masqinterfacenrChoicedmp = "5";
    break;
  };
};

void knetfilter::masqprotocolActivated(int index) {
  switch(index) {
  default:
    masqprotocolChoice = "all";
  case 0:
    masqprotocolChoice = "all";
    break;
  case 1:
    masqprotocolChoice= "tcp";
    break;
  case 2:
    masqprotocolChoice = "udp";
    break;
  case 3:
    masqprotocolChoice = "icmp";
    break;
  };
};

void knetfilter::closemasqRules() {

  masqWin->close();

};








