Basically, IPv4-mapped IPv6 addresses in the CIDR block ::ffff:0.0.0.0/104
are validated as invalid when unpack_ipv4=False, yet is valid when the
first IPv4 octet is non-zero or when unpack_ipv4=True.
--
Ticket URL: <https://code.djangoproject.com/ticket/26378>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: bshen (added)
* needs_better_patch: => 0
* component: Uncategorized => Database layer (models, ORM)
* needs_tests: => 0
* easy: 0 => 1
* needs_docs: => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:1>
Comment (by bshen):
Here's the paste dump in case the ticket goes older than the paste
expiration date:
{{{
# my.app.models
# Django==1.8.6
from django.db import models
class TestIPNoUnpack(models.Model):
ip = models.GenericIPAddressField(null=False, protocol='both',
unpack_ipv4=False)
class TestIPUnpack(models.Model):
ip = models.GenericIPAddressField(null=False, protocol='both',
unpack_ipv4=True)
> python manage.py shell
Python 2.7.6 (default, Sep 9 2014, 15:04:36)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: from my.app.models import TestIPNoUnpack, TestIPUnpack
In [2]: testipunpack = TestIPUnpack(ip='::ffff:0.0.0.0')
In [3]: testipunpack.clean_fields()
In [4]: testipunpack.ip
Out[4]: '0.0.0.0'
In [5]: testipnounpack = TestIPNoUnpack(ip='::ffff:0.0.0.0')
In [6]: testipnounpack.clean_fields()
---------------------------------------------------------------------------
ValidationError Traceback (most recent call
last)
<ipython-input-6-9a763f56e907> in <module>()
----> 1 testipnounpack.clean_fields()
.../lib/python2.7/site-packages/django/db/models/base.pyc in
clean_fields(self, exclude)
1194
1195 if errors:
-> 1196 raise ValidationError(errors)
1197
1198 @classmethod
ValidationError: {'ip': [u'Enter a valid IPv4 or IPv6 address.']}
In [7]: testipnounpack2 = TestIPNoUnpack(ip='::ffff:0.255.255.255')
In [8]: testipnounpack2.clean_fields()
---------------------------------------------------------------------------
ValidationError Traceback (most recent call
last)
<ipython-input-8-e228d0855286> in <module>()
----> 1 testipnounpack2.clean_fields()
.../lib/python2.7/site-packages/django/db/models/base.pyc in
clean_fields(self, exclude)
1194
1195 if errors:
-> 1196 raise ValidationError(errors)
1197
1198 @classmethod
ValidationError: {'ip': [u'Enter a valid IPv4 or IPv6 address.']}
In [9]: testipnounpack3 = TestIPNoUnpack(ip='::ffff:1.0.0.0')
In [10]: testipnounpack3.clean_fields()
In [11]: testipnounpack3.ip
Out[11]: '::ffff:1.0.0.0'
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:2>
Old description:
> https://dpaste.de/EMJa
>
> Basically, IPv4-mapped IPv6 addresses in the CIDR block
> ::ffff:0.0.0.0/104 are validated as invalid when unpack_ipv4=False, yet
> is valid when the first IPv4 octet is non-zero or when unpack_ipv4=True.
New description:
Basically, IPv4-mapped IPv6 addresses in the CIDR block ::ffff:0.0.0.0/104
are validated as invalid when unpack_ipv4=False, yet is valid when the
first IPv4 octet is non-zero or when unpack_ipv4=True.
{{{ #!python
In [3]: testipunpack.clean_fields()
In [10]: testipnounpack3.clean_fields()
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:3>
* owner: nobody => AmineYaiche
* status: new => assigned
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:4>
* Attachment "26378.diff" added.
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/6316 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:5>
Old description:
> Basically, IPv4-mapped IPv6 addresses in the CIDR block
> ::ffff:0.0.0.0/104 are validated as invalid when unpack_ipv4=False, yet
> is valid when the first IPv4 octet is non-zero or when unpack_ipv4=True.
>
New description:
Basically, IPv4-mapped IPv6 addresses in the CIDR block ::ffff:0.0.0.0/104
are validated as invalid when unpack_ipv4=False, yet is valid when the
first IPv4 octet is non-zero or when unpack_ipv4=True.
{{{ #!python
# my.app.models
# Django==1.8.6
from django.db import models
class TestIPNoUnpack(models.Model):
ip = models.GenericIPAddressField(null=False, protocol='both',
unpack_ipv4=False)
class TestIPUnpack(models.Model):
ip = models.GenericIPAddressField(null=False, protocol='both',
unpack_ipv4=True)
> python manage.py shell
In [1]: from my.app.models import TestIPNoUnpack, TestIPUnpack
In [2]: testipunpack = TestIPUnpack(ip='::ffff:0.0.0.0')
In [3]: testipunpack.clean_fields()
In [4]: testipunpack.ip
Out[4]: '0.0.0.0'
In [5]: testipnounpack = TestIPNoUnpack(ip='::ffff:0.0.0.0')
In [6]: testipnounpack.clean_fields()
ValidationError: {'ip': [u'Enter a valid IPv4 or IPv6 address.']}
In [7]: testipnounpack2 = TestIPNoUnpack(ip='::ffff:0.255.255.255')
In [8]: testipnounpack2.clean_fields()
ValidationError: {'ip': [u'Enter a valid IPv4 or IPv6 address.']}
In [9]: testipnounpack3 = TestIPNoUnpack(ip='::ffff:1.0.0.0')
In [10]: testipnounpack3.clean_fields()
In [11]: testipnounpack3.ip
Out[11]: '::ffff:1.0.0.0'
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:6>
Comment (by bshen):
Is this the actual desired behavior? I don't think we want to have mixed
IPv4 and IPv6 representation be invalid when unpack_ipv4 is False. Mixed
IPv4 and IPv6 is still valid IPv6. In fact, this would probably break
existing code written by others that depends on this functionality where
the first IPv4 octet is not 0.
Furthermore, it appears that root cause of the inconsistency is not
addressed, but rather a whole class of valid IPv6 addresses is now marked
invalid.
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:7>
Comment (by AmineYaiche):
You are completely right. My apologies for the inconvenience. I was
looking at the wrong problem.
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:8>
* Attachment "26378.1.diff" added.
Comment (by bshen):
This looks like the correct fix. Thanks for responding and fixing it
quickly!
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:9>
Comment (by timgraham):
Hi Amine, just wanted to mention for future reference that you don't need
to attach a patch here when you also send a pull request.
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:10>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:11>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"32c8e43ef1e859fa55af2f470a2a1120f51afabe" 32c8e43e]:
{{{
#!CommitTicketReference repository=""
revision="32c8e43ef1e859fa55af2f470a2a1120f51afabe"
Fixed #26378 -- Allowed a left byte of zero in mixed IPv4/IPv6 validation.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/26378#comment:12>