Getting Started with ION-DTN 3.4.0 on FreeBSD
I was reading Wikipedia articles about things like the interplanetary internet, InterPlaNet and delay-tolerant networking. After writing a post on serving web content with tor, I wanted to try to serve a web page over ION-DTN. This post covers installing ION-DTN 3.4.0 on FreeBSD.
After the installation instructions, there are a few usage examples, including a very crude scripted web server. The original goal was to take an outside web request, send it over ION-DTN to a server on the other side and return the response. That example deserves a separate post.
Special thanks to Scott C Burleigh for helping me work through some setup problems.
The following are follow ups to this post:
- ION DTN as a Service on FreeBSD
- Almost Serving a Web Page with ION-DTN bpchat
- Serving a Web Page with ION-DTN bpsendfile and bprecvfile
Software Versions
$ date
February 8, 2016 at 03:34:50 PM JST
$ uname -vm
FreeBSD 11.0-CURRENT #0 r287598: Thu Sep 10 14:45:48 JST 2015 root@:/usr/obj/usr/src/sys/MIRAGE_KERNEL amd64
$ ionadmin
: v
ION OPEN SOURCE 3.4.0
Instructions
First, download and extract the source code.
wget 'http://downloads.sourceforge.net/project/ion-dtn/ion-3.4.0b.tar.gz'
tar -zxvf ion-3.4.0b.tar.gz
cd ion-open-source/
Note that ION-DTN requires gmake and bash. autotools are not required but useful.
portmaster devel/gmake shells/bash devel/autotools
The sysctl_script.sh script needs to be patched to build IOT-DTN run on FreeBSD. A number of other files also need to be patched work properly. These scripts appear to be written for Linux and use #!/bin/bash instad of #!/usr/bin/env bash.
sed -i '' 's:#!/bin/bash:#!/usr/bin/env bash:' sysctl_script.sh
find ./ -type f -print0 | xargs -0 sed -i '' 's:#!/bin/bash:#!/usr/bin/env bash:'
Some of the shared memory values suggested by sysctl_script.sh are too low on FreeBSD. Copy the following lines into /boot/loader.conf. These values are read only tunable and must be set before the system enters multi-user mode.
kern.ipc.shmmni=192
kern.ipc.shmseg=128
kern.ipc.semmns=32000
kern.ipc.semmni=128
Copy the following lines into your choice of /boot/loader.conf or /etc/sysctl.conf. These values are tunable in multi-user mode. See the chapter in the FreeBSD Handbook for more information.
kern.ipc.shmmax=536870912
kern.ipc.shmmin=1
kern.ipc.shmall=131072
net.inet.udp.maxdgram=32000
kern.ipc.shm_use_phys=0
kern.ipc.shm_allow_removed=0
Note that the above tunable values can be changed by root at runtime.
su
sysctl kern.ipc.shmmax=536870912
Reboot the system so the new shared memory values will take effect.
su
shutdown -r now
Read README.txt. Optionally run ./config -h. When you know what you are doing, configure and build.
System Wide Install
A system wide installation needs to be performed by root. I also run the build as root because I ultimately want root to be the owner of the installed files. Note that by default the man pages are installed in the wrong place on FreeBSD.
su
./configure --mandir=/usr/local/man
gmake clean
gmake
Test the build. gmake test should work, but it is configured to test the original Bundle Security Protocol. The depreciated bsp tests are skipped, so running gmake test is pointless. Instead, Run the following command. It tests the new not yet standardized Streamlined Bundle Security Protocol.
(cd tests/; ./runtests sbsp/)
If the tests pass, perform a system wide install as root.
gmake install
ldconfig
Single User Install
A single user install can be performed by passing the –prefix flag to configure.
./configure --prefix="$HOME/ion" --mandir="$HOME/ion/man"
gmake clean
gmake
(cd tests/; ./runtests sbsp/)
gmake install
Appended ion/bin to PATH. If ion/bin is in $PATH then manpath will look for manpages in ion/man.
~/.profile
export "PATH=$HOME/ion/bin:$PATH"
The ion library path could be added to LD_LIBRARY_PATH, but running ldconfig requires root privileges, so this does not make sense for a single user install. See this link for details.
Documentation
Serve tutorial.html and open it in your favorite browser. Read through the tutorial.
FILE="tutorial.html"; { printf "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c <"$FILE")\r\n\r\n"; cat "$FILE"; } | nc -N -l 0.0.0.0 8080
Also look at ION Deployment Guide.pdf and ION.pdf. Note the AMS programmer’s guide v2.2.pdf and the Windows related PDFs. On a system wide install, there are a bunch of useful resources in /usr/local/share/ion/. Finally, man ion.
FILE="ION Deployment Guide.pdf"; { printf "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c <"$FILE")\r\n\r\n"; cat "$FILE"; } | nc -N -l 0.0.0.0 8080
FILE="ION.pdf"; { printf "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c <"$FILE")\r\n\r\n"; cat "$FILE"; } | nc -N -l 0.0.0.0 8080
ls /usr/local/share/ion/
man ion
Starting ION
A number of configuration files are required to start ION. Add the following lines to the specified files. It is probably a good idea to move to a different directory first.
host1.ionrc
1 1 ''
s
a contact +1 +3600 1 1 100000
a range +1 +3600 1 1 1
m production 1000000
m consumption 1000000
host1.ltprc
1 32
a span 1 32 32 1400 10000 1 'udplso localhost:1113'
s 'udplsi localhost:1113'
host1.bprc
1
a scheme ipn 'ipnfw' 'ipnadminep'
a endpoint ipn:1.0 q
a endpoint ipn:1.1 q
a endpoint ipn:1.2 q
a protocol ltp 1400 100
a induct ltp 1 ltpcli
a outduct ltp 1 ltpclo
s
host1.ipnrc
a plan 1 ltp/1
host1.ionsecrc is not required, but it keeps “Can’t find ION security database.” from being logged in ion.log.
1
Create host1.rc with the following command.
ionscript -i host1.ionrc -s host1.ionsecrc -l host1.ltprc -b host1.bprc -p host1.ipnrc -O host1.rc
Start ION with either of the following commands.
ionstart -I host1.rc
ionstart -i host1.ionrc -s host1.ionsecrc -l host1.ltprc -b host1.bprc -p host1.ipnrc
ION can be stopped with the following command.
ionstop
Examples
The following examples can be used to get started.
Hello World
Enter the follow lines into the terminal. Hit ^C to exit bpsink after verifying the payload has been delivered.
echo "Hello, World!" | bpsource ipn:1.1
bpsink ipn:1.1
# ^C to exit bpsink
A slightly unreliable single line hello world example is below.
{ echo "Hello, World!"; sleep 1; } | bpchat ipn:1.1 ipn:1.1
Chat
Use two terminals to enter the following commands. Enter text and hit enter to transfer the line to the other terminal. Hit ^C to exit.
# α terminal
bpchat ipn:1.1 ipn:1.2
# ^C to exit bpchat
# β terminal
bpchat ipn:1.2 ipn:1.1
# ^C to exit bpchat
Echo Loop
This modified chat example sets up an echo server. The server echoes lines back to the client until it receives EOT on a single line. EOT is piped into the connection after the client is closed with ^C. The server closes automatically without any manual intervention.
# α terminal
mkfifo fifo
bpchat ipn:1.1 ipn:1.2 <fifo | sed -u -n "/^$(printf "\4")$/q; p" | tee fifo
# β terminal
bpchat ipn:1.2 ipn:1.1; printf "\4\n" | bpchat ipn:1.2 ipn:1.1
# ^C to exit bpchat
Scripted Request-Response: Serving a Web Page Over BP
This is a crude example of using bpsendfile and bprecvfile to serve a web page over BP. First, create index.html. Alternatively, use tutorial.html or another file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hello World!</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
Add the following to server.sh. The request is written to testfile1. It also moonlights as the file to be sent.
#/bin/sh
SOURCE=ipn:1.1
DESTINATION=ipn:1.2
SERVICE_CLASS=0.1
FILE=index.html
CONTENT_TYPE=text/html
while true; do
echo "<<<$((X=X+1))<<<"
bprecvfile $SOURCE 1
REQUEST=$(cat testfile1)
echo "$REQUEST"
# in a real server, do something with the request
echo ">>>${X}>>>"
BODY=$(cat $FILE)
RESPONSE=$(cat <<EOF
HTTP/1.0 200 OK
Content-Type: ${CONTENT_TYPE}
Content-Length: $((${#BODY}+1))
Connection: close
${BODY}
EOF
)
echo "$RESPONSE"
echo "$RESPONSE" > testfile1
bpsendfile $SOURCE $DESTINATION testfile1 $SERVICE_CLASS
done
Add the following to request.sh. This script is much like server.sh, but without the loop.
#/bin/sh
SOURCE=ipn:1.2
DESTINATION=ipn:1.1
SERVICE_CLASS=0.1
echo "<<<$((X=X+1))<<<"
REQUEST=$(cat <<EOF
GET / HTTP/1.1
Host: www.host.com
Connection: close
EOF
)
echo "$REQUEST"
echo "$REQUEST" > testfile1
bpsendfile $SOURCE $DESTINATION testfile1 $SERVICE_CLASS
echo ">>>${X}>>>"
bprecvfile $SOURCE 1
RESPONSE=$(cat testfile1)
echo "$RESPONSE"
From different terminals, start the server and make a request. Note that request.sh is run in the current shell so that the request number increases if the command is executed multiple times.
chmod +x server.sh request.sh
# α terminal
./server.sh
# β terminal
. ./request.sh
Unresponsive ION
If ION becomes unresponsive, restart it. This example abuses ION. Enter the following in badserver.sh.
#/bin/sh
SOURCE=ipn:1.1
DESTINATION=ipn:1.2
FILE=index.html
CONTENT_TYPE=text/html
while true; do
BODY=$(cat $FILE)
RESPONSE=$(cat <<EOF
HTTP/1.0 200 OK
Content-Type: ${CONTENT_TYPE}
Content-Length: $((${#BODY}+1))
Connection: close
${BODY}
EOF
)
echo "---$((X=X+1))---"
echo "$RESPONSE" | bpchat $SOURCE $DESTINATION
done
Let badserver.sh run until the hello world example stops working.
# α terminal
chmod +x badserver.sh
./badserver.sh
# β terminal
echo "Hello, World!" | bpsource ipn:1.3
bpsink ipn:1.3
# ^C to exit bpsink
Receive the data sent from badserver.sh.
bpsink ipn:1.2
# ^C to exit bpsink
Hold ^C to kill the badserver.sh script. Stopping ION may help badserver.sh die faster. Restart ION and the hello world example should work agian.
ionstop
ionstart -I host1.rc
echo "Hello, World!" | bpsource ipn:1.3
bpsink ipn:1.3
# ^C to exit bpsink
If ionstart or ionstop hangs, run killm directly and restart ion.
killm
ionstart -I host1.rc
write failed, filesystem is full
Congratulations! ion.log probably ate up all of your disk space. Delete it.
rm ion.log
References:
- ION-DTN, SourceForge, ION-DTN
- ION-DTN, SourceForge, Source Code Download
- ION-DTN, SourceForge, Support
- ION-DTN, Introduction to DTN
- ION-DTN, RFC 5050 Bundle Protocol Specification
- ION-DTN, dtn-interest Mailing List Archives
- ION-DTN, Re: (dtn-interest) DTN2 manual or tutorials?
- ION-DTN, Web Archive, DTN Train - Berkeley Open House, October 15, 2004
- ION-DTN, ion and dtn2 interoperability configuration
- ION-DTN, NASA Astronaut Email - MS-RPC Over HTTP - ION-DTN Module Architecture
- ION-DTN, GitHub ION 2.2.1
- ION-DTN, Interplanetary Overlay Network (ION) Design and Operation V1.12 PDF
- ION-DTN, Man ion
- ION-DTN, Man bp
- ION-DTN, Man bpsource
- ION-DTN, Man bpsink
- ION-DTN, Man bpchat
- ION-DTN, Man bpsendfile
- ION-DTN, Man bprecvfile
- ION-DTN, Man bptrace
- ION-DTN, Man ionsecadmin
- ION-DTN, Man ionsecrc
- FreeBSD, freebsd server limits question
- FreeBSD, sysctl options loader.conf or sysctl.conf
- FreeBSD, man pages not installed correctly on FreeBSD
- FreeBSD, On FreeBSD, what is the best practice for adding to manpath?
- FreeBSD, man manpath
- FreeBSD, LD_LIBRARY_PATH
- FreeBSD Forums, sed not working with -i?
- FreeBSD Handbook, Tuning with sysctl(8)
- FreeBSD, Single Line Web Server With nc on FreeBSD
- FreeBSD, Getting Started With tor Hidden Services on FreeBSD
- UNIX, How do I download from SourceForge with wget?
- UNIX, Extract tar.gz File
- UNIX, How to replace a path with another path in sed?
- UNIX, Awk/Sed: How to do a recursive find/replace of a string?
- UNIX, Is there a standard command-line tool for unix for piping to a socket?
- UNIX, Empty the contents of a file
- UNIX, Single File Elixir Programs
- UNIX, What, at the bare minimum, is required for an HTTP request?
- UNIX, Pipe multiple commands to a single command with no EOF signal wait
- UNIX, Netcat without -e? No Problem!
- UNIX, Using netcat to build a simple TCP proxy in Linux
- UNIX, TCP proxy with netcat
- UNIX, Installing glib in non-standard prefix fails
- Wikipedia, Interplanetary Internet
- Wikipedia, InterPlaNet
- Wikipedia, Delay-tolerant networking