nsap-address

Crates.ionsap-address
lib.rsnsap-address
version1.0.0
created_at2025-08-29 10:27:48.538925+00
updated_at2025-08-29 10:27:48.538925+00
descriptionITU-T Rec. X.213 NSAP address parsing, printing, etc.
homepage
repositoryhttps://github.com/JonathanWilbur/asn1.rs/tree/master/nsap-address
max_upload_size
id1815671
size136,085
Jonathan Wilbur (JonathanWilbur)

documentation

README

X.213 NSAP Library

ITU-T Recommendation X.213 Network Service Access Point (NSAP) address parsing and printing. These address types were designed for use in OSI networking, but have full compatibility with IP networking. Since OSI networking is ancient history, this library prioritizes the IP networking aspects, but everything should be supported.

This crate

This module decodes and encodes a Network Service Access Point (NSAP) to and from the "preferred binary encoding" described in Annex A, Section A.5.3 of ITU-T Recommendation X.213 (2001).

In addition to this, it displays and decodes NSAPs to and from human-readable strings according to the procedures defined in IETF RFC 1278, drawing on additional information found in IETF RFC 1277.

There are some deviations to the above, however. Since the human-friendly string syntax was defined, new AFIs were added, including one for directly representing IP addresses and another for representing URLs. As such this library extends the specification, but should be completely backwards compatible with it.

You should not expect an NSAP decoded from a string to encode back into the same exact string. You should not expect an NSAP decoded from bytes to encode back into the same exact bytes. You should not expect all NSAP syntaxes to be recognized everywhere; your application and dependencies should handle unrecognized NSAP syntaxes gracefully.

This crate is no_std and supports almost everything with no alloc as well; the only thing alloc gives you is better URL encoding and decoding, per ITU-T Recommendation X.519. Only extremely short URLs are supported without alloc.

Usage

An NSAP address is represented using X213NetworkAddress. You can construct this using several methods:

  • X213NetworkAddress::from_vec()
  • X213NetworkAddress::from_vec_unchecked()
  • X213NetworkAddress::from_slice()
  • X213NetworkAddress::from_slice_unchecked()
  • X213NetworkAddress::from_ip()
  • X213NetworkAddress::from_ipv4()
  • X213NetworkAddress::from_ipv6()
  • X213NetworkAddress::from_itot_url()
  • X213NetworkAddress::from_non_osi_url()
  • X213NetworkAddress::from_itot_socket_addr()
  • X213NetworkAddress::try_from() (for Vec<u8> or &[u8])
  • X213NetworkAddress::from_str()
  • X213NetworkAddress::from() (for &IpAddr, &Ipv4Addr, or &Ipv6Addr)

The X213NetworkAddress type implements Display, which prints the NSAP address according to IETF RFC 1278.

If you need to pass NSAP addresses between heterogeneous systems, consider using to_ns_string or fmt_as_ns_string() instead. This will always encode the NSAP address using the NS+ syntax like: NS+A433BB93C1. These are not human-friendly, but they are really easy to parse and completely unambiguous.

There is no way in this crate to compare two NSAP addresses. The rationale for this is documented along with X213NetworkAddress, but if you want to compare the addresses byte-for-byte, you can use get_octets(), like so:

assert_eq!(addr1.get_octets(), addr2.get_octets());

This crate also supports several functions for working specifically with IP networking, above and beyond those already named, which are:

  • X213NetworkAddress::get_url()
  • X213NetworkAddress::get_ip()
  • X213NetworkAddress::get_rfc1277_socket()

In a TCP/IP only environment, you'll likely want to invoke all three of these methods until one of them returns a result, then perform the appropriate connection setup.

Here is an example usage of this crate:

extern crate alloc;
use alloc::vec::Vec;
use nsap_address::X213NetworkAddress;
use nsap_address::AFI_F69_DEC_LEADING_ZERO;
use core::net::{IpAddr, Ipv4Addr};
use core::str::FromStr;

let addrstr = "TELEX+00728722+RFC-1006+03+255.0.0.2+65535+2";
let addr = X213NetworkAddress::from_str(addrstr).unwrap();
let (_, sock, _) = addr.get_rfc1277_socket().unwrap();
assert_eq!(sock.ip(), &Ipv4Addr::new(255, 0, 0, 2));
assert_eq!(sock.port(), 65535);
let idi_digits: Vec<u8> = addr.idi_digits().unwrap().collect();
assert_eq!(idi_digits.as_slice(), &[ 0, 0, 7, 2, 8, 7, 2, 2 ]);
assert_eq!(addr.get_octets(), &[
  AFI_F69_DEC_LEADING_ZERO, // AFI
  0x00, 0x72, 0x87, 0x22, // Telex 00728722
  0x03, // Network prefix (0x03 = Internet)
  0x25, 0x50, 0x00, 0x00, 0x00, 0x02, // IP address
  0x65, 0x53, 0x50, 0x00, 0x02, // port + tset
]);
let ns_string = addr.to_ns_string();
assert_eq!(ns_string.as_str(), "NS+5400728722032550000000026553500002");

Feature Flags

  • alloc: heap allocation, which enables URL encoding and decoding for URLs
  • x25: Parsing of X.25 DSP strings, per IETF RFC 1278
  • ecma117: Parsing of ECMA 177 DSP strings, per IETF RFC 1278
  • nonstd: Parsing for non-standard syntaxes: those defined by this crate, but not in any standard, which are the IP4, IP6, URL, ICP, and IND.
  • nonstddisplay: implementation of std::fmt::Display for the above non-standard syntaxes. This is a separate feature flag so that, if you have an application that passes NSAPs as strings, you can ensure that you only use standardized syntaxes, while still being able to parse the non-standard ones.

alloc is the only one enabled by default. Keeping x25 off is a good idea unless, somehow, you are still using or working with X.25 networks. The ECMA 117 syntax was not widely used, so you are unlikely to encounter that as well; for this reason, you might want to keep ecma117 off. nonstd and nonstddisplay will be big quality-of-life improvements for you in almost all cases.

AI Usage Statement

No code, tests, or documentation was produced by AI or an LLM of any kind, except for two small internal functions in utils, which were reviewed by the crate's author.

Deviations from IETF RFC 1278

  • ICP and IND AFIs recognized in the <afi>-<idi>-<dsp> syntax
  • IP4, IP6, and URL schemes supported in FromStr and Display

To Do (Future)

Commit count: 429

cargo fmt