Changed separators to constants, added set,get unique and set,get separator
This commit is contained in:
parent
7bef10a2a5
commit
d420db9d09
12
README.md
12
README.md
|
@ -13,12 +13,18 @@ composer require sikofitt/generate-mac
|
|||
use Sikofitt\GenerateMac\Mac;
|
||||
|
||||
$mac = new Mac(); // default is ':'
|
||||
// or
|
||||
$mac->setSeparator(':');
|
||||
$address = $mac->getAddress(); // ab:cd:ef:01:23:45
|
||||
|
||||
$mac = new Mac('-');
|
||||
// or
|
||||
$mac->setSeparator('-');
|
||||
$address = $mac->getAddress(); // ab-cd-ef-01-23-45
|
||||
|
||||
$mac = new Mac('');
|
||||
// or
|
||||
$mac->setSeparator('');
|
||||
$address = $mac->getAddress(); // abcdef012345
|
||||
```
|
||||
|
||||
|
@ -26,6 +32,9 @@ If you don't care that it is unique you can remove the check for private mac pre
|
|||
|
||||
```php
|
||||
$mac = new Mac(':', false);
|
||||
// or
|
||||
$mac->setUnique(false);
|
||||
|
||||
$address = $mac->getAddress();
|
||||
|
||||
// '52:54:00:ab:cd:ef', QEMU virtual NIC prefix 52:54:00
|
||||
|
@ -51,6 +60,9 @@ var_dump($addresses);
|
|||
* 9 => '32:73:c0:b3:62:27',
|
||||
* );
|
||||
*/
|
||||
|
||||
// if you call this with 1 as the count it will still
|
||||
// return an array [0 => '32:73:c0:b3:62:27']
|
||||
```
|
||||
|
||||
#### Test
|
||||
|
|
|
@ -21,12 +21,15 @@ namespace Sikofitt\GenerateMac\Command;
|
|||
|
||||
use Sikofitt\GenerateMac\Mac;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Exception\{
|
||||
InvalidArgumentException,
|
||||
RuntimeException
|
||||
};
|
||||
use Symfony\Component\Console\Input\{
|
||||
InputInterface,
|
||||
InputOption
|
||||
};
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
|
@ -41,7 +44,7 @@ class GenerateMacCommand extends Command
|
|||
->addOption('separator', 's', InputOption::VALUE_REQUIRED, 'The separator to use for mac addresses.')
|
||||
;
|
||||
|
||||
parent::configure(); // TODO: Change the autogenerated stub
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +52,7 @@ class GenerateMacCommand extends Command
|
|||
* @param \Symfony\Component\Console\Output\OutputInterface $output
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
|
@ -58,6 +61,7 @@ class GenerateMacCommand extends Command
|
|||
if ($count <= 0) {
|
||||
throw new RuntimeException('$count should be a positive number greater than zero.');
|
||||
}
|
||||
|
||||
$separator = strtolower($input->getOption('separator') ?? 'colon');
|
||||
|
||||
if (!\in_array($separator, ['colon','none','dash'], true)) {
|
||||
|
@ -67,19 +71,22 @@ class GenerateMacCommand extends Command
|
|||
$outputFormat = strtolower($input->getOption('output') ?? 'string');
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
switch ($separator) {
|
||||
case 'colon':
|
||||
default:
|
||||
$separator = ':';
|
||||
$separator = Mac::SEPARATOR_COLON;
|
||||
break;
|
||||
case 'none':
|
||||
$separator = '';
|
||||
$separator = Mac::SEPARATOR_NONE;
|
||||
break;
|
||||
case 'dash':
|
||||
$separator = '-';
|
||||
$separator = Mac::SEPARATOR_DASH;
|
||||
break;
|
||||
}
|
||||
|
||||
$mac = new Mac($separator);
|
||||
|
||||
$macAddresses = $mac->getMacAddresses($count);
|
||||
|
||||
switch ($outputFormat) {
|
||||
|
@ -93,7 +100,7 @@ class GenerateMacCommand extends Command
|
|||
$io->writeln(\json_encode($result, JSON_PRETTY_PRINT));
|
||||
break;
|
||||
case 'plain':
|
||||
$io->writeln($macAddresses);
|
||||
$io->writeln($macAddresses, SymfonyStyle::OUTPUT_PLAIN | SymfonyStyle::VERBOSITY_NORMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,21 +21,25 @@ namespace Sikofitt\GenerateMac;
|
|||
|
||||
class Mac
|
||||
{
|
||||
/**
|
||||
* Private mac address prefixes that are used
|
||||
* internally or with virtual machines and containers.
|
||||
*/
|
||||
private const UNAVAILABLE_LOCAL_PREFIXES = [
|
||||
'02bb01', // Octothorpe
|
||||
'02aa3c', // Olivetti Telecomm SPA (olteco)
|
||||
'02608c', // 3com
|
||||
'027001', // Racal-datacom
|
||||
'021c7c', //Perq Systems
|
||||
'02e6d3', //Nixdorf Computer
|
||||
'020701', //Racal-datacom
|
||||
'029d8e', //Cardiac Recorders
|
||||
'0270b3', //Data Recall
|
||||
'02cf1c', //Communication Machinery
|
||||
'02c08c', //3com
|
||||
'0270b0', //M/a-com Companies
|
||||
'026086', //Logic Replacement TECH.
|
||||
'525400', //QEMU virtual NIC
|
||||
'021c7c', // Perq Systems
|
||||
'02e6d3', // Nixdorf Computer
|
||||
'020701', // Racal-datacom
|
||||
'029d8e', // Cardiac Recorders
|
||||
'0270b3', // Data Recall
|
||||
'02cf1c', // Communication Machinery
|
||||
'02c08c', // 3com
|
||||
'0270b0', // M/a-com Companies
|
||||
'026086', // Logic Replacement TECH.
|
||||
'525400', // QEMU virtual NIC
|
||||
'aa0000', // Digital Equipment
|
||||
'aa0001', // Digital Equipment
|
||||
'aa0002', // Digital Equipment
|
||||
|
@ -44,42 +48,46 @@ class Mac
|
|||
'deadca', // PearPC virtual NIC
|
||||
];
|
||||
|
||||
/**
|
||||
* Reserved mac prefixes for private devices.
|
||||
*/
|
||||
private const AVAILABLE_PREFIXES = [
|
||||
'x2xxxx',
|
||||
'x6xxxx',
|
||||
'xaxxxx',
|
||||
'xaxxxx',
|
||||
'xexxxx',
|
||||
];
|
||||
|
||||
public const SEPARATOR_COLON = 0;
|
||||
public const SEPARATOR_DASH = 1;
|
||||
public const SEPARATOR_NONE = 2;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @internal
|
||||
* @var bool For testing that we get a prefix that is not used.
|
||||
*/
|
||||
protected $isTest = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var int The mac address separator, can be self::SEPARATOR_*
|
||||
*/
|
||||
private $separator;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var bool If we care if we get an already used prefix or not.
|
||||
*/
|
||||
private $unique;
|
||||
|
||||
/**
|
||||
* Mac constructor.
|
||||
*
|
||||
* @param string $separator
|
||||
* @param bool $unique
|
||||
* @param int $separator The mac address separator, one of ':', '-', or ''
|
||||
* @param bool $unique Whether or not we care if we get a non unique prefix.
|
||||
*/
|
||||
public function __construct(string $separator = ':', bool $unique = true)
|
||||
public function __construct(int $separator = self::SEPARATOR_COLON, bool $unique = true)
|
||||
{
|
||||
if (!\in_array($separator, [':', '', '-'], true)) {
|
||||
throw new \InvalidArgumentException('Separator is invalid. Acceptable values: ":", "-", or ""');
|
||||
}
|
||||
|
||||
$this->unique = $unique;
|
||||
$this->separator = $separator;
|
||||
$this->setUnique($unique);
|
||||
$this->setSeparator($separator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,7 +103,7 @@ class Mac
|
|||
$prefix = '02bb01';
|
||||
}
|
||||
|
||||
if ($this->unique) {
|
||||
if ($this->getUnique()) {
|
||||
while ($this->isTaken($prefix)) {
|
||||
$prefix = $this->generateString($template);
|
||||
}
|
||||
|
@ -107,7 +115,9 @@ class Mac
|
|||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
* Note: if count is 1 it will still be returned as an array. [0 => $macAddress]
|
||||
*
|
||||
* @param int $count The number of mac addresses to generate.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return array
|
||||
|
@ -124,7 +134,53 @@ class Mac
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
* @param bool $unique
|
||||
*
|
||||
* @return \Sikofitt\GenerateMac\Mac
|
||||
*/
|
||||
public function setUnique(bool $unique = true): Mac
|
||||
{
|
||||
$this->unique = $unique;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getUnique(): bool
|
||||
{
|
||||
return $this->unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $separator
|
||||
*
|
||||
* @return \Sikofitt\GenerateMac\Mac
|
||||
*/
|
||||
public function setSeparator(int $separator): Mac
|
||||
{
|
||||
if (!\in_array($separator, [self::SEPARATOR_COLON, self::SEPARATOR_DASH, self::SEPARATOR_NONE], true)) {
|
||||
throw new \InvalidArgumentException('Separator is invalid. Acceptable values: ":", "-", or ""');
|
||||
}
|
||||
|
||||
$this->separator = $separator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSeparator(): int
|
||||
{
|
||||
return $this->separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if we have a unique prefix.
|
||||
*
|
||||
* @param string $prefix The current prefix.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -134,12 +190,14 @@ class Mac
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $template
|
||||
* Generates a string
|
||||
*
|
||||
* @param string $template The template to use xexxxx.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return mixed|string
|
||||
* @return string
|
||||
*/
|
||||
private function generateString(string $template)
|
||||
private function generateString(string $template): string
|
||||
{
|
||||
$bytes = sodium_bin2hex(\random_bytes(32));
|
||||
|
||||
|
@ -161,13 +219,29 @@ class Mac
|
|||
return \current($prefixes);
|
||||
}
|
||||
|
||||
private function getSeparatorAsString(): string
|
||||
{
|
||||
switch($this->getSeparator()) {
|
||||
default:
|
||||
case self::SEPARATOR_COLON:
|
||||
return ':';
|
||||
case self::SEPARATOR_DASH:
|
||||
return '-';
|
||||
case self::SEPARATOR_NONE:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the chosen separator.
|
||||
*
|
||||
* @param string $macAddress
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function insertSeparator(string $macAddress): string
|
||||
{
|
||||
return implode($this->separator, str_split($macAddress, 2));
|
||||
|
||||
return implode($this->getSeparatorAsString(), str_split($macAddress, 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,10 +83,10 @@ class GenerateMacCommandTest extends TestCase
|
|||
$this->commandTester->execute(['--separator' => 'none', '--output' => 'plain']);
|
||||
|
||||
$output = $this->commandTester->getDisplay(true);
|
||||
// 13 because it adds a new line
|
||||
$this->assertSame(13, strlen($output));
|
||||
// 13 because it adds a new line with SymfonyStyle::writeLn();
|
||||
$this->assertSame(13, \strlen($output));
|
||||
// just to make sure trim it.
|
||||
$this->assertSame(12, strlen(trim($output)));
|
||||
$this->assertSame(12, \strlen(trim($output)));
|
||||
|
||||
$this->commandTester->execute(['--separator' => 'dash', '--output' => 'plain']);
|
||||
$output = $this->commandTester->getDisplay();
|
||||
|
|
|
@ -40,12 +40,20 @@ class MacTest extends TestCase
|
|||
}
|
||||
|
||||
$this->assertRegExp(self::REGEX, $mac->getMacAddress());
|
||||
$this->assertSame(Mac::SEPARATOR_COLON, $mac->getSeparator());
|
||||
$this->assertTrue($mac->getUnique());
|
||||
}
|
||||
|
||||
public function testSeparator(): void
|
||||
{
|
||||
$mac = new Mac('-');
|
||||
$mac = new Mac(Mac::SEPARATOR_DASH);
|
||||
|
||||
$this->assertSame(Mac::SEPARATOR_DASH, $mac->getSeparator());
|
||||
$this->assertRegExp(self::REGEX, $mac->getMacAddress());
|
||||
$mac->setSeparator(Mac::SEPARATOR_COLON);
|
||||
$this->assertSame(Mac::SEPARATOR_COLON, $mac->getSeparator());
|
||||
$this->assertRegExp(self::REGEX, $mac->getMacAddress());
|
||||
$this->assertNotFalse(strpos($mac->getMacAddress(), ':'));
|
||||
}
|
||||
|
||||
public function testUnique(): void
|
||||
|
@ -53,14 +61,17 @@ class MacTest extends TestCase
|
|||
$class = new class extends Mac {
|
||||
protected $isTest = true;
|
||||
};
|
||||
$this->assertTrue($class->getUnique());
|
||||
|
||||
$macAddress = $class->getMacAddress();
|
||||
$this->assertStringStartsNotWith(self::NON_UNIQ_PREFIX, $macAddress);
|
||||
$class->setUnique(false);
|
||||
$this->assertFalse($class->getUnique());
|
||||
}
|
||||
|
||||
public function testThrowsOnInvalidPrefix(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$mac = new Mac('_');
|
||||
$mac = new Mac(4);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue