From 985d0c6ceb9127af9469240d4548a9341fc9be48 Mon Sep 17 00:00:00 2001 From: MikhailMS <1488maiklm@gmail.com> Date: Tue, 20 Feb 2024 12:55:18 +0000 Subject: [PATCH 1/3] Implement suggestion from #27 --- dict_examples/empty_test_dictionary_dict | 0 src/protocol/dictionary.rs | 137 +++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 dict_examples/empty_test_dictionary_dict diff --git a/dict_examples/empty_test_dictionary_dict b/dict_examples/empty_test_dictionary_dict new file mode 100644 index 0000000..e69de29 diff --git a/src/protocol/dictionary.rs b/src/protocol/dictionary.rs index 7d5c86a..bc355ea 100644 --- a/src/protocol/dictionary.rs +++ b/src/protocol/dictionary.rs @@ -159,6 +159,31 @@ impl Dictionary { Ok(Dictionary { attributes, values, vendors }) } + /// Adds a dictionary file to existing Dictionary + pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> { + let mut vendor_name: String = String::new(); + + let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?); + let lines = reader.lines() + .filter_map(Result::ok) + .filter(|line| !line.is_empty()) + .filter(|line| !line.contains(&COMMENT_PREFIX)); + + for line in lines { + let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect(); + match parsed_line[0] { + "ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut self.attributes), + "VALUE" => parse_value(parsed_line, &vendor_name, &mut self.values), + "VENDOR" => parse_vendor(parsed_line, &mut self.vendors), + "BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) }, + "END-VENDOR" => { vendor_name.clear() }, + _ => continue + } + }; + + Ok(()) + } + /// Returns parsed DictionaryAttributes pub fn attributes(&self) -> &[DictionaryAttribute] { &self.attributes @@ -341,4 +366,116 @@ mod tests { let expected_dict = Dictionary { attributes, values, vendors }; assert_eq!(dict, expected_dict) } + + #[test] + fn test_add_file() { + let empty_dictionary_path = "./dict_examples/empty_test_dictionary_dict"; + let dictionary_path = "./dict_examples/test_dictionary_dict"; + + let mut dict = Dictionary::from_file(empty_dictionary_path).unwrap(); + dict.add_file(dictionary_path).unwrap(); + + let mut attributes: Vec = Vec::new(); + attributes.push(DictionaryAttribute { + name: "User-Name".to_string(), + vendor_name: "".to_string(), + code: 1, + code_type: Some(SupportedAttributeTypes::AsciiString) + }); + attributes.push(DictionaryAttribute { + name: "NAS-IP-Address".to_string(), + vendor_name: "".to_string(), + code: 4, + code_type: Some(SupportedAttributeTypes::IPv4Addr) + }); + attributes.push(DictionaryAttribute { + name: "NAS-Port-Id".to_string(), + vendor_name: "".to_string(), + code: 5, + code_type: Some(SupportedAttributeTypes::Integer) + }); + attributes.push(DictionaryAttribute { + name: "Framed-Protocol".to_string(), + vendor_name: "".to_string(), + code: 7, + code_type: Some(SupportedAttributeTypes::Integer) + }); + attributes.push(DictionaryAttribute { + name: "Chargeable-User-Identity".to_string(), + vendor_name: "".to_string(), + code: 89, + code_type: Some(SupportedAttributeTypes::ByteString) + }); + attributes.push(DictionaryAttribute { + name: "Delegated-IPv6-Prefix".to_string(), + vendor_name: "".to_string(), + code: 123, + code_type: Some(SupportedAttributeTypes::IPv6Prefix) + }); + attributes.push(DictionaryAttribute { + name: "MIP6-Feature-Vector".to_string(), + vendor_name: "".to_string(), + code: 124, + code_type: Some(SupportedAttributeTypes::Integer64) + }); + attributes.push(DictionaryAttribute { + name: "Mobile-Node-Identifier".to_string(), + vendor_name: "".to_string(), + code: 145, + code_type: Some(SupportedAttributeTypes::ByteString) + }); + attributes.push(DictionaryAttribute { + name: "PMIP6-Home-Interface-ID".to_string(), + vendor_name: "".to_string(), + code: 153, + code_type: Some(SupportedAttributeTypes::InterfaceId) + }); + attributes.push(DictionaryAttribute { + name: "PMIP6-Home-IPv4-HoA".to_string(), + vendor_name: "".to_string(), + code: 155, + code_type: Some(SupportedAttributeTypes::IPv4Prefix) + }); + attributes.push(DictionaryAttribute { + name: "Somevendor-Name".to_string(), + vendor_name: "Somevendor".to_string(), + code: 1, + code_type: Some(SupportedAttributeTypes::AsciiString) + }); + attributes.push(DictionaryAttribute { + name: "Somevendor-Number".to_string(), + vendor_name: "Somevendor".to_string(), + code: 2, + code_type: Some(SupportedAttributeTypes::Integer) + }); + attributes.push(DictionaryAttribute { + name: "Class".to_string(), + vendor_name: "".to_string(), + code: 25, + code_type: Some(SupportedAttributeTypes::ByteString) + }); + + let mut values: Vec = Vec::new(); + values.push(DictionaryValue { + attribute_name: "Framed-Protocol".to_string(), + value_name: "PPP".to_string(), + vendor_name: "".to_string(), + value: "1".to_string() + }); + values.push(DictionaryValue { + attribute_name: "Somevendor-Number".to_string(), + value_name: "Two".to_string(), + vendor_name: "Somevendor".to_string(), + value: "2".to_string() + }); + + let mut vendors: Vec = Vec::new(); + vendors.push(DictionaryVendor { + name: "Somevendor".to_string(), + id: 10, + }); + + let expected_dict = Dictionary { attributes, values, vendors }; + assert_eq!(dict, expected_dict) + } } From 848fac7b7ff30fad9c757577a12645eedcad2dd3 Mon Sep 17 00:00:00 2001 From: MikhailMS <1488maiklm@gmail.com> Date: Wed, 20 Mar 2024 23:54:48 +0000 Subject: [PATCH 2/3] Update add_file doc comment --- src/protocol/dictionary.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocol/dictionary.rs b/src/protocol/dictionary.rs index bc355ea..4ef57f2 100644 --- a/src/protocol/dictionary.rs +++ b/src/protocol/dictionary.rs @@ -160,6 +160,9 @@ impl Dictionary { } /// Adds a dictionary file to existing Dictionary + /// + /// Processes attributes, values and vendors from supplied dictionary file + /// and adds them to existing attributes, values and vendors pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> { let mut vendor_name: String = String::new(); From e7705610af855d340d42745abde5eb3115286397 Mon Sep 17 00:00:00 2001 From: MikhailMS <1488maiklm@gmail.com> Date: Sat, 23 Mar 2024 21:32:35 +0000 Subject: [PATCH 3/3] Completes #27 --- src/protocol/dictionary.rs | 71 ++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/src/protocol/dictionary.rs b/src/protocol/dictionary.rs index 4ef57f2..8691da1 100644 --- a/src/protocol/dictionary.rs +++ b/src/protocol/dictionary.rs @@ -137,26 +137,11 @@ impl Dictionary { let mut attributes: Vec = Vec::new(); let mut values: Vec = Vec::new(); let mut vendors: Vec = Vec::new(); - let mut vendor_name: String = String::new(); - - let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?); - let lines = reader.lines() - .filter_map(Result::ok) - .filter(|line| !line.is_empty()) - .filter(|line| !line.contains(&COMMENT_PREFIX)); - - for line in lines { - let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect(); - match parsed_line[0] { - "ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut attributes), - "VALUE" => parse_value(parsed_line, &vendor_name, &mut values), - "VENDOR" => parse_vendor(parsed_line, &mut vendors), - "BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) }, - "END-VENDOR" => { vendor_name.clear() }, - _ => continue - } - }; - Ok(Dictionary { attributes, values, vendors }) + + match parse_file(file_path, &mut attributes, &mut values, &mut vendors) { + Ok(()) => Ok(Dictionary { attributes, values, vendors }), + Err(error) => Err(error) + } } /// Adds a dictionary file to existing Dictionary @@ -164,27 +149,7 @@ impl Dictionary { /// Processes attributes, values and vendors from supplied dictionary file /// and adds them to existing attributes, values and vendors pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> { - let mut vendor_name: String = String::new(); - - let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?); - let lines = reader.lines() - .filter_map(Result::ok) - .filter(|line| !line.is_empty()) - .filter(|line| !line.contains(&COMMENT_PREFIX)); - - for line in lines { - let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect(); - match parsed_line[0] { - "ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut self.attributes), - "VALUE" => parse_value(parsed_line, &vendor_name, &mut self.values), - "VENDOR" => parse_vendor(parsed_line, &mut self.vendors), - "BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) }, - "END-VENDOR" => { vendor_name.clear() }, - _ => continue - } - }; - - Ok(()) + parse_file(file_path, &mut self.attributes, &mut self.values, &mut self.vendors) } /// Returns parsed DictionaryAttributes @@ -226,6 +191,30 @@ fn assign_attribute_type(code_type: &str) -> Option { } } +fn parse_file(file_path: &str, attributes: &mut Vec, values: &mut Vec, vendors: &mut Vec) -> Result<(), RadiusError> { + let mut vendor_name: String = String::new(); + + let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?); + let lines = reader.lines() + .filter_map(Result::ok) + .filter(|line| !line.is_empty()) + .filter(|line| !line.contains(&COMMENT_PREFIX)); + + for line in lines { + let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect(); + match parsed_line[0] { + "ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, attributes), + "VALUE" => parse_value(parsed_line, &vendor_name, values), + "VENDOR" => parse_vendor(parsed_line, vendors), + "BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) }, + "END-VENDOR" => { vendor_name.clear() }, + _ => continue + } + }; + + Ok(()) +} + fn parse_attribute(parsed_line: Vec<&str>, vendor_name: &str, attributes: &mut Vec) { if let Ok(code) = parsed_line[2].parse::() { attributes.push(DictionaryAttribute {