----------------------------------------------------------------------------- -- | -- Module : Network.Socket.LocalAddress -- Copyright : 2011 Kei Hibino -- License : BSD3 -- -- Maintainer : ex8k.hibino@gmail.com -- Stability : experimental -- Portability : portable -- -- This package includes small functions to get local interface address. -- Following method is traditional technique to getSockName without sending packet. -- ----------------------------------------------------------------------------- module Network.Socket.LocalAddress ( localSockAddr', localSockAddr, localAddress, localAddressString) where import Network.Socket (Socket, Family(..), SockAddr(..), SocketType(..), HostAddress, socket, connect, defaultProtocol, getSocketName, sClose, inet_addr, inet_ntoa) toIO :: a -> IO a toIO = return {- | Get local address and datagram socket corresponding to remote address without sending any packet. -} localSockAddr' :: SockAddr -> IO (SockAddr, Socket) localSockAddr' remote = do sock <- socket (af remote) Datagram defaultProtocol connect sock remote addr <- getSocketName sock toIO (addr, sock) where af (SockAddrInet _ _) = AF_INET af (SockAddrInet6 _ _ _ _) = AF_INET6 af (SockAddrUnix _) = AF_UNIX {- | Get local address corresponding to remote address without sending any packet. -} localSockAddr :: SockAddr -> IO SockAddr localSockAddr remote = do (addr, sock) <- localSockAddr' remote sClose sock toIO $ erasePort addr where erasePort (SockAddrInet _ addr) = SockAddrInet 0 addr erasePort (SockAddrInet6 _ fi ha si) = SockAddrInet6 0 fi ha si erasePort sa@(SockAddrUnix _) = sa {- | Get IPv4 local address corresponding to remote IPv4 address without sending any packet. -} localAddress :: HostAddress -> IO (Maybe HostAddress) localAddress = fmap expect4 . localSockAddr . SockAddrInet 0 where expect4 (SockAddrInet _ addr) = Just addr expect4 _ = Nothing {- | Get IPv4 local address string corresponding to remote IPv4 address string without sending any packet. -} localAddressString :: String -> IO (Maybe String) localAddressString astr = do remote <- inet_addr astr local <- localAddress remote maybe (toIO Nothing) (fmap Just . inet_ntoa) local