diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # ChangeLog
 
+## 0.2.1
+
+* Using recvMsg and sendBufMsg.
+
 ## 0.2.0
 
 * A new server architecture: only wildcard (unconnected) sockets are used.
diff --git a/Network/QUIC/Client/Reader.hs b/Network/QUIC/Client/Reader.hs
--- a/Network/QUIC/Client/Reader.hs
+++ b/Network/QUIC/Client/Reader.hs
@@ -11,7 +11,7 @@
 
 import Data.List (intersect)
 import Network.Socket (Socket, close, getSocketName)
-import Network.Socket.ByteString (recvFrom)
+import qualified Network.Socket.ByteString as NSB
 import UnliftIO.Concurrent
 import qualified UnliftIO.Exception as E
 
@@ -44,11 +44,11 @@
         ito <- readMinIdleTimeout conn
         mbs <-
             timeout ito "readeClient" $
-                recvFrom s0 2048 -- fixme
+                NSB.recvMsg s0 2048 2048 0 -- fixme
         case mbs of
             Nothing -> close s0
-            Just (bs, peersa) -> do
-                setPeerSockAddr conn peersa
+            Just (peersa, bs, cmsgs, _) -> do
+                setPeerInfo conn $ PeerInfo peersa cmsgs
                 now <- getTimeMicrosecond
                 let quicBit = greaseQuicBit $ getMyParameters conn
                 pkts <- decodePackets bs (not quicBit)
@@ -142,7 +142,7 @@
 
 rebind :: Connection -> Microseconds -> IO ()
 rebind conn microseconds = do
-    peersa <- getPeerSockAddr conn
+    PeerInfo peersa _ <- getPeerInfo conn
     newSock <- natRebinding peersa
     oldSock <- setSocket conn newSock
     let reader = readerClient newSock conn
diff --git a/Network/QUIC/Client/Run.hs b/Network/QUIC/Client/Run.hs
--- a/Network/QUIC/Client/Run.hs
+++ b/Network/QUIC/Client/Run.hs
@@ -108,11 +108,11 @@
     (sock, peersa) <- clientSocket ccServerName ccPortName
     q <- newRecvQ
     sref <- newIORef sock
-    psaref <- newIORef peersa
-    let send = \buf siz -> do
+    piref <- newIORef $ PeerInfo peersa []
+    let send buf siz = do
             s <- readIORef sref
-            sa <- readIORef psaref
-            void $ NS.sendBufTo s buf siz sa
+            PeerInfo sa cmsgs <- readIORef piref
+            void $ NS.sendBufMsg s sa [(buf, siz)] cmsgs 0
         recv = recvClient q
     myCID <- newCID
     peerCID <- newCID
@@ -134,7 +134,7 @@
             qLog
             ccHooks
             sref
-            psaref
+            piref
             q
             send
             recv
diff --git a/Network/QUIC/Closer.hs b/Network/QUIC/Closer.hs
--- a/Network/QUIC/Closer.hs
+++ b/Network/QUIC/Closer.hs
@@ -39,11 +39,11 @@
 closure' :: Connection -> LDCC -> Frame -> IO ()
 closure' conn ldcc frame = do
     sock <- getSocket conn
-    peersa <- getPeerSockAddr conn
+    PeerInfo peersa cmsgs <- getPeerInfo conn
     -- send
-    let sbuf@(SizedBuffer sendBuf _) = encryptRes conn
+    let sbuf@(SizedBuffer sendbuf _) = encryptRes conn
     siz <- encodeCC conn sbuf frame
-    let send = void $ NS.sendBufTo sock sendBuf siz peersa
+    let send = void $ NS.sendBufMsg sock peersa [(sendbuf, siz)] cmsgs 0
     -- recv and clos
     killReaders conn -- client only
     (recv, freeRecvBuf, clos) <-
@@ -51,9 +51,9 @@
             then return (void $ connRecv conn, return (), return ())
             else do
                 let bufsiz = maximumUdpPayloadSize
-                recvBuf <- mallocBytes bufsiz
-                let recv' = void $ NS.recvBuf sock recvBuf bufsiz
-                    free' = free recvBuf
+                recvbuf <- mallocBytes bufsiz
+                let recv' = void $ NS.recvBuf sock recvbuf bufsiz
+                    free' = free recvbuf
                     clos' = do
                         NS.close sock
                         -- This is just in case.
@@ -70,7 +70,7 @@
         clos
 
 encodeCC :: Connection -> SizedBuffer -> Frame -> IO Int
-encodeCC conn res0@(SizedBuffer sendBuf0 bufsiz0) frame = do
+encodeCC conn res0@(SizedBuffer sendbuf0 bufsiz0) frame = do
     lvl0 <- getEncryptionLevel conn
     let lvl
             | lvl0 == RTT0Level = InitialLevel
@@ -78,9 +78,9 @@
     if lvl == HandshakeLevel
         then do
             siz0 <- encCC res0 InitialLevel
-            let sendBuf1 = sendBuf0 `plusPtr` siz0
+            let sendbuf1 = sendbuf0 `plusPtr` siz0
                 bufsiz1 = bufsiz0 - siz0
-                res1 = SizedBuffer sendBuf1 bufsiz1
+                res1 = SizedBuffer sendbuf1 bufsiz1
             siz1 <- encCC res1 HandshakeLevel
             return (siz0 + siz1)
         else
diff --git a/Network/QUIC/Connection/Misc.hs b/Network/QUIC/Connection/Misc.hs
--- a/Network/QUIC/Connection/Misc.hs
+++ b/Network/QUIC/Connection/Misc.hs
@@ -10,8 +10,8 @@
     getSocket,
     setSocket,
     clearSocket,
-    getPeerSockAddr,
-    setPeerSockAddr,
+    getPeerInfo,
+    setPeerInfo,
     getPeerAuthCIDs,
     setPeerAuthCIDs,
     getClientDstCID,
@@ -33,7 +33,7 @@
     abortConnection,
 ) where
 
-import Network.Socket (SockAddr, Socket)
+import Network.Socket (Socket)
 import System.Mem.Weak
 import UnliftIO.Concurrent
 import qualified UnliftIO.Exception as E
@@ -77,11 +77,11 @@
 clearSocket :: Connection -> IO Socket
 clearSocket Connection{..} = atomicModifyIORef' connSocket (undefined,)
 
-getPeerSockAddr :: Connection -> IO SockAddr
-getPeerSockAddr Connection{..} = readIORef peerSockAddr
+getPeerInfo :: Connection -> IO PeerInfo
+getPeerInfo Connection{..} = readIORef peerInfo
 
-setPeerSockAddr :: Connection -> SockAddr -> IO ()
-setPeerSockAddr Connection{..} sa = writeIORef peerSockAddr sa
+setPeerInfo :: Connection -> PeerInfo -> IO ()
+setPeerInfo Connection{..} = writeIORef peerInfo
 
 ----------------------------------------------------------------
 
diff --git a/Network/QUIC/Connection/Stream.hs b/Network/QUIC/Connection/Stream.hs
--- a/Network/QUIC/Connection/Stream.hs
+++ b/Network/QUIC/Connection/Stream.hs
@@ -112,7 +112,7 @@
         let StreamIdBase base = maxStreams
             initialStreams = initialMaxStreamsBidi $ getMyParameters conn
             cbase = currentStream !>>. 2
-         in if (base - cbase < (initialStreams !>>. 3))
+         in if base - cbase < (initialStreams !>>. 3)
                 then
                     let base' = cbase + initialStreams
                      in (conc{maxStreams = StreamIdBase base'}, Just base')
diff --git a/Network/QUIC/Connection/Types.hs b/Network/QUIC/Connection/Types.hs
--- a/Network/QUIC/Connection/Types.hs
+++ b/Network/QUIC/Connection/Types.hs
@@ -16,7 +16,7 @@
 import Foreign.Marshal.Alloc
 import Foreign.Ptr (nullPtr)
 import Network.Control (Rate, RxFlow, TxFlow, newRate, newRxFlow, newTxFlow)
-import Network.Socket (SockAddr, Socket)
+import Network.Socket (Cmsg, SockAddr, Socket)
 import Network.TLS.QUIC
 import UnliftIO.Concurrent
 import UnliftIO.STM
@@ -185,6 +185,8 @@
 type Send = Buffer -> Int -> IO ()
 type Recv = IO ReceivedPacket
 
+data PeerInfo = PeerInfo SockAddr [Cmsg] deriving (Eq, Show)
+
 ----------------------------------------------------------------
 
 -- | A quic connection to carry multiple streams.
@@ -213,7 +215,7 @@
     , -- Peer
       peerParameters :: IORef Parameters
     , peerCIDDB :: TVar CIDDB
-    , peerSockAddr :: IORef SockAddr
+    , peerInfo :: IORef PeerInfo
     , -- Queues
       inputQ :: InputQ
     , cryptoQ :: CryptoQ
@@ -289,12 +291,12 @@
     -> QLogger
     -> Hooks
     -> IORef Socket
-    -> IORef SockAddr
+    -> IORef PeerInfo
     -> RecvQ
     -> Send
     -> Recv
     -> IO Connection
-newConnection rl myparams verInfo myAuthCIDs peerAuthCIDs debugLog qLog hooks sref psaref recvQ ~send ~recv = do
+newConnection rl myparams verInfo myAuthCIDs peerAuthCIDs debugLog qLog hooks sref piref recvQ ~send ~recv = do
     -- ~ for testing
     outQ <- newTQueueIO
     let put x = atomically $ writeTQueue outQ $ OutRetrans x
@@ -317,7 +319,7 @@
         -- Peer
         <*> newIORef baseParameters
         <*> newTVarIO (newCIDDB peerCID)
-        <*> return psaref
+        <*> return piref
         -- Queues
         <*> newTQueueIO
         <*> newTQueueIO
@@ -385,7 +387,7 @@
     -> QLogger
     -> Hooks
     -> IORef Socket
-    -> IORef SockAddr
+    -> IORef PeerInfo
     -> RecvQ
     -> Send
     -> Recv
@@ -402,7 +404,7 @@
     -> QLogger
     -> Hooks
     -> IORef Socket
-    -> IORef SockAddr
+    -> IORef PeerInfo
     -> RecvQ
     -> Send
     -> Recv
diff --git a/Network/QUIC/Crypto.hs b/Network/QUIC/Crypto.hs
--- a/Network/QUIC/Crypto.hs
+++ b/Network/QUIC/Crypto.hs
@@ -1,6 +1,3 @@
-{-# LANGUAGE BinaryLiterals #-}
-{-# LANGUAGE OverloadedStrings #-}
-
 module Network.QUIC.Crypto (
     module Network.QUIC.Crypto.Fusion,
     module Network.QUIC.Crypto.Nite,
diff --git a/Network/QUIC/IO.hs b/Network/QUIC/IO.hs
--- a/Network/QUIC/IO.hs
+++ b/Network/QUIC/IO.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Network.QUIC.IO where
 
 import qualified Data.ByteString as BS
diff --git a/Network/QUIC/Info.hs b/Network/QUIC/Info.hs
--- a/Network/QUIC/Info.hs
+++ b/Network/QUIC/Info.hs
@@ -1,6 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
-
 module Network.QUIC.Info where
 
 import Data.ByteString ()
@@ -17,7 +14,7 @@
     sock <- getSocket conn
     -- fixme: this is undefined
     mysa <- NS.getSocketName sock
-    peersa <- getPeerSockAddr conn
+    PeerInfo peersa _ <- getPeerInfo conn
     mycid <- getMyCID conn
     peercid <- getPeerCID conn
     c <- getCipher conn RTT1Level
diff --git a/Network/QUIC/Packet/Decrypt.hs b/Network/QUIC/Packet/Decrypt.hs
--- a/Network/QUIC/Packet/Decrypt.hs
+++ b/Network/QUIC/Packet/Decrypt.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.QUIC.Packet.Decrypt (
diff --git a/Network/QUIC/Packet/Frame.hs b/Network/QUIC/Packet/Frame.hs
--- a/Network/QUIC/Packet/Frame.hs
+++ b/Network/QUIC/Packet/Frame.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Network.QUIC.Packet.Frame (
     encodeFrames,
     encodeFramesWithPadding,
diff --git a/Network/QUIC/Recovery/Interface.hs b/Network/QUIC/Recovery/Interface.hs
--- a/Network/QUIC/Recovery/Interface.hs
+++ b/Network/QUIC/Recovery/Interface.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.QUIC.Recovery.Interface (
diff --git a/Network/QUIC/Recovery/Persistent.hs b/Network/QUIC/Recovery/Persistent.hs
--- a/Network/QUIC/Recovery/Persistent.hs
+++ b/Network/QUIC/Recovery/Persistent.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.QUIC.Recovery.Persistent (
diff --git a/Network/QUIC/Recovery/Release.hs b/Network/QUIC/Recovery/Release.hs
--- a/Network/QUIC/Recovery/Release.hs
+++ b/Network/QUIC/Recovery/Release.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.QUIC.Recovery.Release (
diff --git a/Network/QUIC/Recovery/Utils.hs b/Network/QUIC/Recovery/Utils.hs
--- a/Network/QUIC/Recovery/Utils.hs
+++ b/Network/QUIC/Recovery/Utils.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.QUIC.Recovery.Utils (
diff --git a/Network/QUIC/Sender.hs b/Network/QUIC/Sender.hs
--- a/Network/QUIC/Sender.hs
+++ b/Network/QUIC/Sender.hs
@@ -423,12 +423,12 @@
                                         StreamF _ o d _ -> (o, d)
                                         _ -> error "sendStreamSmall"
                                     frame1 = StreamF sid off (dats ++ dats1) fin1'
-                                    sb1 = if fin1' then (sb . (s1 :)) else sb
+                                    sb1 = if fin1' then sb . (s1 :) else sb
                                 loop s1 frame1 total1 build sb1
                             else do
                                 let frame1 = StreamF sid1 off1 dats1 fin1'
                                     build1 = build . (frame :)
-                                    sb1 = if fin1' then (sb . (s1 :)) else sb
+                                    sb1 = if fin1' then sb . (s1 :) else sb
                                 loop s1 frame1 total1 build1 sb1
                     else return (build [frame], sb [])
 
diff --git a/Network/QUIC/Server/Reader.hs b/Network/QUIC/Server/Reader.hs
--- a/Network/QUIC/Server/Reader.hs
+++ b/Network/QUIC/Server/Reader.hs
@@ -25,7 +25,7 @@
 import Network.ByteOrder
 import Network.Control (LRUCache)
 import qualified Network.Control as LRUCache
-import Network.Socket (SockAddr, Socket)
+import Network.Socket (Socket)
 import qualified Network.Socket.ByteString as NSB
 import qualified System.IO.Error as E
 import UnliftIO.Concurrent
@@ -87,7 +87,7 @@
 ----------------------------------------------------------------
 
 -- Original destination CID -> RecvQ
-data RecvQDict = RecvQDict (LRUCache CID RecvQ)
+newtype RecvQDict = RecvQDict (LRUCache CID RecvQ)
 
 recvQDictSize :: Int
 recvQDictSize = 100
@@ -114,7 +114,7 @@
     , accMyAuthCIDs :: AuthCIDs
     , accPeerAuthCIDs :: AuthCIDs
     , accMySocket :: Socket
-    , accPeerSockAddr :: SockAddr
+    , accPeerInfo :: PeerInfo
     , accRecvQ :: RecvQ
     , accPacketSize :: Int
     , accRegister :: CID -> Connection -> IO ()
@@ -145,14 +145,15 @@
 dispatcher :: Dispatch -> ServerConfig -> Socket -> IO ()
 dispatcher d conf mysock = handleLogUnit logAction $ do
     forever $ do
-        (bs, peersa) <- safeRecv $ NSB.recvFrom mysock 2048
+        (peersa, bs, cmsgs, _) <- safeRecv $ NSB.recvMsg mysock 2048 2048 0
         now <- getTimeMicrosecond
-        let send' b = void $ NSB.sendTo mysock b peersa
+        let send' b = void $ NSB.sendMsg mysock peersa [b] cmsgs 0
             -- cf: greaseQuicBit $ getMyParameters conn
             quicBit = greaseQuicBit $ scParameters conf
         cpckts <- decodeCryptPackets bs (not quicBit)
         let bytes = BS.length bs
-            switch = dispatch d conf logAction mysock peersa send' bytes now
+            peerInfo = PeerInfo peersa cmsgs
+            switch = dispatch d conf logAction mysock peerInfo send' bytes now
         mapM_ switch cpckts
   where
     doDebug = isJust $ scDebugLog conf
@@ -184,7 +185,7 @@
     -> ServerConfig
     -> DebugLogger
     -> Socket
-    -> SockAddr
+    -> PeerInfo
     -> (ByteString -> IO ())
     -> Int
     -> TimeMicrosecond
@@ -195,13 +196,13 @@
     ServerConfig{..}
     logAction
     mysock
-    peersa
+    peerInfo
     send'
     bytes
     tim
     (cpkt@(CryptPacket (Initial peerVer dCID sCID token) _), lvl, siz)
         | bytes < defaultQUICPacketSize = do
-            logAction $ "too small " <> bhow bytes <> ", " <> bhow peersa
+            logAction $ "too small " <> bhow bytes <> ", " <> bhow peerInfo
         | peerVer `notElem` myVersions = do
             let offerVersions
                     | peerVer == GreasingVersion = GreasingVersion2 : myVersions
@@ -247,7 +248,7 @@
                                 , accMyAuthCIDs = myAuthCIDs
                                 , accPeerAuthCIDs = peerAuthCIDs
                                 , accMySocket = mysock
-                                , accPeerSockAddr = peersa
+                                , accPeerInfo = peerInfo
                                 , accRecvQ = q
                                 , accPacketSize = bytes
                                 , accRegister = reg
@@ -328,7 +329,7 @@
     _
     _
     _mysock
-    _peersa
+    _peerInfo
     _
     _
     tim
@@ -343,7 +344,7 @@
     _
     logAction
     mysock
-    peersa
+    peerInfo
     _
     _
     tim
@@ -351,10 +352,10 @@
         let dCID = headerMyCID hdr
         mconn <- lookupConnectionDict dstTable dCID
         case mconn of
-            Nothing -> logAction $ "CID no match: " <> bhow dCID <> ", " <> bhow peersa
+            Nothing -> logAction $ "CID no match: " <> bhow dCID <> ", " <> bhow peerInfo
             Just conn -> do
                 void $ setSocket conn mysock
-                setPeerSockAddr conn peersa
+                setPeerInfo conn peerInfo
                 writeRecvQ (connRecvQ conn) $ mkReceivedPacket cpkt tim siz lvl
 
 recvServer :: RecvQ -> IO ReceivedPacket
diff --git a/Network/QUIC/Server/Run.hs b/Network/QUIC/Server/Run.hs
--- a/Network/QUIC/Server/Run.hs
+++ b/Network/QUIC/Server/Run.hs
@@ -143,11 +143,11 @@
     -> IO ConnRes
 createServerConnection conf@ServerConfig{..} dispatch Accept{..} baseThreadId = do
     sref <- newIORef accMySocket
-    psaref <- newIORef accPeerSockAddr
+    piref <- newIORef accPeerInfo
     let send buf siz = void $ do
             sock <- readIORef sref
-            sa <- readIORef psaref
-            NS.sendBufTo sock buf siz sa
+            PeerInfo sa cmsgs <- readIORef piref
+            NS.sendBufMsg sock sa [(buf, siz)] cmsgs 0
         recv = recvServer accRecvQ
     let myCID = fromJust $ initSrcCID accMyAuthCIDs
         ocid = fromJust $ origDstCID accMyAuthCIDs
@@ -164,7 +164,7 @@
             qLog
             scHooks
             sref
-            psaref
+            piref
             accRecvQ
             send
             recv
@@ -174,9 +174,10 @@
         ver = chosenVersion accVersionInfo
     initializeCoder conn InitialLevel $ initialSecrets ver cid
     setupCryptoStreams conn -- fixme: cleanup
-    let pktSiz =
-            (defaultPacketSize accPeerSockAddr `max` accPacketSize)
-                `min` maximumPacketSize accPeerSockAddr
+    let PeerInfo peersa _ = accPeerInfo
+        pktSiz =
+            (defaultPacketSize peersa `max` accPacketSize)
+                `min` maximumPacketSize peersa
     setMaxPacketSize conn pktSiz
     setInitialCongestionWindow (connLDCC conn) pktSiz
     debugLog $ "Packet size: " <> bhow pktSiz <> " (" <> bhow accPacketSize <> ")"
diff --git a/Network/QUIC/Stream/Table.hs b/Network/QUIC/Stream/Table.hs
--- a/Network/QUIC/Stream/Table.hs
+++ b/Network/QUIC/Stream/Table.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Network.QUIC.Stream.Table (
     StreamTable,
     emptyStreamTable,
diff --git a/quic.cabal b/quic.cabal
--- a/quic.cabal
+++ b/quic.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               quic
-version:            0.2.0
+version:            0.2.1
 license:            BSD3
 license-file:       LICENSE
 maintainer:         kazu@iij.ad.jp
diff --git a/test/ErrorSpec.hs b/test/ErrorSpec.hs
--- a/test/ErrorSpec.hs
+++ b/test/ErrorSpec.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module ErrorSpec where
 
 import Control.Monad (forever, void)
@@ -28,7 +26,7 @@
     loop conn = forever $ void $ acceptStream conn
 
 teardown :: ThreadId -> IO ()
-teardown tid = killThread tid
+teardown = killThread
 
 spec :: Spec
 spec =
diff --git a/test/PacketSpec.hs b/test/PacketSpec.hs
--- a/test/PacketSpec.hs
+++ b/test/PacketSpec.hs
@@ -49,7 +49,7 @@
     (sock, peersa) <- clientSocket "127.0.0.1" "2000"
     q <- newRecvQ
     sref <- newIORef sock
-    psaref <- newIORef peersa
+    piref <- newIORef $ PeerInfo peersa []
     let ver = v
         verInfo = VersionInfo ver [ver]
     ----
@@ -63,7 +63,7 @@
             noLog
             defaultHooks
             sref
-            psaref
+            piref
             q
             undefined
             undefined
@@ -78,7 +78,7 @@
             noLog
             defaultHooks
             sref
-            psaref -- dummy
+            piref -- dummy
             q
             undefined
             undefined
