Ethereal-dev: [ethereal-dev] The next Ethereal release might not have the Red Hat 6.2 SNMP lib

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Fri, 16 Jun 2000 23:22:37 -0700
Well, I finally said "enough is enough" and put in the "dlopen()" hack I
may have spoken of in previous threads on this topic.  I realized that I
didn't actually have to install any Red Hat releases to test it - I
could just install various versions of UCD SNMP on my Debian 2.1
partition, and that should at least let me get it working.

Thus, the next release of Ethereal *should*, if built on a Red Hat
release prior to 6.2, work on 6.2.

(In the process of testing it, I also decided that the way it displays
OIDs if you call "snmp_set_suffix_only(2)" may be better than the way it
display sthem if you call "snmp_set_full_objid()", or even if you don't
- it displays, for example, the OID 1.3.6.1.2.1.1.1.1.1 as
"SNMPv2-MIB:sysDescr.1.1" rather than
".iso.org.dod.internet.mgmt.mib-2.system.sysDescr.1.1".

The former may make it easier to find which RFC, or whatever, describes
the object in question.

This is why I refer to "snmp_set_suffix_only()" and "ds_set_int()",
rather than to "snmp_set_full_objid()" and "ds_set_boolean()", below.)

The hack uses a trick similar to one I've seen mentioned as used in
Windows applications to let you build binaries that run on many
different versions of Windows 9x and Windows NT, that use features
present on later versions if run on those later versions, but that avoid
calling, when run on older versions, routines not present on those older
versions.

I.e., we load "libsnmp.so" with "dlopen()", and call "dlsym()" to try to
find "snmp_set_suffix_only()"; if we don't find it, we make the
appropriate call to "ds_set_int()" instead.

We do this only on Linux, for now, as we've only seen the problem on Red
Hat; it may show up on other OSes that bundle UCD SNMP, or on OSes where
it's not bundled but for which binary packages are built that link
against a shared version of the UCD SNMP library.  If we run into one of
those, we can do this under those OSes as well, *if* "dlopen()" makes
the run-time linker use the same search rules as it uses when loading
libraries with which the application is linked.

(Perhaps we could use the GLib wrappers for run-time linking, *if*
they're thin enough; however, as this code is currently used only on
Linux, we don't worry about that for now.)

When calling "ds_set_int()" directly, we do *not* use DS_LIBRARY_ID or
DS_LIB_PRINT_SUFFIX_ONLY by name, so that we don't require that Ethereal
be built with versions of UCD SNMP that include that value; instead, we
use their values in UCD SNMP 4.1.1, which are 0 and 4, respectively.  On
most versions of UCD SNMP, we shouldn't call "ds_set_int()" directly, as
only 4.1.1 lacks "snmp_set_suffix_only()" but has "ds_set_int()", so
hardcoding the numeric values from 4.1.1 should be OK.

I configured and compiled the current CVS tree with UCD SNMP 4.0.1
installed (built with "--enable-shared", and with a fix to the
"configure" script, from 4.1.1, to correctly set, on Linux, the commands
to build shared libraries), and then installed UCD SNMP 4.1.1; the
program ran with the 4.0.1 shared library, but failed in the usual
fashion with the 4.1.1 shared library.

With the hack in place, I re-installed 4.0.1 and reconfigured and
rebuilt; the resulting binary worked both with the 4.0.1 and 4.1.1
shared libraries, and displayed stuff the same way (i.e., the
appropriate OID-display setting was done with both libraries, that being
the setting that the offending call attempts to change.)

I also successfully built a purely statically-linked Tethereal
(building a purely statically-liked Ethereal would have required me to
dig up a static "-lXext" from my Debian CDs), and removed the UCD SNMP
shared library; that worked as well, so I don't appear to have broken
statically-linked binaries (although note that a statically-linked
binary, on a system that has a UCD SNMP shared library installed, will
call the offending routine as it appears in the shared library, which
may or may not do the right thing; I don't know of any way to detect,
from within the program, whether it was statically linked with the UCD
SNMP library, and thus don't know any way to keep it from "dlopen()"ing
the shared library and getting pointers to the routines in that library
and calling them if the program wasn't originally dynamically linked
with the UCD SNMP library).

NOTE: I have not tried this on any libc5 system, as I don't have one. 
Hopefully, the dynamic-loading code should work.