summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--nss-myhostname.c164
2 files changed, 177 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..9301fab9f2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CFLAGS=-Wall -pipe -W -O2 -Wextra -Wno-unused-parameter
+
+libnss_myhostname.so.2: nss-myhostname.o
+ $(CC) -shared -o $@ -Wl,-soname,$@ $^
+ strip $@
+
+install:
+ install -D -g root -m 644 -o root -s -v libnss_myhostname.so.2 /usr/lib/libnss_myhostname.so.2
+
+clean:
+ rm -f *.o *~ libnss_myhostname.so.2
+
+.PHONY: clean
diff --git a/nss-myhostname.c b/nss-myhostname.c
new file mode 100644
index 0000000000..a459fd0ea0
--- /dev/null
+++ b/nss-myhostname.c
@@ -0,0 +1,164 @@
+/*
+ * This file is part of nss-myhostname.
+ *
+ * nss-myhostname 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.
+ *
+ * nss-myhostname 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 nss-myhostname; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <nss.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+
+#define LOCALADDRESS (htonl(0x7F0002))
+
+static enum nss_status fill_in_hostent(
+ const char *hn,
+ struct hostent *result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ size_t l, idx;
+ char *r_addr, *r_name, *r_aliases, *r_addr_list;
+
+ l = strlen(hn);
+ if (buflen < l+1+sizeof(char*)+4+sizeof(char*)*2) {
+ *errnop = ENOMEM;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ r_name = buffer;
+ strcpy(buffer, hn);
+
+ idx = l+1;
+
+ *(char**) (buffer + idx) = NULL;
+ r_aliases = buffer + idx;
+ idx += sizeof(char*);
+
+ r_addr = buffer + idx;
+ *(uint32_t*) &buffer[idx] = LOCALADDRESS;
+ idx += 4;
+
+ r_addr_list = buffer + idx;
+ * (char**) (buffer + idx) = r_addr;
+ * (((char**) (buffer + idx)) +1) = NULL;
+
+ result->h_name = r_name;
+ result->h_aliases = (char**) r_aliases;
+ result->h_addrtype = AF_INET;
+ result->h_length = 4;
+ result->h_addr_list = (char**) r_addr_list;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status _nss_hostname_gethostbyname2_r(
+ const char *name,
+ int af,
+ struct hostent * result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ char hn[HOST_NAME_MAX+1];
+
+ assert(errnop);
+ assert(h_errnop);
+
+ if (af == AF_UNSPEC)
+ af = AF_INET;
+
+ if (af != AF_INET) {
+ *errnop = ENOENT;
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ if (gethostname(hn, sizeof(hn)-1) < 0) {
+ *errnop = errno;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ hn[sizeof(hn)-1] = 0;
+
+ if (strcasecmp(name, hn) != 0) {
+ *errnop = ENOENT;
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ return fill_in_hostent(hn, result, buffer, buflen, errnop, h_errnop);
+}
+
+enum nss_status _nss_hostname_gethostbyname_r (
+ const char *name,
+ struct hostent *result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ return _nss_hostname_gethostbyname2_r(
+ name,
+ AF_UNSPEC,
+ result,
+ buffer,
+ buflen,
+ errnop,
+ h_errnop);
+}
+
+enum nss_status _nss_hostname_gethostbyaddr_r(
+ const void* addr,
+ int len,
+ int af,
+ struct hostent *result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ char hn[HOST_NAME_MAX+1];
+
+ assert(errnop);
+ assert(h_errnop);
+
+ if (af != AF_INET || len != 4 || (*(uint32_t*) addr) != LOCALADDRESS) {
+ *errnop = ENOENT;
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ if (gethostname(hn, sizeof(hn)-1) < 0) {
+ *errnop = errno;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ hn[sizeof(hn)-1] = 0;
+
+ return fill_in_hostent(hn, result, buffer, buflen, errnop, h_errnop);
+}