diff --git a/Data/IP/Addr.hs b/Data/IP/Addr.hs
--- a/Data/IP/Addr.hs
+++ b/Data/IP/Addr.hs
@@ -125,10 +125,11 @@
                                    c' = fromEnum c `shift` 32
                                    d' = fromEnum d
                                in a' .|. b' .|. c' .|. d'
-    toEnum i = let a = toEnum (i `shiftR` 96 .&. 0xffffffff)
-                   b = toEnum (i `shiftR` 64 .&. 0xffffffff)
-                   c = toEnum (i `shiftR` 32 .&. 0xffffffff)
-                   d = toEnum (i             .&. 0xffffffff)
+    toEnum i = let i' = fromIntegral i :: Integer
+                   a = fromIntegral (i' `shiftR` 96 .&. 0xffffffff)
+                   b = fromIntegral (i' `shiftR` 64 .&. 0xffffffff)
+                   c = fromIntegral (i' `shiftR` 32 .&. 0xffffffff)
+                   d = fromIntegral (i'             .&. 0xffffffff)
                in IP6 (a,b,c,d)
 
     succ (IP6 (0xffffffff,0xffffffff,0xffffffff,0xffffffff)) = succError "IPv6"
diff --git a/Data/IP/Mask.hs b/Data/IP/Mask.hs
--- a/Data/IP/Mask.hs
+++ b/Data/IP/Mask.hs
@@ -3,31 +3,43 @@
 import Data.Bits
 import Data.IP.Addr
 import Data.Word
-import Data.IntMap hiding (map)
 
-----------------------------------------------------------------
-
 maskIPv4 :: Int -> IPv4
-maskIPv4 len = IP4 (masksIPv4 ! len)
+maskIPv4 len =
+    IP4 $ complement $ 0xffffffff `shift` (-len)
 
 maskIPv6 :: Int -> IPv6
-maskIPv6 len = IP6 (masksIPv6 ! len)
+maskIPv6 len =
+    IP6 $ toIP6Addr $ bimapTup complement $
+            (0xffffffffffffffff, 0xffffffffffffffff) `shift128` (-len)
+ where
+   bimapTup f (x,y) = (f x, f y)
 
-masksWord32 :: [Word32]
-masksWord32 = take 33 $ iterate (`shift` 1) 0xffffffff
+shift128 :: (Word64, Word64) -> Int -> (Word64, Word64)
+shift128 x i
+    | i < 0  = x `shiftR128` (-i)
+    | i > 0  = x `shiftL128` i
+    | otherwise = x
 
-masksIPv4 :: IntMap IPv4Addr
-masksIPv4 = fromList $ zip [32,31..0] masksWord32
+shiftL128 :: (Word64, Word64) -> Int -> (Word64, Word64)
+shiftL128 (h, l) i =
+        ( (h `shiftL` i) .|. (l `shift` (i - 64) ), (l `shiftL` i))
 
-masksIPv6 :: IntMap IPv6Addr
-masksIPv6 = fromList $ zip [128,127..0] ms
-  where
-    ms = m0 ++ m1 ++ m2 ++ m3 ++ m4
-    m0 = [(all1,all1,all1,all1)]
-    m1 = map (\vmsk -> (all1,all1,all1,vmsk)) masks
-    m2 = map (\vmsk -> (all1,all1,vmsk,all0)) masks
-    m3 = map (\vmsk -> (all1,vmsk,all0,all0)) masks
-    m4 = map (\vmsk -> (vmsk,all0,all0,all0)) masks
-    masks = tail masksWord32
-    all1 = 0xffffffff
-    all0 = 0x00000000
+shiftR128 :: (Word64, Word64) -> Int -> (Word64, Word64)
+shiftR128 (h, l) i =
+    (h `shiftR` i, (l `shiftR` i) .|. h `shift` (64 - i) )
+
+fromIP6Addr :: IPv6Addr -> (Word64, Word64)
+fromIP6Addr (w3, w2, w1, w0) =
+   ( (fromIntegral w3 `shiftL` 32) .|. fromIntegral w2
+   , (fromIntegral w1 `shiftL` 32) .|. fromIntegral w0
+   )
+
+toIP6Addr :: (Word64, Word64) -> IPv6Addr
+toIP6Addr (h, l) =
+    ( fromIntegral $ (h `shiftR` 32) .&. m
+    , fromIntegral $ h .&. m
+    , fromIntegral $ (l `shiftR` 32) .&. m
+    , fromIntegral $ l .&. m
+    )
+  where m = 0xffffffff
diff --git a/Data/IP/Op.hs b/Data/IP/Op.hs
--- a/Data/IP/Op.hs
+++ b/Data/IP/Op.hs
@@ -19,8 +19,23 @@
     -}
     masked :: a -> a -> a
     {-|
-      The 'intToMask' function takes 'Int' and returns a contiguous
-      mask.
+
+      The 'intToMask' function takes an 'Int' representing the number of bits to
+      be set in the returned contiguous mask. When this integer is positive the
+      bits will be starting from the MSB and from the LSB otherwise.
+
+      >>> intToMask 16 :: IPv4
+      255.255.0.0
+
+      >>> intToMask (-16) :: IPv4
+      0.0.255.255
+
+      >>> intToMask 16 :: IPv6
+      ffff::
+
+      >>> intToMask (-16) :: IPv6
+      ::ffff
+
     -}
     intToMask :: Int -> a
 
diff --git a/iproute.cabal b/iproute.cabal
--- a/iproute.cabal
+++ b/iproute.cabal
@@ -1,5 +1,5 @@
 Name:                   iproute
-Version:                1.7.0
+Version:                1.7.1
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
