Simpler checking of permissions on private RSA key and other fixes.
[tinc] / src / netutl.c
1 /*
2     netutl.c -- some supporting network utility code
3     Copyright (C) 1998-2003 Ivo Timmermans <ivo@o2w.nl>
4                   2000-2003 Guus Sliepen <guus@sliepen.eu.org>
5
6     This program 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     This program 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 this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: netutl.c,v 1.12.4.52 2003/08/03 12:38:43 guus Exp $
21 */
22
23 #include "system.h"
24
25 #include "net.h"
26 #include "netutl.h"
27 #include "logger.h"
28 #include "utils.h"
29 #include "xalloc.h"
30
31 bool hostnames = false;
32
33 /*
34   Turn a string into a struct addrinfo.
35   Return NULL on failure.
36 */
37 struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype)
38 {
39         struct addrinfo *ai, hint = {0};
40         int err;
41
42         cp();
43
44         hint.ai_family = addressfamily;
45         hint.ai_socktype = socktype;
46
47         err = getaddrinfo(address, service, &hint, &ai);
48
49         if(err) {
50                 logger(LOG_WARNING, _("Error looking up %s port %s: %s"), address,
51                                    service, gai_strerror(err));
52                 return NULL;
53         }
54
55         return ai;
56 }
57
58 sockaddr_t str2sockaddr(const char *address, const char *port)
59 {
60         struct addrinfo *ai, hint = {0};
61         sockaddr_t result;
62         int err;
63
64         cp();
65
66         hint.ai_family = AF_UNSPEC;
67         hint.ai_flags = AI_NUMERICHOST;
68         hint.ai_socktype = SOCK_STREAM;
69
70         err = getaddrinfo(address, port, &hint, &ai);
71
72         if(err || !ai) {
73                 logger(LOG_ERR, _("Error looking up %s port %s: %s"), address, port,
74                            gai_strerror(err));
75                 cp_trace();
76                 raise(SIGFPE);
77                 exit(0);
78         }
79
80         result = *(sockaddr_t *) ai->ai_addr;
81         freeaddrinfo(ai);
82
83         return result;
84 }
85
86 void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr)
87 {
88         char address[NI_MAXHOST];
89         char port[NI_MAXSERV];
90         char *scopeid;
91         int err;
92
93         cp();
94
95         err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
96
97         if(err) {
98                 logger(LOG_ERR, _("Error while translating addresses: %s"),
99                            gai_strerror(err));
100                 cp_trace();
101                 raise(SIGFPE);
102                 exit(0);
103         }
104
105         scopeid = strchr(address, '%');
106
107         if(scopeid)
108                 *scopeid = '\0';                /* Descope. */
109
110         *addrstr = xstrdup(address);
111         *portstr = xstrdup(port);
112 }
113
114 char *sockaddr2hostname(const sockaddr_t *sa)
115 {
116         char *str;
117         char address[NI_MAXHOST] = "unknown";
118         char port[NI_MAXSERV] = "unknown";
119         int err;
120
121         cp();
122
123         err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port),
124                                         hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
125         if(err) {
126                 logger(LOG_ERR, _("Error while looking up hostname: %s"),
127                            gai_strerror(err));
128         }
129
130         asprintf(&str, _("%s port %s"), address, port);
131
132         return str;
133 }
134
135 int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b)
136 {
137         int result;
138
139         cp();
140
141         result = a->sa.sa_family - b->sa.sa_family;
142
143         if(result)
144                 return result;
145
146         switch (a->sa.sa_family) {
147                 case AF_UNSPEC:
148                         return 0;
149
150                 case AF_INET:
151                         result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
152
153                         if(result)
154                                 return result;
155
156                         return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
157
158                 case AF_INET6:
159                         result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
160
161                         if(result)
162                                 return result;
163
164                         return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
165
166                 default:
167                         logger(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"),
168                                    a->sa.sa_family);
169                         cp_trace();
170                         raise(SIGFPE);
171                         exit(0);
172         }
173 }
174
175 void sockaddrunmap(sockaddr_t *sa)
176 {
177         if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr)) {
178                 sa->in.sin_addr.s_addr = ((uint32_t *) & sa->in6.sin6_addr)[3];
179                 sa->in.sin_family = AF_INET;
180         }
181 }
182
183 /* Subnet mask handling */
184
185 int maskcmp(const void *va, const void *vb, int masklen, int len)
186 {
187         int i, m, result;
188         const char *a = va;
189         const char *b = vb;
190
191         cp();
192
193         for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
194                 result = a[i] - b[i];
195                 if(result)
196                         return result;
197         }
198
199         if(m)
200                 return (a[i] & (0x100 - (1 << (8 - m)))) -
201                         (b[i] & (0x100 - (1 << (8 - m))));
202
203         return 0;
204 }
205
206 void mask(void *va, int masklen, int len)
207 {
208         int i;
209         char *a = va;
210
211         cp();
212
213         i = masklen / 8;
214         masklen %= 8;
215
216         if(masklen)
217                 a[i++] &= (0x100 - (1 << masklen));
218
219         for(; i < len; i++)
220                 a[i] = 0;
221 }
222
223 void maskcpy(void *va, const void *vb, int masklen, int len)
224 {
225         int i, m;
226         char *a = va;
227         const char *b = vb;
228
229         cp();
230
231         for(m = masklen, i = 0; m >= 8; m -= 8, i++)
232                 a[i] = b[i];
233
234         if(m) {
235                 a[i] = b[i] & (0x100 - (1 << m));
236                 i++;
237         }
238
239         for(; i < len; i++)
240                 a[i] = 0;
241 }
242
243 bool maskcheck(const void *va, int masklen, int len)
244 {
245         int i;
246         const char *a = va;
247
248         cp();
249
250         i = masklen / 8;
251         masklen %= 8;
252
253         if(masklen && a[i++] & (0xff >> masklen))
254                 return false;
255
256         for(; i < len; i++)
257                 if(a[i] != 0)
258                         return false;
259
260         return true;
261 }