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 24238106Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25238106Sdes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26238106Sdes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27238106Sdes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28238106Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29238106Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30238106Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31238106Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32238106Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33238106Sdes * POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes/** 36238106Sdes * \file 37238106Sdes * Implementation of net_help.h. 38238106Sdes */ 39238106Sdes 40238106Sdes#include "config.h" 41238106Sdes#include <ldns/ldns.h> 42238106Sdes#include "util/net_help.h" 43238106Sdes#include "util/log.h" 44238106Sdes#include "util/data/dname.h" 45238106Sdes#include "util/module.h" 46238106Sdes#include "util/regional.h" 47238106Sdes#include <fcntl.h> 48249141Sdes#ifdef HAVE_OPENSSL_SSL_H 49238106Sdes#include <openssl/ssl.h> 50249141Sdes#endif 51249141Sdes#ifdef HAVE_OPENSSL_ERR_H 52238106Sdes#include <openssl/err.h> 53249141Sdes#endif 54238106Sdes 55238106Sdes/** max length of an IP address (the address portion) that we allow */ 56238106Sdes#define MAX_ADDR_STRLEN 128 /* characters */ 57238106Sdes/** default value for EDNS ADVERTISED size */ 58238106Sdesuint16_t EDNS_ADVERTISED_SIZE = 4096; 59238106Sdes 60238106Sdes/** minimal responses when positive answer: default is no */ 61238106Sdesint MINIMAL_RESPONSES = 0; 62238106Sdes 63238106Sdes/** rrset order roundrobin: default is no */ 64238106Sdesint RRSET_ROUNDROBIN = 0; 65238106Sdes 66238106Sdes/* returns true is string addr is an ip6 specced address */ 67238106Sdesint 68238106Sdesstr_is_ip6(const char* str) 69238106Sdes{ 70238106Sdes if(strchr(str, ':')) 71238106Sdes return 1; 72238106Sdes else return 0; 73238106Sdes} 74238106Sdes 75238106Sdesint 76238106Sdesfd_set_nonblock(int s) 77238106Sdes{ 78238106Sdes#ifdef HAVE_FCNTL 79238106Sdes int flag; 80238106Sdes if((flag = fcntl(s, F_GETFL)) == -1) { 81238106Sdes log_err("can't fcntl F_GETFL: %s", strerror(errno)); 82238106Sdes flag = 0; 83238106Sdes } 84238106Sdes flag |= O_NONBLOCK; 85238106Sdes if(fcntl(s, F_SETFL, flag) == -1) { 86238106Sdes log_err("can't fcntl F_SETFL: %s", strerror(errno)); 87238106Sdes return 0; 88238106Sdes } 89238106Sdes#elif defined(HAVE_IOCTLSOCKET) 90238106Sdes unsigned long on = 1; 91238106Sdes if(ioctlsocket(s, FIONBIO, &on) != 0) { 92238106Sdes log_err("can't ioctlsocket FIONBIO on: %s", 93238106Sdes wsa_strerror(WSAGetLastError())); 94238106Sdes } 95238106Sdes#endif 96238106Sdes return 1; 97238106Sdes} 98238106Sdes 99238106Sdesint 100238106Sdesfd_set_block(int s) 101238106Sdes{ 102238106Sdes#ifdef HAVE_FCNTL 103238106Sdes int flag; 104238106Sdes if((flag = fcntl(s, F_GETFL)) == -1) { 105238106Sdes log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 106238106Sdes flag = 0; 107238106Sdes } 108238106Sdes flag &= ~O_NONBLOCK; 109238106Sdes if(fcntl(s, F_SETFL, flag) == -1) { 110238106Sdes log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 111238106Sdes return 0; 112238106Sdes } 113238106Sdes#elif defined(HAVE_IOCTLSOCKET) 114238106Sdes unsigned long off = 0; 115238106Sdes if(ioctlsocket(s, FIONBIO, &off) != 0) { 116238106Sdes log_err("can't ioctlsocket FIONBIO off: %s", 117238106Sdes wsa_strerror(WSAGetLastError())); 118238106Sdes } 119238106Sdes#endif 120238106Sdes return 1; 121238106Sdes} 122238106Sdes 123238106Sdesint 124238106Sdesis_pow2(size_t num) 125238106Sdes{ 126238106Sdes if(num == 0) return 1; 127238106Sdes return (num & (num-1)) == 0; 128238106Sdes} 129238106Sdes 130238106Sdesvoid* 131238106Sdesmemdup(void* data, size_t len) 132238106Sdes{ 133238106Sdes void* d; 134238106Sdes if(!data) return NULL; 135238106Sdes if(len == 0) return NULL; 136238106Sdes d = malloc(len); 137238106Sdes if(!d) return NULL; 138238106Sdes memcpy(d, data, len); 139238106Sdes return d; 140238106Sdes} 141238106Sdes 142238106Sdesvoid 143238106Sdeslog_addr(enum verbosity_value v, const char* str, 144238106Sdes struct sockaddr_storage* addr, socklen_t addrlen) 145238106Sdes{ 146238106Sdes uint16_t port; 147238106Sdes const char* family = "unknown"; 148238106Sdes char dest[100]; 149238106Sdes int af = (int)((struct sockaddr_in*)addr)->sin_family; 150238106Sdes void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 151238106Sdes if(verbosity < v) 152238106Sdes return; 153238106Sdes switch(af) { 154238106Sdes case AF_INET: family="ip4"; break; 155238106Sdes case AF_INET6: family="ip6"; 156238106Sdes sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 157238106Sdes break; 158238106Sdes case AF_UNIX: family="unix"; break; 159238106Sdes default: break; 160238106Sdes } 161238106Sdes if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 162238106Sdes strncpy(dest, "(inet_ntop error)", sizeof(dest)); 163238106Sdes } 164238106Sdes dest[sizeof(dest)-1] = 0; 165238106Sdes port = ntohs(((struct sockaddr_in*)addr)->sin_port); 166238106Sdes if(verbosity >= 4) 167238106Sdes verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 168238106Sdes (int)port, (int)addrlen); 169238106Sdes else verbose(v, "%s %s port %d", str, dest, (int)port); 170238106Sdes} 171238106Sdes 172238106Sdesint 173238106Sdesextstrtoaddr(const char* str, struct sockaddr_storage* addr, 174238106Sdes socklen_t* addrlen) 175238106Sdes{ 176238106Sdes char* s; 177238106Sdes int port = UNBOUND_DNS_PORT; 178238106Sdes if((s=strchr(str, '@'))) { 179238106Sdes char buf[MAX_ADDR_STRLEN]; 180238106Sdes if(s-str >= MAX_ADDR_STRLEN) { 181238106Sdes return 0; 182238106Sdes } 183238106Sdes strncpy(buf, str, MAX_ADDR_STRLEN); 184238106Sdes buf[s-str] = 0; 185238106Sdes port = atoi(s+1); 186238106Sdes if(port == 0 && strcmp(s+1,"0")!=0) { 187238106Sdes return 0; 188238106Sdes } 189238106Sdes return ipstrtoaddr(buf, port, addr, addrlen); 190238106Sdes } 191238106Sdes return ipstrtoaddr(str, port, addr, addrlen); 192238106Sdes} 193238106Sdes 194238106Sdes 195238106Sdesint 196238106Sdesipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 197238106Sdes socklen_t* addrlen) 198238106Sdes{ 199238106Sdes uint16_t p; 200238106Sdes if(!ip) return 0; 201238106Sdes p = (uint16_t) port; 202238106Sdes if(str_is_ip6(ip)) { 203238106Sdes char buf[MAX_ADDR_STRLEN]; 204238106Sdes char* s; 205238106Sdes struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 206238106Sdes *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 207238106Sdes memset(sa, 0, *addrlen); 208238106Sdes sa->sin6_family = AF_INET6; 209238106Sdes sa->sin6_port = (in_port_t)htons(p); 210238106Sdes if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 211238106Sdes if(s-ip >= MAX_ADDR_STRLEN) 212238106Sdes return 0; 213238106Sdes strncpy(buf, ip, MAX_ADDR_STRLEN); 214238106Sdes buf[s-ip]=0; 215238106Sdes sa->sin6_scope_id = (uint32_t)atoi(s+1); 216238106Sdes ip = buf; 217238106Sdes } 218238106Sdes if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 219238106Sdes return 0; 220238106Sdes } 221238106Sdes } else { /* ip4 */ 222238106Sdes struct sockaddr_in* sa = (struct sockaddr_in*)addr; 223238106Sdes *addrlen = (socklen_t)sizeof(struct sockaddr_in); 224238106Sdes memset(sa, 0, *addrlen); 225238106Sdes sa->sin_family = AF_INET; 226238106Sdes sa->sin_port = (in_port_t)htons(p); 227238106Sdes if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 228238106Sdes return 0; 229238106Sdes } 230238106Sdes } 231238106Sdes return 1; 232238106Sdes} 233238106Sdes 234238106Sdesint netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 235238106Sdes socklen_t* addrlen, int* net) 236238106Sdes{ 237238106Sdes char* s = NULL; 238238106Sdes *net = (str_is_ip6(str)?128:32); 239238106Sdes if((s=strchr(str, '/'))) { 240238106Sdes if(atoi(s+1) > *net) { 241238106Sdes log_err("netblock too large: %s", str); 242238106Sdes return 0; 243238106Sdes } 244238106Sdes *net = atoi(s+1); 245238106Sdes if(*net == 0 && strcmp(s+1, "0") != 0) { 246238106Sdes log_err("cannot parse netblock: '%s'", str); 247238106Sdes return 0; 248238106Sdes } 249238106Sdes if(!(s = strdup(str))) { 250238106Sdes log_err("out of memory"); 251238106Sdes return 0; 252238106Sdes } 253238106Sdes *strchr(s, '/') = '\0'; 254238106Sdes } 255238106Sdes if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 256238106Sdes free(s); 257238106Sdes log_err("cannot parse ip address: '%s'", str); 258238106Sdes return 0; 259238106Sdes } 260238106Sdes if(s) { 261238106Sdes free(s); 262238106Sdes addr_mask(addr, *addrlen, *net); 263238106Sdes } 264238106Sdes return 1; 265238106Sdes} 266238106Sdes 267238106Sdesvoid 268238106Sdeslog_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 269238106Sdes uint16_t type, uint16_t dclass) 270238106Sdes{ 271238106Sdes char buf[LDNS_MAX_DOMAINLEN+1]; 272238106Sdes char t[12], c[12]; 273238106Sdes const char *ts, *cs; 274238106Sdes if(verbosity < v) 275238106Sdes return; 276238106Sdes dname_str(name, buf); 277238106Sdes if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 278238106Sdes else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 279238106Sdes else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 280238106Sdes else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 281238106Sdes else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 282238106Sdes else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 283238106Sdes else if(ldns_rr_descript(type) && ldns_rr_descript(type)->_name) 284238106Sdes ts = ldns_rr_descript(type)->_name; 285238106Sdes else { 286238106Sdes snprintf(t, sizeof(t), "TYPE%d", (int)type); 287238106Sdes ts = t; 288238106Sdes } 289238106Sdes if(ldns_lookup_by_id(ldns_rr_classes, (int)dclass) && 290238106Sdes ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name) 291238106Sdes cs = ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name; 292238106Sdes else { 293238106Sdes snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 294238106Sdes cs = c; 295238106Sdes } 296238106Sdes log_info("%s %s %s %s", str, buf, ts, cs); 297238106Sdes} 298238106Sdes 299238106Sdesvoid log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 300238106Sdes struct sockaddr_storage* addr, socklen_t addrlen) 301238106Sdes{ 302238106Sdes uint16_t port; 303238106Sdes const char* family = "unknown_family "; 304238106Sdes char namebuf[LDNS_MAX_DOMAINLEN+1]; 305238106Sdes char dest[100]; 306238106Sdes int af = (int)((struct sockaddr_in*)addr)->sin_family; 307238106Sdes void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 308238106Sdes if(verbosity < v) 309238106Sdes return; 310238106Sdes switch(af) { 311238106Sdes case AF_INET: family=""; break; 312238106Sdes case AF_INET6: family=""; 313238106Sdes sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 314238106Sdes break; 315238106Sdes case AF_UNIX: family="unix_family "; break; 316238106Sdes default: break; 317238106Sdes } 318238106Sdes if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 319238106Sdes strncpy(dest, "(inet_ntop error)", sizeof(dest)); 320238106Sdes } 321238106Sdes dest[sizeof(dest)-1] = 0; 322238106Sdes port = ntohs(((struct sockaddr_in*)addr)->sin_port); 323238106Sdes dname_str(zone, namebuf); 324238106Sdes if(af != AF_INET && af != AF_INET6) 325238106Sdes verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 326238106Sdes str, namebuf, family, dest, (int)port, (int)addrlen); 327238106Sdes else verbose(v, "%s <%s> %s%s#%d", 328238106Sdes str, namebuf, family, dest, (int)port); 329238106Sdes} 330238106Sdes 331238106Sdesint 332238106Sdessockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 333238106Sdes struct sockaddr_storage* addr2, socklen_t len2) 334238106Sdes{ 335238106Sdes struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 336238106Sdes struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 337238106Sdes struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 338238106Sdes struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 339238106Sdes if(len1 < len2) 340238106Sdes return -1; 341238106Sdes if(len1 > len2) 342238106Sdes return 1; 343238106Sdes log_assert(len1 == len2); 344238106Sdes if( p1_in->sin_family < p2_in->sin_family) 345238106Sdes return -1; 346238106Sdes if( p1_in->sin_family > p2_in->sin_family) 347238106Sdes return 1; 348238106Sdes log_assert( p1_in->sin_family == p2_in->sin_family ); 349238106Sdes /* compare ip4 */ 350238106Sdes if( p1_in->sin_family == AF_INET ) { 351238106Sdes /* just order it, ntohs not required */ 352238106Sdes if(p1_in->sin_port < p2_in->sin_port) 353238106Sdes return -1; 354238106Sdes if(p1_in->sin_port > p2_in->sin_port) 355238106Sdes return 1; 356238106Sdes log_assert(p1_in->sin_port == p2_in->sin_port); 357238106Sdes return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 358238106Sdes } else if (p1_in6->sin6_family == AF_INET6) { 359238106Sdes /* just order it, ntohs not required */ 360238106Sdes if(p1_in6->sin6_port < p2_in6->sin6_port) 361238106Sdes return -1; 362238106Sdes if(p1_in6->sin6_port > p2_in6->sin6_port) 363238106Sdes return 1; 364238106Sdes log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 365238106Sdes return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 366238106Sdes INET6_SIZE); 367238106Sdes } else { 368238106Sdes /* eek unknown type, perform this comparison for sanity. */ 369238106Sdes return memcmp(addr1, addr2, len1); 370238106Sdes } 371238106Sdes} 372238106Sdes 373238106Sdesint 374238106Sdessockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 375238106Sdes struct sockaddr_storage* addr2, socklen_t len2) 376238106Sdes{ 377238106Sdes struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 378238106Sdes struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 379238106Sdes struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 380238106Sdes struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 381238106Sdes if(len1 < len2) 382238106Sdes return -1; 383238106Sdes if(len1 > len2) 384238106Sdes return 1; 385238106Sdes log_assert(len1 == len2); 386238106Sdes if( p1_in->sin_family < p2_in->sin_family) 387238106Sdes return -1; 388238106Sdes if( p1_in->sin_family > p2_in->sin_family) 389238106Sdes return 1; 390238106Sdes log_assert( p1_in->sin_family == p2_in->sin_family ); 391238106Sdes /* compare ip4 */ 392238106Sdes if( p1_in->sin_family == AF_INET ) { 393238106Sdes return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 394238106Sdes } else if (p1_in6->sin6_family == AF_INET6) { 395238106Sdes return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 396238106Sdes INET6_SIZE); 397238106Sdes } else { 398238106Sdes /* eek unknown type, perform this comparison for sanity. */ 399238106Sdes return memcmp(addr1, addr2, len1); 400238106Sdes } 401238106Sdes} 402238106Sdes 403238106Sdesint 404238106Sdesaddr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 405238106Sdes{ 406238106Sdes if(len == (socklen_t)sizeof(struct sockaddr_in6) && 407238106Sdes ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 408238106Sdes return 1; 409238106Sdes else return 0; 410238106Sdes} 411238106Sdes 412238106Sdesvoid 413238106Sdesaddr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 414238106Sdes{ 415238106Sdes uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 416238106Sdes int i, max; 417238106Sdes uint8_t* s; 418238106Sdes if(addr_is_ip6(addr, len)) { 419238106Sdes s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 420238106Sdes max = 128; 421238106Sdes } else { 422238106Sdes s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 423238106Sdes max = 32; 424238106Sdes } 425238106Sdes if(net >= max) 426238106Sdes return; 427238106Sdes for(i=net/8+1; i<max/8; i++) { 428238106Sdes s[i] = 0; 429238106Sdes } 430238106Sdes s[net/8] &= mask[net&0x7]; 431238106Sdes} 432238106Sdes 433238106Sdesint 434238106Sdesaddr_in_common(struct sockaddr_storage* addr1, int net1, 435238106Sdes struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 436238106Sdes{ 437238106Sdes int min = (net1<net2)?net1:net2; 438238106Sdes int i, to; 439238106Sdes int match = 0; 440238106Sdes uint8_t* s1, *s2; 441238106Sdes if(addr_is_ip6(addr1, addrlen)) { 442238106Sdes s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 443238106Sdes s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 444238106Sdes to = 16; 445238106Sdes } else { 446238106Sdes s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 447238106Sdes s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 448238106Sdes to = 4; 449238106Sdes } 450238106Sdes /* match = bits_in_common(s1, s2, to); */ 451238106Sdes for(i=0; i<to; i++) { 452238106Sdes if(s1[i] == s2[i]) { 453238106Sdes match += 8; 454238106Sdes } else { 455238106Sdes uint8_t z = s1[i]^s2[i]; 456238106Sdes log_assert(z); 457238106Sdes while(!(z&0x80)) { 458238106Sdes match++; 459238106Sdes z<<=1; 460238106Sdes } 461238106Sdes break; 462238106Sdes } 463238106Sdes } 464238106Sdes if(match > min) match = min; 465238106Sdes return match; 466238106Sdes} 467238106Sdes 468238106Sdesvoid 469238106Sdesaddr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 470238106Sdes char* buf, size_t len) 471238106Sdes{ 472238106Sdes int af = (int)((struct sockaddr_in*)addr)->sin_family; 473238106Sdes void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 474238106Sdes if(addr_is_ip6(addr, addrlen)) 475238106Sdes sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 476238106Sdes if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 477238106Sdes snprintf(buf, len, "(inet_ntop_error)"); 478238106Sdes } 479238106Sdes} 480238106Sdes 481238106Sdesint 482238106Sdesaddr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 483238106Sdes{ 484238106Sdes /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 485238106Sdes const uint8_t map_prefix[16] = 486238106Sdes {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 487238106Sdes uint8_t* s; 488238106Sdes if(!addr_is_ip6(addr, addrlen)) 489238106Sdes return 0; 490238106Sdes /* s is 16 octet ipv6 address string */ 491238106Sdes s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 492238106Sdes return (memcmp(s, map_prefix, 12) == 0); 493238106Sdes} 494238106Sdes 495238106Sdesint addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 496238106Sdes{ 497238106Sdes int af = (int)((struct sockaddr_in*)addr)->sin_family; 498238106Sdes void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 499238106Sdes return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 500238106Sdes && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 501238106Sdes} 502238106Sdes 503238106Sdesint addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 504238106Sdes{ 505238106Sdes int af = (int)((struct sockaddr_in*)addr)->sin_family; 506238106Sdes void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 507238106Sdes void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 508238106Sdes if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 509238106Sdes && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 510238106Sdes return 1; 511238106Sdes else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 512238106Sdes && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 513238106Sdes "\000\000\000\000\000\000\000\000", 16) == 0) 514238106Sdes return 1; 515238106Sdes return 0; 516238106Sdes} 517238106Sdes 518238106Sdesvoid sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 519238106Sdes socklen_t len, struct regional* region) 520238106Sdes{ 521238106Sdes struct sock_list* add = (struct sock_list*)regional_alloc(region, 522238106Sdes sizeof(*add) - sizeof(add->addr) + (size_t)len); 523238106Sdes if(!add) { 524238106Sdes log_err("out of memory in socketlist insert"); 525238106Sdes return; 526238106Sdes } 527238106Sdes log_assert(list); 528238106Sdes add->next = *list; 529238106Sdes add->len = len; 530238106Sdes *list = add; 531238106Sdes if(len) memmove(&add->addr, addr, len); 532238106Sdes} 533238106Sdes 534238106Sdesvoid sock_list_prepend(struct sock_list** list, struct sock_list* add) 535238106Sdes{ 536238106Sdes struct sock_list* last = add; 537238106Sdes if(!last) 538238106Sdes return; 539238106Sdes while(last->next) 540238106Sdes last = last->next; 541238106Sdes last->next = *list; 542238106Sdes *list = add; 543238106Sdes} 544238106Sdes 545238106Sdesint sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 546238106Sdes socklen_t len) 547238106Sdes{ 548238106Sdes while(list) { 549238106Sdes if(len == list->len) { 550238106Sdes if(len == 0 || sockaddr_cmp_addr(addr, len, 551238106Sdes &list->addr, list->len) == 0) 552238106Sdes return 1; 553238106Sdes } 554238106Sdes list = list->next; 555238106Sdes } 556238106Sdes return 0; 557238106Sdes} 558238106Sdes 559238106Sdesvoid sock_list_merge(struct sock_list** list, struct regional* region, 560238106Sdes struct sock_list* add) 561238106Sdes{ 562238106Sdes struct sock_list* p; 563238106Sdes for(p=add; p; p=p->next) { 564238106Sdes if(!sock_list_find(*list, &p->addr, p->len)) 565238106Sdes sock_list_insert(list, &p->addr, p->len, region); 566238106Sdes } 567238106Sdes} 568238106Sdes 569238106Sdesvoid 570238106Sdeslog_crypto_err(const char* str) 571238106Sdes{ 572249141Sdes#ifdef HAVE_SSL 573238106Sdes /* error:[error code]:[library name]:[function name]:[reason string] */ 574238106Sdes char buf[128]; 575238106Sdes unsigned long e; 576238106Sdes ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 577238106Sdes log_err("%s crypto %s", str, buf); 578238106Sdes while( (e=ERR_get_error()) ) { 579238106Sdes ERR_error_string_n(e, buf, sizeof(buf)); 580238106Sdes log_err("and additionally crypto %s", buf); 581238106Sdes } 582249141Sdes#else 583249141Sdes (void)str; 584249141Sdes#endif /* HAVE_SSL */ 585238106Sdes} 586238106Sdes 587238106Sdesvoid* listen_sslctx_create(char* key, char* pem, char* verifypem) 588238106Sdes{ 589249141Sdes#ifdef HAVE_SSL 590238106Sdes SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 591238106Sdes if(!ctx) { 592238106Sdes log_crypto_err("could not SSL_CTX_new"); 593238106Sdes return NULL; 594238106Sdes } 595238106Sdes /* no SSLv2 because has defects */ 596238106Sdes if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ 597238106Sdes log_crypto_err("could not set SSL_OP_NO_SSLv2"); 598238106Sdes SSL_CTX_free(ctx); 599238106Sdes return NULL; 600238106Sdes } 601238106Sdes if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 602238106Sdes log_err("error for cert file: %s", pem); 603238106Sdes log_crypto_err("error in SSL_CTX use_certificate_file"); 604238106Sdes SSL_CTX_free(ctx); 605238106Sdes return NULL; 606238106Sdes } 607238106Sdes if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 608238106Sdes log_err("error for private key file: %s", key); 609238106Sdes log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 610238106Sdes SSL_CTX_free(ctx); 611238106Sdes return NULL; 612238106Sdes } 613238106Sdes if(!SSL_CTX_check_private_key(ctx)) { 614238106Sdes log_err("error for key file: %s", key); 615238106Sdes log_crypto_err("Error in SSL_CTX check_private_key"); 616238106Sdes SSL_CTX_free(ctx); 617238106Sdes return NULL; 618238106Sdes } 619238106Sdes 620238106Sdes if(verifypem && verifypem[0]) { 621238106Sdes if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 622238106Sdes log_crypto_err("Error in SSL_CTX verify locations"); 623238106Sdes SSL_CTX_free(ctx); 624238106Sdes return NULL; 625238106Sdes } 626238106Sdes SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 627238106Sdes verifypem)); 628238106Sdes SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 629238106Sdes } 630238106Sdes return ctx; 631249141Sdes#else 632249141Sdes (void)key; (void)pem; (void)verifypem; 633249141Sdes return NULL; 634249141Sdes#endif 635238106Sdes} 636238106Sdes 637238106Sdesvoid* connect_sslctx_create(char* key, char* pem, char* verifypem) 638238106Sdes{ 639249141Sdes#ifdef HAVE_SSL 640238106Sdes SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 641238106Sdes if(!ctx) { 642238106Sdes log_crypto_err("could not allocate SSL_CTX pointer"); 643238106Sdes return NULL; 644238106Sdes } 645238106Sdes if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) { 646238106Sdes log_crypto_err("could not set SSL_OP_NO_SSLv2"); 647238106Sdes SSL_CTX_free(ctx); 648238106Sdes return NULL; 649238106Sdes } 650238106Sdes if(key && key[0]) { 651238106Sdes if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 652238106Sdes log_err("error in client certificate %s", pem); 653238106Sdes log_crypto_err("error in certificate file"); 654238106Sdes SSL_CTX_free(ctx); 655238106Sdes return NULL; 656238106Sdes } 657238106Sdes if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 658238106Sdes log_err("error in client private key %s", key); 659238106Sdes log_crypto_err("error in key file"); 660238106Sdes SSL_CTX_free(ctx); 661238106Sdes return NULL; 662238106Sdes } 663238106Sdes if(!SSL_CTX_check_private_key(ctx)) { 664238106Sdes log_err("error in client key %s", key); 665238106Sdes log_crypto_err("error in SSL_CTX_check_private_key"); 666238106Sdes SSL_CTX_free(ctx); 667238106Sdes return NULL; 668238106Sdes } 669238106Sdes } 670238106Sdes if(verifypem && verifypem[0]) { 671238106Sdes if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL) != 1) { 672238106Sdes log_crypto_err("error in SSL_CTX verify"); 673238106Sdes SSL_CTX_free(ctx); 674238106Sdes return NULL; 675238106Sdes } 676238106Sdes SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 677238106Sdes } 678238106Sdes return ctx; 679249141Sdes#else 680249141Sdes (void)key; (void)pem; (void)verifypem; 681249141Sdes return NULL; 682249141Sdes#endif 683238106Sdes} 684238106Sdes 685238106Sdesvoid* incoming_ssl_fd(void* sslctx, int fd) 686238106Sdes{ 687249141Sdes#ifdef HAVE_SSL 688238106Sdes SSL* ssl = SSL_new((SSL_CTX*)sslctx); 689238106Sdes if(!ssl) { 690238106Sdes log_crypto_err("could not SSL_new"); 691238106Sdes return NULL; 692238106Sdes } 693238106Sdes SSL_set_accept_state(ssl); 694238106Sdes (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 695238106Sdes if(!SSL_set_fd(ssl, fd)) { 696238106Sdes log_crypto_err("could not SSL_set_fd"); 697238106Sdes SSL_free(ssl); 698238106Sdes return NULL; 699238106Sdes } 700238106Sdes return ssl; 701249141Sdes#else 702249141Sdes (void)sslctx; (void)fd; 703249141Sdes return NULL; 704249141Sdes#endif 705238106Sdes} 706238106Sdes 707238106Sdesvoid* outgoing_ssl_fd(void* sslctx, int fd) 708238106Sdes{ 709249141Sdes#ifdef HAVE_SSL 710238106Sdes SSL* ssl = SSL_new((SSL_CTX*)sslctx); 711238106Sdes if(!ssl) { 712238106Sdes log_crypto_err("could not SSL_new"); 713238106Sdes return NULL; 714238106Sdes } 715238106Sdes SSL_set_connect_state(ssl); 716238106Sdes (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 717238106Sdes if(!SSL_set_fd(ssl, fd)) { 718238106Sdes log_crypto_err("could not SSL_set_fd"); 719238106Sdes SSL_free(ssl); 720238106Sdes return NULL; 721238106Sdes } 722238106Sdes return ssl; 723249141Sdes#else 724249141Sdes (void)sslctx; (void)fd; 725249141Sdes return NULL; 726249141Sdes#endif 727238106Sdes} 728249141Sdes 729249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 730249141Sdes/** global lock list for openssl locks */ 731249141Sdesstatic lock_basic_t *ub_openssl_locks = NULL; 732249141Sdes 733249141Sdes/** callback that gets thread id for openssl */ 734249141Sdesstatic unsigned long 735249141Sdesub_crypto_id_cb(void) 736249141Sdes{ 737249141Sdes return (unsigned long)ub_thread_self(); 738249141Sdes} 739249141Sdes 740249141Sdesstatic void 741249141Sdesub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 742249141Sdes int ATTR_UNUSED(line)) 743249141Sdes{ 744249141Sdes if((mode&CRYPTO_LOCK)) { 745249141Sdes lock_basic_lock(&ub_openssl_locks[type]); 746249141Sdes } else { 747249141Sdes lock_basic_unlock(&ub_openssl_locks[type]); 748249141Sdes } 749249141Sdes} 750249141Sdes#endif /* OPENSSL_THREADS */ 751249141Sdes 752249141Sdesint ub_openssl_lock_init(void) 753249141Sdes{ 754249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 755249141Sdes int i; 756249141Sdes ub_openssl_locks = (lock_basic_t*)malloc( 757249141Sdes sizeof(lock_basic_t)*CRYPTO_num_locks()); 758249141Sdes if(!ub_openssl_locks) 759249141Sdes return 0; 760249141Sdes for(i=0; i<CRYPTO_num_locks(); i++) { 761249141Sdes lock_basic_init(&ub_openssl_locks[i]); 762249141Sdes } 763249141Sdes CRYPTO_set_id_callback(&ub_crypto_id_cb); 764249141Sdes CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 765249141Sdes#endif /* OPENSSL_THREADS */ 766249141Sdes return 1; 767249141Sdes} 768249141Sdes 769249141Sdesvoid ub_openssl_lock_delete(void) 770249141Sdes{ 771249141Sdes#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 772249141Sdes int i; 773249141Sdes if(!ub_openssl_locks) 774249141Sdes return; 775249141Sdes CRYPTO_set_id_callback(NULL); 776249141Sdes CRYPTO_set_locking_callback(NULL); 777249141Sdes for(i=0; i<CRYPTO_num_locks(); i++) { 778249141Sdes lock_basic_destroy(&ub_openssl_locks[i]); 779249141Sdes } 780249141Sdes free(ub_openssl_locks); 781249141Sdes#endif /* OPENSSL_THREADS */ 782249141Sdes} 783249141Sdes 784