diff --git a/Network/Wai/Application/Classic.hs b/Network/Wai/Application/Classic.hs
--- a/Network/Wai/Application/Classic.hs
+++ b/Network/Wai/Application/Classic.hs
@@ -5,13 +5,14 @@
 module Network.Wai.Application.Classic (
   -- * Types
     AppSpec(..)
+  , Logger
   , FileInfo(..)
   -- * Files
   , FileRoute(..), fileApp
   -- * CGI
   , CgiRoute(..), cgiApp
   -- * Utilities for logging
-  , NumericAddress, getPeerAddr
+  , NumericAddress, showSockAddr
   , FieldKey
   , lookupRequestField, lookupRequestField'
   ) where
diff --git a/Network/Wai/Application/Classic/CGI.hs b/Network/Wai/Application/Classic/CGI.hs
--- a/Network/Wai/Application/Classic/CGI.hs
+++ b/Network/Wai/Application/Classic/CGI.hs
@@ -51,7 +51,7 @@
 
 cgiApp' :: Bool -> AppSpec -> CgiRoute -> Application
 cgiApp' body spec cgii req = do
-    naddr <- liftIO . getPeerAddr . remoteHost $ req
+    let naddr = showSockAddr . remoteHost $ req
     (Just whdl,Just rhdl,_,_) <- liftIO . createProcess . proSpec $ naddr
     liftIO $ do
         hSetEncoding rhdl latin1
diff --git a/Network/Wai/Application/Classic/Types.hs b/Network/Wai/Application/Classic/Types.hs
--- a/Network/Wai/Application/Classic/Types.hs
+++ b/Network/Wai/Application/Classic/Types.hs
@@ -14,9 +14,12 @@
     -- | Whether this is an HTML or not.
   , isHTML :: ByteString -> Bool
     -- | A function for logging. The third argument is a body size.
-  , logger :: Request -> Status -> Maybe Integer -> IO ()
+  , logger :: Logger
+    -- | A function to obtain information about a file.
   , getFileInfo :: ByteString -> IO (Maybe FileInfo)
   }
+
+type Logger = Request -> Status -> Maybe Integer -> IO ()
 
 data FileInfo = FileInfo {
     fileInfoName :: FilePath
diff --git a/Network/Wai/Application/Classic/Utils.hs b/Network/Wai/Application/Classic/Utils.hs
--- a/Network/Wai/Application/Classic/Utils.hs
+++ b/Network/Wai/Application/Classic/Utils.hs
@@ -1,32 +1,63 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module Network.Wai.Application.Classic.Utils where
+module Network.Wai.Application.Classic.Utils (
+    NumericAddress, showSockAddr
+  , hasTrailingPathSeparator, pathSep
+  , (+++), (</>)
+  ) where
 
-import Control.Applicative
+import Data.Bits
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
 import Data.ByteString.Char8 ()
-import Data.List (isPrefixOf)
-import Data.Maybe
 import Data.Word
-import Network.Socket (getNameInfo, SockAddr, NameInfoFlag(..))
+import Network.Socket (SockAddr(..))
+import System.ByteOrder
+import Text.Printf
 
 {-|
   A type for IP address in numeric string representation.
 -}
 type NumericAddress = String
 
+showIPv4 :: Word32 -> Bool -> NumericAddress
+showIPv4 w32 little
+    | little    = show b1 ++ "." ++ show b2 ++ "." ++ show b3 ++ "." ++ show b4
+    | otherwise = show b4 ++ "." ++ show b3 ++ "." ++ show b2 ++ "." ++ show b1
+  where
+    t1 = w32
+    t2 = shift t1 (-8)
+    t3 = shift t2 (-8)
+    t4 = shift t3 (-8)
+    b1 = t1 .&. 0x000000ff
+    b2 = t2 .&. 0x000000ff
+    b3 = t3 .&. 0x000000ff
+    b4 = t4 .&. 0x000000ff
+
+showIPv6 :: (Word32,Word32,Word32,Word32) -> String
+showIPv6 (w1,w2,w3,w4) =
+    printf "%x:%x:%x:%x:%x:%x:%x:%x" s1 s2 s3 s4 s5 s6 s7 s8
+  where
+    (s1,s2) = foo w1
+    (s3,s4) = foo w2
+    (s5,s6) = foo w3
+    (s7,s8) = foo w4
+    foo w = (h1,h2)
+      where
+        h1 = w .&. 0x0000ffff
+        h2 = shift w (-16) .&. 0x0000ffff
 {-|
   Convert 'SockAddr' to 'NumericAddress'. If the address is
   an IPv4-embedded IPv6 address, the IPv4 is extracted.
 -}
-getPeerAddr :: SockAddr -> IO NumericAddress
-getPeerAddr sa = strip . fromJust . fst <$> getInfo sa
-  where
-    getInfo = getNameInfo [NI_NUMERICHOST, NI_NUMERICSERV] True True
-    strip x
-      | "::ffff:" `isPrefixOf` x = drop 7 x
-      | otherwise                = x
+-- HostAddr is network byte order.
+-- HostAddr6 is host byte order.
+showSockAddr :: SockAddr -> NumericAddress
+showSockAddr (SockAddrInet _ addr4)                       = showIPv4 addr4 (byteOrder == LittleEndian)
+showSockAddr (SockAddrInet6 _ _ (0,0,0x0000ffff,addr4) _) = showIPv4 addr4 False
+showSockAddr (SockAddrInet6 _ _ (0,0,0,1) _)              = "::1"
+showSockAddr (SockAddrInet6 _ _ addr6 _)                  = showIPv6 addr6
+showSockAddr _                                            = "unknownSocket"
 
 pathSep :: Word8
 pathSep = 47
diff --git a/wai-app-file-cgi.cabal b/wai-app-file-cgi.cabal
--- a/wai-app-file-cgi.cabal
+++ b/wai-app-file-cgi.cabal
@@ -1,5 +1,5 @@
 Name:                   wai-app-file-cgi
-Version:                0.2.3
+Version:                0.3.0
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -35,7 +35,7 @@
                         wai, enumerator >= 0.4.9,
                         bytestring, blaze-builder,
                         wai-app-static, http-types, http-date,
-                        case-insensitive, static-hash
+                        case-insensitive, static-hash, byteorder
 Source-Repository head
   Type:                 git
   Location:             git://github.com/kazu-yamamoto/wai-app-file-cgi.git
