Add startup command

This commit is contained in:
James Gilliland 2022-03-04 20:02:36 -06:00
parent f3d785156f
commit 7289a45c39
4 changed files with 221 additions and 3 deletions

View file

@ -1,14 +1,14 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
// application.php
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use Pfatt\Commands\Monitor; use Pfatt\Commands\Monitor;
use Pfatt\Commands\Startup;
use Symfony\Component\Console\Application; use Symfony\Component\Console\Application;
$application = new Application(); $application = new Application();
$application->add(new Monitor()); $application->add(new Monitor());
// ... register commands $application->add(new Startup());
$application->run(); $application->run();

View file

@ -17,7 +17,8 @@
"require": { "require": {
"php": "~7.4", "php": "~7.4",
"psr/log": "^1.1", "psr/log": "^1.1",
"symfony/console": "^5.4" "symfony/console": "^5.4",
"symfony/process": "^5.4"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.4", "phpstan/phpstan": "^1.4",

79
src/Commands/Startup.php Normal file
View file

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Pfatt\Commands;
use Pfatt\Config;
use Pfatt\Logger;
use Pfatt\NgController;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
final class Startup extends Command
{
protected static $defaultName = 'startup';
protected static $defaultDescription = 'Setup initial connection';
protected Config $config;
protected Logger $logger;
protected NgController $ngControl;
protected function configure(): void
{
// @todo Inject these. Maybe with a factory or container.
$this->config = new Config('', '', '');
$this->logger = new Logger('pfatt-5268AC');
$this->ngControl = new NgController($this->logger);
}
/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
switch ($this->getVeriant()) {
case 'opnsense':
$kldload = function (string $mod): Process {
return new Process(['/sbin/kldload', '-nq', $mod]);
};
$this->logger->info('loading netgraph kernel modules...');
$kldload('netgraph')->mustRun();
$kldload('ng_ether')->mustRun();
$kldload('ng_etf')->mustRun();
$kldload('ng_vlan')->mustRun();
$kldload('ng_eiface')->mustRun();
$kldload('ng_one2many')->mustRun();
$this->logger->info('OK!');
break;
case 'pfsense':
default:
$attach = function (string $interface): Process {
return new Process(['/usr/local/bin/php', '-r', '"pfSense_ngctl_attach(\'.\', \'' . $interface . '\';"']);
};
$this->logger->info('attaching interfaces to ng_ether...');
$attach($this->config->getOntInterface())->mustRun();
$attach($this->config->getRgInterface())->mustRun();
$this->logger->info('OK!');
break;
}
$this->ngControl->createNodes(
$this->config->getOntInterface(),
$this->config->getRgInterface(),
$this->config->getRgEthernetMac()
);
return Command::SUCCESS;
}
/**
* @return string
*/
private function getVeriant(): string {
return 'opnsense';
}
}

View file

@ -46,6 +46,144 @@ class NgController implements LoggerAwareInterface
$this->logger->error('ERROR!'); $this->logger->error('ERROR!');
} }
/**
* Use ngctl to setup virtual connection.
*
* @todo are all the ifs reversed?
*
* @param string $ont
* ONT network connection interface.
* @param string $rg
* Residential Gateway network connection interface.
* @return int|void
* ...
*/
public function createNodes(string $ont, string $rg, string $rgMac) {
$this->logger->info('Building netgraph nodes.');
$this->logger->info(' creating ng_one2many...');
if (
$this->ngCtlRun("mkpeer $ont: one2many lower one")
&& $this->ngCtlRun("name $ont:lower o2m")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(' creating vlan node and interface...');
if (
$this->ngCtlRun('mkpeer o2m: vlan many0 downstream')
&& $this->ngCtlRun('name o2m:many0 vlan0')
&& $this->ngCtlRun('mkpeer vlan0: eiface vlan0 ether')
&& $this->ngCtlRun('msg vlan0: \'addfilter { vlan=0 hook="vlan0" }\'')
&& $this->ngCtlRun("msg ngeth0: set $rgMac")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" defining etf for $ont (ONT)...");
if (
$this->ngCtlRun('mkpeer o2m: etf many1 downstream')
&& $this->ngCtlRun('name o2m:many1 waneapfilter')
&& $this->ngCtlRun("connect waneapfilter: $ont: nomatch upper")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" defining etf for $rg (RG)...");
if (
$this->ngCtlRun("mkpeer $rg: etf lower downstream")
&& $this->ngCtlRun("name $rg:lower laneapfilter")
&& $this->ngCtlRun("connect laneapfilter: $rg: nomatch upper")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" bridging etf for $ont <-> $rg...");
if (
$this->ngCtlRun('connect waneapfilter: laneapfilter: eapout eapout')
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" defining filters for EAP traffic...");
if (
$this->ngCtlRun('msg waneapfilter: \'setfilter { matchhook="eapout" ethertype=0x888e }\'')
&& $this->ngCtlRun('msg laneapfilter: \'setfilter { matchhook="eapout" ethertype=0x888e }\'')
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" enabling one2many links...");
if (
$this->ngCtlRun('msg o2m: setconfig "{ xmitAlg=2 failAlg=1 enabledLinks=[ 1 1 ] }"')
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" removing waneapfilter:nomatch hook...");
if (
$this->ngCtlRun('rmhook waneapfilter: nomatch')
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" enabling $rg interface...");
if (
$this->ngCtlRun("$rg up")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" enabling $ont interface...");
if (
$this->ngCtlRun("$ont up")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info(" enabling promiscuous mode on $rg...");
if (
$this->ngCtlRun("$rg promisc")
) {
$this->logger->info('OK!');
} else {
$this->logger->error('ERROR!');
return 1;
}
$this->logger->info("ngeth0 should now be available to configure as your pfSense WAN");
$this->logger->info("Done");
return 0;
}
/** /**
* Check filter status. * Check filter status.
* *