2 use std::sync::atomic::Ordering;
3 use std::io::BufReader;
4 use std::net::{IpAddr, Ipv6Addr, SocketAddr};
5 use std::time::Instant;
8 use tokio::io::{stdin, lines};
10 use crate::printer::Printer;
11 use crate::datastore::{Store, AddressState, U64Setting, RegexSetting};
12 use crate::bgp_client::BGPClient;
14 use crate::{START_SHUTDOWN, scan_node};
18 // base32 decoder and tests stolen (transliterated) from Bitcoin Core
19 // Copyright (c) 2012-2019 The Bitcoin Core developers
20 // Distributed under the MIT software license, see
21 // http://www.opensource.org/licenses/mit-license.php.
22 fn decode_base32(inp: &[u8]) -> Option<Vec<u8>> {
23 let decode32_table: [i8; 256] = [
24 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
25 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
26 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
27 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
28 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
29 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
30 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
39 let mut ret = Vec::with_capacity((inp.len() * 5) / 8);
44 if *i == '=' as u8 { break; }
45 let codepoint = decode32_table[*i as usize];
46 if codepoint < 0 { return None; }
47 acc = ((acc << 5) | codepoint as u16) & ((1 << (8 + 5 - 1)) - 1);
51 ret.push((acc >> bits) as u8);
58 fn test_decode_base32() {
59 let tests_in = ["","f","fo","foo","foob","fooba","foobar"];
60 let tests_out = ["","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"];
61 for (inp, out) in tests_in.iter().zip(tests_out.iter()) {
62 assert_eq!(&decode_base32(out.as_bytes()).unwrap()[..], inp.as_bytes());
64 // My seednode's onion addr:
65 assert_eq!(decode_base32("nkf5e6b7pl4jfd4a".as_bytes()).unwrap()[..],[0x6a, 0x8b, 0xd2, 0x78, 0x3f, 0x7a, 0xf8, 0x92, 0x8f, 0x80]);
68 pub fn read(store: &'static Store, printer: &'static Printer, bgp_client: Arc<BGPClient>) {
69 tokio::spawn(lines(BufReader::new(stdin())).for_each(move |line| {
72 printer.add_line(format!("Unparsable input: \"{}\"", line), true);
73 return future::ok(());
76 let mut line_iter = line.split(' ');
77 macro_rules! get_next_chunk {
79 match line_iter.next() {
85 macro_rules! try_parse_next_chunk {
87 match get_next_chunk!().parse::<$type>() {
93 match get_next_chunk!() {
94 "t" => store.set_u64(U64Setting::RunTimeout, try_parse_next_chunk!(u64)),
95 "v" => store.set_u64(U64Setting::MinProtocolVersion, try_parse_next_chunk!(u64)),
96 "w" => store.set_u64(U64Setting::WasGoodTimeout, try_parse_next_chunk!(u64)),
98 if line.len() < 3 || !line.starts_with("s ") {
101 store.set_regex(RegexSetting::SubverRegex, match line[2..].parse::<Regex>() {
107 let host_port = get_next_chunk!();
108 let parsed = if host_port.len() > 23 && &host_port[16..23] == ".onion:" {
109 let port = match host_port[23..].parse::<u16>() { Ok(res) => res, Err(_) => err!(), };
111 let ipv6 = match decode_base32(host_port[0..16].as_bytes()) { Some(res) => res, None => err!(), };
112 if ipv6.len() != 10 { err!(); }
113 let mut octets = [0xFD,0x87,0xD8,0x7E,0xEB,0x43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
114 octets[6..].copy_from_slice(&ipv6[0..10]);
116 SocketAddr::new(IpAddr::V6(Ipv6Addr::from(octets)), port)
118 match host_port.parse::<SocketAddr>() {
119 Ok(res) => res, Err(_) => err!(), }
121 scan_node(Instant::now(), parsed, true)
124 let ip = try_parse_next_chunk!(IpAddr);
125 printer.add_line(format!("ASN for {} is {} (prefixlen, path: {:?})", ip, bgp_client.get_asn(ip), bgp_client.get_path(ip)), false);
128 match AddressState::from_num(try_parse_next_chunk!(u8)) {
129 Some(state) => store.set_u64(U64Setting::RescanInterval(state), try_parse_next_chunk!(u64)),
134 START_SHUTDOWN.store(true, Ordering::SeqCst);
135 return future::err(std::io::Error::new(std::io::ErrorKind::Other, ""));
141 printer.add_line("Shutting down...".to_string(), true);