-- |
-- Module: NetSpider.RPL.IPv6
-- Description: (INTERNAL) Basic routines for IPv6 type
-- Maintainer: Toshio Ito <debug.ito@gmail.com>
--
-- __This module is for internal use.__
--
-- @since 0.3.1.0
module NetSpider.RPL.IPv6
  ( Prefix,
    InterfaceID,
    isLinkLocal,
    getPrefix,
    setPrefix,
    getInterfaceID
  ) where

import Data.Bits ((.&.), shift, shiftL, (.|.), shiftR)
import Data.Word (Word64, Word32)
import Net.IPv6 (IPv6, toWord16s, toWord32s, fromWord32s)

type Prefix = Word64

type InterfaceID = Word64

isLinkLocal :: IPv6 -> Bool
isLinkLocal :: IPv6 -> Bool
isLinkLocal IPv6
addr = (Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
== Word16
0xfe80) (Word16 -> Bool) -> Word16 -> Bool
forall a b. (a -> b) -> a -> b
$ (Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
bit_mask) (Word16 -> Word16) -> Word16 -> Word16
forall a b. (a -> b) -> a -> b
$ Word16
top_word
  where
    (Word16
top_word, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_) = IPv6
-> (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16)
toWord16s IPv6
addr
    bit_mask :: Word16
bit_mask = (Word16
2 Word16 -> Int -> Word16
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
10 :: Int) Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
- Word16
1) Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`shift` Int
6

getPrefix :: IPv6 -> Prefix
getPrefix :: IPv6 -> Prefix
getPrefix IPv6
addr = Word32 -> Word32 -> Prefix
to64 Word32
u Word32
l
  where
    (Word32
u, Word32
l, Word32
_, Word32
_) = IPv6 -> (Word32, Word32, Word32, Word32)
toWord32s IPv6
addr

setPrefix :: Prefix -> IPv6 -> IPv6
setPrefix :: Prefix -> IPv6 -> IPv6
setPrefix Prefix
p IPv6
orig = Word32 -> Word32 -> Word32 -> Word32 -> IPv6
fromWord32s Word32
u1 Word32
u2 Word32
l1 Word32
l2
  where
    (Word32
_, Word32
_, Word32
l1, Word32
l2) = IPv6 -> (Word32, Word32, Word32, Word32)
toWord32s IPv6
orig
    u1 :: Word32
u1 = Prefix -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Prefix
p Prefix -> Int -> Prefix
forall a. Bits a => a -> Int -> a
`shiftR` Int
32) Prefix -> Prefix -> Prefix
forall a. Bits a => a -> a -> a
.&. Prefix
0xFFFFFFFF)
    u2 :: Word32
u2 = Prefix -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Prefix
p Prefix -> Prefix -> Prefix
forall a. Bits a => a -> a -> a
.&. Prefix
0xFFFFFFFF)

getInterfaceID :: IPv6 -> InterfaceID
getInterfaceID :: IPv6 -> Prefix
getInterfaceID IPv6
addr = Word32 -> Word32 -> Prefix
to64 Word32
u Word32
l
  where
    (Word32
_, Word32
_, Word32
u, Word32
l) = IPv6 -> (Word32, Word32, Word32, Word32)
toWord32s IPv6
addr

to64 :: Word32 -> Word32 -> Word64
to64 :: Word32 -> Word32 -> Prefix
to64 Word32
u Word32
l = (Word32 -> Prefix
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
u Prefix -> Int -> Prefix
forall a. Bits a => a -> Int -> a
`shiftL` Int
32) Prefix -> Prefix -> Prefix
forall a. Bits a => a -> a -> a
.|. Word32 -> Prefix
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
l