log_analysis/
ip2location.rs

1use reqwest::blocking::Client;
2use std::error::Error;
3use std::sync::{Arc,Mutex};
4
5use crate::zeek::zeek_log_proto::ZeekProtocol;
6use crate::zeek::zeek_log::Data;
7use crate::types::helpers::print_type_of;
8
9#[derive(Debug, PartialEq, Eq, Clone)]
10pub struct IP2LocationResponse 
11{
12    ip: Option<String>,
13    country_code: Option<String>,
14    country_name: Option<String>,
15    region_name: Option<String>,
16    city_name: Option<String>,
17    latitude: Option<String>, 
18    longitude: Option<String>, 
19    zip_code: Option<String>, 
20    time_zone: Option<String>,
21    auto_system_num: Option<String>,
22    auto_system_name: Option<String>,
23    is_proxy: Option<String>,
24}
25
26impl IP2LocationResponse
27{
28    pub fn new() -> Self//IP2LocationResponse 
29    {
30        IP2LocationResponse {
31            ip: None,
32            country_code: None,
33            country_name: None,
34            region_name: None,
35            city_name: None,
36            latitude: None, 
37            longitude: None, 
38            zip_code: None,
39            time_zone: None,
40            auto_system_num: None,
41            auto_system_name: None,
42            is_proxy: None,
43        }
44    }
45
46    fn set_ip(&mut self, val: String) 
47    {
48        self.ip = Some(val);
49    }
50    fn set_country_code(&mut self, val: String) 
51    {
52        self.country_code= Some(val);
53    }
54    fn set_country_name(&mut self, val: String) 
55    {
56        self.country_name = Some(val);
57    }
58    fn set_region_name(&mut self, val: String) 
59    {
60        self.region_name = Some(val);
61    }
62    fn set_city_name(&mut self, val: String) 
63    {
64        self.city_name = Some(val);
65    }
66    fn set_latitude(&mut self, val: String) 
67    {
68        self.latitude = Some(val);
69    }
70    fn set_longitude(&mut self, val: String) 
71    {
72        self.longitude = Some(val);
73    }
74    fn set_zip_code(&mut self, val: String) 
75    {
76        self.zip_code = Some(val);
77    }
78    fn set_time_zone(&mut self, val: String) 
79    {
80        self.time_zone = Some(val);
81    }
82    fn set_auto_system_num(&mut self, val: String) 
83    {
84        self.auto_system_num = Some(val);
85    }
86    fn set_auto_system_name(&mut self, val: String) 
87    {
88        self.auto_system_name = Some(val);
89    }
90    fn set_is_proxy(&mut self, val: String) 
91    {
92        self.is_proxy = Some(val);
93    }
94    pub fn create(&mut self, data: &str)
95    {
96        if let Some(data) = data.strip_prefix("{")
97        {
98            if let Some(data) = data.strip_suffix("}")
99            {
100                let data: Vec<&str> = data.split(',').collect();
101                for prop in data.iter()
102                {
103                    let item = &prop.split(':').collect::<Vec<&str>>();
104                    dbg!(&item);
105                    match item[0].trim_matches('"')
106                    {
107                        "ip" => {self.set_ip(String::from(item[1].trim_matches('"')));},
108                        "country_code" => {self.set_country_code(String::from(item[1].trim_matches('"')));},
109                        "country_name" => {self.set_country_name(String::from(item[1].trim_matches('"')));},
110                        "region_name" => {self.set_region_name(String::from(item[1].trim_matches('"')));},
111                        "city_name" => {self.set_city_name(String::from(item[1].trim_matches('"')));},
112                        "latitude" => {self.set_latitude(String::from(item[1].trim_matches('"')));},
113                        "longitude" => {self.set_longitude(String::from(item[1].trim_matches('"')));},
114                        "zip_code" => {self.set_zip_code(String::from(item[1].trim_matches('"')));},
115                        "time_zone" => {self.set_time_zone(String::from(item[1].trim_matches('"')));},
116                        "asn" => {self.set_auto_system_num(String::from(item[1].trim_matches('"')));},
117                        "as" => {self.set_auto_system_name(String::from(item[1].trim_matches('"')));},
118                        "is_proxy" => {self.set_is_proxy(String::from(item[1].trim_matches('"')));},
119                        _ => println!("implement {:?}", &item[0]),
120                    }
121                }
122            }
123        };
124    }
125}
126
127// For now, the local db will remain during development. Eventually, a database
128// will exist to retrieve known IP addresses and store new log dates. This library 
129// is will primarily function as a custom solution that takes care of retrieving logs,
130// populating a database, returning relevant summaries for the client.
131pub fn request(ip_addr: &String) -> Result<String, String>
132{
133    let local_json_db = std::env::var("LOCAL_JSON_DB").unwrap();
134    let local_json_db = local_json_db.as_str();
135    if local_json_db == "ip2loc.json"
136    {
137        use std::io::BufRead;
138        let file = std::fs::File::open(local_json_db).expect("local json db should exist"); 
139        let mut buffer = String::new();
140        let mut reader = std::io::BufReader::new(&file);
141        let mut res = String::new();
142        let mut found: bool = false;
143        let mut count = 0;
144        let mut lines_iter = reader.lines().map(|line| line.unwrap());
145        while let Some(line) = lines_iter.next()
146        {
147            if line.contains(ip_addr.as_str())
148            {
149                res.push_str("{");
150                res.push_str(&line);
151                while count < 11 // 12 items expected in the free tier ip2location response.
152                {
153                    let line = lines_iter.next().unwrap();
154                    let line = line.replace('\t',"").replace('\r',"")
155                        .replace('\n',"").replace(' ',"");
156                    res.push_str(&line);
157                    count = count + 1;
158                }
159                res.push_str("}");
160                return Ok(res);
161            }
162        }
163    } 
164    else
165    {
166        let api_key = std::env::var("IP2LOCATION_API_KEY")
167            .expect("add IP2LOCATION_API_KEY to $CARGO_HOME/config.toml");
168        let url = format!("https://api.ip2location.io/?key={}&ip={}&format=json",api_key, ip_addr.as_str());
169        let client = Client::new();
170        let b = client.get(url).send();
171        if let Ok(res) = b
172        {
173            let res = res.text().unwrap();
174            return Ok(res);
175        }
176    }
177    Err("create an error for this at some point".to_string())
178}
179