chiark / gitweb /
clean up for distribution
[elogind.git] / nss-myhostname.c
1 /* $Id$ */
2
3 /*
4  * This file is part of nss-myhostname.
5  *
6  * nss-myhostname is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * nss-myhostname is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with nss-myhostname; if not, write to the Free
18  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  */
21
22 #include <limits.h>
23 #include <nss.h>
24 #include <sys/types.h>
25 #include <netdb.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <assert.h>
30 #include <unistd.h>
31
32 #define LOCALADDRESS (htonl(0x7F000002))
33
34 static enum nss_status fill_in_hostent(
35     const char *hn,
36     struct hostent *result,
37     char *buffer,
38     size_t buflen,
39     int *errnop,
40     int *h_errnop) {
41
42     size_t l, idx; 
43     char *r_addr, *r_name, *r_aliases, *r_addr_list;
44
45     l = strlen(hn);
46     if (buflen < l+1+sizeof(char*)+4+sizeof(char*)*2) {
47         *errnop = ENOMEM;
48         *h_errnop = NO_RECOVERY;
49         return NSS_STATUS_TRYAGAIN;
50     }
51     
52     r_name = buffer;
53     strcpy(buffer, hn);
54
55     idx = l+1;
56
57     *(char**) (buffer + idx) = NULL;
58     r_aliases = buffer + idx;
59     idx += sizeof(char*);
60     
61     r_addr = buffer + idx;
62     *(uint32_t*) &buffer[idx] = LOCALADDRESS;
63     idx += 4;
64
65     r_addr_list = buffer + idx;
66     * (char**) (buffer + idx) = r_addr;
67     * (((char**) (buffer + idx)) +1)  = NULL;
68     
69     result->h_name = r_name;
70     result->h_aliases = (char**) r_aliases;
71     result->h_addrtype = AF_INET;
72     result->h_length = 4;
73     result->h_addr_list = (char**) r_addr_list;
74
75     return NSS_STATUS_SUCCESS;
76 }
77
78 enum nss_status _nss_myhostname_gethostbyname2_r(
79     const char *name,
80     int af,
81     struct hostent * result,
82     char *buffer,
83     size_t buflen,
84     int *errnop,
85     int *h_errnop) {
86
87     char hn[HOST_NAME_MAX+1];
88
89     assert(errnop);
90     assert(h_errnop);
91
92     if (af == AF_UNSPEC)
93         af = AF_INET;
94
95     if (af != AF_INET) {
96         *errnop = ENOENT;
97         *h_errnop = HOST_NOT_FOUND;
98         return NSS_STATUS_NOTFOUND;
99     }
100
101     if (gethostname(hn, sizeof(hn)-1) < 0) {
102         *errnop = errno;
103         *h_errnop = NO_RECOVERY;
104         return NSS_STATUS_TRYAGAIN;
105     }
106
107     hn[sizeof(hn)-1] = 0;
108
109     if (strcasecmp(name, hn) != 0) {
110         *errnop = ENOENT;
111         *h_errnop = HOST_NOT_FOUND;
112         return NSS_STATUS_NOTFOUND;
113     }
114
115     return fill_in_hostent(hn, result, buffer, buflen, errnop, h_errnop);
116 }
117
118 enum nss_status _nss_myhostname_gethostbyname_r (
119     const char *name,
120     struct hostent *result,
121     char *buffer,
122     size_t buflen,
123     int *errnop,
124     int *h_errnop) {
125
126     return _nss_myhostname_gethostbyname2_r(
127         name,
128         AF_UNSPEC,
129         result,
130         buffer,
131         buflen,
132         errnop,
133         h_errnop);
134 }
135
136 enum nss_status _nss_myhostname_gethostbyaddr_r(
137     const void* addr,
138     int len,
139     int af,
140     struct hostent *result,
141     char *buffer,
142     size_t buflen,
143     int *errnop,
144     int *h_errnop) {
145
146     char hn[HOST_NAME_MAX+1];
147
148     assert(errnop);
149     assert(h_errnop);
150
151     if (af != AF_INET || len < 4 || (*(uint32_t*) addr) != LOCALADDRESS) {
152         *errnop = ENOENT;
153         *h_errnop = HOST_NOT_FOUND;
154         return NSS_STATUS_NOTFOUND;
155     }
156
157     if (gethostname(hn, sizeof(hn)-1) < 0) {
158         *errnop = errno;
159         *h_errnop = NO_RECOVERY;
160         return NSS_STATUS_TRYAGAIN;
161     }
162
163     hn[sizeof(hn)-1] = 0;
164
165     return fill_in_hostent(hn, result, buffer, buflen, errnop, h_errnop);
166 }