Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides the IPv4 data type and functions for working with it.
Synopsis
- ipv4 :: Word8 -> Word8 -> Word8 -> Word8 -> IPv4
- fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> IPv4
- fromTupleOctets :: (Word8, Word8, Word8, Word8) -> IPv4
- toOctets :: IPv4 -> (Word8, Word8, Word8, Word8)
- any :: IPv4
- loopback :: IPv4
- localhost :: IPv4
- broadcast :: IPv4
- private :: IPv4 -> Bool
- reserved :: IPv4 -> Bool
- public :: IPv4 -> Bool
- encode :: IPv4 -> Text
- decode :: Text -> Maybe IPv4
- builder :: IPv4 -> Builder
- reader :: Reader IPv4
- parser :: Parser IPv4
- decodeShort :: ShortText -> Maybe IPv4
- encodeShort :: IPv4 -> ShortText
- encodeUtf8 :: IPv4 -> ByteString
- decodeUtf8 :: ByteString -> Maybe IPv4
- builderUtf8 :: IPv4 -> Builder
- parserUtf8 :: Parser IPv4
- decodeUtf8Bytes :: Bytes -> Maybe IPv4
- parserUtf8Bytes :: e -> Parser e s IPv4
- byteArrayBuilderUtf8 :: IPv4 -> Builder
- boundedBuilderUtf8 :: IPv4 -> Builder 15
- encodeString :: IPv4 -> String
- decodeString :: String -> Maybe IPv4
- print :: IPv4 -> IO ()
- range :: IPv4 -> Word8 -> IPv4Range
- fromBounds :: IPv4 -> IPv4 -> IPv4Range
- normalize :: IPv4Range -> IPv4Range
- contains :: IPv4Range -> IPv4 -> Bool
- member :: IPv4 -> IPv4Range -> Bool
- lowerInclusive :: IPv4Range -> IPv4
- upperInclusive :: IPv4Range -> IPv4
- toList :: IPv4Range -> [IPv4]
- toGenerator :: MonadPlus m => IPv4Range -> m IPv4
- private24 :: IPv4Range
- private20 :: IPv4Range
- private16 :: IPv4Range
- encodeRange :: IPv4Range -> Text
- decodeRange :: Text -> Maybe IPv4Range
- builderRange :: IPv4Range -> Builder
- parserRange :: Parser IPv4Range
- printRange :: IPv4Range -> IO ()
- newtype IPv4 = IPv4 {}
- type IPv4# = Word#
- data IPv4Range = IPv4Range {
- ipv4RangeBase :: !IPv4
- ipv4RangeLength :: !Word8
- box :: IPv4# -> IPv4
- unbox :: IPv4 -> IPv4#
- parserUtf8Bytes# :: e -> Parser e s IPv4#
Conversion Functions
ipv4 :: Word8 -> Word8 -> Word8 -> Word8 -> IPv4 Source #
Create an IPv4
address from four octets. The first argument
is the most significant octet. The last argument is the least
significant. Since IP addresses are commonly written using dot-decimal
notation, this is the recommended way to create an IP address.
Additionally, it is used for the Show
and Read
instances
of IPv4
to help keep things readable in GHCi.
>>>
let addr = ipv4 192 168 1 1
>>>
addr
ipv4 192 168 1 1>>>
getIPv4 addr
3232235777
fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> IPv4 Source #
An alias for the ipv4
smart constructor.
fromTupleOctets :: (Word8, Word8, Word8, Word8) -> IPv4 Source #
An uncurried variant of fromOctets
.
toOctets :: IPv4 -> (Word8, Word8, Word8, Word8) Source #
Convert an IPv4
address into a quadruple of octets. The first
element in the quadruple is the most significant octet. The last
element is the least significant octet.
Special IP Addresses
Range Predicates
private :: IPv4 -> Bool Source #
Checks to see if the IPv4
address belongs to a private
network. The three private networks that are checked are
10.0.0.0/8
, 172.16.0.0/12
, and 192.168.0.0/16
.
public :: IPv4 -> Bool Source #
Checks to see if the IPv4
address is publicly routable.
public x == not (reserved x)
Textual Conversion
Text
decode :: Text -> Maybe IPv4 Source #
Decode an IPv4
address.
>>>
decode "192.168.2.47"
Just (ipv4 192 168 2 47)
>>>
decode "10.100.256.256"
Nothing
encodeShort :: IPv4 -> ShortText Source #
UTF-8 ByteString
encodeUtf8 :: IPv4 -> ByteString Source #
Encode an IPv4
address to a UTF-8 encoded ByteString
.
>>>
encodeUtf8 (ipv4 192 168 2 47)
"192.168.2.47"
decodeUtf8 :: ByteString -> Maybe IPv4 Source #
Decode a UTF8-encoded ByteString
into an IPv4
.
>>>
decodeUtf8 "192.168.2.47"
Just (ipv4 192 168 2 47)
Currently not terribly efficient since the implementation re-encodes the argument as UTF-16 text before decoding that IPv4 address from that. PRs to fix this are welcome.
builderUtf8 :: IPv4 -> Builder Source #
parserUtf8 :: Parser IPv4 Source #
UTF-8 Bytes
decodeUtf8Bytes :: Bytes -> Maybe IPv4 Source #
Decode UTF-8-encoded Bytes
into an IPv4
address.
>>>
decodeUtf8Bytes (Bytes.fromAsciiString "127.0.0.1")
Just (ipv4 127 0 0 1)
parserUtf8Bytes :: e -> Parser e s IPv4 Source #
Parse UTF-8-encoded Bytes
as an IPv4
address.
>>>
Parser.parseBytes (parserUtf8Bytes ()) (Bytes.fromAsciiString "10.0.1.254")
Success (Slice {offset = 10, length = 0, value = ipv4 10 0 1 254})
byteArrayBuilderUtf8 :: IPv4 -> Builder Source #
Encode an IPv4
address as a unbounded byte array builder.
>>>
Chunks.concat (UB.run 1 (byteArrayBuilderUtf8 (fromOctets 192 168 2 13)))
[0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x32, 0x2e, 0x31, 0x33]
Note that period is encoded by UTF-8 as 0x2e
.
boundedBuilderUtf8 :: IPv4 -> Builder 15 Source #
Encode an IPv4
address as a bounded byte array builder.
>>>
BB.run Nat.constant (boundedBuilderUtf8 (fromOctets 192 168 2 14))
[0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x32, 0x2e, 0x31, 0x34]
Note that period is encoded by UTF-8 as 0x2e
.
String
These functions exist for the convenience of those who need a
String
representation of an IPv4
address. Using them
is discouraged unless the end user is working with a library
that can only use String
to deal with textual data (such as
pandoc
, hxr
, or network
).
Printing
IPv4 Ranges
Range functions
fromBounds :: IPv4 -> IPv4 -> IPv4Range Source #
Given an inclusive lower and upper ip address, create the smallest
IPv4Range
that contains the two. This is helpful in situations where
input given as a range like 192.168.16.0-192.168.19.255
needs to be
handled. This makes the range broader if it cannot be represented in
CIDR notation.
>>>
printRange $ fromBounds (fromOctets 192 168 16 0) (fromOctets 192 168 19 255)
192.168.16.0/22>>>
printRange $ fromBounds (fromOctets 10 0 5 7) (fromOctets 10 0 5 14)
10.0.5.0/28
normalize :: IPv4Range -> IPv4Range Source #
Normalize an IPv4Range
. The first result of this is that the
IPv4
inside the IPv4Range
is changed so that the insignificant
bits are zeroed out. For example:
>>>
printRange $ normalize $ IPv4Range (fromOctets 192 168 1 19) 24
192.168.1.0/24>>>
printRange $ normalize $ IPv4Range (fromOctets 192 168 1 163) 28
192.168.1.160/28
The second effect of this is that the mask length is lowered to
be 32 or smaller. Working with IPv4Range
s that have not been
normalized does not cause any issues for this library, although
other applications may reject such ranges (especially those with
a mask length above 32).
Note that normalize
is idempotent, that is:
normalize r == (normalize . normalize) r
contains :: IPv4Range -> IPv4 -> Bool Source #
Checks to see if an IPv4
address belongs in the IPv4Range
.
>>>
let ip = fromOctets 10 10 1 92
>>>
contains (IPv4Range (fromOctets 10 0 0 0) 8) ip
True>>>
contains (IPv4Range (fromOctets 10 11 0 0) 16) ip
False
Typically, element-testing functions are written to take the element as the first argument and the set as the second argument. This is intentionally written the other way for better performance when iterating over a collection. For example, you might test elements in a list for membership like this:
>>>
let r = IPv4Range (fromOctets 10 10 10 6) 31
>>>
mapM_ (P.print . contains r) (take 5 $ iterate succ $ fromOctets 10 10 10 5)
False True True False False
The implementation of contains
ensures that (with GHC), the bitmask
creation and range normalization only occur once in the above example.
They are reused as the list is iterated.
member :: IPv4 -> IPv4Range -> Bool Source #
This is provided to mirror the interface provided by Data.Set
. It
behaves just like contains
but with flipped arguments.
member ip r == contains r ip
lowerInclusive :: IPv4Range -> IPv4 Source #
The inclusive lower bound of an IPv4Range
. This is conventionally
understood to be the broadcast address of a subnet. For example:
>>>
T.putStrLn $ encode $ lowerInclusive $ IPv4Range (ipv4 10 10 1 160) 25
10.10.1.128
Note that the lower bound of a normalized IPv4Range
is simply the
ip address of the range:
lowerInclusive r == ipv4RangeBase (normalize r)
upperInclusive :: IPv4Range -> IPv4 Source #
The inclusive upper bound of an IPv4Range
.
>>>
T.putStrLn $ encode $ upperInclusive $ IPv4Range (ipv4 10 10 1 160) 25
10.10.1.255
Conversion to IPv4
toGenerator :: MonadPlus m => IPv4Range -> m IPv4 Source #
A stream-polymorphic generator over an IPv4Range
.
For more information, see How to build library-agnostic streaming sources.
Private Ranges
Textual Conversion
Text
encodeRange :: IPv4Range -> Text Source #
builderRange :: IPv4Range -> Builder Source #
printRange :: IPv4Range -> IO () Source #
Print an IPv4Range
. Helper function that
exists mostly for testing purposes.
Types
A 32-bit Internet Protocol version 4 address. To use this with the
network
library, it is necessary to use Network.Socket.htonl
to
convert the underlying Word32
from host byte order to network byte
order.
Instances
The length should be between 0 and 32. These bounds are inclusive. This expectation is not in any way enforced by this library because it does not cause errors. A mask length greater than 32 will be treated as if it were 32.
IPv4Range | |
|
Instances
Unboxing
These functions are useful for micro-optimizing when GHC does a poor job with worker-wrapper.
parserUtf8Bytes# :: e -> Parser e s IPv4# Source #
Variant of parserUtf8Bytes
with unboxed result type.
Interoperability
The network
library is commonly
used to open sockets and communicate over them. In the Network.Socket
module,
it provides a type synonym HostAddress
that, like IPv4
, is used
to represent an IPv4 address. However, while IPv4
uses a big-endian representation
for ip addresses, HostAddress
has platform dependent endianness.
Consequently, it is necessary to convert between the two as follows:
import Network.Socket (HostAddress,htonl,ntohl) toHostAddr :: IPv4 -> HostAddress toHostAddr (IPv4 w) = htonl w fromHostAddr :: HostAddress -> IPv4 fromHostAddr w = IPv4 (ntohl w)
These functions are not included with this library since it would require
picking up a dependency on network
.