summaryrefslogtreecommitdiff
path: root/OnionRouter.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-11-02 21:24:34 -0400
committerjoe <joe@jerkface.net>2017-11-02 21:24:34 -0400
commitb514e562e0d77b9adb8ca5c75289204013de2968 (patch)
tree07c3ec90614f9a51bf822f2d6bca1c11da2e5f56 /OnionRouter.hs
parent30748b9edd4eb8df8998e29f68dfedb218ff8e8c (diff)
Fixed onion routes for IPv4-mapped IPv6 addresses.
Diffstat (limited to 'OnionRouter.hs')
-rw-r--r--OnionRouter.hs67
1 files changed, 50 insertions, 17 deletions
diff --git a/OnionRouter.hs b/OnionRouter.hs
index 26bc6525..eb79b70b 100644
--- a/OnionRouter.hs
+++ b/OnionRouter.hs
@@ -1,8 +1,10 @@
1{-# LANGUAGE NondecreasingIndentation #-} 1{-# LANGUAGE NondecreasingIndentation #-}
2{-# LANGUAGE LambdaCase #-}
2module OnionRouter where 3module OnionRouter where
3 4
4import Control.Concurrent.Lifted.Instrument 5import Control.Concurrent.Lifted.Instrument
5import Crypto.Tox 6import Crypto.Tox
7import Network.Address
6import Network.Kademlia 8import Network.Kademlia
7import Network.Kademlia.Routing 9import Network.Kademlia.Routing
8import Network.QueryResponse 10import Network.QueryResponse
@@ -144,7 +146,7 @@ newOnionRouter = do
144 } 146 }
145 return or 147 return or
146 148
147forkRouteBuilder :: OnionRouter -> (NodeId -> NodeInfo -> IO [NodeInfo]) -> IO OnionRouter 149forkRouteBuilder :: OnionRouter -> (NodeId -> NodeInfo -> IO (Maybe [NodeInfo])) -> IO OnionRouter
148forkRouteBuilder or getnodes = do 150forkRouteBuilder or getnodes = do
149 tid <- forkIO $ do 151 tid <- forkIO $ do
150 me <- myThreadId 152 me <- myThreadId
@@ -152,7 +154,8 @@ forkRouteBuilder or getnodes = do
152 forever $ do 154 forever $ do
153 let checkRebuild rid want_build stm = flip orElse stm $ do 155 let checkRebuild rid want_build stm = flip orElse stm $ do
154 readTVar want_build >>= check 156 readTVar want_build >>= check
155 writeTVar want_build False 157 -- This was moved to handleEvent to allow retry on fail.
158 -- writeTVar want_build False -- Prevent redundant BuildRoute events.
156 return $ BuildRoute $ RouteId rid 159 return $ BuildRoute $ RouteId rid
157 io <- atomically $ 160 io <- atomically $
158 (readTChan (routeLog or) >>= return . hPutStrLn stderr) 161 (readTChan (routeLog or) >>= return . hPutStrLn stderr)
@@ -204,8 +207,24 @@ randomIvalInteger (l,h) rng
204 (x,g') = next g -- next :: RandomGen g => g -> (Int, g) 207 (x,g') = next g -- next :: RandomGen g => g -> (Int, g)
205 v' = (v * b + (fromIntegral x - fromIntegral genlo)) 208 v' = (v * b + (fromIntegral x - fromIntegral genlo))
206 209
207selectTrampolines :: OnionRouter -> STM [NodeInfo] 210selectTrampolines :: OnionRouter -> IO [NodeInfo]
208selectTrampolines or = do 211selectTrampolines or = do
212 myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines")
213 atomically (selectTrampolines' or) >>= \case
214 Left ns -> do
215 -- atomically $ writeTChan (routeLog or)
216 hPutStrLn stderr $ unwords
217 ( "ONION Discarding insecure trampolines:" : (map (show . nodeAddr) ns) )
218 myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines.sleep")
219 threadDelay 1000000
220 myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines")
221 selectTrampolines or
222 Right ns -> do
223 myThreadId >>= flip labelThread ("OnionRouter")
224 return ns
225
226selectTrampolines' :: OnionRouter -> STM (Either [NodeInfo] [NodeInfo])
227selectTrampolines' or = do
209 cnt <- readTVar (trampolineCount or) 228 cnt <- readTVar (trampolineCount or)
210 ts <- readTVar (trampolineNodes or) 229 ts <- readTVar (trampolineNodes or)
211 drg0 <- readTVar (onionDRG or) 230 drg0 <- readTVar (onionDRG or)
@@ -220,17 +239,18 @@ selectTrampolines or = do
220 | otherwise = c1 + 1 239 | otherwise = c1 + 1
221 ns = mapMaybe (\n -> IntMap.lookup n ts) [a,b,c] 240 ns = mapMaybe (\n -> IntMap.lookup n ts) [a,b,c]
222 ns' <- case ns of 241 ns' <- case ns of
223 [an,bn,cn] -> do check $ distinct3by nodeClass an bn cn 242 [an,bn,cn] | distinct3by nodeClass an bn cn
224 return ns 243 -> return $ Right ns
225 _ -> retry 244 _ -> return $ Left ns
226 writeTVar (onionDRG or) drg 245 writeTVar (onionDRG or) drg
227 return ns' 246 return ns'
228 247
229handleEvent :: (NodeId -> NodeInfo -> IO [NodeInfo]) -> OnionRouter -> RouteEvent -> IO () 248handleEvent :: (NodeId -> NodeInfo -> IO (Maybe [NodeInfo])) -> OnionRouter -> RouteEvent -> IO ()
230handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do 249handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do
231 hPutStrLn stderr $ "ONION Rebuilding RouteId " ++ show rid 250 hPutStrLn stderr $ "ONION Rebuilding RouteId " ++ show rid
232 mb <- join . atomically $ do 251 mb <- do
233 ts <- selectTrampolines or 252 ts <- selectTrampolines or
253 join . atomically $ do
234 drg <- readTVar (onionDRG or) 254 drg <- readTVar (onionDRG or)
235 [av,bv,cv] <- sequence $ replicate 3 (newTVar Nothing) 255 [av,bv,cv] <- sequence $ replicate 3 (newTVar Nothing)
236 let (getr, drg') = withDRG drg $ do 256 let (getr, drg') = withDRG drg $ do
@@ -244,7 +264,7 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do
244 let asel = sel .&. 0x3 264 let asel = sel .&. 0x3
245 bsel = shiftR sel 2 .&. 0x3 265 bsel = shiftR sel 2 .&. 0x3
246 csel = shiftR sel 4 .&. 0x3 266 csel = shiftR sel 4 .&. 0x3
247 sendq s q ni = listToMaybe . drop (fromIntegral s) <$> getnodes q ni 267 sendq s q ni = fmap (listToMaybe . drop (fromIntegral s)) <$> getnodes q ni
248 sendqs = do 268 sendqs = do
249 forkIO $ sendq asel aq (ts !! 0) >>= atomically . writeTVar av . Just 269 forkIO $ sendq asel aq (ts !! 0) >>= atomically . writeTVar av . Just
250 forkIO $ sendq bsel bq (ts !! 1) >>= atomically . writeTVar bv . Just 270 forkIO $ sendq bsel bq (ts !! 1) >>= atomically . writeTVar bv . Just
@@ -252,18 +272,26 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do
252 atomically $ do -- Wait for all 3 results. 272 atomically $ do -- Wait for all 3 results.
253 rs <- catMaybes <$> sequence [readTVar av,readTVar bv,readTVar cv] 273 rs <- catMaybes <$> sequence [readTVar av,readTVar bv,readTVar cv]
254 case rs of [_,_,_] -> do 274 case rs of [_,_,_] -> do
255 return $ catMaybes rs 275 return $ catMaybes $ catMaybes rs
256 -- self <- IntMap.lookup (-1) <$> readTVar (trampolineNodes or) 276 -- self <- IntMap.lookup (-1) <$> readTVar (trampolineNodes or)
257 -- return $ maybe (catMaybes rs) (\x -> [x,x,x]) self 277 -- return $ maybe (catMaybes rs) (\x -> [x,x,x]) self
258 _ -> retry 278 _ -> retry
259 return $ do 279 return $ do
260 nodes <- sendqs 280 myThreadId >>= flip labelThread ("OnionRouter.sendqs")
281 nodes <- case ts of
282 [_,_,_] -> sendqs
283 _ -> return []
284 myThreadId >>= flip labelThread ("OnionRouter")
261 hPutStr stderr $ unlines 285 hPutStr stderr $ unlines
262 [ "ONION trampolines: " ++ show ts 286 [ "ONION trampolines: " ++ show ts
263 , "ONION query results: " ++ show nodes ] 287 , "ONION query results: " ++ show nodes ]
264 case nodes of 288 case nodes of
265 [a,b,c] | distinct3by nodeClass a b c -> do 289 [a,b,c] | distinct3by nodeClass a b c -> do
266 atomically $ writeTChan (routeLog or) $ unwords [ "ONION using route:", show $ nodeAddr a, show $ nodeAddr b, show $ nodeAddr c] 290 atomically $ do
291 writeTChan (routeLog or) $ unwords [ "ONION using route:"
292 , show $ nodeAddr a
293 , show $ nodeAddr b
294 , show $ nodeAddr c ]
267 return $ Just OnionRoute 295 return $ Just OnionRoute
268 { routeAliasA = asec 296 { routeAliasA = asec
269 , routeAliasB = bsec 297 , routeAliasB = bsec
@@ -279,8 +307,10 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do
279 writeTVar (onionDRG or) drg' 307 writeTVar (onionDRG or) drg'
280 return $ getr 308 return $ getr
281 atomically $ maybe (writeTVar (pendingRoutes or IntMap.! rid) True) 309 atomically $ maybe (writeTVar (pendingRoutes or IntMap.! rid) True)
282 (\r -> modifyTVar' (routeMap or) 310 (\r -> do modifyTVar' (routeMap or)
283 (IntMap.insert rid $ freshRoute r)) 311 (IntMap.insert rid $ freshRoute r)
312 writeTVar (pendingRoutes or IntMap.! rid) False
313 )
284 mb 314 mb
285 case mb of 315 case mb of
286 Just _ -> hPutStrLn stderr $ "ONION Finished RouteId " ++ show rid 316 Just _ -> hPutStrLn stderr $ "ONION Finished RouteId " ++ show rid
@@ -405,6 +435,9 @@ nodeClass :: NodeInfo -> IPClass
405nodeClass = ipClass. nodeAddr 435nodeClass = ipClass. nodeAddr
406 436
407ipClass :: SockAddr -> IPClass 437ipClass :: SockAddr -> IPClass
408ipClass (SockAddrInet _ addr) = IPClass (fromBE32 addr .&. 0xFF000000) 438ipClass= either ipClass' ipClass' . either4or6
409ipClass (SockAddrInet6 _ _ (hiword,_,_,_) _) = IPClass hiword 439
410ipClass _ = IPClass 0 -- unreachable. 440ipClass' :: SockAddr -> IPClass
441ipClass' (SockAddrInet _ addr) = IPClass (fromBE32 addr .&. 0xFF000000)
442ipClass' (SockAddrInet6 _ _ (hiword,_,_,_) _) = IPClass hiword
443ipClass' _ = IPClass 0 -- unreachable.