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