]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/statd/hostname.c
3d10d6f1fa1f59e489388615ec2b80b69bf2d26e
[nfs-utils.git] / utils / statd / hostname.c
1 /*
2  * Copyright 2009 Oracle.  All rights reserved.
3  *
4  * This file is part of nfs-utils.
5  *
6  * nfs-utils is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * nfs-utils 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * NSM for Linux.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30
31 #include <stdlib.h>
32 #include <stdbool.h>
33 #include <strings.h>
34 #include <netdb.h>
35
36 #include "sockaddr.h"
37 #include "statd.h"
38 #include "xlog.h"
39
40 /*
41  * Look up the hostname; report exceptional errors.  Caller must
42  * call freeaddrinfo(3) if a valid addrinfo is returned.
43  */
44 __attribute_malloc__
45 static struct addrinfo *
46 get_addrinfo(const char *hostname, const struct addrinfo *hint)
47 {
48         struct addrinfo *ai = NULL;
49         int error;
50
51         error = getaddrinfo(hostname, NULL, hint, &ai);
52         switch (error) {
53         case 0:
54                 return ai;
55         case EAI_NONAME:
56                 break;
57         default:
58                 xlog(D_GENERAL, "%s: failed to resolve host %s: %s",
59                                 __func__, hostname, gai_strerror(error));
60         }
61
62         return NULL;
63 }
64
65 /**
66  * statd_matchhostname - check if two hostnames are equivalent
67  * @hostname1: C string containing hostname
68  * @hostname2: C string containing hostname
69  *
70  * Returns true if the hostnames are the same, the hostnames resolve
71  * to the same canonical name, or the hostnames resolve to at least
72  * one address that is the same.  False is returned if the hostnames
73  * do not match in any of these ways, if either hostname contains
74  * wildcard characters, if either hostname is a netgroup name, or
75  * if an error occurs.
76  */
77 _Bool
78 statd_matchhostname(const char *hostname1, const char *hostname2)
79 {
80         struct addrinfo *ai1, *ai2, *results1 = NULL, *results2 = NULL;
81         struct addrinfo hint = {
82                 .ai_family      = AF_UNSPEC,
83                 .ai_flags       = AI_CANONNAME,
84                 .ai_protocol    = (int)IPPROTO_UDP,
85         };
86         _Bool result = false;
87
88         if (strcasecmp(hostname1, hostname2) == 0) {
89                 result = true;
90                 goto out;
91         }
92
93         results1 = get_addrinfo(hostname1, &hint);
94         if (results1 == NULL)
95                 goto out;
96         results2 = get_addrinfo(hostname2, &hint);
97         if (results2 == NULL)
98                 goto out;
99
100         if (strcasecmp(results1->ai_canonname, results2->ai_canonname) == 0) {
101                 result = true;
102                 goto out;
103         }
104
105         for (ai1 = results1; ai1 != NULL; ai1 = ai1->ai_next)
106                 for (ai2 = results2; ai2 != NULL; ai2 = ai2->ai_next)
107                         if (nfs_compare_sockaddr(ai1->ai_addr, ai2->ai_addr)) {
108                                 result = true;
109                                 break;
110                         }
111
112 out:
113         freeaddrinfo(results2);
114         freeaddrinfo(results1);
115
116         xlog(D_CALL, "%s: hostnames %s", __func__,
117                         (result ? "matched" : "did not match"));
118         return result;
119 }