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