The following describes a procedure for compiling sdr from the source code to run under the standard Linux kernel (2.4 series) and also describes the extra steps needed to compile sdr to run under the USAGI kernel. USAGI is an advanced IPv6 stack for Linux developed in Japan (http://www.linux-ipv6.org). Some source code and header file adaptations are needed to enable sdr to run under USAGI because USAGI has a different implementation of the bind system call.
What is needed to compile sdr and the rest of the Mbone tools (MICE tools) are the source code of the tool itself, the source code of the common multimedia library, the source code of TCL and the source code of TK. All of those can be found in the MICE webpage in UCL’s site (University College London): http://www-mice.cs.ucl.ac.uk/multimedia/software.
The TCL and TK libraries maintained by the site are special versions that are patched by UCL to work with the Mbone tools.
The following steps are required to compile sdr:
1- Start by downloading the source code from UCL’s MICE tools page (http://www-mice.cs.ucl.ac.uk/multimedia/software). The current sdr version is sdr 3.0.
2- Also download the source code of the common multimedia library from the same site (common). This code is used by all MICE tools.
3- Download the UCL patched versions of TCL and TK.
4- Create a work directory for the compilation process and copy all tarballs to it:
mkdir mice
cp sdr-3.0.tar.gz mice
cp common-1.2.14.tar.gz mice
cp tcl-8.0.3ucl8.tar.gz mice
cp tk-8.0.3ucl8.tar.gz mice
5- Uncompress and extract (unzip and untar) all four tarballs (tcl, tk, common, sdr).
6- Start configuring and compiling.
a. Configure and compile the UCL-patched TCL:
./configure
make
b. Configure and compile the UCL-patched TK:
./configure
make
c. Change the name of the Common Multimedia Library, configure it and compile it:
cd mice/common/
./configure --enable-ipv6
make
d. Configure and compile sdr itself. You’ll need some slight modifications to the file Makefile.linux as the path of the include files and the libraries is incorrectly specified. In particular, the include directory common should be common/src and the library directory common should be " common/src ":
cd mice/sdr/linux
The content of the file Makefile.linux is:
INCLUDES = -I../../tk-8.0/generic -I../../tcl-8.0/generic -I../../common
LIBS = ../../tk-8.0/unix/libtk8.0.a ../../tcl-8.0/unix/libtcl8.0.a ../../common/libuclmmbase.a -L/usr/X11R6/lib -lX11 -lc -lm -ldl -lresolv
CFLAGS = $(INCLUDES) -Wall -DNORANDPROTO -DDIFF_BYTE_ORDER -DAUTH -DLinux $(IFLAGS)
all:: sdr
It has to be changed to:
INCLUDES = -I../../tk-8.0/generic -I../../tcl-8.0/generic -I../../common/src
LIBS = ../../tk-8.0/unix/libtk8.0.a ../../tcl-8.0/unix/libtcl8.0.a ../../common/src/libuclmmbase.a -L/usr/X11R6/lib -lX11 -lc -lm -ldl -lresolv
CFLAGS = $(INCLUDES) -Wall -DNORANDPROTO -DDIFF_BYTE_ORDER -DAUTH -DLinux $(IFLAGS)
all:: sdr
After modifying the file, configure and compile:
make
If the compilation succefully concludes, you should find the sdr executable in the current directory.
7- Test sdr by performing the following:
a. Prepare your machine for launching sdr by making sure that:
You have the IPv6 stack enabled either by having it compiled into the kernel or by inserting the IPv6 module ( insmod ipv6 ).
You have this IPv4 route:
route add -net 224.0.0.0 netmask 224.0.0.0 dev eth0
You have a global IPv6 address configured on your interface (either manually or through router advertisements).
b. Launch sdr: ./sdr &
c. Check IPv4 and IPv6 ports open by sdr to verify that sdr is working for both IPv4 and IPv6 multicast:
Check that sdr is listening for IPv4 multicast (use lsof or netstat )
sdr 1210 root 4u IPv4 2912 UDP *:9859
sdr 1210 root 5u IPv4 2914 UDP sap.mcast.net:9875
sdr 1210 root 6u IPv4 2915 UDP 10.13.60.6:32772->sap.mcast.net:9875
sdr 1210 root 9u IPv4 2918 UDP 239.255.255.255:9875
sdr 1210 root 12u IPv4 2921 UDP *:5060
sdr 1210 root 13u IPv4 2922 TCP *:5060 (LISTEN)
Check that sdr is listening for IPv6 multicast (use lsof or netstat )
sdr 1210 root 7u IPv6 2916 UDP *:9875
sdr 1210 root 8u IPv6 2917 UDP [3000::1]:32773->[ff0e::2:7ffe]:9875
sdr 1210 root 10u IPv6 2919 UDP *:9875
sdr 1210 root 11u IPv6 2920 UDP *:9875
While an IPv6 multicast experimenter might elect to use the USAGI IPv6 stack as it is superior to the standard Linux IPv6 stack, sdr compiled using the procedure above will not work properly under USAGI. A typical error message that can be generated when trying to launch sdr when a USAGI kernel is running:
Address: 0, Port: 9875
The short explanation for this behavior is that USAGI uses a different implementation of the bind(2) system call which necessities the use of special socket options to avoid conflicts. A more detailed explanation can be found in the IMPLEMENTATION file contained within the USAGI kit.
To configure sdr to run properly under USAGI:
1- Patch the sdr source code with the following patch:
patch -p0 < patchfile
Where patchfile contains the following:
--- sdr/src/sd_listen.c
+++ sdr.usagi/src/sd_listen.c
@@ -216,7 +216,13 @@
perror("socket");
exit(1);
}
-
+#ifdef LINUX_IPV6
+ if (af == AF_INET6) {
+ int on = 1;
+ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+
+ }
+#endif
if (s >= sizeof(rfd2sock)) {
fprintf(stderr, "socket fd too large (%d)\n", s);
@@ -244,12 +250,20 @@
if (addr_fam == IPv6) {
#ifdef HAVE_IPv6
+ static int already_binded_port_9875 = 0;
+
inet_pton(AF_INET6, address, &group6);
memset((char *)&name6, 0, sizeof (name6));
name6.sin6_family = AF_INET6;
name6.sin6_addr = in6addr_any;
name6.sin6_port = htons((short)port);
- i = bind(s, (struct sockaddr *)&name6, sizeof(name6));
+ if (!already_binded_port_9875) {
+ i = bind(s, (struct sockaddr *)&name6, sizeof(name6));
+ already_binded_port_9875 = 1;
+ } else {
+ i = 0;
+ fatal = 0;
+ }
#endif
} else {
group = inet_addr(address);
2- Change /usr/include/bits/in.h: Append the following at the end of the file /usr/include/bits/in.h: #define IPV6_V6ONLY 26
3- Change the file mice/common/net_udp.c:
In mice/common/net_udp.c, just above the lines:
s_in.sin6_family = AF_INET6;
s_in.sin6_port = htons(rx_port);
Insert the following:
{
int on = 1;
setsockopt(s->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
}
#endif
4- Start applying the procedure outlined above for compiling and testing sdr.
Salah M. S. Al-Buraiky
Dhahran
May 12, 2004