mirror of
https://github.com/cubixle/radius-rs.git
synced 2026-04-30 15:58:44 +01:00
Support dict defined value
This commit is contained in:
+123
-56
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufWriter, Write};
|
use std::io::{BufRead, BufWriter, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -12,6 +12,8 @@ use regex::Regex;
|
|||||||
const ATTRIBUTE_KIND: &str = "ATTRIBUTE";
|
const ATTRIBUTE_KIND: &str = "ATTRIBUTE";
|
||||||
const VALUE_KIND: &str = "VALUE";
|
const VALUE_KIND: &str = "VALUE";
|
||||||
|
|
||||||
|
const RADIUS_VALUE_TYPE: &str = "u32";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RadiusAttribute {
|
struct RadiusAttribute {
|
||||||
name: String,
|
name: String,
|
||||||
@@ -23,7 +25,7 @@ struct RadiusAttribute {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RadiusValue {
|
struct RadiusValue {
|
||||||
name: String,
|
name: String,
|
||||||
typ: u16,
|
value: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@@ -78,71 +80,119 @@ fn main() {
|
|||||||
panic!("no such dictionary file => {}", &matches.free[0]);
|
panic!("no such dictionary file => {}", &matches.free[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rfc_code = dict_file_path.extension().unwrap().to_str().unwrap();
|
let (radius_attributes, radius_attribute_to_values_map) =
|
||||||
let struct_name = rfc_code.to_uppercase();
|
parse_dict_file(dict_file_path).unwrap();
|
||||||
|
|
||||||
let (radius_attributes, radius_attribute_to_values) = parse_dict_file(dict_file_path).unwrap();
|
let value_defined_attributes_set = radius_attribute_to_values_map
|
||||||
|
.keys()
|
||||||
|
.collect::<HashSet<&String>>();
|
||||||
|
|
||||||
let mut buf_writer = BufWriter::new(File::create(&matches.free[1]).unwrap());
|
let mut w = BufWriter::new(File::create(&matches.free[1]).unwrap());
|
||||||
|
|
||||||
generate_header(&mut buf_writer, &struct_name);
|
generate_header(&mut w);
|
||||||
generate_attributes_code(&mut buf_writer, &radius_attributes);
|
generate_values_code(&mut w, &radius_attribute_to_values_map);
|
||||||
generate_footer(&mut buf_writer);
|
generate_attributes_code(&mut w, &radius_attributes, &value_defined_attributes_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_header(w: &mut BufWriter<File>, struct_name: &str) {
|
fn generate_header(w: &mut BufWriter<File>) {
|
||||||
let code = format!(
|
let code = b"// Code generated by machine generator; DO NOT EDIT.
|
||||||
"// Code generated by machine generator; DO NOT EDIT.
|
|
||||||
|
|
||||||
use std::net::{{Ipv4Addr, Ipv6Addr}};
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use crate::attribute::Attribute;
|
use crate::attribute::Attribute;
|
||||||
use crate::attributes::AVPType;
|
use crate::attributes::AVPType;
|
||||||
use crate::packet::Packet;
|
use crate::packet::Packet;
|
||||||
|
|
||||||
pub struct {struct_name} {{
|
";
|
||||||
}}
|
|
||||||
impl {struct_name} {{
|
|
||||||
",
|
|
||||||
struct_name = struct_name
|
|
||||||
);
|
|
||||||
|
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_footer(w: &mut BufWriter<File>) {
|
fn generate_values_code(
|
||||||
w.write_all(b"}\n").unwrap();
|
w: &mut BufWriter<File>,
|
||||||
}
|
attr_to_values_map: &HashMap<String, Vec<RadiusValue>>,
|
||||||
|
) {
|
||||||
fn generate_attributes_code(w: &mut BufWriter<File>, attrs: &[RadiusAttribute]) {
|
for (attr, values) in attr_to_values_map {
|
||||||
for attr in attrs {
|
generate_values_for_attribute_code(w, attr, values);
|
||||||
generate_attribute_code(w, attr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_attribute_code(w: &mut BufWriter<File>, attr: &RadiusAttribute) {
|
fn generate_values_for_attribute_code(
|
||||||
|
w: &mut BufWriter<File>,
|
||||||
|
attr: &String,
|
||||||
|
values: &[RadiusValue],
|
||||||
|
) {
|
||||||
|
let type_name = attr.to_pascal_case();
|
||||||
|
w.write_all(
|
||||||
|
format!(
|
||||||
|
"\npub type {type_name} = {radius_value_type};\n",
|
||||||
|
type_name = type_name,
|
||||||
|
radius_value_type = RADIUS_VALUE_TYPE
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
for v in values {
|
||||||
|
w.write_all(
|
||||||
|
format!(
|
||||||
|
"pub const {type_name_prefix}_{value_name}: {type_name} = {value};\n",
|
||||||
|
type_name_prefix = type_name.to_screaming_snake_case(),
|
||||||
|
value_name = v.name.to_screaming_snake_case(),
|
||||||
|
type_name = type_name,
|
||||||
|
value = v.value,
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
w.write_all(b"\n").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_attributes_code(
|
||||||
|
w: &mut BufWriter<File>,
|
||||||
|
attrs: &[RadiusAttribute],
|
||||||
|
value_defined_attributes_set: &HashSet<&String>,
|
||||||
|
) {
|
||||||
|
for attr in attrs {
|
||||||
|
generate_attribute_code(w, attr, &value_defined_attributes_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_attribute_code(
|
||||||
|
w: &mut BufWriter<File>,
|
||||||
|
attr: &RadiusAttribute,
|
||||||
|
value_defined_attributes_set: &HashSet<&String>,
|
||||||
|
) {
|
||||||
let attr_name = attr.name.clone();
|
let attr_name = attr.name.clone();
|
||||||
let type_identifier = format!("{}_TYPE", attr_name.to_screaming_snake_case());
|
let type_identifier = format!("{}_TYPE", attr_name.to_screaming_snake_case());
|
||||||
let type_calling = format!("Self::{}", type_identifier);
|
|
||||||
let type_value = attr.typ;
|
let type_value = attr.typ;
|
||||||
let method_identifier = attr_name.to_snake_case();
|
let method_identifier = attr_name.to_snake_case();
|
||||||
|
|
||||||
generate_common_attribute_code(w, &attr_name, &type_identifier, &type_calling, type_value);
|
generate_common_attribute_code(w, &attr_name, &type_identifier, type_value);
|
||||||
match attr.value_type {
|
match attr.value_type {
|
||||||
RadiusAttributeValueType::String => {
|
RadiusAttributeValueType::String => {
|
||||||
generate_string_attribute_code(w, &method_identifier, &type_calling)
|
generate_string_attribute_code(w, &method_identifier, &type_identifier)
|
||||||
}
|
}
|
||||||
RadiusAttributeValueType::UserPassword => {
|
RadiusAttributeValueType::UserPassword => {
|
||||||
generate_user_password_attribute_code(w, &method_identifier, &type_calling)
|
generate_user_password_attribute_code(w, &method_identifier, &type_identifier)
|
||||||
}
|
}
|
||||||
RadiusAttributeValueType::Octets => {
|
RadiusAttributeValueType::Octets => {
|
||||||
generate_octets_attribute_code(w, &method_identifier, &type_calling)
|
generate_octets_attribute_code(w, &method_identifier, &type_identifier)
|
||||||
}
|
}
|
||||||
RadiusAttributeValueType::IpAddr => {
|
RadiusAttributeValueType::IpAddr => {
|
||||||
generate_ipaddr_attribute_code(w, &method_identifier, &type_calling)
|
generate_ipaddr_attribute_code(w, &method_identifier, &type_identifier)
|
||||||
}
|
}
|
||||||
RadiusAttributeValueType::Integer => {
|
RadiusAttributeValueType::Integer => {
|
||||||
generate_integer_attribute_code(w, &method_identifier, &type_calling)
|
if value_defined_attributes_set.contains(&attr_name) {
|
||||||
|
generate_value_defined_integer_attribute_code(
|
||||||
|
w,
|
||||||
|
&method_identifier,
|
||||||
|
&type_identifier,
|
||||||
|
&attr_name.to_pascal_case(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
generate_integer_attribute_code(w, &method_identifier, &type_identifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RadiusAttributeValueType::VSA => generate_vsa_attribute_code(),
|
RadiusAttributeValueType::VSA => generate_vsa_attribute_code(),
|
||||||
}
|
}
|
||||||
@@ -152,25 +202,23 @@ fn generate_common_attribute_code(
|
|||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
attr_name: &str,
|
attr_name: &str,
|
||||||
type_identifier: &str,
|
type_identifier: &str,
|
||||||
type_calling: &str,
|
|
||||||
type_value: u8,
|
type_value: u8,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"
|
"
|
||||||
pub const {type_identifier}: AVPType = {type_value};
|
pub const {type_identifier}: AVPType = {type_value};
|
||||||
pub fn delete_{method_identifier}(packet: &mut Packet) {{
|
pub fn delete_{method_identifier}(packet: &mut Packet) {{
|
||||||
packet.delete({type_calling});
|
packet.delete({type_identifier});
|
||||||
}}
|
}}
|
||||||
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<&Attribute> {{
|
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<&Attribute> {{
|
||||||
packet.lookup({type_calling})
|
packet.lookup({type_identifier})
|
||||||
}}
|
}}
|
||||||
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Vec<&Attribute> {{
|
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Vec<&Attribute> {{
|
||||||
packet.lookup_all({type_calling})
|
packet.lookup_all({type_identifier})
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = attr_name.to_snake_case(),
|
method_identifier = attr_name.to_snake_case(),
|
||||||
type_identifier = type_identifier,
|
type_identifier = type_identifier,
|
||||||
type_calling = type_calling,
|
|
||||||
type_value = type_value,
|
type_value = type_value,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
@@ -179,16 +227,16 @@ pub fn lookup_all_{method_identifier}(packet: &Packet) -> Vec<&Attribute> {{
|
|||||||
fn generate_string_attribute_code(
|
fn generate_string_attribute_code(
|
||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
method_identifier: &str,
|
method_identifier: &str,
|
||||||
type_calling: &str,
|
type_identifier: &str,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"pub fn add_{method_identifier}(packet: &mut Packet, value: &str) {{
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: &str) {{
|
||||||
let attr = Attribute::from_string(value);
|
let attr = Attribute::from_string(value);
|
||||||
packet.add({type_calling}, &attr);
|
packet.add({type_identifier}, &attr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = method_identifier,
|
method_identifier = method_identifier,
|
||||||
type_calling = type_calling,
|
type_identifier = type_identifier,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
@@ -196,17 +244,17 @@ fn generate_string_attribute_code(
|
|||||||
fn generate_user_password_attribute_code(
|
fn generate_user_password_attribute_code(
|
||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
method_identifier: &str,
|
method_identifier: &str,
|
||||||
type_calling: &str,
|
type_identifier: &str,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), String> {{
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), String> {{
|
||||||
let attr = Attribute::from_user_password(value, packet.get_secret(), packet.get_authenticator())?;
|
let attr = Attribute::from_user_password(value, packet.get_secret(), packet.get_authenticator())?;
|
||||||
packet.add({type_calling}, &attr);
|
packet.add({type_identifier}, &attr);
|
||||||
Ok(())
|
Ok(())
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = method_identifier,
|
method_identifier = method_identifier,
|
||||||
type_calling = type_calling,
|
type_identifier = type_identifier,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
@@ -214,16 +262,16 @@ fn generate_user_password_attribute_code(
|
|||||||
fn generate_octets_attribute_code(
|
fn generate_octets_attribute_code(
|
||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
method_identifier: &str,
|
method_identifier: &str,
|
||||||
type_calling: &str,
|
type_identifier: &str,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) {{
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) {{
|
||||||
let attr = Attribute::from_bytes(value);
|
let attr = Attribute::from_bytes(value);
|
||||||
packet.add({type_calling}, &attr);
|
packet.add({type_identifier}, &attr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = method_identifier,
|
method_identifier = method_identifier,
|
||||||
type_calling = type_calling,
|
type_identifier = type_identifier,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
@@ -231,16 +279,16 @@ fn generate_octets_attribute_code(
|
|||||||
fn generate_ipaddr_attribute_code(
|
fn generate_ipaddr_attribute_code(
|
||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
method_identifier: &str,
|
method_identifier: &str,
|
||||||
type_calling: &str,
|
type_identifier: &str,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv4Addr) {{
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv4Addr) {{
|
||||||
let attr = Attribute::from_ipv4(value);
|
let attr = Attribute::from_ipv4(value);
|
||||||
packet.add({type_calling}, &attr);
|
packet.add({type_identifier}, &attr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = method_identifier,
|
method_identifier = method_identifier,
|
||||||
type_calling = type_calling,
|
type_identifier = type_identifier,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
@@ -248,16 +296,35 @@ fn generate_ipaddr_attribute_code(
|
|||||||
fn generate_integer_attribute_code(
|
fn generate_integer_attribute_code(
|
||||||
w: &mut BufWriter<File>,
|
w: &mut BufWriter<File>,
|
||||||
method_identifier: &str,
|
method_identifier: &str,
|
||||||
type_calling: &str,
|
type_identifier: &str,
|
||||||
) {
|
) {
|
||||||
let code = format!(
|
let code = format!(
|
||||||
"pub fn add_{method_identifier}(packet: &mut Packet, value: u32) {{
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: u32) {{
|
||||||
let attr = Attribute::from_u32(value);
|
let attr = Attribute::from_u32(value);
|
||||||
packet.add({type_calling}, &attr);
|
packet.add({type_identifier}, &attr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
method_identifier = method_identifier,
|
method_identifier = method_identifier,
|
||||||
type_calling = type_calling,
|
type_identifier = type_identifier,
|
||||||
|
);
|
||||||
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_value_defined_integer_attribute_code(
|
||||||
|
w: &mut BufWriter<File>,
|
||||||
|
method_identifier: &str,
|
||||||
|
type_identifier: &str,
|
||||||
|
value_type: &str,
|
||||||
|
) {
|
||||||
|
let code = format!(
|
||||||
|
"pub fn add_{method_identifier}(packet: &mut Packet, value: {value_type}) {{
|
||||||
|
let attr = Attribute::from_u32(value as u32);
|
||||||
|
packet.add({type_identifier}, &attr);
|
||||||
|
}}
|
||||||
|
",
|
||||||
|
method_identifier = method_identifier,
|
||||||
|
type_identifier = type_identifier,
|
||||||
|
value_type = value_type,
|
||||||
);
|
);
|
||||||
w.write_all(code.as_bytes()).unwrap();
|
w.write_all(code.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
@@ -326,7 +393,7 @@ fn parse_dict_file(dict_file_path: &Path) -> Result<DictParsed, String> {
|
|||||||
|
|
||||||
let radius_value = RadiusValue {
|
let radius_value = RadiusValue {
|
||||||
name,
|
name,
|
||||||
typ: items[3].parse().unwrap(),
|
value: items[3].parse().unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match radius_attribute_to_values.get_mut(&attribute_name) {
|
match radius_attribute_to_values.get_mut(&attribute_name) {
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ impl Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_authenticator(&self) -> &Vec<u8> {
|
pub fn get_authenticator(&self) -> &Vec<u8> {
|
||||||
&self.get_authenticator()
|
&self.authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(bs: &[u8], secret: &[u8]) -> Result<Self, String> {
|
pub fn parse(bs: &[u8], secret: &[u8]) -> Result<Self, String> {
|
||||||
|
|||||||
+682
-611
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user