classification
Title: ipaddress: increment/decrement on IPv*Interface disregards bitmask prefix
Type: Stage:
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: katsel
Priority: normal Keywords:

Created on 2021-04-30 11:15 by katsel, last changed 2021-04-30 11:15 by katsel.

Messages (1)
msg392417 - (view) Author: Kat Hoessel (katsel) Date: 2021-04-30 11:15
IPv4 and IPv6 interface objects of the `ipaddress` library show unexpected behaviour when arithmetic operators like + (increment) and - (decrement) are run on them.


`ipaddress` interfaces can be incremented/decremented, similar to IP addresses.
Currently, there are two problems with how these operations are implemented for interfaces within this library.
This applies to both IPv4 and IPv6, and may yield incorrect and inconsistent results.


1. Increment/decrement on an interface overrides subnet prefix length

The resulting interface will always have a prefix length of /32 for IPv4, /128 for IPv6, regardless of the original interface prefix. (See iPython code examples below.)
This behaviour is incomprehensible and unexpected.


2. Increment/decrement on an interface does not respect subnet arithmetic

For example,

    ipaddress.ip_interface('10.0.0.1/24') + 255

has no valid result under subnet arithmetic.
`ipaddress` however, incorrectly returns

    IPv4Interface('10.0.1.0/32')


It is likely that the behaviour seen in 2) logically follows after 1).
Both are assumedly related to the fact that IPv*Interface is a subclass of IPv*Address with inherited properties.


To achieve consistent behaviour for interfaces under +/-, I would suggest to either

  a) make sure that +/- operators on interfaces preserve the prefix and respect subnet arithmetic, or
  b) forbid +/- operators on interfaces.

My preferred solution would be a). I would be interested in providing a patch, given that the observed behaviour is confirmed as a bug.


----------------------------------------------------------------
### IPv4

In [1]: import ipaddress

In [2]: iff = ipaddress.ip_interface('10.0.0.1/24')

In [3]: iff
Out[3]: IPv4Interface('10.0.0.1/24')

In [4]: iff1 = iff + 1

In [5]: iff1
Out[5]: IPv4Interface('10.0.0.2/32')

In [6]: iff.network.prefixlen
Out[6]: 24

In [7]: iff1.network.prefixlen
Out[7]: 32

### overflow

In [8]: iff + 255  # this should not work
Out[8]: IPv4Interface('10.0.1.0/32')

### IPv6

In [9]: iff = ipaddress.ip_interface('1:1:1:2::1/64')

In [10]: iff
Out[10]: IPv6Interface('1:1:1:2::1/64')

In [11]: iff + 1
Out[11]: IPv6Interface('1:1:1:2::2/128')

### version information

In [12]: import sys

In [13]: sys.version
Out[13]: '3.8.3 (default, Aug 31 2020, 16:03:14) \n[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]'
History
Date User Action Args
2021-04-30 11:15:38katselcreate