From d27648753dde7add9395a02d7dac181bf0ac536b Mon Sep 17 00:00:00 2001 From: Stu Tomlinson Date: Fri, 29 Dec 2023 11:48:52 +0000 Subject: [PATCH] Validate MAC EUI versions Postgres 'macaddr' field only accepts EUI-48 addresses, restrict MACAddressField to the same. Also fix conversion from EUI-48 to EUI-64/MACAddress8Field --- netfields/fields.py | 9 +++++++-- netfields/forms.py | 9 +++++++-- netfields/rest_framework.py | 9 +++++++-- test/tests/test_form_fields.py | 9 +++++++++ test/tests/test_functions.py | 6 +++--- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/netfields/fields.py b/netfields/fields.py index bae7b6e..e09630d 100644 --- a/netfields/fields.py +++ b/netfields/fields.py @@ -194,7 +194,7 @@ def to_python(self, value): return value try: - return EUI(value, dialect=mac_unix_common) + return EUI(value, version=48, dialect=mac_unix_common) except (AddrFormatError, IndexError, TypeError) as e: raise ValidationError(e) @@ -240,7 +240,12 @@ def to_python(self, value): return value try: - return EUI(value, dialect=mac_eui64) + mac = EUI(value, dialect=mac_eui64) + if mac.version == 64: + return mac + mac = mac.eui64() + mac.dialect = mac_eui64 + return mac except (AddrFormatError, IndexError, TypeError) as e: raise ValidationError(e) diff --git a/netfields/forms.py b/netfields/forms.py index 8db6716..2f0a223 100644 --- a/netfields/forms.py +++ b/netfields/forms.py @@ -107,7 +107,7 @@ def to_python(self, value): value = value.strip() try: - return EUI(value, dialect=mac_unix_common) + return EUI(value, version=48, dialect=mac_unix_common) except (AddrFormatError, IndexError, TypeError): raise ValidationError(self.error_messages['invalid']) @@ -136,7 +136,12 @@ def to_python(self, value): value = value.strip() try: - return EUI(value, dialect=mac_eui64) + mac = EUI(value, dialect=mac_eui64) + if mac.version == 64: + return mac + mac = mac.eui64() + mac.dialect = mac_eui64 + return mac except (AddrFormatError, IndexError, TypeError): raise ValidationError(self.error_messages['invalid']) diff --git a/netfields/rest_framework.py b/netfields/rest_framework.py index bfce87f..5ca42c0 100644 --- a/netfields/rest_framework.py +++ b/netfields/rest_framework.py @@ -73,7 +73,7 @@ def to_internal_value(self, data): if data is None: return data try: - return EUI(data, dialect=mac_unix_common) + return EUI(data, version=48, dialect=mac_unix_common) except (AddrFormatError, IndexError, TypeError): self.fail('invalid') @@ -92,7 +92,12 @@ def to_internal_value(self, data): if data is None: return data try: - return EUI(data, dialect=mac_eui64) + mac = EUI(data, dialect=mac_eui64) + if mac.version == 64: + return mac + mac = mac.eui64() + mac.dialect = mac_eui64 + return mac except (AddrFormatError, IndexError, TypeError): self.fail('invalid') diff --git a/test/tests/test_form_fields.py b/test/tests/test_form_fields.py index 93a1f06..13d2b30 100644 --- a/test/tests/test_form_fields.py +++ b/test/tests/test_form_fields.py @@ -225,6 +225,10 @@ def test_strip(self): self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['field'], self.mac) + def test_eui64(self): + form = MacAddressTestModelForm({'field': '00-AA-2B-C3-DD-44-EE-55'}) + self.assertFalse(form.is_valid()) + def test_invalid(self): form = MacAddressTestModelForm({'field': 'notvalid'}) self.assertFalse(form.is_valid()) @@ -275,6 +279,11 @@ def test_strip(self): self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['field'], self.mac) + def test_eui48(self): + form = MacAddress8TestModelForm({'field': '00:aa:2b:c3:dd:44'}) + self.assertTrue(form.is_valid()) + self.assertEqual(form.cleaned_data['field'], EUI('00:aa:2b:ff:fe:c3:dd:44', dialect=mac_eui64)) + def test_invalid(self): form = MacAddress8TestModelForm({'field': 'notvalid'}) self.assertFalse(form.is_valid()) diff --git a/test/tests/test_functions.py b/test/tests/test_functions.py index 9894d43..da30b36 100644 --- a/test/tests/test_functions.py +++ b/test/tests/test_functions.py @@ -253,15 +253,15 @@ def test_read_me_example(self): class TestMacFieldFunctions(TestCase): def setUp(self): - MACTestModel.objects.create(field='aa:bb:cc:dd:ee:ff') + MACTestModel.objects.create(field='88:bb:cc:dd:ee:ff') def test_trunc(self): qs = MACTestModel.objects.annotate(trunc=Trunc(F('field'))) - self.assertEqual(qs[0].trunc, EUI('aa:bb:cc:00:00:00')) + self.assertEqual(qs[0].trunc, EUI('88:bb:cc:00:00:00')) def test_macaddr8_to7bit(self): qs = MACTestModel.objects.annotate(eui64=Macaddr8Set7bit(F('field'))) - self.assertEqual(qs[0].eui64, EUI('aa:bb:cc:ff:fe:dd:ee:ff')) + self.assertEqual(qs[0].eui64, EUI('8a:bb:cc:ff:fe:dd:ee:ff')) class TestMac8FieldFunctions(TestCase):