├── .github └── workflows │ └── test.yaml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── code-generator ├── Cargo.toml └── src │ └── main.rs ├── dicts ├── dictionary.rfc2865 ├── dictionary.rfc2866 ├── dictionary.rfc2867 ├── dictionary.rfc2868 ├── dictionary.rfc2869 ├── dictionary.rfc3162 ├── dictionary.rfc3576 ├── dictionary.rfc3580 ├── dictionary.rfc4072 ├── dictionary.rfc4372 ├── dictionary.rfc4603 ├── dictionary.rfc4675 ├── dictionary.rfc4818 ├── dictionary.rfc4849 ├── dictionary.rfc5090 ├── dictionary.rfc5176 ├── dictionary.rfc5607 ├── dictionary.rfc5904 ├── dictionary.rfc6519 ├── dictionary.rfc6572 ├── dictionary.rfc6677 ├── dictionary.rfc6911 ├── dictionary.rfc7055 └── dictionary.rfc7155 ├── e2e-test ├── Cargo.toml └── src │ ├── lib.rs │ └── test.rs ├── examples ├── Cargo.toml ├── client.rs └── server.rs ├── radius ├── Cargo.toml └── src │ ├── client.rs │ ├── core │ ├── attributes.rs │ ├── avp.rs │ ├── code.rs │ ├── mod.rs │ ├── packet.rs │ ├── request.rs │ ├── rfc2865.rs │ ├── rfc2866.rs │ ├── rfc2867.rs │ ├── rfc2868.rs │ ├── rfc2869.rs │ ├── rfc3162.rs │ ├── rfc3576.rs │ ├── rfc3580.rs │ ├── rfc4072.rs │ ├── rfc4372.rs │ ├── rfc4603.rs │ ├── rfc4675.rs │ ├── rfc4818.rs │ ├── rfc4849.rs │ ├── rfc5090.rs │ ├── rfc5176.rs │ ├── rfc5607.rs │ ├── rfc5904.rs │ ├── rfc6519.rs │ ├── rfc6572.rs │ ├── rfc6677.rs │ ├── rfc6911.rs │ ├── rfc7055.rs │ ├── rfc7155.rs │ ├── tag.rs │ └── vsa.rs │ ├── lib.rs │ └── server.rs ├── renovate.json └── scripts └── generate-code.sh /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Check 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | os: [ubuntu-latest, macOS-latest, windows-latest] 11 | rust: [stable, nightly] 12 | steps: 13 | - uses: hecrj/setup-rust-action@v2 14 | with: 15 | rust-version: ${{ matrix.rust }} 16 | # install openssl {{{ 17 | - name: Install OpenSSL on Ubuntu 18 | if: matrix.os == 'ubuntu-latest' 19 | run: | 20 | sudo apt-get update 21 | sudo apt-get install -y libssl-dev 22 | - name: Install OpenSSL on macOS 23 | if: matrix.os == 'macOS-latest' 24 | run: | 25 | brew update 26 | brew install openssl 27 | - name: Install OpenSSL on Windows 28 | if: matrix.os == 'windows-latest' 29 | run: | 30 | echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append 31 | vcpkg install openssl:x64-windows-static-md 32 | # }}} 33 | - uses: actions/checkout@v4 34 | - name: install clippy 35 | run: rustup component add clippy 36 | - name: Run checks 37 | run: make check_all 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "radius", 5 | 6 | # Internal 7 | "code-generator", 8 | "examples", 9 | "e2e-test" 10 | ] 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Taiki Kawakami (a.k.a moznion) https://moznion.net 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | check_all: check check_openssl check_md5 2 | check: test lint 3 | check_openssl: lint_with_openssl build_with_openssl test_with_openssl 4 | check_md5: lint_with_md5 build_with_md5 test_with_md5 5 | 6 | test: 7 | cargo test 8 | 9 | build: 10 | cargo build 11 | 12 | lint: 13 | cargo clippy 14 | 15 | gen: 16 | bash ./scripts/generate-code.sh 17 | $(MAKE) fix 18 | 19 | fix: 20 | cargo fix --allow-dirty --allow-staged 21 | cargo fmt 22 | 23 | build_with_openssl: 24 | cd radius && cargo build --verbose --no-default-features --features openssl 25 | 26 | test_with_openssl: 27 | cd radius && cargo test --verbose --no-default-features --features openssl 28 | 29 | lint_with_openssl: 30 | cd radius && cargo clippy --verbose --no-default-features --features openssl 31 | 32 | build_with_md5: 33 | cd radius && cargo build --verbose --no-default-features --features md5 34 | 35 | test_with_md5: 36 | cd radius && cargo test --verbose --no-default-features --features md5 37 | 38 | lint_with_md5: 39 | cd radius && cargo clippy --verbose --no-default-features --features md5 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # radius-rs [![Check](https://github.com/moznion/radius-rs/workflows/Check/badge.svg)](https://github.com/moznion/radius-rs/actions) [![crates.io](https://img.shields.io/crates/v/radius.svg)](https://crates.io/crates/radius) 2 | 3 | An async/await native implementation of the RADIUS server and client for Rust. And this also can be used for parsing/constructing (i.e. decoding/encoding) purposes as a RADIUS library. 4 | 5 | ## Description 6 | 7 | This RADIUS server and client implementation use [tokio](https://tokio.rs/) to support asynchronous operations natively. This implementation satisfies basic functions that are described in [RFC2865](https://tools.ietf.org/html/rfc2865). 8 | 9 | ## Usage 10 | 11 | Simple example implementations are here: 12 | 13 | - [server](./examples/server.rs) 14 | - [client](./examples/client.rs) 15 | 16 | Those examples implement a quite simple `Access-Request` processor. You can try those with the following commands. 17 | 18 | ``` 19 | $ RUST_LOG=debug cargo run --example server 20 | $ RUST_LOG=debug cargo run --example client # in another shell 21 | ``` 22 | 23 | ## Supported Dictionaries 24 | 25 | This supports the following RFC dictionaries at the moment: 26 | 27 | - [RFC2865](https://tools.ietf.org/html/rfc2865) 28 | - [RFC2866](https://tools.ietf.org/html/rfc2866) 29 | - [RFC2867](https://tools.ietf.org/html/rfc2867) 30 | - [RFC2868](https://tools.ietf.org/html/rfc2868) 31 | - [RFC2869](https://tools.ietf.org/html/rfc2869) 32 | - [RFC3162](https://tools.ietf.org/html/rfc3162) 33 | - [RFC3576](https://tools.ietf.org/html/rfc3576) 34 | - [RFC3580](https://tools.ietf.org/html/rfc3580) 35 | - [RFC4072](https://tools.ietf.org/html/rfc4072) 36 | - [RFC4372](https://tools.ietf.org/html/rfc4372) 37 | - [RFC4603](https://tools.ietf.org/html/rfc4603) 38 | - [RFC4675](https://tools.ietf.org/html/rfc4675) 39 | - [RFC4818](https://tools.ietf.org/html/rfc4818) 40 | - [RFC4849](https://tools.ietf.org/html/rfc4849) 41 | - [RFC5090](https://tools.ietf.org/html/rfc5090) 42 | - [RFC5176](https://tools.ietf.org/html/rfc5176) 43 | - [RFC5607](https://tools.ietf.org/html/rfc5607) 44 | - [RFC5904](https://tools.ietf.org/html/rfc5904) 45 | - [RFC6519](https://tools.ietf.org/html/rfc6519) 46 | - [RFC6572](https://tools.ietf.org/html/rfc6572) 47 | - [RFC6677](https://tools.ietf.org/html/rfc6677) 48 | - [RFC6911](https://tools.ietf.org/html/rfc6911) 49 | - [RFC7055](https://tools.ietf.org/html/rfc7055) 50 | - [RFC7155](https://tools.ietf.org/html/rfc7155) 51 | 52 | ## Cryptography method feature option 53 | 54 | By default, this library uses MD5 for authentication. 55 | Starting from version v0.4.0, it also supports [OpenSSL](https://www.openssl.org/). 56 | 57 | If you prefer to use OpenSSL, please add the following lines to your Cargo.toml: 58 | 59 | ```toml 60 | [dependencies] 61 | radius = { version = "__version__", default-features = false, features = ["openssl"] } 62 | ``` 63 | 64 | ## Implementation guide for your RADIUS application 65 | 66 | ### Common 67 | 68 | - `Packet` struct represents request packet and response one. 69 | - This struct has a list of AVPs. 70 | - You can get a specific AVP by RFC dictionary module. 71 | - e.g. `rfc2865::lookup_user_name(packet)` 72 | - This method returns `Some(Result)` if the packet contains `User-Name` attribute. 73 | - On the other hand, if the package doesn't have that attribute, it returns `None`. 74 | - You can construct a packet with RFC dictionary module. 75 | - e.g. `rfc2865::add_user_name(&mut packet, "user")` 76 | - This method adds a `User-Name` AVP to the packet. 77 | - Please refer to the rustdoc for each RFC dictionary module in detail. 78 | 79 | ### Server 80 | 81 | - Must implement `RequestHandler` interface. 82 | - This interface method is the core function of the server application what you need. 83 | - Please refer also to the example implementation: [server](./examples/server.rs) 84 | 85 | ### Client 86 | 87 | - Please refer also to the example implementation: [client](./examples/client.rs) 88 | 89 | ## Roadmap 90 | 91 | - Support the following RFC dictionaries: 92 | - rfc4679 93 | - rfc5447 94 | - rfc5580 95 | - rfc6929 96 | - rfc6930 97 | - rfc7268 98 | - rfc7499 99 | - rfc7930 100 | - rfc8045 101 | - rfc8559 102 | 103 | ## Development guide for this library 104 | 105 | ### How to generate code from dictionary 106 | 107 | ```shell 108 | $ make gen 109 | ``` 110 | 111 | `code-generator` sub project has the responsibility to generate the Rust code according to 112 | given RFC dictionary files. The dictionary files are in `dicts` directory. 113 | 114 | The format of the dictionary files respect the [FreeRADIUS project's ones](https://github.com/FreeRADIUS/freeradius-server/tree/master/share/dictionary/radius). 115 | 116 | ## Note 117 | 118 | The original implementation and design of this are inspired by [layeh/radius](https://github.com/layeh/radius). 119 | 120 | ## Author 121 | 122 | moznion () 123 | -------------------------------------------------------------------------------- /code-generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "code-generator" 3 | version = "0.4.0" 4 | edition = "2021" 5 | license-file = "../LICENSE" 6 | publish = false 7 | 8 | [dependencies] 9 | regex = "1" 10 | getopts = "0.2" 11 | Inflector = "0.11" 12 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc2865: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 2865. 7 | # http://www.ietf.org/rfc/rfc2865.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE User-Name 1 string 12 | ATTRIBUTE User-Password 2 string encrypt=1 13 | ATTRIBUTE CHAP-Password 3 octets 14 | ATTRIBUTE NAS-IP-Address 4 ipaddr 15 | ATTRIBUTE NAS-Port 5 integer 16 | ATTRIBUTE Service-Type 6 integer 17 | ATTRIBUTE Framed-Protocol 7 integer 18 | ATTRIBUTE Framed-IP-Address 8 ipaddr 19 | ATTRIBUTE Framed-IP-Netmask 9 ipaddr 20 | ATTRIBUTE Framed-Routing 10 integer 21 | ATTRIBUTE Filter-Id 11 string 22 | ATTRIBUTE Framed-MTU 12 integer 23 | ATTRIBUTE Framed-Compression 13 integer 24 | ATTRIBUTE Login-IP-Host 14 ipaddr 25 | ATTRIBUTE Login-Service 15 integer 26 | ATTRIBUTE Login-TCP-Port 16 integer 27 | # Attribute 17 is undefined 28 | ATTRIBUTE Reply-Message 18 string 29 | ATTRIBUTE Callback-Number 19 string 30 | ATTRIBUTE Callback-Id 20 string 31 | # Attribute 21 is undefined 32 | ATTRIBUTE Framed-Route 22 string 33 | ATTRIBUTE Framed-IPX-Network 23 ipaddr 34 | ATTRIBUTE State 24 octets 35 | ATTRIBUTE Class 25 octets 36 | ATTRIBUTE Vendor-Specific 26 vsa 37 | ATTRIBUTE Session-Timeout 27 integer 38 | ATTRIBUTE Idle-Timeout 28 integer 39 | ATTRIBUTE Termination-Action 29 integer 40 | ATTRIBUTE Called-Station-Id 30 string 41 | ATTRIBUTE Calling-Station-Id 31 string 42 | ATTRIBUTE NAS-Identifier 32 string 43 | ATTRIBUTE Proxy-State 33 octets 44 | ATTRIBUTE Login-LAT-Service 34 string 45 | ATTRIBUTE Login-LAT-Node 35 string 46 | ATTRIBUTE Login-LAT-Group 36 octets 47 | ATTRIBUTE Framed-AppleTalk-Link 37 integer 48 | ATTRIBUTE Framed-AppleTalk-Network 38 integer 49 | ATTRIBUTE Framed-AppleTalk-Zone 39 string 50 | 51 | ATTRIBUTE CHAP-Challenge 60 octets 52 | ATTRIBUTE NAS-Port-Type 61 integer 53 | ATTRIBUTE Port-Limit 62 integer 54 | ATTRIBUTE Login-LAT-Port 63 string 55 | 56 | # 57 | # Integer Translations 58 | # 59 | 60 | # Service types 61 | 62 | VALUE Service-Type Login-User 1 63 | VALUE Service-Type Framed-User 2 64 | VALUE Service-Type Callback-Login-User 3 65 | VALUE Service-Type Callback-Framed-User 4 66 | VALUE Service-Type Outbound-User 5 67 | VALUE Service-Type Administrative-User 6 68 | VALUE Service-Type NAS-Prompt-User 7 69 | VALUE Service-Type Authenticate-Only 8 70 | VALUE Service-Type Callback-NAS-Prompt 9 71 | VALUE Service-Type Call-Check 10 72 | VALUE Service-Type Callback-Administrative 11 73 | 74 | # Framed Protocols 75 | 76 | VALUE Framed-Protocol PPP 1 77 | VALUE Framed-Protocol SLIP 2 78 | VALUE Framed-Protocol ARAP 3 79 | VALUE Framed-Protocol Gandalf-SLML 4 80 | VALUE Framed-Protocol Xylogics-IPX-SLIP 5 81 | VALUE Framed-Protocol X.75-Synchronous 6 82 | 83 | # Framed Routing Values 84 | 85 | VALUE Framed-Routing None 0 86 | VALUE Framed-Routing Broadcast 1 87 | VALUE Framed-Routing Listen 2 88 | VALUE Framed-Routing Broadcast-Listen 3 89 | 90 | # Framed Compression Types 91 | 92 | VALUE Framed-Compression None 0 93 | VALUE Framed-Compression Van-Jacobson-TCP-IP 1 94 | VALUE Framed-Compression IPX-Header-Compression 2 95 | VALUE Framed-Compression Stac-LZS 3 96 | 97 | # Login Services 98 | 99 | VALUE Login-Service Telnet 0 100 | VALUE Login-Service Rlogin 1 101 | VALUE Login-Service TCP-Clear 2 102 | VALUE Login-Service PortMaster 3 103 | VALUE Login-Service LAT 4 104 | VALUE Login-Service X25-PAD 5 105 | VALUE Login-Service X25-T3POS 6 106 | VALUE Login-Service TCP-Clear-Quiet 8 107 | 108 | # Login-TCP-Port (see /etc/services for more examples) 109 | 110 | VALUE Login-TCP-Port Telnet 23 111 | VALUE Login-TCP-Port Rlogin 513 112 | VALUE Login-TCP-Port Rsh 514 113 | 114 | # Termination Options 115 | 116 | VALUE Termination-Action Default 0 117 | VALUE Termination-Action RADIUS-Request 1 118 | 119 | # NAS Port Types 120 | 121 | VALUE NAS-Port-Type Async 0 122 | VALUE NAS-Port-Type Sync 1 123 | VALUE NAS-Port-Type ISDN 2 124 | VALUE NAS-Port-Type ISDN-V120 3 125 | VALUE NAS-Port-Type ISDN-V110 4 126 | VALUE NAS-Port-Type Virtual 5 127 | VALUE NAS-Port-Type PIAFS 6 128 | VALUE NAS-Port-Type HDLC-Clear-Channel 7 129 | VALUE NAS-Port-Type X.25 8 130 | VALUE NAS-Port-Type X.75 9 131 | VALUE NAS-Port-Type G.3-Fax 10 132 | VALUE NAS-Port-Type SDSL 11 133 | VALUE NAS-Port-Type ADSL-CAP 12 134 | VALUE NAS-Port-Type ADSL-DMT 13 135 | VALUE NAS-Port-Type IDSL 14 136 | VALUE NAS-Port-Type Ethernet 15 137 | VALUE NAS-Port-Type xDSL 16 138 | VALUE NAS-Port-Type Cable 17 139 | VALUE NAS-Port-Type Wireless-Other 18 140 | VALUE NAS-Port-Type Wireless-802.11 19 141 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc2866: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 2866. 7 | # http://www.ietf.org/rfc/rfc2866.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Acct-Status-Type 40 integer 12 | ATTRIBUTE Acct-Delay-Time 41 integer 13 | ATTRIBUTE Acct-Input-Octets 42 integer 14 | ATTRIBUTE Acct-Output-Octets 43 integer 15 | ATTRIBUTE Acct-Session-Id 44 string 16 | ATTRIBUTE Acct-Authentic 45 integer 17 | ATTRIBUTE Acct-Session-Time 46 integer 18 | ATTRIBUTE Acct-Input-Packets 47 integer 19 | ATTRIBUTE Acct-Output-Packets 48 integer 20 | ATTRIBUTE Acct-Terminate-Cause 49 integer 21 | ATTRIBUTE Acct-Multi-Session-Id 50 string 22 | ATTRIBUTE Acct-Link-Count 51 integer 23 | 24 | # Accounting Status Types 25 | 26 | VALUE Acct-Status-Type Start 1 27 | VALUE Acct-Status-Type Stop 2 28 | VALUE Acct-Status-Type Alive 3 # dup 29 | VALUE Acct-Status-Type Interim-Update 3 30 | VALUE Acct-Status-Type Accounting-On 7 31 | VALUE Acct-Status-Type Accounting-Off 8 32 | VALUE Acct-Status-Type Failed 15 33 | 34 | # Authentication Types 35 | 36 | VALUE Acct-Authentic RADIUS 1 37 | VALUE Acct-Authentic Local 2 38 | VALUE Acct-Authentic Remote 3 39 | VALUE Acct-Authentic Diameter 4 40 | 41 | # Acct Terminate Causes 42 | 43 | VALUE Acct-Terminate-Cause User-Request 1 44 | VALUE Acct-Terminate-Cause Lost-Carrier 2 45 | VALUE Acct-Terminate-Cause Lost-Service 3 46 | VALUE Acct-Terminate-Cause Idle-Timeout 4 47 | VALUE Acct-Terminate-Cause Session-Timeout 5 48 | VALUE Acct-Terminate-Cause Admin-Reset 6 49 | VALUE Acct-Terminate-Cause Admin-Reboot 7 50 | VALUE Acct-Terminate-Cause Port-Error 8 51 | VALUE Acct-Terminate-Cause NAS-Error 9 52 | VALUE Acct-Terminate-Cause NAS-Request 10 53 | VALUE Acct-Terminate-Cause NAS-Reboot 11 54 | VALUE Acct-Terminate-Cause Port-Unneeded 12 55 | VALUE Acct-Terminate-Cause Port-Preempted 13 56 | VALUE Acct-Terminate-Cause Port-Suspended 14 57 | VALUE Acct-Terminate-Cause Service-Unavailable 15 58 | VALUE Acct-Terminate-Cause Callback 16 59 | VALUE Acct-Terminate-Cause User-Error 17 60 | VALUE Acct-Terminate-Cause Host-Request 18 61 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc2867: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 2867. 7 | # http://www.ietf.org/rfc/rfc2867.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Acct-Tunnel-Connection 68 string 12 | ATTRIBUTE Acct-Tunnel-Packets-Lost 86 integer 13 | 14 | VALUE Acct-Status-Type Tunnel-Start 9 15 | VALUE Acct-Status-Type Tunnel-Stop 10 16 | VALUE Acct-Status-Type Tunnel-Reject 11 17 | VALUE Acct-Status-Type Tunnel-Link-Start 12 18 | VALUE Acct-Status-Type Tunnel-Link-Stop 13 19 | VALUE Acct-Status-Type Tunnel-Link-Reject 14 20 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc2868: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 2868. 7 | # http://www.ietf.org/rfc/rfc2868.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Tunnel-Type 64 integer has_tag 12 | ATTRIBUTE Tunnel-Medium-Type 65 integer has_tag 13 | ATTRIBUTE Tunnel-Client-Endpoint 66 string has_tag 14 | ATTRIBUTE Tunnel-Server-Endpoint 67 string has_tag 15 | 16 | ATTRIBUTE Tunnel-Password 69 string has_tag,encrypt=2 17 | 18 | ATTRIBUTE Tunnel-Private-Group-Id 81 string has_tag 19 | ATTRIBUTE Tunnel-Assignment-Id 82 string has_tag 20 | ATTRIBUTE Tunnel-Preference 83 integer has_tag 21 | 22 | ATTRIBUTE Tunnel-Client-Auth-Id 90 string has_tag 23 | ATTRIBUTE Tunnel-Server-Auth-Id 91 string has_tag 24 | 25 | # Tunnel Type 26 | 27 | VALUE Tunnel-Type PPTP 1 28 | VALUE Tunnel-Type L2F 2 29 | VALUE Tunnel-Type L2TP 3 30 | VALUE Tunnel-Type ATMP 4 31 | VALUE Tunnel-Type VTP 5 32 | VALUE Tunnel-Type AH 6 33 | VALUE Tunnel-Type IP 7 34 | VALUE Tunnel-Type MIN-IP 8 35 | VALUE Tunnel-Type ESP 9 36 | VALUE Tunnel-Type GRE 10 37 | VALUE Tunnel-Type DVS 11 38 | VALUE Tunnel-Type IP-in-IP 12 39 | 40 | # Tunnel Medium Type 41 | 42 | VALUE Tunnel-Medium-Type IP 1 43 | VALUE Tunnel-Medium-Type IPv4 1 44 | VALUE Tunnel-Medium-Type IPv6 2 45 | VALUE Tunnel-Medium-Type NSAP 3 46 | VALUE Tunnel-Medium-Type HDLC 4 47 | VALUE Tunnel-Medium-Type BBN-1822 5 48 | VALUE Tunnel-Medium-Type IEEE-802 6 49 | VALUE Tunnel-Medium-Type E.163 7 50 | VALUE Tunnel-Medium-Type E.164 8 51 | VALUE Tunnel-Medium-Type F.69 9 52 | VALUE Tunnel-Medium-Type X.121 10 53 | VALUE Tunnel-Medium-Type IPX 11 54 | VALUE Tunnel-Medium-Type Appletalk 12 55 | VALUE Tunnel-Medium-Type DecNet-IV 13 56 | VALUE Tunnel-Medium-Type Banyan-Vines 14 57 | VALUE Tunnel-Medium-Type E.164-NSAP 15 58 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc2869: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 2869. 7 | # http://www.ietf.org/rfc/rfc2869.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Acct-Input-Gigawords 52 integer 12 | ATTRIBUTE Acct-Output-Gigawords 53 integer 13 | 14 | ATTRIBUTE Event-Timestamp 55 date 15 | 16 | ATTRIBUTE ARAP-Password 70 octets[16] 17 | ATTRIBUTE ARAP-Features 71 octets[14] 18 | ATTRIBUTE ARAP-Zone-Access 72 integer 19 | ATTRIBUTE ARAP-Security 73 integer 20 | ATTRIBUTE ARAP-Security-Data 74 string 21 | ATTRIBUTE Password-Retry 75 integer 22 | ATTRIBUTE Prompt 76 integer 23 | ATTRIBUTE Connect-Info 77 string 24 | ATTRIBUTE Configuration-Token 78 string 25 | ATTRIBUTE EAP-Message 79 octets concat 26 | ATTRIBUTE Message-Authenticator 80 octets 27 | 28 | ATTRIBUTE ARAP-Challenge-Response 84 octets[8] 29 | ATTRIBUTE Acct-Interim-Interval 85 integer 30 | # 86: RFC 2867 31 | ATTRIBUTE NAS-Port-Id 87 string 32 | ATTRIBUTE Framed-Pool 88 string 33 | 34 | # ARAP Zone Access 35 | 36 | VALUE ARAP-Zone-Access Default-Zone 1 37 | VALUE ARAP-Zone-Access Zone-Filter-Inclusive 2 38 | VALUE ARAP-Zone-Access Zone-Filter-Exclusive 4 39 | 40 | # Prompt 41 | VALUE Prompt No-Echo 0 42 | VALUE Prompt Echo 1 43 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc3162: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 3162. 7 | # http://www.ietf.org/rfc/rfc3162.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE NAS-IPV6-Address 95 ipv6addr 12 | ATTRIBUTE Framed-Interface-Id 96 ifid 13 | ATTRIBUTE Framed-IPV6-Prefix 97 ipv6prefix 14 | ATTRIBUTE Login-IPV6-Host 98 ipv6addr 15 | ATTRIBUTE Framed-IPV6-Route 99 string 16 | ATTRIBUTE Framed-IPV6-Pool 100 string 17 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc3576: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 3576. 7 | # http://www.ietf.org/rfc/rfc3576.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Error-Cause 101 integer 12 | 13 | # Service Types 14 | 15 | VALUE Service-Type Authorize-Only 17 16 | 17 | # Error causes 18 | 19 | VALUE Error-Cause Residual-Context-Removed 201 20 | VALUE Error-Cause Invalid-EAP-Packet 202 21 | VALUE Error-Cause Unsupported-Attribute 401 22 | VALUE Error-Cause Missing-Attribute 402 23 | VALUE Error-Cause NAS-Identification-Mismatch 403 24 | VALUE Error-Cause Invalid-Request 404 25 | VALUE Error-Cause Unsupported-Service 405 26 | VALUE Error-Cause Unsupported-Extension 406 27 | VALUE Error-Cause Administratively-Prohibited 501 28 | VALUE Error-Cause Proxy-Request-Not-Routable 502 29 | VALUE Error-Cause Session-Context-Not-Found 503 30 | VALUE Error-Cause Session-Context-Not-Removable 504 31 | VALUE Error-Cause Proxy-Processing-Error 505 32 | VALUE Error-Cause Resources-Unavailable 506 33 | VALUE Error-Cause Request-Initiated 507 34 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc3580: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 3580. 7 | # http://www.ietf.org/rfc/rfc3580.txt 8 | # 9 | # $Id$ 10 | # 11 | VALUE Acct-Terminate-Cause Supplicant-Restart 19 12 | VALUE Acct-Terminate-Cause Reauthentication-Failure 20 13 | VALUE Acct-Terminate-Cause Port-Reinit 21 14 | VALUE Acct-Terminate-Cause Port-Disabled 22 15 | 16 | VALUE NAS-Port-Type Token-Ring 20 17 | VALUE NAS-Port-Type FDDI 21 18 | 19 | VALUE Tunnel-Type VLAN 13 20 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4072: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 4072 7 | # http://www.ietf.org/rfc/rfc4072.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | ATTRIBUTE EAP-Key-Name 102 octets 13 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4372: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 4372. 7 | # http://www.ietf.org/rfc/rfc4372.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Chargeable-User-Identity 89 octets 12 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4603: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | ############################################################################## 6 | # 7 | # Attributes and values defined in RFC 4603. 8 | # http://www.ietf.org/rfc/rfc4603.txt 9 | # 10 | # $Id$ 11 | # 12 | ############################################################################## 13 | 14 | VALUE NAS-Port-Type PPPoA 30 15 | VALUE NAS-Port-Type PPPoEoA 31 16 | VALUE NAS-Port-Type PPPoEoE 32 17 | VALUE NAS-Port-Type PPPoEoVLAN 33 18 | VALUE NAS-Port-Type PPPoEoQinQ 34 19 | 20 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4675: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 4675. 7 | # http://www.ietf.org/rfc/rfc4675.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | # 13 | # High byte = '1' (0x31) means the frames are tagged. 14 | # High byte = '2' (0x32) means the frames are untagged. 15 | # 16 | # Next 12 bits MUST be zero. 17 | # 18 | # Lower 12 bits is the IEEE-802.1Q VLAN VID. 19 | # 20 | ATTRIBUTE Egress-VLANID 56 integer 21 | ATTRIBUTE Ingress-Filters 57 integer 22 | 23 | # 24 | # First byte == '1' (0x31) means that the frames are tagged. 25 | # First byte == '2' (0x32) means that the frames are untagged. 26 | # 27 | ATTRIBUTE Egress-VLAN-Name 58 string 28 | ATTRIBUTE User-Priority-Table 59 octets 29 | 30 | VALUE Ingress-Filters Enabled 1 31 | VALUE Ingress-Filters Disabled 2 32 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4818: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | ############################################################################## 6 | # 7 | # Attributes and values defined in RFC 4818. 8 | # http://www.ietf.org/rfc/rfc4818.txt 9 | # 10 | # $Id$ 11 | # 12 | ############################################################################## 13 | 14 | ATTRIBUTE Delegated-IPV6-Prefix 123 ipv6prefix 15 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc4849: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 4849. 7 | # http://www.ietf.org/rfc/rfc4849.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE NAS-Filter-Rule 92 string 12 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc5090: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 5090. 7 | # http://www.ietf.org/rfc/rfc5090.txt 8 | # 9 | # $Id$ 10 | # 11 | ATTRIBUTE Digest-Response 103 string 12 | ATTRIBUTE Digest-Realm 104 string 13 | ATTRIBUTE Digest-Nonce 105 string 14 | ATTRIBUTE Digest-Response-Auth 106 string 15 | ATTRIBUTE Digest-Nextnonce 107 string 16 | ATTRIBUTE Digest-Method 108 string 17 | ATTRIBUTE Digest-URI 109 string 18 | ATTRIBUTE Digest-Qop 110 string 19 | ATTRIBUTE Digest-Algorithm 111 string 20 | ATTRIBUTE Digest-Entity-Body-Hash 112 string 21 | ATTRIBUTE Digest-CNonce 113 string 22 | ATTRIBUTE Digest-Nonce-Count 114 string 23 | ATTRIBUTE Digest-Username 115 string 24 | ATTRIBUTE Digest-Opaque 116 string 25 | ATTRIBUTE Digest-Auth-Param 117 string 26 | ATTRIBUTE Digest-AKA-Auts 118 string 27 | ATTRIBUTE Digest-Domain 119 string 28 | ATTRIBUTE Digest-Stale 120 string 29 | ATTRIBUTE Digest-HA1 121 string 30 | ATTRIBUTE SIP-AOR 122 string 31 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc5176: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 5176. 7 | # http://www.ietf.org/rfc/rfc5176.txt 8 | # 9 | # $Id$ 10 | # 11 | VALUE Error-Cause Invalid-Attribute-Value 407 12 | VALUE Error-Cause Multiple-Session-Selection-Unsupported 508 13 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc5607: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 5607. 7 | # http://www.ietf.org/rfc/rfc5607.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | VALUE Service-Type Framed-Management 18 13 | 14 | ATTRIBUTE Framed-Management 133 integer 15 | 16 | VALUE Framed-Management SNMP 1 17 | VALUE Framed-Management Web-Based 2 18 | VALUE Framed-Management Netconf 3 19 | VALUE Framed-Management FTP 4 20 | VALUE Framed-Management TFTP 5 21 | VALUE Framed-Management SFTP 6 22 | VALUE Framed-Management RCP 7 23 | VALUE Framed-Management SCP 8 24 | 25 | ATTRIBUTE Management-Transport-Protection 134 integer 26 | 27 | VALUE Management-Transport-Protection No-Protection 1 28 | VALUE Management-Transport-Protection Integrity-Protection 2 29 | VALUE Management-Transport-Protection Integrity-Confidentiality-Protection 3 30 | 31 | ATTRIBUTE Management-Policy-Id 135 string 32 | 33 | ATTRIBUTE Management-Privilege-Level 136 integer 34 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc5904: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 5904. 7 | # http://www.ietf.org/rfc/rfc5904.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | # The next two attributes are continued, like EAP-Message 13 | ATTRIBUTE PKM-SS-Cert 137 octets concat 14 | ATTRIBUTE PKM-CA-Cert 138 octets concat 15 | 16 | # 28 bytes of data, 7 integers 17 | ATTRIBUTE PKM-Config-Settings 139 octets 18 | ATTRIBUTE PKM-Cryptosuite-List 140 octets 19 | ATTRIBUTE PKM-SAID 141 short 20 | 21 | # 6 bytes of data: SAID, 1 byte of type, 3 of cryptosuite 22 | ATTRIBUTE PKM-SA-Descriptor 142 octets 23 | 24 | # 133 bytes of data: integer lifetime, 1 byte sequence, 128 bytes of key 25 | ATTRIBUTE PKM-Auth-Key 143 octets 26 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc6519: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 6519. 7 | # http://www.ietf.org/rfc/rfc6519.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | ATTRIBUTE DS-Lite-Tunnel-Name 144 string 13 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc6572: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 6572. 7 | # http://www.ietf.org/rfc/rfc6572.txt 8 | # 9 | # $Id$ 10 | # 11 | 12 | ATTRIBUTE Mobile-Node-Identifier 145 octets 13 | ATTRIBUTE Service-Selection 146 string 14 | ATTRIBUTE PMIP6-Home-LMA-IPV6-Address 147 ipv6addr 15 | ATTRIBUTE PMIP6-Visited-LMA-IPV6-Address 148 ipv6addr 16 | ATTRIBUTE PMIP6-Home-LMA-IPV4-Address 149 ipaddr 17 | ATTRIBUTE PMIP6-Visited-LMA-IPV4-Address 150 ipaddr 18 | ATTRIBUTE PMIP6-Home-HN-Prefix 151 ipv6prefix 19 | ATTRIBUTE PMIP6-Visited-HN-Prefix 152 ipv6prefix 20 | ATTRIBUTE PMIP6-Home-Interface-ID 153 ifid 21 | ATTRIBUTE PMIP6-Visited-Interface-ID 154 ifid 22 | ATTRIBUTE PMIP6-Home-IPV4-HoA 155 ipv4prefix 23 | ATTRIBUTE PMIP6-Visited-IPV4-HoA 156 ipv4prefix 24 | ATTRIBUTE PMIP6-Home-DHCP4-Server-Address 157 ipaddr 25 | ATTRIBUTE PMIP6-Visited-DHCP4-Server-Address 158 ipaddr 26 | ATTRIBUTE PMIP6-Home-DHCP6-Server-Address 159 ipv6addr 27 | ATTRIBUTE PMIP6-Visited-DHCP6-Server-Address 160 ipv6addr 28 | ATTRIBUTE PMIP6-Home-IPV4-Gateway 161 ipaddr 29 | ATTRIBUTE PMIP6-Visited-IPV4-Gateway 162 ipaddr 30 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc6677: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 6677 7 | # http://www.ietf.org/rfc/rfc6677.txt 8 | # 9 | 10 | ATTRIBUTE EAP-Lower-Layer 163 integer 11 | 12 | VALUE EAP-Lower-Layer Wired-IEEE-802.1X 1 13 | VALUE EAP-Lower-Layer IEEE-802.1X-No-Preauth 2 14 | VALUE EAP-Lower-Layer IEEE-802.1X-Preauth 3 15 | VALUE EAP-Lower-Layer IEEE-802.16e 4 16 | VALUE EAP-Lower-Layer IKEv2 5 17 | VALUE EAP-Lower-Layer PPP 6 18 | VALUE EAP-Lower-Layer PANA-No-Preauth 7 19 | VALUE EAP-Lower-Layer GSS-API 8 20 | VALUE EAP-Lower-Layer PANA-Preauth 9 21 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc6911: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 6911 7 | # http://www.ietf.org/rfc/rfc6911.txt 8 | # 9 | 10 | ATTRIBUTE Framed-IPV6-Address 168 ipv6addr 11 | ATTRIBUTE DNS-Server-IPV6-Address 169 ipv6addr 12 | ATTRIBUTE Route-IPV6-Information 170 ipv6prefix 13 | ATTRIBUTE Delegated-IPV6-Prefix-Pool 171 string 14 | ATTRIBUTE Stateful-IPV6-Address-Pool 172 string 15 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc7055: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 7055 7 | # http://www.ietf.org/rfc/rfc7055.txt 8 | # 9 | 10 | ATTRIBUTE GSS-Acceptor-Service-Name 164 string 11 | ATTRIBUTE GSS-Acceptor-Host-Name 165 string 12 | ATTRIBUTE GSS-Acceptor-Service-Specifics 166 string 13 | ATTRIBUTE GSS-Acceptor-Realm-Name 167 string 14 | -------------------------------------------------------------------------------- /dicts/dictionary.rfc7155: -------------------------------------------------------------------------------- 1 | # -*- text -*- 2 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors 3 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 4 | # Version $Id$ 5 | # 6 | # Attributes and values defined in RFC 7155 7 | # http://www.ietf.org/rfc/rfc7155.txt 8 | # 9 | 10 | # The Value field contains two octets (00 - 99). ANSI T1.113 and 11 | # BELLCORE 394 can be used for additional information about these 12 | # values and their use. 13 | ATTRIBUTE Originating-Line-Info 94 octets[2] 14 | -------------------------------------------------------------------------------- /e2e-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "e2e-test" 3 | version = "0.4.0" 4 | edition = "2018" 5 | license-file = "../LICENSE" 6 | publish = false 7 | 8 | [dependencies] 9 | radius = { version = "0.4.0", path = "../radius" } 10 | tokio = { version = "1.35.1", features = ["signal", "net"] } 11 | async-trait = "0.1.77" 12 | -------------------------------------------------------------------------------- /e2e-test/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod test; 2 | -------------------------------------------------------------------------------- /e2e-test/src/test.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::net::SocketAddr; 3 | use std::time::Duration; 4 | 5 | use async_trait::async_trait; 6 | use tokio::net::UdpSocket; 7 | use tokio::time::sleep; 8 | 9 | use radius::core::code::Code; 10 | use radius::core::request::Request; 11 | use radius::core::rfc2865; 12 | use radius::server::{RequestHandler, SecretProvider, SecretProviderError}; 13 | 14 | struct MyRequestHandler {} 15 | 16 | #[async_trait] 17 | impl RequestHandler<(), io::Error> for MyRequestHandler { 18 | async fn handle_radius_request( 19 | &self, 20 | conn: &UdpSocket, 21 | req: &Request, 22 | ) -> Result<(), io::Error> { 23 | let req_packet = req.get_packet(); 24 | let maybe_user_name_attr = rfc2865::lookup_user_name(req_packet); 25 | let maybe_user_password_attr = rfc2865::lookup_user_password(req_packet); 26 | 27 | let user_name = maybe_user_name_attr.unwrap().unwrap(); 28 | let user_password = String::from_utf8(maybe_user_password_attr.unwrap().unwrap()).unwrap(); 29 | let code = if user_name == "admin" && user_password == "p@ssw0rd" { 30 | Code::AccessAccept 31 | } else { 32 | Code::AccessReject 33 | }; 34 | 35 | let mut resp_packet = req_packet.make_response_packet(code); 36 | rfc2865::add_user_name(&mut resp_packet, user_name.as_str()); 37 | conn.send_to(&resp_packet.encode().unwrap(), req.get_remote_addr()) 38 | .await?; 39 | Ok(()) 40 | } 41 | } 42 | 43 | struct LongTimeTakingHandler {} 44 | 45 | #[async_trait] 46 | impl RequestHandler<(), io::Error> for LongTimeTakingHandler { 47 | async fn handle_radius_request( 48 | &self, 49 | conn: &UdpSocket, 50 | req: &Request, 51 | ) -> Result<(), io::Error> { 52 | sleep(Duration::from_secs(30)).await; 53 | let req_packet = req.get_packet(); 54 | let resp_packet = req_packet.make_response_packet(Code::AccessReject); 55 | conn.send_to(&resp_packet.encode().unwrap(), req.get_remote_addr()) 56 | .await?; 57 | Ok(()) 58 | } 59 | } 60 | 61 | struct MySecretProvider {} 62 | 63 | impl SecretProvider for MySecretProvider { 64 | fn fetch_secret(&self, _remote_addr: SocketAddr) -> Result, SecretProviderError> { 65 | let bs = b"secret".to_vec(); 66 | Ok(bs) 67 | } 68 | } 69 | 70 | #[cfg(test)] 71 | mod tests { 72 | use std::net::SocketAddr; 73 | use std::time::Duration; 74 | 75 | use tokio::sync::oneshot; 76 | 77 | use radius::client::{Client, ClientError}; 78 | use radius::core::code::Code; 79 | use radius::core::packet::Packet; 80 | use radius::core::rfc2865; 81 | 82 | use crate::test::{LongTimeTakingHandler, MyRequestHandler, MySecretProvider}; 83 | use radius::server::Server; 84 | 85 | #[tokio::test] 86 | async fn test_runner() { 87 | test_access_request().await; 88 | test_socket_timeout().await; 89 | } 90 | 91 | async fn test_access_request() { 92 | let (sender, receiver) = oneshot::channel::<()>(); 93 | 94 | let port = 1812; 95 | 96 | let mut server = Server::listen("0.0.0.0", port, MyRequestHandler {}, MySecretProvider {}) 97 | .await 98 | .unwrap(); 99 | 100 | let server_proc = tokio::spawn(async move { 101 | server.run(receiver).await.unwrap(); 102 | }); 103 | 104 | let remote_addr: SocketAddr = format!("127.0.0.1:{}", port).parse().unwrap(); 105 | let client = Client::new(None, None); 106 | 107 | let mut req_packet = Packet::new(Code::AccessRequest, &b"secret".to_vec()); 108 | rfc2865::add_user_name(&mut req_packet, "admin"); 109 | rfc2865::add_user_password(&mut req_packet, b"p@ssw0rd").unwrap(); 110 | let res = client.send_packet(&remote_addr, &req_packet).await.unwrap(); 111 | let maybe_user_name = rfc2865::lookup_user_name(&res); 112 | let maybe_user_pass = rfc2865::lookup_user_password(&res); 113 | assert_eq!(res.get_code(), Code::AccessAccept); 114 | assert_eq!(maybe_user_name.is_some(), true); 115 | assert_eq!(maybe_user_name.unwrap().unwrap(), "admin"); 116 | assert_eq!(maybe_user_pass.is_none(), true); 117 | 118 | let mut req_packet = Packet::new(Code::AccessRequest, &b"secret".to_vec()); 119 | rfc2865::add_user_name(&mut req_packet, "admin"); 120 | rfc2865::add_user_password(&mut req_packet, b"INVALID-PASS").unwrap(); 121 | let res = client.send_packet(&remote_addr, &req_packet).await.unwrap(); 122 | assert_eq!(res.get_code(), Code::AccessReject); 123 | 124 | sender.send(()).unwrap(); 125 | server_proc.await.unwrap(); 126 | } 127 | 128 | async fn test_socket_timeout() { 129 | let (sender, receiver) = oneshot::channel::<()>(); 130 | 131 | let port = 1812; 132 | 133 | let mut server = Server::listen( 134 | "0.0.0.0", 135 | port, 136 | LongTimeTakingHandler {}, 137 | MySecretProvider {}, 138 | ) 139 | .await 140 | .unwrap(); 141 | 142 | let server_proc = tokio::spawn(async move { 143 | server.run(receiver).await.unwrap(); 144 | }); 145 | 146 | let remote_addr: SocketAddr = format!("127.0.0.1:{}", port).parse().unwrap(); 147 | let client = Client::new(None, Some(Duration::from_secs(0))); 148 | 149 | let mut req_packet = Packet::new(Code::AccessRequest, &b"secret".to_vec()); 150 | rfc2865::add_user_name(&mut req_packet, "admin"); 151 | rfc2865::add_user_password(&mut req_packet, b"p@ssw0rd").unwrap(); 152 | let res = client.send_packet(&remote_addr, &req_packet).await; 153 | 154 | let err = res.unwrap_err(); 155 | match err { 156 | ClientError::SocketTimeoutError() => {} 157 | _ => panic!("unexpected error: {}", err), 158 | } 159 | 160 | sender.send(()).unwrap(); 161 | server_proc.await.unwrap(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /examples/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples" 3 | version = "0.4.0" 4 | publish = false 5 | edition = "2021" 6 | license-file = "../LICENSE" 7 | repository = "https://github.com/moznion/radius-rs" 8 | 9 | [dev-dependencies] 10 | radius = { version = "0.4.0", path = "../radius" } 11 | log = "0.4.11" 12 | env_logger = "0.8.2" 13 | tokio = { version = "1.0.1", features = ["signal", "net"] } 14 | async-trait = "0.1.42" 15 | 16 | [[example]] 17 | name = "server" 18 | path = "server.rs" 19 | 20 | [[example]] 21 | name = "client" 22 | path = "client.rs" 23 | 24 | -------------------------------------------------------------------------------- /examples/client.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | use radius::client::Client; 4 | use radius::core::code::Code; 5 | use radius::core::packet::Packet; 6 | use radius::core::rfc2865; 7 | use std::net::SocketAddr; 8 | use tokio::time::Duration; 9 | 10 | #[tokio::main] 11 | async fn main() { 12 | env_logger::init(); 13 | 14 | let remote_addr: SocketAddr = "127.0.0.1:1812".parse().unwrap(); 15 | 16 | let mut req_packet = Packet::new(Code::AccessRequest, &b"secret".to_vec()); 17 | rfc2865::add_user_name(&mut req_packet, "admin"); 18 | rfc2865::add_user_password(&mut req_packet, b"p@ssw0rd").unwrap(); 19 | 20 | let client = Client::new(Some(Duration::from_secs(3)), Some(Duration::from_secs(5))); 21 | let res = client.send_packet(&remote_addr, &req_packet).await; 22 | info!("response: {:?}", res); 23 | } 24 | -------------------------------------------------------------------------------- /examples/server.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | use std::net::SocketAddr; 5 | use std::{io, process}; 6 | 7 | use async_trait::async_trait; 8 | use tokio::net::UdpSocket; 9 | use tokio::signal; 10 | 11 | use radius::core::code::Code; 12 | use radius::core::request::Request; 13 | use radius::core::rfc2865; 14 | use radius::server::{RequestHandler, SecretProvider, SecretProviderError, Server}; 15 | 16 | #[tokio::main] 17 | async fn main() { 18 | env_logger::init(); 19 | 20 | // start UDP listening 21 | let mut server = Server::listen("0.0.0.0", 1812, MyRequestHandler {}, MySecretProvider {}) 22 | .await 23 | .unwrap(); 24 | server.set_buffer_size(1500); // default value: 1500 25 | server.set_skip_authenticity_validation(false); // default value: false 26 | 27 | // once it has reached here, a RADIUS server is now ready 28 | info!( 29 | "serve is now ready: {}", 30 | server.get_listen_address().unwrap() 31 | ); 32 | 33 | // start the loop to handle the RADIUS requests 34 | let result = server.run(signal::ctrl_c()).await; 35 | info!("{:?}", result); 36 | if result.is_err() { 37 | process::exit(1); 38 | } 39 | } 40 | 41 | struct MyRequestHandler {} 42 | 43 | #[async_trait] 44 | impl RequestHandler<(), io::Error> for MyRequestHandler { 45 | async fn handle_radius_request( 46 | &self, 47 | conn: &UdpSocket, 48 | req: &Request, 49 | ) -> Result<(), io::Error> { 50 | let req_packet = req.get_packet(); 51 | let maybe_user_name_attr = rfc2865::lookup_user_name(req_packet); 52 | let maybe_user_password_attr = rfc2865::lookup_user_password(req_packet); 53 | 54 | let user_name = maybe_user_name_attr.unwrap().unwrap(); 55 | let user_password = String::from_utf8(maybe_user_password_attr.unwrap().unwrap()).unwrap(); 56 | let code = if user_name == "admin" && user_password == "p@ssw0rd" { 57 | Code::AccessAccept 58 | } else { 59 | Code::AccessReject 60 | }; 61 | info!("response => {:?} to {}", code, req.get_remote_addr()); 62 | 63 | conn.send_to( 64 | &req_packet.make_response_packet(code).encode().unwrap(), 65 | req.get_remote_addr(), 66 | ) 67 | .await?; 68 | Ok(()) 69 | } 70 | } 71 | 72 | struct MySecretProvider {} 73 | 74 | impl SecretProvider for MySecretProvider { 75 | fn fetch_secret(&self, _remote_addr: SocketAddr) -> Result, SecretProviderError> { 76 | let bs = b"secret".to_vec(); 77 | Ok(bs) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /radius/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "radius" 3 | version = "0.4.0" 4 | authors = ["moznion "] 5 | edition = "2021" 6 | description = "An async/await native implementation of the RADIUS server and client for Rust." 7 | license = "MIT" 8 | readme = "../README.md" 9 | repository = "https://github.com/moznion/radius-rs" 10 | homepage = "https://github.com/moznion/radius-rs" 11 | documentation = "https://docs.rs/radius" 12 | categories = ["network-programming"] 13 | keywords = ["radius", "async"] 14 | 15 | [dependencies] 16 | md5 = { version = "0.7.0", optional = true } 17 | openssl = { version = "0.10", optional = true } 18 | chrono = "0.4" 19 | rand = "0.8.5" 20 | num_enum = "0.7.2" 21 | thiserror = "1.0" 22 | log = "0.4.20" 23 | tokio = { version = "1.35.1", features = ["full"] } 24 | async-trait = "0.1.77" 25 | 26 | [features] 27 | default = ["md5"] 28 | openssl = ["dep:openssl"] 29 | md5 = ["dep:md5"] 30 | 31 | -------------------------------------------------------------------------------- /radius/src/client.rs: -------------------------------------------------------------------------------- 1 | //! RADIUS client implementation. 2 | 3 | use std::net::SocketAddr; 4 | use std::time::Duration; 5 | 6 | use thiserror::Error; 7 | use tokio::net::UdpSocket; 8 | use tokio::time::timeout; 9 | 10 | use crate::core::packet::Packet; 11 | 12 | #[derive(Error, Debug)] 13 | pub enum ClientError { 14 | /// This error is occurred when UDP socket binding has been failed. 15 | #[error("failed to bind a UDP socket; {0}")] 16 | FailedUdpSocketBindingError(String), 17 | 18 | /// This error is raised when it failed to establish the connection. 19 | #[error("failed to establish a UDP connection to {0}; {1}")] 20 | FailedEstablishingUdpConnectionError(String, String), 21 | 22 | /// This error is raised when encoding RADIUS packet has been failed. 23 | #[error("failed to encode a RADIUS request; {0}")] 24 | FailedRadiusPacketEncodingError(String), 25 | 26 | /// This error is raised when it fails to send a RADIUS packet. 27 | #[error("failed to send a UDP datagram to {0}; {1}")] 28 | FailedSendingRadiusPacketError(String, String), 29 | 30 | /// This error is raised when it fails to receive a RADIUS response. 31 | #[error("failed to receive the UDP response from {0}; {1}")] 32 | FailedReceivingResponseError(String, String), 33 | 34 | /// This error is raised when it fails to decode a RADIUS response packet. 35 | #[error("failed to decode a RADIUS response packet; {0}")] 36 | FailedDecodingRadiusResponseError(String), 37 | 38 | /// This error is raised when it exceeds the connection timeout duration. 39 | /// Connection timeout means it fails to establish a connection in time. 40 | #[error("connection timeout")] 41 | ConnectionTimeoutError(), 42 | 43 | /// This error is raised when it exceeds the socket timeout duration. 44 | /// Socket timeout means it fails to receive a response from the request target in time. 45 | #[error("socket timeout")] 46 | SocketTimeoutError(), 47 | } 48 | 49 | /// A basic implementation of the RADIUS client. 50 | pub struct Client { 51 | connection_timeout: Option, 52 | socket_timeout: Option, 53 | } 54 | 55 | impl Client { 56 | const MAX_DATAGRAM_SIZE: usize = 65507; 57 | 58 | /// A constructor for a client. 59 | /// 60 | /// # Arguments 61 | /// 62 | /// * `connection_timeout` - A duration of connection timeout. If the connection is not established in time, the `ConnectionTimeoutError` occurs. 63 | /// If this value is `None`, it never timed-out. 64 | /// * `socket_timeout` - A duration of socket timeout. If the response is not returned in time, the `SocketTimeoutError` occurs. 65 | /// If this value is `None`, it never timed-out. 66 | pub fn new(connection_timeout: Option, socket_timeout: Option) -> Self { 67 | Client { 68 | connection_timeout, 69 | socket_timeout, 70 | } 71 | } 72 | 73 | /// This method sends a packet to the destination. 74 | /// 75 | /// This method doesn't support auto retransmission when something failed, so if you need such a feature you have to implement that. 76 | pub async fn send_packet( 77 | &self, 78 | remote_addr: &SocketAddr, 79 | request_packet: &Packet, 80 | ) -> Result { 81 | let local_addr: SocketAddr = if remote_addr.is_ipv4() { 82 | "0.0.0.0:0" 83 | } else { 84 | "[::]:0" 85 | } 86 | .parse() 87 | .unwrap(); 88 | 89 | let conn = match UdpSocket::bind(local_addr).await { 90 | Ok(conn) => conn, 91 | Err(e) => return Err(ClientError::FailedUdpSocketBindingError(e.to_string())), 92 | }; 93 | 94 | match self.connection_timeout { 95 | Some(connection_timeout) => { 96 | match timeout(connection_timeout, self.connect(&conn, remote_addr)).await { 97 | Ok(conn_establish_res) => conn_establish_res, 98 | Err(_) => Err(ClientError::ConnectionTimeoutError()), 99 | } 100 | } 101 | None => self.connect(&conn, remote_addr).await, 102 | }?; 103 | 104 | let request_data = match request_packet.encode() { 105 | Ok(encoded) => encoded, 106 | Err(e) => return Err(ClientError::FailedRadiusPacketEncodingError(format!("{e}"))), 107 | }; 108 | 109 | let response = match self.socket_timeout { 110 | Some(socket_timeout) => { 111 | match timeout( 112 | socket_timeout, 113 | self.request(&conn, &request_data, remote_addr), 114 | ) 115 | .await 116 | { 117 | Ok(response) => response, 118 | Err(_) => Err(ClientError::SocketTimeoutError()), 119 | } 120 | } 121 | None => self.request(&conn, &request_data, remote_addr).await, 122 | }?; 123 | 124 | match Packet::decode(&response.to_vec(), request_packet.get_secret()) { 125 | Ok(response_packet) => Ok(response_packet), 126 | Err(e) => Err(ClientError::FailedDecodingRadiusResponseError(format!( 127 | "{e}" 128 | ))), 129 | } 130 | } 131 | 132 | async fn connect(&self, conn: &UdpSocket, remote_addr: &SocketAddr) -> Result<(), ClientError> { 133 | match conn.connect(remote_addr).await { 134 | Ok(_) => Ok(()), 135 | Err(e) => Err(ClientError::FailedEstablishingUdpConnectionError( 136 | remote_addr.to_string(), 137 | e.to_string(), 138 | )), 139 | } 140 | } 141 | 142 | async fn request( 143 | &self, 144 | conn: &UdpSocket, 145 | request_data: &[u8], 146 | remote_addr: &SocketAddr, 147 | ) -> Result, ClientError> { 148 | match conn.send(request_data).await { 149 | Ok(_) => {} 150 | Err(e) => { 151 | return Err(ClientError::FailedSendingRadiusPacketError( 152 | remote_addr.to_string(), 153 | e.to_string(), 154 | )) 155 | } 156 | }; 157 | 158 | let mut buf = vec![0; Self::MAX_DATAGRAM_SIZE]; 159 | match conn.recv(&mut buf).await { 160 | Ok(len) => Ok(buf[..len].to_vec()), 161 | Err(e) => Err(ClientError::FailedReceivingResponseError( 162 | remote_addr.to_string(), 163 | e.to_string(), 164 | )), 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /radius/src/core/attributes.rs: -------------------------------------------------------------------------------- 1 | use crate::core::avp::{AVPType, AVP}; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub(crate) struct Attributes(pub(crate) Vec); 5 | 6 | impl Attributes { 7 | pub(crate) fn decode(bs: &[u8]) -> Result { 8 | let mut i = 0; 9 | let mut attrs = Vec::new(); 10 | 11 | while bs.len() > i { 12 | if bs[i..].len() < 2 { 13 | return Err("short buffer".to_owned()); 14 | } 15 | 16 | let length = bs[i + 1] as usize; 17 | if length > bs[i..].len() || !(2..=255).contains(&length) { 18 | return Err("invalid attribute length".to_owned()); 19 | } 20 | 21 | attrs.push(AVP { 22 | typ: bs[i], 23 | value: if length > 2 { 24 | bs[i + 2..i + length].to_vec() 25 | } else { 26 | vec![] 27 | }, 28 | }); 29 | 30 | i += length; 31 | } 32 | 33 | Ok(Attributes(attrs)) 34 | } 35 | 36 | pub(crate) fn add(&mut self, avp: AVP) { 37 | self.0.push(avp) 38 | } 39 | 40 | pub(crate) fn extend(&mut self, avps: Vec) { 41 | self.0.extend(avps) 42 | } 43 | 44 | pub(crate) fn del(&mut self, typ: AVPType) { 45 | self.0.retain(|avp| avp.typ != typ); 46 | } 47 | 48 | pub(crate) fn lookup(&self, typ: AVPType) -> Option<&AVP> { 49 | self.0.iter().find(|avp| avp.typ == typ) 50 | } 51 | 52 | pub(crate) fn lookup_all(&self, typ: AVPType) -> Vec<&AVP> { 53 | self.0.iter().filter(|&avp| avp.typ == typ).collect() 54 | } 55 | 56 | pub(crate) fn encode(&self) -> Result, String> { 57 | let mut encoded: Vec = Vec::new(); 58 | 59 | for avp in &self.0 { 60 | let attr_len = avp.value.len(); 61 | if attr_len > 253 { 62 | return Err("attribute is too large".to_owned()); 63 | } 64 | encoded.push(avp.typ); 65 | encoded.push(2 + attr_len as u8); 66 | encoded.extend(&avp.value); 67 | } 68 | 69 | Ok(encoded) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /radius/src/core/code.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryFrom; 2 | 3 | use num_enum::TryFromPrimitive; 4 | 5 | #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)] 6 | #[repr(u8)] 7 | pub enum Code { 8 | AccessRequest = 1, 9 | AccessAccept = 2, 10 | AccessReject = 3, 11 | AccountingRequest = 4, 12 | AccountingResponse = 5, 13 | AccessChallenge = 11, 14 | StatusServer = 12, 15 | StatusClient = 13, 16 | DisconnectRequest = 40, 17 | DisconnectACK = 41, 18 | DisconnectNAK = 42, 19 | CoARequest = 43, 20 | CoAACK = 44, 21 | CoANAK = 45, 22 | Reserved = 255, 23 | Invalid = 0, 24 | } 25 | 26 | impl Code { 27 | pub fn string(&self) -> &'static str { 28 | match self { 29 | Code::AccessRequest => "Access-Request", 30 | Code::AccessAccept => "Access-Accept", 31 | Code::AccessReject => "Access-Reject", 32 | Code::AccountingRequest => "Accounting-Request", 33 | Code::AccountingResponse => "Accounting-Response", 34 | Code::AccessChallenge => "Access-Challenge", 35 | Code::StatusServer => "Status-Server", 36 | Code::StatusClient => "Status-Client", 37 | Code::DisconnectRequest => "Disconnect-Request", 38 | Code::DisconnectACK => "Disconnect-ACK", 39 | Code::DisconnectNAK => "Disconnect-NAK", 40 | Code::CoARequest => "CoA-Request", 41 | Code::CoAACK => "CoA-ACK", 42 | Code::CoANAK => "CoA-NAK", 43 | Code::Reserved => "Reserved", 44 | Code::Invalid => "Invalid", 45 | } 46 | } 47 | 48 | pub fn from(value: u8) -> Self { 49 | match Code::try_from(value) { 50 | Ok(code) => code, 51 | Err(_) => Code::Invalid, 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /radius/src/core/mod.rs: -------------------------------------------------------------------------------- 1 | //! RADIUS core implementation for server, client and application. 2 | 3 | pub(crate) mod attributes; 4 | pub mod avp; 5 | pub mod code; 6 | pub mod packet; 7 | pub mod request; 8 | pub mod rfc2865; 9 | pub mod rfc2866; 10 | pub mod rfc2867; 11 | pub mod rfc2868; 12 | pub mod rfc2869; 13 | pub mod rfc3162; 14 | pub mod rfc3576; 15 | pub mod rfc3580; 16 | pub mod rfc4072; 17 | pub mod rfc4372; 18 | pub mod rfc4603; 19 | pub mod rfc4675; 20 | pub mod rfc4818; 21 | pub mod rfc4849; 22 | pub mod rfc5090; 23 | pub mod rfc5176; 24 | pub mod rfc5607; 25 | pub mod rfc5904; 26 | pub mod rfc6519; 27 | pub mod rfc6572; 28 | pub mod rfc6677; 29 | pub mod rfc6911; 30 | pub mod rfc7055; 31 | pub mod rfc7155; 32 | pub mod tag; 33 | pub mod vsa; 34 | -------------------------------------------------------------------------------- /radius/src/core/request.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | 3 | use crate::core::packet::Packet; 4 | 5 | /// RADIUS request object. 6 | pub struct Request { 7 | local_addr: SocketAddr, 8 | remote_addr: SocketAddr, 9 | packet: Packet, 10 | } 11 | 12 | impl Request { 13 | pub fn new(local_addr: SocketAddr, remote_addr: SocketAddr, packet: Packet) -> Self { 14 | Self { 15 | local_addr, 16 | remote_addr, 17 | packet, 18 | } 19 | } 20 | 21 | pub fn get_local_addr(&self) -> SocketAddr { 22 | self.local_addr 23 | } 24 | 25 | pub fn get_remote_addr(&self) -> SocketAddr { 26 | self.remote_addr 27 | } 28 | 29 | pub fn get_packet(&self) -> &Packet { 30 | &self.packet 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /radius/src/core/rfc2866.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc2866 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 2866. 13 | //! # http://www.ietf.org/rfc/rfc2866.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Acct-Status-Type 40 integer 18 | //! ATTRIBUTE Acct-Delay-Time 41 integer 19 | //! ATTRIBUTE Acct-Input-Octets 42 integer 20 | //! ATTRIBUTE Acct-Output-Octets 43 integer 21 | //! ATTRIBUTE Acct-Session-Id 44 string 22 | //! ATTRIBUTE Acct-Authentic 45 integer 23 | //! ATTRIBUTE Acct-Session-Time 46 integer 24 | //! ATTRIBUTE Acct-Input-Packets 47 integer 25 | //! ATTRIBUTE Acct-Output-Packets 48 integer 26 | //! ATTRIBUTE Acct-Terminate-Cause 49 integer 27 | //! ATTRIBUTE Acct-Multi-Session-Id 50 string 28 | //! ATTRIBUTE Acct-Link-Count 51 integer 29 | //! 30 | //! # Accounting Status Types 31 | //! 32 | //! VALUE Acct-Status-Type Start 1 33 | //! VALUE Acct-Status-Type Stop 2 34 | //! VALUE Acct-Status-Type Alive 3 # dup 35 | //! VALUE Acct-Status-Type Interim-Update 3 36 | //! VALUE Acct-Status-Type Accounting-On 7 37 | //! VALUE Acct-Status-Type Accounting-Off 8 38 | //! VALUE Acct-Status-Type Failed 15 39 | //! 40 | //! # Authentication Types 41 | //! 42 | //! VALUE Acct-Authentic RADIUS 1 43 | //! VALUE Acct-Authentic Local 2 44 | //! VALUE Acct-Authentic Remote 3 45 | //! VALUE Acct-Authentic Diameter 4 46 | //! 47 | //! # Acct Terminate Causes 48 | //! 49 | //! VALUE Acct-Terminate-Cause User-Request 1 50 | //! VALUE Acct-Terminate-Cause Lost-Carrier 2 51 | //! VALUE Acct-Terminate-Cause Lost-Service 3 52 | //! VALUE Acct-Terminate-Cause Idle-Timeout 4 53 | //! VALUE Acct-Terminate-Cause Session-Timeout 5 54 | //! VALUE Acct-Terminate-Cause Admin-Reset 6 55 | //! VALUE Acct-Terminate-Cause Admin-Reboot 7 56 | //! VALUE Acct-Terminate-Cause Port-Error 8 57 | //! VALUE Acct-Terminate-Cause NAS-Error 9 58 | //! VALUE Acct-Terminate-Cause NAS-Request 10 59 | //! VALUE Acct-Terminate-Cause NAS-Reboot 11 60 | //! VALUE Acct-Terminate-Cause Port-Unneeded 12 61 | //! VALUE Acct-Terminate-Cause Port-Preempted 13 62 | //! VALUE Acct-Terminate-Cause Port-Suspended 14 63 | //! VALUE Acct-Terminate-Cause Service-Unavailable 15 64 | //! VALUE Acct-Terminate-Cause Callback 16 65 | //! VALUE Acct-Terminate-Cause User-Error 17 66 | //! VALUE Acct-Terminate-Cause Host-Request 18 67 | //! ``` 68 | 69 | use crate::core::avp::{AVPError, AVPType, AVP}; 70 | use crate::core::packet::Packet; 71 | 72 | pub const ACCT_STATUS_TYPE_TYPE: AVPType = 40; 73 | /// Delete all of `acct_status_type` values from a packet. 74 | pub fn delete_acct_status_type(packet: &mut Packet) { 75 | packet.delete(ACCT_STATUS_TYPE_TYPE); 76 | } 77 | /// Add `acct_status_type` value-defined integer value to a packet. 78 | pub fn add_acct_status_type(packet: &mut Packet, value: AcctStatusType) { 79 | packet.add(AVP::from_u32(ACCT_STATUS_TYPE_TYPE, value)); 80 | } 81 | /// Lookup a `acct_status_type` value-defined integer value from a packet. 82 | /// 83 | /// It returns the first looked up value. If there is no associated value with `acct_status_type`, it returns `None`. 84 | pub fn lookup_acct_status_type(packet: &Packet) -> Option> { 85 | packet 86 | .lookup(ACCT_STATUS_TYPE_TYPE) 87 | .map(|v| Ok(v.encode_u32()? as AcctStatusType)) 88 | } 89 | /// Lookup all of the `acct_status_type` value-defined integer value from a packet. 90 | pub fn lookup_all_acct_status_type(packet: &Packet) -> Result, AVPError> { 91 | let mut vec = Vec::new(); 92 | for avp in packet.lookup_all(ACCT_STATUS_TYPE_TYPE) { 93 | vec.push(avp.encode_u32()? as AcctStatusType) 94 | } 95 | Ok(vec) 96 | } 97 | 98 | pub const ACCT_DELAY_TIME_TYPE: AVPType = 41; 99 | /// Delete all of `acct_delay_time` values from a packet. 100 | pub fn delete_acct_delay_time(packet: &mut Packet) { 101 | packet.delete(ACCT_DELAY_TIME_TYPE); 102 | } 103 | /// Add `acct_delay_time` integer value to a packet. 104 | pub fn add_acct_delay_time(packet: &mut Packet, value: u32) { 105 | packet.add(AVP::from_u32(ACCT_DELAY_TIME_TYPE, value)); 106 | } 107 | /// Lookup a `acct_delay_time` integer value from a packet. 108 | /// 109 | /// It returns the first looked up value. If there is no associated value with `acct_delay_time`, it returns `None`. 110 | pub fn lookup_acct_delay_time(packet: &Packet) -> Option> { 111 | packet.lookup(ACCT_DELAY_TIME_TYPE).map(|v| v.encode_u32()) 112 | } 113 | /// Lookup all of the `acct_delay_time` integer value from a packet. 114 | pub fn lookup_all_acct_delay_time(packet: &Packet) -> Result, AVPError> { 115 | let mut vec = Vec::new(); 116 | for avp in packet.lookup_all(ACCT_DELAY_TIME_TYPE) { 117 | vec.push(avp.encode_u32()?) 118 | } 119 | Ok(vec) 120 | } 121 | 122 | pub const ACCT_INPUT_OCTETS_TYPE: AVPType = 42; 123 | /// Delete all of `acct_input_octets` values from a packet. 124 | pub fn delete_acct_input_octets(packet: &mut Packet) { 125 | packet.delete(ACCT_INPUT_OCTETS_TYPE); 126 | } 127 | /// Add `acct_input_octets` integer value to a packet. 128 | pub fn add_acct_input_octets(packet: &mut Packet, value: u32) { 129 | packet.add(AVP::from_u32(ACCT_INPUT_OCTETS_TYPE, value)); 130 | } 131 | /// Lookup a `acct_input_octets` integer value from a packet. 132 | /// 133 | /// It returns the first looked up value. If there is no associated value with `acct_input_octets`, it returns `None`. 134 | pub fn lookup_acct_input_octets(packet: &Packet) -> Option> { 135 | packet 136 | .lookup(ACCT_INPUT_OCTETS_TYPE) 137 | .map(|v| v.encode_u32()) 138 | } 139 | /// Lookup all of the `acct_input_octets` integer value from a packet. 140 | pub fn lookup_all_acct_input_octets(packet: &Packet) -> Result, AVPError> { 141 | let mut vec = Vec::new(); 142 | for avp in packet.lookup_all(ACCT_INPUT_OCTETS_TYPE) { 143 | vec.push(avp.encode_u32()?) 144 | } 145 | Ok(vec) 146 | } 147 | 148 | pub const ACCT_OUTPUT_OCTETS_TYPE: AVPType = 43; 149 | /// Delete all of `acct_output_octets` values from a packet. 150 | pub fn delete_acct_output_octets(packet: &mut Packet) { 151 | packet.delete(ACCT_OUTPUT_OCTETS_TYPE); 152 | } 153 | /// Add `acct_output_octets` integer value to a packet. 154 | pub fn add_acct_output_octets(packet: &mut Packet, value: u32) { 155 | packet.add(AVP::from_u32(ACCT_OUTPUT_OCTETS_TYPE, value)); 156 | } 157 | /// Lookup a `acct_output_octets` integer value from a packet. 158 | /// 159 | /// It returns the first looked up value. If there is no associated value with `acct_output_octets`, it returns `None`. 160 | pub fn lookup_acct_output_octets(packet: &Packet) -> Option> { 161 | packet 162 | .lookup(ACCT_OUTPUT_OCTETS_TYPE) 163 | .map(|v| v.encode_u32()) 164 | } 165 | /// Lookup all of the `acct_output_octets` integer value from a packet. 166 | pub fn lookup_all_acct_output_octets(packet: &Packet) -> Result, AVPError> { 167 | let mut vec = Vec::new(); 168 | for avp in packet.lookup_all(ACCT_OUTPUT_OCTETS_TYPE) { 169 | vec.push(avp.encode_u32()?) 170 | } 171 | Ok(vec) 172 | } 173 | 174 | pub const ACCT_SESSION_ID_TYPE: AVPType = 44; 175 | /// Delete all of `acct_session_id` values from a packet. 176 | pub fn delete_acct_session_id(packet: &mut Packet) { 177 | packet.delete(ACCT_SESSION_ID_TYPE); 178 | } 179 | /// Add `acct_session_id` string value to a packet. 180 | pub fn add_acct_session_id(packet: &mut Packet, value: &str) { 181 | packet.add(AVP::from_string(ACCT_SESSION_ID_TYPE, value)); 182 | } 183 | /// Lookup a `acct_session_id` string value from a packet. 184 | /// 185 | /// It returns the first looked up value. If there is no associated value with `acct_session_id`, it returns `None`. 186 | pub fn lookup_acct_session_id(packet: &Packet) -> Option> { 187 | packet 188 | .lookup(ACCT_SESSION_ID_TYPE) 189 | .map(|v| v.encode_string()) 190 | } 191 | /// Lookup all of the `acct_session_id` string value from a packet. 192 | pub fn lookup_all_acct_session_id(packet: &Packet) -> Result, AVPError> { 193 | let mut vec = Vec::new(); 194 | for avp in packet.lookup_all(ACCT_SESSION_ID_TYPE) { 195 | vec.push(avp.encode_string()?) 196 | } 197 | Ok(vec) 198 | } 199 | 200 | pub const ACCT_AUTHENTIC_TYPE: AVPType = 45; 201 | /// Delete all of `acct_authentic` values from a packet. 202 | pub fn delete_acct_authentic(packet: &mut Packet) { 203 | packet.delete(ACCT_AUTHENTIC_TYPE); 204 | } 205 | /// Add `acct_authentic` value-defined integer value to a packet. 206 | pub fn add_acct_authentic(packet: &mut Packet, value: AcctAuthentic) { 207 | packet.add(AVP::from_u32(ACCT_AUTHENTIC_TYPE, value)); 208 | } 209 | /// Lookup a `acct_authentic` value-defined integer value from a packet. 210 | /// 211 | /// It returns the first looked up value. If there is no associated value with `acct_authentic`, it returns `None`. 212 | pub fn lookup_acct_authentic(packet: &Packet) -> Option> { 213 | packet 214 | .lookup(ACCT_AUTHENTIC_TYPE) 215 | .map(|v| Ok(v.encode_u32()? as AcctAuthentic)) 216 | } 217 | /// Lookup all of the `acct_authentic` value-defined integer value from a packet. 218 | pub fn lookup_all_acct_authentic(packet: &Packet) -> Result, AVPError> { 219 | let mut vec = Vec::new(); 220 | for avp in packet.lookup_all(ACCT_AUTHENTIC_TYPE) { 221 | vec.push(avp.encode_u32()? as AcctAuthentic) 222 | } 223 | Ok(vec) 224 | } 225 | 226 | pub const ACCT_SESSION_TIME_TYPE: AVPType = 46; 227 | /// Delete all of `acct_session_time` values from a packet. 228 | pub fn delete_acct_session_time(packet: &mut Packet) { 229 | packet.delete(ACCT_SESSION_TIME_TYPE); 230 | } 231 | /// Add `acct_session_time` integer value to a packet. 232 | pub fn add_acct_session_time(packet: &mut Packet, value: u32) { 233 | packet.add(AVP::from_u32(ACCT_SESSION_TIME_TYPE, value)); 234 | } 235 | /// Lookup a `acct_session_time` integer value from a packet. 236 | /// 237 | /// It returns the first looked up value. If there is no associated value with `acct_session_time`, it returns `None`. 238 | pub fn lookup_acct_session_time(packet: &Packet) -> Option> { 239 | packet 240 | .lookup(ACCT_SESSION_TIME_TYPE) 241 | .map(|v| v.encode_u32()) 242 | } 243 | /// Lookup all of the `acct_session_time` integer value from a packet. 244 | pub fn lookup_all_acct_session_time(packet: &Packet) -> Result, AVPError> { 245 | let mut vec = Vec::new(); 246 | for avp in packet.lookup_all(ACCT_SESSION_TIME_TYPE) { 247 | vec.push(avp.encode_u32()?) 248 | } 249 | Ok(vec) 250 | } 251 | 252 | pub const ACCT_INPUT_PACKETS_TYPE: AVPType = 47; 253 | /// Delete all of `acct_input_packets` values from a packet. 254 | pub fn delete_acct_input_packets(packet: &mut Packet) { 255 | packet.delete(ACCT_INPUT_PACKETS_TYPE); 256 | } 257 | /// Add `acct_input_packets` integer value to a packet. 258 | pub fn add_acct_input_packets(packet: &mut Packet, value: u32) { 259 | packet.add(AVP::from_u32(ACCT_INPUT_PACKETS_TYPE, value)); 260 | } 261 | /// Lookup a `acct_input_packets` integer value from a packet. 262 | /// 263 | /// It returns the first looked up value. If there is no associated value with `acct_input_packets`, it returns `None`. 264 | pub fn lookup_acct_input_packets(packet: &Packet) -> Option> { 265 | packet 266 | .lookup(ACCT_INPUT_PACKETS_TYPE) 267 | .map(|v| v.encode_u32()) 268 | } 269 | /// Lookup all of the `acct_input_packets` integer value from a packet. 270 | pub fn lookup_all_acct_input_packets(packet: &Packet) -> Result, AVPError> { 271 | let mut vec = Vec::new(); 272 | for avp in packet.lookup_all(ACCT_INPUT_PACKETS_TYPE) { 273 | vec.push(avp.encode_u32()?) 274 | } 275 | Ok(vec) 276 | } 277 | 278 | pub const ACCT_OUTPUT_PACKETS_TYPE: AVPType = 48; 279 | /// Delete all of `acct_output_packets` values from a packet. 280 | pub fn delete_acct_output_packets(packet: &mut Packet) { 281 | packet.delete(ACCT_OUTPUT_PACKETS_TYPE); 282 | } 283 | /// Add `acct_output_packets` integer value to a packet. 284 | pub fn add_acct_output_packets(packet: &mut Packet, value: u32) { 285 | packet.add(AVP::from_u32(ACCT_OUTPUT_PACKETS_TYPE, value)); 286 | } 287 | /// Lookup a `acct_output_packets` integer value from a packet. 288 | /// 289 | /// It returns the first looked up value. If there is no associated value with `acct_output_packets`, it returns `None`. 290 | pub fn lookup_acct_output_packets(packet: &Packet) -> Option> { 291 | packet 292 | .lookup(ACCT_OUTPUT_PACKETS_TYPE) 293 | .map(|v| v.encode_u32()) 294 | } 295 | /// Lookup all of the `acct_output_packets` integer value from a packet. 296 | pub fn lookup_all_acct_output_packets(packet: &Packet) -> Result, AVPError> { 297 | let mut vec = Vec::new(); 298 | for avp in packet.lookup_all(ACCT_OUTPUT_PACKETS_TYPE) { 299 | vec.push(avp.encode_u32()?) 300 | } 301 | Ok(vec) 302 | } 303 | 304 | pub const ACCT_TERMINATE_CAUSE_TYPE: AVPType = 49; 305 | /// Delete all of `acct_terminate_cause` values from a packet. 306 | pub fn delete_acct_terminate_cause(packet: &mut Packet) { 307 | packet.delete(ACCT_TERMINATE_CAUSE_TYPE); 308 | } 309 | /// Add `acct_terminate_cause` value-defined integer value to a packet. 310 | pub fn add_acct_terminate_cause(packet: &mut Packet, value: AcctTerminateCause) { 311 | packet.add(AVP::from_u32(ACCT_TERMINATE_CAUSE_TYPE, value)); 312 | } 313 | /// Lookup a `acct_terminate_cause` value-defined integer value from a packet. 314 | /// 315 | /// It returns the first looked up value. If there is no associated value with `acct_terminate_cause`, it returns `None`. 316 | pub fn lookup_acct_terminate_cause( 317 | packet: &Packet, 318 | ) -> Option> { 319 | packet 320 | .lookup(ACCT_TERMINATE_CAUSE_TYPE) 321 | .map(|v| Ok(v.encode_u32()? as AcctTerminateCause)) 322 | } 323 | /// Lookup all of the `acct_terminate_cause` value-defined integer value from a packet. 324 | pub fn lookup_all_acct_terminate_cause( 325 | packet: &Packet, 326 | ) -> Result, AVPError> { 327 | let mut vec = Vec::new(); 328 | for avp in packet.lookup_all(ACCT_TERMINATE_CAUSE_TYPE) { 329 | vec.push(avp.encode_u32()? as AcctTerminateCause) 330 | } 331 | Ok(vec) 332 | } 333 | 334 | pub const ACCT_MULTI_SESSION_ID_TYPE: AVPType = 50; 335 | /// Delete all of `acct_multi_session_id` values from a packet. 336 | pub fn delete_acct_multi_session_id(packet: &mut Packet) { 337 | packet.delete(ACCT_MULTI_SESSION_ID_TYPE); 338 | } 339 | /// Add `acct_multi_session_id` string value to a packet. 340 | pub fn add_acct_multi_session_id(packet: &mut Packet, value: &str) { 341 | packet.add(AVP::from_string(ACCT_MULTI_SESSION_ID_TYPE, value)); 342 | } 343 | /// Lookup a `acct_multi_session_id` string value from a packet. 344 | /// 345 | /// It returns the first looked up value. If there is no associated value with `acct_multi_session_id`, it returns `None`. 346 | pub fn lookup_acct_multi_session_id(packet: &Packet) -> Option> { 347 | packet 348 | .lookup(ACCT_MULTI_SESSION_ID_TYPE) 349 | .map(|v| v.encode_string()) 350 | } 351 | /// Lookup all of the `acct_multi_session_id` string value from a packet. 352 | pub fn lookup_all_acct_multi_session_id(packet: &Packet) -> Result, AVPError> { 353 | let mut vec = Vec::new(); 354 | for avp in packet.lookup_all(ACCT_MULTI_SESSION_ID_TYPE) { 355 | vec.push(avp.encode_string()?) 356 | } 357 | Ok(vec) 358 | } 359 | 360 | pub const ACCT_LINK_COUNT_TYPE: AVPType = 51; 361 | /// Delete all of `acct_link_count` values from a packet. 362 | pub fn delete_acct_link_count(packet: &mut Packet) { 363 | packet.delete(ACCT_LINK_COUNT_TYPE); 364 | } 365 | /// Add `acct_link_count` integer value to a packet. 366 | pub fn add_acct_link_count(packet: &mut Packet, value: u32) { 367 | packet.add(AVP::from_u32(ACCT_LINK_COUNT_TYPE, value)); 368 | } 369 | /// Lookup a `acct_link_count` integer value from a packet. 370 | /// 371 | /// It returns the first looked up value. If there is no associated value with `acct_link_count`, it returns `None`. 372 | pub fn lookup_acct_link_count(packet: &Packet) -> Option> { 373 | packet.lookup(ACCT_LINK_COUNT_TYPE).map(|v| v.encode_u32()) 374 | } 375 | /// Lookup all of the `acct_link_count` integer value from a packet. 376 | pub fn lookup_all_acct_link_count(packet: &Packet) -> Result, AVPError> { 377 | let mut vec = Vec::new(); 378 | for avp in packet.lookup_all(ACCT_LINK_COUNT_TYPE) { 379 | vec.push(avp.encode_u32()?) 380 | } 381 | Ok(vec) 382 | } 383 | 384 | pub type AcctAuthentic = u32; 385 | pub const ACCT_AUTHENTIC_RADIUS: AcctAuthentic = 1; 386 | pub const ACCT_AUTHENTIC_LOCAL: AcctAuthentic = 2; 387 | pub const ACCT_AUTHENTIC_REMOTE: AcctAuthentic = 3; 388 | pub const ACCT_AUTHENTIC_DIAMETER: AcctAuthentic = 4; 389 | 390 | pub type AcctStatusType = u32; 391 | pub const ACCT_STATUS_TYPE_START: AcctStatusType = 1; 392 | pub const ACCT_STATUS_TYPE_STOP: AcctStatusType = 2; 393 | pub const ACCT_STATUS_TYPE_ALIVE: AcctStatusType = 3; 394 | pub const ACCT_STATUS_TYPE_INTERIM_UPDATE: AcctStatusType = 3; 395 | pub const ACCT_STATUS_TYPE_ACCOUNTING_ON: AcctStatusType = 7; 396 | pub const ACCT_STATUS_TYPE_ACCOUNTING_OFF: AcctStatusType = 8; 397 | pub const ACCT_STATUS_TYPE_FAILED: AcctStatusType = 15; 398 | 399 | pub type AcctTerminateCause = u32; 400 | pub const ACCT_TERMINATE_CAUSE_USER_REQUEST: AcctTerminateCause = 1; 401 | pub const ACCT_TERMINATE_CAUSE_LOST_CARRIER: AcctTerminateCause = 2; 402 | pub const ACCT_TERMINATE_CAUSE_LOST_SERVICE: AcctTerminateCause = 3; 403 | pub const ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT: AcctTerminateCause = 4; 404 | pub const ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT: AcctTerminateCause = 5; 405 | pub const ACCT_TERMINATE_CAUSE_ADMIN_RESET: AcctTerminateCause = 6; 406 | pub const ACCT_TERMINATE_CAUSE_ADMIN_REBOOT: AcctTerminateCause = 7; 407 | pub const ACCT_TERMINATE_CAUSE_PORT_ERROR: AcctTerminateCause = 8; 408 | pub const ACCT_TERMINATE_CAUSE_NAS_ERROR: AcctTerminateCause = 9; 409 | pub const ACCT_TERMINATE_CAUSE_NAS_REQUEST: AcctTerminateCause = 10; 410 | pub const ACCT_TERMINATE_CAUSE_NAS_REBOOT: AcctTerminateCause = 11; 411 | pub const ACCT_TERMINATE_CAUSE_PORT_UNNEEDED: AcctTerminateCause = 12; 412 | pub const ACCT_TERMINATE_CAUSE_PORT_PREEMPTED: AcctTerminateCause = 13; 413 | pub const ACCT_TERMINATE_CAUSE_PORT_SUSPENDED: AcctTerminateCause = 14; 414 | pub const ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE: AcctTerminateCause = 15; 415 | pub const ACCT_TERMINATE_CAUSE_CALLBACK: AcctTerminateCause = 16; 416 | pub const ACCT_TERMINATE_CAUSE_USER_ERROR: AcctTerminateCause = 17; 417 | pub const ACCT_TERMINATE_CAUSE_HOST_REQUEST: AcctTerminateCause = 18; 418 | -------------------------------------------------------------------------------- /radius/src/core/rfc2867.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc2867 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 2867. 13 | //! # http://www.ietf.org/rfc/rfc2867.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Acct-Tunnel-Connection 68 string 18 | //! ATTRIBUTE Acct-Tunnel-Packets-Lost 86 integer 19 | //! 20 | //! VALUE Acct-Status-Type Tunnel-Start 9 21 | //! VALUE Acct-Status-Type Tunnel-Stop 10 22 | //! VALUE Acct-Status-Type Tunnel-Reject 11 23 | //! VALUE Acct-Status-Type Tunnel-Link-Start 12 24 | //! VALUE Acct-Status-Type Tunnel-Link-Stop 13 25 | //! VALUE Acct-Status-Type Tunnel-Link-Reject 14 26 | //! ``` 27 | 28 | use crate::core::avp::{AVPError, AVPType, AVP}; 29 | use crate::core::packet::Packet; 30 | 31 | use crate::core::rfc2866; 32 | 33 | pub const ACCT_TUNNEL_CONNECTION_TYPE: AVPType = 68; 34 | /// Delete all of `acct_tunnel_connection` values from a packet. 35 | pub fn delete_acct_tunnel_connection(packet: &mut Packet) { 36 | packet.delete(ACCT_TUNNEL_CONNECTION_TYPE); 37 | } 38 | /// Add `acct_tunnel_connection` string value to a packet. 39 | pub fn add_acct_tunnel_connection(packet: &mut Packet, value: &str) { 40 | packet.add(AVP::from_string(ACCT_TUNNEL_CONNECTION_TYPE, value)); 41 | } 42 | /// Lookup a `acct_tunnel_connection` string value from a packet. 43 | /// 44 | /// It returns the first looked up value. If there is no associated value with `acct_tunnel_connection`, it returns `None`. 45 | pub fn lookup_acct_tunnel_connection(packet: &Packet) -> Option> { 46 | packet 47 | .lookup(ACCT_TUNNEL_CONNECTION_TYPE) 48 | .map(|v| v.encode_string()) 49 | } 50 | /// Lookup all of the `acct_tunnel_connection` string value from a packet. 51 | pub fn lookup_all_acct_tunnel_connection(packet: &Packet) -> Result, AVPError> { 52 | let mut vec = Vec::new(); 53 | for avp in packet.lookup_all(ACCT_TUNNEL_CONNECTION_TYPE) { 54 | vec.push(avp.encode_string()?) 55 | } 56 | Ok(vec) 57 | } 58 | 59 | pub const ACCT_TUNNEL_PACKETS_LOST_TYPE: AVPType = 86; 60 | /// Delete all of `acct_tunnel_packets_lost` values from a packet. 61 | pub fn delete_acct_tunnel_packets_lost(packet: &mut Packet) { 62 | packet.delete(ACCT_TUNNEL_PACKETS_LOST_TYPE); 63 | } 64 | /// Add `acct_tunnel_packets_lost` integer value to a packet. 65 | pub fn add_acct_tunnel_packets_lost(packet: &mut Packet, value: u32) { 66 | packet.add(AVP::from_u32(ACCT_TUNNEL_PACKETS_LOST_TYPE, value)); 67 | } 68 | /// Lookup a `acct_tunnel_packets_lost` integer value from a packet. 69 | /// 70 | /// It returns the first looked up value. If there is no associated value with `acct_tunnel_packets_lost`, it returns `None`. 71 | pub fn lookup_acct_tunnel_packets_lost(packet: &Packet) -> Option> { 72 | packet 73 | .lookup(ACCT_TUNNEL_PACKETS_LOST_TYPE) 74 | .map(|v| v.encode_u32()) 75 | } 76 | /// Lookup all of the `acct_tunnel_packets_lost` integer value from a packet. 77 | pub fn lookup_all_acct_tunnel_packets_lost(packet: &Packet) -> Result, AVPError> { 78 | let mut vec = Vec::new(); 79 | for avp in packet.lookup_all(ACCT_TUNNEL_PACKETS_LOST_TYPE) { 80 | vec.push(avp.encode_u32()?) 81 | } 82 | Ok(vec) 83 | } 84 | pub const ACCT_STATUS_TYPE_TUNNEL_START: rfc2866::AcctStatusType = 9; 85 | pub const ACCT_STATUS_TYPE_TUNNEL_STOP: rfc2866::AcctStatusType = 10; 86 | pub const ACCT_STATUS_TYPE_TUNNEL_REJECT: rfc2866::AcctStatusType = 11; 87 | pub const ACCT_STATUS_TYPE_TUNNEL_LINK_START: rfc2866::AcctStatusType = 12; 88 | pub const ACCT_STATUS_TYPE_TUNNEL_LINK_STOP: rfc2866::AcctStatusType = 13; 89 | pub const ACCT_STATUS_TYPE_TUNNEL_LINK_REJECT: rfc2866::AcctStatusType = 14; 90 | -------------------------------------------------------------------------------- /radius/src/core/rfc2868.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc2868 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 2868. 13 | //! # http://www.ietf.org/rfc/rfc2868.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Tunnel-Type 64 integer has_tag 18 | //! ATTRIBUTE Tunnel-Medium-Type 65 integer has_tag 19 | //! ATTRIBUTE Tunnel-Client-Endpoint 66 string has_tag 20 | //! ATTRIBUTE Tunnel-Server-Endpoint 67 string has_tag 21 | //! 22 | //! ATTRIBUTE Tunnel-Password 69 string has_tag,encrypt=2 23 | //! 24 | //! ATTRIBUTE Tunnel-Private-Group-Id 81 string has_tag 25 | //! ATTRIBUTE Tunnel-Assignment-Id 82 string has_tag 26 | //! ATTRIBUTE Tunnel-Preference 83 integer has_tag 27 | //! 28 | //! ATTRIBUTE Tunnel-Client-Auth-Id 90 string has_tag 29 | //! ATTRIBUTE Tunnel-Server-Auth-Id 91 string has_tag 30 | //! 31 | //! # Tunnel Type 32 | //! 33 | //! VALUE Tunnel-Type PPTP 1 34 | //! VALUE Tunnel-Type L2F 2 35 | //! VALUE Tunnel-Type L2TP 3 36 | //! VALUE Tunnel-Type ATMP 4 37 | //! VALUE Tunnel-Type VTP 5 38 | //! VALUE Tunnel-Type AH 6 39 | //! VALUE Tunnel-Type IP 7 40 | //! VALUE Tunnel-Type MIN-IP 8 41 | //! VALUE Tunnel-Type ESP 9 42 | //! VALUE Tunnel-Type GRE 10 43 | //! VALUE Tunnel-Type DVS 11 44 | //! VALUE Tunnel-Type IP-in-IP 12 45 | //! 46 | //! # Tunnel Medium Type 47 | //! 48 | //! VALUE Tunnel-Medium-Type IP 1 49 | //! VALUE Tunnel-Medium-Type IPv4 1 50 | //! VALUE Tunnel-Medium-Type IPv6 2 51 | //! VALUE Tunnel-Medium-Type NSAP 3 52 | //! VALUE Tunnel-Medium-Type HDLC 4 53 | //! VALUE Tunnel-Medium-Type BBN-1822 5 54 | //! VALUE Tunnel-Medium-Type IEEE-802 6 55 | //! VALUE Tunnel-Medium-Type E.163 7 56 | //! VALUE Tunnel-Medium-Type E.164 8 57 | //! VALUE Tunnel-Medium-Type F.69 9 58 | //! VALUE Tunnel-Medium-Type X.121 10 59 | //! VALUE Tunnel-Medium-Type IPX 11 60 | //! VALUE Tunnel-Medium-Type Appletalk 12 61 | //! VALUE Tunnel-Medium-Type DecNet-IV 13 62 | //! VALUE Tunnel-Medium-Type Banyan-Vines 14 63 | //! VALUE Tunnel-Medium-Type E.164-NSAP 15 64 | //! ``` 65 | 66 | use crate::core::avp::{AVPError, AVPType, AVP}; 67 | use crate::core::packet::Packet; 68 | use crate::core::tag::Tag; 69 | 70 | pub const TUNNEL_TYPE_TYPE: AVPType = 64; 71 | /// Delete all of `tunnel_type` values from a packet. 72 | pub fn delete_tunnel_type(packet: &mut Packet) { 73 | packet.delete(TUNNEL_TYPE_TYPE); 74 | } 75 | /// Add `tunnel_type` tagged value-defined integer value to a packet. 76 | pub fn add_tunnel_type(packet: &mut Packet, tag: Option<&Tag>, value: TunnelType) { 77 | packet.add(AVP::from_tagged_u32(TUNNEL_TYPE_TYPE, tag, value)); 78 | } 79 | /// Lookup a `tunnel_type` tagged value-defined integer value from a packet. 80 | /// 81 | /// It returns the first looked up value. If there is no associated value with `tunnel_type`, it returns `None`. 82 | pub fn lookup_tunnel_type(packet: &Packet) -> Option> { 83 | packet.lookup(TUNNEL_TYPE_TYPE).map(|v| { 84 | let (v, t) = v.encode_tagged_u32()?; 85 | Ok((v as TunnelType, t)) 86 | }) 87 | } 88 | /// Lookup all of the `tunnel_type` tagged value-defined integer value from a packet. 89 | pub fn lookup_all_tunnel_type(packet: &Packet) -> Result, AVPError> { 90 | let mut vec = Vec::new(); 91 | for avp in packet.lookup_all(TUNNEL_TYPE_TYPE) { 92 | let (v, t) = avp.encode_tagged_u32()?; 93 | vec.push((v as TunnelType, t)) 94 | } 95 | Ok(vec) 96 | } 97 | 98 | pub const TUNNEL_MEDIUM_TYPE_TYPE: AVPType = 65; 99 | /// Delete all of `tunnel_medium_type` values from a packet. 100 | pub fn delete_tunnel_medium_type(packet: &mut Packet) { 101 | packet.delete(TUNNEL_MEDIUM_TYPE_TYPE); 102 | } 103 | /// Add `tunnel_medium_type` tagged value-defined integer value to a packet. 104 | pub fn add_tunnel_medium_type(packet: &mut Packet, tag: Option<&Tag>, value: TunnelMediumType) { 105 | packet.add(AVP::from_tagged_u32(TUNNEL_MEDIUM_TYPE_TYPE, tag, value)); 106 | } 107 | /// Lookup a `tunnel_medium_type` tagged value-defined integer value from a packet. 108 | /// 109 | /// It returns the first looked up value. If there is no associated value with `tunnel_medium_type`, it returns `None`. 110 | pub fn lookup_tunnel_medium_type( 111 | packet: &Packet, 112 | ) -> Option> { 113 | packet.lookup(TUNNEL_MEDIUM_TYPE_TYPE).map(|v| { 114 | let (v, t) = v.encode_tagged_u32()?; 115 | Ok((v as TunnelMediumType, t)) 116 | }) 117 | } 118 | /// Lookup all of the `tunnel_medium_type` tagged value-defined integer value from a packet. 119 | pub fn lookup_all_tunnel_medium_type( 120 | packet: &Packet, 121 | ) -> Result, AVPError> { 122 | let mut vec = Vec::new(); 123 | for avp in packet.lookup_all(TUNNEL_MEDIUM_TYPE_TYPE) { 124 | let (v, t) = avp.encode_tagged_u32()?; 125 | vec.push((v as TunnelMediumType, t)) 126 | } 127 | Ok(vec) 128 | } 129 | 130 | pub const TUNNEL_CLIENT_ENDPOINT_TYPE: AVPType = 66; 131 | /// Delete all of `tunnel_client_endpoint` values from a packet. 132 | pub fn delete_tunnel_client_endpoint(packet: &mut Packet) { 133 | packet.delete(TUNNEL_CLIENT_ENDPOINT_TYPE); 134 | } 135 | /// Add `tunnel_client_endpoint` tagged string value to a packet. 136 | pub fn add_tunnel_client_endpoint(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 137 | packet.add(AVP::from_tagged_string( 138 | TUNNEL_CLIENT_ENDPOINT_TYPE, 139 | tag, 140 | value, 141 | )); 142 | } 143 | /// Lookup a `tunnel_client_endpoint` tagged string value from a packet. 144 | /// 145 | /// It returns the first looked up value. If there is no associated value with `tunnel_client_endpoint`, it returns `None`. 146 | pub fn lookup_tunnel_client_endpoint( 147 | packet: &Packet, 148 | ) -> Option), AVPError>> { 149 | packet 150 | .lookup(TUNNEL_CLIENT_ENDPOINT_TYPE) 151 | .map(|v| v.encode_tagged_string()) 152 | } 153 | /// Lookup all of the `tunnel_client_endpoint` tagged string value from a packet. 154 | pub fn lookup_all_tunnel_client_endpoint( 155 | packet: &Packet, 156 | ) -> Result)>, AVPError> { 157 | let mut vec = Vec::new(); 158 | for avp in packet.lookup_all(TUNNEL_CLIENT_ENDPOINT_TYPE) { 159 | vec.push(avp.encode_tagged_string()?) 160 | } 161 | Ok(vec) 162 | } 163 | 164 | pub const TUNNEL_SERVER_ENDPOINT_TYPE: AVPType = 67; 165 | /// Delete all of `tunnel_server_endpoint` values from a packet. 166 | pub fn delete_tunnel_server_endpoint(packet: &mut Packet) { 167 | packet.delete(TUNNEL_SERVER_ENDPOINT_TYPE); 168 | } 169 | /// Add `tunnel_server_endpoint` tagged string value to a packet. 170 | pub fn add_tunnel_server_endpoint(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 171 | packet.add(AVP::from_tagged_string( 172 | TUNNEL_SERVER_ENDPOINT_TYPE, 173 | tag, 174 | value, 175 | )); 176 | } 177 | /// Lookup a `tunnel_server_endpoint` tagged string value from a packet. 178 | /// 179 | /// It returns the first looked up value. If there is no associated value with `tunnel_server_endpoint`, it returns `None`. 180 | pub fn lookup_tunnel_server_endpoint( 181 | packet: &Packet, 182 | ) -> Option), AVPError>> { 183 | packet 184 | .lookup(TUNNEL_SERVER_ENDPOINT_TYPE) 185 | .map(|v| v.encode_tagged_string()) 186 | } 187 | /// Lookup all of the `tunnel_server_endpoint` tagged string value from a packet. 188 | pub fn lookup_all_tunnel_server_endpoint( 189 | packet: &Packet, 190 | ) -> Result)>, AVPError> { 191 | let mut vec = Vec::new(); 192 | for avp in packet.lookup_all(TUNNEL_SERVER_ENDPOINT_TYPE) { 193 | vec.push(avp.encode_tagged_string()?) 194 | } 195 | Ok(vec) 196 | } 197 | 198 | pub const TUNNEL_PASSWORD_TYPE: AVPType = 69; 199 | /// Delete all of `tunnel_password` values from a packet. 200 | pub fn delete_tunnel_password(packet: &mut Packet) { 201 | packet.delete(TUNNEL_PASSWORD_TYPE); 202 | } 203 | /// Add `tunnel_password` tunnel-password value to a packet. 204 | pub fn add_tunnel_password( 205 | packet: &mut Packet, 206 | tag: Option<&Tag>, 207 | value: &[u8], 208 | ) -> Result<(), AVPError> { 209 | packet.add(AVP::from_tunnel_password( 210 | TUNNEL_PASSWORD_TYPE, 211 | tag, 212 | value, 213 | packet.get_secret(), 214 | packet.get_authenticator(), 215 | )?); 216 | Ok(()) 217 | } 218 | /// Lookup a `tunnel_password` tunnel-password value from a packet. 219 | /// 220 | /// It returns the first looked up value. If there is no associated value with `tunnel_password`, it returns `None`. 221 | pub fn lookup_tunnel_password(packet: &Packet) -> Option, Tag), AVPError>> { 222 | packet 223 | .lookup(TUNNEL_PASSWORD_TYPE) 224 | .map(|v| v.encode_tunnel_password(packet.get_secret(), packet.get_authenticator())) 225 | } 226 | /// Lookup all of the `tunnel_password` tunnel-password value from a packet. 227 | pub fn lookup_all_tunnel_password(packet: &Packet) -> Result, Tag)>, AVPError> { 228 | let mut vec = Vec::new(); 229 | for avp in packet.lookup_all(TUNNEL_PASSWORD_TYPE) { 230 | vec.push(avp.encode_tunnel_password(packet.get_secret(), packet.get_authenticator())?) 231 | } 232 | Ok(vec) 233 | } 234 | 235 | pub const TUNNEL_PRIVATE_GROUP_ID_TYPE: AVPType = 81; 236 | /// Delete all of `tunnel_private_group_id` values from a packet. 237 | pub fn delete_tunnel_private_group_id(packet: &mut Packet) { 238 | packet.delete(TUNNEL_PRIVATE_GROUP_ID_TYPE); 239 | } 240 | /// Add `tunnel_private_group_id` tagged string value to a packet. 241 | pub fn add_tunnel_private_group_id(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 242 | packet.add(AVP::from_tagged_string( 243 | TUNNEL_PRIVATE_GROUP_ID_TYPE, 244 | tag, 245 | value, 246 | )); 247 | } 248 | /// Lookup a `tunnel_private_group_id` tagged string value from a packet. 249 | /// 250 | /// It returns the first looked up value. If there is no associated value with `tunnel_private_group_id`, it returns `None`. 251 | pub fn lookup_tunnel_private_group_id( 252 | packet: &Packet, 253 | ) -> Option), AVPError>> { 254 | packet 255 | .lookup(TUNNEL_PRIVATE_GROUP_ID_TYPE) 256 | .map(|v| v.encode_tagged_string()) 257 | } 258 | /// Lookup all of the `tunnel_private_group_id` tagged string value from a packet. 259 | pub fn lookup_all_tunnel_private_group_id( 260 | packet: &Packet, 261 | ) -> Result)>, AVPError> { 262 | let mut vec = Vec::new(); 263 | for avp in packet.lookup_all(TUNNEL_PRIVATE_GROUP_ID_TYPE) { 264 | vec.push(avp.encode_tagged_string()?) 265 | } 266 | Ok(vec) 267 | } 268 | 269 | pub const TUNNEL_ASSIGNMENT_ID_TYPE: AVPType = 82; 270 | /// Delete all of `tunnel_assignment_id` values from a packet. 271 | pub fn delete_tunnel_assignment_id(packet: &mut Packet) { 272 | packet.delete(TUNNEL_ASSIGNMENT_ID_TYPE); 273 | } 274 | /// Add `tunnel_assignment_id` tagged string value to a packet. 275 | pub fn add_tunnel_assignment_id(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 276 | packet.add(AVP::from_tagged_string( 277 | TUNNEL_ASSIGNMENT_ID_TYPE, 278 | tag, 279 | value, 280 | )); 281 | } 282 | /// Lookup a `tunnel_assignment_id` tagged string value from a packet. 283 | /// 284 | /// It returns the first looked up value. If there is no associated value with `tunnel_assignment_id`, it returns `None`. 285 | pub fn lookup_tunnel_assignment_id( 286 | packet: &Packet, 287 | ) -> Option), AVPError>> { 288 | packet 289 | .lookup(TUNNEL_ASSIGNMENT_ID_TYPE) 290 | .map(|v| v.encode_tagged_string()) 291 | } 292 | /// Lookup all of the `tunnel_assignment_id` tagged string value from a packet. 293 | pub fn lookup_all_tunnel_assignment_id( 294 | packet: &Packet, 295 | ) -> Result)>, AVPError> { 296 | let mut vec = Vec::new(); 297 | for avp in packet.lookup_all(TUNNEL_ASSIGNMENT_ID_TYPE) { 298 | vec.push(avp.encode_tagged_string()?) 299 | } 300 | Ok(vec) 301 | } 302 | 303 | pub const TUNNEL_PREFERENCE_TYPE: AVPType = 83; 304 | /// Delete all of `tunnel_preference` values from a packet. 305 | pub fn delete_tunnel_preference(packet: &mut Packet) { 306 | packet.delete(TUNNEL_PREFERENCE_TYPE); 307 | } 308 | /// Add `tunnel_preference` tagged integer value to a packet. 309 | pub fn add_tunnel_preference(packet: &mut Packet, tag: Option<&Tag>, value: u32) { 310 | packet.add(AVP::from_tagged_u32(TUNNEL_PREFERENCE_TYPE, tag, value)); 311 | } 312 | /// Lookup a `tunnel_preference` tagged integer value from a packet. 313 | /// 314 | /// It returns the first looked up value. If there is no associated value with `tunnel_preference`, it returns `None`. 315 | pub fn lookup_tunnel_preference(packet: &Packet) -> Option> { 316 | packet 317 | .lookup(TUNNEL_PREFERENCE_TYPE) 318 | .map(|v| v.encode_tagged_u32()) 319 | } 320 | /// Lookup all of the `tunnel_preference` tagged integer value from a packet. 321 | pub fn lookup_all_tunnel_preference(packet: &Packet) -> Result, AVPError> { 322 | let mut vec = Vec::new(); 323 | for avp in packet.lookup_all(TUNNEL_PREFERENCE_TYPE) { 324 | vec.push(avp.encode_tagged_u32()?) 325 | } 326 | Ok(vec) 327 | } 328 | 329 | pub const TUNNEL_CLIENT_AUTH_ID_TYPE: AVPType = 90; 330 | /// Delete all of `tunnel_client_auth_id` values from a packet. 331 | pub fn delete_tunnel_client_auth_id(packet: &mut Packet) { 332 | packet.delete(TUNNEL_CLIENT_AUTH_ID_TYPE); 333 | } 334 | /// Add `tunnel_client_auth_id` tagged string value to a packet. 335 | pub fn add_tunnel_client_auth_id(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 336 | packet.add(AVP::from_tagged_string( 337 | TUNNEL_CLIENT_AUTH_ID_TYPE, 338 | tag, 339 | value, 340 | )); 341 | } 342 | /// Lookup a `tunnel_client_auth_id` tagged string value from a packet. 343 | /// 344 | /// It returns the first looked up value. If there is no associated value with `tunnel_client_auth_id`, it returns `None`. 345 | pub fn lookup_tunnel_client_auth_id( 346 | packet: &Packet, 347 | ) -> Option), AVPError>> { 348 | packet 349 | .lookup(TUNNEL_CLIENT_AUTH_ID_TYPE) 350 | .map(|v| v.encode_tagged_string()) 351 | } 352 | /// Lookup all of the `tunnel_client_auth_id` tagged string value from a packet. 353 | pub fn lookup_all_tunnel_client_auth_id( 354 | packet: &Packet, 355 | ) -> Result)>, AVPError> { 356 | let mut vec = Vec::new(); 357 | for avp in packet.lookup_all(TUNNEL_CLIENT_AUTH_ID_TYPE) { 358 | vec.push(avp.encode_tagged_string()?) 359 | } 360 | Ok(vec) 361 | } 362 | 363 | pub const TUNNEL_SERVER_AUTH_ID_TYPE: AVPType = 91; 364 | /// Delete all of `tunnel_server_auth_id` values from a packet. 365 | pub fn delete_tunnel_server_auth_id(packet: &mut Packet) { 366 | packet.delete(TUNNEL_SERVER_AUTH_ID_TYPE); 367 | } 368 | /// Add `tunnel_server_auth_id` tagged string value to a packet. 369 | pub fn add_tunnel_server_auth_id(packet: &mut Packet, tag: Option<&Tag>, value: &str) { 370 | packet.add(AVP::from_tagged_string( 371 | TUNNEL_SERVER_AUTH_ID_TYPE, 372 | tag, 373 | value, 374 | )); 375 | } 376 | /// Lookup a `tunnel_server_auth_id` tagged string value from a packet. 377 | /// 378 | /// It returns the first looked up value. If there is no associated value with `tunnel_server_auth_id`, it returns `None`. 379 | pub fn lookup_tunnel_server_auth_id( 380 | packet: &Packet, 381 | ) -> Option), AVPError>> { 382 | packet 383 | .lookup(TUNNEL_SERVER_AUTH_ID_TYPE) 384 | .map(|v| v.encode_tagged_string()) 385 | } 386 | /// Lookup all of the `tunnel_server_auth_id` tagged string value from a packet. 387 | pub fn lookup_all_tunnel_server_auth_id( 388 | packet: &Packet, 389 | ) -> Result)>, AVPError> { 390 | let mut vec = Vec::new(); 391 | for avp in packet.lookup_all(TUNNEL_SERVER_AUTH_ID_TYPE) { 392 | vec.push(avp.encode_tagged_string()?) 393 | } 394 | Ok(vec) 395 | } 396 | 397 | pub type TunnelMediumType = u32; 398 | pub const TUNNEL_MEDIUM_TYPE_IP: TunnelMediumType = 1; 399 | pub const TUNNEL_MEDIUM_TYPE_I_PV_4: TunnelMediumType = 1; 400 | pub const TUNNEL_MEDIUM_TYPE_I_PV_6: TunnelMediumType = 2; 401 | pub const TUNNEL_MEDIUM_TYPE_NSAP: TunnelMediumType = 3; 402 | pub const TUNNEL_MEDIUM_TYPE_HDLC: TunnelMediumType = 4; 403 | pub const TUNNEL_MEDIUM_TYPE_BBN_1822: TunnelMediumType = 5; 404 | pub const TUNNEL_MEDIUM_TYPE_IEEE_802: TunnelMediumType = 6; 405 | pub const TUNNEL_MEDIUM_TYPE_E_163: TunnelMediumType = 7; 406 | pub const TUNNEL_MEDIUM_TYPE_E_164: TunnelMediumType = 8; 407 | pub const TUNNEL_MEDIUM_TYPE_F_69: TunnelMediumType = 9; 408 | pub const TUNNEL_MEDIUM_TYPE_X_121: TunnelMediumType = 10; 409 | pub const TUNNEL_MEDIUM_TYPE_IPX: TunnelMediumType = 11; 410 | pub const TUNNEL_MEDIUM_TYPE_APPLETALK: TunnelMediumType = 12; 411 | pub const TUNNEL_MEDIUM_TYPE_DEC_NET_IV: TunnelMediumType = 13; 412 | pub const TUNNEL_MEDIUM_TYPE_BANYAN_VINES: TunnelMediumType = 14; 413 | pub const TUNNEL_MEDIUM_TYPE_E_164_NSAP: TunnelMediumType = 15; 414 | 415 | pub type TunnelType = u32; 416 | pub const TUNNEL_TYPE_PPTP: TunnelType = 1; 417 | pub const TUNNEL_TYPE_L2F: TunnelType = 2; 418 | pub const TUNNEL_TYPE_L2TP: TunnelType = 3; 419 | pub const TUNNEL_TYPE_ATMP: TunnelType = 4; 420 | pub const TUNNEL_TYPE_VTP: TunnelType = 5; 421 | pub const TUNNEL_TYPE_AH: TunnelType = 6; 422 | pub const TUNNEL_TYPE_IP: TunnelType = 7; 423 | pub const TUNNEL_TYPE_MIN_IP: TunnelType = 8; 424 | pub const TUNNEL_TYPE_ESP: TunnelType = 9; 425 | pub const TUNNEL_TYPE_GRE: TunnelType = 10; 426 | pub const TUNNEL_TYPE_DVS: TunnelType = 11; 427 | pub const TUNNEL_TYPE_IP_IN_IP: TunnelType = 12; 428 | -------------------------------------------------------------------------------- /radius/src/core/rfc2869.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc2869 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 2869. 13 | //! # http://www.ietf.org/rfc/rfc2869.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Acct-Input-Gigawords 52 integer 18 | //! ATTRIBUTE Acct-Output-Gigawords 53 integer 19 | //! 20 | //! ATTRIBUTE Event-Timestamp 55 date 21 | //! 22 | //! ATTRIBUTE ARAP-Password 70 octets[16] 23 | //! ATTRIBUTE ARAP-Features 71 octets[14] 24 | //! ATTRIBUTE ARAP-Zone-Access 72 integer 25 | //! ATTRIBUTE ARAP-Security 73 integer 26 | //! ATTRIBUTE ARAP-Security-Data 74 string 27 | //! ATTRIBUTE Password-Retry 75 integer 28 | //! ATTRIBUTE Prompt 76 integer 29 | //! ATTRIBUTE Connect-Info 77 string 30 | //! ATTRIBUTE Configuration-Token 78 string 31 | //! ATTRIBUTE EAP-Message 79 octets concat 32 | //! ATTRIBUTE Message-Authenticator 80 octets 33 | //! 34 | //! ATTRIBUTE ARAP-Challenge-Response 84 octets[8] 35 | //! ATTRIBUTE Acct-Interim-Interval 85 integer 36 | //! # 86: RFC 2867 37 | //! ATTRIBUTE NAS-Port-Id 87 string 38 | //! ATTRIBUTE Framed-Pool 88 string 39 | //! 40 | //! # ARAP Zone Access 41 | //! 42 | //! VALUE ARAP-Zone-Access Default-Zone 1 43 | //! VALUE ARAP-Zone-Access Zone-Filter-Inclusive 2 44 | //! VALUE ARAP-Zone-Access Zone-Filter-Exclusive 4 45 | //! 46 | //! # Prompt 47 | //! VALUE Prompt No-Echo 0 48 | //! VALUE Prompt Echo 1 49 | //! ``` 50 | 51 | use chrono::{DateTime, Utc}; 52 | 53 | use crate::core::avp::{AVPError, AVPType, AVP}; 54 | use crate::core::packet::Packet; 55 | 56 | pub const ACCT_INPUT_GIGAWORDS_TYPE: AVPType = 52; 57 | /// Delete all of `acct_input_gigawords` values from a packet. 58 | pub fn delete_acct_input_gigawords(packet: &mut Packet) { 59 | packet.delete(ACCT_INPUT_GIGAWORDS_TYPE); 60 | } 61 | /// Add `acct_input_gigawords` integer value to a packet. 62 | pub fn add_acct_input_gigawords(packet: &mut Packet, value: u32) { 63 | packet.add(AVP::from_u32(ACCT_INPUT_GIGAWORDS_TYPE, value)); 64 | } 65 | /// Lookup a `acct_input_gigawords` integer value from a packet. 66 | /// 67 | /// It returns the first looked up value. If there is no associated value with `acct_input_gigawords`, it returns `None`. 68 | pub fn lookup_acct_input_gigawords(packet: &Packet) -> Option> { 69 | packet 70 | .lookup(ACCT_INPUT_GIGAWORDS_TYPE) 71 | .map(|v| v.encode_u32()) 72 | } 73 | /// Lookup all of the `acct_input_gigawords` integer value from a packet. 74 | pub fn lookup_all_acct_input_gigawords(packet: &Packet) -> Result, AVPError> { 75 | let mut vec = Vec::new(); 76 | for avp in packet.lookup_all(ACCT_INPUT_GIGAWORDS_TYPE) { 77 | vec.push(avp.encode_u32()?) 78 | } 79 | Ok(vec) 80 | } 81 | 82 | pub const ACCT_OUTPUT_GIGAWORDS_TYPE: AVPType = 53; 83 | /// Delete all of `acct_output_gigawords` values from a packet. 84 | pub fn delete_acct_output_gigawords(packet: &mut Packet) { 85 | packet.delete(ACCT_OUTPUT_GIGAWORDS_TYPE); 86 | } 87 | /// Add `acct_output_gigawords` integer value to a packet. 88 | pub fn add_acct_output_gigawords(packet: &mut Packet, value: u32) { 89 | packet.add(AVP::from_u32(ACCT_OUTPUT_GIGAWORDS_TYPE, value)); 90 | } 91 | /// Lookup a `acct_output_gigawords` integer value from a packet. 92 | /// 93 | /// It returns the first looked up value. If there is no associated value with `acct_output_gigawords`, it returns `None`. 94 | pub fn lookup_acct_output_gigawords(packet: &Packet) -> Option> { 95 | packet 96 | .lookup(ACCT_OUTPUT_GIGAWORDS_TYPE) 97 | .map(|v| v.encode_u32()) 98 | } 99 | /// Lookup all of the `acct_output_gigawords` integer value from a packet. 100 | pub fn lookup_all_acct_output_gigawords(packet: &Packet) -> Result, AVPError> { 101 | let mut vec = Vec::new(); 102 | for avp in packet.lookup_all(ACCT_OUTPUT_GIGAWORDS_TYPE) { 103 | vec.push(avp.encode_u32()?) 104 | } 105 | Ok(vec) 106 | } 107 | 108 | pub const EVENT_TIMESTAMP_TYPE: AVPType = 55; 109 | /// Delete all of `event_timestamp` values from a packet. 110 | pub fn delete_event_timestamp(packet: &mut Packet) { 111 | packet.delete(EVENT_TIMESTAMP_TYPE); 112 | } 113 | /// Add `event_timestamp` date value to a packet. 114 | pub fn add_event_timestamp(packet: &mut Packet, value: &DateTime) { 115 | packet.add(AVP::from_date(EVENT_TIMESTAMP_TYPE, value)); 116 | } 117 | /// Lookup a `event_timestamp` date value from a packet. 118 | /// 119 | /// It returns the first looked up value. If there is no associated value with `event_timestamp`, it returns `None`. 120 | pub fn lookup_event_timestamp(packet: &Packet) -> Option, AVPError>> { 121 | packet.lookup(EVENT_TIMESTAMP_TYPE).map(|v| v.encode_date()) 122 | } 123 | /// Lookup all of the `event_timestamp` date value from a packet. 124 | pub fn lookup_all_event_timestamp(packet: &Packet) -> Result>, AVPError> { 125 | let mut vec = Vec::new(); 126 | for avp in packet.lookup_all(EVENT_TIMESTAMP_TYPE) { 127 | vec.push(avp.encode_date()?) 128 | } 129 | Ok(vec) 130 | } 131 | 132 | pub const ARAP_PASSWORD_TYPE: AVPType = 70; 133 | /// Delete all of `arap_password` values from a packet. 134 | pub fn delete_arap_password(packet: &mut Packet) { 135 | packet.delete(ARAP_PASSWORD_TYPE); 136 | } 137 | /// Add `arap_password` fixed-length octets value to a packet. 138 | pub fn add_arap_password(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 139 | if value.len() != 16 { 140 | return Err(AVPError::InvalidAttributeLengthError( 141 | "16 bytes".to_owned(), 142 | value.len(), 143 | )); 144 | } 145 | packet.add(AVP::from_bytes(ARAP_PASSWORD_TYPE, value)); 146 | Ok(()) 147 | } 148 | /// Lookup a `arap_password` fixed-length octets value from a packet. 149 | /// 150 | /// It returns the first looked up value. If there is no associated value with `arap_password`, it returns `None`. 151 | pub fn lookup_arap_password(packet: &Packet) -> Option> { 152 | packet.lookup(ARAP_PASSWORD_TYPE).map(|v| v.encode_bytes()) 153 | } 154 | /// Lookup all of the `arap_password` fixed-length octets value from a packet. 155 | pub fn lookup_all_arap_password(packet: &Packet) -> Vec> { 156 | let mut vec = Vec::new(); 157 | for avp in packet.lookup_all(ARAP_PASSWORD_TYPE) { 158 | vec.push(avp.encode_bytes()) 159 | } 160 | vec 161 | } 162 | 163 | pub const ARAP_FEATURES_TYPE: AVPType = 71; 164 | /// Delete all of `arap_features` values from a packet. 165 | pub fn delete_arap_features(packet: &mut Packet) { 166 | packet.delete(ARAP_FEATURES_TYPE); 167 | } 168 | /// Add `arap_features` fixed-length octets value to a packet. 169 | pub fn add_arap_features(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 170 | if value.len() != 14 { 171 | return Err(AVPError::InvalidAttributeLengthError( 172 | "14 bytes".to_owned(), 173 | value.len(), 174 | )); 175 | } 176 | packet.add(AVP::from_bytes(ARAP_FEATURES_TYPE, value)); 177 | Ok(()) 178 | } 179 | /// Lookup a `arap_features` fixed-length octets value from a packet. 180 | /// 181 | /// It returns the first looked up value. If there is no associated value with `arap_features`, it returns `None`. 182 | pub fn lookup_arap_features(packet: &Packet) -> Option> { 183 | packet.lookup(ARAP_FEATURES_TYPE).map(|v| v.encode_bytes()) 184 | } 185 | /// Lookup all of the `arap_features` fixed-length octets value from a packet. 186 | pub fn lookup_all_arap_features(packet: &Packet) -> Vec> { 187 | let mut vec = Vec::new(); 188 | for avp in packet.lookup_all(ARAP_FEATURES_TYPE) { 189 | vec.push(avp.encode_bytes()) 190 | } 191 | vec 192 | } 193 | 194 | pub const ARAP_ZONE_ACCESS_TYPE: AVPType = 72; 195 | /// Delete all of `arap_zone_access` values from a packet. 196 | pub fn delete_arap_zone_access(packet: &mut Packet) { 197 | packet.delete(ARAP_ZONE_ACCESS_TYPE); 198 | } 199 | /// Add `arap_zone_access` value-defined integer value to a packet. 200 | pub fn add_arap_zone_access(packet: &mut Packet, value: ArapZoneAccess) { 201 | packet.add(AVP::from_u32(ARAP_ZONE_ACCESS_TYPE, value)); 202 | } 203 | /// Lookup a `arap_zone_access` value-defined integer value from a packet. 204 | /// 205 | /// It returns the first looked up value. If there is no associated value with `arap_zone_access`, it returns `None`. 206 | pub fn lookup_arap_zone_access(packet: &Packet) -> Option> { 207 | packet 208 | .lookup(ARAP_ZONE_ACCESS_TYPE) 209 | .map(|v| Ok(v.encode_u32()? as ArapZoneAccess)) 210 | } 211 | /// Lookup all of the `arap_zone_access` value-defined integer value from a packet. 212 | pub fn lookup_all_arap_zone_access(packet: &Packet) -> Result, AVPError> { 213 | let mut vec = Vec::new(); 214 | for avp in packet.lookup_all(ARAP_ZONE_ACCESS_TYPE) { 215 | vec.push(avp.encode_u32()? as ArapZoneAccess) 216 | } 217 | Ok(vec) 218 | } 219 | 220 | pub const ARAP_SECURITY_TYPE: AVPType = 73; 221 | /// Delete all of `arap_security` values from a packet. 222 | pub fn delete_arap_security(packet: &mut Packet) { 223 | packet.delete(ARAP_SECURITY_TYPE); 224 | } 225 | /// Add `arap_security` integer value to a packet. 226 | pub fn add_arap_security(packet: &mut Packet, value: u32) { 227 | packet.add(AVP::from_u32(ARAP_SECURITY_TYPE, value)); 228 | } 229 | /// Lookup a `arap_security` integer value from a packet. 230 | /// 231 | /// It returns the first looked up value. If there is no associated value with `arap_security`, it returns `None`. 232 | pub fn lookup_arap_security(packet: &Packet) -> Option> { 233 | packet.lookup(ARAP_SECURITY_TYPE).map(|v| v.encode_u32()) 234 | } 235 | /// Lookup all of the `arap_security` integer value from a packet. 236 | pub fn lookup_all_arap_security(packet: &Packet) -> Result, AVPError> { 237 | let mut vec = Vec::new(); 238 | for avp in packet.lookup_all(ARAP_SECURITY_TYPE) { 239 | vec.push(avp.encode_u32()?) 240 | } 241 | Ok(vec) 242 | } 243 | 244 | pub const ARAP_SECURITY_DATA_TYPE: AVPType = 74; 245 | /// Delete all of `arap_security_data` values from a packet. 246 | pub fn delete_arap_security_data(packet: &mut Packet) { 247 | packet.delete(ARAP_SECURITY_DATA_TYPE); 248 | } 249 | /// Add `arap_security_data` string value to a packet. 250 | pub fn add_arap_security_data(packet: &mut Packet, value: &str) { 251 | packet.add(AVP::from_string(ARAP_SECURITY_DATA_TYPE, value)); 252 | } 253 | /// Lookup a `arap_security_data` string value from a packet. 254 | /// 255 | /// It returns the first looked up value. If there is no associated value with `arap_security_data`, it returns `None`. 256 | pub fn lookup_arap_security_data(packet: &Packet) -> Option> { 257 | packet 258 | .lookup(ARAP_SECURITY_DATA_TYPE) 259 | .map(|v| v.encode_string()) 260 | } 261 | /// Lookup all of the `arap_security_data` string value from a packet. 262 | pub fn lookup_all_arap_security_data(packet: &Packet) -> Result, AVPError> { 263 | let mut vec = Vec::new(); 264 | for avp in packet.lookup_all(ARAP_SECURITY_DATA_TYPE) { 265 | vec.push(avp.encode_string()?) 266 | } 267 | Ok(vec) 268 | } 269 | 270 | pub const PASSWORD_RETRY_TYPE: AVPType = 75; 271 | /// Delete all of `password_retry` values from a packet. 272 | pub fn delete_password_retry(packet: &mut Packet) { 273 | packet.delete(PASSWORD_RETRY_TYPE); 274 | } 275 | /// Add `password_retry` integer value to a packet. 276 | pub fn add_password_retry(packet: &mut Packet, value: u32) { 277 | packet.add(AVP::from_u32(PASSWORD_RETRY_TYPE, value)); 278 | } 279 | /// Lookup a `password_retry` integer value from a packet. 280 | /// 281 | /// It returns the first looked up value. If there is no associated value with `password_retry`, it returns `None`. 282 | pub fn lookup_password_retry(packet: &Packet) -> Option> { 283 | packet.lookup(PASSWORD_RETRY_TYPE).map(|v| v.encode_u32()) 284 | } 285 | /// Lookup all of the `password_retry` integer value from a packet. 286 | pub fn lookup_all_password_retry(packet: &Packet) -> Result, AVPError> { 287 | let mut vec = Vec::new(); 288 | for avp in packet.lookup_all(PASSWORD_RETRY_TYPE) { 289 | vec.push(avp.encode_u32()?) 290 | } 291 | Ok(vec) 292 | } 293 | 294 | pub const PROMPT_TYPE: AVPType = 76; 295 | /// Delete all of `prompt` values from a packet. 296 | pub fn delete_prompt(packet: &mut Packet) { 297 | packet.delete(PROMPT_TYPE); 298 | } 299 | /// Add `prompt` value-defined integer value to a packet. 300 | pub fn add_prompt(packet: &mut Packet, value: Prompt) { 301 | packet.add(AVP::from_u32(PROMPT_TYPE, value)); 302 | } 303 | /// Lookup a `prompt` value-defined integer value from a packet. 304 | /// 305 | /// It returns the first looked up value. If there is no associated value with `prompt`, it returns `None`. 306 | pub fn lookup_prompt(packet: &Packet) -> Option> { 307 | packet 308 | .lookup(PROMPT_TYPE) 309 | .map(|v| Ok(v.encode_u32()? as Prompt)) 310 | } 311 | /// Lookup all of the `prompt` value-defined integer value from a packet. 312 | pub fn lookup_all_prompt(packet: &Packet) -> Result, AVPError> { 313 | let mut vec = Vec::new(); 314 | for avp in packet.lookup_all(PROMPT_TYPE) { 315 | vec.push(avp.encode_u32()? as Prompt) 316 | } 317 | Ok(vec) 318 | } 319 | 320 | pub const CONNECT_INFO_TYPE: AVPType = 77; 321 | /// Delete all of `connect_info` values from a packet. 322 | pub fn delete_connect_info(packet: &mut Packet) { 323 | packet.delete(CONNECT_INFO_TYPE); 324 | } 325 | /// Add `connect_info` string value to a packet. 326 | pub fn add_connect_info(packet: &mut Packet, value: &str) { 327 | packet.add(AVP::from_string(CONNECT_INFO_TYPE, value)); 328 | } 329 | /// Lookup a `connect_info` string value from a packet. 330 | /// 331 | /// It returns the first looked up value. If there is no associated value with `connect_info`, it returns `None`. 332 | pub fn lookup_connect_info(packet: &Packet) -> Option> { 333 | packet.lookup(CONNECT_INFO_TYPE).map(|v| v.encode_string()) 334 | } 335 | /// Lookup all of the `connect_info` string value from a packet. 336 | pub fn lookup_all_connect_info(packet: &Packet) -> Result, AVPError> { 337 | let mut vec = Vec::new(); 338 | for avp in packet.lookup_all(CONNECT_INFO_TYPE) { 339 | vec.push(avp.encode_string()?) 340 | } 341 | Ok(vec) 342 | } 343 | 344 | pub const CONFIGURATION_TOKEN_TYPE: AVPType = 78; 345 | /// Delete all of `configuration_token` values from a packet. 346 | pub fn delete_configuration_token(packet: &mut Packet) { 347 | packet.delete(CONFIGURATION_TOKEN_TYPE); 348 | } 349 | /// Add `configuration_token` string value to a packet. 350 | pub fn add_configuration_token(packet: &mut Packet, value: &str) { 351 | packet.add(AVP::from_string(CONFIGURATION_TOKEN_TYPE, value)); 352 | } 353 | /// Lookup a `configuration_token` string value from a packet. 354 | /// 355 | /// It returns the first looked up value. If there is no associated value with `configuration_token`, it returns `None`. 356 | pub fn lookup_configuration_token(packet: &Packet) -> Option> { 357 | packet 358 | .lookup(CONFIGURATION_TOKEN_TYPE) 359 | .map(|v| v.encode_string()) 360 | } 361 | /// Lookup all of the `configuration_token` string value from a packet. 362 | pub fn lookup_all_configuration_token(packet: &Packet) -> Result, AVPError> { 363 | let mut vec = Vec::new(); 364 | for avp in packet.lookup_all(CONFIGURATION_TOKEN_TYPE) { 365 | vec.push(avp.encode_string()?) 366 | } 367 | Ok(vec) 368 | } 369 | 370 | pub const EAP_MESSAGE_TYPE: AVPType = 79; 371 | /// Delete all of `eap_message` values from a packet. 372 | pub fn delete_eap_message(packet: &mut Packet) { 373 | packet.delete(EAP_MESSAGE_TYPE); 374 | } 375 | pub fn add_eap_message(packet: &mut Packet, value: &[u8]) { 376 | packet.extend( 377 | value 378 | .chunks(253) 379 | .map(|chunk| AVP::from_bytes(EAP_MESSAGE_TYPE, chunk)) 380 | .collect(), 381 | ); 382 | } 383 | pub fn lookup_eap_message(packet: &Packet) -> Option> { 384 | let avps = packet.lookup_all(EAP_MESSAGE_TYPE); 385 | match avps.is_empty() { 386 | true => None, 387 | false => Some(avps.into_iter().fold(Vec::new(), |mut acc, v| { 388 | acc.extend(v.encode_bytes()); 389 | acc 390 | })), 391 | } 392 | } 393 | 394 | pub const MESSAGE_AUTHENTICATOR_TYPE: AVPType = 80; 395 | /// Delete all of `message_authenticator` values from a packet. 396 | pub fn delete_message_authenticator(packet: &mut Packet) { 397 | packet.delete(MESSAGE_AUTHENTICATOR_TYPE); 398 | } 399 | /// Add `message_authenticator` octets value to a packet. 400 | pub fn add_message_authenticator(packet: &mut Packet, value: &[u8]) { 401 | packet.add(AVP::from_bytes(MESSAGE_AUTHENTICATOR_TYPE, value)); 402 | } 403 | /// Lookup a `message_authenticator` octets value from a packet. 404 | /// 405 | /// It returns the first looked up value. If there is no associated value with `message_authenticator`, it returns `None`. 406 | pub fn lookup_message_authenticator(packet: &Packet) -> Option> { 407 | packet 408 | .lookup(MESSAGE_AUTHENTICATOR_TYPE) 409 | .map(|v| v.encode_bytes()) 410 | } 411 | /// Lookup all of the `message_authenticator` octets value from a packet. 412 | pub fn lookup_all_message_authenticator(packet: &Packet) -> Vec> { 413 | let mut vec = Vec::new(); 414 | for avp in packet.lookup_all(MESSAGE_AUTHENTICATOR_TYPE) { 415 | vec.push(avp.encode_bytes()) 416 | } 417 | vec 418 | } 419 | 420 | pub const ARAP_CHALLENGE_RESPONSE_TYPE: AVPType = 84; 421 | /// Delete all of `arap_challenge_response` values from a packet. 422 | pub fn delete_arap_challenge_response(packet: &mut Packet) { 423 | packet.delete(ARAP_CHALLENGE_RESPONSE_TYPE); 424 | } 425 | /// Add `arap_challenge_response` fixed-length octets value to a packet. 426 | pub fn add_arap_challenge_response(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 427 | if value.len() != 8 { 428 | return Err(AVPError::InvalidAttributeLengthError( 429 | "8 bytes".to_owned(), 430 | value.len(), 431 | )); 432 | } 433 | packet.add(AVP::from_bytes(ARAP_CHALLENGE_RESPONSE_TYPE, value)); 434 | Ok(()) 435 | } 436 | /// Lookup a `arap_challenge_response` fixed-length octets value from a packet. 437 | /// 438 | /// It returns the first looked up value. If there is no associated value with `arap_challenge_response`, it returns `None`. 439 | pub fn lookup_arap_challenge_response(packet: &Packet) -> Option> { 440 | packet 441 | .lookup(ARAP_CHALLENGE_RESPONSE_TYPE) 442 | .map(|v| v.encode_bytes()) 443 | } 444 | /// Lookup all of the `arap_challenge_response` fixed-length octets value from a packet. 445 | pub fn lookup_all_arap_challenge_response(packet: &Packet) -> Vec> { 446 | let mut vec = Vec::new(); 447 | for avp in packet.lookup_all(ARAP_CHALLENGE_RESPONSE_TYPE) { 448 | vec.push(avp.encode_bytes()) 449 | } 450 | vec 451 | } 452 | 453 | pub const ACCT_INTERIM_INTERVAL_TYPE: AVPType = 85; 454 | /// Delete all of `acct_interim_interval` values from a packet. 455 | pub fn delete_acct_interim_interval(packet: &mut Packet) { 456 | packet.delete(ACCT_INTERIM_INTERVAL_TYPE); 457 | } 458 | /// Add `acct_interim_interval` integer value to a packet. 459 | pub fn add_acct_interim_interval(packet: &mut Packet, value: u32) { 460 | packet.add(AVP::from_u32(ACCT_INTERIM_INTERVAL_TYPE, value)); 461 | } 462 | /// Lookup a `acct_interim_interval` integer value from a packet. 463 | /// 464 | /// It returns the first looked up value. If there is no associated value with `acct_interim_interval`, it returns `None`. 465 | pub fn lookup_acct_interim_interval(packet: &Packet) -> Option> { 466 | packet 467 | .lookup(ACCT_INTERIM_INTERVAL_TYPE) 468 | .map(|v| v.encode_u32()) 469 | } 470 | /// Lookup all of the `acct_interim_interval` integer value from a packet. 471 | pub fn lookup_all_acct_interim_interval(packet: &Packet) -> Result, AVPError> { 472 | let mut vec = Vec::new(); 473 | for avp in packet.lookup_all(ACCT_INTERIM_INTERVAL_TYPE) { 474 | vec.push(avp.encode_u32()?) 475 | } 476 | Ok(vec) 477 | } 478 | 479 | pub const NAS_PORT_ID_TYPE: AVPType = 87; 480 | /// Delete all of `nas_port_id` values from a packet. 481 | pub fn delete_nas_port_id(packet: &mut Packet) { 482 | packet.delete(NAS_PORT_ID_TYPE); 483 | } 484 | /// Add `nas_port_id` string value to a packet. 485 | pub fn add_nas_port_id(packet: &mut Packet, value: &str) { 486 | packet.add(AVP::from_string(NAS_PORT_ID_TYPE, value)); 487 | } 488 | /// Lookup a `nas_port_id` string value from a packet. 489 | /// 490 | /// It returns the first looked up value. If there is no associated value with `nas_port_id`, it returns `None`. 491 | pub fn lookup_nas_port_id(packet: &Packet) -> Option> { 492 | packet.lookup(NAS_PORT_ID_TYPE).map(|v| v.encode_string()) 493 | } 494 | /// Lookup all of the `nas_port_id` string value from a packet. 495 | pub fn lookup_all_nas_port_id(packet: &Packet) -> Result, AVPError> { 496 | let mut vec = Vec::new(); 497 | for avp in packet.lookup_all(NAS_PORT_ID_TYPE) { 498 | vec.push(avp.encode_string()?) 499 | } 500 | Ok(vec) 501 | } 502 | 503 | pub const FRAMED_POOL_TYPE: AVPType = 88; 504 | /// Delete all of `framed_pool` values from a packet. 505 | pub fn delete_framed_pool(packet: &mut Packet) { 506 | packet.delete(FRAMED_POOL_TYPE); 507 | } 508 | /// Add `framed_pool` string value to a packet. 509 | pub fn add_framed_pool(packet: &mut Packet, value: &str) { 510 | packet.add(AVP::from_string(FRAMED_POOL_TYPE, value)); 511 | } 512 | /// Lookup a `framed_pool` string value from a packet. 513 | /// 514 | /// It returns the first looked up value. If there is no associated value with `framed_pool`, it returns `None`. 515 | pub fn lookup_framed_pool(packet: &Packet) -> Option> { 516 | packet.lookup(FRAMED_POOL_TYPE).map(|v| v.encode_string()) 517 | } 518 | /// Lookup all of the `framed_pool` string value from a packet. 519 | pub fn lookup_all_framed_pool(packet: &Packet) -> Result, AVPError> { 520 | let mut vec = Vec::new(); 521 | for avp in packet.lookup_all(FRAMED_POOL_TYPE) { 522 | vec.push(avp.encode_string()?) 523 | } 524 | Ok(vec) 525 | } 526 | 527 | pub type ArapZoneAccess = u32; 528 | pub const ARAP_ZONE_ACCESS_DEFAULT_ZONE: ArapZoneAccess = 1; 529 | pub const ARAP_ZONE_ACCESS_ZONE_FILTER_INCLUSIVE: ArapZoneAccess = 2; 530 | pub const ARAP_ZONE_ACCESS_ZONE_FILTER_EXCLUSIVE: ArapZoneAccess = 4; 531 | 532 | pub type Prompt = u32; 533 | pub const PROMPT_NO_ECHO: Prompt = 0; 534 | pub const PROMPT_ECHO: Prompt = 1; 535 | -------------------------------------------------------------------------------- /radius/src/core/rfc3162.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc3162 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 3162. 13 | //! # http://www.ietf.org/rfc/rfc3162.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE NAS-IPV6-Address 95 ipv6addr 18 | //! ATTRIBUTE Framed-Interface-Id 96 ifid 19 | //! ATTRIBUTE Framed-IPV6-Prefix 97 ipv6prefix 20 | //! ATTRIBUTE Login-IPV6-Host 98 ipv6addr 21 | //! ATTRIBUTE Framed-IPV6-Route 99 string 22 | //! ATTRIBUTE Framed-IPV6-Pool 100 string 23 | //! ``` 24 | 25 | use std::net::Ipv6Addr; 26 | 27 | use crate::core::avp::{AVPError, AVPType, AVP}; 28 | use crate::core::packet::Packet; 29 | 30 | pub const NAS_IPV6_ADDRESS_TYPE: AVPType = 95; 31 | /// Delete all of `nas_ipv6_address` values from a packet. 32 | pub fn delete_nas_ipv6_address(packet: &mut Packet) { 33 | packet.delete(NAS_IPV6_ADDRESS_TYPE); 34 | } 35 | /// Add `nas_ipv6_address` ipv6addr value to a packet. 36 | pub fn add_nas_ipv6_address(packet: &mut Packet, value: &Ipv6Addr) { 37 | packet.add(AVP::from_ipv6(NAS_IPV6_ADDRESS_TYPE, value)); 38 | } 39 | /// Lookup a `nas_ipv6_address` ipv6addr value from a packet. 40 | /// 41 | /// It returns the first looked up value. If there is no associated value with `nas_ipv6_address`, it returns `None`. 42 | pub fn lookup_nas_ipv6_address(packet: &Packet) -> Option> { 43 | packet 44 | .lookup(NAS_IPV6_ADDRESS_TYPE) 45 | .map(|v| v.encode_ipv6()) 46 | } 47 | /// Lookup all of the `nas_ipv6_address` ipv6addr value from a packet. 48 | pub fn lookup_all_nas_ipv6_address(packet: &Packet) -> Result, AVPError> { 49 | let mut vec = Vec::new(); 50 | for avp in packet.lookup_all(NAS_IPV6_ADDRESS_TYPE) { 51 | vec.push(avp.encode_ipv6()?) 52 | } 53 | Ok(vec) 54 | } 55 | 56 | pub const FRAMED_INTERFACE_ID_TYPE: AVPType = 96; 57 | /// Delete all of `framed_interface_id` values from a packet. 58 | pub fn delete_framed_interface_id(packet: &mut Packet) { 59 | packet.delete(FRAMED_INTERFACE_ID_TYPE); 60 | } 61 | /// Add `framed_interface_id` fixed-length octets value to a packet. 62 | pub fn add_framed_interface_id(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 63 | if value.len() != 8 { 64 | return Err(AVPError::InvalidAttributeLengthError( 65 | "8 bytes".to_owned(), 66 | value.len(), 67 | )); 68 | } 69 | packet.add(AVP::from_bytes(FRAMED_INTERFACE_ID_TYPE, value)); 70 | Ok(()) 71 | } 72 | /// Lookup a `framed_interface_id` fixed-length octets value from a packet. 73 | /// 74 | /// It returns the first looked up value. If there is no associated value with `framed_interface_id`, it returns `None`. 75 | pub fn lookup_framed_interface_id(packet: &Packet) -> Option> { 76 | packet 77 | .lookup(FRAMED_INTERFACE_ID_TYPE) 78 | .map(|v| v.encode_bytes()) 79 | } 80 | /// Lookup all of the `framed_interface_id` fixed-length octets value from a packet. 81 | pub fn lookup_all_framed_interface_id(packet: &Packet) -> Vec> { 82 | let mut vec = Vec::new(); 83 | for avp in packet.lookup_all(FRAMED_INTERFACE_ID_TYPE) { 84 | vec.push(avp.encode_bytes()) 85 | } 86 | vec 87 | } 88 | 89 | pub const FRAMED_IPV6_PREFIX_TYPE: AVPType = 97; 90 | /// Delete all of `framed_ipv6_prefix` values from a packet. 91 | pub fn delete_framed_ipv6_prefix(packet: &mut Packet) { 92 | packet.delete(FRAMED_IPV6_PREFIX_TYPE); 93 | } 94 | /// Add `framed_ipv6_prefix` ipv6 prefix value to a packet. 95 | pub fn add_framed_ipv6_prefix(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 96 | packet.add(AVP::from_ipv6_prefix(FRAMED_IPV6_PREFIX_TYPE, value)?); 97 | Ok(()) 98 | } 99 | /// Lookup a `framed_ipv6_prefix` ipv6 prefix value from a packet. 100 | /// 101 | /// It returns the first looked up value. If there is no associated value with `framed_ipv6_prefix`, it returns `None`. 102 | pub fn lookup_framed_ipv6_prefix(packet: &Packet) -> Option, AVPError>> { 103 | packet 104 | .lookup(FRAMED_IPV6_PREFIX_TYPE) 105 | .map(|v| v.encode_ipv6_prefix()) 106 | } 107 | /// Lookup all of the `framed_ipv6_prefix` ipv6 prefix value from a packet. 108 | pub fn lookup_all_framed_ipv6_prefix(packet: &Packet) -> Result>, AVPError> { 109 | let mut vec = Vec::new(); 110 | for avp in packet.lookup_all(FRAMED_IPV6_PREFIX_TYPE) { 111 | vec.push(avp.encode_ipv6_prefix()?) 112 | } 113 | Ok(vec) 114 | } 115 | 116 | pub const LOGIN_IPV6_HOST_TYPE: AVPType = 98; 117 | /// Delete all of `login_ipv6_host` values from a packet. 118 | pub fn delete_login_ipv6_host(packet: &mut Packet) { 119 | packet.delete(LOGIN_IPV6_HOST_TYPE); 120 | } 121 | /// Add `login_ipv6_host` ipv6addr value to a packet. 122 | pub fn add_login_ipv6_host(packet: &mut Packet, value: &Ipv6Addr) { 123 | packet.add(AVP::from_ipv6(LOGIN_IPV6_HOST_TYPE, value)); 124 | } 125 | /// Lookup a `login_ipv6_host` ipv6addr value from a packet. 126 | /// 127 | /// It returns the first looked up value. If there is no associated value with `login_ipv6_host`, it returns `None`. 128 | pub fn lookup_login_ipv6_host(packet: &Packet) -> Option> { 129 | packet.lookup(LOGIN_IPV6_HOST_TYPE).map(|v| v.encode_ipv6()) 130 | } 131 | /// Lookup all of the `login_ipv6_host` ipv6addr value from a packet. 132 | pub fn lookup_all_login_ipv6_host(packet: &Packet) -> Result, AVPError> { 133 | let mut vec = Vec::new(); 134 | for avp in packet.lookup_all(LOGIN_IPV6_HOST_TYPE) { 135 | vec.push(avp.encode_ipv6()?) 136 | } 137 | Ok(vec) 138 | } 139 | 140 | pub const FRAMED_IPV6_ROUTE_TYPE: AVPType = 99; 141 | /// Delete all of `framed_ipv6_route` values from a packet. 142 | pub fn delete_framed_ipv6_route(packet: &mut Packet) { 143 | packet.delete(FRAMED_IPV6_ROUTE_TYPE); 144 | } 145 | /// Add `framed_ipv6_route` string value to a packet. 146 | pub fn add_framed_ipv6_route(packet: &mut Packet, value: &str) { 147 | packet.add(AVP::from_string(FRAMED_IPV6_ROUTE_TYPE, value)); 148 | } 149 | /// Lookup a `framed_ipv6_route` string value from a packet. 150 | /// 151 | /// It returns the first looked up value. If there is no associated value with `framed_ipv6_route`, it returns `None`. 152 | pub fn lookup_framed_ipv6_route(packet: &Packet) -> Option> { 153 | packet 154 | .lookup(FRAMED_IPV6_ROUTE_TYPE) 155 | .map(|v| v.encode_string()) 156 | } 157 | /// Lookup all of the `framed_ipv6_route` string value from a packet. 158 | pub fn lookup_all_framed_ipv6_route(packet: &Packet) -> Result, AVPError> { 159 | let mut vec = Vec::new(); 160 | for avp in packet.lookup_all(FRAMED_IPV6_ROUTE_TYPE) { 161 | vec.push(avp.encode_string()?) 162 | } 163 | Ok(vec) 164 | } 165 | 166 | pub const FRAMED_IPV6_POOL_TYPE: AVPType = 100; 167 | /// Delete all of `framed_ipv6_pool` values from a packet. 168 | pub fn delete_framed_ipv6_pool(packet: &mut Packet) { 169 | packet.delete(FRAMED_IPV6_POOL_TYPE); 170 | } 171 | /// Add `framed_ipv6_pool` string value to a packet. 172 | pub fn add_framed_ipv6_pool(packet: &mut Packet, value: &str) { 173 | packet.add(AVP::from_string(FRAMED_IPV6_POOL_TYPE, value)); 174 | } 175 | /// Lookup a `framed_ipv6_pool` string value from a packet. 176 | /// 177 | /// It returns the first looked up value. If there is no associated value with `framed_ipv6_pool`, it returns `None`. 178 | pub fn lookup_framed_ipv6_pool(packet: &Packet) -> Option> { 179 | packet 180 | .lookup(FRAMED_IPV6_POOL_TYPE) 181 | .map(|v| v.encode_string()) 182 | } 183 | /// Lookup all of the `framed_ipv6_pool` string value from a packet. 184 | pub fn lookup_all_framed_ipv6_pool(packet: &Packet) -> Result, AVPError> { 185 | let mut vec = Vec::new(); 186 | for avp in packet.lookup_all(FRAMED_IPV6_POOL_TYPE) { 187 | vec.push(avp.encode_string()?) 188 | } 189 | Ok(vec) 190 | } 191 | -------------------------------------------------------------------------------- /radius/src/core/rfc3576.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc3576 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 3576. 13 | //! # http://www.ietf.org/rfc/rfc3576.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Error-Cause 101 integer 18 | //! 19 | //! # Service Types 20 | //! 21 | //! VALUE Service-Type Authorize-Only 17 22 | //! 23 | //! # Error causes 24 | //! 25 | //! VALUE Error-Cause Residual-Context-Removed 201 26 | //! VALUE Error-Cause Invalid-EAP-Packet 202 27 | //! VALUE Error-Cause Unsupported-Attribute 401 28 | //! VALUE Error-Cause Missing-Attribute 402 29 | //! VALUE Error-Cause NAS-Identification-Mismatch 403 30 | //! VALUE Error-Cause Invalid-Request 404 31 | //! VALUE Error-Cause Unsupported-Service 405 32 | //! VALUE Error-Cause Unsupported-Extension 406 33 | //! VALUE Error-Cause Administratively-Prohibited 501 34 | //! VALUE Error-Cause Proxy-Request-Not-Routable 502 35 | //! VALUE Error-Cause Session-Context-Not-Found 503 36 | //! VALUE Error-Cause Session-Context-Not-Removable 504 37 | //! VALUE Error-Cause Proxy-Processing-Error 505 38 | //! VALUE Error-Cause Resources-Unavailable 506 39 | //! VALUE Error-Cause Request-Initiated 507 40 | //! ``` 41 | 42 | use crate::core::avp::{AVPError, AVPType, AVP}; 43 | use crate::core::packet::Packet; 44 | 45 | use crate::core::rfc2865; 46 | 47 | pub const ERROR_CAUSE_TYPE: AVPType = 101; 48 | /// Delete all of `error_cause` values from a packet. 49 | pub fn delete_error_cause(packet: &mut Packet) { 50 | packet.delete(ERROR_CAUSE_TYPE); 51 | } 52 | /// Add `error_cause` value-defined integer value to a packet. 53 | pub fn add_error_cause(packet: &mut Packet, value: ErrorCause) { 54 | packet.add(AVP::from_u32(ERROR_CAUSE_TYPE, value)); 55 | } 56 | /// Lookup a `error_cause` value-defined integer value from a packet. 57 | /// 58 | /// It returns the first looked up value. If there is no associated value with `error_cause`, it returns `None`. 59 | pub fn lookup_error_cause(packet: &Packet) -> Option> { 60 | packet 61 | .lookup(ERROR_CAUSE_TYPE) 62 | .map(|v| Ok(v.encode_u32()? as ErrorCause)) 63 | } 64 | /// Lookup all of the `error_cause` value-defined integer value from a packet. 65 | pub fn lookup_all_error_cause(packet: &Packet) -> Result, AVPError> { 66 | let mut vec = Vec::new(); 67 | for avp in packet.lookup_all(ERROR_CAUSE_TYPE) { 68 | vec.push(avp.encode_u32()? as ErrorCause) 69 | } 70 | Ok(vec) 71 | } 72 | 73 | pub type ErrorCause = u32; 74 | pub const ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED: ErrorCause = 201; 75 | pub const ERROR_CAUSE_INVALID_EAP_PACKET: ErrorCause = 202; 76 | pub const ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE: ErrorCause = 401; 77 | pub const ERROR_CAUSE_MISSING_ATTRIBUTE: ErrorCause = 402; 78 | pub const ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH: ErrorCause = 403; 79 | pub const ERROR_CAUSE_INVALID_REQUEST: ErrorCause = 404; 80 | pub const ERROR_CAUSE_UNSUPPORTED_SERVICE: ErrorCause = 405; 81 | pub const ERROR_CAUSE_UNSUPPORTED_EXTENSION: ErrorCause = 406; 82 | pub const ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED: ErrorCause = 501; 83 | pub const ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE: ErrorCause = 502; 84 | pub const ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND: ErrorCause = 503; 85 | pub const ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE: ErrorCause = 504; 86 | pub const ERROR_CAUSE_PROXY_PROCESSING_ERROR: ErrorCause = 505; 87 | pub const ERROR_CAUSE_RESOURCES_UNAVAILABLE: ErrorCause = 506; 88 | pub const ERROR_CAUSE_REQUEST_INITIATED: ErrorCause = 507; 89 | 90 | pub const SERVICE_TYPE_AUTHORIZE_ONLY: rfc2865::ServiceType = 17; 91 | -------------------------------------------------------------------------------- /radius/src/core/rfc3580.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc3580 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 3580. 13 | //! # http://www.ietf.org/rfc/rfc3580.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! VALUE Acct-Terminate-Cause Supplicant-Restart 19 18 | //! VALUE Acct-Terminate-Cause Reauthentication-Failure 20 19 | //! VALUE Acct-Terminate-Cause Port-Reinit 21 20 | //! VALUE Acct-Terminate-Cause Port-Disabled 22 21 | //! 22 | //! VALUE NAS-Port-Type Token-Ring 20 23 | //! VALUE NAS-Port-Type FDDI 21 24 | //! 25 | //! VALUE Tunnel-Type VLAN 13 26 | //! ``` 27 | 28 | use crate::core::rfc2865; 29 | use crate::core::rfc2866; 30 | 31 | use crate::core::rfc2868; 32 | 33 | pub const ACCT_TERMINATE_CAUSE_SUPPLICANT_RESTART: rfc2866::AcctTerminateCause = 19; 34 | pub const ACCT_TERMINATE_CAUSE_REAUTHENTICATION_FAILURE: rfc2866::AcctTerminateCause = 20; 35 | pub const ACCT_TERMINATE_CAUSE_PORT_REINIT: rfc2866::AcctTerminateCause = 21; 36 | pub const ACCT_TERMINATE_CAUSE_PORT_DISABLED: rfc2866::AcctTerminateCause = 22; 37 | 38 | pub const NAS_PORT_TYPE_TOKEN_RING: rfc2865::NasPortType = 20; 39 | pub const NAS_PORT_TYPE_FDDI: rfc2865::NasPortType = 21; 40 | 41 | pub const TUNNEL_TYPE_VLAN: rfc2868::TunnelType = 13; 42 | -------------------------------------------------------------------------------- /radius/src/core/rfc4072.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4072 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 4072 13 | //! # http://www.ietf.org/rfc/rfc4072.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! 18 | //! ATTRIBUTE EAP-Key-Name 102 octets 19 | //! ``` 20 | 21 | use crate::core::avp::{AVPType, AVP}; 22 | use crate::core::packet::Packet; 23 | 24 | pub const EAP_KEY_NAME_TYPE: AVPType = 102; 25 | /// Delete all of `eap_key_name` values from a packet. 26 | pub fn delete_eap_key_name(packet: &mut Packet) { 27 | packet.delete(EAP_KEY_NAME_TYPE); 28 | } 29 | /// Add `eap_key_name` octets value to a packet. 30 | pub fn add_eap_key_name(packet: &mut Packet, value: &[u8]) { 31 | packet.add(AVP::from_bytes(EAP_KEY_NAME_TYPE, value)); 32 | } 33 | /// Lookup a `eap_key_name` octets value from a packet. 34 | /// 35 | /// It returns the first looked up value. If there is no associated value with `eap_key_name`, it returns `None`. 36 | pub fn lookup_eap_key_name(packet: &Packet) -> Option> { 37 | packet.lookup(EAP_KEY_NAME_TYPE).map(|v| v.encode_bytes()) 38 | } 39 | /// Lookup all of the `eap_key_name` octets value from a packet. 40 | pub fn lookup_all_eap_key_name(packet: &Packet) -> Vec> { 41 | let mut vec = Vec::new(); 42 | for avp in packet.lookup_all(EAP_KEY_NAME_TYPE) { 43 | vec.push(avp.encode_bytes()) 44 | } 45 | vec 46 | } 47 | -------------------------------------------------------------------------------- /radius/src/core/rfc4372.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4372 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 4372. 13 | //! # http://www.ietf.org/rfc/rfc4372.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE Chargeable-User-Identity 89 octets 18 | //! ``` 19 | 20 | use crate::core::avp::{AVPType, AVP}; 21 | use crate::core::packet::Packet; 22 | 23 | pub const CHARGEABLE_USER_IDENTITY_TYPE: AVPType = 89; 24 | /// Delete all of `chargeable_user_identity` values from a packet. 25 | pub fn delete_chargeable_user_identity(packet: &mut Packet) { 26 | packet.delete(CHARGEABLE_USER_IDENTITY_TYPE); 27 | } 28 | /// Add `chargeable_user_identity` octets value to a packet. 29 | pub fn add_chargeable_user_identity(packet: &mut Packet, value: &[u8]) { 30 | packet.add(AVP::from_bytes(CHARGEABLE_USER_IDENTITY_TYPE, value)); 31 | } 32 | /// Lookup a `chargeable_user_identity` octets value from a packet. 33 | /// 34 | /// It returns the first looked up value. If there is no associated value with `chargeable_user_identity`, it returns `None`. 35 | pub fn lookup_chargeable_user_identity(packet: &Packet) -> Option> { 36 | packet 37 | .lookup(CHARGEABLE_USER_IDENTITY_TYPE) 38 | .map(|v| v.encode_bytes()) 39 | } 40 | /// Lookup all of the `chargeable_user_identity` octets value from a packet. 41 | pub fn lookup_all_chargeable_user_identity(packet: &Packet) -> Vec> { 42 | let mut vec = Vec::new(); 43 | for avp in packet.lookup_all(CHARGEABLE_USER_IDENTITY_TYPE) { 44 | vec.push(avp.encode_bytes()) 45 | } 46 | vec 47 | } 48 | -------------------------------------------------------------------------------- /radius/src/core/rfc4603.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4603 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! ############################################################################## 12 | //! # 13 | //! # Attributes and values defined in RFC 4603. 14 | //! # http://www.ietf.org/rfc/rfc4603.txt 15 | //! # 16 | //! # $Id$ 17 | //! # 18 | //! ############################################################################## 19 | //! 20 | //! VALUE NAS-Port-Type PPPoA 30 21 | //! VALUE NAS-Port-Type PPPoEoA 31 22 | //! VALUE NAS-Port-Type PPPoEoE 32 23 | //! VALUE NAS-Port-Type PPPoEoVLAN 33 24 | //! VALUE NAS-Port-Type PPPoEoQinQ 34 25 | //! 26 | //! ``` 27 | 28 | use crate::core::rfc2865; 29 | 30 | pub const NAS_PORT_TYPE_PP_PO_A: rfc2865::NasPortType = 30; 31 | pub const NAS_PORT_TYPE_PP_PO_EO_A: rfc2865::NasPortType = 31; 32 | pub const NAS_PORT_TYPE_PP_PO_EO_E: rfc2865::NasPortType = 32; 33 | pub const NAS_PORT_TYPE_PP_PO_EO_VLAN: rfc2865::NasPortType = 33; 34 | pub const NAS_PORT_TYPE_PP_PO_EO_QIN_Q: rfc2865::NasPortType = 34; 35 | -------------------------------------------------------------------------------- /radius/src/core/rfc4675.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4675 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 4675. 13 | //! # http://www.ietf.org/rfc/rfc4675.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! 18 | //! # 19 | //! # High byte = '1' (0x31) means the frames are tagged. 20 | //! # High byte = '2' (0x32) means the frames are untagged. 21 | //! # 22 | //! # Next 12 bits MUST be zero. 23 | //! # 24 | //! # Lower 12 bits is the IEEE-802.1Q VLAN VID. 25 | //! # 26 | //! ATTRIBUTE Egress-VLANID 56 integer 27 | //! ATTRIBUTE Ingress-Filters 57 integer 28 | //! 29 | //! # 30 | //! # First byte == '1' (0x31) means that the frames are tagged. 31 | //! # First byte == '2' (0x32) means that the frames are untagged. 32 | //! # 33 | //! ATTRIBUTE Egress-VLAN-Name 58 string 34 | //! ATTRIBUTE User-Priority-Table 59 octets 35 | //! 36 | //! VALUE Ingress-Filters Enabled 1 37 | //! VALUE Ingress-Filters Disabled 2 38 | //! ``` 39 | 40 | use crate::core::avp::{AVPError, AVPType, AVP}; 41 | use crate::core::packet::Packet; 42 | 43 | pub const EGRESS_VLANID_TYPE: AVPType = 56; 44 | /// Delete all of `egress_vlanid` values from a packet. 45 | pub fn delete_egress_vlanid(packet: &mut Packet) { 46 | packet.delete(EGRESS_VLANID_TYPE); 47 | } 48 | /// Add `egress_vlanid` integer value to a packet. 49 | pub fn add_egress_vlanid(packet: &mut Packet, value: u32) { 50 | packet.add(AVP::from_u32(EGRESS_VLANID_TYPE, value)); 51 | } 52 | /// Lookup a `egress_vlanid` integer value from a packet. 53 | /// 54 | /// It returns the first looked up value. If there is no associated value with `egress_vlanid`, it returns `None`. 55 | pub fn lookup_egress_vlanid(packet: &Packet) -> Option> { 56 | packet.lookup(EGRESS_VLANID_TYPE).map(|v| v.encode_u32()) 57 | } 58 | /// Lookup all of the `egress_vlanid` integer value from a packet. 59 | pub fn lookup_all_egress_vlanid(packet: &Packet) -> Result, AVPError> { 60 | let mut vec = Vec::new(); 61 | for avp in packet.lookup_all(EGRESS_VLANID_TYPE) { 62 | vec.push(avp.encode_u32()?) 63 | } 64 | Ok(vec) 65 | } 66 | 67 | pub const INGRESS_FILTERS_TYPE: AVPType = 57; 68 | /// Delete all of `ingress_filters` values from a packet. 69 | pub fn delete_ingress_filters(packet: &mut Packet) { 70 | packet.delete(INGRESS_FILTERS_TYPE); 71 | } 72 | /// Add `ingress_filters` value-defined integer value to a packet. 73 | pub fn add_ingress_filters(packet: &mut Packet, value: IngressFilters) { 74 | packet.add(AVP::from_u32(INGRESS_FILTERS_TYPE, value)); 75 | } 76 | /// Lookup a `ingress_filters` value-defined integer value from a packet. 77 | /// 78 | /// It returns the first looked up value. If there is no associated value with `ingress_filters`, it returns `None`. 79 | pub fn lookup_ingress_filters(packet: &Packet) -> Option> { 80 | packet 81 | .lookup(INGRESS_FILTERS_TYPE) 82 | .map(|v| Ok(v.encode_u32()? as IngressFilters)) 83 | } 84 | /// Lookup all of the `ingress_filters` value-defined integer value from a packet. 85 | pub fn lookup_all_ingress_filters(packet: &Packet) -> Result, AVPError> { 86 | let mut vec = Vec::new(); 87 | for avp in packet.lookup_all(INGRESS_FILTERS_TYPE) { 88 | vec.push(avp.encode_u32()? as IngressFilters) 89 | } 90 | Ok(vec) 91 | } 92 | 93 | pub const EGRESS_VLAN_NAME_TYPE: AVPType = 58; 94 | /// Delete all of `egress_vlan_name` values from a packet. 95 | pub fn delete_egress_vlan_name(packet: &mut Packet) { 96 | packet.delete(EGRESS_VLAN_NAME_TYPE); 97 | } 98 | /// Add `egress_vlan_name` string value to a packet. 99 | pub fn add_egress_vlan_name(packet: &mut Packet, value: &str) { 100 | packet.add(AVP::from_string(EGRESS_VLAN_NAME_TYPE, value)); 101 | } 102 | /// Lookup a `egress_vlan_name` string value from a packet. 103 | /// 104 | /// It returns the first looked up value. If there is no associated value with `egress_vlan_name`, it returns `None`. 105 | pub fn lookup_egress_vlan_name(packet: &Packet) -> Option> { 106 | packet 107 | .lookup(EGRESS_VLAN_NAME_TYPE) 108 | .map(|v| v.encode_string()) 109 | } 110 | /// Lookup all of the `egress_vlan_name` string value from a packet. 111 | pub fn lookup_all_egress_vlan_name(packet: &Packet) -> Result, AVPError> { 112 | let mut vec = Vec::new(); 113 | for avp in packet.lookup_all(EGRESS_VLAN_NAME_TYPE) { 114 | vec.push(avp.encode_string()?) 115 | } 116 | Ok(vec) 117 | } 118 | 119 | pub const USER_PRIORITY_TABLE_TYPE: AVPType = 59; 120 | /// Delete all of `user_priority_table` values from a packet. 121 | pub fn delete_user_priority_table(packet: &mut Packet) { 122 | packet.delete(USER_PRIORITY_TABLE_TYPE); 123 | } 124 | /// Add `user_priority_table` octets value to a packet. 125 | pub fn add_user_priority_table(packet: &mut Packet, value: &[u8]) { 126 | packet.add(AVP::from_bytes(USER_PRIORITY_TABLE_TYPE, value)); 127 | } 128 | /// Lookup a `user_priority_table` octets value from a packet. 129 | /// 130 | /// It returns the first looked up value. If there is no associated value with `user_priority_table`, it returns `None`. 131 | pub fn lookup_user_priority_table(packet: &Packet) -> Option> { 132 | packet 133 | .lookup(USER_PRIORITY_TABLE_TYPE) 134 | .map(|v| v.encode_bytes()) 135 | } 136 | /// Lookup all of the `user_priority_table` octets value from a packet. 137 | pub fn lookup_all_user_priority_table(packet: &Packet) -> Vec> { 138 | let mut vec = Vec::new(); 139 | for avp in packet.lookup_all(USER_PRIORITY_TABLE_TYPE) { 140 | vec.push(avp.encode_bytes()) 141 | } 142 | vec 143 | } 144 | 145 | pub type IngressFilters = u32; 146 | pub const INGRESS_FILTERS_ENABLED: IngressFilters = 1; 147 | pub const INGRESS_FILTERS_DISABLED: IngressFilters = 2; 148 | -------------------------------------------------------------------------------- /radius/src/core/rfc4818.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4818 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! ############################################################################## 12 | //! # 13 | //! # Attributes and values defined in RFC 4818. 14 | //! # http://www.ietf.org/rfc/rfc4818.txt 15 | //! # 16 | //! # $Id$ 17 | //! # 18 | //! ############################################################################## 19 | //! 20 | //! ATTRIBUTE Delegated-IPV6-Prefix 123 ipv6prefix 21 | //! ``` 22 | 23 | use crate::core::avp::{AVPError, AVPType, AVP}; 24 | use crate::core::packet::Packet; 25 | 26 | pub const DELEGATED_IPV6_PREFIX_TYPE: AVPType = 123; 27 | /// Delete all of `delegated_ipv6_prefix` values from a packet. 28 | pub fn delete_delegated_ipv6_prefix(packet: &mut Packet) { 29 | packet.delete(DELEGATED_IPV6_PREFIX_TYPE); 30 | } 31 | /// Add `delegated_ipv6_prefix` ipv6 prefix value to a packet. 32 | pub fn add_delegated_ipv6_prefix(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 33 | packet.add(AVP::from_ipv6_prefix(DELEGATED_IPV6_PREFIX_TYPE, value)?); 34 | Ok(()) 35 | } 36 | /// Lookup a `delegated_ipv6_prefix` ipv6 prefix value from a packet. 37 | /// 38 | /// It returns the first looked up value. If there is no associated value with `delegated_ipv6_prefix`, it returns `None`. 39 | pub fn lookup_delegated_ipv6_prefix(packet: &Packet) -> Option, AVPError>> { 40 | packet 41 | .lookup(DELEGATED_IPV6_PREFIX_TYPE) 42 | .map(|v| v.encode_ipv6_prefix()) 43 | } 44 | /// Lookup all of the `delegated_ipv6_prefix` ipv6 prefix value from a packet. 45 | pub fn lookup_all_delegated_ipv6_prefix(packet: &Packet) -> Result>, AVPError> { 46 | let mut vec = Vec::new(); 47 | for avp in packet.lookup_all(DELEGATED_IPV6_PREFIX_TYPE) { 48 | vec.push(avp.encode_ipv6_prefix()?) 49 | } 50 | Ok(vec) 51 | } 52 | -------------------------------------------------------------------------------- /radius/src/core/rfc4849.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc4849 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 4849. 13 | //! # http://www.ietf.org/rfc/rfc4849.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! ATTRIBUTE NAS-Filter-Rule 92 string 18 | //! ``` 19 | 20 | use crate::core::avp::{AVPError, AVPType, AVP}; 21 | use crate::core::packet::Packet; 22 | 23 | pub const NAS_FILTER_RULE_TYPE: AVPType = 92; 24 | /// Delete all of `nas_filter_rule` values from a packet. 25 | pub fn delete_nas_filter_rule(packet: &mut Packet) { 26 | packet.delete(NAS_FILTER_RULE_TYPE); 27 | } 28 | /// Add `nas_filter_rule` string value to a packet. 29 | pub fn add_nas_filter_rule(packet: &mut Packet, value: &str) { 30 | packet.add(AVP::from_string(NAS_FILTER_RULE_TYPE, value)); 31 | } 32 | /// Lookup a `nas_filter_rule` string value from a packet. 33 | /// 34 | /// It returns the first looked up value. If there is no associated value with `nas_filter_rule`, it returns `None`. 35 | pub fn lookup_nas_filter_rule(packet: &Packet) -> Option> { 36 | packet 37 | .lookup(NAS_FILTER_RULE_TYPE) 38 | .map(|v| v.encode_string()) 39 | } 40 | /// Lookup all of the `nas_filter_rule` string value from a packet. 41 | pub fn lookup_all_nas_filter_rule(packet: &Packet) -> Result, AVPError> { 42 | let mut vec = Vec::new(); 43 | for avp in packet.lookup_all(NAS_FILTER_RULE_TYPE) { 44 | vec.push(avp.encode_string()?) 45 | } 46 | Ok(vec) 47 | } 48 | -------------------------------------------------------------------------------- /radius/src/core/rfc5176.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc5176 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 5176. 13 | //! # http://www.ietf.org/rfc/rfc5176.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! VALUE Error-Cause Invalid-Attribute-Value 407 18 | //! VALUE Error-Cause Multiple-Session-Selection-Unsupported 508 19 | //! ``` 20 | 21 | use crate::core::rfc3576; 22 | 23 | pub const ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE: rfc3576::ErrorCause = 407; 24 | pub const ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED: rfc3576::ErrorCause = 508; 25 | -------------------------------------------------------------------------------- /radius/src/core/rfc5607.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc5607 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 5607. 13 | //! # http://www.ietf.org/rfc/rfc5607.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! 18 | //! VALUE Service-Type Framed-Management 18 19 | //! 20 | //! ATTRIBUTE Framed-Management 133 integer 21 | //! 22 | //! VALUE Framed-Management SNMP 1 23 | //! VALUE Framed-Management Web-Based 2 24 | //! VALUE Framed-Management Netconf 3 25 | //! VALUE Framed-Management FTP 4 26 | //! VALUE Framed-Management TFTP 5 27 | //! VALUE Framed-Management SFTP 6 28 | //! VALUE Framed-Management RCP 7 29 | //! VALUE Framed-Management SCP 8 30 | //! 31 | //! ATTRIBUTE Management-Transport-Protection 134 integer 32 | //! 33 | //! VALUE Management-Transport-Protection No-Protection 1 34 | //! VALUE Management-Transport-Protection Integrity-Protection 2 35 | //! VALUE Management-Transport-Protection Integrity-Confidentiality-Protection 3 36 | //! 37 | //! ATTRIBUTE Management-Policy-Id 135 string 38 | //! 39 | //! ATTRIBUTE Management-Privilege-Level 136 integer 40 | //! ``` 41 | 42 | use crate::core::avp::{AVPError, AVPType, AVP}; 43 | use crate::core::packet::Packet; 44 | 45 | use crate::core::rfc2865; 46 | 47 | pub const FRAMED_MANAGEMENT_TYPE: AVPType = 133; 48 | /// Delete all of `framed_management` values from a packet. 49 | pub fn delete_framed_management(packet: &mut Packet) { 50 | packet.delete(FRAMED_MANAGEMENT_TYPE); 51 | } 52 | /// Add `framed_management` value-defined integer value to a packet. 53 | pub fn add_framed_management(packet: &mut Packet, value: FramedManagement) { 54 | packet.add(AVP::from_u32(FRAMED_MANAGEMENT_TYPE, value)); 55 | } 56 | /// Lookup a `framed_management` value-defined integer value from a packet. 57 | /// 58 | /// It returns the first looked up value. If there is no associated value with `framed_management`, it returns `None`. 59 | pub fn lookup_framed_management(packet: &Packet) -> Option> { 60 | packet 61 | .lookup(FRAMED_MANAGEMENT_TYPE) 62 | .map(|v| Ok(v.encode_u32()? as FramedManagement)) 63 | } 64 | /// Lookup all of the `framed_management` value-defined integer value from a packet. 65 | pub fn lookup_all_framed_management(packet: &Packet) -> Result, AVPError> { 66 | let mut vec = Vec::new(); 67 | for avp in packet.lookup_all(FRAMED_MANAGEMENT_TYPE) { 68 | vec.push(avp.encode_u32()? as FramedManagement) 69 | } 70 | Ok(vec) 71 | } 72 | 73 | pub const MANAGEMENT_TRANSPORT_PROTECTION_TYPE: AVPType = 134; 74 | /// Delete all of `management_transport_protection` values from a packet. 75 | pub fn delete_management_transport_protection(packet: &mut Packet) { 76 | packet.delete(MANAGEMENT_TRANSPORT_PROTECTION_TYPE); 77 | } 78 | /// Add `management_transport_protection` value-defined integer value to a packet. 79 | pub fn add_management_transport_protection( 80 | packet: &mut Packet, 81 | value: ManagementTransportProtection, 82 | ) { 83 | packet.add(AVP::from_u32(MANAGEMENT_TRANSPORT_PROTECTION_TYPE, value)); 84 | } 85 | /// Lookup a `management_transport_protection` value-defined integer value from a packet. 86 | /// 87 | /// It returns the first looked up value. If there is no associated value with `management_transport_protection`, it returns `None`. 88 | pub fn lookup_management_transport_protection( 89 | packet: &Packet, 90 | ) -> Option> { 91 | packet 92 | .lookup(MANAGEMENT_TRANSPORT_PROTECTION_TYPE) 93 | .map(|v| Ok(v.encode_u32()? as ManagementTransportProtection)) 94 | } 95 | /// Lookup all of the `management_transport_protection` value-defined integer value from a packet. 96 | pub fn lookup_all_management_transport_protection( 97 | packet: &Packet, 98 | ) -> Result, AVPError> { 99 | let mut vec = Vec::new(); 100 | for avp in packet.lookup_all(MANAGEMENT_TRANSPORT_PROTECTION_TYPE) { 101 | vec.push(avp.encode_u32()? as ManagementTransportProtection) 102 | } 103 | Ok(vec) 104 | } 105 | 106 | pub const MANAGEMENT_POLICY_ID_TYPE: AVPType = 135; 107 | /// Delete all of `management_policy_id` values from a packet. 108 | pub fn delete_management_policy_id(packet: &mut Packet) { 109 | packet.delete(MANAGEMENT_POLICY_ID_TYPE); 110 | } 111 | /// Add `management_policy_id` string value to a packet. 112 | pub fn add_management_policy_id(packet: &mut Packet, value: &str) { 113 | packet.add(AVP::from_string(MANAGEMENT_POLICY_ID_TYPE, value)); 114 | } 115 | /// Lookup a `management_policy_id` string value from a packet. 116 | /// 117 | /// It returns the first looked up value. If there is no associated value with `management_policy_id`, it returns `None`. 118 | pub fn lookup_management_policy_id(packet: &Packet) -> Option> { 119 | packet 120 | .lookup(MANAGEMENT_POLICY_ID_TYPE) 121 | .map(|v| v.encode_string()) 122 | } 123 | /// Lookup all of the `management_policy_id` string value from a packet. 124 | pub fn lookup_all_management_policy_id(packet: &Packet) -> Result, AVPError> { 125 | let mut vec = Vec::new(); 126 | for avp in packet.lookup_all(MANAGEMENT_POLICY_ID_TYPE) { 127 | vec.push(avp.encode_string()?) 128 | } 129 | Ok(vec) 130 | } 131 | 132 | pub const MANAGEMENT_PRIVILEGE_LEVEL_TYPE: AVPType = 136; 133 | /// Delete all of `management_privilege_level` values from a packet. 134 | pub fn delete_management_privilege_level(packet: &mut Packet) { 135 | packet.delete(MANAGEMENT_PRIVILEGE_LEVEL_TYPE); 136 | } 137 | /// Add `management_privilege_level` integer value to a packet. 138 | pub fn add_management_privilege_level(packet: &mut Packet, value: u32) { 139 | packet.add(AVP::from_u32(MANAGEMENT_PRIVILEGE_LEVEL_TYPE, value)); 140 | } 141 | /// Lookup a `management_privilege_level` integer value from a packet. 142 | /// 143 | /// It returns the first looked up value. If there is no associated value with `management_privilege_level`, it returns `None`. 144 | pub fn lookup_management_privilege_level(packet: &Packet) -> Option> { 145 | packet 146 | .lookup(MANAGEMENT_PRIVILEGE_LEVEL_TYPE) 147 | .map(|v| v.encode_u32()) 148 | } 149 | /// Lookup all of the `management_privilege_level` integer value from a packet. 150 | pub fn lookup_all_management_privilege_level(packet: &Packet) -> Result, AVPError> { 151 | let mut vec = Vec::new(); 152 | for avp in packet.lookup_all(MANAGEMENT_PRIVILEGE_LEVEL_TYPE) { 153 | vec.push(avp.encode_u32()?) 154 | } 155 | Ok(vec) 156 | } 157 | 158 | pub type FramedManagement = u32; 159 | pub const FRAMED_MANAGEMENT_SNMP: FramedManagement = 1; 160 | pub const FRAMED_MANAGEMENT_WEB_BASED: FramedManagement = 2; 161 | pub const FRAMED_MANAGEMENT_NETCONF: FramedManagement = 3; 162 | pub const FRAMED_MANAGEMENT_FTP: FramedManagement = 4; 163 | pub const FRAMED_MANAGEMENT_TFTP: FramedManagement = 5; 164 | pub const FRAMED_MANAGEMENT_SFTP: FramedManagement = 6; 165 | pub const FRAMED_MANAGEMENT_RCP: FramedManagement = 7; 166 | pub const FRAMED_MANAGEMENT_SCP: FramedManagement = 8; 167 | 168 | pub type ManagementTransportProtection = u32; 169 | pub const MANAGEMENT_TRANSPORT_PROTECTION_NO_PROTECTION: ManagementTransportProtection = 1; 170 | pub const MANAGEMENT_TRANSPORT_PROTECTION_INTEGRITY_PROTECTION: ManagementTransportProtection = 2; 171 | pub const MANAGEMENT_TRANSPORT_PROTECTION_INTEGRITY_CONFIDENTIALITY_PROTECTION: 172 | ManagementTransportProtection = 3; 173 | 174 | pub const SERVICE_TYPE_FRAMED_MANAGEMENT: rfc2865::ServiceType = 18; 175 | -------------------------------------------------------------------------------- /radius/src/core/rfc5904.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc5904 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 5904. 13 | //! # http://www.ietf.org/rfc/rfc5904.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! 18 | //! # The next two attributes are continued, like EAP-Message 19 | //! ATTRIBUTE PKM-SS-Cert 137 octets concat 20 | //! ATTRIBUTE PKM-CA-Cert 138 octets concat 21 | //! 22 | //! # 28 bytes of data, 7 integers 23 | //! ATTRIBUTE PKM-Config-Settings 139 octets 24 | //! ATTRIBUTE PKM-Cryptosuite-List 140 octets 25 | //! ATTRIBUTE PKM-SAID 141 short 26 | //! 27 | //! # 6 bytes of data: SAID, 1 byte of type, 3 of cryptosuite 28 | //! ATTRIBUTE PKM-SA-Descriptor 142 octets 29 | //! 30 | //! # 133 bytes of data: integer lifetime, 1 byte sequence, 128 bytes of key 31 | //! ATTRIBUTE PKM-Auth-Key 143 octets 32 | //! ``` 33 | 34 | use crate::core::avp::{AVPError, AVPType, AVP}; 35 | use crate::core::packet::Packet; 36 | 37 | pub const PKM_SS_CERT_TYPE: AVPType = 137; 38 | /// Delete all of `pkm_ss_cert` values from a packet. 39 | pub fn delete_pkm_ss_cert(packet: &mut Packet) { 40 | packet.delete(PKM_SS_CERT_TYPE); 41 | } 42 | pub fn add_pkm_ss_cert(packet: &mut Packet, value: &[u8]) { 43 | packet.extend( 44 | value 45 | .chunks(253) 46 | .map(|chunk| AVP::from_bytes(PKM_SS_CERT_TYPE, chunk)) 47 | .collect(), 48 | ); 49 | } 50 | pub fn lookup_pkm_ss_cert(packet: &Packet) -> Option> { 51 | let avps = packet.lookup_all(PKM_SS_CERT_TYPE); 52 | match avps.is_empty() { 53 | true => None, 54 | false => Some(avps.into_iter().fold(Vec::new(), |mut acc, v| { 55 | acc.extend(v.encode_bytes()); 56 | acc 57 | })), 58 | } 59 | } 60 | 61 | pub const PKM_CA_CERT_TYPE: AVPType = 138; 62 | /// Delete all of `pkm_ca_cert` values from a packet. 63 | pub fn delete_pkm_ca_cert(packet: &mut Packet) { 64 | packet.delete(PKM_CA_CERT_TYPE); 65 | } 66 | pub fn add_pkm_ca_cert(packet: &mut Packet, value: &[u8]) { 67 | packet.extend( 68 | value 69 | .chunks(253) 70 | .map(|chunk| AVP::from_bytes(PKM_CA_CERT_TYPE, chunk)) 71 | .collect(), 72 | ); 73 | } 74 | pub fn lookup_pkm_ca_cert(packet: &Packet) -> Option> { 75 | let avps = packet.lookup_all(PKM_CA_CERT_TYPE); 76 | match avps.is_empty() { 77 | true => None, 78 | false => Some(avps.into_iter().fold(Vec::new(), |mut acc, v| { 79 | acc.extend(v.encode_bytes()); 80 | acc 81 | })), 82 | } 83 | } 84 | 85 | pub const PKM_CONFIG_SETTINGS_TYPE: AVPType = 139; 86 | /// Delete all of `pkm_config_settings` values from a packet. 87 | pub fn delete_pkm_config_settings(packet: &mut Packet) { 88 | packet.delete(PKM_CONFIG_SETTINGS_TYPE); 89 | } 90 | /// Add `pkm_config_settings` octets value to a packet. 91 | pub fn add_pkm_config_settings(packet: &mut Packet, value: &[u8]) { 92 | packet.add(AVP::from_bytes(PKM_CONFIG_SETTINGS_TYPE, value)); 93 | } 94 | /// Lookup a `pkm_config_settings` octets value from a packet. 95 | /// 96 | /// It returns the first looked up value. If there is no associated value with `pkm_config_settings`, it returns `None`. 97 | pub fn lookup_pkm_config_settings(packet: &Packet) -> Option> { 98 | packet 99 | .lookup(PKM_CONFIG_SETTINGS_TYPE) 100 | .map(|v| v.encode_bytes()) 101 | } 102 | /// Lookup all of the `pkm_config_settings` octets value from a packet. 103 | pub fn lookup_all_pkm_config_settings(packet: &Packet) -> Vec> { 104 | let mut vec = Vec::new(); 105 | for avp in packet.lookup_all(PKM_CONFIG_SETTINGS_TYPE) { 106 | vec.push(avp.encode_bytes()) 107 | } 108 | vec 109 | } 110 | 111 | pub const PKM_CRYPTOSUITE_LIST_TYPE: AVPType = 140; 112 | /// Delete all of `pkm_cryptosuite_list` values from a packet. 113 | pub fn delete_pkm_cryptosuite_list(packet: &mut Packet) { 114 | packet.delete(PKM_CRYPTOSUITE_LIST_TYPE); 115 | } 116 | /// Add `pkm_cryptosuite_list` octets value to a packet. 117 | pub fn add_pkm_cryptosuite_list(packet: &mut Packet, value: &[u8]) { 118 | packet.add(AVP::from_bytes(PKM_CRYPTOSUITE_LIST_TYPE, value)); 119 | } 120 | /// Lookup a `pkm_cryptosuite_list` octets value from a packet. 121 | /// 122 | /// It returns the first looked up value. If there is no associated value with `pkm_cryptosuite_list`, it returns `None`. 123 | pub fn lookup_pkm_cryptosuite_list(packet: &Packet) -> Option> { 124 | packet 125 | .lookup(PKM_CRYPTOSUITE_LIST_TYPE) 126 | .map(|v| v.encode_bytes()) 127 | } 128 | /// Lookup all of the `pkm_cryptosuite_list` octets value from a packet. 129 | pub fn lookup_all_pkm_cryptosuite_list(packet: &Packet) -> Vec> { 130 | let mut vec = Vec::new(); 131 | for avp in packet.lookup_all(PKM_CRYPTOSUITE_LIST_TYPE) { 132 | vec.push(avp.encode_bytes()) 133 | } 134 | vec 135 | } 136 | 137 | pub const PKM_SAID_TYPE: AVPType = 141; 138 | /// Delete all of `pkm_said` values from a packet. 139 | pub fn delete_pkm_said(packet: &mut Packet) { 140 | packet.delete(PKM_SAID_TYPE); 141 | } 142 | /// Add `pkm_said` short integer value to a packet. 143 | pub fn add_pkm_said(packet: &mut Packet, value: u16) { 144 | packet.add(AVP::from_u16(PKM_SAID_TYPE, value)); 145 | } 146 | /// Lookup a `pkm_said` short integer value from a packet. 147 | /// 148 | /// It returns the first looked up value. If there is no associated value with `pkm_said`, it returns `None`. 149 | pub fn lookup_pkm_said(packet: &Packet) -> Option> { 150 | packet.lookup(PKM_SAID_TYPE).map(|v| v.encode_u16()) 151 | } 152 | /// Lookup all of the `pkm_said` short integer value from a packet. 153 | pub fn lookup_all_pkm_said(packet: &Packet) -> Result, AVPError> { 154 | let mut vec = Vec::new(); 155 | for avp in packet.lookup_all(PKM_SAID_TYPE) { 156 | vec.push(avp.encode_u16()?) 157 | } 158 | Ok(vec) 159 | } 160 | 161 | pub const PKM_SA_DESCRIPTOR_TYPE: AVPType = 142; 162 | /// Delete all of `pkm_sa_descriptor` values from a packet. 163 | pub fn delete_pkm_sa_descriptor(packet: &mut Packet) { 164 | packet.delete(PKM_SA_DESCRIPTOR_TYPE); 165 | } 166 | /// Add `pkm_sa_descriptor` octets value to a packet. 167 | pub fn add_pkm_sa_descriptor(packet: &mut Packet, value: &[u8]) { 168 | packet.add(AVP::from_bytes(PKM_SA_DESCRIPTOR_TYPE, value)); 169 | } 170 | /// Lookup a `pkm_sa_descriptor` octets value from a packet. 171 | /// 172 | /// It returns the first looked up value. If there is no associated value with `pkm_sa_descriptor`, it returns `None`. 173 | pub fn lookup_pkm_sa_descriptor(packet: &Packet) -> Option> { 174 | packet 175 | .lookup(PKM_SA_DESCRIPTOR_TYPE) 176 | .map(|v| v.encode_bytes()) 177 | } 178 | /// Lookup all of the `pkm_sa_descriptor` octets value from a packet. 179 | pub fn lookup_all_pkm_sa_descriptor(packet: &Packet) -> Vec> { 180 | let mut vec = Vec::new(); 181 | for avp in packet.lookup_all(PKM_SA_DESCRIPTOR_TYPE) { 182 | vec.push(avp.encode_bytes()) 183 | } 184 | vec 185 | } 186 | 187 | pub const PKM_AUTH_KEY_TYPE: AVPType = 143; 188 | /// Delete all of `pkm_auth_key` values from a packet. 189 | pub fn delete_pkm_auth_key(packet: &mut Packet) { 190 | packet.delete(PKM_AUTH_KEY_TYPE); 191 | } 192 | /// Add `pkm_auth_key` octets value to a packet. 193 | pub fn add_pkm_auth_key(packet: &mut Packet, value: &[u8]) { 194 | packet.add(AVP::from_bytes(PKM_AUTH_KEY_TYPE, value)); 195 | } 196 | /// Lookup a `pkm_auth_key` octets value from a packet. 197 | /// 198 | /// It returns the first looked up value. If there is no associated value with `pkm_auth_key`, it returns `None`. 199 | pub fn lookup_pkm_auth_key(packet: &Packet) -> Option> { 200 | packet.lookup(PKM_AUTH_KEY_TYPE).map(|v| v.encode_bytes()) 201 | } 202 | /// Lookup all of the `pkm_auth_key` octets value from a packet. 203 | pub fn lookup_all_pkm_auth_key(packet: &Packet) -> Vec> { 204 | let mut vec = Vec::new(); 205 | for avp in packet.lookup_all(PKM_AUTH_KEY_TYPE) { 206 | vec.push(avp.encode_bytes()) 207 | } 208 | vec 209 | } 210 | -------------------------------------------------------------------------------- /radius/src/core/rfc6519.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc6519 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 6519. 13 | //! # http://www.ietf.org/rfc/rfc6519.txt 14 | //! # 15 | //! # $Id$ 16 | //! # 17 | //! 18 | //! ATTRIBUTE DS-Lite-Tunnel-Name 144 string 19 | //! ``` 20 | 21 | use crate::core::avp::{AVPError, AVPType, AVP}; 22 | use crate::core::packet::Packet; 23 | 24 | pub const DS_LITE_TUNNEL_NAME_TYPE: AVPType = 144; 25 | /// Delete all of `ds_lite_tunnel_name` values from a packet. 26 | pub fn delete_ds_lite_tunnel_name(packet: &mut Packet) { 27 | packet.delete(DS_LITE_TUNNEL_NAME_TYPE); 28 | } 29 | /// Add `ds_lite_tunnel_name` string value to a packet. 30 | pub fn add_ds_lite_tunnel_name(packet: &mut Packet, value: &str) { 31 | packet.add(AVP::from_string(DS_LITE_TUNNEL_NAME_TYPE, value)); 32 | } 33 | /// Lookup a `ds_lite_tunnel_name` string value from a packet. 34 | /// 35 | /// It returns the first looked up value. If there is no associated value with `ds_lite_tunnel_name`, it returns `None`. 36 | pub fn lookup_ds_lite_tunnel_name(packet: &Packet) -> Option> { 37 | packet 38 | .lookup(DS_LITE_TUNNEL_NAME_TYPE) 39 | .map(|v| v.encode_string()) 40 | } 41 | /// Lookup all of the `ds_lite_tunnel_name` string value from a packet. 42 | pub fn lookup_all_ds_lite_tunnel_name(packet: &Packet) -> Result, AVPError> { 43 | let mut vec = Vec::new(); 44 | for avp in packet.lookup_all(DS_LITE_TUNNEL_NAME_TYPE) { 45 | vec.push(avp.encode_string()?) 46 | } 47 | Ok(vec) 48 | } 49 | -------------------------------------------------------------------------------- /radius/src/core/rfc6677.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc6677 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 6677 13 | //! # http://www.ietf.org/rfc/rfc6677.txt 14 | //! # 15 | //! 16 | //! ATTRIBUTE EAP-Lower-Layer 163 integer 17 | //! 18 | //! VALUE EAP-Lower-Layer Wired-IEEE-802.1X 1 19 | //! VALUE EAP-Lower-Layer IEEE-802.1X-No-Preauth 2 20 | //! VALUE EAP-Lower-Layer IEEE-802.1X-Preauth 3 21 | //! VALUE EAP-Lower-Layer IEEE-802.16e 4 22 | //! VALUE EAP-Lower-Layer IKEv2 5 23 | //! VALUE EAP-Lower-Layer PPP 6 24 | //! VALUE EAP-Lower-Layer PANA-No-Preauth 7 25 | //! VALUE EAP-Lower-Layer GSS-API 8 26 | //! VALUE EAP-Lower-Layer PANA-Preauth 9 27 | //! ``` 28 | 29 | use crate::core::avp::{AVPError, AVPType, AVP}; 30 | use crate::core::packet::Packet; 31 | 32 | pub const EAP_LOWER_LAYER_TYPE: AVPType = 163; 33 | /// Delete all of `eap_lower_layer` values from a packet. 34 | pub fn delete_eap_lower_layer(packet: &mut Packet) { 35 | packet.delete(EAP_LOWER_LAYER_TYPE); 36 | } 37 | /// Add `eap_lower_layer` value-defined integer value to a packet. 38 | pub fn add_eap_lower_layer(packet: &mut Packet, value: EapLowerLayer) { 39 | packet.add(AVP::from_u32(EAP_LOWER_LAYER_TYPE, value)); 40 | } 41 | /// Lookup a `eap_lower_layer` value-defined integer value from a packet. 42 | /// 43 | /// It returns the first looked up value. If there is no associated value with `eap_lower_layer`, it returns `None`. 44 | pub fn lookup_eap_lower_layer(packet: &Packet) -> Option> { 45 | packet 46 | .lookup(EAP_LOWER_LAYER_TYPE) 47 | .map(|v| Ok(v.encode_u32()? as EapLowerLayer)) 48 | } 49 | /// Lookup all of the `eap_lower_layer` value-defined integer value from a packet. 50 | pub fn lookup_all_eap_lower_layer(packet: &Packet) -> Result, AVPError> { 51 | let mut vec = Vec::new(); 52 | for avp in packet.lookup_all(EAP_LOWER_LAYER_TYPE) { 53 | vec.push(avp.encode_u32()? as EapLowerLayer) 54 | } 55 | Ok(vec) 56 | } 57 | 58 | pub type EapLowerLayer = u32; 59 | pub const EAP_LOWER_LAYER_WIRED_IEEE_802_1X: EapLowerLayer = 1; 60 | pub const EAP_LOWER_LAYER_IEEE_802_1X_NO_PREAUTH: EapLowerLayer = 2; 61 | pub const EAP_LOWER_LAYER_IEEE_802_1X_PREAUTH: EapLowerLayer = 3; 62 | pub const EAP_LOWER_LAYER_IEEE_802_1_6E: EapLowerLayer = 4; 63 | pub const EAP_LOWER_LAYER_IK_EV_2: EapLowerLayer = 5; 64 | pub const EAP_LOWER_LAYER_PPP: EapLowerLayer = 6; 65 | pub const EAP_LOWER_LAYER_PANA_NO_PREAUTH: EapLowerLayer = 7; 66 | pub const EAP_LOWER_LAYER_GSS_API: EapLowerLayer = 8; 67 | pub const EAP_LOWER_LAYER_PANA_PREAUTH: EapLowerLayer = 9; 68 | -------------------------------------------------------------------------------- /radius/src/core/rfc6911.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc6911 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 6911 13 | //! # http://www.ietf.org/rfc/rfc6911.txt 14 | //! # 15 | //! 16 | //! ATTRIBUTE Framed-IPV6-Address 168 ipv6addr 17 | //! ATTRIBUTE DNS-Server-IPV6-Address 169 ipv6addr 18 | //! ATTRIBUTE Route-IPV6-Information 170 ipv6prefix 19 | //! ATTRIBUTE Delegated-IPV6-Prefix-Pool 171 string 20 | //! ATTRIBUTE Stateful-IPV6-Address-Pool 172 string 21 | //! ``` 22 | 23 | use std::net::Ipv6Addr; 24 | 25 | use crate::core::avp::{AVPError, AVPType, AVP}; 26 | use crate::core::packet::Packet; 27 | 28 | pub const FRAMED_IPV6_ADDRESS_TYPE: AVPType = 168; 29 | /// Delete all of `framed_ipv6_address` values from a packet. 30 | pub fn delete_framed_ipv6_address(packet: &mut Packet) { 31 | packet.delete(FRAMED_IPV6_ADDRESS_TYPE); 32 | } 33 | /// Add `framed_ipv6_address` ipv6addr value to a packet. 34 | pub fn add_framed_ipv6_address(packet: &mut Packet, value: &Ipv6Addr) { 35 | packet.add(AVP::from_ipv6(FRAMED_IPV6_ADDRESS_TYPE, value)); 36 | } 37 | /// Lookup a `framed_ipv6_address` ipv6addr value from a packet. 38 | /// 39 | /// It returns the first looked up value. If there is no associated value with `framed_ipv6_address`, it returns `None`. 40 | pub fn lookup_framed_ipv6_address(packet: &Packet) -> Option> { 41 | packet 42 | .lookup(FRAMED_IPV6_ADDRESS_TYPE) 43 | .map(|v| v.encode_ipv6()) 44 | } 45 | /// Lookup all of the `framed_ipv6_address` ipv6addr value from a packet. 46 | pub fn lookup_all_framed_ipv6_address(packet: &Packet) -> Result, AVPError> { 47 | let mut vec = Vec::new(); 48 | for avp in packet.lookup_all(FRAMED_IPV6_ADDRESS_TYPE) { 49 | vec.push(avp.encode_ipv6()?) 50 | } 51 | Ok(vec) 52 | } 53 | 54 | pub const DNS_SERVER_IPV6_ADDRESS_TYPE: AVPType = 169; 55 | /// Delete all of `dns_server_ipv6_address` values from a packet. 56 | pub fn delete_dns_server_ipv6_address(packet: &mut Packet) { 57 | packet.delete(DNS_SERVER_IPV6_ADDRESS_TYPE); 58 | } 59 | /// Add `dns_server_ipv6_address` ipv6addr value to a packet. 60 | pub fn add_dns_server_ipv6_address(packet: &mut Packet, value: &Ipv6Addr) { 61 | packet.add(AVP::from_ipv6(DNS_SERVER_IPV6_ADDRESS_TYPE, value)); 62 | } 63 | /// Lookup a `dns_server_ipv6_address` ipv6addr value from a packet. 64 | /// 65 | /// It returns the first looked up value. If there is no associated value with `dns_server_ipv6_address`, it returns `None`. 66 | pub fn lookup_dns_server_ipv6_address(packet: &Packet) -> Option> { 67 | packet 68 | .lookup(DNS_SERVER_IPV6_ADDRESS_TYPE) 69 | .map(|v| v.encode_ipv6()) 70 | } 71 | /// Lookup all of the `dns_server_ipv6_address` ipv6addr value from a packet. 72 | pub fn lookup_all_dns_server_ipv6_address(packet: &Packet) -> Result, AVPError> { 73 | let mut vec = Vec::new(); 74 | for avp in packet.lookup_all(DNS_SERVER_IPV6_ADDRESS_TYPE) { 75 | vec.push(avp.encode_ipv6()?) 76 | } 77 | Ok(vec) 78 | } 79 | 80 | pub const ROUTE_IPV6_INFORMATION_TYPE: AVPType = 170; 81 | /// Delete all of `route_ipv6_information` values from a packet. 82 | pub fn delete_route_ipv6_information(packet: &mut Packet) { 83 | packet.delete(ROUTE_IPV6_INFORMATION_TYPE); 84 | } 85 | /// Add `route_ipv6_information` ipv6 prefix value to a packet. 86 | pub fn add_route_ipv6_information(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 87 | packet.add(AVP::from_ipv6_prefix(ROUTE_IPV6_INFORMATION_TYPE, value)?); 88 | Ok(()) 89 | } 90 | /// Lookup a `route_ipv6_information` ipv6 prefix value from a packet. 91 | /// 92 | /// It returns the first looked up value. If there is no associated value with `route_ipv6_information`, it returns `None`. 93 | pub fn lookup_route_ipv6_information(packet: &Packet) -> Option, AVPError>> { 94 | packet 95 | .lookup(ROUTE_IPV6_INFORMATION_TYPE) 96 | .map(|v| v.encode_ipv6_prefix()) 97 | } 98 | /// Lookup all of the `route_ipv6_information` ipv6 prefix value from a packet. 99 | pub fn lookup_all_route_ipv6_information(packet: &Packet) -> Result>, AVPError> { 100 | let mut vec = Vec::new(); 101 | for avp in packet.lookup_all(ROUTE_IPV6_INFORMATION_TYPE) { 102 | vec.push(avp.encode_ipv6_prefix()?) 103 | } 104 | Ok(vec) 105 | } 106 | 107 | pub const DELEGATED_IPV6_PREFIX_POOL_TYPE: AVPType = 171; 108 | /// Delete all of `delegated_ipv6_prefix_pool` values from a packet. 109 | pub fn delete_delegated_ipv6_prefix_pool(packet: &mut Packet) { 110 | packet.delete(DELEGATED_IPV6_PREFIX_POOL_TYPE); 111 | } 112 | /// Add `delegated_ipv6_prefix_pool` string value to a packet. 113 | pub fn add_delegated_ipv6_prefix_pool(packet: &mut Packet, value: &str) { 114 | packet.add(AVP::from_string(DELEGATED_IPV6_PREFIX_POOL_TYPE, value)); 115 | } 116 | /// Lookup a `delegated_ipv6_prefix_pool` string value from a packet. 117 | /// 118 | /// It returns the first looked up value. If there is no associated value with `delegated_ipv6_prefix_pool`, it returns `None`. 119 | pub fn lookup_delegated_ipv6_prefix_pool(packet: &Packet) -> Option> { 120 | packet 121 | .lookup(DELEGATED_IPV6_PREFIX_POOL_TYPE) 122 | .map(|v| v.encode_string()) 123 | } 124 | /// Lookup all of the `delegated_ipv6_prefix_pool` string value from a packet. 125 | pub fn lookup_all_delegated_ipv6_prefix_pool(packet: &Packet) -> Result, AVPError> { 126 | let mut vec = Vec::new(); 127 | for avp in packet.lookup_all(DELEGATED_IPV6_PREFIX_POOL_TYPE) { 128 | vec.push(avp.encode_string()?) 129 | } 130 | Ok(vec) 131 | } 132 | 133 | pub const STATEFUL_IPV6_ADDRESS_POOL_TYPE: AVPType = 172; 134 | /// Delete all of `stateful_ipv6_address_pool` values from a packet. 135 | pub fn delete_stateful_ipv6_address_pool(packet: &mut Packet) { 136 | packet.delete(STATEFUL_IPV6_ADDRESS_POOL_TYPE); 137 | } 138 | /// Add `stateful_ipv6_address_pool` string value to a packet. 139 | pub fn add_stateful_ipv6_address_pool(packet: &mut Packet, value: &str) { 140 | packet.add(AVP::from_string(STATEFUL_IPV6_ADDRESS_POOL_TYPE, value)); 141 | } 142 | /// Lookup a `stateful_ipv6_address_pool` string value from a packet. 143 | /// 144 | /// It returns the first looked up value. If there is no associated value with `stateful_ipv6_address_pool`, it returns `None`. 145 | pub fn lookup_stateful_ipv6_address_pool(packet: &Packet) -> Option> { 146 | packet 147 | .lookup(STATEFUL_IPV6_ADDRESS_POOL_TYPE) 148 | .map(|v| v.encode_string()) 149 | } 150 | /// Lookup all of the `stateful_ipv6_address_pool` string value from a packet. 151 | pub fn lookup_all_stateful_ipv6_address_pool(packet: &Packet) -> Result, AVPError> { 152 | let mut vec = Vec::new(); 153 | for avp in packet.lookup_all(STATEFUL_IPV6_ADDRESS_POOL_TYPE) { 154 | vec.push(avp.encode_string()?) 155 | } 156 | Ok(vec) 157 | } 158 | -------------------------------------------------------------------------------- /radius/src/core/rfc7055.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc7055 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 7055 13 | //! # http://www.ietf.org/rfc/rfc7055.txt 14 | //! # 15 | //! 16 | //! ATTRIBUTE GSS-Acceptor-Service-Name 164 string 17 | //! ATTRIBUTE GSS-Acceptor-Host-Name 165 string 18 | //! ATTRIBUTE GSS-Acceptor-Service-Specifics 166 string 19 | //! ATTRIBUTE GSS-Acceptor-Realm-Name 167 string 20 | //! ``` 21 | 22 | use crate::core::avp::{AVPError, AVPType, AVP}; 23 | use crate::core::packet::Packet; 24 | 25 | pub const GSS_ACCEPTOR_SERVICE_NAME_TYPE: AVPType = 164; 26 | /// Delete all of `gss_acceptor_service_name` values from a packet. 27 | pub fn delete_gss_acceptor_service_name(packet: &mut Packet) { 28 | packet.delete(GSS_ACCEPTOR_SERVICE_NAME_TYPE); 29 | } 30 | /// Add `gss_acceptor_service_name` string value to a packet. 31 | pub fn add_gss_acceptor_service_name(packet: &mut Packet, value: &str) { 32 | packet.add(AVP::from_string(GSS_ACCEPTOR_SERVICE_NAME_TYPE, value)); 33 | } 34 | /// Lookup a `gss_acceptor_service_name` string value from a packet. 35 | /// 36 | /// It returns the first looked up value. If there is no associated value with `gss_acceptor_service_name`, it returns `None`. 37 | pub fn lookup_gss_acceptor_service_name(packet: &Packet) -> Option> { 38 | packet 39 | .lookup(GSS_ACCEPTOR_SERVICE_NAME_TYPE) 40 | .map(|v| v.encode_string()) 41 | } 42 | /// Lookup all of the `gss_acceptor_service_name` string value from a packet. 43 | pub fn lookup_all_gss_acceptor_service_name(packet: &Packet) -> Result, AVPError> { 44 | let mut vec = Vec::new(); 45 | for avp in packet.lookup_all(GSS_ACCEPTOR_SERVICE_NAME_TYPE) { 46 | vec.push(avp.encode_string()?) 47 | } 48 | Ok(vec) 49 | } 50 | 51 | pub const GSS_ACCEPTOR_HOST_NAME_TYPE: AVPType = 165; 52 | /// Delete all of `gss_acceptor_host_name` values from a packet. 53 | pub fn delete_gss_acceptor_host_name(packet: &mut Packet) { 54 | packet.delete(GSS_ACCEPTOR_HOST_NAME_TYPE); 55 | } 56 | /// Add `gss_acceptor_host_name` string value to a packet. 57 | pub fn add_gss_acceptor_host_name(packet: &mut Packet, value: &str) { 58 | packet.add(AVP::from_string(GSS_ACCEPTOR_HOST_NAME_TYPE, value)); 59 | } 60 | /// Lookup a `gss_acceptor_host_name` string value from a packet. 61 | /// 62 | /// It returns the first looked up value. If there is no associated value with `gss_acceptor_host_name`, it returns `None`. 63 | pub fn lookup_gss_acceptor_host_name(packet: &Packet) -> Option> { 64 | packet 65 | .lookup(GSS_ACCEPTOR_HOST_NAME_TYPE) 66 | .map(|v| v.encode_string()) 67 | } 68 | /// Lookup all of the `gss_acceptor_host_name` string value from a packet. 69 | pub fn lookup_all_gss_acceptor_host_name(packet: &Packet) -> Result, AVPError> { 70 | let mut vec = Vec::new(); 71 | for avp in packet.lookup_all(GSS_ACCEPTOR_HOST_NAME_TYPE) { 72 | vec.push(avp.encode_string()?) 73 | } 74 | Ok(vec) 75 | } 76 | 77 | pub const GSS_ACCEPTOR_SERVICE_SPECIFICS_TYPE: AVPType = 166; 78 | /// Delete all of `gss_acceptor_service_specifics` values from a packet. 79 | pub fn delete_gss_acceptor_service_specifics(packet: &mut Packet) { 80 | packet.delete(GSS_ACCEPTOR_SERVICE_SPECIFICS_TYPE); 81 | } 82 | /// Add `gss_acceptor_service_specifics` string value to a packet. 83 | pub fn add_gss_acceptor_service_specifics(packet: &mut Packet, value: &str) { 84 | packet.add(AVP::from_string(GSS_ACCEPTOR_SERVICE_SPECIFICS_TYPE, value)); 85 | } 86 | /// Lookup a `gss_acceptor_service_specifics` string value from a packet. 87 | /// 88 | /// It returns the first looked up value. If there is no associated value with `gss_acceptor_service_specifics`, it returns `None`. 89 | pub fn lookup_gss_acceptor_service_specifics(packet: &Packet) -> Option> { 90 | packet 91 | .lookup(GSS_ACCEPTOR_SERVICE_SPECIFICS_TYPE) 92 | .map(|v| v.encode_string()) 93 | } 94 | /// Lookup all of the `gss_acceptor_service_specifics` string value from a packet. 95 | pub fn lookup_all_gss_acceptor_service_specifics(packet: &Packet) -> Result, AVPError> { 96 | let mut vec = Vec::new(); 97 | for avp in packet.lookup_all(GSS_ACCEPTOR_SERVICE_SPECIFICS_TYPE) { 98 | vec.push(avp.encode_string()?) 99 | } 100 | Ok(vec) 101 | } 102 | 103 | pub const GSS_ACCEPTOR_REALM_NAME_TYPE: AVPType = 167; 104 | /// Delete all of `gss_acceptor_realm_name` values from a packet. 105 | pub fn delete_gss_acceptor_realm_name(packet: &mut Packet) { 106 | packet.delete(GSS_ACCEPTOR_REALM_NAME_TYPE); 107 | } 108 | /// Add `gss_acceptor_realm_name` string value to a packet. 109 | pub fn add_gss_acceptor_realm_name(packet: &mut Packet, value: &str) { 110 | packet.add(AVP::from_string(GSS_ACCEPTOR_REALM_NAME_TYPE, value)); 111 | } 112 | /// Lookup a `gss_acceptor_realm_name` string value from a packet. 113 | /// 114 | /// It returns the first looked up value. If there is no associated value with `gss_acceptor_realm_name`, it returns `None`. 115 | pub fn lookup_gss_acceptor_realm_name(packet: &Packet) -> Option> { 116 | packet 117 | .lookup(GSS_ACCEPTOR_REALM_NAME_TYPE) 118 | .map(|v| v.encode_string()) 119 | } 120 | /// Lookup all of the `gss_acceptor_realm_name` string value from a packet. 121 | pub fn lookup_all_gss_acceptor_realm_name(packet: &Packet) -> Result, AVPError> { 122 | let mut vec = Vec::new(); 123 | for avp in packet.lookup_all(GSS_ACCEPTOR_REALM_NAME_TYPE) { 124 | vec.push(avp.encode_string()?) 125 | } 126 | Ok(vec) 127 | } 128 | -------------------------------------------------------------------------------- /radius/src/core/rfc7155.rs: -------------------------------------------------------------------------------- 1 | // Code generated by machine generator; DO NOT EDIT. 2 | 3 | //! Utility for rfc7155 packet. 4 | //! 5 | //! This module handles the packet according to the following definition: 6 | //! ```text 7 | //! //! # -*- text -*- 8 | //! # Copyright (C) 2020 The FreeRADIUS Server project and contributors 9 | //! # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 10 | //! # Version $Id$ 11 | //! # 12 | //! # Attributes and values defined in RFC 7155 13 | //! # http://www.ietf.org/rfc/rfc7155.txt 14 | //! # 15 | //! 16 | //! # The Value field contains two octets (00 - 99). ANSI T1.113 and 17 | //! # BELLCORE 394 can be used for additional information about these 18 | //! # values and their use. 19 | //! ATTRIBUTE Originating-Line-Info 94 octets[2] 20 | //! ``` 21 | 22 | use crate::core::avp::{AVPError, AVPType, AVP}; 23 | use crate::core::packet::Packet; 24 | 25 | pub const ORIGINATING_LINE_INFO_TYPE: AVPType = 94; 26 | /// Delete all of `originating_line_info` values from a packet. 27 | pub fn delete_originating_line_info(packet: &mut Packet) { 28 | packet.delete(ORIGINATING_LINE_INFO_TYPE); 29 | } 30 | /// Add `originating_line_info` fixed-length octets value to a packet. 31 | pub fn add_originating_line_info(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> { 32 | if value.len() != 2 { 33 | return Err(AVPError::InvalidAttributeLengthError( 34 | "2 bytes".to_owned(), 35 | value.len(), 36 | )); 37 | } 38 | packet.add(AVP::from_bytes(ORIGINATING_LINE_INFO_TYPE, value)); 39 | Ok(()) 40 | } 41 | /// Lookup a `originating_line_info` fixed-length octets value from a packet. 42 | /// 43 | /// It returns the first looked up value. If there is no associated value with `originating_line_info`, it returns `None`. 44 | pub fn lookup_originating_line_info(packet: &Packet) -> Option> { 45 | packet 46 | .lookup(ORIGINATING_LINE_INFO_TYPE) 47 | .map(|v| v.encode_bytes()) 48 | } 49 | /// Lookup all of the `originating_line_info` fixed-length octets value from a packet. 50 | pub fn lookup_all_originating_line_info(packet: &Packet) -> Vec> { 51 | let mut vec = Vec::new(); 52 | for avp in packet.lookup_all(ORIGINATING_LINE_INFO_TYPE) { 53 | vec.push(avp.encode_bytes()) 54 | } 55 | vec 56 | } 57 | -------------------------------------------------------------------------------- /radius/src/core/tag.rs: -------------------------------------------------------------------------------- 1 | pub(crate) const UNUSED_TAG_VALUE: u8 = 0x00; 2 | 3 | /// Tag represents a tag of a RADIUS value. 4 | /// see also: http://www.ietf.org/rfc/rfc2868.html 5 | #[derive(Debug, PartialEq)] 6 | pub struct Tag { 7 | pub(crate) value: u8, 8 | } 9 | 10 | impl Tag { 11 | pub fn new(value: u8) -> Self { 12 | Tag { value } 13 | } 14 | 15 | pub fn new_unused() -> Self { 16 | Tag { 17 | value: UNUSED_TAG_VALUE, 18 | } 19 | } 20 | 21 | pub fn get_value(&self) -> u8 { 22 | self.value 23 | } 24 | 25 | pub fn is_zero(&self) -> bool { 26 | self.value == UNUSED_TAG_VALUE 27 | } 28 | 29 | pub fn is_valid_value(&self) -> bool { 30 | 1 <= self.value && self.value <= 0x1f 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use crate::core::tag::Tag; 37 | 38 | #[test] 39 | fn test_is_zero() { 40 | let tag = Tag { value: 0 }; 41 | assert_eq!(tag.is_zero(), true); 42 | let tag = Tag { value: 1 }; 43 | assert_eq!(tag.is_zero(), false); 44 | } 45 | 46 | #[test] 47 | fn test_is_valid_value() { 48 | let tag = Tag { value: 1 }; 49 | assert_eq!(tag.is_valid_value(), true); 50 | let tag = Tag { value: 0 }; 51 | assert_eq!(tag.is_valid_value(), false); 52 | let tag = Tag { value: 0x20 }; 53 | assert_eq!(tag.is_valid_value(), false); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /radius/src/core/vsa.rs: -------------------------------------------------------------------------------- 1 | /// VSA trait represents the general vendor-specific struct related methods. 2 | pub trait VSA { 3 | /// len returns the length of sub-attribute of vendor-specific. 4 | /// 5 | /// Ref: RFC 4679 - https://datatracker.ietf.org/doc/html/rfc4679 6 | /// > Vendor-Length 7 | /// > 8 | /// > The Vendor-Length field is one octet and indicates the length of 9 | /// > the entire sub-attribute, including the Vendor-Type, 10 | /// > Vendor-Length, and Value fields. 11 | fn len(&self) -> usize; 12 | /// is_empty returns whether the VSA is empty or not. 13 | fn is_empty(&self) -> bool; 14 | /// message returns the serialized vendor-specific message for AVP. 15 | fn message(&self) -> Vec; 16 | } 17 | 18 | /// StringVSA represents the VSA according to the RFC 2865. 19 | #[derive(Debug, Clone, PartialEq)] 20 | pub struct StringVSA { 21 | vendor_id: Vec, 22 | vendor_type: u8, 23 | length: u8, 24 | value: Vec, 25 | } 26 | 27 | impl StringVSA { 28 | const BYTE_SIZE_OFFSET: usize = 2; 29 | 30 | pub fn new(vendor_id: i32, vendor_type: u8, value: &str) -> StringVSA { 31 | StringVSA { 32 | vendor_id: vendor_id.to_be_bytes().to_vec(), 33 | vendor_type, 34 | /* 35 | * Ref: RFC 4679 - https://datatracker.ietf.org/doc/html/rfc4679 36 | * > Vendor-Length 37 | * > 38 | * > The Vendor-Length field is one octet and indicates the length of 39 | * > the entire sub-attribute, including the Vendor-Type, 40 | * > Vendor-Length, and Value fields. 41 | */ 42 | length: (Self::BYTE_SIZE_OFFSET + value.len()) as u8, 43 | value: value.as_bytes().to_vec(), 44 | } 45 | } 46 | } 47 | 48 | impl VSA for StringVSA { 49 | fn len(&self) -> usize { 50 | self.length as usize 51 | } 52 | 53 | fn is_empty(&self) -> bool { 54 | self.length == 0 55 | } 56 | 57 | /// message returns the serialized vendor-specific message for AVP. 58 | /// 59 | /// Format: 60 | /// 0 1 2 3 61 | /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 62 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 63 | /// | Type | Length | Vendor-Id 64 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 65 | /// Vendor-Id (cont) | Vendor type | Vendor length | 66 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 67 | /// | Attribute-Specific... 68 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 69 | /// 70 | /// See also: RFC 2865 - https://datatracker.ietf.org/doc/html/rfc2865 71 | fn message(&self) -> Vec { 72 | let total_length: usize = Self::BYTE_SIZE_OFFSET + self.vendor_id.len() + self.value.len(); 73 | let mut result = Vec::with_capacity(total_length); 74 | 75 | result.extend(&self.vendor_id); 76 | result.extend(vec![self.vendor_type, self.length]); 77 | result.extend(&self.value); 78 | 79 | result 80 | } 81 | } 82 | 83 | /// TaggedStringVSA represents the VSA which has a tag value. 84 | #[derive(Debug, Clone, PartialEq)] 85 | pub struct TaggedStringVSA { 86 | vendor_id: Vec, 87 | vendor_type: u8, 88 | length: u8, 89 | tag: u8, 90 | value: Vec, 91 | } 92 | 93 | impl TaggedStringVSA { 94 | const BYTE_SIZE_OFFSET: usize = 3; 95 | 96 | pub fn new(vendor_id: i32, vendor_type: u8, tag: u8, value: &str) -> TaggedStringVSA { 97 | TaggedStringVSA { 98 | vendor_id: vendor_id.to_be_bytes().to_vec(), 99 | vendor_type, 100 | /* 101 | * Ref: RFC 4679 - https://datatracker.ietf.org/doc/html/rfc4679 102 | * > Vendor-Length 103 | * > 104 | * > The Vendor-Length field is one octet and indicates the length of 105 | * > the entire sub-attribute, including the Vendor-Type, 106 | * > Vendor-Length, and Value fields. 107 | */ 108 | length: (Self::BYTE_SIZE_OFFSET + value.len()) as u8, 109 | tag, 110 | value: value.as_bytes().to_vec(), 111 | } 112 | } 113 | } 114 | 115 | impl VSA for TaggedStringVSA { 116 | fn len(&self) -> usize { 117 | self.length as usize 118 | } 119 | 120 | fn is_empty(&self) -> bool { 121 | self.length == 0 122 | } 123 | 124 | /// message returns the serialized vendor-specific message for AVP. 125 | /// 126 | /// Format: 127 | /// 0 1 2 3 128 | /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 129 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 130 | /// | Type | Length | Vendor-Id 131 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 132 | /// Vendor-Id (cont) | Vendor type | Vendor length | 133 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 134 | /// | Tag | Attribute-Specific... 135 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 136 | /// 137 | /// See also: CISCO RADIUS Attributes Configuration Guide - https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/sec_usr_radatt/configuration/xe-16/sec-usr-radatt-xe-16-book.pdf 138 | fn message(&self) -> Vec { 139 | let total_length: usize = Self::BYTE_SIZE_OFFSET + self.vendor_id.len() + self.value.len(); 140 | let mut result = Vec::with_capacity(total_length); 141 | 142 | result.extend(&self.vendor_id); 143 | result.extend(vec![self.vendor_type, self.length, self.tag]); 144 | result.extend(&self.value); 145 | 146 | result 147 | } 148 | } 149 | 150 | #[cfg(test)] 151 | mod string_vsa_tests { 152 | use crate::core::vsa::{StringVSA, VSA}; 153 | 154 | #[test] 155 | fn it_should_get_len_successfully() { 156 | let vendor_id = 4874; 157 | let vsa_type = 65; 158 | let value = "bar(1000,5441)"; 159 | let vsa = StringVSA::new(vendor_id, vsa_type, value); 160 | 161 | assert_eq!(vsa.len(), 16); 162 | } 163 | 164 | #[test] 165 | fn it_should_get_message_successfully() { 166 | let vendor_id = 4874; 167 | let vsa_type = 65; 168 | let value = "bar(1000,5441)"; 169 | let vsa = StringVSA::new(vendor_id, vsa_type, value); 170 | 171 | assert_eq!( 172 | vsa.message(), 173 | [0, 0, 19, 10, 65, 16, 98, 97, 114, 40, 49, 48, 48, 48, 44, 53, 52, 52, 49, 41] 174 | ) 175 | } 176 | } 177 | 178 | #[cfg(test)] 179 | mod tagged_string_vsa_tests { 180 | use crate::core::vsa::{TaggedStringVSA, VSA}; 181 | 182 | #[test] 183 | fn it_should_get_len_successfully() { 184 | let vendor_id = 4874; 185 | let vsa_type = 65; 186 | let tag = 5; 187 | let value = "bar(1000,5441)"; 188 | let vsa = TaggedStringVSA::new(vendor_id, vsa_type, tag, value); 189 | 190 | assert_eq!(vsa.len(), 17); 191 | } 192 | 193 | #[test] 194 | fn it_should_get_message_successfully() { 195 | let vendor_id = 4874; 196 | let vsa_type = 65; 197 | let tag = 5; 198 | let value = "bar(1000,5441)"; 199 | let vsa = TaggedStringVSA::new(vendor_id, vsa_type, tag, value); 200 | 201 | assert_eq!( 202 | vsa.message(), 203 | [0, 0, 19, 10, 65, 17, 5, 98, 97, 114, 40, 49, 48, 48, 48, 44, 53, 52, 52, 49, 41] 204 | ) 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /radius/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | pub mod client; 5 | pub mod core; 6 | pub mod server; 7 | 8 | #[cfg(all(feature = "md5", feature = "openssl"))] 9 | compile_error!("feature \"md5\" and feature \"openssl\" cannot be enabled at the same time"); 10 | -------------------------------------------------------------------------------- /radius/src/server.rs: -------------------------------------------------------------------------------- 1 | //! RADIUS server implementation. 2 | 3 | use async_trait::async_trait; 4 | use std::borrow::Borrow; 5 | use std::collections::HashSet; 6 | use std::future::Future; 7 | use std::io; 8 | use std::net::SocketAddr; 9 | use std::sync::{Arc, RwLock}; 10 | 11 | use thiserror::Error; 12 | use tokio::net::UdpSocket; 13 | 14 | use crate::core::packet::Packet; 15 | use crate::core::request::Request; 16 | use std::fmt::Debug; 17 | use std::marker::PhantomData; 18 | 19 | const DEFAULT_BUFFER_SIZE: usize = 1500; 20 | const DEFAULT_SKIP_AUTHENTICITY_VALIDATION: bool = false; 21 | 22 | /// A basic implementation of the RADIUS server. 23 | /// 24 | /// ## Example Usage 25 | /// - https://github.com/moznion/radius-rs/blob/HEAD/examples/server.rs 26 | pub struct Server, U: SecretProvider> { 27 | skip_authenticity_validation: bool, 28 | buf_size: usize, 29 | conn_arc: Arc, 30 | request_handler_arc: Arc, 31 | secret_provider_arc: Arc, 32 | undergoing_requests_lock_arc: Arc>>, 33 | _phantom_return_type: PhantomData, 34 | _phantom_error_type: PhantomData, 35 | } 36 | 37 | impl, U: SecretProvider> Server { 38 | // NOTE: why it separates between `listen()` and `run()`. 39 | // Initially it uses a channel that given through the `run()` parameter to notify when a server becomes ready, 40 | // but that doesn't work because it never run the procedure until `await` called. 41 | // This means if it calls `await`, it blocks the procedure so it cannot consume a channel simultaneously. 42 | // Thus, it separates bootstrap sequence between `listen()` and `run()`. 43 | // `listen()`: Start UDP listening. After this function call is finished, the RADIUS server is ready. 44 | // `run()`: Start a loop to handle the RADIUS requests. 45 | 46 | /// Starts UDP listening for the RADIUS server. 47 | /// After this function call is finished, the RADIUS server becomes ready to handle the requests; 48 | /// then it calls `run()` method for a `Server` instance that returned by this function, 49 | /// it starts RADIUS request handling. 50 | /// 51 | /// ## Parameters 52 | /// 53 | /// - `host` - a host to listen (e.g. `0.0.0.0`) 54 | /// - `port` - a port number to listen (e.g. `1812`) 55 | /// - `request_handler` - a request handler for the RADIUS requests. 56 | /// - `secret_provider` - a provider for shared-secret value. 57 | pub async fn listen( 58 | host: &str, 59 | port: u16, 60 | request_handler: T, 61 | secret_provider: U, 62 | ) -> Result { 63 | let undergoing_requests_lock_arc = Arc::new(RwLock::new(HashSet::new())); 64 | let request_handler_arc = Arc::new(request_handler); 65 | let secret_provider_arc = Arc::new(secret_provider); 66 | 67 | let address = format!("{host}:{port}"); 68 | let conn = UdpSocket::bind(address).await?; 69 | let conn_arc = Arc::new(conn); 70 | 71 | Ok(Server { 72 | skip_authenticity_validation: DEFAULT_SKIP_AUTHENTICITY_VALIDATION, 73 | buf_size: DEFAULT_BUFFER_SIZE, 74 | conn_arc, 75 | request_handler_arc, 76 | secret_provider_arc, 77 | undergoing_requests_lock_arc, 78 | _phantom_return_type: Default::default(), 79 | _phantom_error_type: Default::default(), 80 | }) 81 | } 82 | 83 | /// Starts the RADIUS requests handling. 84 | /// 85 | /// ## Parameters 86 | /// 87 | /// - `shutdown_trigger`: an implementation of the `Future` to interrupt to shutdown the RADIUS server (e.g. `signal::ctrl_c()`) 88 | pub async fn run(&mut self, shutdown_trigger: impl Future) -> Result<(), io::Error> { 89 | tokio::select! { 90 | res = self.run_loop() => { 91 | res 92 | } 93 | _ = shutdown_trigger => { 94 | info!("server is shutting down"); 95 | Ok(()) 96 | } 97 | } 98 | } 99 | 100 | /// Set a buffer size for receiving the request payload (default: `1500`). 101 | pub fn set_buffer_size(&mut self, buf_size: usize) { 102 | self.buf_size = buf_size; 103 | } 104 | 105 | /// Set a flag to specify whether to skip the authenticity validation or not (default: `false`). 106 | pub fn set_skip_authenticity_validation(&mut self, skip_authenticity_validation: bool) { 107 | self.skip_authenticity_validation = skip_authenticity_validation; 108 | } 109 | 110 | /// Returns the listening address. 111 | pub fn get_listen_address(&self) -> io::Result { 112 | self.conn_arc.local_addr() 113 | } 114 | 115 | async fn run_loop(&self) -> Result<(), io::Error> { 116 | let mut buf: Vec = vec![Default::default(); self.buf_size]; 117 | 118 | loop { 119 | let conn = self.conn_arc.clone(); 120 | let request_handler = self.request_handler_arc.clone(); 121 | let secret_provider = self.secret_provider_arc.clone(); 122 | 123 | let (size, remote_addr) = conn.recv_from(&mut buf).await?; 124 | 125 | let request_data = buf[..size].to_vec(); 126 | 127 | let local_addr = match conn.local_addr() { 128 | Ok(addr) => addr, 129 | Err(e) => { 130 | error!( 131 | "failed to get a local address from from a connection; {}", 132 | e 133 | ); 134 | continue; 135 | } 136 | }; 137 | 138 | let undergoing_requests_lock = self.undergoing_requests_lock_arc.clone(); 139 | let skip_authenticity_validation = self.skip_authenticity_validation; 140 | 141 | tokio::spawn(async move { 142 | Self::process_request( 143 | conn, 144 | &request_data, 145 | local_addr, 146 | remote_addr, 147 | undergoing_requests_lock, 148 | request_handler, 149 | secret_provider, 150 | skip_authenticity_validation, 151 | ) 152 | .await; 153 | }); 154 | } 155 | } 156 | 157 | #[allow(clippy::too_many_arguments)] 158 | async fn process_request( 159 | conn: Arc, 160 | request_data: &[u8], 161 | local_addr: SocketAddr, 162 | remote_addr: SocketAddr, 163 | undergoing_requests_lock: Arc>>, 164 | request_handler: Arc, 165 | secret_provider: Arc, 166 | skip_authenticity_validation: bool, 167 | ) { 168 | let secret: Vec = match secret_provider.fetch_secret(remote_addr) { 169 | Ok(secret) => secret, 170 | Err(e) => { 171 | error!( 172 | "failed to fetch secret binary vector from the secret provider; {}", 173 | e 174 | ); 175 | return; 176 | } 177 | }; 178 | if secret.is_empty() { 179 | error!("empty secret returned from secret source; empty secret is prohibited"); 180 | return; 181 | } 182 | 183 | if !skip_authenticity_validation && !Packet::is_authentic_request(request_data, &secret) { 184 | info!("packet validation failed; bad secret"); 185 | return; 186 | } 187 | 188 | let packet = match Packet::decode(request_data, &secret) { 189 | Ok(packet) => packet, 190 | Err(e) => { 191 | error!( 192 | "failed to parse given request data to pack into the RADIUS packet; {}", 193 | e 194 | ); 195 | debug!("failed request data => {:?}", request_data); 196 | // TODO error handler support? 197 | return; 198 | } 199 | }; 200 | 201 | let key = RequestKey { 202 | ip: remote_addr.to_string(), 203 | identifier: packet.get_identifier(), 204 | }; 205 | let key_for_remove = key.clone(); 206 | 207 | { 208 | let mut undergoing_requests = undergoing_requests_lock.write().unwrap(); 209 | if undergoing_requests.contains(&key) { 210 | return; 211 | } 212 | undergoing_requests.insert(key); 213 | } 214 | 215 | match request_handler 216 | .handle_radius_request( 217 | conn.borrow(), 218 | &Request::new(local_addr, remote_addr, packet), 219 | ) 220 | .await 221 | { 222 | Ok(_) => {} 223 | Err(e) => { 224 | println!("{e:?}"); 225 | } 226 | } 227 | 228 | let mut undergoing_requests = undergoing_requests_lock.write().unwrap(); 229 | undergoing_requests.remove(&key_for_remove); 230 | } 231 | } 232 | 233 | /// RequestHandler is a handler for the received RADIUS request. 234 | #[async_trait] 235 | pub trait RequestHandler: 'static + Sync + Send { 236 | /// This method has to implement the core feature of the server application what you need. 237 | /// 238 | /// # Arguments 239 | /// 240 | /// * conn - This connection is associated with the remote requester. In the most situations, 241 | /// you have to send a response through this connection object. 242 | /// * request - This is a request object that comes from the remote requester. 243 | async fn handle_radius_request(&self, conn: &UdpSocket, request: &Request) -> Result; 244 | } 245 | 246 | #[derive(Error, Debug)] 247 | pub enum SecretProviderError { 248 | /// An error that represents a failure to fetch a secret value from the provider. 249 | #[error("failed to fetch a secret value: {0}")] 250 | FailedFetchingError(String), 251 | /// An error that represents a generic (i.e. unclassified) error that occurs on the secret value provider. 252 | #[error("unexpected error: {0}")] 253 | GenericError(String), 254 | } 255 | 256 | /// SecretProvider is a provider for secret value. 257 | pub trait SecretProvider: 'static + Sync + Send { 258 | /// This method has to implement the generator of the shared-secret value to verify the request. 259 | fn fetch_secret(&self, remote_addr: SocketAddr) -> Result, SecretProviderError>; 260 | } 261 | 262 | #[derive(PartialEq, Eq, Hash, Clone)] 263 | struct RequestKey { 264 | ip: String, 265 | identifier: u8, 266 | } 267 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /scripts/generate-code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | REPO_ROOT="$(cd ./"$(git rev-parse --show-cdup)" || exit; pwd)" 6 | DICTS_DIR="${REPO_ROOT}/dicts" 7 | SRC_DIR="${REPO_ROOT}/radius/src" 8 | 9 | DICTS=$(ls "$DICTS_DIR") 10 | DICT_FILES=() 11 | 12 | # shellcheck disable=SC2068 13 | for DICT in ${DICTS[@]}; do 14 | DICT_NAME="${DICT##*.}" 15 | DICT_FILE="${DICTS_DIR}/dictionary.${DICT_NAME}" 16 | if [ -f "$DICT_FILE" ]; then 17 | cat /dev/null > "${SRC_DIR}/core/${DICT_NAME}.rs" 18 | DICT_FILES+=("$DICT_FILE") 19 | fi 20 | done 21 | 22 | # shellcheck disable=SC2068 23 | cargo run --bin code-generator -- --out-dir="${SRC_DIR}/core/" ${DICT_FILES[@]} 24 | 25 | --------------------------------------------------------------------------------