This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ipaddress.IPv{4,6}Network.reverse_pointer is broken
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: bbayles, ekohl, forst, h.venev, jana, pmoody, python-dev, ronaldoussoren
Priority: normal Keywords: patch

Created on 2017-05-31 17:15 by h.venev, last changed 2022-04-11 14:58 by admin.

Pull Requests
URL Status Linked Edit
PR 3632 closed ekohl, 2017-09-17 22:50
PR 25371 open python-dev, 2021-04-12 19:24
PR 29011 open forst, 2021-10-17 17:27
Messages (8)
msg294854 - (view) Author: Hristo Venev (h.venev) * Date: 2017-05-31 17:15
`ipaddress.IPv4Network('127.0.0.0/16').reverse_pointer = '0/16.0.0.127.in-addr.arpa'` is definitely wrong. I think it should be '0.127.in-addr.arpa'.

A funnier case, `ipaddress.IPv6Network('2001:db8::/32').reverse_pointer = '2.3./.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa'`.

For the case where no single reverse pointer exists (e.g. `127.0.0.0/13`), I think it should be `None`.
msg302390 - (view) Author: Ewoud Kohl van Wijngaarden (ekohl) * Date: 2017-09-17 22:52
Today I ran into this as well. In the case of IPv6 it's simple to decide what should be returned but on the IPv4Network I disagree. My expectation would be the domain where I would make the reverse needed. That means for 127.0.0.0/13 it should be '127.in-addr.arpa'.

I implemented it this way in the linked PR but I'm open to other opinions.
msg311869 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2018-02-09 08:26
<https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.reverse_pointer> documents that this attribute contains the name of the DNS name that could be used to query for PTR record. 

That functionality is not well defined for a network object. It might therefore be better to just raise an exception for this attribute on network objects.
msg313675 - (view) Author: Ewoud Kohl van Wijngaarden (ekohl) * Date: 2018-03-12 18:16
It's interesting to note that neither IPv4Network[1] nor IPv4Network docs mention reverse_pointer. That means it could also remove them (which essentially also throws an exception) since they don't make sense for networks. It would be useful to have the described functionality under a better name.

[1]: https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Network
[2]: https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Network
msg313750 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2018-03-13 14:25
The "reverse_pointers" attribute is implicitly documented by this phrase in the introduction of network objects:

--
All attributes implemented by address objects are implemented by network objects as well.
--
msg390880 - (view) Author: jana (jana) Date: 2021-04-12 18:02
Running into the same problem here. Within the zonefile rfc1035 defines a usecase for ipv4, but I can't find anything similar for IPv6. The feature is also rather obscure. The zone however is used in the zonefile as origin and in bind in the named.conf to refer to which zone is managed where. 

For this you want to provide the reverse network address, minus the irrelevant zeros, so 192.168.0.0/24 => 0.168.192.in-addr.arpa and 2001:db8::/32 => 8.b.d.0.1.0.0.2.ip6.arpa

This would be to me a fitting and convenient interpretation of the function.
msg390884 - (view) Author: jana (jana) Date: 2021-04-12 18:37
This code does the trick:

ipn = ipaddress.ip_network("2a0c:ac10::/32")
prefix = ipn.prefixlen
if ipn.version == 6:
    rest = int((ipn.max_prefixlen - prefix) / 4)
elif ipn.version == 4:
    rest = int((ipn.max_prefixlen - prefix) / 8)
return ipn.network_address.reverse_pointer.split(".", rest)[-1]
msg404144 - (view) Author: Foster Snowhill (forst) * Date: 2021-10-17 17:38
I've stumbled upon this myself, and had a go at fixing it, before looking up this issue. My approach ended up being a bit different:

1. I rewrote the existing _reverse_pointer() methods, so that they'd handle both addresses and networks, instead of defining separate methods for the IPvXNetwork classes.
2. Trying to generate a reverse pointer for a prefix that doesn't align with the granularity of reverse pointers (8 bits for IPv4, 4 bits for IPv6) will raise an exception instead of returning a more general prefix.

I would like to bring up point 2 for discussion, since it differs from both of the other PRs submitted regarding this issue.

For example, let's take an example subnet 127.45.240.0/20. The other solutions here propose generating a reverse pointer like "45.127.in-addr.arpa", i.e. returning a reverse pointer to a bigger subnet that includes the original one. When you convert that reverse pointer back into a network, you get 127.45.0.0/16. It doesn't match the original network, thus you lose some information about it.

I'd like to propose to be more strict about it (or at least, make the strict behaviour an option) to avoid unintentional loss of precision when generating reverse pointers in these cases.
History
Date User Action Args
2022-04-11 14:58:47adminsetgithub: 74713
2021-10-17 17:38:56forstsetmessages: + msg404144
2021-10-17 17:27:15forstsetpull_requests: + pull_request27289
2021-10-13 21:47:51forstsetnosy: + forst
2021-04-12 19:24:19python-devsetnosy: + python-dev
pull_requests: + pull_request24104
2021-04-12 18:37:26janasetmessages: + msg390884
2021-04-12 18:02:00janasetnosy: + jana

messages: + msg390880
versions: + Python 3.7, - Python 3.5
2018-03-13 14:25:06ronaldoussorensetmessages: + msg313750
2018-03-13 13:47:33bbaylessetnosy: + bbayles
2018-03-12 18:16:08ekohlsetmessages: + msg313675
2018-02-09 08:26:56ronaldoussorensetnosy: + ronaldoussoren
messages: + msg311869
2018-02-04 19:47:52cheryl.sabellasetnosy: + pmoody
2017-09-17 22:52:00ekohlsetnosy: + ekohl
messages: + msg302390
2017-09-17 22:50:59ekohlsetkeywords: + patch
stage: patch review
pull_requests: + pull_request3621
2017-05-31 17:15:31h.venevcreate