[Bro] Notes on compiling bro for Linksys
Jim Mellander
jmellander at lbl.gov
Tue Jul 26 14:38:17 PDT 2005
Here's a log of my cross-compiling effort of the latest public Bro
distribution to run on a linksys wireless router using the openwrt.org
distribution. The goal here was not to cross compile the whole bro
environment, but to create a bro binary that will function as expected
on the box. The scripts, etc. are copied over from a working installation.
The log appears to be one interrupted path of forward progress, whereas
in reality, there were numerous false starts, blind alleys,
head-scratching, and dumb luck involved.
Hopefully, this will be of use to others attempting porting, etc. to odd
platforms. BTW the shell used is bash, if you're using another one, YMMV
Still to be compiled are utilities (cf, etc.)
======================================================================
1. Download latest bro 0.9a9 from broids.org
2. compile for host system (linux) and save compiled program 'bifcl' away
3. delete tree & recreate from tarball (all we wanted from step 2 was bifcl)
4. Download openwrt buildroot, see
http://downloads.openwrt.org/docs/buildroot-documentation.html
5. Build in home directory - we are really just interested in the
cross-compile toolkit. (note: you may need to be running GNU Make 3.80,
older versions sometimes fail - OTOH, this version fails in different
ways - I compiled & put v3.80 in /usr/local/bin, the original make on my
distro is 3.79.1 - so if strange make problems occur, try modifying PATH
so that other make is found first). Note that only the cross compile
tools in openwrt/staging_dir_mipsel/bin really need to be built, as well
as the uclibc stuff (all should be there if you got thru most of the
compile)
6. Set PATH to have <basedir>/openwrt/staging_dir_mipsel/bin before
other stuff, so cross compile will work. Go into that directory and run:
for i in mipsel-linux-*; do ln -s $i `echo $i|sed s/mipsel-linux-//`; done
to create gcc, etc. links (running the above probably isn't really
necessary.)
7. go into bro directory
8. execute ./configure --build=mipsel-linux to perform cross-compile
configure
9. Go into src directory, edit Makefile, comment out stuff unpacking &
building libedit, edit ../config.h, uncomment line: #undef HAVE_READLINE
10. copy back in previously compiled bifcl
11. Now we a going to need libpcap - so create a new directory &
download libpcap-0.8.3.tar.gz to it. unpack & go into libpcap-0.8.3
11a. Remember that PATH still needs to have the cross compile tools
before compiling,etc.
12. execute:
ac_cv_linux_vers=2 ./configure --host=mipsel-linux --with-pcap=linux
to perform cross-compile configure
13. run make, should complete, and produce a libpcap.a
14. copy libpcap.a and *.h to bro src directory
15. go back into bro src directory, edit Makefile, modify INCLS and LIBS
as follows:
Original:
INCLS = -I${top_srcdir}/linux-include -I${top_srcdir}/aux/libpcap-0.7.2
LIBS = $(LIBEDIT_LIBS) $(LIBIDMEF_LIBS)
-L${top_srcdir}/aux/libpcap-0.7.2 -lpcap -lresolv -ltermcap -lm
New:
INCLS = -I${top_srcdir}/linux-include -I${top_srcdir}/src
LIBS = $(LIBEDIT_LIBS) $(LIBIDMEF_LIBS) -L${top_srcdir}/src -lpcap
-lresolv -ltermcap -lm
16. Now remember, you've copied in the precompiled bifcl
17. Edit SerialObj.h add line
#define SIZEOF_LONG_LONG 8
before message squawking about it.
18. more modifications to Makefile:
CFLAGS = -g -O2 -DRETSIGTYPE=void -DRETSIGVAL=""
CXXFLAGS = -g -O2 -DRETSIGTYPE=void -DRETSIGVAL="" -static
19. In util.cc need gettimeofday() - modified code to just use /dev/urandom
Orig:
// Gather up some entropy.
gettimeofday((struct timeval *)(buf + pos), 0);
pos += sizeof(struct timeval) / sizeof(uint32);
#if defined(O_NONBLOCK)
int fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
#elif defined(O_NDELAY)
int fd = open("/dev/random", O_RDONLY | O_NDELAY);
#else
int fd = open("/dev/random", O_RDONLY);
#endif
New:
// Gather up some entropy.
int fd = open("/dev/urandom", O_RDONLY);
19a. Change util.cc to always include sys/time.h - previous change not
necessary, but not problematic either.
20 Compile continues until final link, then get error message:
ld: cannot find -ledit
which indicates looking for libedit which we (supposedly) disabled -
edit Makefile, change LIBS, per below:
#LIBS = $(LIBEDIT_LIBS) $(LIBIDMEF_LIBS) -L${top_srcdir}/src -lpcap
-lresolv -ltermcap -lm
LIBS = $(LIBIDMEF_LIBS) -L${top_srcdir}/src -lpcap -lresolv -ltermcap -lm
Next error, cannot find -ltermcap, solution: take out of LIBS above
Next error, missing Bind functions:
nb_dns.o(.text+0x3f0): In function `_nb_dns_mkquery':
/tmp/bro-0.9a9/src/nb_dns.c:293: undefined reference to `__res_mkquery'
nb_dns.o(.text+0x9b4): In function `nb_dns_activity':
/tmp/bro-0.9a9/src/nb_dns.c:476: undefined reference to `__ns_initparse'
nb_dns.o(.text+0xb9c):/tmp/bro-0.9a9/src/nb_dns.c:519: undefined
reference to `_ns_flagdata'
nb_dns.o(.text+0xc94):/tmp/bro-0.9a9/src/nb_dns.c:561: undefined
reference to `__ns_parserr'
21. Since these are name server functions, download BIND 9.3.1 source
from http://www.isc.org/index.pl?/sw/bind/ to separate directory.
go into lib/bind, run:
./configure --host=mipsel-linux --enable-threads
--with-randomdev=/dev/urandom
run make until error,
go into each subdir
run make until error
22. Now lets see if we have enough compiled to resolve the undefined
symbols:
$ find . -name '*.o'|xargs egrep -i
'res_mkquery|ns_initparse|ns_flagdata|ns_parserr' /dev/null
Binary file ./nameser/ns_parse.o matches
$ nm ./nameser/ns_parse.o
U __dn_expand
U __dn_skipname
U __errno_location
U _gp_disp
U memset
00000000 D _ns_flagdata
000001a8 T __ns_initparse
00000000 T __ns_msg_getflag
00000384 T __ns_parserr
00000044 T __ns_skiprr
00000174 t setsection
cp /home/jmel/bind/bind-9.3.1/lib/bind/nameser/ns_parse.o /tmp/bro-0.9a9/src
Add ns_parse.o to LIBS in Makefile
Now tackling res_mkquery, source is in lib/bind/resolv, make fails:
/home/jmel/bind/bind-9.3.1/lib/bind/port_after.h:384: error: conflicting
types for 'getnetgrent_r'
./../include/netdb.h:528: error: previous declaration of 'getnetgrent_r'
was here
in ../include/netdb.h getnetgrent_r is defined here:
#ifdef __GLIBC__
int getnetgrent_r __P((char **, char **, char **, char *,
size_t));
#endif
Disable definition by wrapping in #if 0 / #endif
Compiled far enough to compile res_mkquery, so copy res_mkquery.o to
bro/src directory, and add to LIBS
I actually ended up going into the top level directory of the bind build
tree, and running
ar rs libbind.a `find . -name '*.o' -print`
ranlib libbind.a
then copy into the bro/src directory, and add -lbind to LIBS
Compile still fails, with missing pthread stuff, so:
Building dietlibc
20. pthread & friends can be gotten from another small C library:
dietlibc, so download dietlibc-0.29 (search web for location) and
compile in its own dir by:
make -n ARCH=mipsel CROSS=mipsel-linux- all >x
edit x and globallly remove -fno-pic
Also, globally modify -Os to -O0
Then 'sh x'
(These steps are necessary to ensure that the code is PIC, which is how
Bro is compiled, and to turn off optimization, which is buggy)
cd bin-mipsel
ar rs libdiet.a *.o
ranlib libdiet.a
Then copy libdiet.a to bro/src directory, and add to LIBS in Makefile
When make is run in bro/src directory, errors in linking are:
Func.o(.text+0x8798): In function `bro_system(ValPList*)':
/tmp/bro-0.9a9/src/bro.bif:1138: warning: warning: system() is a
security risk. Use fork and execvp instead!
../src/libdiet.a(vfscanf.o)(.text+0x24): In function `vfscanf':
vfscanf.c: warning: warning: the scanf functions add several kilobytes
of bloat.
../src/libdiet.a(vprintf.o)(.text+0x68): In function `vprintf':
vprintf.c: warning: warning: the printf functions add several kilobytes
of bloat.
../src/libdiet.a(abort.o)(.text+0x8): In function `abort':
abort.c: undefined reference to `__stdio_flushall'
../src/libdiet.a(fclose.o)(.text+0x34): In function `fclose_unlocked':
fclose.c: undefined reference to `__stdio_root'
../src/libdiet.a(fclose.o)(.text+0x38):fclose.c: undefined reference to
`__stdio_root'
../src/libdiet.a(fclose.o)(.text+0x84):fclose.c: undefined reference to
`__stdio_root'
../src/libdiet.a(fgetc_unlocked.o)(.text+0x58): In function
`fgetc_unlocked':
fgetc_unlocked.c: undefined reference to `__fflush4'
../src/libdiet.a(fputc_unlocked.o)(.text+0x24): In function
`fputc_unlocked':
fputc_unlocked.c: undefined reference to `__fflush4'
../src/libdiet.a(pthread_sys_alloc.o)(.text+0x68): In function `free':
pthread_sys_alloc.c: undefined reference to `__libc_free'
../src/libdiet.a(pthread_sys_alloc.o)(.text+0x148): In function `malloc':
pthread_sys_alloc.c: undefined reference to `__libc_malloc'
../src/libdiet.a(pthread_sys_alloc.o)(.text+0x23c): In function `realloc':
pthread_sys_alloc.c: undefined reference to `__libc_realloc'
../src/libdiet.a(pthread_sys_sigsuspend.o)(.text+0x28): In function
`sigsuspend':
pthread_sys_sigsuspend.c: undefined reference to `__libc_sigsuspend'
../src/libdiet.a(localtime_r.o)(.text+0x14): In function `localtime_r':
localtime_r.c: undefined reference to `__maplocaltime'
../src/libdiet.a(localtime_r.o)(.text+0x2c):localtime_r.c: undefined
reference to `__tzfile_map'
So, lets just delete some functions from the library, go back in
dietlibc directory, then into bin/mipsel, then delete the following files:
vfscanf.o
vprintf.o
abort.o
fclose.o
fgetc_unlocked.o
fputc_unlocked.o
pthread_sys_alloc.o
pthread_sys_sigsuspend.o
localtime_r.o
pthread_fgetc.o
inet_ntoa_r.o
getopt_data.o
delete libdiet.a, then rebuild libdiet.a as indicated above, copy back
into bro/src directory, run make
BTW- Final LIBS in Makefile is:
LIBS = $(LIBIDMEF_LIBS) -L${top_srcdir}/src -lpcap -lresolv -lm -lbind
-ldiet
Bro compiles!!
$ ls -l bro
-rwxrwxr-x 1 jmel jmel 10562750 Jul 26 14:23 bro
$ strip bro
$ ls -l bro
-rwxrwxr-x 1 jmel jmel 2722728 Jul 26 14:23 bro
--
Jim Mellander
Incident Response Manager
Computer Protection Program
Lawrence Berkeley National Laboratory
(510) 486-7204
Your fortune for today is:
You may be recognized soon. Hide.
More information about the Bro
mailing list