diff options
author | joe <joe@jerkface.net> | 2017-11-02 21:24:34 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-11-02 21:24:34 -0400 |
commit | b514e562e0d77b9adb8ca5c75289204013de2968 (patch) | |
tree | 07c3ec90614f9a51bf822f2d6bca1c11da2e5f56 /OnionRouter.hs | |
parent | 30748b9edd4eb8df8998e29f68dfedb218ff8e8c (diff) |
Fixed onion routes for IPv4-mapped IPv6 addresses.
Diffstat (limited to 'OnionRouter.hs')
-rw-r--r-- | OnionRouter.hs | 67 |
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 #-} | ||
2 | module OnionRouter where | 3 | module OnionRouter where |
3 | 4 | ||
4 | import Control.Concurrent.Lifted.Instrument | 5 | import Control.Concurrent.Lifted.Instrument |
5 | import Crypto.Tox | 6 | import Crypto.Tox |
7 | import Network.Address | ||
6 | import Network.Kademlia | 8 | import Network.Kademlia |
7 | import Network.Kademlia.Routing | 9 | import Network.Kademlia.Routing |
8 | import Network.QueryResponse | 10 | import Network.QueryResponse |
@@ -144,7 +146,7 @@ newOnionRouter = do | |||
144 | } | 146 | } |
145 | return or | 147 | return or |
146 | 148 | ||
147 | forkRouteBuilder :: OnionRouter -> (NodeId -> NodeInfo -> IO [NodeInfo]) -> IO OnionRouter | 149 | forkRouteBuilder :: OnionRouter -> (NodeId -> NodeInfo -> IO (Maybe [NodeInfo])) -> IO OnionRouter |
148 | forkRouteBuilder or getnodes = do | 150 | forkRouteBuilder 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 | ||
207 | selectTrampolines :: OnionRouter -> STM [NodeInfo] | 210 | selectTrampolines :: OnionRouter -> IO [NodeInfo] |
208 | selectTrampolines or = do | 211 | selectTrampolines 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 | |||
226 | selectTrampolines' :: OnionRouter -> STM (Either [NodeInfo] [NodeInfo]) | ||
227 | selectTrampolines' 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 | ||
229 | handleEvent :: (NodeId -> NodeInfo -> IO [NodeInfo]) -> OnionRouter -> RouteEvent -> IO () | 248 | handleEvent :: (NodeId -> NodeInfo -> IO (Maybe [NodeInfo])) -> OnionRouter -> RouteEvent -> IO () |
230 | handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do | 249 | handleEvent 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 | |||
405 | nodeClass = ipClass. nodeAddr | 435 | nodeClass = ipClass. nodeAddr |
406 | 436 | ||
407 | ipClass :: SockAddr -> IPClass | 437 | ipClass :: SockAddr -> IPClass |
408 | ipClass (SockAddrInet _ addr) = IPClass (fromBE32 addr .&. 0xFF000000) | 438 | ipClass= either ipClass' ipClass' . either4or6 |
409 | ipClass (SockAddrInet6 _ _ (hiword,_,_,_) _) = IPClass hiword | 439 | |
410 | ipClass _ = IPClass 0 -- unreachable. | 440 | ipClass' :: SockAddr -> IPClass |
441 | ipClass' (SockAddrInet _ addr) = IPClass (fromBE32 addr .&. 0xFF000000) | ||
442 | ipClass' (SockAddrInet6 _ _ (hiword,_,_,_) _) = IPClass hiword | ||
443 | ipClass' _ = IPClass 0 -- unreachable. | ||