Commit c16563f2 authored by Vincent Pelletier's avatar Vincent Pelletier

Initial commit.

parents
This diff is collapsed.
CFLAGS=-Wall --pedantic
all: libuserhosts.so
libuserhosts.so: userhosts.c
gcc -ldl -shared -fPIC $(CFLAGS) $< -o $@
userhosts - Redirects accesses to /etc/hosts to another file.
Rationale
---------
The need is to customise hostname (reverse )resolution for a single process
(and potentially its children), potentially resolving conflicting domain names
to different addresses and vice-versa.
libnss' HOSTALIASES feature only allows mapping between domain names, not
between names and addresses, so it is not powerful enough.
Limitations
-----------
This library relies on LD_PRELOAD mechanism, so it inherits its limitations
(it will not work on suid binaries, ...).
Requirements
------------
- make
- gcc (source uses __attribute__)
- glibc (source uses RTLD_NEXT)
Building
--------
Just run "make".
Usage
-----
$ env HOSTS=/path/to/custom/hosts LD_PRELOAD=/path/to/libuserhosts.so <command>
/* userhosts - redirect access to /etc/hosts to another file */
/*
* Copyright (C) 2014 Vincent Pelletier <vincent@nexedi.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Needed for RTLD_NEXT */
#define _GNU_SOURCE
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <fcntl.h>
#define ORIGINAL_HOSTS_PATH "/etc/hosts"
static int (*original_open)(const char *, int, ...);
static FILE *(*original_fopen)(const char *, const char *);
static const char *replacement_hosts;
/* Call dlsym(RTLD_NEXT, name), abort()'ing with informative message to
* stderr if it cannot be found. */
static inline void *dlsym_or_abort(const char *name) {
char *error;
void *symbol;
dlerror(); /* Clear any previous error */
if (NULL == (symbol = dlsym(RTLD_NEXT, name)) && (error = dlerror())) {
fprintf(stderr, "Error loading '%s': %s\n", name, error);
abort();
}
return symbol;
}
static void __attribute__ ((constructor)) init(void) {
*(void **)(&original_open) = dlsym_or_abort("open");
*(void **)(&original_fopen) = dlsym_or_abort("fopen");
replacement_hosts = getenv("HOSTS");
if (replacement_hosts == NULL)
/* XXX: warn ? fallback on $HOME/???/hosts ? */
replacement_hosts = ORIGINAL_HOSTS_PATH;
}
int open(const char *__file, int __oflag, ...) {
if(strcmp(__file, ORIGINAL_HOSTS_PATH) == 0)
__file = replacement_hosts;
if (__oflag & (O_CREAT | O_TMPFILE)) {
va_list ap;
mode_t mode;
va_start(ap, __oflag);
mode = va_arg(ap, mode_t);
va_end(ap);
return (*original_open)(__file, __oflag, mode);
}
return (*original_open)(__file, __oflag);
}
FILE *fopen(const char *path, const char *mode) {
if (strcmp(path, ORIGINAL_HOSTS_PATH) == 0)
path = replacement_hosts;
return (*original_fopen)(path, mode);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment