]> git.decadent.org.uk Git - nfs-utils.git/blob - support/export/hostname.c
fix unexpiring
[nfs-utils.git] / support / export / hostname.c
1 /*
2  * support/export/hostname.c
3  *
4  * Functions for hostname.
5  *
6  */
7
8 #include "config.h"
9
10 /*
11 #define TEST
12 */
13
14 #include <string.h>
15 #include <netdb.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <stdlib.h>
19 #include <xlog.h>
20 #ifdef TEST
21 #define xmalloc malloc
22 #else
23 #include "xmalloc.h"
24 #include "misc.h"
25 #endif
26
27 #define ALIGNMENT       sizeof (char *)
28
29 static int
30 align (int len, int al)
31 {
32   int i;
33   i = len % al;
34   if (i)
35     len += al - i;
36   return len;
37 }
38
39 struct hostent *
40 get_hostent (const char *addr, int len, int type)
41 {
42   struct hostent *cp;
43   int len_ent;
44   const char *name;
45   int len_name;
46   int num_aliases = 1;
47   int len_aliases = sizeof (char *);
48   int num_addr_list = 1;
49   int len_addr_list = sizeof (char *);
50   int pos;
51   struct in_addr *ipv4;
52
53   switch (type)
54     {
55     case AF_INET:
56       ipv4 = (struct in_addr *) addr;
57       name = inet_ntoa (*ipv4);
58       break;
59
60     default:
61       return NULL;
62     }
63
64   len_ent = align (sizeof (*cp), ALIGNMENT);
65   len_name = align (strlen (name) + 1, ALIGNMENT);
66
67   num_addr_list++;
68   len_addr_list += align (len, ALIGNMENT) + sizeof (char *);
69
70   cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
71                                    + len_addr_list);
72
73   cp->h_addrtype = type;
74   cp->h_length = len;
75   pos = len_ent;
76   cp->h_name = (char *) &(((char *) cp) [pos]);
77   strcpy (cp->h_name, name);
78
79   pos += len_name;
80   cp->h_aliases = (char **) &(((char *) cp) [pos]);
81   pos += num_aliases * sizeof (char *);
82   cp->h_aliases [0] = NULL;
83
84   pos = len_ent + len_name + len_aliases;
85   cp->h_addr_list = (char **) &(((char *) cp) [pos]);
86   pos += num_addr_list * sizeof (char *);
87   cp->h_addr_list [0] = (char *) &(((char *) cp) [pos]);
88   memcpy (cp->h_addr_list [0], addr, cp->h_length);
89   pos += align (cp->h_length, ALIGNMENT);
90   cp->h_addr_list [1] = NULL;
91
92   return cp;
93 }
94
95 struct hostent *
96 hostent_dup (struct hostent *hp)
97 {
98   int len_ent = align (sizeof (*hp), ALIGNMENT);
99   int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT);
100   int num_aliases = 1;
101   int len_aliases = sizeof (char *);
102   int num_addr_list = 1;
103   int len_addr_list = sizeof (char *);
104   int pos, i;
105   char **sp;
106   struct hostent *cp;
107
108   for (sp = hp->h_aliases; sp && *sp; sp++)
109     {
110       num_aliases++;
111       len_aliases += align (strlen (*sp) + 1, ALIGNMENT)
112                      + sizeof (char *);
113     }
114
115   for (sp = hp->h_addr_list; *sp; sp++)
116     {
117       num_addr_list++;
118       len_addr_list += align (hp->h_length, ALIGNMENT)
119                        + sizeof (char *);
120     }
121   
122   cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
123                                    + len_addr_list);
124
125   *cp = *hp;
126   pos = len_ent;
127   cp->h_name = (char *) &(((char *) cp) [pos]);
128   strcpy (cp->h_name, hp->h_name);
129
130   pos += len_name;
131   cp->h_aliases = (char **) &(((char *) cp) [pos]);
132   pos += num_aliases * sizeof (char *);
133   for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++)
134     if (sp && *sp)
135       {
136         cp->h_aliases [i] = (char *) &(((char *) cp) [pos]);
137         strcpy (cp->h_aliases [i], *sp);
138         pos += align (strlen (*sp) + 1, ALIGNMENT);
139       }
140     else
141       cp->h_aliases [i] = NULL;
142
143   pos = len_ent + len_name + len_aliases;
144   cp->h_addr_list = (char **) &(((char *) cp) [pos]);
145   pos += num_addr_list * sizeof (char *);
146   for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++)
147     if (*sp)
148       {
149         cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]);
150         memcpy (cp->h_addr_list [i], *sp, hp->h_length);
151         pos += align (hp->h_length, ALIGNMENT);
152       }
153     else
154       cp->h_addr_list [i] = *sp;
155
156   return cp;
157 }
158
159 static int
160 is_hostname(const char *sp)
161 {
162   if (*sp == '\0' || *sp == '@')
163     return 0;
164
165   for (; *sp; sp++)
166     {
167       if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/')
168         return 0;
169       if (*sp == '\\' && sp[1])
170         sp++;
171     }
172
173   return 1;
174 }
175
176 int
177 matchhostname (const char *h1, const char *h2)
178 {
179   struct hostent *hp1, *hp2;
180   int status;
181
182   if (strcasecmp (h1, h2) == 0)
183     return 1;
184
185   if (!is_hostname (h1) || !is_hostname (h2))
186     return 0;
187
188   hp1 = gethostbyname (h1);
189   if (hp1 == NULL)
190     return 0;
191
192   hp1 = hostent_dup (hp1);
193
194   hp2 = gethostbyname (h2);
195   if (hp2)
196     {
197       if (strcasecmp (hp1->h_name, hp2->h_name) == 0)
198         status = 1;
199       else
200         {
201           char **ap1, **ap2;
202
203           status = 0;
204           for (ap1 = hp1->h_addr_list; *ap1 && status == 0; ap1++)
205             for (ap2 = hp2->h_addr_list; *ap2; ap2++)
206               if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0)
207                 {
208                   status = 1;
209                   break;
210                 }
211         }
212     }
213   else
214     status = 0;
215
216   free (hp1);
217   return status;
218 }
219
220
221 /* Map IP to hostname, and then map back to addr to make sure it is a
222  * reliable hostname 
223  */
224 struct hostent *
225 get_reliable_hostbyaddr(const char *addr, int len, int type)
226 {
227         struct hostent *hp;
228
229         char **sp;
230         struct hostent *forward = NULL;
231         char *tmpname;
232
233         hp = gethostbyaddr(addr, len , type);
234         if (!hp)
235                 return hp;
236
237         /* must make sure the hostent is authorative. */
238
239         hp = hostent_dup (hp);
240         tmpname = xstrdup((hp)->h_name);
241         if (tmpname) {
242                 forward = gethostbyname(tmpname);
243                 free(tmpname);
244         }
245         if (forward) {
246                 /* now make sure the "addr" is in the list */
247                 for (sp = forward->h_addr_list ; *sp ; sp++) {
248                         if (memcmp(*sp, addr, forward->h_length)==0)
249                                 break;
250                 }
251                 
252                 if (!*sp) {
253                         /* it was a FAKE */
254                         xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't match reverse",
255                              forward->h_name, inet_ntoa(*(struct in_addr*)addr));
256                         return NULL;
257                 }
258                 free (hp);
259                 hp = hostent_dup (forward);
260         }
261         else {
262                 /* never heard of it. misconfigured DNS? */
263                 xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't exist",
264                      forward->h_name, inet_ntoa(*(struct in_addr*)addr));
265                 return NULL;
266         }
267         return hp;
268 }
269
270
271 #ifdef TEST
272 void
273 print_host (struct hostent *hp)
274 {
275   char **sp;
276
277   if (hp)
278     {
279       printf ("official hostname: %s\n", hp->h_name); 
280       printf ("aliases:\n");
281       for (sp = hp->h_aliases; *sp; sp++)
282         printf ("  %s\n", *sp);
283       printf ("IP addresses:\n");
284       for (sp = hp->h_addr_list; *sp; sp++)
285         printf ("  %s\n", inet_ntoa (*(struct in_addr *) *sp));
286     }
287   else
288     printf ("Not host information\n");
289 }
290
291 int
292 main (int argc, char **argv)
293 {
294   struct hostent *hp = gethostbyname (argv [1]);
295   struct hostent *cp;
296   struct in_addr addr;
297
298   print_host (hp);
299
300   if (hp)
301     {
302       cp = hostent_dup (hp);
303       print_host (cp);
304       free (cp);
305     }
306   printf ("127.0.0.1 == %s: %d\n", argv [1],
307           matchhostname ("127.0.0.1", argv [1]));
308   addr.s_addr = inet_addr(argv [2]);
309   printf ("%s\n", inet_ntoa (addr));
310   cp = get_hostent ((const char *)&addr, sizeof(addr), AF_INET);
311   print_host (cp);
312   return 0;
313 }
314 #endif