/* * The idea of this is to get a program that tries to resolve one name, * to resolve another instead. This is just so that programs that do not support SRV yet * can be tricked into connecting properly. * * compile with: gcc -Wall -shared -o libdivert.so libdivert.c -ldl -fPIC * usage: env LD_PRELOAD=libdivert.so LD_LIBRARY_PATH=. /path/to/program */ #include #include #include #include #include #include #define RTLD_NEXT ((void*)(-1l)) extern int h_errno; static const char* divert(const char* name) { /* fprintf(stderr, "Resolving a name with getaddrinfo %s and service %s \n", node, service); */ char* next; next = getenv(name); if (next != NULL) { return next; } return name; } /* This hooks into any call to getaddrinfo by the target program * if it tries to resolve a trapped name, we have it resolve something else. */ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { int (*real_getaddrinfo)(const char*, const char*, const struct addrinfo *, struct addrinfo **); real_getaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo"); return (*real_getaddrinfo)(divert(node), service, hints, res); } int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { int (*real_gethostbyname_r)(const char*, struct hostent*, char *, size_t, struct hostent**, int*); real_gethostbyname_r = dlsym(RTLD_NEXT, "gethostbyname_r"); return (*real_gethostbyname_r)(divert(name), ret, buf, buflen, result, h_errnop); } struct hostent* gethostbyname(const char *name) { struct hostent* (*real_gethostbyname)(const char*); real_gethostbyname = dlsym(RTLD_NEXT, "gethostbyname"); return (*real_gethostbyname)(divert(name)); } int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, socklen_t hostlen, char* serv, socklen_t servlen, unsigned int flags) { int (*real_getnameinfo)(const struct sockaddr*, socklen_t, char*, socklen_t, char*, socklen_t, unsigned int); real_getnameinfo = dlsym(RTLD_NEXT, "getnameinfo"); return (*real_getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags); }