-
Notifications
You must be signed in to change notification settings - Fork 6
Open5066 is an open source implementation of NATO STANAG 5066
License
GPL-2.0, GPL-2.0 licenses found
Licenses found
GPL-2.0
LICENSE
GPL-2.0
COPYING
Rhizomatica/open5066
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Open5066 - s5066d ################# This is a fork of the Open5066, originally written by Sampo Kellomaki. Abstract Open5066 is an open source implementation of NATO NC3A STANAG 5066 protocol stack for HF radio communications. It aims to implement all of SIS (Annex A), DTS (Annex C), and some of the application layer (Annex F) functionality such as HMTP. Eventually Open5066 will also implement crypto module and may implement a softmodem for some waveforms such as S-4285 or S-4529, or it may evolve a smooth interface to integrate softmodems from other open source projects. Concrete embodiment of Open5066 is the s5066d daemon. See https://github.com/Rhizomatica/open5066/blob/master/open5066.pdf for more information. 1. Status Project was started in April 2006 and is in very early phase. Major feature enhancements and debugging is going on. Unless you have C debugging skills and are willing to contribute, you probably should not be trying this program yet. But watch this space, in a month or two we expect to have a system that is usable in limited ways. > Current relase is *0.4*, dated 3.5.2006. This is the first release > that is capable of full HMTP over DTS to remote roundtrip. We follow the philosophy of "release early, release often". We are now in the early part. S-5066 Features Status Feature ======= ======================================================= 80% I/O engine, command line interface, and daemon code 75% SIS Primitives over TCP, parsing and generation 60% DTS over TCP 0% DTS over modem 50% S_PDUs 50% C_PDUs 40% D_PDUs 95% Nonarq transfers, including repetitions 10% ARQ transfers 0% Rank and priority support 0% Expedited anything 0% Soft link establishement and tear down 0% Hard link establishement and tear down 0% Special broadcast mode (as opposed to simply sending nonarq) 0% Break-in 0% ALE or similar 0% Routing 0% Crypto module 0% Soft-modem >> 2. Howto 2.1 Compiling and Installation At the moment only Linux 2.6 (an onwards) and Solaris 8 are supported. We use epoll(4) so porting to other UNIX will require some effort. git clone https://github.com/Rhizomatica/open5066.git cd open5066 make cp s5066d /usr/sbin Solaris 8 using /dev/poll can be compiled as follows: make TARGET=sol8 Sparc Solaris 8 using /dev/poll can be compiled using a gcc cross compiler as follows: PATH=/apps/gcc/sol8/bin:/apps/binutils/sol8/bin:$PATH make TARGET=xsol8 This assumes your cross compiler is in the supplied path. If you change the path, you MUST also change the definition of the SYSROOT variable inside the make file. See gcc documentation for further instructions on creating cross compilers if you are interested in this approach. 2.2 Running You can pass mail between two nodes by doing following On node 1: echo secret | s5066d -p sis::5066 -p dts::5067 -c AES256 -k 0 dts:node2:5067 s5066d -p smtp::25 sis:localhost:5066 smtp:mail.yourdom.com:25 On node 2: echo secret | s5066d -p sis::5066 -p dts::5067 -c AES256 -k 0 dts:node1:5067 s5066d -p smtp::25 sis:localhost:5066 smtp:mail.theirdom.com:25 Next you need to configure the mail servers mail.yourdom.com and mail.theirdom.com to forward mail to node1 and node2, respectively. Probably the best way to do this is to pick some special subdomain and forward all mail to this subdomain to the s5066 pipe. For example mail destined to [email protected] could be funneled to port 25 on node 1 and emerge from node2 where the local daemon there will talk to the SMTP server and try to deliver her mail. NODE 1 NODE 2 Mail Client A Mail Client B | ^ V | mail server mail server | ^ V | hmtpgwd --s--> s5066d ---z---> s5066d --s--> hmtpgwd s = SIS primitives (Annex A) z = "over the air" (currently TCP) DTS traffic (Annex C) hmtpgwd = specially configured s5066d (the second command line on each node) <<dot: hmtp-scenario: Connecting regular SMTP servers via HMTP gateways and S5066 network. digraph hmtpgw { rankdir=LR subgraph cluster_node1 { label="Node 1" { rank=same mua1 [label="Mail Client A"] mta1 [label="Mail Server"] hmtp1 [label="HMTPgwd"] } s5066d1 [label="s5066d"] mua1 -> mta1 -> hmtp1 -> s5066d1 } subgraph cluster_node2 { label="Node 2" { rank=same mua2 [label="Mail Client B"] mta2 [label="Mail Server"] hmtp2 [label="HMTPgwd"] } s5066d2 [label="s5066d"] mta2 -> hmtp2 [dir=back] mua2 -> mta2 s5066d2 -> hmtp2 } s5066d1 -> s5066d2 [style=dotted] } >> Needless to say, you will need to be pretty good at your mail server configuration to pull this off. Please do not ask me how to configure them: consult your mail server documentation. 3. s5066d - The STANAG 5066 Daemon Documentation 3.1 Invocation Usage: s5066d [options] PROTO:REMOTEHOST:PORT echo secret | s5066d -p sis::5066 -c AES256 -k 0 dts:quebec.cellmail.com:5067 s5066d -p smtp::25 sis:localhost:5066 smtp:mail.cellmail.com:25 -p PR:IF:PORT Protocol, network interface and TCP port for listening connections. Default sis:0.0.0.0:5066. You can omit interface. sis:0.0.0.0:5066 - Listen for SIS (Annex A primitives) dts:0.0.0.0:5067 - Listen for DTS (Annex B) smtp:0.0.0.0:25 - Listen for SMTP (RFC 2821) http:0.0.0.0:80 - Listen for HTTP/1.0 (simplified) tp:0.0.0.0:5068 - Listen for test ping protocol -t SECONDS Connection timeout for both SIS and DTS. Default: 0=no timeout. -c CIPHER Enable crypto on DTS interface using specified cipher. Use '?' for list. -k FDNUMBER File descriptor for reading symmetric key. Use 0 for stdin. -nfd NUMBER Maximum number of file descriptors, i.e. simultaneous connections. Default 20 (about 16 connections). -npdu NUMBER Maximum number of simultaneously active PDUs. Default 60. -nthr NUMBER Number of threads. Default 1. Should not exceed number of CPUs. -nkbuf BYTES Size of kernel buffers. Default is not to change kernel buffer size. -nlisten NUMBER Listen backlog size. Default 128. -egd PATH Specify path of Entropy Gathering Daemon socket, default on Solaris: /tmp/entropy. On Linux /dev/urandom is used instead See http://www.lothar.com/tech/crypto/ or http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html -rand PATH Location of random number seed file. On Solaris EGD is used. On Linux the default is /dev/urandom. See RFC1750. -uid UID:GID If run as root, drop privileges and assume specified uid and gid. -pid PATH Write process id in the supplied path -watchdog Enable built-in watch dog -kidpid PATH Write process id of the child of watchdog in the supplied path -afr size_MB Turn on Application Flight Recorder. size_MB is per thread buffer. -v Verbose messages. -q Be extra quiet. -d Turn on debugging. -license Show licensing details, including NATO C3 Agency disclaimer. -h This help message -- End of options N.B. Although s5066d is a 'daemon', it does not daemonize itself. You can always say s5066d& Mostly the daemon acts as an I/O engine or proxy. You will need to specify listening port with -p option if you want to contract the daemon or if you want anyone else to contact the daemon. If you want the daemon to contact anyone else, you will need to specify the servers to contact on the command line. Each -p or commandline specification follows format PROTOCOL:HOST:PORT The PROTOCOL is one of * sis - S5066 Annex A SIS primitives are passed over TCP stream * dts - S5066 Annex C DTS D_PDUs are passed over TCP stream * smtp - Simple Mail Transfer Protocol (SMTP, RFC2821) is spoken over TCP connection * http - HTTP/1.0 is spoken over TCP. Note that this support is very limited and only used for debugging and benchmarking the I/O engine. +This is NOT a real web server.+ * tp - Test Ping Protocol. Used for debugging the I/O engine. For listening sockets the HOST specifies which network interface the listener will bind to. This is only relevant for multihomed hosts and generally you will know what this means if you need it. For everybody else, specify 0.0.0.0 or just omit the host and the port will be bound to all interfaces. For remote servers the HOST specifies the domain name or IP address of the remote server. You can also specify ~localhost~ or 127.0.0.1 if you want. The PORT specifies either the TCP port to listen to or the TCP port to contact. Typical ports to use * 5066 - SIS primitives over TCP (Annex A) * 5067 - DTS D_PDUs over TCP (Annex C) * 5068 - Test ping * 25 - SMTP (you will need to run s5066d as root, but see -uid UID:GID flag) * 80 - HTTP (you will need to run s5066d as root, but see -uid UID:GID flag) * 8080 - HTTP if you do not want to run as root (*** TBW) 3.2 SIS Server Main function of s5066d is to relay SIS primitives from a TCP socket to DTS connection (which also may be TCP, but will eventually be HF Modem connection). To accomplish this you have to make sure s5066d listens for SIS primitives. You also need to specify the remote DTS node (usually another s5066d) to contact. It is also useful for the s5066d to listen for new DTS traffic from other nodes. All of this can be accomplished with the following command line: s5066d -p sis::5066 -p dts::5067 dts:remote.theirdom.com:5067 3.2 HMTP Gateway Node High Frequecy Mail Transfer Protocol (Annex F) gateway can be created by configuring s5006d to listen to SMTP (Simple Mail Transfer Protocol, RFC2821) and then contact the SIS s5066d -p smtp::25 sis:localhost:5066 smtp:mail.mydomain.com:25 3.3 Testing Effectively create back-to-back gateway that talks to itself: ./s5066d -p smtp:0.0.0.0:2525 -p sis:0.0.0.0:5066 sis:localhost:5066 smtp:ilpo:25 perl hitest.pl 1 * This actually CAN NOT work because we send out UNIDATA_REQ, but expect to receive UNIDATA_IND and the two are not sufficiently compatible. Full test setup ./s5066d -di Bsis -p sis:0.0.0.0:5065 -p dts:0.0.0.0:5067 ./s5066d -di Asis -p sis:0.0.0.0:5066 dts:localhost:5067 ./s5066d -di Asmtp -p smtp:0.0.0.0:2525 sis:localhost:5066 # SMTP server ./s5066d -di Bsmtp sis:localhost:5065 smtp:ilpo:25 # SMTP client perl hitest.pl 1 See: ./setup1.sh for a way to lauch all necessary servers. 4. Architecture <<dot: s5066d-arch: Module structure of s5066d rankdir=BT {rank=same accept [shape=plaintext] connect [shape=plaintext] } accept -> hiios:sw hiios:se -> connect hiios [ shape=box, label="hiios I/O engine", width=5 ] {rank=same ordering=out dts_dec [ shape=box ] dts_enc [ shape=box ] sis_dec [ shape=box ] sis_enc [ shape=box ] smtp_client_dec [ shape=box, label="smtp\nclient\ndec" ] smtp_client_enc [ shape=box, label="smtp\nclient\nenc" ] smtp_server_dec [ shape=box, label="smtp\nserver\ndec" ] smtp_server_enc [ shape=box, label="smtp\nserver\nenc" ] } hiios -> dts_dec dts_enc -> hiios hiios -> sis_dec sis_enc -> hiios hiios -> smtp_client_dec smtp_client_enc -> hiios hiios -> smtp_server_dec smtp_server_enc -> hiios dts_dec -> route [weight=0] route -> dts_enc [weight=0] route -> sis_enc [weight=0] sis_dec:n -> dts_enc:n [weight=0] sis_dec:n -> smtp_client_enc:n [weight=0] sis_dec:n -> smtp_server_enc:n [weight=0] smtp_client_dec:n -> sis_enc:n [weight=0] smtp_server_dec:n -> sis_enc:n [weight=0] dts_enc:s -> dts_dec:s [style=dotted weight=10] sis_enc:s -> sis_dec:s [style=dotted weight=10] smtp_client_enc:s -> smtp_server_dec:s [style=dotted] smtp_server_enc:s -> smtp_client_dec:s [style=dotted] connect -> dts_dec [style=invis] >> 4.1 Connection Management The hiios engine is used. Every connection (io object) MUST be associated with a file descriptor. The memory for the connection is obtained from an array indexed by the file descriptor. Since the file descriptor is used as a mutual exclusion mechanism for the connection memory array, you must not close a file descriptor until you are fully done with all the memory associated with it. 4.2 PDU Management Allocate from preallocated pools. Reference counted? Garbage collected? 4.3 todo_queue 1. polling inserts the io objects that are eligble for I/O 2. also PDUs can be inserted if they require further processing 3. worker threads eat from the todo_queue and dispatch 4.4 Detecting that I/O is possible * epoll(4) on Linux 2.6 - edge triggered events - requires every I/O to be "exhausted" until it returns EAGAIN * /dev/poll on Solaris 8 and newer - To Be Investigated 4.5 Some Open Issues * Remote management - remotes are given on command line, but should not really be opened immediately - depends on protocol: DTS immediate, SMTP only upon SIS HMTP traffic - closing a remote, e.g. SMTP after message - reconnect after failure? - multiple remotes to choose from * Handling sidebars 5 Protocol Processing 5.1 Protocol TODO * Segmentation of HMTP at SIS interface (currently entire HMTP message has to fit in one S_PDU wihout segmenting) * more SIS primitives * soft link establishment * arq mode * hard link establishment * expedited modes 5.2 DTS 5.3 SIS 5.4 SMTP Client Processing When a HMTP connection arrives from SIS layer, a connection is established to destination SMTP server which must have been specified on the command line. The SMTP server will send responses which are processed by smtp_resp_data() as they come. This processing updates the ~smtp_state~ variable on the SMTP connection object. The problem is "feeding" the HMTP payload piecemeal to the SMTP server. We can not just blast the whole blob to the server because that would be a violation of the SMTP protocol, pipelining or not. The ~smtp_state~ effectively acts as a synchronization mechanism between the feeder and the response processor. This mechanism only supports pipelined SMTP [RFC2197] <<table: Sequence of pipelined SMTP states for client Value Symbol Who Action ===== ====== ====== ========================================= 0 INIT resp Wait to receive 220 greeting. Can not send HMTP yet. 1 EHLO feeder Send SMTP EHLO. Feeder will do this as soon as HMTP message arrives from SIS layer. 2 RDY resp Wait to receive 250 from EHLO. Can not send HMTP yet. 3 MAIL feeder Send HMTP payload, except for message and QUIT. As mail can be big, several SIS primitives may be consumed. 4 RCPT feeder Continue sending SMTP payload except QUIT. Internal state of feeder. 5 DATA resp Process 250 responses from MAIL FROM and RCPT to commands until 354 enter mail is seen 6 SEND feeder Send message. As mail can be big, several SIS primitives may be consumed. 7 SENT resp Expect to see 250 from message input. Reply to SIS layer by sending HMTP response (synthesizing 221 goodbye response). Reply to SMTP server with QUIT. 8 QUIT resp Expect to see 221 goodbye from Quit. Close SMTP server connection. >> The tricky part is that the HMTP pdu will originally trigger EHLO, but can not be sent immediately. What we do is schedule the HMTP pdu to todo_queue only once we have seen the 250 response. Eventually the processing will resume. A slight problem remains in how to prevent reading further PDUs from the SIS connection? This is solved by NOT scheduling the SIS connection to the todo until we are ready to receive something from it. We also set the need more data field to zero to block it from reading further input in case there is a spurious I/O event reported. Current implementation only supports one SIS source and one SMTP destination, both of which are supplied on command line. Supplying more than one of each will produce unpredicatble results. 5.5 SMTP Server Processing When a SMTP connection is accepted from another SMTP server, we need to play the pleasantries (EHLO, etc.) until we get to the point of the payload that starts with MAIL FROM command. Until and including when DATA is received, we keep receiving all the protocol data into cur_pdu, playing a state machine that will send the right responses. Once the DATA has been received we formulate HMTP PDU and send it using SIS layer. As an important optimization, we look beyoud DATA and add as much as makes sense to the SIS primitive. This could mean we see the dot on its own line that terminates the message. In that case we add our own QUIT and the HMTP PDU is complete. It could also happen that the mail message is long and all we can see is in middle of some data, or worse something like "\r\n.\r" (but not the final "\n"). If so, we record the state of end of visible data in ~smtp_state~ variable and just send the data with SIS primitive. For long mail there can be any number of SIS primitives that just contain data and no protocol information. Finally we will see "\r\n.\r\n" or deduce its existence from the ~smtp_state~. We add our own QUIT and ship the last fragment with SIS (What if QUIT does not fit? No problem, we can use writev). The SIS receiving process eventually gets HMTP response PDU. We scan the HMTP message until we see 354 after which the next response code is expected to contain the outcome of the transaction. We send the outcome back to the SMTP server (usually "250 message sent") and move the protocol to state where either QUIT or new MAIL FROM can be received. In case of former we send "221 Bye" response and close the connection. In case of the latter, we start the processing from the beginning, sans the EHLO. <<table: Sequence of pipelined SMTP states for server Value Symbol Who Action ===== ====== ======= ======================================== 0 INIT write Send 220 greeting 11 START read Wait for EHLO. Send 250 response. 12 MAIN read Wait for MAIL FROM and rest of payload (we are using pipelining) and ship it as SIS primitive. 13 TO read Wait for RCPT TO or DATA. Substate of main. 13 MORE0 read For long mails, continue shipping the mail message as SIS primitives. Work this way until end of message is detected (sole dot on a line). Asseme no precursor of "\r\n.\r\n" has been seen. 14 MORE1 read Assume "\r\n" has been seen and ".\r\n" needs to be seen. 15 MORE2 read Assume "\r\n." has been seen and "\r\n" needs to be seen. 16 WAIT sisread Expect to see 354 response in HMTP response. 17 STATUS sisread Expect to see 250 indicating the success of message. Send the status to SMTP, but do not send 221 bye even if one was part of HMTP message. 18 END read Wait for QUIT (which probably was already in the buffer) and send 221 bye. If we get MAIL FROM instead, continue processing at state MAIN (12). >> 6. Simple Routing s5066d implements<<footnote: Release 0.1 does not implement routing yet.>> routing by decoding DTS packets and using destination node address to look up a line from a routing table. The line can say: * ignore * my local address, process locally * my group address, process locally * route to other DTS interface The last form makes it possible to route traffic from one subnet to another provided that the node is able to participate on both subnets and knows which subnet is closer to the ultimate destination. Following hierarchy of the network is is easy to establish a default route. <<dia: global-net,,,L410B70R450T0:basecov,base,cs,csrange,op,nvis,legend: Global HF network connects to regional networks that use NVIS propagation. Some global bandwidth is provided by HF.>> <<dia: global-net,,,L410B70R450T0:base,cs,csrange,op,nvis,legend: Global HF network connects to regional networks that use NVIS propagation. All global bandwidth is via satellite.>> The routing capability can also be used to implement a repeater within the same subnetwork. In the above diagram note that L2 can only reach the rest of the network via L1, which is configured as a repeater for L2 traffic. While MAD may be hearable within all of the CS Liberia territory, most of the actual Outposts are not hearable by MAD, thus two way communication MUST pass through CS Liberia, or via L1 in case L2 wants to communicate. <<dot: routing-scenario,,2: Routing Scenario MAD -> Panama MAD -> CS_Liberia MAD -> SIN SIN -> CS_Java Panama -> P1 CS_Liberia -> L1 -> L2 CS_Java -> J1 >> If J1 wants to communicate with P1, it sends a message that is detected by CS Java as message requiring routing. CS Java uses the long haul network and SIN notices it and also determines it as routable. Effectively SIN will act as a repeater and send the message with enough power for MAD to hear it (incidentally, this power is enough to reach J1 as well, but that does not help because it is one way communication). MAD determines that the message needs to be repeated so that Panama can hear it. Finally Panama figures that P1 is within local NVIS coverage and sends it using that channel. > The s5066d routing capability, despite being very simple, is very > powerful and allows any node on the globe to reach any other node. 7. Resources NEEDS UPDATE! S5066 site:: https://elayne.nc3a.nato.int/ (needs password for most interesting stuff) Project home:: http://open5066.org/ Download:: http://open5066.org/open5066-0.4.tgz Freshmeat page:: http://freshmeat.net/projects/open5066 Mailing list:: none yet, though announcements will happen on freshmeat.net Reporting bugs:: no bug tracking yet, mail author CVS access:: None. If you contribute a lot, I can create you nonanonymous access. This document as PDF:: http://open5066.org/open5066.pdf This document as HTML:: http://open5066.org/open5066-frame.html 8. S-5066 Doubts If someone could answer following questions, or improve the S-5066 spec, I would be grateful. 1. Meaning of confirmation modes "node" and "client"? Local node or remote node? Remote client? 2. Redundancy of ARQ mechanism wrt "confirmations"? Especially node confirm would seem to me to be the same as ARQ. 3. How is HMTP traffic segmented to U_PDUs given that a mail can be much bigger than the U_PDU maximum limit? 4. TTD Julian date? Exactly how is this formatted? In seconds? Since what epoch? Any modular arithmetic invoved? 5. Would destination sap id and source sap id ever differ? 6. The SMTP - HMTP comparison table, Table F-2, on p. F-10 would seem to violate RFC2920 section 3.1 "Client use of pipelining" third paragraph. The actual message can not be pipelined with DATA. However it can be pipelined with QUIT. 9. License and Disclaimers Copyright (c) 2006 Sampo Kellomäki ([email protected]), All Rights Reserved. You may use this code under the terms of Gnu General Public License, version 2 (GPL 2). > IMPORTANT: If you use this code for actual radio emissions, beware > that this has neither been debugged yet nor validated, let alone > certified to be conformant with anything. If you perform radio emissions > YOU, and not me or my contributors, are responsible for any bad signal > or protocol emitted, interference caused, horrible consequences > triggered, or for starting a nuclear war. I expressly do NOT warrant > that this code, in its present state, is correct. Of course > this disclaimer is redundant as GPL disclaims all warranties anyway > and requires you to waive all responsibility on my behalf or on behalf > of my contributors. > That said, if you are willing to validate, certify, or sponsor > a certification, this type of help would be very welcome. Even > just informal interoperability testing would be very valuable. Another point to remember, I am working under assumption that STANAG 5066 is patent free and I have not done, neither do I plan to do, patent search. Obviously I will not indemnify for any IPR breach, your sole remedy is to cease using this software. If this worries you and you do a patent review, or you are aware of patent claims, please let me know (with specific patent numbers so I can look them up myself). This product includes software developed by the NATO C3 Agency The Hague the Netherlands and its contributors. Such software is subject to following copyright and terms Copyright 1999, 2005 NATO C3 Agency, The Hague. Communication Systems Division -- Radio Branch. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the NATO C3 Agency The Hague the Netherlands and its contributors. 4. Neither the name of the NATO C3 Agency nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior permission. THIS SOFTWARE IS PROVIDED BY THE NATO C3 AGENCY AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE NATO C3 AGENCY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. References: [RFC2821] SMTP [RFC2197] SMTP pipelining extension
About
Open5066 is an open source implementation of NATO STANAG 5066
Resources
License
GPL-2.0, GPL-2.0 licenses found
Licenses found
GPL-2.0
LICENSE
GPL-2.0
COPYING
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published