I recently used your libkeepalive package to help determine if TCP keepalive would resolve a firewall problem we were experiencing.
And yes, it does fix the problem.
However, in the process I found a problem with using the program under Solaris (but will probably occur on other Operating Systems). Specifically the problem arises for one of our programs that uses dlopen/dlsym/dlclose to implement a plugin architecture, before performing socket communications.
The plugin handling code would repeatedly call dlsym until it returned NULL (effectively resolving all the symbols in the library). Notice though that the plugin code did not call dlerror to determine the actual error that occurred.
The subsequent socket call would then attempt to use dlsym to resolve the next socket address - this succeeded however the libkeepalive code then unconditionally calls dlerror. In this case dlerror is returning an error description - from the earlier plugin code.
In my opinion you should not call dlerror, unless the preceding dl* function has indicated that an error occurred. A successful dl* operation does not reset the error information held by dlerror.
I've also modified the code to only call dlsym on the first socket call.
The changes are shown here (and I've uploaded the modified source):
int socket(int domain, int type, int protocol)
{
static int (*libc_socket)(int, int, int) = NULL;
int s, optval;
char *env;
if ( libc_socket == NULL ) {
*(void **)(&libc_socket) = dlsym(RTLD_NEXT, "socket");
if ( libc_socket == NULL ) {
errno = EACCES;
return -1;
}
}
if((s = (*libc_socket)(domain, type, protocol)) != -1) {
if((domain == PF_INET) && (type == SOCK_STREAM)) {
...
Another thing to note for Solaris users is that you need to compile separate versions of libkeepalive for 32 bit and 64 bit programs. I've done so using the Sun cc compiler as shown here. (I guess I could have used gcc as well.)
% cc -o libkeepalive32.so -G -KPIC libkeepalive.c
% cc -o libkeepalive64.so -xtarget=ultra -xarch=v9 -G -KPIC libkeepalive.c
To enable these separate libkeepalive shared libraries, there are separate preload environment variables on Solaris:
% setenv LD_PRELOAD_64 libkeepalive64.so
% setenv LD_PRELOAD_32 libkeepalive32.so
Lastly, if you ever have LD_PRELOAD_32 set in a shell where you intend to run ping/traceroute, then Solaris has specific security checks to prevent setuid programs from using LD_PRELOAD*. I've had to install the keepalive shared library into the "secure" path as per the instructions here (http://bwachter.lart.info/solaris/solfaq.html). By doing so it prevents nasty warnings whenever you run ping/traceroute.
Anyway, I hope this information is useful to yourself and others.
Thanks, Mark
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Modified source that does not use dlerror