Building a Linux Static Binary with sipcalc, CentOS 7, and Docker

First: What is sipcalc?

sipcalc is a handy tool that makes networking a bit less painful, e.g.:

$ sipcalc 192.168.0.0/24
-[ipv4 : 192.168.0.0/24] - 0
[CIDR]
Host address		- 192.168.0.0
Host address (decimal)	- 3232235520
Host address (hex)	- C0A80000
Network address		- 192.168.0.0
Network mask		- 255.255.255.0
Network mask (bits)	- 24
Network mask (hex)	- FFFFFF00
Broadcast address	- 192.168.0.255
Cisco wildcard		- 0.0.0.255
Addresses in network	- 256
Network range		- 192.168.0.0 - 192.168.0.255
Usable range		- 192.168.0.1 - 192.168.0.254
-

As it turns out, there are package installers for various distros of Linux here, and you can even run brew install sipcalc on a Mac.

But what about CentOS 7? Well it turns out that sipcalc is not in the EPEL repository for CentOS 7. (Take a look at EPEL for v6 and EPEL for v7.) Since I want to add this to our jumpbox setup script, I decided that I wanted a static binary that could be run on any Linux system.

Building the binary with the rpmbuild/centos7 Docker image

Environment: latest version of Docker Toolbox on Mac OS X.

Using the rpmbuild/centos7 Docker image for this project and grabbing the sipcalc tarball:

==[]=[ 20:21:33 ]=[  [email protected]  ]=[ ~     ]=[]==
$ docker pull rpmbuild/centos7
Using default tag: latest
latest: Pulling from rpmbuild/centos7
3d8673bd162a: Already exists
a3ed95caeb02: Already exists
fe6f78a62503: Already exists
365f5e11f348: Already exists
Digest: sha256:10a62db594c19a0fc6026cab1492d48ba611a52f5b68c07e33a0da9c6c54e039
Status: Image is up to date for rpmbuild/centos7:latest
==[]=[ 20:21:42 ]=[  [email protected]  ]=[ ~     ]=[]==
$ docker run -it rpmbuild/centos7 /bin/bash
[[email protected] /]$ sudo wget http://www.routemeister.net/projects/sipcalc/files/sipcalc-1.1.6.tar.gz
[[email protected] /]$ tar -xvzf sipcalc-1.1.6.tar.gz && cd sipcalc-1.1.6

The INSTALL file states that we can build and install sipcalc with ./configure && make && make install. So first I’ll try to build the binary by running ./configure && make:

[[email protected] sipcalc-1.1.6]$ ./configure && make
[lengthy output not included]

And now to test the binary:

[[email protected] sipcalc-1.1.6]$ find . -name sipcalc
./src/sipcalc
[[email protected] sipcalc-1.1.6]$ ./src/sipcalc 10.20.30.40/17
-[ipv4 : 10.20.30.40/17] - 0
[CIDR]
Host address		- 10.20.30.40
Host address (decimal)	- 169090600
Host address (hex)	- A141E28
Network address		- 10.20.0.0
Network mask		- 255.255.128.0
Network mask (bits)	- 17
Network mask (hex)	- FFFF8000
Broadcast address	- 10.20.127.255
Cisco wildcard		- 0.0.127.255
Addresses in network	- 32768
Network range		- 10.20.0.0 - 10.20.127.255
Usable range		- 10.20.0.1 - 10.20.127.254
-

Right on we have a working binary! But is it a static binary?

[[email protected] sipcalc-1.1.6]$ ldd src/sipcalc
	linux-vdso.so.1 =>  (0x00007ffc46768000)
	libnsl.so.1 => /lib64/libnsl.so.1 (0x00007fc6c8f5c000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fc6c8b9a000)
	/lib64/ld-linux-x86-64.so.2 (0x000055777a652000)

Nope. The secret sauce:

[[email protected] sipcalc-1.1.6]$ sudo yum install glibc-static
[[email protected] sipcalc-1.1.6]$ CFLAGS=-static ./configure
[[email protected] sipcalc-1.1.6]$ make clean && make
[[email protected] sipcalc-1.1.6]$ ldd src/sipcalc
	not a dynamic executable

Static binary win!

Now to make it even easier with a BASH script! Create an executable script named pkg:

#!/bin/bash
set -e
cd /tmp
curl -LO http://www.routemeister.net/projects/sipcalc/files/sipcalc-1.1.6.tar.gz
tar -xzvf sipcalc-1.1.6.tar.gz
cd sipcalc-1.1.6
sudo yum install -y glibc-static
CFLAGS=-static ./configure
make
sudo cp src/sipcalc /srv/sipcalc

Then start up the Docker container to execute the script and exit:

==[]=[ 21:56:57 ]=[  [email protected]  ]=[ ~     ]=[]==
$ docker run -it -v $PWD:/srv rpmbuild/centos7
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0  93450      0  0:00:01  0:00:01 --:--:-- 93503
sipcalc-1.1.6/
sipcalc-1.1.6/TODO
sipcalc-1.1.6/src/
sipcalc-1.1.6/src/sub.c
...
make[2]: Leaving directory `/tmp/sipcalc-1.1.6/src'
make[2]: Entering directory `/tmp/sipcalc-1.1.6'
make[2]: Leaving directory `/tmp/sipcalc-1.1.6'
make[1]: Leaving directory `/tmp/sipcalc-1.1.6'
==[]=[ 21:57:13 ]=[  [email protected]  ]=[ ~     ]=[]==
$ ls -al | grep sipcalc
-rwxr-xr-x    1 quinn  staff     1058380 Mmm DD 21:57 sipcalc
==[]=[ 21:57:15 ]=[  [email protected]  ]=[ ~     ]=[]==
$ file sipcalc
sipcalc: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, from 'bp', not stripped

Now to test on an Ubuntu Docker container:

==[]=[ 22:00:31 ]=[  [email protected]  ]=[ ~     ]=[]==
$ docker run -it -v $PWD:/srv debuild/precise /srv/sipcalc 10.20.30.40/17
Unable to find image 'debuild/precise:latest' locally
latest: Pulling from debuild/precise
765826873799: Pull complete
e7a187926114: Pull complete
fd01d4f3de3b: Pull complete
c704fce22a3c: Pull complete
a3ed95caeb02: Pull complete
6acafd366a73: Pull complete
8026c6cf1ae4: Pull complete
Digest: sha256:2c14957baab89d6595cd9437f9c9d40c76c23f26ab6ab3c77e04542ca5178cff
Status: Downloaded newer image for debuild/precise:latest
-[ipv4 : 10.20.30.40/17] - 0
[CIDR]
Host address		- 10.20.30.40
Host address (decimal)	- 169090600
Host address (hex)	- A141E28
Network address		- 10.20.0.0
Network mask		- 255.255.128.0
Network mask (bits)	- 17
Network mask (hex)	- FFFF8000
Broadcast address	- 10.20.127.255
Cisco wildcard		- 0.0.127.255
Addresses in network	- 32768
Network range		- 10.20.0.0 - 10.20.127.255
Usable range		- 10.20.0.1 - 10.20.127.254
-

BAM. Linux x86_64 compatible sipcalc static binary.

Spread the word

twitter icon facebook icon linkedin icon