Problem Solving

These are actual examples of source code being compiled and generating problems. This will provide some ideas in how to solve problems with sources that won't compile. Many of the problems are unique to using the older headers instead of the newer ones.

Scenario #1: Echo Security Scanner

In this case, the problem turned out to be something more than just header files. In compiling ess (echo Security Scanner), several problems were seen. They will be taken one at a time.

tcp_gen.c: In function `tcp_gen':
		tcp_gen.c:47: structure has no member named `th_sport'
		tcp_gen.c:48: structure has no member named `th_dport'
		tcp_gen.c:50: structure has no member named `th_seq'
		tcp_gen.c:51: structure has no member named `th_ack'
		tcp_gen.c:56: structure has no member named `th_off'
		tcp_gen.c:57: structure has no member named `th_x2'
		tcp_gen.c:60: structure has no member named `th_win'
		tcp_gen.c:62: structure has no member named `th_flags'
		tcp_gen.c:62: `TH_SYN' undeclared (first use this function)
		tcp_gen.c:62: (Each undeclared identifier is reported only once
		tcp_gen.c:62: for each function it appears in.)
		tcp.c: In function `syn2port':
		tcp.c:95: structure has no member named `th_sum'

This is apparently because there is no TH_SYN defined in the header files. So the first step is to determine where TH_SYN is defined in the Linux header files. Looking for the definition turns this up:

# cd /usr/i386-glibc20-linux/include
		# grep -l "TH_SYN" * */* 2>/dev/null
		netinet/tcp.h

Notice the directory used for the include files; if /usr/include is used instead, problems will result if the installed version of glibc isn't 2.0. In most modern Red Hat distributions, glibc 2.0 is not used.

To fix these errors, it is necessary to find out why the desired files are not being included. This may be because the proper include directory is not being included, or because the proper subdirectory is not being included. The appropriate source files must be examined to see. Checking tcp_gen.c turns up this portion of code:

#if defined(LINUX)
		#include <linux/tcp.h>
		#else
		#include <netinet/tcp.h>
		#endif

Presumably (since this is a Linux system) LINUX is defined, and thus the header file is being looked for in linux/tcp.h and not netinet/tcp.h. Changing the source code to use netinet/tcp.h doesn't help.

Next, check netinet/tcp.h and see what the actual definition or usage of TH_SYN was. It appears within a #ifdef ... #else ... #endif block — so it would appear it depends on __FAVOR_BSD being set (which is the variable which is tested). So edit the Makefile of the source to reflect this — since this program uses GNU autoconfigure, the proper file to edit is actually Makefile.in (or changes will be lost after a configure is run!). Thus, a line is changed to define __FAVOR_BSD:

CC = @CC@ @DEFS@ -D_REENTRANT -DLINUX -D__FAVOR_BSD

Now, rerun configure and check the results. In this case, nothing's changed. In the file netinet/tcp.h, there is another #ifdef ... #endif block which prevents defining things more than once. Perhaps this is the problem. To test for it, change the source code so netinet/tcp.h is used early on.

Making this change does not fix it. However, checking the Makefile (again) makes one realize that in this source tree, the variable CC actually holds some of the options to gcc (!), and CC is being replaced by only the alternate C compiler without options. Recompiling without the -e option to make (which causes the CC variable to be overridden) — and this time it seems to work. It also solves several other problems at the same time, and now results in a working binary.

Scenario #2: axfer

Compiling axfer generates this error:

i386-glibc20-linux-gcc -g -O2  -o axfr  axfr.o error.o getopt.o getopt1.o getaxfr.o
		/usr/lib/libresolv.a zlib-1.1.2/libz.a
		/usr/lib/libresolv.a(res_send.o): In function `__res_send':
		/usr/src/bs/BUILD/glibc-2.1.3/resolv/res_send.c:642: undefined reference to `__poll'
		collect2: ld returned 1 exit status

A important piece of information is here: the reference to /usr/src/bs/BUILD/glibc-2.1.3. It seems likely that /usr/lib/libresolv.a (the resolver library — static version) should not be used, but rather one in /usr/i386-glibc20-linux/lib. Checking there:

# ls -1 /usr/i386-glibc20-linux/lib/*resolv*
		/usr/i386-glibc20-linux/lib/libresolv-2.0.7.so
		/usr/i386-glibc20-linux/lib/libresolv.so
		/usr/i386-glibc20-linux/lib/libresolv.so.2

Note that these are dynamic libraries, not static. Since these do exist here, it is necessary to check whether the /usr/i386-glibc20-linux/lib libraries are being checked for first, before others. Since this source tree uses autoconfig, the file Makefile.in needs to be checked instead of Makefile. Checking the file, a hard-coded reference to /usr/lib/libresolv.a is found in two lines:

LDADD = /usr/lib/libresolv.a zlib-1.1.2/libz.a
		axfr_DEPENDENCIES = /usr/lib/libresolv.a zlib-1.1.2/libz.a

It is also worth noting that the version of zlib is also hard-coded here. This is almost okay, since it is included in the distribution; however, it means that a more recent version of the library will not be used.

The references to /usr/lib/libresolv.a must be removed. Since these variables appear to be for use with the linker and only specify static libraries, and the dynamic libresolv library is included on most systems, including LRP systems, the library reference is simply removed from the line.

Now there are errors like (abbreviated):

i386-glibc20-linux-gcc -g -O2  -o axfr  axfr.o error.o getopt.o getopt1.o getaxfr.o 
		zlib-1.1.2/libz.a getaxfr.o: In function `gzp_fqname':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:86: undefined reference to 
		`__p_fqnname' getaxfr.o: In function `short_prr':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:231: undefined reference to 
		`__p_fqnname' getaxfr.o: In function `do_rrset':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:395: undefined reference to 
		`__dn_skipname'
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:399: undefined reference to 
		`_getshort' getaxfr.o: In function `setnslistfordomain':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:432: undefined reference to 
		`res_mkquery' /pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:438: 
		getaxfr.o: In function `sp_fqnname':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:517: undefined reference to 
		`dn_expand' getaxfr.o: In function `printZone':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:632: undefined reference to 
		`res_mkquery'
		getaxfr.o: In function `printRR':
		/pub/oxygen/src/net/diags/axfer/axfr-0.5.2/getaxfr.c:831: undefined reference to 
		`__dn_skipname'

First thing is to find out where these functions are defined. The library libresolv is immediately suspect, since we were working with it — so start there:

# cd /usr/i386-glibc20-linux/lib
		# nm libresolv.so | grep getshort
		000036e0 T _getshort

Doesn't look like libresolv is being referenced. Check Makefile.in and make sure there is a -lresolv option to the C compiler during its link phase. According to make's output there isn't; so add it (to LDFLAGS in this case). It also turns out that axfr is built using axfr_LDFLAGS which does not contain LDFLAGS, so adjust that.

This time it compiles just fine. The libresolv.so dynamic library is referenced, and all symbols are resolved.