1238106Sdes/*
2238106Sdes * util/net_help.c - implementation of the network helper code
3238106Sdes *
4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved.
5238106Sdes *
6238106Sdes * This software is open source.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes *
12238106Sdes * Redistributions of source code must retain the above copyright notice,
13238106Sdes * this list of conditions and the following disclaimer.
14238106Sdes *
15238106Sdes * Redistributions in binary form must reproduce the above copyright notice,
16238106Sdes * this list of conditions and the following disclaimer in the documentation
17238106Sdes * and/or other materials provided with the distribution.
18238106Sdes *
19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20238106Sdes * be used to endorse or promote products derived from this software without
21238106Sdes * specific prior written permission.
22238106Sdes *
23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34238106Sdes */
35238106Sdes/**
36238106Sdes * \file
37238106Sdes * Implementation of net_help.h.
38238106Sdes */
39238106Sdes
40238106Sdes#include "config.h"
41238106Sdes#include "util/net_help.h"
42238106Sdes#include "util/log.h"
43238106Sdes#include "util/data/dname.h"
44238106Sdes#include "util/module.h"
45238106Sdes#include "util/regional.h"
46291767Sdes#include "sldns/parseutil.h"
47291767Sdes#include "sldns/wire2str.h"
48238106Sdes#include <fcntl.h>
49249141Sdes#ifdef HAVE_OPENSSL_SSL_H
50238106Sdes#include <openssl/ssl.h>
51249141Sdes#endif
52249141Sdes#ifdef HAVE_OPENSSL_ERR_H
53238106Sdes#include <openssl/err.h>
54249141Sdes#endif
55238106Sdes
56238106Sdes/** max length of an IP address (the address portion) that we allow */
57238106Sdes#define MAX_ADDR_STRLEN 128 /* characters */
58238106Sdes/** default value for EDNS ADVERTISED size */
59238106Sdesuint16_t EDNS_ADVERTISED_SIZE = 4096;
60238106Sdes
61238106Sdes/** minimal responses when positive answer: default is no */
62238106Sdesint MINIMAL_RESPONSES = 0;
63238106Sdes
64238106Sdes/** rrset order roundrobin: default is no */
65238106Sdesint RRSET_ROUNDROBIN = 0;
66238106Sdes
67238106Sdes/* returns true is string addr is an ip6 specced address */
68238106Sdesint
69238106Sdesstr_is_ip6(const char* str)
70238106Sdes{
71238106Sdes	if(strchr(str, ':'))
72238106Sdes		return 1;
73238106Sdes	else    return 0;
74238106Sdes}
75238106Sdes
76238106Sdesint
77238106Sdesfd_set_nonblock(int s)
78238106Sdes{
79238106Sdes#ifdef HAVE_FCNTL
80238106Sdes	int flag;
81238106Sdes	if((flag = fcntl(s, F_GETFL)) == -1) {
82238106Sdes		log_err("can't fcntl F_GETFL: %s", strerror(errno));
83238106Sdes		flag = 0;
84238106Sdes	}
85238106Sdes	flag |= O_NONBLOCK;
86238106Sdes	if(fcntl(s, F_SETFL, flag) == -1) {
87238106Sdes		log_err("can't fcntl F_SETFL: %s", strerror(errno));
88238106Sdes		return 0;
89238106Sdes	}
90238106Sdes#elif defined(HAVE_IOCTLSOCKET)
91238106Sdes	unsigned long on = 1;
92238106Sdes	if(ioctlsocket(s, FIONBIO, &on) != 0) {
93238106Sdes		log_err("can't ioctlsocket FIONBIO on: %s",
94238106Sdes			wsa_strerror(WSAGetLastError()));
95238106Sdes	}
96238106Sdes#endif
97238106Sdes	return 1;
98238106Sdes}
99238106Sdes
100238106Sdesint
101238106Sdesfd_set_block(int s)
102238106Sdes{
103238106Sdes#ifdef HAVE_FCNTL
104238106Sdes	int flag;
105238106Sdes	if((flag = fcntl(s, F_GETFL)) == -1) {
106238106Sdes		log_err("cannot fcntl F_GETFL: %s", strerror(errno));
107238106Sdes		flag = 0;
108238106Sdes	}
109238106Sdes	flag &= ~O_NONBLOCK;
110238106Sdes	if(fcntl(s, F_SETFL, flag) == -1) {
111238106Sdes		log_err("cannot fcntl F_SETFL: %s", strerror(errno));
112238106Sdes		return 0;
113238106Sdes	}
114238106Sdes#elif defined(HAVE_IOCTLSOCKET)
115238106Sdes	unsigned long off = 0;
116238106Sdes	if(ioctlsocket(s, FIONBIO, &off) != 0) {
117238106Sdes		log_err("can't ioctlsocket FIONBIO off: %s",
118238106Sdes			wsa_strerror(WSAGetLastError()));
119238106Sdes	}
120238106Sdes#endif
121238106Sdes	return 1;
122238106Sdes}
123238106Sdes
124238106Sdesint
125238106Sdesis_pow2(size_t num)
126238106Sdes{
127238106Sdes	if(num == 0) return 1;
128238106Sdes	return (num & (num-1)) == 0;
129238106Sdes}
130238106Sdes
131238106Sdesvoid*
132238106Sdesmemdup(void* data, size_t len)
133238106Sdes{
134238106Sdes	void* d;
135238106Sdes	if(!data) return NULL;
136238106Sdes	if(len == 0) return NULL;
137238106Sdes	d = malloc(len);
138238106Sdes	if(!d) return NULL;
139238106Sdes	memcpy(d, data, len);
140238106Sdes	return d;
141238106Sdes}
142238106Sdes
143238106Sdesvoid
144238106Sdeslog_addr(enum verbosity_value v, const char* str,
145238106Sdes	struct sockaddr_storage* addr, socklen_t addrlen)
146238106Sdes{
147238106Sdes	uint16_t port;
148238106Sdes	const char* family = "unknown";
149238106Sdes	char dest[100];
150238106Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
151238106Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
152238106Sdes	if(verbosity < v)
153238106Sdes		return;
154238106Sdes	switch(af) {
155238106Sdes		case AF_INET: family="ip4"; break;
156238106Sdes		case AF_INET6: family="ip6";
157238106Sdes			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
158238106Sdes			break;
159285206Sdes		case AF_LOCAL:
160285206Sdes			dest[0]=0;
161285206Sdes			(void)inet_ntop(af, sinaddr, dest,
162285206Sdes				(socklen_t)sizeof(dest));
163285206Sdes			verbose(v, "%s local %s", str, dest);
164285206Sdes			return; /* do not continue and try to get port */
165238106Sdes		default: break;
166238106Sdes	}
167238106Sdes	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
168269257Sdes		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
169238106Sdes	}
170238106Sdes	dest[sizeof(dest)-1] = 0;
171238106Sdes	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
172238106Sdes	if(verbosity >= 4)
173238106Sdes		verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
174238106Sdes			(int)port, (int)addrlen);
175238106Sdes	else	verbose(v, "%s %s port %d", str, dest, (int)port);
176238106Sdes}
177238106Sdes
178238106Sdesint
179238106Sdesextstrtoaddr(const char* str, struct sockaddr_storage* addr,
180238106Sdes	socklen_t* addrlen)
181238106Sdes{
182238106Sdes	char* s;
183238106Sdes	int port = UNBOUND_DNS_PORT;
184238106Sdes	if((s=strchr(str, '@'))) {
185238106Sdes		char buf[MAX_ADDR_STRLEN];
186238106Sdes		if(s-str >= MAX_ADDR_STRLEN) {
187238106Sdes			return 0;
188238106Sdes		}
189269257Sdes		(void)strlcpy(buf, str, sizeof(buf));
190238106Sdes		buf[s-str] = 0;
191238106Sdes		port = atoi(s+1);
192238106Sdes		if(port == 0 && strcmp(s+1,"0")!=0) {
193238106Sdes			return 0;
194238106Sdes		}
195238106Sdes		return ipstrtoaddr(buf, port, addr, addrlen);
196238106Sdes	}
197238106Sdes	return ipstrtoaddr(str, port, addr, addrlen);
198238106Sdes}
199238106Sdes
200238106Sdes
201238106Sdesint
202238106Sdesipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
203238106Sdes	socklen_t* addrlen)
204238106Sdes{
205238106Sdes	uint16_t p;
206238106Sdes	if(!ip) return 0;
207238106Sdes	p = (uint16_t) port;
208238106Sdes	if(str_is_ip6(ip)) {
209238106Sdes		char buf[MAX_ADDR_STRLEN];
210238106Sdes		char* s;
211238106Sdes		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
212238106Sdes		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
213238106Sdes		memset(sa, 0, *addrlen);
214238106Sdes		sa->sin6_family = AF_INET6;
215238106Sdes		sa->sin6_port = (in_port_t)htons(p);
216238106Sdes		if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
217238106Sdes			if(s-ip >= MAX_ADDR_STRLEN)
218238106Sdes				return 0;
219269257Sdes			(void)strlcpy(buf, ip, sizeof(buf));
220238106Sdes			buf[s-ip]=0;
221238106Sdes			sa->sin6_scope_id = (uint32_t)atoi(s+1);
222238106Sdes			ip = buf;
223238106Sdes		}
224238106Sdes		if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
225238106Sdes			return 0;
226238106Sdes		}
227238106Sdes	} else { /* ip4 */
228238106Sdes		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
229238106Sdes		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
230238106Sdes		memset(sa, 0, *addrlen);
231238106Sdes		sa->sin_family = AF_INET;
232238106Sdes		sa->sin_port = (in_port_t)htons(p);
233238106Sdes		if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
234238106Sdes			return 0;
235238106Sdes		}
236238106Sdes	}
237238106Sdes	return 1;
238238106Sdes}
239238106Sdes
240238106Sdesint netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
241238106Sdes        socklen_t* addrlen, int* net)
242238106Sdes{
243238106Sdes	char* s = NULL;
244238106Sdes	*net = (str_is_ip6(str)?128:32);
245238106Sdes	if((s=strchr(str, '/'))) {
246238106Sdes		if(atoi(s+1) > *net) {
247238106Sdes			log_err("netblock too large: %s", str);
248238106Sdes			return 0;
249238106Sdes		}
250238106Sdes		*net = atoi(s+1);
251238106Sdes		if(*net == 0 && strcmp(s+1, "0") != 0) {
252238106Sdes			log_err("cannot parse netblock: '%s'", str);
253238106Sdes			return 0;
254238106Sdes		}
255238106Sdes		if(!(s = strdup(str))) {
256238106Sdes			log_err("out of memory");
257238106Sdes			return 0;
258238106Sdes		}
259238106Sdes		*strchr(s, '/') = '\0';
260238106Sdes	}
261238106Sdes	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
262238106Sdes		free(s);
263238106Sdes		log_err("cannot parse ip address: '%s'", str);
264238106Sdes		return 0;
265238106Sdes	}
266238106Sdes	if(s) {
267238106Sdes		free(s);
268238106Sdes		addr_mask(addr, *addrlen, *net);
269238106Sdes	}
270238106Sdes	return 1;
271238106Sdes}
272238106Sdes
273238106Sdesvoid
274238106Sdeslog_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
275238106Sdes	uint16_t type, uint16_t dclass)
276238106Sdes{
277238106Sdes	char buf[LDNS_MAX_DOMAINLEN+1];
278238106Sdes	char t[12], c[12];
279238106Sdes	const char *ts, *cs;
280238106Sdes	if(verbosity < v)
281238106Sdes		return;
282238106Sdes	dname_str(name, buf);
283238106Sdes	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
284238106Sdes	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
285238106Sdes	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
286238106Sdes	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
287238106Sdes	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
288238106Sdes	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
289269257Sdes	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
290269257Sdes		ts = sldns_rr_descript(type)->_name;
291238106Sdes	else {
292238106Sdes		snprintf(t, sizeof(t), "TYPE%d", (int)type);
293238106Sdes		ts = t;
294238106Sdes	}
295269257Sdes	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
296269257Sdes		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
297269257Sdes		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
298238106Sdes	else {
299238106Sdes		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
300238106Sdes		cs = c;
301238106Sdes	}
302238106Sdes	log_info("%s %s %s %s", str, buf, ts, cs);
303238106Sdes}
304238106Sdes
305238106Sdesvoid log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
306238106Sdes	struct sockaddr_storage* addr, socklen_t addrlen)
307238106Sdes{
308238106Sdes	uint16_t port;
309238106Sdes	const char* family = "unknown_family ";
310238106Sdes	char namebuf[LDNS_MAX_DOMAINLEN+1];
311238106Sdes	char dest[100];
312238106Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
313238106Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
314238106Sdes	if(verbosity < v)
315238106Sdes		return;
316238106Sdes	switch(af) {
317238106Sdes		case AF_INET: family=""; break;
318238106Sdes		case AF_INET6: family="";
319238106Sdes			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
320238106Sdes			break;
321285206Sdes		case AF_LOCAL: family="local "; break;
322238106Sdes		default: break;
323238106Sdes	}
324238106Sdes	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
325269257Sdes		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
326238106Sdes	}
327238106Sdes	dest[sizeof(dest)-1] = 0;
328238106Sdes	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
329238106Sdes	dname_str(zone, namebuf);
330238106Sdes	if(af != AF_INET && af != AF_INET6)
331238106Sdes		verbose(v, "%s <%s> %s%s#%d (addrlen %d)",
332238106Sdes			str, namebuf, family, dest, (int)port, (int)addrlen);
333238106Sdes	else	verbose(v, "%s <%s> %s%s#%d",
334238106Sdes			str, namebuf, family, dest, (int)port);
335238106Sdes}
336238106Sdes
337285206Sdesvoid log_err_addr(const char* str, const char* err,
338285206Sdes	struct sockaddr_storage* addr, socklen_t addrlen)
339285206Sdes{
340285206Sdes	uint16_t port;
341285206Sdes	char dest[100];
342285206Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
343285206Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
344285206Sdes	if(af == AF_INET6)
345285206Sdes		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
346285206Sdes	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
347285206Sdes		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
348285206Sdes	}
349285206Sdes	dest[sizeof(dest)-1] = 0;
350285206Sdes	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
351285206Sdes	if(verbosity >= 4)
352285206Sdes		log_err("%s: %s for %s port %d (len %d)", str, err, dest,
353285206Sdes			(int)port, (int)addrlen);
354285206Sdes	else	log_err("%s: %s for %s", str, err, dest);
355285206Sdes}
356285206Sdes
357238106Sdesint
358238106Sdessockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
359238106Sdes	struct sockaddr_storage* addr2, socklen_t len2)
360238106Sdes{
361238106Sdes	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
362238106Sdes	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
363238106Sdes	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
364238106Sdes	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
365238106Sdes	if(len1 < len2)
366238106Sdes		return -1;
367238106Sdes	if(len1 > len2)
368238106Sdes		return 1;
369238106Sdes	log_assert(len1 == len2);
370238106Sdes	if( p1_in->sin_family < p2_in->sin_family)
371238106Sdes		return -1;
372238106Sdes	if( p1_in->sin_family > p2_in->sin_family)
373238106Sdes		return 1;
374238106Sdes	log_assert( p1_in->sin_family == p2_in->sin_family );
375238106Sdes	/* compare ip4 */
376238106Sdes	if( p1_in->sin_family == AF_INET ) {
377238106Sdes		/* just order it, ntohs not required */
378238106Sdes		if(p1_in->sin_port < p2_in->sin_port)
379238106Sdes			return -1;
380238106Sdes		if(p1_in->sin_port > p2_in->sin_port)
381238106Sdes			return 1;
382238106Sdes		log_assert(p1_in->sin_port == p2_in->sin_port);
383238106Sdes		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
384238106Sdes	} else if (p1_in6->sin6_family == AF_INET6) {
385238106Sdes		/* just order it, ntohs not required */
386238106Sdes		if(p1_in6->sin6_port < p2_in6->sin6_port)
387238106Sdes			return -1;
388238106Sdes		if(p1_in6->sin6_port > p2_in6->sin6_port)
389238106Sdes			return 1;
390238106Sdes		log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
391238106Sdes		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
392238106Sdes			INET6_SIZE);
393238106Sdes	} else {
394238106Sdes		/* eek unknown type, perform this comparison for sanity. */
395238106Sdes		return memcmp(addr1, addr2, len1);
396238106Sdes	}
397238106Sdes}
398238106Sdes
399238106Sdesint
400238106Sdessockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
401238106Sdes	struct sockaddr_storage* addr2, socklen_t len2)
402238106Sdes{
403238106Sdes	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
404238106Sdes	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
405238106Sdes	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
406238106Sdes	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
407238106Sdes	if(len1 < len2)
408238106Sdes		return -1;
409238106Sdes	if(len1 > len2)
410238106Sdes		return 1;
411238106Sdes	log_assert(len1 == len2);
412238106Sdes	if( p1_in->sin_family < p2_in->sin_family)
413238106Sdes		return -1;
414238106Sdes	if( p1_in->sin_family > p2_in->sin_family)
415238106Sdes		return 1;
416238106Sdes	log_assert( p1_in->sin_family == p2_in->sin_family );
417238106Sdes	/* compare ip4 */
418238106Sdes	if( p1_in->sin_family == AF_INET ) {
419238106Sdes		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
420238106Sdes	} else if (p1_in6->sin6_family == AF_INET6) {
421238106Sdes		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
422238106Sdes			INET6_SIZE);
423238106Sdes	} else {
424238106Sdes		/* eek unknown type, perform this comparison for sanity. */
425238106Sdes		return memcmp(addr1, addr2, len1);
426238106Sdes	}
427238106Sdes}
428238106Sdes
429238106Sdesint
430238106Sdesaddr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
431238106Sdes{
432238106Sdes	if(len == (socklen_t)sizeof(struct sockaddr_in6) &&
433238106Sdes		((struct sockaddr_in6*)addr)->sin6_family == AF_INET6)
434238106Sdes		return 1;
435238106Sdes	else    return 0;
436238106Sdes}
437238106Sdes
438238106Sdesvoid
439238106Sdesaddr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
440238106Sdes{
441238106Sdes	uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
442238106Sdes	int i, max;
443238106Sdes	uint8_t* s;
444238106Sdes	if(addr_is_ip6(addr, len)) {
445238106Sdes		s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
446238106Sdes		max = 128;
447238106Sdes	} else {
448238106Sdes		s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
449238106Sdes		max = 32;
450238106Sdes	}
451238106Sdes	if(net >= max)
452238106Sdes		return;
453238106Sdes	for(i=net/8+1; i<max/8; i++) {
454238106Sdes		s[i] = 0;
455238106Sdes	}
456238106Sdes	s[net/8] &= mask[net&0x7];
457238106Sdes}
458238106Sdes
459238106Sdesint
460238106Sdesaddr_in_common(struct sockaddr_storage* addr1, int net1,
461238106Sdes	struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
462238106Sdes{
463238106Sdes	int min = (net1<net2)?net1:net2;
464238106Sdes	int i, to;
465238106Sdes	int match = 0;
466238106Sdes	uint8_t* s1, *s2;
467238106Sdes	if(addr_is_ip6(addr1, addrlen)) {
468238106Sdes		s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
469238106Sdes		s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
470238106Sdes		to = 16;
471238106Sdes	} else {
472238106Sdes		s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
473238106Sdes		s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
474238106Sdes		to = 4;
475238106Sdes	}
476238106Sdes	/* match = bits_in_common(s1, s2, to); */
477238106Sdes	for(i=0; i<to; i++) {
478238106Sdes		if(s1[i] == s2[i]) {
479238106Sdes			match += 8;
480238106Sdes		} else {
481238106Sdes			uint8_t z = s1[i]^s2[i];
482238106Sdes			log_assert(z);
483238106Sdes			while(!(z&0x80)) {
484238106Sdes				match++;
485238106Sdes				z<<=1;
486238106Sdes			}
487238106Sdes			break;
488238106Sdes		}
489238106Sdes	}
490238106Sdes	if(match > min) match = min;
491238106Sdes	return match;
492238106Sdes}
493238106Sdes
494238106Sdesvoid
495238106Sdesaddr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
496238106Sdes	char* buf, size_t len)
497238106Sdes{
498238106Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
499238106Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
500238106Sdes	if(addr_is_ip6(addr, addrlen))
501238106Sdes		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
502238106Sdes	if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
503238106Sdes		snprintf(buf, len, "(inet_ntop_error)");
504238106Sdes	}
505238106Sdes}
506238106Sdes
507238106Sdesint
508238106Sdesaddr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
509238106Sdes{
510238106Sdes	/* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
511238106Sdes	const uint8_t map_prefix[16] =
512238106Sdes		{0,0,0,0,  0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
513238106Sdes	uint8_t* s;
514238106Sdes	if(!addr_is_ip6(addr, addrlen))
515238106Sdes		return 0;
516238106Sdes	/* s is 16 octet ipv6 address string */
517238106Sdes	s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
518238106Sdes	return (memcmp(s, map_prefix, 12) == 0);
519238106Sdes}
520238106Sdes
521238106Sdesint addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
522238106Sdes{
523238106Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
524238106Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
525238106Sdes	return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
526238106Sdes		&& memcmp(sinaddr, "\377\377\377\377", 4) == 0;
527238106Sdes}
528238106Sdes
529238106Sdesint addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen)
530238106Sdes{
531238106Sdes	int af = (int)((struct sockaddr_in*)addr)->sin_family;
532238106Sdes	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
533238106Sdes	void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
534238106Sdes	if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
535238106Sdes		&& memcmp(sinaddr, "\000\000\000\000", 4) == 0)
536238106Sdes		return 1;
537238106Sdes	else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6)
538238106Sdes		&& memcmp(sin6addr, "\000\000\000\000\000\000\000\000"
539238106Sdes		"\000\000\000\000\000\000\000\000", 16) == 0)
540238106Sdes		return 1;
541238106Sdes	return 0;
542238106Sdes}
543238106Sdes
544238106Sdesvoid sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr,
545238106Sdes	socklen_t len, struct regional* region)
546238106Sdes{
547238106Sdes	struct sock_list* add = (struct sock_list*)regional_alloc(region,
548238106Sdes		sizeof(*add) - sizeof(add->addr) + (size_t)len);
549238106Sdes	if(!add) {
550238106Sdes		log_err("out of memory in socketlist insert");
551238106Sdes		return;
552238106Sdes	}
553238106Sdes	log_assert(list);
554238106Sdes	add->next = *list;
555238106Sdes	add->len = len;
556238106Sdes	*list = add;
557238106Sdes	if(len) memmove(&add->addr, addr, len);
558238106Sdes}
559238106Sdes
560238106Sdesvoid sock_list_prepend(struct sock_list** list, struct sock_list* add)
561238106Sdes{
562238106Sdes	struct sock_list* last = add;
563238106Sdes	if(!last)
564238106Sdes		return;
565238106Sdes	while(last->next)
566238106Sdes		last = last->next;
567238106Sdes	last->next = *list;
568238106Sdes	*list = add;
569238106Sdes}
570238106Sdes
571238106Sdesint sock_list_find(struct sock_list* list, struct sockaddr_storage* addr,
572238106Sdes        socklen_t len)
573238106Sdes{
574238106Sdes	while(list) {
575238106Sdes		if(len == list->len) {
576238106Sdes			if(len == 0 || sockaddr_cmp_addr(addr, len,
577238106Sdes				&list->addr, list->len) == 0)
578238106Sdes				return 1;
579238106Sdes		}
580238106Sdes		list = list->next;
581238106Sdes	}
582238106Sdes	return 0;
583238106Sdes}
584238106Sdes
585238106Sdesvoid sock_list_merge(struct sock_list** list, struct regional* region,
586238106Sdes	struct sock_list* add)
587238106Sdes{
588238106Sdes	struct sock_list* p;
589238106Sdes	for(p=add; p; p=p->next) {
590238106Sdes		if(!sock_list_find(*list, &p->addr, p->len))
591238106Sdes			sock_list_insert(list, &p->addr, p->len, region);
592238106Sdes	}
593238106Sdes}
594238106Sdes
595238106Sdesvoid
596238106Sdeslog_crypto_err(const char* str)
597238106Sdes{
598249141Sdes#ifdef HAVE_SSL
599238106Sdes	/* error:[error code]:[library name]:[function name]:[reason string] */
600238106Sdes	char buf[128];
601238106Sdes	unsigned long e;
602238106Sdes	ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
603238106Sdes	log_err("%s crypto %s", str, buf);
604238106Sdes	while( (e=ERR_get_error()) ) {
605238106Sdes		ERR_error_string_n(e, buf, sizeof(buf));
606238106Sdes		log_err("and additionally crypto %s", buf);
607238106Sdes	}
608249141Sdes#else
609249141Sdes	(void)str;
610249141Sdes#endif /* HAVE_SSL */
611238106Sdes}
612238106Sdes
613238106Sdesvoid* listen_sslctx_create(char* key, char* pem, char* verifypem)
614238106Sdes{
615249141Sdes#ifdef HAVE_SSL
616238106Sdes	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
617238106Sdes	if(!ctx) {
618238106Sdes		log_crypto_err("could not SSL_CTX_new");
619238106Sdes		return NULL;
620238106Sdes	}
621285206Sdes	/* no SSLv2, SSLv3 because has defects */
622294190Sdes	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
623294190Sdes		!= SSL_OP_NO_SSLv2){
624238106Sdes		log_crypto_err("could not set SSL_OP_NO_SSLv2");
625238106Sdes		SSL_CTX_free(ctx);
626238106Sdes		return NULL;
627238106Sdes	}
628294190Sdes	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
629294190Sdes		!= SSL_OP_NO_SSLv3){
630285206Sdes		log_crypto_err("could not set SSL_OP_NO_SSLv3");
631285206Sdes		SSL_CTX_free(ctx);
632285206Sdes		return NULL;
633285206Sdes	}
634291767Sdes	if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
635238106Sdes		log_err("error for cert file: %s", pem);
636291767Sdes		log_crypto_err("error in SSL_CTX use_certificate_chain_file");
637238106Sdes		SSL_CTX_free(ctx);
638238106Sdes		return NULL;
639238106Sdes	}
640238106Sdes	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
641238106Sdes		log_err("error for private key file: %s", key);
642238106Sdes		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
643238106Sdes		SSL_CTX_free(ctx);
644238106Sdes		return NULL;
645238106Sdes	}
646238106Sdes	if(!SSL_CTX_check_private_key(ctx)) {
647238106Sdes		log_err("error for key file: %s", key);
648238106Sdes		log_crypto_err("Error in SSL_CTX check_private_key");
649238106Sdes		SSL_CTX_free(ctx);
650238106Sdes		return NULL;
651238106Sdes	}
652291767Sdes#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
653291767Sdes	if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
654291767Sdes		log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
655291767Sdes	}
656291767Sdes#elif defined(USE_ECDSA)
657291767Sdes	if(1) {
658291767Sdes		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
659291767Sdes		if (!ecdh) {
660291767Sdes			log_crypto_err("could not find p256, not enabling ECDHE");
661291767Sdes		} else {
662291767Sdes			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
663291767Sdes				log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
664291767Sdes			}
665291767Sdes			EC_KEY_free (ecdh);
666291767Sdes		}
667291767Sdes	}
668291767Sdes#endif
669238106Sdes
670238106Sdes	if(verifypem && verifypem[0]) {
671238106Sdes		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
672238106Sdes			log_crypto_err("Error in SSL_CTX verify locations");
673238106Sdes			SSL_CTX_free(ctx);
674238106Sdes			return NULL;
675238106Sdes		}
676238106Sdes		SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
677238106Sdes			verifypem));
678238106Sdes		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
679238106Sdes	}
680238106Sdes	return ctx;
681249141Sdes#else
682249141Sdes	(void)key; (void)pem; (void)verifypem;
683249141Sdes	return NULL;
684249141Sdes#endif
685238106Sdes}
686238106Sdes
687238106Sdesvoid* connect_sslctx_create(char* key, char* pem, char* verifypem)
688238106Sdes{
689249141Sdes#ifdef HAVE_SSL
690238106Sdes	SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
691238106Sdes	if(!ctx) {
692238106Sdes		log_crypto_err("could not allocate SSL_CTX pointer");
693238106Sdes		return NULL;
694238106Sdes	}
695294190Sdes	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
696294190Sdes		!= SSL_OP_NO_SSLv2) {
697238106Sdes		log_crypto_err("could not set SSL_OP_NO_SSLv2");
698238106Sdes		SSL_CTX_free(ctx);
699238106Sdes		return NULL;
700238106Sdes	}
701294190Sdes	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
702294190Sdes		!= SSL_OP_NO_SSLv3) {
703285206Sdes		log_crypto_err("could not set SSL_OP_NO_SSLv3");
704285206Sdes		SSL_CTX_free(ctx);
705285206Sdes		return NULL;
706285206Sdes	}
707238106Sdes	if(key && key[0]) {
708291767Sdes		if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
709238106Sdes			log_err("error in client certificate %s", pem);
710238106Sdes			log_crypto_err("error in certificate file");
711238106Sdes			SSL_CTX_free(ctx);
712238106Sdes			return NULL;
713238106Sdes		}
714238106Sdes		if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
715238106Sdes			log_err("error in client private key %s", key);
716238106Sdes			log_crypto_err("error in key file");
717238106Sdes			SSL_CTX_free(ctx);
718238106Sdes			return NULL;
719238106Sdes		}
720238106Sdes		if(!SSL_CTX_check_private_key(ctx)) {
721238106Sdes			log_err("error in client key %s", key);
722238106Sdes			log_crypto_err("error in SSL_CTX_check_private_key");
723238106Sdes			SSL_CTX_free(ctx);
724238106Sdes			return NULL;
725238106Sdes		}
726238106Sdes	}
727238106Sdes	if(verifypem && verifypem[0]) {
728285206Sdes		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
729238106Sdes			log_crypto_err("error in SSL_CTX verify");
730238106Sdes			SSL_CTX_free(ctx);
731238106Sdes			return NULL;
732238106Sdes		}
733238106Sdes		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
734238106Sdes	}
735238106Sdes	return ctx;
736249141Sdes#else
737249141Sdes	(void)key; (void)pem; (void)verifypem;
738249141Sdes	return NULL;
739249141Sdes#endif
740238106Sdes}
741238106Sdes
742238106Sdesvoid* incoming_ssl_fd(void* sslctx, int fd)
743238106Sdes{
744249141Sdes#ifdef HAVE_SSL
745238106Sdes	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
746238106Sdes	if(!ssl) {
747238106Sdes		log_crypto_err("could not SSL_new");
748238106Sdes		return NULL;
749238106Sdes	}
750238106Sdes	SSL_set_accept_state(ssl);
751238106Sdes	(void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
752238106Sdes	if(!SSL_set_fd(ssl, fd)) {
753238106Sdes		log_crypto_err("could not SSL_set_fd");
754238106Sdes		SSL_free(ssl);
755238106Sdes		return NULL;
756238106Sdes	}
757238106Sdes	return ssl;
758249141Sdes#else
759249141Sdes	(void)sslctx; (void)fd;
760249141Sdes	return NULL;
761249141Sdes#endif
762238106Sdes}
763238106Sdes
764238106Sdesvoid* outgoing_ssl_fd(void* sslctx, int fd)
765238106Sdes{
766249141Sdes#ifdef HAVE_SSL
767238106Sdes	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
768238106Sdes	if(!ssl) {
769238106Sdes		log_crypto_err("could not SSL_new");
770238106Sdes		return NULL;
771238106Sdes	}
772238106Sdes	SSL_set_connect_state(ssl);
773238106Sdes	(void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
774238106Sdes	if(!SSL_set_fd(ssl, fd)) {
775238106Sdes		log_crypto_err("could not SSL_set_fd");
776238106Sdes		SSL_free(ssl);
777238106Sdes		return NULL;
778238106Sdes	}
779238106Sdes	return ssl;
780249141Sdes#else
781249141Sdes	(void)sslctx; (void)fd;
782249141Sdes	return NULL;
783249141Sdes#endif
784238106Sdes}
785249141Sdes
786249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
787249141Sdes/** global lock list for openssl locks */
788249141Sdesstatic lock_basic_t *ub_openssl_locks = NULL;
789249141Sdes
790249141Sdes/** callback that gets thread id for openssl */
791249141Sdesstatic unsigned long
792249141Sdesub_crypto_id_cb(void)
793249141Sdes{
794291767Sdes	return (unsigned long)log_thread_get();
795249141Sdes}
796249141Sdes
797249141Sdesstatic void
798249141Sdesub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
799249141Sdes	int ATTR_UNUSED(line))
800249141Sdes{
801249141Sdes	if((mode&CRYPTO_LOCK)) {
802249141Sdes		lock_basic_lock(&ub_openssl_locks[type]);
803249141Sdes	} else {
804249141Sdes		lock_basic_unlock(&ub_openssl_locks[type]);
805249141Sdes	}
806249141Sdes}
807249141Sdes#endif /* OPENSSL_THREADS */
808249141Sdes
809249141Sdesint ub_openssl_lock_init(void)
810249141Sdes{
811249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
812249141Sdes	int i;
813291767Sdes	ub_openssl_locks = (lock_basic_t*)reallocarray(
814291767Sdes		NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_t));
815249141Sdes	if(!ub_openssl_locks)
816249141Sdes		return 0;
817249141Sdes	for(i=0; i<CRYPTO_num_locks(); i++) {
818249141Sdes		lock_basic_init(&ub_openssl_locks[i]);
819249141Sdes	}
820249141Sdes	CRYPTO_set_id_callback(&ub_crypto_id_cb);
821249141Sdes	CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
822249141Sdes#endif /* OPENSSL_THREADS */
823249141Sdes	return 1;
824249141Sdes}
825249141Sdes
826249141Sdesvoid ub_openssl_lock_delete(void)
827249141Sdes{
828249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
829249141Sdes	int i;
830249141Sdes	if(!ub_openssl_locks)
831249141Sdes		return;
832249141Sdes	CRYPTO_set_id_callback(NULL);
833249141Sdes	CRYPTO_set_locking_callback(NULL);
834249141Sdes	for(i=0; i<CRYPTO_num_locks(); i++) {
835249141Sdes		lock_basic_destroy(&ub_openssl_locks[i]);
836249141Sdes	}
837249141Sdes	free(ub_openssl_locks);
838249141Sdes#endif /* OPENSSL_THREADS */
839249141Sdes}
840249141Sdes
841