IP Address Conversion¶
pcapkit.corekit.schema.ipaddress converts a caller-supplied IP address to an
ipaddress object, refusing a bool before ipaddress reads it as
an int (#491), for the IP address fields
(pcapkit.corekit.fields.ipaddress) and the protocols’ makers alike. It is one
of the pcapkit.corekit.schema helpers shared across the schema layer, not
part of the header schema framework in pcapkit.protocols.schema; see
Choosing Between utilities and corekit.
Added in version 1.6.0: Moved here from pcapkit.corekit.fields.ipaddress, with the guards the
IP address fields share (#2674).
Construction Helpers¶
- pcapkit.corekit.schema.ipaddress.parse_ip_address(value, description, version=None)[source]¶
Convert a caller-supplied address on the construction path.
- Parameters:
value (
IPv4Address|IPv6Address|bytes|int|str) – Address as the caller gave it – anipaddressobject, which is returned unchanged, or anythingipaddressaccepts.description (
str) – Human-readable description of whatvalueis, used to build theFieldValueErrormessage. Callers in a protocol should carry their usual context into it, e.g.f'{self.alias}: [OptNo {type}] care-of address'.version (
int|None) – IP version to demand,4or6, orNoneto take whichever familyvaluedescribes. Pass it where the wire format fixes the family, so that anintis widened to the right one –258is::102forversion=6but0.0.1.2foripaddress.ip_address().
- Return type:
- Returns:
The converted address.
- Raises:
FieldValueError – If
valueis abool(cf._reject_bool()), is not a valid IP address, or is not ofversion.
Notes
This is the sanctioned way for a
_make_*method to turn a caller-supplied address into anipaddressobject, and it exists because doing it withipaddress.ip_address()directly is the defect #508 found: a_make_*that has to know the address family before it can build the schema – to size an option whose length is the only thing on the wire that carries the family – must convert the argument itself, and that conversion happens before the schema, so it launders aboolinto anIPv4Addressthat the #491 guard in_IPAddressField.pre_processcan then only see as a legitimate address:True/Falsebecome0.0.0.1/0.0.0.0– or::1/::where the wire format fixes the family as IPv6 – without complaint.Routing every one of them through here rather than giving each its own
isinstance()check is the whole point:MH._make_opt_mn_idcarries exactly such a check (#469), and #491 is the same defect at every site that lacks one. A guard that has to be remembered per call site is a guard that will be forgotten at the next one.The
boolrejection is the first statement here, ahead of any dispatch on the value’s type, for the placement reason #469 gives and_reject_bool()repeats.This raises
FieldValueErrorand notProtocolError, which is deliberate even though sibling guards for the same mistake –MH._make_opt_mn_idfrom #469 andESP's SecurityAssociationfrom #491 – raise the latter. The layer decides: this is a field-level conversion, so it answers with what_IPAddressField.pre_processanswers with for the identical value, and a caller sees one exception whether theboolreached the field through the schema or through a_make_*. Those protocol-level guards answer for the option, alongside siblings that are not about addresses at all –_make_opt_mn_idrefuses aboolfor every MN-ID subtype, address-typed or not – so none of them can route through here without losing the subtype-aware message that is the point of it. Both exception classes derive fromBaseErrorandValueError, so the difference is invisible toexcept BaseErrorandexcept ValueError, and no call of this function or of a_make_*in the library sits inside anexceptfor either one specifically.Added in version 1.5.0.
Internal Definitions¶
- pcapkit.corekit.schema.ipaddress._reject_bool(value, description)[source]¶
Reject a
boolvalue before it reachesipaddress.- Parameters:
value (
object) – Value to check.description (
str) – Human-readable description of whatvalueis, used to build theFieldValueErrormessage.
- Raises:
FieldValueError – If
valueis abool.
Notes
boolis anintsubclass, and every conversion here and inpcapkit.corekit.fields.ipaddressultimately callsipaddress.ip_address()oripaddress.ip_interface(), both of which treat anyintbelow2**32as IPv4 – so without this guard,True/Falseare silently accepted as0.0.0.1/0.0.0.0(or the equivalent interface) on an IPv4-typed field, with no exception and no warning. On an IPv6-typed field the same conversion happens to raise instead, because the resultingIPv4Address’s version mismatches – and that asymmetry is exactly what let this slip past #469’s otherwise equivalent guard forMH._make_opt_mn_id(cf. #491).Every caller checks this before dispatching on the value’s type, for the same placement reason #469 gives: a correct check in the wrong position does not fire.
Guarding the field classes is necessary but not sufficient, because a
_make_*that must know the address family before it can build the schema converts the argument itself and so never hands the fields aboolat all.parse_ip_address()is where those callers reach this guard (cf. #508).